aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2011-07-07 16:14:24 +0300
committerTimo Teräs <timo.teras@iki.fi>2011-07-07 16:14:24 +0300
commit491adc1d879b67ff4095fd32eb376f9e580e97ad (patch)
tree45caf5b64a48186352e8fe7e502c9c9bd296750f
parent05a00bd3b1689298d2ad59c797d43424c18ea855 (diff)
downloadaports-491adc1d879b67ff4095fd32eb376f9e580e97ad.tar.bz2
aports-491adc1d879b67ff4095fd32eb376f9e580e97ad.tar.xz
main/libpri: upgrade to 1.4.12
* remove unneeded patches
-rw-r--r--main/libpri/APKBUILD7
-rw-r--r--main/libpri/libpri-1.4-r1357.patch39961
-rw-r--r--main/libpri/libpri-cflags.patch21
3 files changed, 4 insertions, 39985 deletions
diff --git a/main/libpri/APKBUILD b/main/libpri/APKBUILD
index aec4f46831..fef96994fe 100644
--- a/main/libpri/APKBUILD
+++ b/main/libpri/APKBUILD
@@ -1,8 +1,8 @@
# Contributor: Timo Teras <timo.teras@iki.fi>
# Maintainer: Timo Teras <timo.teras@iki.fi>
pkgname=libpri
-pkgver=1.4.12_beta3
-_pkgver=1.4.12-beta3
+pkgver=1.4.12
+_pkgver=$pkgver
pkgrel=0
pkgdesc="Primary Rate ISDN (PRI) library"
url="http://www.asterisk.orig"
@@ -30,4 +30,5 @@ package() {
make LDCONFIG="echo" INSTALL_PREFIX="$pkgdir" install
}
-md5sums="9cbbaa009264b76af930529e8aae8cfd libpri-1.4.12-beta3.tar.gz"
+md5sums="9de39b866f049cc20a4f431cc6245166 libpri-1.4.12.tar.gz
+8df2ca48ce7db4f1a8604b0904bc9394 libpri-cflags.patch"
diff --git a/main/libpri/libpri-1.4-r1357.patch b/main/libpri/libpri-1.4-r1357.patch
deleted file mode 100644
index be827eebb7..0000000000
--- a/main/libpri/libpri-1.4-r1357.patch
+++ /dev/null
@@ -1,39961 +0,0 @@
-===================================================================
---- a/pri_timers.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_timers.h (.../branches/1.4) (revision 1357)
-@@ -1,97 +0,0 @@
--/*
-- * libpri: An implementation of Primary Rate ISDN
-- *
-- * Written by Mark Spencer <markster@digium.com>
-- *
-- * Copyright (C) 2001, Digium, Inc.
-- * All Rights Reserved.
-- */
--
--/*
-- * See http://www.asterisk.org for more information about
-- * the Asterisk project. Please do not directly contact
-- * any of the maintainers of this project for assistance;
-- * the project provides a web site, mailing lists and IRC
-- * channels for your use.
-- *
-- * This program is free software, distributed under the terms of
-- * the GNU General Public License Version 2 as published by the
-- * Free Software Foundation. See the LICENSE file included with
-- * this program for more details.
-- *
-- * In addition, when this program is distributed with Asterisk in
-- * any form that would qualify as a 'combined work' or as a
-- * 'derivative work' (but not mere aggregation), you can redistribute
-- * and/or modify the combination under the terms of the license
-- * provided with that copy of Asterisk, instead of the license
-- * terms granted here.
-- */
--
--#ifndef _PRI_TIMERS_H
--#define _PRI_TIMERS_H
--
--/* -1 means we dont currently support the timer/counter */
--#define PRI_TIMERS_DEFAULT { \
-- 3, /* N200 */ \
-- -1, /* N201 */ \
-- 3, /* N202 */ \
-- 7, /* K */ \
-- 1000, /* T200 */ \
-- -1, /* T201 */ \
-- 10000, /* T202 */ \
-- 10000, /* T203 */ \
-- -1, /* T300 */ \
-- -1, /* T301 */ \
-- -1, /* T302 */ \
-- -1, /* T303 */ \
-- -1, /* T304 */ \
-- 30000, /* T305 */ \
-- -1, /* T306 */ \
-- -1, /* T307 */ \
-- 4000, /* T308 */ \
-- -1, /* T309 */ \
-- -1, /* T310 */ \
-- 4000, /* T313 */ \
-- -1, /* T314 */ \
-- -1, /* T316 */ \
-- -1, /* T317 */ \
-- -1, /* T318 */ \
-- -1, /* T319 */ \
-- -1, /* T320 */ \
-- -1, /* T321 */ \
-- -1, /* T322 */ \
-- 2500, /* TM20 - Q.921 Appendix IV */ \
-- 3, /* NM20 - Q.921 Appendix IV */ \
-- }
--
--/* XXX Only our default timers are setup now XXX */
--#define PRI_TIMERS_UNKNOWN PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_NI2 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_DMS100 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_LUCENT5E PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_ATT4ESS PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_EUROISDN_E1 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_EUROISDN_T1 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_NI1 PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_GR303_EOC PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_GR303_TMC PRI_TIMERS_DEFAULT
--#define PRI_TIMERS_QSIG PRI_TIMERS_DEFAULT
--#define __PRI_TIMERS_GR303_EOC_INT PRI_TIMERS_DEFAULT
--#define __PRI_TIMERS_GR303_TMC_INT PRI_TIMERS_DEFAULT
--
--#define PRI_TIMERS_ALL { PRI_TIMERS_UNKNOWN, \
-- PRI_TIMERS_NI2, \
-- PRI_TIMERS_DMS100, \
-- PRI_TIMERS_LUCENT5E, \
-- PRI_TIMERS_ATT4ESS, \
-- PRI_TIMERS_EUROISDN_E1, \
-- PRI_TIMERS_EUROISDN_T1, \
-- PRI_TIMERS_NI1, \
-- PRI_TIMERS_QSIG, \
-- PRI_TIMERS_GR303_EOC, \
-- PRI_TIMERS_GR303_TMC, \
-- __PRI_TIMERS_GR303_EOC_INT, \
-- __PRI_TIMERS_GR303_TMC_INT, \
-- }
--
--#endif
-Index: .version
-===================================================================
---- a/.version (.../tags/1.4.10.2) (revision 1357)
-+++ b/.version (.../branches/1.4) (revision 1357)
-@@ -1 +1 @@
--1.4.10.2
-+1.4.10.2-r1357
-Index: prisched.c
-===================================================================
---- a/prisched.c (.../tags/1.4.10.2) (revision 1357)
-+++ b/prisched.c (.../branches/1.4) (revision 1357)
-@@ -33,25 +33,43 @@
- #include "pri_internal.h"
-
-
-+/*! \brief The maximum number of timers that were active at once. */
- static int maxsched = 0;
-
- /* Scheduler routines */
--int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data)
-+
-+/*!
-+ * \brief Start a timer to schedule an event.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param ms Number of milliseconds to scheduled event.
-+ * \param function Callback function to call when timeout.
-+ * \param data Value to give callback function when timeout.
-+ *
-+ * \retval 0 if scheduler table is full and could not schedule the event.
-+ * \retval id Scheduled event id.
-+ */
-+int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), void *data)
- {
- int x;
- struct timeval tv;
-+
- /* Scheduling runs on master channels only */
-- while (pri->master)
-- pri = pri->master;
-- for (x=1;x<MAX_SCHED;x++)
-- if (!pri->pri_sched[x].callback)
-+ while (ctrl->master) {
-+ ctrl = ctrl->master;
-+ }
-+ for (x = 0; x < MAX_SCHED; ++x) {
-+ if (!ctrl->pri_sched[x].callback) {
- break;
-+ }
-+ }
- if (x == MAX_SCHED) {
-- pri_error(pri, "No more room in scheduler\n");
-- return -1;
-+ pri_error(ctrl, "No more room in scheduler\n");
-+ return 0;
- }
-- if (x > maxsched)
-- maxsched = x;
-+ if (x >= maxsched) {
-+ maxsched = x + 1;
-+ }
- gettimeofday(&tv, NULL);
- tv.tv_sec += ms / 1000;
- tv.tv_usec += (ms % 1000) * 1000;
-@@ -59,71 +77,110 @@
- tv.tv_usec -= 1000000;
- tv.tv_sec += 1;
- }
-- pri->pri_sched[x].when = tv;
-- pri->pri_sched[x].callback = function;
-- pri->pri_sched[x].data = data;
-- return x;
-+ ctrl->pri_sched[x].when = tv;
-+ ctrl->pri_sched[x].callback = function;
-+ ctrl->pri_sched[x].data = data;
-+ return x + 1;
- }
-
--struct timeval *pri_schedule_next(struct pri *pri)
-+/*!
-+ * \brief Determine the time of the next scheduled event to expire.
-+ *
-+ * \param ctrl D channel controller.
-+ *
-+ * \return Time of the next scheduled event to expire or NULL if no timers active.
-+ */
-+struct timeval *pri_schedule_next(struct pri *ctrl)
- {
- struct timeval *closest = NULL;
- int x;
-- /* Check subchannels */
-- if (pri->subchannel)
-- closest = pri_schedule_next(pri->subchannel);
-- for (x=1;x<MAX_SCHED;x++) {
-- if (pri->pri_sched[x].callback &&
-- (!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) ||
-- ((closest->tv_sec == pri->pri_sched[x].when.tv_sec) &&
-- (closest->tv_usec > pri->pri_sched[x].when.tv_usec))))
-- closest = &pri->pri_sched[x].when;
-+
-+ /* Scheduling runs on master channels only */
-+ while (ctrl->master) {
-+ ctrl = ctrl->master;
- }
-+ for (x = 0; x < MAX_SCHED; ++x) {
-+ if (ctrl->pri_sched[x].callback && (!closest
-+ || (closest->tv_sec > ctrl->pri_sched[x].when.tv_sec)
-+ || ((closest->tv_sec == ctrl->pri_sched[x].when.tv_sec)
-+ && (closest->tv_usec > ctrl->pri_sched[x].when.tv_usec)))) {
-+ closest = &ctrl->pri_sched[x].when;
-+ }
-+ }
- return closest;
- }
-
--static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv)
-+/*!
-+ * \internal
-+ * \brief Run all expired timers or return an event generated by an expired timer.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param tv Current time.
-+ *
-+ * \return Event for upper layer to process or NULL if all expired timers run.
-+ */
-+static pri_event *__pri_schedule_run(struct pri *ctrl, struct timeval *tv)
- {
- int x;
- void (*callback)(void *);
- void *data;
-- pri_event *e;
-- if (pri->subchannel) {
-- if ((e = __pri_schedule_run(pri->subchannel, tv))) {
-- return e;
-+
-+ /* Scheduling runs on master channels only */
-+ while (ctrl->master) {
-+ ctrl = ctrl->master;
-+ }
-+ for (x = 0; x < MAX_SCHED; ++x) {
-+ if (ctrl->pri_sched[x].callback && ((ctrl->pri_sched[x].when.tv_sec < tv->tv_sec)
-+ || ((ctrl->pri_sched[x].when.tv_sec == tv->tv_sec)
-+ && (ctrl->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
-+ /* This timer has expired. */
-+ ctrl->schedev = 0;
-+ callback = ctrl->pri_sched[x].callback;
-+ data = ctrl->pri_sched[x].data;
-+ ctrl->pri_sched[x].callback = NULL;
-+ callback(data);
-+ if (ctrl->schedev) {
-+ return &ctrl->ev;
-+ }
- }
- }
-- for (x=1;x<MAX_SCHED;x++) {
-- if (pri->pri_sched[x].callback &&
-- ((pri->pri_sched[x].when.tv_sec < tv->tv_sec) ||
-- ((pri->pri_sched[x].when.tv_sec == tv->tv_sec) &&
-- (pri->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
-- pri->schedev = 0;
-- callback = pri->pri_sched[x].callback;
-- data = pri->pri_sched[x].data;
-- pri->pri_sched[x].callback = NULL;
-- pri->pri_sched[x].data = NULL;
-- callback(data);
-- if (pri->schedev)
-- return &pri->ev;
-- }
-- }
- return NULL;
- }
-
--pri_event *pri_schedule_run(struct pri *pri)
-+/*!
-+ * \brief Run all expired timers or return an event generated by an expired timer.
-+ *
-+ * \param ctrl D channel controller.
-+ *
-+ * \return Event for upper layer to process or NULL if all expired timers run.
-+ */
-+pri_event *pri_schedule_run(struct pri *ctrl)
- {
- struct timeval tv;
-+
- gettimeofday(&tv, NULL);
-- return __pri_schedule_run(pri, &tv);
-+ return __pri_schedule_run(ctrl, &tv);
- }
-
--
--void pri_schedule_del(struct pri *pri,int id)
-+/*!
-+ * \brief Delete a scheduled event.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param id Scheduled event id to delete.
-+ * 0 is a disabled/unscheduled event id that is ignored.
-+ * 1 - MAX_SCHED is a valid event id.
-+ *
-+ * \return Nothing
-+ */
-+void pri_schedule_del(struct pri *ctrl, int id)
- {
-- while (pri->master)
-- pri = pri->master;
-- if ((id >= MAX_SCHED) || (id < 0))
-- pri_error(pri, "Asked to delete sched id %d???\n", id);
-- pri->pri_sched[id].callback = NULL;
-+ /* Scheduling runs on master channels only */
-+ while (ctrl->master) {
-+ ctrl = ctrl->master;
-+ }
-+ if (0 < id && id <= MAX_SCHED) {
-+ ctrl->pri_sched[id - 1].callback = NULL;
-+ } else if (id) {
-+ pri_error(ctrl, "Asked to delete sched id %d???\n", id);
-+ }
- }
-Index: rose_qsig_mwi.c
-===================================================================
---- a/rose_qsig_mwi.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_qsig_mwi.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,790 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Q.SIG ROSE SS-MWI-Operations
-+ *
-+ * SS-MWI-Operations ECMA-242 Annex E Table E.1
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the MsgCentreId type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param msg_centre_id
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_MsgCentreId(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct roseQsigMsgCentreId *msg_centre_id)
-+{
-+ unsigned char *seq_len;
-+
-+ switch (msg_centre_id->type) {
-+ case 0: /* integer */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
-+ msg_centre_id->u.integer));
-+ break;
-+ case 1: /* partyNumber */
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &msg_centre_id->u.number));
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+ break;
-+ case 2: /* numericString */
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ msg_centre_id->u.str, sizeof(msg_centre_id->u.str) - 1));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown MsgCentreId type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the MWIActivate invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigMWIActivateArg *mwi_activate;
-+ unsigned char *seq_len;
-+ unsigned char *explicit_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ mwi_activate = &args->qsig.MWIActivate;
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &mwi_activate->served_user_number));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ mwi_activate->basic_service));
-+ if (mwi_activate->msg_centre_id_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
-+ &mwi_activate->msg_centre_id));
-+ }
-+ if (mwi_activate->number_of_messages_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
-+ mwi_activate->number_of_messages));
-+ }
-+ if (mwi_activate->originating_number.length) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &mwi_activate->originating_number));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+ if (mwi_activate->timestamp_present) {
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
-+ mwi_activate->timestamp, sizeof(mwi_activate->timestamp) - 1));
-+ }
-+ if (mwi_activate->priority_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
-+ mwi_activate->priority));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the MWIDeactivate invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigMWIDeactivateArg *mwi_deactivate;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ mwi_deactivate = &args->qsig.MWIDeactivate;
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &mwi_deactivate->served_user_number));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ mwi_deactivate->basic_service));
-+ if (mwi_deactivate->msg_centre_id_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
-+ &mwi_deactivate->msg_centre_id));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the MWIInterrogate invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigMWIInterrogateArg *mwi_interrogate;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ mwi_interrogate = &args->qsig.MWIInterrogate;
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &mwi_interrogate->served_user_number));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ mwi_interrogate->basic_service));
-+ if (mwi_interrogate->msg_centre_id_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
-+ &mwi_interrogate->msg_centre_id));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the MWIInterrogateResElt type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param record
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_MWIInterrogateResElt(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseQsigMWIInterrogateResElt *record)
-+{
-+ unsigned char *seq_len;
-+ unsigned char *explicit_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, record->basic_service));
-+ if (record->msg_centre_id_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
-+ &record->msg_centre_id));
-+ }
-+ if (record->number_of_messages_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
-+ record->number_of_messages));
-+ }
-+ if (record->originating_number.length) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &record->originating_number));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+ if (record->timestamp_present) {
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
-+ record->timestamp, sizeof(record->timestamp) - 1));
-+ }
-+ if (record->priority_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
-+ record->priority));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the MWIInterrogate result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ unsigned index;
-+ unsigned char *seq_len;
-+ const struct roseQsigMWIInterrogateRes *mwi_interrogate;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ mwi_interrogate = &args->qsig.MWIInterrogate;
-+ for (index = 0; index < mwi_interrogate->num_records; ++index) {
-+ ASN1_CALL(pos, rose_enc_qsig_MWIInterrogateResElt(ctrl, pos, end,
-+ ASN1_TAG_SEQUENCE, &mwi_interrogate->list[index]));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the MsgCentreId argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param msg_centre_id Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_MsgCentreId(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigMsgCentreId *msg_centre_id)
-+{
-+ int32_t value;
-+ size_t str_len;
-+ int length;
-+ int explicit_offset;
-+ const unsigned char *explicit_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s MsgCentreId\n", name);
-+ }
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ msg_centre_id->type = 0; /* integer */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "integer", tag, pos, end, &value));
-+ msg_centre_id->u.integer = value;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ msg_centre_id->type = 1; /* partyNumber */
-+
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, explicit_end,
-+ &msg_centre_id->u.number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ msg_centre_id->type = 2; /* numericString */
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "numericString", tag, pos, end,
-+ sizeof(msg_centre_id->u.str), msg_centre_id->u.str, &str_len));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG MWIActivate invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ size_t str_len;
-+ int length;
-+ int seq_offset;
-+ int explicit_offset;
-+ const unsigned char *explicit_end;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigMWIActivateArg *mwi_activate;
-+
-+ mwi_activate = &args->qsig.MWIActivate;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " MWIActivateArg %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
-+ &mwi_activate->served_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ mwi_activate->basic_service = value;
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ mwi_activate->msg_centre_id_present = 0;
-+ mwi_activate->number_of_messages_present = 0;
-+ mwi_activate->originating_number.length = 0;
-+ mwi_activate->timestamp_present = 0;
-+ mwi_activate->priority_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
-+ seq_end, &mwi_activate->msg_centre_id));
-+ mwi_activate->msg_centre_id_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ /* Must not be constructed but we will not check for it for simplicity. */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "nbOfMessages", tag, pos, seq_end,
-+ &value));
-+ mwi_activate->number_of_messages = value;
-+ mwi_activate->number_of_messages_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ /* Must be constructed but we will not check for it for simplicity. */
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "originatingNr", tag, pos,
-+ explicit_end, &mwi_activate->originating_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_TYPE_GENERALIZED_TIME:
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
-+ sizeof(mwi_activate->timestamp), mwi_activate->timestamp, &str_len));
-+ mwi_activate->timestamp_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
-+ /* Must not be constructed but we will not check for it for simplicity. */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "priority", tag, pos, seq_end, &value));
-+ mwi_activate->priority = value;
-+ mwi_activate->priority_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG MWIDeactivate invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigMWIDeactivateArg *mwi_deactivate;
-+
-+ mwi_deactivate = &args->qsig.MWIDeactivate;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " MWIDeactivateArg %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
-+ &mwi_deactivate->served_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ mwi_deactivate->basic_service = value;
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ mwi_deactivate->msg_centre_id_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
-+ seq_end, &mwi_deactivate->msg_centre_id));
-+ mwi_deactivate->msg_centre_id_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG MWIInterrogate invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigMWIInterrogateArg *mwi_interrogate;
-+
-+ mwi_interrogate = &args->qsig.MWIInterrogate;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " MWIInterrogateArg %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
-+ &mwi_interrogate->served_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ mwi_interrogate->basic_service = value;
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ mwi_interrogate->msg_centre_id_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
-+ seq_end, &mwi_interrogate->msg_centre_id));
-+ mwi_interrogate->msg_centre_id_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the MWIInterrogateResElt argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param record Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_MWIInterrogateResElt(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigMWIInterrogateResElt *record)
-+{
-+ int32_t value;
-+ size_t str_len;
-+ int length;
-+ int seq_offset;
-+ int explicit_offset;
-+ const unsigned char *explicit_end;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " MWIInterrogateResElt %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ record->basic_service = value;
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ record->msg_centre_id_present = 0;
-+ record->number_of_messages_present = 0;
-+ record->originating_number.length = 0;
-+ record->timestamp_present = 0;
-+ record->priority_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
-+ seq_end, &record->msg_centre_id));
-+ record->msg_centre_id_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ /* Must not be constructed but we will not check for it for simplicity. */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "nbOfMessages", tag, pos, seq_end,
-+ &value));
-+ record->number_of_messages = value;
-+ record->number_of_messages_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ /* Must be constructed but we will not check for it for simplicity. */
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "originatingNr", tag, pos,
-+ explicit_end, &record->originating_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_TYPE_GENERALIZED_TIME:
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
-+ sizeof(record->timestamp), record->timestamp, &str_len));
-+ record->timestamp_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
-+ /* Must not be constructed but we will not check for it for simplicity. */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "priority", tag, pos, seq_end, &value));
-+ record->priority = value;
-+ record->priority_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG MWIInterrogate result argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigMWIInterrogateRes *mwi_interrogate;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " MWIInterrogateRes %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ mwi_interrogate = &args->qsig.MWIInterrogate;
-+
-+ mwi_interrogate->num_records = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ if (mwi_interrogate->num_records < ARRAY_LEN(mwi_interrogate->list)) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_qsig_MWIInterrogateResElt(ctrl, "listEntry", tag,
-+ pos, seq_end, &mwi_interrogate->list[mwi_interrogate->num_records]));
-+ ++mwi_interrogate->num_records;
-+ } else {
-+ /* Too many records */
-+ return NULL;
-+ }
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_qsig_mwi.c */
-
-Property changes on: rose_qsig_mwi.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rosetest.c
-===================================================================
---- a/rosetest.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rosetest.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,2473 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief ROSE encode/decode test program
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+static const struct fac_extension_header fac_headers[] = {
-+/* *INDENT-OFF* */
-+ {
-+ .nfe_present = 0,
-+ },
-+ {
-+ .nfe_present = 1,
-+ .nfe.source_entity = 1,
-+ .nfe.destination_entity = 1,
-+ },
-+ {
-+ .nfe_present = 1,
-+ .nfe.source_entity = 1,
-+ .nfe.source_number.plan = 4,
-+ .nfe.source_number.length = 4,
-+ .nfe.source_number.str = "9834",
-+ .nfe.destination_entity = 1,
-+ .nfe.destination_number.plan = 4,
-+ .nfe.destination_number.length = 4,
-+ .nfe.destination_number.str = "9834",
-+ },
-+ {
-+ .nfe_present = 1,
-+ .nfe.source_entity = 1,
-+ .nfe.destination_entity = 1,
-+ .npp_present = 1,
-+ .npp = 19,
-+ .interpretation_present = 1,
-+ .interpretation = 2,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+static const struct rose_message rose_etsi_msgs[] = {
-+/* *INDENT-OFF* */
-+ /* Error messages */
-+ {
-+ .type = ROSE_COMP_TYPE_ERROR,
-+ .component.error.invoke_id = 82,
-+ .component.error.code = ROSE_ERROR_Div_SpecialServiceNr,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_ERROR,
-+ .component.error.invoke_id = 8,
-+ .component.error.code = ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork,
-+ },
-+
-+ /* Reject messages */
-+ {
-+ .type = ROSE_COMP_TYPE_REJECT,
-+ .component.reject.code = ROSE_REJECT_Gen_BadlyStructuredComponent,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_REJECT,
-+ .component.reject.invoke_id_present = 1,
-+ .component.reject.invoke_id = 10,
-+ .component.reject.code = ROSE_REJECT_Inv_InitiatorReleasing,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_REJECT,
-+ .component.reject.invoke_id_present = 1,
-+ .component.reject.invoke_id = 11,
-+ .component.reject.code = ROSE_REJECT_Res_MistypedResult,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_REJECT,
-+ .component.reject.invoke_id_present = 1,
-+ .component.reject.invoke_id = 12,
-+ .component.reject.code = ROSE_REJECT_Err_ErrorResponseUnexpected,
-+ },
-+
-+ /* Anonymous result or result without any arguments. */
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_None,
-+ .component.result.invoke_id = 9,
-+ },
-+
-+ /* Advice Of Charge (AOC) */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ChargingRequest,
-+ .component.invoke.invoke_id = 98,
-+ .component.invoke.args.etsi.ChargingRequest.charging_case = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 99,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.special_charging_code = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 100,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.currency = "Dollars",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.currency = 7,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.multiplier = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.charging_type = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.length = 8,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.scale = 4,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 101,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.currency = "Dollars",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.currency = 7,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.multiplier = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.charging_type = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.length = 8,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.scale = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.granularity_present = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.granularity.length = 20,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.granularity.scale = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 102,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 2,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.currency = "Euros",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.currency = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 103,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 3,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.currency = "Yen",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.amount.currency = 300,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.amount.multiplier = 5,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.unit = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 104,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 2,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 2,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.currency = "Euros",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.currency = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].currency_type = 3,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.currency = "Yen",
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.amount.currency = 300,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.amount.multiplier = 5,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.unit = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 105,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 4,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ChargingRequest,
-+ .component.result.invoke_id = 106,
-+ .component.result.args.etsi.ChargingRequest.type = 0,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
-+ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 5,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCSCurrency,
-+ .component.invoke.invoke_id = 107,
-+ .component.invoke.args.etsi.AOCSCurrency.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCSCurrency,
-+ .component.invoke.invoke_id = 108,
-+ .component.invoke.args.etsi.AOCSCurrency.type = 1,
-+ .component.invoke.args.etsi.AOCSCurrency.currency_info.num_records = 1,
-+ .component.invoke.args.etsi.AOCSCurrency.currency_info.list[0].charged_item = 3,
-+ .component.invoke.args.etsi.AOCSCurrency.currency_info.list[0].currency_type = 4,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCSSpecialArr,
-+ .component.invoke.invoke_id = 109,
-+ .component.invoke.args.etsi.AOCSSpecialArr.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCSSpecialArr,
-+ .component.invoke.invoke_id = 110,
-+ .component.invoke.args.etsi.AOCSSpecialArr.type = 1,
-+ .component.invoke.args.etsi.AOCSSpecialArr.special_arrangement = 9,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
-+ .component.invoke.invoke_id = 111,
-+ .component.invoke.args.etsi.AOCDCurrency.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
-+ .component.invoke.invoke_id = 112,
-+ .component.invoke.args.etsi.AOCDCurrency.type = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
-+ .component.invoke.invoke_id = 113,
-+ .component.invoke.args.etsi.AOCDCurrency.type = 2,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.type_of_charging_info = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
-+ .component.invoke.invoke_id = 114,
-+ .component.invoke.args.etsi.AOCDCurrency.type = 2,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.type_of_charging_info = 1,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCDCurrency.specific.billing_id = 2,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 115,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 116,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 117,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 118,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 0,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].number_of_units = 8523,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.billing_id = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 119,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit_present = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit = 13,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 120,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 0,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].number_of_units = 8523,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit_present = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit = 13,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
-+ .component.invoke.invoke_id = 121,
-+ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 2,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].not_available = 0,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].number_of_units = 8523,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].type_of_unit_present = 1,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].type_of_unit = 13,
-+ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 122,
-+ .component.invoke.args.etsi.AOCECurrency.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 123,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 124,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.id = -37,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 125,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.number.plan = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.number.length = 7,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.number.str = "5551212",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 126,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 127,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.id = -37,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 128,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
-+ .component.invoke.invoke_id = 129,
-+ .component.invoke.args.etsi.AOCECurrency.type = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id = 2,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.id = -37,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 130,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 131,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 132,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.id = -37,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 133,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 134,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.id = -37,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 135,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
-+ .component.invoke.invoke_id = 136,
-+ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id = 2,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association_present = 1,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.type = 0,
-+ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.id = -37,
-+ },
-+
-+ /* Call diversion */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ActivationDiversion,
-+ .component.invoke.invoke_id = 67,
-+ .component.invoke.linked_id_present = 1,
-+ .component.invoke.linked_id = 27,
-+ .component.invoke.args.etsi.ActivationDiversion.procedure = 2,
-+ .component.invoke.args.etsi.ActivationDiversion.basic_service = 3,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.plan = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.length = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.str = "1803",
-+ .component.invoke.args.etsi.ActivationDiversion.served_user_number.plan = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.served_user_number.length = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.served_user_number.str = "5398",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ActivationDiversion,
-+ .component.invoke.invoke_id = 68,
-+ .component.invoke.args.etsi.ActivationDiversion.procedure = 1,
-+ .component.invoke.args.etsi.ActivationDiversion.basic_service = 5,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.plan = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.length = 4,
-+ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.str = "1803",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_ActivationDiversion,
-+ .component.result.invoke_id = 69,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DeactivationDiversion,
-+ .component.invoke.invoke_id = 70,
-+ .component.invoke.args.etsi.DeactivationDiversion.procedure = 1,
-+ .component.invoke.args.etsi.DeactivationDiversion.basic_service = 5,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_DeactivationDiversion,
-+ .component.result.invoke_id = 71,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ActivationStatusNotificationDiv,
-+ .component.invoke.invoke_id = 72,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.procedure = 1,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.basic_service = 5,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.forwarded_to.number.plan = 4,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.forwarded_to.number.length = 4,
-+ .component.invoke.args.etsi.ActivationStatusNotificationDiv.forwarded_to.number.str = "1803",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DeactivationStatusNotificationDiv,
-+ .component.invoke.invoke_id = 73,
-+ .component.invoke.args.etsi.DeactivationStatusNotificationDiv.procedure = 1,
-+ .component.invoke.args.etsi.DeactivationStatusNotificationDiv.basic_service = 5,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_InterrogationDiversion,
-+ .component.invoke.invoke_id = 74,
-+ .component.invoke.args.etsi.InterrogationDiversion.procedure = 1,
-+ .component.invoke.args.etsi.InterrogationDiversion.basic_service = 5,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_InterrogationDiversion,
-+ .component.invoke.invoke_id = 75,
-+ .component.invoke.args.etsi.InterrogationDiversion.procedure = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_InterrogationDiversion,
-+ .component.result.invoke_id = 76,
-+ .component.result.args.etsi.InterrogationDiversion.num_records = 2,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].procedure = 2,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].basic_service = 5,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].forwarded_to.number.plan = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].forwarded_to.number.length = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[0].forwarded_to.number.str = "1803",
-+ .component.result.args.etsi.InterrogationDiversion.list[1].procedure = 1,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].basic_service = 3,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].forwarded_to.number.plan = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].forwarded_to.number.length = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].forwarded_to.number.str = "1903",
-+ .component.result.args.etsi.InterrogationDiversion.list[1].served_user_number.plan = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].served_user_number.length = 4,
-+ .component.result.args.etsi.InterrogationDiversion.list[1].served_user_number.str = "5398",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 77,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 3,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 5,
-+ .component.invoke.args.etsi.DiversionInformation.served_user_subaddress.type = 1,
-+ .component.invoke.args.etsi.DiversionInformation.served_user_subaddress.length = 4,
-+ .component.invoke.args.etsi.DiversionInformation.served_user_subaddress.u.nsap = "6492",
-+ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 0,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.screening_indicator = 3,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.plan = 4,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.length = 4,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.str = "1803",
-+ .component.invoke.args.etsi.DiversionInformation.original_called_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.original_called.presentation = 1,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting.presentation = 2,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting_reason_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting_reason = 3,
-+ .component.invoke.args.etsi.DiversionInformation.q931ie.length = 5,
-+ .component.invoke.args.etsi.DiversionInformation.q931ie_contents = "79828",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 78,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 3,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 5,
-+ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 1,
-+ .component.invoke.args.etsi.DiversionInformation.original_called_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.original_called.presentation = 2,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.last_diverting.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 79,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 2,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 3,
-+ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 80,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 3,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 5,
-+ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
-+ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 3,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.screening_indicator = 2,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.plan = 4,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.length = 4,
-+ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.str = "1803",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 81,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 2,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 4,
-+ .component.invoke.args.etsi.DiversionInformation.q931ie.length = 5,
-+ .component.invoke.args.etsi.DiversionInformation.q931ie_contents = "79828",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
-+ .component.invoke.invoke_id = 82,
-+ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 2,
-+ .component.invoke.args.etsi.DiversionInformation.basic_service = 4,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallDeflection,
-+ .component.invoke.invoke_id = 83,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.plan = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.length = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.str = "1803",
-+ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present = 1,
-+ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallDeflection,
-+ .component.invoke.invoke_id = 84,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.plan = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.length = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.str = "1803",
-+ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present = 1,
-+ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallDeflection,
-+ .component.invoke.invoke_id = 85,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.plan = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.length = 4,
-+ .component.invoke.args.etsi.CallDeflection.deflection.number.str = "1803",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_CallDeflection,
-+ .component.result.invoke_id = 86,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallRerouting,
-+ .component.invoke.invoke_id = 87,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_counter = 2,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.plan = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.length = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.str = "1803",
-+ .component.invoke.args.etsi.CallRerouting.q931ie.length = 129,
-+ .component.invoke.args.etsi.CallRerouting.q931ie_contents =
-+ "YEHAW."
-+ " The quick brown fox jumped over the lazy dog test."
-+ " Now is the time for all good men to come to the aid of their country.",
-+ .component.invoke.args.etsi.CallRerouting.last_rerouting.presentation = 1,
-+ .component.invoke.args.etsi.CallRerouting.subscription_option = 2,
-+ .component.invoke.args.etsi.CallRerouting.calling_subaddress.type = 1,
-+ .component.invoke.args.etsi.CallRerouting.calling_subaddress.length = 4,
-+ .component.invoke.args.etsi.CallRerouting.calling_subaddress.u.nsap = "6492",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallRerouting,
-+ .component.invoke.invoke_id = 88,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_counter = 2,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.plan = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.length = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.str = "1803",
-+ .component.invoke.args.etsi.CallRerouting.q931ie.length = 2,
-+ .component.invoke.args.etsi.CallRerouting.q931ie_contents = "RT",
-+ .component.invoke.args.etsi.CallRerouting.last_rerouting.presentation = 1,
-+ .component.invoke.args.etsi.CallRerouting.subscription_option = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_CallRerouting,
-+ .component.invoke.invoke_id = 89,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.etsi.CallRerouting.rerouting_counter = 2,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.plan = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.length = 4,
-+ .component.invoke.args.etsi.CallRerouting.called_address.number.str = "1803",
-+ .component.invoke.args.etsi.CallRerouting.q931ie.length = 2,
-+ .component.invoke.args.etsi.CallRerouting.q931ie_contents = "RT",
-+ .component.invoke.args.etsi.CallRerouting.last_rerouting.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_CallRerouting,
-+ .component.result.invoke_id = 90,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_InterrogateServedUserNumbers,
-+ .component.invoke.invoke_id = 91,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_InterrogateServedUserNumbers,
-+ .component.result.invoke_id = 92,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.num_records = 2,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[0].plan = 4,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[0].length = 4,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[0].str = "1803",
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[1].plan = 4,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[1].length = 4,
-+ .component.result.args.etsi.InterrogateServedUserNumbers.number[1].str = "5786",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation1,
-+ .component.invoke.invoke_id = 93,
-+ .component.invoke.args.etsi.DivertingLegInformation1.diversion_reason = 4,
-+ .component.invoke.args.etsi.DivertingLegInformation1.subscription_option = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation1.diverted_to_present = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation1.diverted_to.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation1,
-+ .component.invoke.invoke_id = 94,
-+ .component.invoke.args.etsi.DivertingLegInformation1.diversion_reason = 4,
-+ .component.invoke.args.etsi.DivertingLegInformation1.subscription_option = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 95,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_counter = 3,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_reason = 2,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diverting_present = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diverting.presentation = 2,
-+ .component.invoke.args.etsi.DivertingLegInformation2.original_called_present = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation2.original_called.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 96,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_counter = 3,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_reason = 2,
-+ .component.invoke.args.etsi.DivertingLegInformation2.original_called_present = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation2.original_called.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 97,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_counter = 1,
-+ .component.invoke.args.etsi.DivertingLegInformation2.diversion_reason = 2,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation3,
-+ .component.invoke.invoke_id = 98,
-+ .component.invoke.args.etsi.DivertingLegInformation3.presentation_allowed_indicator = 1,
-+ },
-+
-+ /* Explicit Call Transfer (ECT) */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctExecute,
-+ .component.invoke.invoke_id = 54,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_ExplicitEctExecute,
-+ .component.invoke.invoke_id = 55,
-+ .component.invoke.args.etsi.ExplicitEctExecute.link_id = 23,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_RequestSubaddress,
-+ .component.invoke.invoke_id = 56,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_SubaddressTransfer,
-+ .component.invoke.invoke_id = 57,
-+ .component.invoke.args.etsi.SubaddressTransfer.subaddress.type = 1,
-+ .component.invoke.args.etsi.SubaddressTransfer.subaddress.length = 4,
-+ .component.invoke.args.etsi.SubaddressTransfer.subaddress.u.nsap = "6492",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctLinkIdRequest,
-+ .component.invoke.invoke_id = 58,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_EctLinkIdRequest,
-+ .component.result.invoke_id = 59,
-+ .component.result.args.etsi.EctLinkIdRequest.link_id = 76,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 60,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 1,
-+ .component.invoke.args.etsi.EctInform.redirection.presentation = 0,
-+ .component.invoke.args.etsi.EctInform.redirection.number.plan = 8,
-+ .component.invoke.args.etsi.EctInform.redirection.number.length = 4,
-+ .component.invoke.args.etsi.EctInform.redirection.number.str = "6229",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 61,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 1,
-+ .component.invoke.args.etsi.EctInform.redirection.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 62,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 1,
-+ .component.invoke.args.etsi.EctInform.redirection.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 63,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 1,
-+ .component.invoke.args.etsi.EctInform.redirection.presentation = 3,
-+ .component.invoke.args.etsi.EctInform.redirection.number.plan = 8,
-+ .component.invoke.args.etsi.EctInform.redirection.number.length = 4,
-+ .component.invoke.args.etsi.EctInform.redirection.number.str = "3340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctInform,
-+ .component.invoke.invoke_id = 64,
-+ .component.invoke.args.etsi.EctInform.status = 1,
-+ .component.invoke.args.etsi.EctInform.redirection_present = 0,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_ETSI_EctLoopTest,
-+ .component.invoke.invoke_id = 65,
-+ .component.invoke.args.etsi.EctLoopTest.call_transfer_id = 7,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_ETSI_EctLoopTest,
-+ .component.result.invoke_id = 66,
-+ .component.result.args.etsi.EctLoopTest.loop_result = 2,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+static unsigned char rose_etsi_indefinite_len[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * Context Specific/C [1 0x01] <A1> Len:24 <80>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <44>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <07>
-+ * Sequence/C(48 0x30) <30> Len:16 <80>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <01>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <05>
-+ * Sequence/C(48 0x30) <30> Len:6 <80>
-+ * Context Specific [4 0x04] <84> Len:4 <80>
-+ * <31 38 30 33>
-+ * 0x00, 0x00,
-+ * 0x00, 0x00,
-+ * NULL(5 0x05) <05> Len:0 <00>
-+ * 0x00, 0x00,
-+ * 0x00, 0x00
-+ */
-+ 0x91,
-+ 0xA1, 0x80,
-+ 0x02, 0x01,
-+ 0x44,
-+ 0x02, 0x01,
-+ 0x07,
-+ 0x30, 0x80,
-+ 0x0A, 0x01,
-+ 0x01,
-+ 0x0A, 0x01,
-+ 0x05,
-+ 0x30, 0x80,
-+ 0x84, 0x80,
-+ 0x31, 0x38, 0x30, 0x33,
-+ 0x00, 0x00,
-+ 0x00, 0x00,
-+ 0x05, 0x00,
-+ 0x00, 0x00,
-+ 0x00, 0x00,
-+ 0x00, 0x00
-+/* *INDENT-ON* */
-+};
-+
-+static unsigned char rose_etsi_unused_indefinite_len[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * Context Specific/C [1 0x01] <A1> Len:24 <80>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <44>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <06> -- EctExecute
-+ * Sequence/C(48 0x30) <30> Len:16 <80>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <01>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <05>
-+ * Sequence/C(48 0x30) <30> Len:6 <80>
-+ * Context Specific [4 0x04] <84> Len:4 <80>
-+ * <31 38 30 33>
-+ * 0x00, 0x00,
-+ * 0x00, 0x00,
-+ * NULL(5 0x05) <05> Len:0 <00>
-+ * 0x00, 0x00,
-+ * 0x00, 0x00
-+ */
-+ 0x91,
-+ 0xA1, 0x80,
-+ 0x02, 0x01,
-+ 0x44,
-+ 0x02, 0x01,
-+ 0x06,
-+ 0x30, 0x80,
-+ 0x0A, 0x01,
-+ 0x01,
-+ 0x0A, 0x01,
-+ 0x05,
-+ 0x30, 0x80,
-+ 0x84, 0x80,
-+ 0x31, 0x38, 0x30, 0x33,
-+ 0x00, 0x00,
-+ 0x00, 0x00,
-+ 0x05, 0x00,
-+ 0x00, 0x00,
-+ 0x00, 0x00,
-+ 0x00, 0x00
-+/* *INDENT-ON* */
-+};
-+
-+static unsigned char rose_etsi_unused[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * Context Specific/C [1 0x01] <A1> Len:24 <18>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <44>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <06> -- EctExecute
-+ * Sequence/C(48 0x30) <30> Len:16 <10>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <01>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <05>
-+ * Sequence/C(48 0x30) <30> Len:6 <06>
-+ * Context Specific [4 0x04] <84> Len:4 <04>
-+ * <31 38 30 33>
-+ * NULL(5 0x05) <05> Len:0 <00>
-+ */
-+ 0x91,
-+ 0xA1, 0x18,
-+ 0x02, 0x01,
-+ 0x44,
-+ 0x02, 0x01,
-+ 0x06,
-+ 0x30, 0x10,
-+ 0x0A, 0x01,
-+ 0x01,
-+ 0x0A, 0x01,
-+ 0x05,
-+ 0x30, 0x06,
-+ 0x84, 0x04,
-+ 0x31, 0x38, 0x30, 0x33,
-+ 0x05, 0x00,
-+ 0x00, 0x00
-+/* *INDENT-ON* */
-+};
-+
-+static unsigned char rose_etsi_extra[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * Context Specific/C [1 0x01] <A1> Len:24 <18>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <44>
-+ * Integer(2 0x02) <02> Len:1 <01>
-+ * <07>
-+ * Sequence/C(48 0x30) <30> Len:16 <10>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <01>
-+ * Enumerated(10 0x0A) <0A> Len:1 <01>
-+ * <05>
-+ * Sequence/C(48 0x30) <30> Len:6 <06>
-+ * Context Specific [4 0x04] <84> Len:4 <04>
-+ * <31 38 30 33>
-+ * NULL(5 0x05) <05> Len:0 <00>
-+ */
-+ 0x91,
-+ 0xA1, 0x18,
-+ 0x02, 0x01,
-+ 0x44,
-+ 0x02, 0x01,
-+ 0x07,
-+ 0x30, 0x10,
-+ 0x0A, 0x01,
-+ 0x01,
-+ 0x0A, 0x01,
-+ 0x05,
-+ 0x30, 0x06,
-+ 0x84, 0x04,
-+ 0x31, 0x38, 0x30, 0x33,
-+ 0x05, 0x00,
-+ 0x00, 0x00
-+/* *INDENT-ON* */
-+};
-+
-+
-+static const struct rose_message rose_qsig_msgs[] = {
-+/* *INDENT-OFF* */
-+ /* Q.SIG Name-Operations */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 2,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 1,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ .component.invoke.args.qsig.CallingName.name.length = 7,
-+ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 3,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 1,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 3,
-+ .component.invoke.args.qsig.CallingName.name.length = 7,
-+ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 4,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 2,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ .component.invoke.args.qsig.CallingName.name.length = 7,
-+ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 5,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 2,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 3,
-+ .component.invoke.args.qsig.CallingName.name.length = 7,
-+ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 6,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 3,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallingName,
-+ .component.invoke.invoke_id = 7,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 4,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CalledName,
-+ .component.invoke.invoke_id = 8,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 4,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ConnectedName,
-+ .component.invoke.invoke_id = 9,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 4,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_BusyName,
-+ .component.invoke.invoke_id = 10,
-+ .component.invoke.args.qsig.CallingName.name.presentation = 4,
-+ .component.invoke.args.qsig.CallingName.name.char_set = 1,
-+ },
-+
-+ /* Q.SIG SS-AOC-Operations */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ChargeRequest,
-+ .component.invoke.invoke_id = 11,
-+ .component.invoke.args.qsig.ChargeRequest.num_records = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ChargeRequest,
-+ .component.invoke.invoke_id = 12,
-+ .component.invoke.args.qsig.ChargeRequest.num_records = 1,
-+ .component.invoke.args.qsig.ChargeRequest.advice_mode_combinations[0] = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ChargeRequest,
-+ .component.invoke.invoke_id = 13,
-+ .component.invoke.args.qsig.ChargeRequest.num_records = 2,
-+ .component.invoke.args.qsig.ChargeRequest.advice_mode_combinations[0] = 4,
-+ .component.invoke.args.qsig.ChargeRequest.advice_mode_combinations[1] = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_ChargeRequest,
-+ .component.result.invoke_id = 14,
-+ .component.result.args.qsig.ChargeRequest.advice_mode_combination = 3,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_GetFinalCharge,
-+ .component.invoke.invoke_id = 15,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 16,
-+ .component.invoke.args.qsig.AocFinal.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 17,
-+ .component.invoke.args.qsig.AocFinal.type = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 18,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 19,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocFinal.specific.billing_id_present = 1,
-+ .component.invoke.args.qsig.AocFinal.specific.billing_id = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 20,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocFinal.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocFinal.charging_association.type = 0,
-+ .component.invoke.args.qsig.AocFinal.charging_association.id = 200,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 21,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocFinal.specific.billing_id_present = 1,
-+ .component.invoke.args.qsig.AocFinal.specific.billing_id = 2,
-+ .component.invoke.args.qsig.AocFinal.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocFinal.charging_association.type = 0,
-+ .component.invoke.args.qsig.AocFinal.charging_association.id = 200,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocFinal,
-+ .component.invoke.invoke_id = 22,
-+ .component.invoke.args.qsig.AocFinal.type = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocFinal.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocFinal.charging_association.type = 1,
-+ .component.invoke.args.qsig.AocFinal.charging_association.number.plan = 4,
-+ .component.invoke.args.qsig.AocFinal.charging_association.number.length = 4,
-+ .component.invoke.args.qsig.AocFinal.charging_association.number.str = "1802",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocInterim,
-+ .component.invoke.invoke_id = 23,
-+ .component.invoke.args.qsig.AocInterim.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocInterim,
-+ .component.invoke.invoke_id = 24,
-+ .component.invoke.args.qsig.AocInterim.type = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocInterim,
-+ .component.invoke.invoke_id = 25,
-+ .component.invoke.args.qsig.AocInterim.type = 2,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.currency = "Rupies",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocInterim,
-+ .component.invoke.invoke_id = 26,
-+ .component.invoke.args.qsig.AocInterim.type = 2,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.currency = 800,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.multiplier = 2,
-+ .component.invoke.args.qsig.AocInterim.specific.recorded.currency = "Rupies",
-+ .component.invoke.args.qsig.AocInterim.specific.billing_id_present = 1,
-+ .component.invoke.args.qsig.AocInterim.specific.billing_id = 2,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 27,
-+ .component.invoke.args.qsig.AocRate.type = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 28,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 0,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.special_charging_code = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 29,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.currency = "Dollars",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.currency = 7,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.multiplier = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.charging_type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.length = 8,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.scale = 4,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 30,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.currency = "Dollars",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.currency = 7,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.multiplier = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.charging_type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.length = 8,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.scale = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.granularity_present = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.granularity.length = 20,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.granularity.scale = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 31,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 2,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.currency = "Euros",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.currency = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 32,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 3,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.currency = "Yen",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.amount.currency = 300,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.amount.multiplier = 5,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.unit = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 33,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 2,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 2,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.currency = "Euros",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.currency = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].currency_type = 3,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.currency = "Yen",
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.amount.currency = 300,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.amount.multiplier = 5,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.unit = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 34,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 4,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 35,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 5,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocRate,
-+ .component.invoke.invoke_id = 36,
-+ .component.invoke.args.qsig.AocRate.type = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
-+ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 6,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocComplete,
-+ .component.invoke.invoke_id = 37,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.plan = 4,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.length = 4,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocComplete,
-+ .component.invoke.invoke_id = 38,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.plan = 4,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.length = 4,
-+ .component.invoke.args.qsig.AocComplete.charged_user_number.str = "8340",
-+ .component.invoke.args.qsig.AocComplete.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocComplete.charging_association.type = 0,
-+ .component.invoke.args.qsig.AocComplete.charging_association.id = 8298,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_AocComplete,
-+ .component.result.invoke_id = 39,
-+ .component.result.args.qsig.AocComplete.charging_option = 2,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocDivChargeReq,
-+ .component.invoke.invoke_id = 40,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.plan = 4,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.length = 4,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.str = "8340",
-+ .component.invoke.args.qsig.AocDivChargeReq.diversion_type = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_AocDivChargeReq,
-+ .component.invoke.invoke_id = 41,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.plan = 4,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.length = 4,
-+ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.str = "8340",
-+ .component.invoke.args.qsig.AocDivChargeReq.charging_association_present = 1,
-+ .component.invoke.args.qsig.AocDivChargeReq.charging_association.type = 0,
-+ .component.invoke.args.qsig.AocDivChargeReq.charging_association.id = 8298,
-+ .component.invoke.args.qsig.AocDivChargeReq.diversion_type = 3,
-+ },
-+
-+ /* Q.SIG Call-Transfer-Operations (CT) */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferIdentify,
-+ .component.invoke.invoke_id = 42,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CallTransferIdentify,
-+ .component.result.invoke_id = 43,
-+ .component.result.args.qsig.CallTransferIdentify.call_id = "2345",
-+ .component.result.args.qsig.CallTransferIdentify.rerouting_number.plan = 4,
-+ .component.result.args.qsig.CallTransferIdentify.rerouting_number.length = 4,
-+ .component.result.args.qsig.CallTransferIdentify.rerouting_number.str = "8340",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferAbandon,
-+ .component.invoke.invoke_id = 44,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferInitiate,
-+ .component.invoke.invoke_id = 45,
-+ .component.invoke.args.qsig.CallTransferInitiate.call_id = "2345",
-+ .component.invoke.args.qsig.CallTransferInitiate.rerouting_number.plan = 4,
-+ .component.invoke.args.qsig.CallTransferInitiate.rerouting_number.length = 4,
-+ .component.invoke.args.qsig.CallTransferInitiate.rerouting_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CallTransferInitiate,
-+ .component.result.invoke_id = 46,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferSetup,
-+ .component.invoke.invoke_id = 47,
-+ .component.invoke.args.qsig.CallTransferSetup.call_id = "23",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CallTransferSetup,
-+ .component.result.invoke_id = 48,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
-+ .component.invoke.invoke_id = 49,
-+ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
-+ .component.invoke.invoke_id = 50,
-+ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferActive.q931ie_contents = "RT",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
-+ .component.invoke.invoke_id = 51,
-+ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
-+ .component.invoke.invoke_id = 52,
-+ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferActive.q931ie_contents = "RT",
-+ .component.invoke.args.qsig.CallTransferActive.connected_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferActive.connected_name.data = "Alphred",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 53,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 0,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.screening_indicator = 3,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.plan = 4,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.length = 4,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 54,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 55,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 56,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 3,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.screening_indicator = 3,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.plan = 4,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.length = 4,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 57,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.q931ie_contents = "RT",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 58,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection_name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 59,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.call_status = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
-+ .component.invoke.invoke_id = 60,
-+ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
-+ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferComplete.q931ie_contents = "RT",
-+ .component.invoke.args.qsig.CallTransferComplete.call_status = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
-+ .component.invoke.invoke_id = 61,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
-+ .component.invoke.invoke_id = 62,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.data = "Alphred",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
-+ .component.invoke.invoke_id = 63,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.q931ie_contents = "RT",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
-+ .component.invoke.invoke_id = 64,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name_present = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.presentation = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.char_set = 1,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.length = 7,
-+ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.data = "Alphred",
-+ .component.invoke.args.qsig.CallTransferUpdate.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallTransferUpdate.q931ie_contents = "RT",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_SubaddressTransfer,
-+ .component.invoke.invoke_id = 65,
-+ .component.invoke.args.qsig.SubaddressTransfer.redirection_subaddress.type = 1,
-+ .component.invoke.args.qsig.SubaddressTransfer.redirection_subaddress.length = 4,
-+ .component.invoke.args.qsig.SubaddressTransfer.redirection_subaddress.u.nsap = "4356",
-+ },
-+
-+ /* Q.SIG Call-Diversion-Operations */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_ActivateDiversionQ,
-+ .component.invoke.invoke_id = 66,
-+ .component.invoke.args.qsig.ActivateDiversionQ.procedure = 1,
-+ .component.invoke.args.qsig.ActivateDiversionQ.basic_service = 3,
-+ .component.invoke.args.qsig.ActivateDiversionQ.diverted_to.number.plan = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.diverted_to.number.length = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.diverted_to.number.str = "8340",
-+ .component.invoke.args.qsig.ActivateDiversionQ.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.served_user_number.length = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.ActivateDiversionQ.activating_user_number.plan = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.activating_user_number.length = 4,
-+ .component.invoke.args.qsig.ActivateDiversionQ.activating_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_ActivateDiversionQ,
-+ .component.result.invoke_id = 67,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DeactivateDiversionQ,
-+ .component.invoke.invoke_id = 68,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.procedure = 1,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.basic_service = 3,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.served_user_number.length = 4,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.DeactivateDiversionQ.deactivating_user_number.plan = 4,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.deactivating_user_number.length = 4,
-+ .component.invoke.args.qsig.DeactivateDiversionQ.deactivating_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_DeactivateDiversionQ,
-+ .component.result.invoke_id = 69,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.invoke.invoke_id = 70,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.procedure = 1,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.basic_service = 3,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.length = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.plan = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.length = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.invoke.invoke_id = 71,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.procedure = 1,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.basic_service = 0,/* default */
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.length = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.plan = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.length = 4,
-+ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.result.invoke_id = 72,
-+ .component.result.args.qsig.InterrogateDiversionQ.num_records = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.result.invoke_id = 73,
-+ .component.result.args.qsig.InterrogateDiversionQ.num_records = 1,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].basic_service = 3,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].procedure = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].remote_enabled = 0,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.result.invoke_id = 74,
-+ .component.result.args.qsig.InterrogateDiversionQ.num_records = 1,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].basic_service = 3,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].procedure = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].remote_enabled = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
-+ .component.result.invoke_id = 75,
-+ .component.result.args.qsig.InterrogateDiversionQ.num_records = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].basic_service = 3,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].procedure = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].served_user_number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].served_user_number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].served_user_number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].basic_service = 3,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].procedure = 2,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].diverted_to.number.plan = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].diverted_to.number.length = 4,
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].diverted_to.number.str = "8340",
-+ .component.result.args.qsig.InterrogateDiversionQ.list[1].remote_enabled = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CheckRestriction,
-+ .component.invoke.invoke_id = 76,
-+ .component.invoke.args.qsig.CheckRestriction.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.CheckRestriction.served_user_number.length = 4,
-+ .component.invoke.args.qsig.CheckRestriction.served_user_number.str = "8340",
-+ .component.invoke.args.qsig.CheckRestriction.basic_service = 3,
-+ .component.invoke.args.qsig.CheckRestriction.diverted_to_number.plan = 4,
-+ .component.invoke.args.qsig.CheckRestriction.diverted_to_number.length = 4,
-+ .component.invoke.args.qsig.CheckRestriction.diverted_to_number.str = "8340",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CheckRestriction,
-+ .component.result.invoke_id = 77,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallRerouting,
-+ .component.invoke.invoke_id = 78,
-+ .component.invoke.args.qsig.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.qsig.CallRerouting.called.number.plan = 4,
-+ .component.invoke.args.qsig.CallRerouting.called.number.length = 4,
-+ .component.invoke.args.qsig.CallRerouting.called.number.str = "8340",
-+ .component.invoke.args.qsig.CallRerouting.diversion_counter = 5,
-+ .component.invoke.args.qsig.CallRerouting.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallRerouting.q931ie_contents = "RT",
-+ .component.invoke.args.qsig.CallRerouting.last_rerouting.presentation = 1,
-+ .component.invoke.args.qsig.CallRerouting.subscription_option = 2,
-+ .component.invoke.args.qsig.CallRerouting.calling.presentation = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CallRerouting,
-+ .component.invoke.invoke_id = 79,
-+ .component.invoke.args.qsig.CallRerouting.rerouting_reason = 3,
-+ .component.invoke.args.qsig.CallRerouting.original_rerouting_reason_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_rerouting_reason = 2,
-+ .component.invoke.args.qsig.CallRerouting.called.number.plan = 4,
-+ .component.invoke.args.qsig.CallRerouting.called.number.length = 4,
-+ .component.invoke.args.qsig.CallRerouting.called.number.str = "8340",
-+ .component.invoke.args.qsig.CallRerouting.diversion_counter = 5,
-+ .component.invoke.args.qsig.CallRerouting.q931ie.length = 2,
-+ .component.invoke.args.qsig.CallRerouting.q931ie_contents = "RT",
-+ .component.invoke.args.qsig.CallRerouting.last_rerouting.presentation = 1,
-+ .component.invoke.args.qsig.CallRerouting.subscription_option = 2,
-+ .component.invoke.args.qsig.CallRerouting.calling_subaddress.type = 1,
-+ .component.invoke.args.qsig.CallRerouting.calling_subaddress.length = 4,
-+ .component.invoke.args.qsig.CallRerouting.calling_subaddress.u.nsap = "3253",
-+ .component.invoke.args.qsig.CallRerouting.calling.presentation = 1,
-+ .component.invoke.args.qsig.CallRerouting.calling_name_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.calling_name.presentation = 4,
-+ .component.invoke.args.qsig.CallRerouting.calling_name.char_set = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_called_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_called.presentation = 2,
-+ .component.invoke.args.qsig.CallRerouting.redirecting_name_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.redirecting_name.presentation = 4,
-+ .component.invoke.args.qsig.CallRerouting.redirecting_name.char_set = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_called_name_present = 1,
-+ .component.invoke.args.qsig.CallRerouting.original_called_name.presentation = 4,
-+ .component.invoke.args.qsig.CallRerouting.original_called_name.char_set = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_CallRerouting,
-+ .component.result.invoke_id = 80,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation1,
-+ .component.invoke.invoke_id = 81,
-+ .component.invoke.args.qsig.DivertingLegInformation1.diversion_reason = 3,
-+ .component.invoke.args.qsig.DivertingLegInformation1.subscription_option = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation1.nominated_number.plan = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation1.nominated_number.length = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation1.nominated_number.str = "8340",
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 82,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diversion_counter = 6,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diversion_reason = 3,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation2,
-+ .component.invoke.invoke_id = 83,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diversion_counter = 6,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diversion_reason = 3,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_diversion_reason_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_diversion_reason = 2,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diverting_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.diverting.presentation = 2,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called.presentation = 2,
-+ .component.invoke.args.qsig.DivertingLegInformation2.redirecting_name_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.redirecting_name.presentation = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation2.redirecting_name.char_set = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called_name_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called_name.presentation = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation2.original_called_name.char_set = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation3,
-+ .component.invoke.invoke_id = 84,
-+ .component.invoke.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation3,
-+ .component.invoke.invoke_id = 85,
-+ .component.invoke.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation3.redirection_name_present = 1,
-+ .component.invoke.args.qsig.DivertingLegInformation3.redirection_name.presentation = 4,
-+ .component.invoke.args.qsig.DivertingLegInformation3.redirection_name.char_set = 1,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_CfnrDivertedLegFailed,
-+ .component.invoke.invoke_id = 86,
-+ },
-+
-+ /* Q.SIG SS-MWI-Operations */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIActivate,
-+ .component.invoke.invoke_id = 102,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIActivate,
-+ .component.invoke.invoke_id = 103,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.type = 0,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.integer = 532,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIActivate,
-+ .component.invoke.invoke_id = 104,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.type = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.number.str = "9838",
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIActivate,
-+ .component.invoke.invoke_id = 105,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.type = 2,
-+ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.str = "123456",
-+ .component.invoke.args.qsig.MWIActivate.number_of_messages_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.number_of_messages = 6548,
-+ .component.invoke.args.qsig.MWIActivate.originating_number.plan = 4,
-+ .component.invoke.args.qsig.MWIActivate.originating_number.length = 4,
-+ .component.invoke.args.qsig.MWIActivate.originating_number.str = "9838",
-+ .component.invoke.args.qsig.MWIActivate.timestamp_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.timestamp = "19970621194530",
-+ .component.invoke.args.qsig.MWIActivate.priority_present = 1,
-+ .component.invoke.args.qsig.MWIActivate.priority = 7,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_MWIActivate,
-+ .component.result.invoke_id = 106,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIDeactivate,
-+ .component.invoke.invoke_id = 107,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIDeactivate.basic_service = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIDeactivate,
-+ .component.invoke.invoke_id = 108,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIDeactivate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIDeactivate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIDeactivate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIDeactivate.msg_centre_id.type = 0,
-+ .component.invoke.args.qsig.MWIDeactivate.msg_centre_id.u.integer = 532,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_MWIDeactivate,
-+ .component.result.invoke_id = 109,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIInterrogate,
-+ .component.invoke.invoke_id = 110,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIInterrogate.basic_service = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_QSIG_MWIInterrogate,
-+ .component.invoke.invoke_id = 111,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.plan = 4,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.length = 4,
-+ .component.invoke.args.qsig.MWIInterrogate.served_user_number.str = "9838",
-+ .component.invoke.args.qsig.MWIInterrogate.basic_service = 1,
-+ .component.invoke.args.qsig.MWIInterrogate.msg_centre_id_present = 1,
-+ .component.invoke.args.qsig.MWIInterrogate.msg_centre_id.type = 0,
-+ .component.invoke.args.qsig.MWIInterrogate.msg_centre_id.u.integer = 532,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_MWIInterrogate,
-+ .component.result.invoke_id = 112,
-+ .component.result.args.qsig.MWIInterrogate.num_records = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].basic_service = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_QSIG_MWIInterrogate,
-+ .component.result.invoke_id = 113,
-+ .component.result.args.qsig.MWIInterrogate.num_records = 2,
-+ .component.result.args.qsig.MWIInterrogate.list[0].basic_service = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].msg_centre_id_present = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].msg_centre_id.type = 0,
-+ .component.result.args.qsig.MWIInterrogate.list[0].msg_centre_id.u.integer = 987,
-+ .component.result.args.qsig.MWIInterrogate.list[0].number_of_messages_present = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].number_of_messages = 6548,
-+ .component.result.args.qsig.MWIInterrogate.list[0].originating_number.plan = 4,
-+ .component.result.args.qsig.MWIInterrogate.list[0].originating_number.length = 4,
-+ .component.result.args.qsig.MWIInterrogate.list[0].originating_number.str = "9838",
-+ .component.result.args.qsig.MWIInterrogate.list[0].timestamp_present = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].timestamp = "19970621194530",
-+ .component.result.args.qsig.MWIInterrogate.list[0].priority_present = 1,
-+ .component.result.args.qsig.MWIInterrogate.list[0].priority = 7,
-+ .component.result.args.qsig.MWIInterrogate.list[1].basic_service = 1,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+static const struct rose_message rose_dms100_msgs[] = {
-+/* *INDENT-OFF* */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_DMS100_RLT_OperationInd,
-+ .component.invoke.invoke_id = ROSE_DMS100_RLT_OPERATION_IND,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_DMS100_RLT_OperationInd,
-+ .component.result.invoke_id = ROSE_DMS100_RLT_OPERATION_IND,
-+ .component.result.args.dms100.RLT_OperationInd.call_id = 130363,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_DMS100_RLT_ThirdParty,
-+ .component.invoke.invoke_id = ROSE_DMS100_RLT_THIRD_PARTY,
-+ .component.invoke.args.dms100.RLT_ThirdParty.call_id = 120047,
-+ .component.invoke.args.dms100.RLT_ThirdParty.reason = 1,
-+ },
-+ {
-+ .type = ROSE_COMP_TYPE_RESULT,
-+ .component.result.operation = ROSE_DMS100_RLT_ThirdParty,
-+ .component.result.invoke_id = ROSE_DMS100_RLT_THIRD_PARTY,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+static const struct rose_message rose_ni2_msgs[] = {
-+/* *INDENT-OFF* */
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_NI2_InformationFollowing,
-+ .component.invoke.invoke_id = 1,
-+ .component.invoke.args.ni2.InformationFollowing.value = 7,
-+ },
-+
-+ {
-+ .type = ROSE_COMP_TYPE_INVOKE,
-+ .component.invoke.operation = ROSE_NI2_InitiateTransfer,
-+ .component.invoke.invoke_id = 2,
-+ .component.invoke.args.ni2.InitiateTransfer.call_reference = 5,
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+/* ------------------------------------------------------------------- */
-+
-+static void rose_pri_message(struct pri *ctrl, char *stuff)
-+{
-+ fprintf(stdout, "%s", stuff);
-+}
-+
-+static void rose_pri_error(struct pri *ctrl, char *stuff)
-+{
-+ fprintf(stdout, "%s", stuff);
-+ fprintf(stderr, "%s", stuff);
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Test ROSE encoding and decoding the given message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param index Message number to report.
-+ * \param header Facility message header data to encode.
-+ * \param encode_msg Message data to encode.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_test_msg(struct pri *ctrl, unsigned index,
-+ const struct fac_extension_header *header, const struct rose_message *encode_msg)
-+{
-+ struct fac_extension_header decoded_header;
-+ struct rose_message decoded_msg;
-+ unsigned char *enc_pos;
-+ unsigned char *enc_end;
-+ const unsigned char *dec_pos;
-+ const unsigned char *dec_end;
-+
-+ static unsigned char buf[1024];
-+
-+ pri_message(ctrl, "\n\n");
-+ enc_end = buf + sizeof(buf);
-+ enc_pos = facility_encode_header(ctrl, buf, enc_end, header);
-+ if (!enc_pos) {
-+ pri_error(ctrl, "Error: Message:%u failed to encode header\n", index);
-+ } else {
-+ enc_pos = rose_encode(ctrl, enc_pos, enc_end, encode_msg);
-+ if (!enc_pos) {
-+ pri_error(ctrl, "Error: Message:%u failed to encode ROSE\n", index);
-+ } else {
-+ pri_message(ctrl, "Message %u encoded length is %u\n", index,
-+ (unsigned) (enc_pos - buf));
-+
-+ /* Clear the decoded message contents for comparison. */
-+ memset(&decoded_header, 0, sizeof(decoded_header));
-+ memset(&decoded_msg, 0, sizeof(decoded_msg));
-+
-+ dec_end = enc_pos;
-+ dec_pos = facility_decode_header(ctrl, buf, dec_end, &decoded_header);
-+ if (!dec_pos) {
-+ pri_error(ctrl, "Error: Message:%u failed to decode header\n", index);
-+ } else {
-+ dec_pos = rose_decode(ctrl, dec_pos, dec_end, &decoded_msg);
-+ if (!dec_pos) {
-+ pri_error(ctrl, "Error: Message:%u failed to decode ROSE\n", index);
-+ } else {
-+ if (header
-+ && memcmp(header, &decoded_header, sizeof(decoded_header))) {
-+ pri_error(ctrl, "Error: Message:%u Header did not match\n",
-+ index);
-+ }
-+ if (memcmp(encode_msg, &decoded_msg, sizeof(decoded_msg))) {
-+ pri_error(ctrl, "Error: Message:%u ROSE did not match\n", index);
-+ }
-+ }
-+ }
-+ }
-+ }
-+ pri_message(ctrl, "\n\n"
-+ "************************************************************\n");
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Test ROSE decoding messages of unusual encodings.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Test name for the encoded message.
-+ * \param msg_buf Encoded message to decode.
-+ * \param msg_len Length of encoded message buffer.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_test_exception(struct pri *ctrl, const char *name,
-+ const unsigned char *msg, size_t msg_len)
-+{
-+ const unsigned char *pos;
-+ const unsigned char *end;
-+ struct fac_extension_header header;
-+ struct rose_message decoded_msg;
-+
-+ pri_message(ctrl, "\n\n"
-+ "%s test: Message encoded length is %u\n", name, (unsigned) msg_len);
-+
-+ pos = msg;
-+ end = msg + msg_len;
-+ pos = facility_decode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ pri_error(ctrl, "Error: %s test: Message failed to decode header\n", name);
-+ } else {
-+ pos = rose_decode(ctrl, pos, end, &decoded_msg);
-+ if (!pos) {
-+ pri_error(ctrl, "Error: %s test: Message failed to decode ROSE\n", name);
-+ }
-+ }
-+
-+ pri_message(ctrl, "\n\n"
-+ "************************************************************\n");
-+}
-+
-+/*!
-+ * \brief ROSE encode/decode test program.
-+ *
-+ * \param argc Program argument count.
-+ * \param argv Program argument string array.
-+ *
-+ * \retval 0 on success.
-+ * \retval Nonzero on error.
-+ */
-+int main(int argc, char *argv[])
-+{
-+ unsigned index;
-+ unsigned offset;
-+ static struct pri dummy_ctrl;
-+
-+ pri_set_message(rose_pri_message);
-+ pri_set_error(rose_pri_error);
-+
-+ memset(&dummy_ctrl, 0, sizeof(dummy_ctrl));
-+ dummy_ctrl.debug = PRI_DEBUG_APDU;
-+
-+ offset = 0;
-+ pri_message(&dummy_ctrl, "Encode/decode message(s)\n");
-+ if (argc <= 1) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
-+ for (index = 0; index < ARRAY_LEN(rose_etsi_msgs); ++index) {
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_etsi_msgs[index]);
-+ }
-+ offset += ARRAY_LEN(rose_etsi_msgs);
-+
-+ dummy_ctrl.switchtype = PRI_SWITCH_QSIG;
-+ for (index = 0; index < ARRAY_LEN(rose_qsig_msgs); ++index) {
-+ rose_test_msg(&dummy_ctrl, index + offset,
-+ &fac_headers[index % ARRAY_LEN(fac_headers)], &rose_qsig_msgs[index]);
-+ }
-+ offset += ARRAY_LEN(rose_qsig_msgs);
-+
-+ dummy_ctrl.switchtype = PRI_SWITCH_DMS100;
-+ for (index = 0; index < ARRAY_LEN(rose_dms100_msgs); ++index) {
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_dms100_msgs[index]);
-+ }
-+ offset += ARRAY_LEN(rose_dms100_msgs);
-+
-+ dummy_ctrl.switchtype = PRI_SWITCH_NI2;
-+ for (index = 0; index < ARRAY_LEN(rose_ni2_msgs); ++index) {
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_ni2_msgs[index]);
-+ }
-+ //offset += ARRAY_LEN(rose_ni2_msgs);
-+ } else {
-+ index = atoi(argv[1]);
-+
-+ if (index < ARRAY_LEN(rose_etsi_msgs)) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_etsi_msgs[index]);
-+ return 0;
-+ }
-+ offset += ARRAY_LEN(rose_etsi_msgs);
-+ index -= ARRAY_LEN(rose_etsi_msgs);
-+
-+ if (index < ARRAY_LEN(rose_qsig_msgs)) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_QSIG;
-+ rose_test_msg(&dummy_ctrl, index + offset,
-+ &fac_headers[index % ARRAY_LEN(fac_headers)], &rose_qsig_msgs[index]);
-+ return 0;
-+ }
-+ offset += ARRAY_LEN(rose_qsig_msgs);
-+ index -= ARRAY_LEN(rose_qsig_msgs);
-+
-+ if (index < ARRAY_LEN(rose_dms100_msgs)) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_DMS100;
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_dms100_msgs[index]);
-+ return 0;
-+ }
-+ offset += ARRAY_LEN(rose_dms100_msgs);
-+ index -= ARRAY_LEN(rose_dms100_msgs);
-+
-+ if (index < ARRAY_LEN(rose_ni2_msgs)) {
-+ dummy_ctrl.switchtype = PRI_SWITCH_NI2;
-+ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
-+ &rose_ni2_msgs[index]);
-+ return 0;
-+ }
-+ //offset += ARRAY_LEN(rose_ni2_msgs);
-+ //index -= ARRAY_LEN(rose_ni2_msgs);
-+
-+ fprintf(stderr, "Invalid option\n");
-+ return 0;
-+ }
-+
-+/* ------------------------------------------------------------------- */
-+
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "Decode unusually encoded messages\n");
-+
-+ dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
-+
-+ rose_test_exception(&dummy_ctrl, "Extra bytes on end", rose_etsi_extra,
-+ sizeof(rose_etsi_extra));
-+
-+ rose_test_exception(&dummy_ctrl, "Indefinite length", rose_etsi_indefinite_len,
-+ sizeof(rose_etsi_indefinite_len) - 2);
-+ rose_test_exception(&dummy_ctrl, "Indefinite length (extra)",
-+ rose_etsi_indefinite_len, sizeof(rose_etsi_indefinite_len));
-+
-+ rose_test_exception(&dummy_ctrl, "Unused components (indefinite length)",
-+ rose_etsi_unused_indefinite_len, sizeof(rose_etsi_unused_indefinite_len) - 2);
-+ rose_test_exception(&dummy_ctrl, "Unused components (indefinite length, extra)",
-+ rose_etsi_unused_indefinite_len, sizeof(rose_etsi_unused_indefinite_len));
-+
-+ rose_test_exception(&dummy_ctrl, "Unused components", rose_etsi_unused,
-+ sizeof(rose_etsi_unused) - 2);
-+ rose_test_exception(&dummy_ctrl, "Unused components (extra)", rose_etsi_unused,
-+ sizeof(rose_etsi_unused));
-+
-+/* ------------------------------------------------------------------- */
-+
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "List of operation codes:\n");
-+ for (index = 0; index < ROSE_Num_Operation_Codes; ++index) {
-+ pri_message(&dummy_ctrl, "%d: %s\n", index, rose_operation2str(index));
-+ }
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "************************************************************\n");
-+
-+/* ------------------------------------------------------------------- */
-+
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "List of error codes:\n");
-+ for (index = 0; index < ROSE_ERROR_Num_Codes; ++index) {
-+ pri_message(&dummy_ctrl, "%d: %s\n", index, rose_error2str(index));
-+ }
-+ pri_message(&dummy_ctrl, "\n\n"
-+ "************************************************************\n");
-+
-+/* ------------------------------------------------------------------- */
-+
-+ pri_message(&dummy_ctrl, "\n\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_message) = %u\n",
-+ (unsigned) sizeof(struct rose_message));
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_invoke) = %u\n",
-+ (unsigned) sizeof(struct rose_msg_invoke));
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_result) = %u\n",
-+ (unsigned) sizeof(struct rose_msg_result));
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_error) = %u\n",
-+ (unsigned) sizeof(struct rose_msg_error));
-+ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_reject) = %u\n",
-+ (unsigned) sizeof(struct rose_msg_reject));
-+ pri_message(&dummy_ctrl, "sizeof(union rose_msg_invoke_args) = %u\n",
-+ (unsigned) sizeof(union rose_msg_invoke_args));
-+ pri_message(&dummy_ctrl, "sizeof(union rose_msg_result_args) = %u\n",
-+ (unsigned) sizeof(union rose_msg_result_args));
-+
-+ pri_message(&dummy_ctrl, "\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct roseQsigForwardingList) = %u\n",
-+ (unsigned) sizeof(struct roseQsigForwardingList));
-+
-+ pri_message(&dummy_ctrl, "\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct roseQsigCallRerouting_ARG) = %u\n",
-+ (unsigned) sizeof(struct roseQsigCallRerouting_ARG));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseQsigAocRateArg_ARG) = %u\n",
-+ (unsigned) sizeof(struct roseQsigAocRateArg_ARG));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseQsigMWIInterrogateRes) = %u\n",
-+ (unsigned) sizeof(struct roseQsigMWIInterrogateRes));
-+
-+ pri_message(&dummy_ctrl, "\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiForwardingList) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiForwardingList));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiServedUserNumberList) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiServedUserNumberList));
-+
-+ pri_message(&dummy_ctrl, "\n");
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiCallRerouting_ARG) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiCallRerouting_ARG));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiDiversionInformation_ARG) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiDiversionInformation_ARG));
-+ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiAOCSCurrencyInfoList) = %u\n",
-+ (unsigned) sizeof(struct roseEtsiAOCSCurrencyInfoList));
-+
-+/* ------------------------------------------------------------------- */
-+
-+ return 0;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rosetest.c */
-
-Property changes on: rosetest.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_internal.h
-===================================================================
---- a/rose_internal.h (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_internal.h (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,477 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Internal definitions and prototypes for ROSE.
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+#ifndef _LIBPRI_ROSE_INTERNAL_H
-+#define _LIBPRI_ROSE_INTERNAL_H
-+
-+#include "rose.h"
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/* Embedded-Q931-Types */
-+unsigned char *rose_enc_Q931ie(struct pri *ctrl, unsigned char *pos, unsigned char *end,
-+ unsigned tag, const struct roseQ931ie *q931ie);
-+
-+const unsigned char *rose_dec_Q931ie(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct roseQ931ie *q931ie,
-+ size_t contents_size);
-+
-+/* Addressing-Data-Elements */
-+unsigned char *rose_enc_PartyNumber(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePartyNumber *party_number);
-+unsigned char *rose_enc_PartySubaddress(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePartySubaddress *party_subaddress);
-+unsigned char *rose_enc_Address(struct pri *ctrl, unsigned char *pos, unsigned char *end,
-+ unsigned tag, const struct roseAddress *address);
-+unsigned char *rose_enc_PresentedNumberUnscreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePresentedNumberUnscreened *party);
-+unsigned char *rose_enc_NumberScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseNumberScreened *screened);
-+unsigned char *rose_enc_PresentedNumberScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePresentedNumberScreened *party);
-+unsigned char *rose_enc_AddressScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseAddressScreened *screened);
-+unsigned char *rose_enc_PresentedAddressScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePresentedAddressScreened *party);
-+
-+const unsigned char *rose_dec_PartyNumber(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartyNumber *party_number);
-+const unsigned char *rose_dec_PartySubaddress(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartySubaddress *party_subaddress);
-+const unsigned char *rose_dec_Address(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct roseAddress *address);
-+const unsigned char *rose_dec_PresentedNumberUnscreened(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePresentedNumberUnscreened *party);
-+const unsigned char *rose_dec_NumberScreened(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseNumberScreened *screened);
-+const unsigned char *rose_dec_PresentedNumberScreened(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePresentedNumberScreened *party);
-+const unsigned char *rose_dec_AddressScreened(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseAddressScreened *screened);
-+const unsigned char *rose_dec_PresentedAddressScreened(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePresentedAddressScreened *party);
-+
-+/* ETSI Advice-of-Charge (AOC) */
-+unsigned char *rose_enc_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* ETSI Call Diversion */
-+unsigned char *rose_enc_etsi_ActivationDiversion_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_DeactivationStatusNotificationDiv_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_InterrogationDiversion_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_etsi_DiversionInformation_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_etsi_ActivationDiversion_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_DeactivationStatusNotificationDiv_ARG(struct pri
-+ *ctrl, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_InterrogationDiversion_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_etsi_DiversionInformation_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* ETSI Explicit Call Transfer (ECT) */
-+unsigned char *rose_enc_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_etsi_EctInform_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+
-+const unsigned char *rose_dec_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_etsi_EctInform_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+
-+/* Q.SIG Name-Operations */
-+unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct roseQsigName *name);
-+
-+const unsigned char *rose_dec_qsig_Name(struct pri *ctrl, const char *fname,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigName *name);
-+
-+unsigned char *rose_enc_qsig_CallingName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CalledName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_BusyName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_qsig_CallingName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CalledName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_BusyName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/*
-+ * Q.SIG Dummy invoke/result argument used by:
-+ * SS-AOC-Operations,
-+ * Call-Transfer-Operations,
-+ * Call-Diversion-Operations,
-+ * and SS-MWI-Operations.
-+ */
-+unsigned char *rose_enc_qsig_DummyArg_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DummyRes_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+
-+const unsigned char *rose_dec_qsig_DummyArg_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DummyRes_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+
-+/* Q.SIG SS-AOC-Operations */
-+unsigned char *rose_enc_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_qsig_AocFinal_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_AocInterim_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_AocRate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_AocComplete_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_AocComplete_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_qsig_AocFinal_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_AocInterim_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_AocRate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_AocComplete_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_AocComplete_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* Q.SIG Call-Diversion-Operations */
-+unsigned char *rose_enc_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* Q.SIG Call-Transfer-Operations (CT) */
-+unsigned char *rose_enc_qsig_CallTransferIdentify_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallTransferComplete_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_qsig_CallTransferIdentify_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferComplete_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* Q.SIG SS-MWI-Operations */
-+unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+
-+const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+
-+/* Northern Telecom DMS-100 operations */
-+unsigned char *rose_enc_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+unsigned char *rose_enc_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+const unsigned char *rose_dec_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+/* National ISDN 2 (NI2) operations */
-+unsigned char *rose_enc_ni2_InformationFollowing_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
-+unsigned char *rose_enc_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+
-+const unsigned char *rose_dec_ni2_InformationFollowing_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+const unsigned char *rose_dec_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif /* _LIBPRI_ROSE_INTERNAL_H */
-+/* ------------------------------------------------------------------- */
-+/* end rose_internal.h */
-
-Property changes on: rose_internal.h
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: pri_q921.h
-===================================================================
---- a/pri_q921.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_q921.h (.../branches/1.4) (revision 1357)
-@@ -192,4 +192,10 @@
-
- extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
-
-+extern int q921_transmit_uiframe(struct pri *pri, void *buf, int len);
-+
-+extern pri_event *q921_dchannel_up(struct pri *pri);
-+
-+extern pri_event *q921_dchannel_down(struct pri *pri);
-+
- #endif
-Index: pri_facility.c
-===================================================================
---- a/pri_facility.c (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_facility.c (.../branches/1.4) (revision 1357)
-@@ -33,872 +33,1340 @@
- #include "pri_q921.h"
- #include "pri_q931.h"
- #include "pri_facility.h"
-+#include "rose.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
-
--static char *asn1id2text(int id)
-+static short get_invokeid(struct pri *ctrl)
- {
-- static char data[32];
-- static char *strings[] = {
-- "none",
-- "Boolean",
-- "Integer",
-- "Bit String",
-- "Octet String",
-- "NULL",
-- "Object Identifier",
-- "Object Descriptor",
-- "External Reference",
-- "Real Number",
-- "Enumerated",
-- "Embedded PDV",
-- "UTF-8 String",
-- "Relative Object ID",
-- "Reserved (0e)",
-- "Reserved (0f)",
-- "Sequence",
-- "Set",
-- "Numeric String",
-- "Printable String",
-- "Tele-Text String",
-- "IA-5 String",
-- "UTC Time",
-- "Generalized Time",
-- };
-- if (id > 0 && id <= 0x18) {
-- return strings[id];
-- } else {
-- sprintf(data, "Unknown (%02x)", id);
-- return data;
-- }
-+ ctrl = PRI_MASTER(ctrl);
-+ return ++ctrl->last_invoke;
- }
-
--static int asn1_dumprecursive(struct pri *pri, void *comp_ptr, int len, int level)
-+static int redirectingreason_from_q931(struct pri *ctrl, int redirectingreason)
- {
-- unsigned char *vdata = (unsigned char *)comp_ptr;
-- struct rose_component *comp;
-- int i = 0;
-- int j, k, l;
-- int clen = 0;
-+ int value;
-
-- while (len > 0) {
-- GET_COMPONENT(comp, i, vdata, len);
-- pri_message(pri, "%*s%02X %04X", 2 * level, "", comp->type, comp->len);
-- if ((comp->type == 0) && (comp->len == 0))
-- return clen + 2;
-- if ((comp->type & ASN1_PC_MASK) == ASN1_PRIMITIVE) {
-- for (j = 0; j < comp->len; ++j)
-- pri_message(pri, " %02X", comp->data[j]);
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_QSIG:
-+ switch (redirectingreason) {
-+ case PRI_REDIR_UNKNOWN:
-+ value = QSIG_DIVERT_REASON_UNKNOWN;
-+ break;
-+ case PRI_REDIR_FORWARD_ON_BUSY:
-+ value = QSIG_DIVERT_REASON_CFB;
-+ break;
-+ case PRI_REDIR_FORWARD_ON_NO_REPLY:
-+ value = QSIG_DIVERT_REASON_CFNR;
-+ break;
-+ case PRI_REDIR_UNCONDITIONAL:
-+ value = QSIG_DIVERT_REASON_CFU;
-+ break;
-+ case PRI_REDIR_DEFLECTION:
-+ case PRI_REDIR_DTE_OUT_OF_ORDER:
-+ case PRI_REDIR_FORWARDED_BY_DTE:
-+ pri_message(ctrl,
-+ "!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n",
-+ redirectingreason);
-+ /* Fall through */
-+ default:
-+ value = QSIG_DIVERT_REASON_UNKNOWN;
-+ break;
- }
-- if ((comp->type & ASN1_CLAN_MASK) == ASN1_UNIVERSAL) {
-- switch (comp->type & ASN1_TYPE_MASK) {
-- case 0:
-- pri_message(pri, " (none)");
-- break;
-- case ASN1_BOOLEAN:
-- pri_message(pri, " (BOOLEAN: %d)", comp->data[0]);
-- break;
-- case ASN1_INTEGER:
-- for (k = l = 0; k < comp->len; ++k)
-- l = (l << 8) | comp->data[k];
-- pri_message(pri, " (INTEGER: %d)", l);
-- break;
-- case ASN1_BITSTRING:
-- pri_message(pri, " (BITSTRING:");
-- for (k = 0; k < comp->len; ++k)
-- pri_message(pri, " %02x", comp->data[k]);
-- pri_message(pri, ")");
-- break;
-- case ASN1_OCTETSTRING:
-- pri_message(pri, " (OCTETSTRING:");
-- for (k = 0; k < comp->len; ++k)
-- pri_message(pri, " %02x", comp->data[k]);
-- pri_message(pri, ")");
-- break;
-- case ASN1_NULL:
-- pri_message(pri, " (NULL)");
-- break;
-- case ASN1_OBJECTIDENTIFIER:
-- pri_message(pri, " (OBJECTIDENTIFIER:");
-- for (k = 0; k < comp->len; ++k)
-- pri_message(pri, " %02x", comp->data[k]);
-- pri_message(pri, ")");
-- break;
-- case ASN1_ENUMERATED:
-- for (k = l = 0; k < comp->len; ++k)
-- l = (l << 8) | comp->data[k];
-- pri_message(pri, " (ENUMERATED: %d)", l);
-- break;
-- case ASN1_SEQUENCE:
-- pri_message(pri, " (SEQUENCE)");
-- break;
-- default:
-- pri_message(pri, " (component %02x - %s)", comp->type, asn1id2text(comp->type & ASN1_TYPE_MASK));
-- break;
-- }
-+ break;
-+ default:
-+ switch (redirectingreason) {
-+ case PRI_REDIR_UNKNOWN:
-+ value = Q952_DIVERT_REASON_UNKNOWN;
-+ break;
-+ case PRI_REDIR_FORWARD_ON_BUSY:
-+ value = Q952_DIVERT_REASON_CFB;
-+ break;
-+ case PRI_REDIR_FORWARD_ON_NO_REPLY:
-+ value = Q952_DIVERT_REASON_CFNR;
-+ break;
-+ case PRI_REDIR_DEFLECTION:
-+ value = Q952_DIVERT_REASON_CD;
-+ break;
-+ case PRI_REDIR_UNCONDITIONAL:
-+ value = Q952_DIVERT_REASON_CFU;
-+ break;
-+ case PRI_REDIR_DTE_OUT_OF_ORDER:
-+ case PRI_REDIR_FORWARDED_BY_DTE:
-+ pri_message(ctrl,
-+ "!! Don't know how to convert Q.931 redirection reason %d to Q.952\n",
-+ redirectingreason);
-+ /* Fall through */
-+ default:
-+ value = Q952_DIVERT_REASON_UNKNOWN;
-+ break;
- }
-- else if ((comp->type & ASN1_CLAN_MASK) == ASN1_CONTEXT_SPECIFIC) {
-- pri_message(pri, " (CONTEXT SPECIFIC [%d])", comp->type & ASN1_TYPE_MASK);
-+ break;
-+ }
-+
-+ return value;
-+}
-+
-+static int redirectingreason_for_q931(struct pri *ctrl, int redirectingreason)
-+{
-+ int value;
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_QSIG:
-+ switch (redirectingreason) {
-+ case QSIG_DIVERT_REASON_UNKNOWN:
-+ value = PRI_REDIR_UNKNOWN;
-+ break;
-+ case QSIG_DIVERT_REASON_CFU:
-+ value = PRI_REDIR_UNCONDITIONAL;
-+ break;
-+ case QSIG_DIVERT_REASON_CFB:
-+ value = PRI_REDIR_FORWARD_ON_BUSY;
-+ break;
-+ case QSIG_DIVERT_REASON_CFNR:
-+ value = PRI_REDIR_FORWARD_ON_NO_REPLY;
-+ break;
-+ default:
-+ pri_message(ctrl, "!! Unknown Q.SIG diversion reason %d\n",
-+ redirectingreason);
-+ value = PRI_REDIR_UNKNOWN;
-+ break;
- }
-- else {
-- pri_message(pri, " (component %02x)", comp->type);
-+ break;
-+ default:
-+ switch (redirectingreason) {
-+ case Q952_DIVERT_REASON_UNKNOWN:
-+ value = PRI_REDIR_UNKNOWN;
-+ break;
-+ case Q952_DIVERT_REASON_CFU:
-+ value = PRI_REDIR_UNCONDITIONAL;
-+ break;
-+ case Q952_DIVERT_REASON_CFB:
-+ value = PRI_REDIR_FORWARD_ON_BUSY;
-+ break;
-+ case Q952_DIVERT_REASON_CFNR:
-+ value = PRI_REDIR_FORWARD_ON_NO_REPLY;
-+ break;
-+ case Q952_DIVERT_REASON_CD:
-+ value = PRI_REDIR_DEFLECTION;
-+ break;
-+ case Q952_DIVERT_REASON_IMMEDIATE:
-+ pri_message(ctrl,
-+ "!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
-+ value = PRI_REDIR_UNKNOWN; /* ??? */
-+ break;
-+ default:
-+ pri_message(ctrl, "!! Unknown Q.952 diversion reason %d\n",
-+ redirectingreason);
-+ value = PRI_REDIR_UNKNOWN;
-+ break;
- }
-- pri_message(pri, "\n");
-- if ((comp->type & ASN1_PC_MASK) == ASN1_CONSTRUCTOR)
-- j = asn1_dumprecursive(pri, comp->data, (comp->len ? comp->len : INT_MAX), level+1);
-- else
-- j = comp->len;
-- j += 2;
-- len -= j;
-- vdata += j;
-- clen += j;
-+ break;
- }
-- return clen;
-+
-+ return value;
- }
-
--int asn1_dump(struct pri *pri, void *comp, int len)
-+/*!
-+ * \brief Convert the Q.931 type-of-number field to facility.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param ton Q.931 ton/plan octet.
-+ *
-+ * \return PartyNumber enumeration value.
-+ */
-+static int typeofnumber_from_q931(struct pri *ctrl, int ton)
- {
-- return asn1_dumprecursive(pri, comp, len, 0);
-+ int value;
-+
-+ switch ((ton >> 4) & 0x03) {
-+ default:
-+ pri_message(ctrl, "!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton);
-+ /* fall through */
-+ case PRI_TON_UNKNOWN:
-+ value = Q932_TON_UNKNOWN;
-+ break;
-+ case PRI_TON_INTERNATIONAL:
-+ value = Q932_TON_INTERNATIONAL;
-+ break;
-+ case PRI_TON_NATIONAL:
-+ value = Q932_TON_NATIONAL;
-+ break;
-+ case PRI_TON_NET_SPECIFIC:
-+ value = Q932_TON_NET_SPECIFIC;
-+ break;
-+ case PRI_TON_SUBSCRIBER:
-+ value = Q932_TON_SUBSCRIBER;
-+ break;
-+ case PRI_TON_ABBREVIATED:
-+ value = Q932_TON_ABBREVIATED;
-+ break;
-+ }
-+
-+ return value;
- }
-
--static unsigned char get_invokeid(struct pri *pri)
-+static int typeofnumber_for_q931(struct pri *ctrl, int ton)
- {
-- return ++pri->last_invoke;
-+ int value;
-+
-+ switch (ton) {
-+ default:
-+ pri_message(ctrl, "!! Invalid TypeOfNumber %d\n", ton);
-+ /* fall through */
-+ case Q932_TON_UNKNOWN:
-+ value = PRI_TON_UNKNOWN;
-+ break;
-+ case Q932_TON_INTERNATIONAL:
-+ value = PRI_TON_INTERNATIONAL;
-+ break;
-+ case Q932_TON_NATIONAL:
-+ value = PRI_TON_NATIONAL;
-+ break;
-+ case Q932_TON_NET_SPECIFIC:
-+ value = PRI_TON_NET_SPECIFIC;
-+ break;
-+ case Q932_TON_SUBSCRIBER:
-+ value = PRI_TON_SUBSCRIBER;
-+ break;
-+ case Q932_TON_ABBREVIATED:
-+ value = PRI_TON_ABBREVIATED;
-+ break;
-+ }
-+
-+ return value << 4;
- }
-
--struct addressingdataelements_presentednumberunscreened {
-- char partyaddress[21];
-- char partysubaddress[21];
-- int npi; /* Numbering Plan Indicator */
-- int ton; /* Type Of Number */
-- int pres; /* Presentation */
--};
-+/*!
-+ * \internal
-+ * \brief Convert the Q.931 numbering plan field to facility.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param plan Q.931 ton/plan octet.
-+ *
-+ * \return PartyNumber enumeration value.
-+ */
-+static int numbering_plan_from_q931(struct pri *ctrl, int plan)
-+{
-+ int value;
-
--struct addressingdataelements_presentednumberscreened {
-- char partyaddress[21];
-- char partysubaddress[21];
-- int npi; /* Numbering Plan Indicator */
-- int ton; /* Type Of Number */
-- int pres; /* Presentation */
-- int scrind; /* Screening Indicator */
--};
-+ switch (plan & 0x0F) {
-+ default:
-+ pri_message(ctrl, "!! Unsupported Q.931 numbering plan value (%d)\n", plan);
-+ /* fall through */
-+ case PRI_NPI_UNKNOWN:
-+ value = 0; /* unknown */
-+ break;
-+ case PRI_NPI_E163_E164:
-+ value = 1; /* public */
-+ break;
-+ case PRI_NPI_X121:
-+ value = 3; /* data */
-+ break;
-+ case PRI_NPI_F69:
-+ value = 4; /* telex */
-+ break;
-+ case PRI_NPI_NATIONAL:
-+ value = 8; /* nationalStandard */
-+ break;
-+ case PRI_NPI_PRIVATE:
-+ value = 5; /* private */
-+ break;
-+ }
-
--#define PRI_CHECKOVERFLOW(size) \
-- if (msgptr - message + (size) >= sizeof(message)) { \
-- *msgptr = '\0'; \
-- pri_message(pri, "%s", message); \
-- msgptr = message; \
-- }
-+ return value;
-+}
-
--static void dump_apdu(struct pri *pri, unsigned char *c, int len)
-+/*!
-+ * \internal
-+ * \brief Convert the PartyNumber numbering plan to Q.931 plan field value.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param plan PartyNumber enumeration value.
-+ *
-+ * \return Q.931 plan field value.
-+ */
-+static int numbering_plan_for_q931(struct pri *ctrl, int plan)
- {
-- #define MAX_APDU_LENGTH 255
-- static char hexs[16] = "0123456789ABCDEF";
-- int i;
-- char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */
-- char *msgptr;
--
-- msgptr = message;
-- *msgptr++ = ' ';
-- *msgptr++ = '[';
-- for (i=0; i<len; i++) {
-- PRI_CHECKOVERFLOW(3);
-- *msgptr++ = ' ';
-- *msgptr++ = hexs[(c[i] >> 4) & 0x0f];
-- *msgptr++ = hexs[(c[i]) & 0x0f];
-+ int value;
-+
-+ switch (plan) {
-+ default:
-+ pri_message(ctrl,
-+ "!! Unsupported PartyNumber to Q.931 numbering plan value (%d)\n", plan);
-+ /* fall through */
-+ case 0: /* unknown */
-+ value = PRI_NPI_UNKNOWN;
-+ break;
-+ case 1: /* public */
-+ value = PRI_NPI_E163_E164;
-+ break;
-+ case 3: /* data */
-+ value = PRI_NPI_X121;
-+ break;
-+ case 4: /* telex */
-+ value = PRI_NPI_F69;
-+ break;
-+ case 5: /* private */
-+ value = PRI_NPI_PRIVATE;
-+ break;
-+ case 8: /* nationalStandard */
-+ value = PRI_NPI_NATIONAL;
-+ break;
- }
-- PRI_CHECKOVERFLOW(6);
-- strcpy(msgptr, " ] - [");
-- msgptr += strlen(msgptr);
-- for (i=0; i<len; i++) {
-- PRI_CHECKOVERFLOW(1);
-- *msgptr++ = ((c[i] < ' ') || (c[i] > '~')) ? '.' : c[i];
-+
-+ return value;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the Q.931 number presentation field to facility.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Q.931 presentation/screening octet.
-+ * \param number_present Non-zero if the number is available.
-+ *
-+ * \return Presented<Number/Address><Screened/Unscreened> enumeration value.
-+ */
-+static int presentation_from_q931(struct pri *ctrl, int presentation, int number_present)
-+{
-+ int value;
-+
-+ switch (presentation & PRI_PRES_RESTRICTION) {
-+ case PRI_PRES_ALLOWED:
-+ value = 0; /* presentationAllowed<Number/Address> */
-+ break;
-+ default:
-+ pri_message(ctrl, "!! Unsupported Q.931 number presentation value (%d)\n",
-+ presentation);
-+ /* fall through */
-+ case PRI_PRES_RESTRICTED:
-+ if (number_present) {
-+ value = 3; /* presentationRestricted<Number/Address> */
-+ } else {
-+ value = 1; /* presentationRestricted */
-+ }
-+ break;
-+ case PRI_PRES_UNAVAILABLE:
-+ value = 2; /* numberNotAvailableDueToInterworking */
-+ break;
- }
-- PRI_CHECKOVERFLOW(2);
-- *msgptr++ = ']';
-- *msgptr++ = '\n';
-- *msgptr = '\0';
-- pri_message(pri, "%s", message);
-+
-+ return value;
- }
--#undef PRI_CHECKOVERFLOW
-
--int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
-+/*!
-+ * \internal
-+ * \brief Convert the Presented<Number/Address><Screened/Unscreened> presentation
-+ * to Q.931 presentation field value.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Presented<Number/Address><Screened/Unscreened> value.
-+ *
-+ * \return Q.931 presentation field value.
-+ */
-+static int presentation_for_q931(struct pri *ctrl, int presentation)
- {
-- switch(pri->switchtype) {
-- case PRI_SWITCH_QSIG:
-- switch(redirectingreason) {
-- case PRI_REDIR_UNKNOWN:
-- return QSIG_DIVERT_REASON_UNKNOWN;
-- case PRI_REDIR_FORWARD_ON_BUSY:
-- return QSIG_DIVERT_REASON_CFB;
-- case PRI_REDIR_FORWARD_ON_NO_REPLY:
-- return QSIG_DIVERT_REASON_CFNR;
-- case PRI_REDIR_UNCONDITIONAL:
-- return QSIG_DIVERT_REASON_CFU;
-- case PRI_REDIR_DEFLECTION:
-- case PRI_REDIR_DTE_OUT_OF_ORDER:
-- case PRI_REDIR_FORWARDED_BY_DTE:
-- pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n", redirectingreason);
-- /* Fall through */
-- default:
-- return QSIG_DIVERT_REASON_UNKNOWN;
-- }
-- default:
-- switch(redirectingreason) {
-- case PRI_REDIR_UNKNOWN:
-- return Q952_DIVERT_REASON_UNKNOWN;
-- case PRI_REDIR_FORWARD_ON_BUSY:
-- return Q952_DIVERT_REASON_CFB;
-- case PRI_REDIR_FORWARD_ON_NO_REPLY:
-- return Q952_DIVERT_REASON_CFNR;
-- case PRI_REDIR_DEFLECTION:
-- return Q952_DIVERT_REASON_CD;
-- case PRI_REDIR_UNCONDITIONAL:
-- return Q952_DIVERT_REASON_CFU;
-- case PRI_REDIR_DTE_OUT_OF_ORDER:
-- case PRI_REDIR_FORWARDED_BY_DTE:
-- pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.952\n", redirectingreason);
-- /* Fall through */
-- default:
-- return Q952_DIVERT_REASON_UNKNOWN;
-- }
-+ int value;
-+
-+ switch (presentation) {
-+ case 0: /* presentationAllowed<Number/Address> */
-+ value = PRI_PRES_ALLOWED;
-+ break;
-+ default:
-+ pri_message(ctrl,
-+ "!! Unsupported Presented<Number/Address><Screened/Unscreened> to Q.931 value (%d)\n",
-+ presentation);
-+ /* fall through */
-+ case 1: /* presentationRestricted */
-+ case 3: /* presentationRestricted<Number/Address> */
-+ value = PRI_PRES_RESTRICTED;
-+ break;
-+ case 2: /* numberNotAvailableDueToInterworking */
-+ value = PRI_PRES_UNAVAILABLE;
-+ break;
- }
-+
-+ return value;
- }
-
--static int redirectingreason_for_q931(struct pri *pri, int redirectingreason)
-+/*!
-+ * \internal
-+ * \brief Convert the Q.931 number presentation field to Q.SIG name presentation.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Q.931 presentation/screening octet.
-+ * \param name_present Non-zero if the name is available.
-+ *
-+ * \return Name presentation enumeration value.
-+ */
-+static int qsig_name_presentation_from_q931(struct pri *ctrl, int presentation, int name_present)
- {
-- switch(pri->switchtype) {
-- case PRI_SWITCH_QSIG:
-- switch(redirectingreason) {
-- case QSIG_DIVERT_REASON_UNKNOWN:
-- return PRI_REDIR_UNKNOWN;
-- case QSIG_DIVERT_REASON_CFU:
-- return PRI_REDIR_UNCONDITIONAL;
-- case QSIG_DIVERT_REASON_CFB:
-- return PRI_REDIR_FORWARD_ON_BUSY;
-- case QSIG_DIVERT_REASON_CFNR:
-- return PRI_REDIR_FORWARD_ON_NO_REPLY;
-- default:
-- pri_message(pri, "!! Unknown Q.SIG diversion reason %d\n", redirectingreason);
-- return PRI_REDIR_UNKNOWN;
-- }
-- default:
-- switch(redirectingreason) {
-- case Q952_DIVERT_REASON_UNKNOWN:
-- return PRI_REDIR_UNKNOWN;
-- case Q952_DIVERT_REASON_CFU:
-- return PRI_REDIR_UNCONDITIONAL;
-- case Q952_DIVERT_REASON_CFB:
-- return PRI_REDIR_FORWARD_ON_BUSY;
-- case Q952_DIVERT_REASON_CFNR:
-- return PRI_REDIR_FORWARD_ON_NO_REPLY;
-- case Q952_DIVERT_REASON_CD:
-- return PRI_REDIR_DEFLECTION;
-- case Q952_DIVERT_REASON_IMMEDIATE:
-- pri_message(pri, "!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
-- return PRI_REDIR_UNKNOWN; /* ??? */
-- default:
-- pri_message(pri, "!! Unknown Q.952 diversion reason %d\n", redirectingreason);
-- return PRI_REDIR_UNKNOWN;
-- }
-+ int value;
-+
-+ switch (presentation & PRI_PRES_RESTRICTION) {
-+ case PRI_PRES_ALLOWED:
-+ if (name_present) {
-+ value = 1; /* presentation_allowed */
-+ } else {
-+ value = 4; /* name_not_available */
-+ }
-+ break;
-+ default:
-+ pri_message(ctrl, "!! Unsupported Q.931 number presentation value (%d)\n",
-+ presentation);
-+ /* fall through */
-+ case PRI_PRES_RESTRICTED:
-+ if (name_present) {
-+ value = 2; /* presentation_restricted */
-+ } else {
-+ value = 3; /* presentation_restricted_null */
-+ }
-+ break;
-+ case PRI_PRES_UNAVAILABLE:
-+ value = 4; /* name_not_available */
-+ break;
- }
-+
-+ return value;
- }
-
--int typeofnumber_from_q931(struct pri *pri, int ton)
-+/*!
-+ * \internal
-+ * \brief Convert the Q.SIG name presentation to Q.931 presentation field value.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Q.SIG name presentation value.
-+ *
-+ * \return Q.931 presentation field value.
-+ */
-+static int qsig_name_presentation_for_q931(struct pri *ctrl, int presentation)
- {
-- switch(ton) {
-- case PRI_TON_INTERNATIONAL:
-- return Q932_TON_INTERNATIONAL;
-- case PRI_TON_NATIONAL:
-- return Q932_TON_NATIONAL;
-- case PRI_TON_NET_SPECIFIC:
-- return Q932_TON_NET_SPECIFIC;
-- case PRI_TON_SUBSCRIBER:
-- return Q932_TON_SUBSCRIBER;
-- case PRI_TON_ABBREVIATED:
-- return Q932_TON_ABBREVIATED;
-- case PRI_TON_RESERVED:
-- default:
-- pri_message(pri, "!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton);
-- /* fall through */
-- case PRI_TON_UNKNOWN:
-- return Q932_TON_UNKNOWN;
-+ int value;
-+
-+ switch (presentation) {
-+ case 1: /* presentation_allowed */
-+ value = PRI_PRES_ALLOWED;
-+ break;
-+ default:
-+ pri_message(ctrl,
-+ "!! Unsupported Q.SIG name presentation to Q.931 value (%d)\n",
-+ presentation);
-+ /* fall through */
-+ case 2: /* presentation_restricted */
-+ case 3: /* presentation_restricted_null */
-+ value = PRI_PRES_RESTRICTED;
-+ break;
-+ case 0: /* optional_name_not_present */
-+ case 4: /* name_not_available */
-+ value = PRI_PRES_UNAVAILABLE;
-+ break;
- }
-+
-+ return value;
- }
-
--static int typeofnumber_for_q931(struct pri *pri, int ton)
-+/*!
-+ * \internal
-+ * \brief Convert number presentation to Q.SIG diversion subscription notification.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param presentation Number presentation value.
-+ *
-+ * \return Q.SIG diversion subscription notification value.
-+ */
-+static int presentation_to_subscription(struct pri *ctrl, int presentation)
- {
-- switch (ton) {
-- case Q932_TON_UNKNOWN:
-- return PRI_TON_UNKNOWN;
-- case Q932_TON_INTERNATIONAL:
-- return PRI_TON_INTERNATIONAL;
-- case Q932_TON_NATIONAL:
-- return PRI_TON_NATIONAL;
-- case Q932_TON_NET_SPECIFIC:
-- return PRI_TON_NET_SPECIFIC;
-- case Q932_TON_SUBSCRIBER:
-- return PRI_TON_SUBSCRIBER;
-- case Q932_TON_ABBREVIATED:
-- return PRI_TON_ABBREVIATED;
-- default:
-- pri_message(pri, "!! Invalid Q.932 TypeOfNumber %d\n", ton);
-- return PRI_TON_UNKNOWN;
-+ /* derive subscription value from presentation value */
-+
-+ switch (presentation & PRI_PRES_RESTRICTION) {
-+ case PRI_PRES_ALLOWED:
-+ return QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR;
-+ case PRI_PRES_RESTRICTED:
-+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
-+ case PRI_PRES_UNAVAILABLE: /* Number not available due to interworking */
-+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR; /* ?? QSIG_NO_NOTIFICATION */
-+ default:
-+ pri_message(ctrl, "!! Unknown Q.SIG presentationIndicator 0x%02x\n",
-+ presentation);
-+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
- }
- }
-
--int asn1_name_decode(void * data, int len, char *namebuf, int buflen)
-+/*!
-+ * \internal
-+ * \brief Copy the given rose party number to the q931_party_number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_number Q.931 party number structure
-+ * \param rose_number ROSE party number structure
-+ *
-+ * \note It is assumed that the q931_number has been initialized before calling.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_number_to_q931(struct pri *ctrl,
-+ struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number)
- {
-- struct rose_component *comp = (struct rose_component*)data;
-- int datalen = 0, res = 0;
-+ //q931_party_number_init(q931_number);
-+ libpri_copy_string(q931_number->str, (char *) rose_number->str,
-+ sizeof(q931_number->str));
-+ q931_number->plan = numbering_plan_for_q931(ctrl, rose_number->plan)
-+ | typeofnumber_for_q931(ctrl, rose_number->ton);
-+ q931_number->valid = 1;
-+}
-
-- if (comp->len == ASN1_LEN_INDEF) {
-- datalen = strlen((char *)comp->data);
-- res = datalen + 2;
-- } else
-- datalen = res = comp->len;
-+/*!
-+ * \internal
-+ * \brief Copy the given rose subaddress to the q931_party_subaddress.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_subaddress Q.931 party subaddress structure
-+ * \param rose_subaddress ROSE subaddress structure
-+ *
-+ * \note It is assumed that the q931_subaddress has been initialized before calling.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_subaddress_to_q931(struct pri *ctrl,
-+ struct q931_party_subaddress *q931_subaddress,
-+ const struct rosePartySubaddress *rose_subaddress)
-+{
-+ //q931_party_subaddress_init(q931_subaddress);
-+ if (!rose_subaddress->length) {
-+ /* Subaddress is not present. */
-+ return;
-+ }
-
-- if (datalen > buflen) {
-- /* Truncate */
-- datalen = buflen;
-+ switch (rose_subaddress->type) {
-+ case 0:/* UserSpecified */
-+ q931_subaddress->type = 2;/* user_specified */
-+ q931_subaddress->valid = 1;
-+ q931_subaddress->length = rose_subaddress->length;
-+ if (sizeof(q931_subaddress->data) <= q931_subaddress->length) {
-+ q931_subaddress->length = sizeof(q931_subaddress->data) - 1;
-+ }
-+ memcpy(q931_subaddress->data, rose_subaddress->u.user_specified.information,
-+ q931_subaddress->length);
-+ q931_subaddress->data[q931_subaddress->length] = '\0';
-+ if (rose_subaddress->u.user_specified.odd_count_present) {
-+ q931_subaddress->odd_even_indicator =
-+ rose_subaddress->u.user_specified.odd_count;
-+ }
-+ break;
-+ case 1:/* NSAP */
-+ q931_subaddress->type = 0;/* nsap */
-+ q931_subaddress->valid = 1;
-+ libpri_copy_string((char *) q931_subaddress->data,
-+ (char *) rose_subaddress->u.nsap, sizeof(q931_subaddress->data));
-+ q931_subaddress->length = strlen((char *) q931_subaddress->data);
-+ break;
-+ default:
-+ /* Don't know how to encode so assume it is not present. */
-+ break;
- }
-- memcpy(namebuf, comp->data, datalen);
-- return res + 2;
- }
-
--int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len)
-+/*!
-+ * \internal
-+ * \brief Copy the given rose address to the q931_party_id address.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_address Q.931 party id structure to fill address
-+ * \param rose_address ROSE address structure
-+ *
-+ * \note It is assumed that the q931_address has been initialized before calling.
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_address_to_q931(struct pri *ctrl,
-+ struct q931_party_id *q931_address, const struct roseAddress *rose_address)
- {
-- struct rose_component *comp = NULL;
--
-- if (len < 2 + src_len)
-- return -1;
-+ rose_copy_number_to_q931(ctrl, &q931_address->number, &rose_address->number);
-+ rose_copy_subaddress_to_q931(ctrl, &q931_address->subaddress,
-+ &rose_address->subaddress);
-+}
-
-- if (max_len && (src_len > max_len))
-- src_len = max_len;
-+/*!
-+ * \internal
-+ * \brief Copy the given rose presented screened party number to the q931_party_number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_number Q.931 party number structure
-+ * \param rose_presented ROSE presented screened party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_presented_number_screened_to_q931(struct pri *ctrl,
-+ struct q931_party_number *q931_number,
-+ const struct rosePresentedNumberScreened *rose_presented)
-+{
-+ q931_party_number_init(q931_number);
-+ q931_number->valid = 1;
-+ q931_number->presentation = presentation_for_q931(ctrl, rose_presented->presentation);
-+ switch (rose_presented->presentation) {
-+ case 0: /* presentationAllowedNumber */
-+ case 3: /* presentationRestrictedNumber */
-+ q931_number->presentation |=
-+ (rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
-+ rose_copy_number_to_q931(ctrl, q931_number,
-+ &rose_presented->screened.number);
-+ break;
-+ default:
-+ q931_number->presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ }
-+}
-
-- comp = (struct rose_component *)data;
-- comp->type = asn1_type;
-- comp->len = src_len;
-- memcpy(comp->data, src, src_len);
--
-- return 2 + src_len;
-+/*!
-+ * \internal
-+ * \brief Copy the given rose presented unscreened party number to the q931_party_number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_number Q.931 party number structure
-+ * \param rose_presented ROSE presented unscreened party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl,
-+ struct q931_party_number *q931_number,
-+ const struct rosePresentedNumberUnscreened *rose_presented)
-+{
-+ q931_party_number_init(q931_number);
-+ q931_number->valid = 1;
-+ q931_number->presentation = presentation_for_q931(ctrl,
-+ rose_presented->presentation) | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ switch (rose_presented->presentation) {
-+ case 0: /* presentationAllowedNumber */
-+ case 3: /* presentationRestrictedNumber */
-+ rose_copy_number_to_q931(ctrl, q931_number, &rose_presented->number);
-+ break;
-+ default:
-+ break;
-+ }
- }
-
--int asn1_copy_string(char * buf, int buflen, struct rose_component *comp)
-+/*!
-+ * \internal
-+ * \brief Copy the given rose presented screened party address to the q931_party_number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param q931_address Q.931 party id structure to fill the address
-+ * \param rose_presented ROSE presented screened party address structure
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_presented_address_screened_to_q931(struct pri *ctrl,
-+ struct q931_party_id *q931_address,
-+ const struct rosePresentedAddressScreened *rose_presented)
- {
-- int res;
-- int datalen;
-+ q931_party_number_init(&q931_address->number);
-+ q931_party_subaddress_init(&q931_address->subaddress);
-+ q931_address->number.valid = 1;
-+ q931_address->number.presentation = presentation_for_q931(ctrl,
-+ rose_presented->presentation);
-+ switch (rose_presented->presentation) {
-+ case 0: /* presentationAllowedAddress */
-+ case 3: /* presentationRestrictedAddress */
-+ q931_address->number.presentation |=
-+ (rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
-+ rose_copy_number_to_q931(ctrl, &q931_address->number,
-+ &rose_presented->screened.number);
-+ rose_copy_subaddress_to_q931(ctrl, &q931_address->subaddress,
-+ &rose_presented->screened.subaddress);
-+ break;
-+ default:
-+ q931_address->number.presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ }
-+}
-
-- if ((comp->len > buflen) && (comp->len != ASN1_LEN_INDEF))
-- return -1;
-+/*!
-+ * \internal
-+ * \brief Copy the given rose party name to the q931_party_name
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param qsig_name Q.SIG party name structure
-+ * \param rose_name Q.SIG ROSE party name structure
-+ *
-+ * \return Nothing
-+ */
-+static void rose_copy_name_to_q931(struct pri *ctrl,
-+ struct q931_party_name *qsig_name, const struct roseQsigName *rose_name)
-+{
-+ //q931_party_name_init(qsig_name);
-+ qsig_name->valid = 1;
-+ qsig_name->presentation = qsig_name_presentation_for_q931(ctrl,
-+ rose_name->presentation);
-+ qsig_name->char_set = rose_name->char_set;
-+ libpri_copy_string(qsig_name->str, (char *) rose_name->data, sizeof(qsig_name->str));
-+}
-
-- if (comp->len == ASN1_LEN_INDEF) {
-- datalen = strlen((char*)comp->data);
-- res = datalen + 2;
-- } else
-- res = datalen = comp->len;
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_number to the rose party number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_number ROSE party number structure
-+ * \param q931_number Q.931 party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_number_to_rose(struct pri *ctrl,
-+ struct rosePartyNumber *rose_number, const struct q931_party_number *q931_number)
-+{
-+ rose_number->plan = numbering_plan_from_q931(ctrl, q931_number->plan);
-+ rose_number->ton = typeofnumber_from_q931(ctrl, q931_number->plan);
-+ /* Truncate the q931_number->str if necessary. */
-+ libpri_copy_string((char *) rose_number->str, q931_number->str,
-+ sizeof(rose_number->str));
-+ rose_number->length = strlen((char *) rose_number->str);
-+}
-
-- memcpy(buf, comp->data, datalen);
-- buf[datalen] = 0;
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_subaddress to the rose subaddress.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_subaddress ROSE subaddress structure
-+ * \param q931_subaddress Q.931 party subaddress structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_subaddress_to_rose(struct pri *ctrl,
-+ struct rosePartySubaddress *rose_subaddress,
-+ const struct q931_party_subaddress *q931_subaddress)
-+{
-+ if (!q931_subaddress->valid) {
-+ /* Subaddress is not present. */
-+ rose_subaddress->length = 0;
-+ return;
-+ }
-
-- return res;
-+ switch (q931_subaddress->type) {
-+ case 0: /* NSAP */
-+ rose_subaddress->type = 1;/* NSAP */
-+ libpri_copy_string((char *) rose_subaddress->u.nsap,
-+ (char *) q931_subaddress->data, sizeof(rose_subaddress->u.nsap));
-+ rose_subaddress->length = strlen((char *) rose_subaddress->u.nsap);
-+ break;
-+ case 2: /* user_specified */
-+ rose_subaddress->type = 0;/* UserSpecified */
-+ rose_subaddress->length = q931_subaddress->length;
-+ if (sizeof(rose_subaddress->u.user_specified.information)
-+ <= rose_subaddress->length) {
-+ rose_subaddress->length =
-+ sizeof(rose_subaddress->u.user_specified.information) - 1;
-+ } else {
-+ if (q931_subaddress->odd_even_indicator) {
-+ rose_subaddress->u.user_specified.odd_count_present = 1;
-+ rose_subaddress->u.user_specified.odd_count = 1;
-+ }
-+ }
-+ memcpy(rose_subaddress->u.user_specified.information, q931_subaddress->data,
-+ rose_subaddress->length);
-+ rose_subaddress->u.user_specified.information[rose_subaddress->length] = '\0';
-+ break;
-+ default:
-+ /* Don't know how to encode so assume it is not present. */
-+ rose_subaddress->length = 0;
-+ break;
-+ }
- }
-
--static int rose_number_digits_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_id address to the rose address.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_address ROSE address structure
-+ * \param q931_address Q.931 party id structure to give address
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address,
-+ const struct q931_party_id *q931_address)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-- int datalen = 0;
-- int res = 0;
-+ q931_copy_number_to_rose(ctrl, &rose_address->number, &q931_address->number);
-+ q931_copy_subaddress_to_rose(ctrl, &rose_address->subaddress,
-+ &q931_address->subaddress);
-+}
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_NUMERICSTRING, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
-- if(comp->len > 20 && comp->len != ASN1_LEN_INDEF) {
-- pri_message(pri, "!! Oversized NumberDigits component (%d)\n", comp->len);
-- return -1;
-- }
-- if (comp->len == ASN1_LEN_INDEF) {
-- datalen = strlen((char *)comp->data);
-- res = datalen + 2;
-- } else
-- res = datalen = comp->len;
--
-- memcpy(value->partyaddress, comp->data, datalen);
-- value->partyaddress[datalen] = '\0';
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_number to the rose presented screened party number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_presented ROSE presented screened party number structure
-+ * \param q931_number Q.931 party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_presented_number_screened_to_rose(struct pri *ctrl,
-+ struct rosePresentedNumberScreened *rose_presented,
-+ const struct q931_party_number *q931_number)
-+{
-+ if (q931_number->valid) {
-+ rose_presented->presentation =
-+ presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
-+ rose_presented->screened.screening_indicator =
-+ q931_number->presentation & PRI_PRES_NUMBER_TYPE;
-+ q931_copy_number_to_rose(ctrl, &rose_presented->screened.number, q931_number);
-+ } else {
-+ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
-+ }
-+}
-
-- return res + 2;
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_number to the rose presented unscreened party number
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_presented ROSE presented unscreened party number structure
-+ * \param q931_number Q.931 party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl,
-+ struct rosePresentedNumberUnscreened *rose_presented,
-+ const struct q931_party_number *q931_number)
-+{
-+ if (q931_number->valid) {
-+ rose_presented->presentation =
-+ presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
-+ q931_copy_number_to_rose(ctrl, &rose_presented->number, q931_number);
-+ } else {
-+ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
- }
-- while(0);
--
-- return -1;
- }
-
--static int rose_public_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+#if 0 /* In case it is needed in the future */
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_number to the rose presented screened party address
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_presented ROSE presented screened party address structure
-+ * \param q931_address Q.931 party id structure to get the address
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_presented_address_screened_to_rose(struct pri *ctrl,
-+ struct rosePresentedAddressScreened *rose_presented,
-+ const struct q931_party_id *q931_address)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-- int ton;
-- int res = 0;
-+ if (q931_address->number.valid) {
-+ rose_presented->presentation =
-+ presentation_from_q931(ctrl, q931_address->number.presentation,
-+ q931_address->number.str[0]);
-+ rose_presented->screened.screening_indicator =
-+ q931_address->number.presentation & PRI_PRES_NUMBER_TYPE;
-+ q931_copy_number_to_rose(ctrl, &rose_presented->screened.number,
-+ &q931_address->number);
-+ q931_copy_subaddress_to_rose(ctrl, &rose_presented->screened.subaddress,
-+ &q931_address->subaddress);
-+ } else {
-+ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
-+ }
-+}
-+#endif /* In case it is needed in the future */
-
-- if (len < 2)
-- return -1;
-+/*!
-+ * \internal
-+ * \brief Copy the given q931_party_name to the rose party name
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param rose_name Q.SIG ROSE party name structure
-+ * \param qsig_name Q.SIG party name structure
-+ *
-+ * \return Nothing
-+ */
-+static void q931_copy_name_to_rose(struct pri *ctrl,
-+ struct roseQsigName *rose_name, const struct q931_party_name *qsig_name)
-+{
-+ if (qsig_name->valid) {
-+ rose_name->presentation = qsig_name_presentation_from_q931(ctrl,
-+ qsig_name->presentation, qsig_name->str[0]);
-+ rose_name->char_set = qsig_name->char_set;
-+ /* Truncate the qsig_name->str if necessary. */
-+ libpri_copy_string((char *) rose_name->data, qsig_name->str, sizeof(rose_name->data));
-+ rose_name->length = strlen((char *) rose_name->data);
-+ } else {
-+ rose_name->presentation = 4;/* name_not_available */
-+ }
-+}
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
-- ASN1_GET_INTEGER(comp, ton);
-- NEXT_COMPONENT(comp, i);
-- ton = typeofnumber_for_q931(pri, ton);
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG DivertingLegInformation1 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 1.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_diverting_leg_information1(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
-- if (res < 0)
-- return -1;
-- value->ton = ton;
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- return res + 3;
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_DivertingLegInformation1;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.qsig.DivertingLegInformation1.diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.reason);
-
-- } while(0);
-- return -1;
-+ /* subscriptionOption is the redirecting.to.number.presentation */
-+ msg.args.qsig.DivertingLegInformation1.subscription_option =
-+ presentation_to_subscription(ctrl, call->redirecting.to.number.presentation);
-+
-+ /* nominatedNr is the redirecting.to.number */
-+ q931_copy_number_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation1.nominated_number,
-+ &call->redirecting.to.number);
-+
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
-
--static int rose_private_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI DivertingLegInformation1 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 1.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_diverting_leg_information1(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-- int ton;
-- int res = 0;
-+ struct rose_msg_invoke msg;
-
-- if (len < 2)
-- return -1;
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PrivatePartyNumber ROSE component type 0x%x\n");
-- ASN1_GET_INTEGER(comp, ton);
-- NEXT_COMPONENT(comp, i);
-- ton = typeofnumber_for_q931(pri, ton);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_DivertingLegInformation1;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.etsi.DivertingLegInformation1.diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.reason);
-
-- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
-- if (res < 0)
-- return -1;
-- value->ton = ton;
-+ if (call->redirecting.to.number.valid) {
-+ msg.args.etsi.DivertingLegInformation1.subscription_option = 2;
-
-- return res + 3;
-+ /* divertedToNumber is the redirecting.to.number */
-+ msg.args.etsi.DivertingLegInformation1.diverted_to_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.DivertingLegInformation1.diverted_to,
-+ &call->redirecting.to.number);
-+ } else {
-+ msg.args.etsi.DivertingLegInformation1.subscription_option = 1;
-+ }
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- } while(0);
-- return -1;
-+ return pos;
- }
-
--static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \brief Encode and queue the DivertingLegInformation1 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode diversion leg 1.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rose_diverting_leg_information1_encode(struct pri *ctrl, q931_call *call)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-- int res = 0;
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end = enc_etsi_diverting_leg_information1(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end = enc_qsig_diverting_leg_information1(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ default:
-+ return -1;
-+ }
-+ if (!end) {
-+ return -1;
-+ }
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] unknownPartyNumber */
-- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->ton = PRI_TON_UNKNOWN;
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] unknownPartyNumber */
-- res = asn1_copy_string(value->partyaddress, sizeof(value->partyaddress), comp);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->ton = PRI_TON_UNKNOWN;
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber */
-- res = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_E163_E164;
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* [2] nsapEncodedNumber */
-- pri_message(pri, "!! NsapEncodedNumber isn't handled\n");
-- return -1;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] dataPartyNumber */
-- if(rose_number_digits_decode(pri, call, comp->data, comp->len, value))
-- return -1;
-- value->npi = PRI_NPI_X121 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-- pri_message(pri, "!! dataPartyNumber isn't handled\n");
-- return -1;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] telexPartyNumber */
-- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_F69 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-- pri_message(pri, "!! telexPartyNumber isn't handled\n");
-- return -1;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */
-- res = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_PRIVATE;
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */
-- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (res < 0)
-- return -1;
-- value->npi = PRI_NPI_NATIONAL;
-- value->ton = PRI_TON_NATIONAL;
-- break;
-- default:
-- pri_message(pri, "!! Unknown Party number component received 0x%X\n", comp->type);
-- return -1;
-+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG DivertingLegInformation2 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 2.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_diverting_leg_information2(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_DivertingLegInformation2;
-+ msg.invoke_id = get_invokeid(ctrl);
-+
-+ /* diversionCounter is the redirecting.count */
-+ msg.args.qsig.DivertingLegInformation2.diversion_counter = call->redirecting.count;
-+
-+ msg.args.qsig.DivertingLegInformation2.diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.reason);
-+
-+ /* divertingNr is the redirecting.from.number */
-+ msg.args.qsig.DivertingLegInformation2.diverting_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation2.diverting,
-+ &call->redirecting.from.number);
-+
-+ /* redirectingName is the redirecting.from.name */
-+ if (call->redirecting.from.name.valid) {
-+ msg.args.qsig.DivertingLegInformation2.redirecting_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation2.redirecting_name,
-+ &call->redirecting.from.name);
-+ }
-+
-+ if (1 < call->redirecting.count) {
-+ /* originalCalledNr is the redirecting.orig_called.number */
-+ msg.args.qsig.DivertingLegInformation2.original_called_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation2.original_called,
-+ &call->redirecting.orig_called.number);
-+
-+ msg.args.qsig.DivertingLegInformation2.original_diversion_reason_present = 1;
-+ if (call->redirecting.orig_called.number.valid) {
-+ msg.args.qsig.DivertingLegInformation2.original_diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.orig_reason);
-+ } else {
-+ msg.args.qsig.DivertingLegInformation2.original_diversion_reason =
-+ QSIG_DIVERT_REASON_UNKNOWN;
- }
-- ASN1_FIXUP_LEN(comp, res);
-- NEXT_COMPONENT(comp, i);
-- if(i < len)
-- pri_message(pri, "!! not all information is handled from Address component\n");
-- return res + 2;
-+
-+ /* originalCalledName is the redirecting.orig_called.name */
-+ if (call->redirecting.orig_called.name.valid) {
-+ msg.args.qsig.DivertingLegInformation2.original_called_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation2.original_called_name,
-+ &call->redirecting.orig_called.name);
-+ }
- }
-- while (0);
-
-- return -1;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
-
--static int rose_presented_number_unscreened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI DivertingLegInformation2 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 2.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_diverting_leg_information2(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
- {
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ struct rose_msg_invoke msg;
-
-- /* Fill in default values */
-- value->ton = PRI_TON_UNKNOWN;
-- value->npi = PRI_NPI_E163_E164;
-- value->pres = -1; /* Data is not available */
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_DivertingLegInformation2;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] presentationAllowedNumber */
-- value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-- size = rose_address_decode(pri, call, comp->data, comp->len, value);
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
-- return -1;
-- }
-- value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-- return 2;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
-- return -1;
-- }
-- value->pres = PRES_NUMBER_NOT_AVAILABLE;
-- return 2;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] presentationRestrictedNumber */
-- value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-- size = rose_address_decode(pri, call, comp->data, comp->len, value) + 2;
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
-- default:
-- pri_message(pri, "Invalid PresentedNumberUnscreened component 0x%X\n", comp->type);
-- }
-- return -1;
-+ /* diversionCounter is the redirecting.count */
-+ msg.args.etsi.DivertingLegInformation2.diversion_counter = call->redirecting.count;
-+
-+ msg.args.etsi.DivertingLegInformation2.diversion_reason =
-+ redirectingreason_from_q931(ctrl, call->redirecting.reason);
-+
-+ /* divertingNr is the redirecting.from.number */
-+ msg.args.etsi.DivertingLegInformation2.diverting_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.DivertingLegInformation2.diverting,
-+ &call->redirecting.from.number);
-+
-+ if (1 < call->redirecting.count) {
-+ /* originalCalledNr is the redirecting.orig_called.number */
-+ msg.args.etsi.DivertingLegInformation2.original_called_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.DivertingLegInformation2.original_called,
-+ &call->redirecting.orig_called.number);
- }
-- while (0);
-
-- return -1;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
-
--static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+/*!
-+ * \internal
-+ * \brief Encode and queue the DivertingLegInformation2 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode diversion leg 2.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_diverting_leg_information2_encode(struct pri *ctrl, q931_call *call)
- {
-- int i = 0;
-- int diversion_counter;
-- int diversion_reason;
-- char origcalledname[50] = "", redirectingname[50] = "";
-- struct addressingdataelements_presentednumberunscreened divertingnr;
-- struct addressingdataelements_presentednumberunscreened originalcallednr;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = sequence->data;
-- int res = 0;
-- memset(&divertingnr, 0, sizeof(divertingnr));
-- memset(&originalcallednr, 0, sizeof(originalcallednr));
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-- /* Data checks */
-- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-- pri_message(pri, "Invalid DivertingLegInformation2Type argument\n");
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end = enc_etsi_diverting_leg_information2(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end = enc_qsig_diverting_leg_information2(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ default:
- return -1;
- }
-+ if (!end) {
-+ return -1;
-+ }
-
-- if (sequence->len == ASN1_LEN_INDEF) {
-- len -= 4; /* For the 2 extra characters at the end
-- * and two characters of header */
-- } else
-- len -= 2;
-+ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
-+}
-
-- do {
-- /* diversionCounter stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do it diversionCounter is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, diversion_counter);
-- NEXT_COMPONENT(comp, i);
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG DivertingLegInformation3 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 3.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_diverting_leg_information3(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- /* diversionReason stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid diversionReason type 0x%X of ROSE divertingLegInformation2 component received\n");
-- ASN1_GET_INTEGER(comp, diversion_reason);
-- NEXT_COMPONENT(comp, i);
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- diversion_reason = redirectingreason_for_q931(pri, diversion_reason);
--
-- if(pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Redirection reason: %d, total diversions: %d\n", diversion_reason, diversion_counter);
-- pri_message(NULL, "Length of message is %d\n", len);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_DivertingLegInformation3;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- for(; i < len; NEXT_COMPONENT(comp, i)) {
-- GET_COMPONENT(comp, i, vdata, len);
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0):
-- call->origredirectingreason = redirectingreason_for_q931(pri, comp->data[0]);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received reason for original redirection %d\n", call->origredirectingreason);
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1):
-- res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingnr);
-- /* TODO: Fix indefinite length form hacks */
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- if (res < 0)
-- return -1;
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, " Received divertingNr '%s'\n", divertingnr.partyaddress);
-- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi);
-- }
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2):
-- res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalcallednr);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, " Received originalcallednr '%s'\n", originalcallednr.partyaddress);
-- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", originalcallednr.ton, originalcallednr.pres, originalcallednr.npi);
-- }
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3):
-- res = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname));
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received RedirectingName '%s'\n", redirectingname);
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4):
-- res = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname));
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname);
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5):
-- pri_message(pri, "!! Ignoring DivertingLegInformation2 component 0x%X\n", comp->type);
-- break;
-- default:
-- if (comp->type == 0 && comp->len == 0) {
-- break; /* Found termination characters */
-- }
-- pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type);
-- return -1;
-- }
-- }
-+ /* redirecting.to.number.presentation also indicates if name presentation is allowed */
-+ if ((call->redirecting.to.number.presentation & PRI_PRES_RESTRICTION) == PRI_PRES_ALLOWED) {
-+ msg.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1; /* TRUE */
-
-- if (divertingnr.pres >= 0) {
-- call->redirectingplan = divertingnr.npi;
-- call->redirectingpres = divertingnr.pres;
-- call->redirectingreason = diversion_reason;
-- libpri_copy_string(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum));
-- pri_message(pri, " Received redirectingnum '%s' (%d)\n", call->redirectingnum, (int)call->redirectingnum[0]);
-+ /* redirectionName is the redirecting.to.name */
-+ if (call->redirecting.to.name.valid) {
-+ msg.args.qsig.DivertingLegInformation3.redirection_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.DivertingLegInformation3.redirection_name,
-+ &call->redirecting.to.name);
- }
-- if (originalcallednr.pres >= 0) {
-- call->origcalledplan = originalcallednr.npi;
-- call->origcalledpres = originalcallednr.pres;
-- libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum));
-- pri_message(pri, " Received origcallednum '%s' (%d)\n", call->origcallednum, (int)call->origcallednum[0]);
-- }
-- libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname));
-- libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname));
-- return 0;
- }
-- while (0);
-
-- return -1;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
--
--static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call)
-+
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI DivertingLegInformation3 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode diversion leg 3.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_diverting_leg_information3(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call)
- {
-- int i = 0, j, compsp = 0;
-- struct rose_component *comp, *compstk[10];
-- unsigned char buffer[256];
-- int len = 253;
--
--#if 0 /* This is not required by specifications */
-- if (!strlen(call->callername)) {
-- return -1;
-+ struct rose_msg_invoke msg;
-+
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
- }
--#endif
-
-- buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- i++;
-- /* Interpretation component */
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0x00 /* Discard unrecognized invokes */);
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
--
-- ASN1_PUSH(compstk, compsp, comp);
-- /* Invoke component contents */
-- /* Invoke ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-- /* Operation Tag */
--
-- /* ROSE operationId component */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION2);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_DivertingLegInformation3;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- /* ROSE ARGUMENT component */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* ROSE DivertingLegInformation2.diversionCounter component */
-- /* Always is 1 because other isn't available in the current design */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1);
--
-- /* ROSE DivertingLegInformation2.diversionReason component */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, redirectingreason_from_q931(pri, call->redirectingreason));
--
-- /* ROSE DivertingLegInformation2.divertingNr component */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
--
-- ASN1_PUSH(compstk, compsp, comp);
-- /* Redirecting information always not screened */
--
-- switch(call->redirectingpres) {
-- case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-- case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-- if (call->redirectingnum && strlen(call->redirectingnum)) {
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* NPI of redirected number is not supported in the current design */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
-- if (j < 0)
-- return -1;
--
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- break;
-- }
-- /* fall through */
-- case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- /* Don't know how to handle this */
-- case PRES_ALLOWED_NETWORK_NUMBER:
-- case PRES_PROHIB_NETWORK_NUMBER:
-- case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- default:
-- pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
-- case PRES_NUMBER_NOT_AVAILABLE:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
-- break;
-+ if ((call->redirecting.to.number.presentation & PRI_PRES_RESTRICTION) == PRI_PRES_ALLOWED) {
-+ msg.args.etsi.DivertingLegInformation3.presentation_allowed_indicator = 1; /* TRUE */
- }
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-
-- /* ROSE DivertingLegInformation2.originalCalledNr component */
-- /* This information isn't supported by current design - duplicate divertingNr */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* Redirecting information always not screened */
-- switch(call->redirectingpres) {
-- case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-- case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-- if (call->redirectingnum && strlen(call->redirectingnum)) {
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
--
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
-- if (j < 0)
-- return -1;
--
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- break;
-- }
-- /* fall through */
-- case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- /* Don't know how to handle this */
-- case PRES_ALLOWED_NETWORK_NUMBER:
-- case PRES_PROHIB_NETWORK_NUMBER:
-- case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- default:
-- pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
-- case PRES_NUMBER_NOT_AVAILABLE:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
-- break;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode and queue the DivertingLegInformation3 invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode diversion leg 3.
-+ * \param messagetype Q.931 message type to add facility ie to.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rose_diverting_leg_information3_encode(struct pri *ctrl, q931_call *call,
-+ int messagetype)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end = enc_etsi_diverting_leg_information3(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end = enc_qsig_diverting_leg_information3(ctrl, buffer, buffer + sizeof(buffer),
-+ call);
-+ break;
-+ default:
-+ return -1;
- }
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- /* Fix length of stacked components */
-- while(compsp > 0) {
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ if (!end) {
-+ return -1;
- }
--
-- if (pri_call_apdu_queue(call, Q931_SETUP, buffer, i, NULL, NULL))
-- return -1;
--
-- return 0;
-+
-+ return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL);
- }
-
--/* Send the rltThirdParty: Invoke */
--int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
-+/*!
-+ * \internal
-+ * \brief Encode the rltThirdParty invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param callwithid Call-ID information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_dms100_rlt_initiate_transfer(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const q931_call *callwithid)
- {
-- int i = 0;
-+ struct rose_msg_invoke msg;
-+
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_DMS100_RLT_ThirdParty;
-+ msg.invoke_id = ROSE_DMS100_RLT_THIRD_PARTY;
-+ msg.args.dms100.RLT_ThirdParty.call_id = callwithid->rlt_call_id & 0xFFFFFF;
-+ msg.args.dms100.RLT_ThirdParty.reason = 0; /* unused, set to 129 */
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Send the rltThirdParty: Invoke.
-+ *
-+ * \note For PRI_SWITCH_DMS100 only.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param c1 Q.931 call leg 1
-+ * \param c2 Q.931 call leg 2
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rlt_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
-+{
- unsigned char buffer[256];
-- struct rose_component *comp = NULL, *compstk[10];
-- const unsigned char rlt_3rd_pty = RLT_THIRD_PARTY;
-- q931_call *callwithid = NULL, *apdubearer = NULL;
-- int compsp = 0;
-+ unsigned char *end;
-+ q931_call *apdubearer;
-+ q931_call *callwithid;
-
- if (c2->transferable) {
- apdubearer = c1;
-@@ -906,279 +1374,415 @@
- } else if (c1->transferable) {
- apdubearer = c2;
- callwithid = c1;
-- } else
-+ } else {
- return -1;
-+ }
-
-- buffer[i++] = (Q932_PROTOCOL_ROSE);
-- buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
-+ end =
-+ enc_dms100_rlt_initiate_transfer(ctrl, buffer, buffer + sizeof(buffer),
-+ callwithid);
-+ if (!end) {
-+ return -1;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- /* Invoke ID is set to the operation ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
--
-- /* Operation Tag */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
--
-- /* Additional RLT invoke info - Octet 12 */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- ASN1_ADD_WORDCOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, callwithid->rlt_call_id & 0xFFFFFF); /* Length is 3 octets */
-- /* Reason for redirect - unused, set to 129 */
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, i, NULL, NULL))
-+ if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, end - buffer, NULL)) {
- return -1;
-+ }
-
- if (q931_facility(apdubearer->pri, apdubearer)) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", apdubearer->cr);
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n",
-+ apdubearer->cr);
- return -1;
- }
- return 0;
- }
-
--static int add_dms100_transfer_ability_apdu(struct pri *pri, q931_call *c)
-+/*!
-+ * \internal
-+ * \brief Encode the rltOperationInd invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_dms100_rlt_transfer_ability(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end)
- {
-- int i = 0;
-- unsigned char buffer[256];
-- struct rose_component *comp = NULL, *compstk[10];
-- const unsigned char rlt_op_ind = RLT_OPERATION_IND;
-- int compsp = 0;
-+ struct rose_msg_invoke msg;
-
-- buffer[i++] = (Q932_PROTOCOL_ROSE); /* Note to self: DON'T set the EXT bit */
-- buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_DMS100_RLT_OperationInd;
-+ msg.invoke_id = ROSE_DMS100_RLT_OPERATION_IND;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- /* Invoke ID is set to the operation ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
--
-- /* Operation Tag - basically the same as the invoke ID tag */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
-- return -1;
-- else
-- return 0;
-+ return pos;
- }
-
--/* Sending callername information functions */
--static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
-+/*!
-+ * \internal
-+ * \brief Send the rltOperationInd: Invoke.
-+ *
-+ * \note For PRI_SWITCH_DMS100 only.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Q.931 call leg
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int add_dms100_transfer_ability_apdu(struct pri *ctrl, q931_call *call)
- {
-- int res = 0;
-- int i = 0;
- unsigned char buffer[256];
-- unsigned char namelen = 0;
-- struct rose_component *comp = NULL, *compstk[10];
-- int compsp = 0;
-- int mymessage = 0;
-- static unsigned char op_tag[] = {
-- 0x2a, /* informationFollowing 42 */
-- 0x86,
-- 0x48,
-- 0xce,
-- 0x15,
-- 0x00,
-- 0x04
-- };
--
-- if (!strlen(c->callername)) {
-+ unsigned char *end;
-+
-+ end = enc_dms100_rlt_transfer_ability(ctrl, buffer, buffer + sizeof(buffer));
-+ if (!end) {
- return -1;
- }
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- /* Interpretation component */
-+ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
-+}
-
-- if (pri->switchtype == PRI_SWITCH_QSIG) {
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+/*!
-+ * \internal
-+ * \brief Encode the NI2 InformationFollowing invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_ni2_information_following(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+
-+ memset(&header, 0, sizeof(header));
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
- }
-
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_NI2_InformationFollowing;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.ni2.InformationFollowing.value = 0;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* Invoke ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ return pos;
-+}
-
-- /* Operation Tag */
-- res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-- return -1;
-- i += res;
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG CallingName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param name Name data which to encode name.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_calling_name(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct q931_party_name *name)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- if (!cpe) {
-- if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
-- return -1;
-+ memset(&header, 0, sizeof(header));
-+ if (ctrl->switchtype == PRI_SWITCH_QSIG) {
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
- }
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CallingName;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- /* Now the APDU that contains the information that needs sent.
-- * We can reuse the buffer since the queue function doesn't
-- * need it. */
-+ /* CallingName */
-+ q931_copy_name_to_rose(ctrl, &msg.args.qsig.CallingName.name, name);
-
-- i = 0;
-- namelen = strlen(c->callername);
-- if (namelen > 50) {
-- namelen = 50; /* truncate the name */
-- }
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- /* Interpretation component */
-+ return pos;
-+}
-
-- if (pri->switchtype == PRI_SWITCH_QSIG) {
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+/*!
-+ * \internal
-+ * \brief Send caller name information.
-+ *
-+ * \note For PRI_SWITCH_NI2 and PRI_SWITCH_QSIG.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode name.
-+ * \param cpe TRUE if we are the CPE side.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int add_callername_facility_ies(struct pri *ctrl, q931_call *call, int cpe)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+ int mymessage;
-+
-+ if (!call->local_id.name.valid) {
-+ return 0;
- }
-
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
-+ if (ctrl->switchtype == PRI_SWITCH_NI2 && !cpe) {
-+ end = enc_ni2_information_following(ctrl, buffer, buffer + sizeof(buffer));
-+ if (!end) {
-+ return -1;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ if (pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL)) {
-+ return -1;
-+ }
-
-- /* Invoke ID */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ /*
-+ * We can reuse the buffer since the queue function doesn't
-+ * need it.
-+ */
-+ }
-
-- /* Operation ID: Calling name */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, SS_CNID_CALLINGNAME);
--
-- res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, 50, c->callername, namelen);
-- if (res < 0)
-+ /* CallingName is the local_id.name */
-+ end = enc_qsig_calling_name(ctrl, buffer, buffer + sizeof(buffer),
-+ &call->local_id.name);
-+ if (!end) {
- return -1;
-- i += res;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ }
-
-- if (cpe)
-+ if (cpe) {
- mymessage = Q931_SETUP;
-- else
-+ } else {
- mymessage = Q931_FACILITY;
-+ }
-
-- if (pri_call_apdu_queue(c, mymessage, buffer, i, NULL, NULL))
-- return -1;
--
-- return 0;
-+ return pri_call_apdu_queue(call, mymessage, buffer, end - buffer, NULL);
- }
- /* End Callername */
-
- /* MWI related encode and decode functions */
--static void mwi_activate_encode_cb(void *data)
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG MWIActivate invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param req Served user setup request information.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_mwi_activate_message(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, struct pri_sr *req)
- {
-- return;
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_MWIActivate;
-+ msg.invoke_id = get_invokeid(ctrl);
-+
-+ /* The called.number is the served user */
-+ q931_copy_number_to_rose(ctrl, &msg.args.qsig.MWIActivate.served_user_number,
-+ &req->called.number);
-+ /*
-+ * For now, we will just force the numbering plan to unknown to preserve
-+ * the original behaviour.
-+ */
-+ msg.args.qsig.MWIActivate.served_user_number.plan = 0; /* unknown */
-+
-+ msg.args.qsig.MWIActivate.basic_service = 1; /* speech */
-+
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
-
--int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int activate)
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG MWIDeactivate invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param req Served user setup request information.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_mwi_deactivate_message(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, struct pri_sr *req)
- {
-- int i = 0;
-- unsigned char buffer[255] = "";
-- int destlen = strlen(req->called);
-- struct rose_component *comp = NULL, *compstk[10];
-- int compsp = 0;
-- int res;
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- if (destlen <= 0) {
-- return -1;
-- } else if (destlen > 20)
-- destlen = 20; /* Destination number cannot be greater then 20 digits */
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- /* Interpretation component */
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_MWIDeactivate;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ /* The called.number is the served user */
-+ q931_copy_number_to_rose(ctrl, &msg.args.qsig.MWIDeactivate.served_user_number,
-+ &req->called.number);
-+ /*
-+ * For now, we will just force the numbering plan to unknown to preserve
-+ * the original behaviour.
-+ */
-+ msg.args.qsig.MWIDeactivate.served_user_number.plan = 0; /* unknown */
-
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
-+ msg.args.qsig.MWIDeactivate.basic_service = 1; /* speech */
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ return pos;
-+}
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, (activate) ? SS_MWI_ACTIVATE : SS_MWI_DEACTIVATE);
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* PartyNumber */
-- res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, destlen, req->called, destlen);
--
-- if (res < 0)
-+/*!
-+ * \brief Encode and queue the Q.SIG MWIActivate/MWIDeactivate invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg to queue message.
-+ * \param req Served user setup request information.
-+ * \param activate Nonzero to do the activate message.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int mwi_message_send(struct pri *ctrl, q931_call *call, struct pri_sr *req, int activate)
-+{
-+ unsigned char buffer[255];
-+ unsigned char *end;
-+
-+ if (!req->called.number.valid || !req->called.number.str[0]) {
- return -1;
-- i += res;
-+ }
-
-- /* Enumeration: basicService */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1 /* contents: Voice */);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ if (activate) {
-+ end = enc_qsig_mwi_activate_message(ctrl, buffer, buffer + sizeof(buffer), req);
-+ } else {
-+ end =
-+ enc_qsig_mwi_deactivate_message(ctrl, buffer, buffer + sizeof(buffer), req);
-+ }
-+ if (!end) {
-+ return -1;
-+ }
-
-- return pri_call_apdu_queue(call, Q931_SETUP, buffer, i, mwi_activate_encode_cb, NULL);
-+ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
- }
- /* End MWI */
-
- /* EECT functions */
--int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
-+/*!
-+ * \internal
-+ * \brief Encode the NI2 InitiateTransfer invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode transfer information.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_ni2_initiate_transfer(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call)
- {
-- int i = 0;
-- int res = 0;
-- unsigned char buffer[255] = "";
-- short call_reference = c2->cr ^ 0x8000; /* Let's do the trickery to make sure the flag is correct */
-- struct rose_component *comp = NULL, *compstk[10];
-- int compsp = 0;
-- static unsigned char op_tag[] = {
-- 0x2A,
-- 0x86,
-- 0x48,
-- 0xCE,
-- 0x15,
-- 0x00,
-- 0x08,
-- };
-+ struct rose_msg_invoke msg;
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_NI2_InitiateTransfer;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ /* Let's do the trickery to make sure the flag is correct */
-+ msg.args.ni2.InitiateTransfer.call_reference = call->cr ^ 0x8000;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ return pos;
-+}
-
-- res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-+/*!
-+ * \brief Start a 2BCT
-+ *
-+ * \note Called for PRI_SWITCH_NI2, PRI_SWITCH_LUCENT5E, and PRI_SWITCH_ATT4ESS
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param c1 Q.931 call leg 1
-+ * \param c2 Q.931 call leg 2
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int eect_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
-+{
-+ unsigned char buffer[255];
-+ unsigned char *end;
-+
-+ end = enc_ni2_initiate_transfer(ctrl, buffer, buffer + sizeof(buffer), c2);
-+ if (!end) {
- return -1;
-- i += res;
-+ }
-
-- ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
-- if (res) {
-- pri_message(pri, "Could not queue APDU in facility message\n");
-+ if (pri_call_apdu_queue(c1, Q931_FACILITY, buffer, end - buffer, NULL)) {
-+ pri_message(ctrl, "Could not queue APDU in facility message\n");
- return -1;
- }
-
- /* Remember that if we queue a facility IE for a facility message we
- * have to explicitly send the facility message ourselves */
-
-- res = q931_facility(c1->pri, c1);
-- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
-+ if (q931_facility(c1->pri, c1)) {
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n", c1->cr);
- return -1;
- }
-
-@@ -1187,1494 +1791,2316 @@
- /* End EECT */
-
- /* QSIG CF CallRerouting */
--int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason)
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG CallRerouting invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Q.931 call leg.
-+ * \param calling Call rerouting/deflecting updated caller data.
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_call_rerouting(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, const struct q931_party_id *calling,
-+ const struct q931_party_redirecting *deflection, int subscription_option)
- {
--/*CallRerouting ::= OPERATION
-- -- Sent from the Served User PINX to the Rerouting PINX
-- ARGUMENT SEQUENCE
-- { reroutingReason DiversionReason,
-- originalReroutingReason [0] IMPLICIT DiversionReason OPTIONAL,
-- calledAddress Address,
-- diversionCounter INTEGER (1..15),
-- pSS1InfoElement PSS1InformationElement,
-- -- The basic call information elements Bearer capability, High layer compatibility, Low
-- -- layer compatibity, Progress indicator and Party category can be embedded in the
-- -- pSS1InfoElement in accordance with 6.5.3.1.5
-- lastReroutingNr [1] PresentedNumberUnscreened,
-- subscriptionOption [2] IMPLICIT SubscriptionOption,
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+ unsigned char *q931ie_pos;
-
-- callingPartySubaddress [3] PartySubaddress OPTIONAL,
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 2; /* rejectAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- callingNumber [4] PresentedNumberScreened,
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CallRerouting;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- callingName [5] Name OPTIONAL,
-- originalCalledNr [6] PresentedNumberUnscreened OPTIONAL,
-- redirectingName [7] Name OPTIONAL,
-- originalCalledName [8] Name OPTIONAL,
-- extension CHOICE {
-- [9] IMPLICIT Extension ,
-- [10] IMPLICIT SEQUENCE OF Extension } OPTIONAL }
--*/
-+ msg.args.qsig.CallRerouting.rerouting_reason =
-+ redirectingreason_from_q931(ctrl, deflection->reason);
-
-- int i = 0, j;
-- int res = 0;
-- unsigned char buffer[255] = "";
-- int len = 253;
-- struct rose_component *comp = NULL, *compstk[10];
-- int compsp = 0;
-- static unsigned char op_tag[] = {
-- 0x13,
-- };
-+ /* calledAddress is the passed in deflection->to address */
-+ q931_copy_address_to_rose(ctrl, &msg.args.qsig.CallRerouting.called, &deflection->to);
-
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- /* Interpretation component */
-+ msg.args.qsig.CallRerouting.diversion_counter = deflection->count;
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ /* pSS1InfoElement */
-+ q931ie_pos = msg.args.qsig.CallRerouting.q931ie_contents;
-+ *q931ie_pos++ = 0x04; /* Bearer Capability IE */
-+ *q931ie_pos++ = 0x03; /* len */
-+ *q931ie_pos++ = 0x80 | call->transcapability; /* Rxed transfer capability. */
-+ *q931ie_pos++ = 0x90; /* circuit mode, 64kbit/s */
-+ *q931ie_pos++ = 0xa3; /* level1 protocol, a-law */
-+ *q931ie_pos++ = 0x95; /* locking shift to codeset 5 (national use) */
-+ *q931ie_pos++ = 0x32; /* Unknown ie */
-+ *q931ie_pos++ = 0x01; /* Unknown ie len */
-+ *q931ie_pos++ = 0x81; /* Unknown ie body */
-+ msg.args.qsig.CallRerouting.q931ie.length = q931ie_pos
-+ - msg.args.qsig.CallRerouting.q931ie_contents;
-
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 2); /* reject - to get feedback from QSIG switch */
-+ /* lastReroutingNr is the passed in deflection->from.number */
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.qsig.CallRerouting.last_rerouting, &deflection->from.number);
-
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ msg.args.qsig.CallRerouting.subscription_option = subscription_option;
-
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+ /* callingNumber is the passed in calling->number */
-+ q931_copy_presented_number_screened_to_rose(ctrl,
-+ &msg.args.qsig.CallRerouting.calling, &calling->number);
-
-- res = asn1_string_encode(ASN1_INTEGER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-- return -1;
-- i += res;
-+ /* callingPartySubaddress is the passed in calling->subaddress if valid */
-+ q931_copy_subaddress_to_rose(ctrl, &msg.args.qsig.CallRerouting.calling_subaddress,
-+ &calling->subaddress);
-
-- /* call rerouting argument */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ /* callingName is the passed in calling->name if valid */
-+ if (calling->name.valid) {
-+ msg.args.qsig.CallRerouting.calling_name_present = 1;
-+ q931_copy_name_to_rose(ctrl, &msg.args.qsig.CallRerouting.calling_name,
-+ &calling->name);
-+ }
-
-- /* reroutingReason DiversionReason */
-+ if (1 < deflection->count) {
-+ /* originalCalledNr is the deflection->orig_called.number */
-+ msg.args.qsig.CallRerouting.original_called_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.qsig.CallRerouting.original_called,
-+ &deflection->orig_called.number);
-
-- if (reason) {
-- if (!strcasecmp(reason, "cfu"))
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1); /* cfu */
-- else if (!strcasecmp(reason, "cfb"))
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 2); /* cfb */
-- else if (!strcasecmp(reason, "cfnr"))
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 3); /* cfnr */
-- } else {
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0); /* unknown */
-+ msg.args.qsig.CallRerouting.original_rerouting_reason_present = 1;
-+ if (deflection->orig_called.number.valid) {
-+ msg.args.qsig.CallRerouting.original_rerouting_reason =
-+ redirectingreason_from_q931(ctrl, deflection->orig_reason);
-+ } else {
-+ msg.args.qsig.CallRerouting.original_rerouting_reason =
-+ QSIG_DIVERT_REASON_UNKNOWN;
-+ }
-+
-+ /* originalCalledName is the deflection->orig_called.name */
-+ if (deflection->orig_called.name.valid) {
-+ msg.args.qsig.CallRerouting.original_called_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.CallRerouting.original_called_name,
-+ &deflection->orig_called.name);
-+ }
- }
-
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- /* calledAddress Address */
-- /* explicit sequence tag for Address */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* implicit choice public party number tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* type of public party number = unknown */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
-- /* NumberDigits of public party number */
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, (char*)dest, strlen(dest));
-- if (j < 0)
-- return -1;
-+ return pos;
-+}
-
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI CallRerouting invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Q.931 call leg.
-+ * \param calling Call rerouting/deflecting updated caller data.
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_call_rerouting(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, const struct q931_party_id *calling,
-+ const struct q931_party_redirecting *deflection, int subscription_option)
-+{
-+ struct rose_msg_invoke msg;
-+ unsigned char *q931ie_pos;
-
-- /* diversionCounter INTEGER (1..15) */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- /* pSS1InfoElement */
-- ASN1_ADD_SIMPLE(comp, (ASN1_APPLICATION | ASN1_TAG_0 ), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- buffer[i++] = (0x04); /* Bearer Capability IE */
-- buffer[i++] = (0x03); /* len */
-- buffer[i++] = (0x80); /* ETSI Standard, Speech */
-- buffer[i++] = (0x90); /* circuit mode, 64kbit/s */
-- buffer[i++] = (0xa3); /* level1 protocol, a-law */
-- buffer[i++] = (0x95); /* locking shift to codeset 5 (national use) */
-- buffer[i++] = (0x32); /* Unknown ie */
-- buffer[i++] = (0x01); /* Unknown ie len */
-- buffer[i++] = (0x81); /* Unknown ie body */
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_CallRerouting;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- /* lastReroutingNr [1]*/
-- /* implicit optional lastReroutingNr tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ msg.args.etsi.CallRerouting.rerouting_reason =
-+ redirectingreason_from_q931(ctrl, deflection->reason);
-
-- /* implicit choice presented number unscreened tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ /* calledAddress is the passed in deflection->to address */
-+ q931_copy_address_to_rose(ctrl, &msg.args.etsi.CallRerouting.called_address,
-+ &deflection->to);
-
-- /* implicit choice public party number tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* type of public party number = unknown */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, original?(char*)original:c->callednum, original?strlen(original):strlen(c->callednum));
-- if (j < 0)
-- return -1;
-+ msg.args.etsi.CallRerouting.rerouting_counter = deflection->count;
-
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ /* q931InfoElement */
-+ q931ie_pos = msg.args.etsi.CallRerouting.q931ie_contents;
-+ *q931ie_pos++ = 0x04; /* Bearer Capability IE */
-+ *q931ie_pos++ = 0x03; /* len */
-+ *q931ie_pos++ = 0x80 | call->transcapability; /* Rxed transfer capability. */
-+ *q931ie_pos++ = 0x90; /* circuit mode, 64kbit/s */
-+ *q931ie_pos++ = 0xa3; /* level1 protocol, a-law */
-+ msg.args.etsi.CallRerouting.q931ie.length = q931ie_pos
-+ - msg.args.etsi.CallRerouting.q931ie_contents;
-
-- /* subscriptionOption [2]*/
-- /* implicit optional lastReroutingNr tag */
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* noNotification */
-+ /* lastReroutingNr is the passed in deflection->from.number */
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.CallRerouting.last_rerouting, &deflection->from.number);
-
-- /* callingNumber [4]*/
-- /* implicit optional callingNumber tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ msg.args.etsi.CallRerouting.subscription_option = subscription_option;
-
-- /* implicit choice presented number screened tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ /* callingPartySubaddress is the passed in calling->subaddress if valid */
-+ q931_copy_subaddress_to_rose(ctrl, &msg.args.etsi.CallRerouting.calling_subaddress,
-+ &calling->subaddress);
-
-- /* implicit choice presentationAllowedAddress tag */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* type of public party number = subscriber number */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 4);
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, c->callernum, strlen(c->callernum));
-- if (j < 0)
-- return -1;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ return pos;
-+}
-
-- /* Screeening Indicator network provided */
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 3);
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI CallDeflection invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Q.931 call leg.
-+ * \param deflection Call deflection address.
-+ *
-+ * \note
-+ * deflection is the new called number and must always be present.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_call_deflection(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, const struct q931_party_id *deflection)
-+{
-+ struct rose_msg_invoke msg;
-
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- /**/
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_CallDeflection;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ /* deflectionAddress is the passed in deflection->to address */
-+ q931_copy_address_to_rose(ctrl, &msg.args.etsi.CallDeflection.deflection,
-+ deflection);
-
-- res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
-- if (res) {
-- pri_message(pri, "Could not queue ADPU in facility message\n");
-+ msg.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present = 1;
-+ switch (deflection->number.presentation & PRI_PRES_RESTRICTION) {
-+ case PRI_PRES_ALLOWED:
-+ msg.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user = 1;
-+ break;
-+ default:
-+ case PRI_PRES_UNAVAILABLE:
-+ case PRI_PRES_RESTRICTED:
-+ break;
-+ }
-+
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode and queue the CallRerouting/CallDeflection message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_reroute_request_encode(struct pri *ctrl, q931_call *call,
-+ const struct q931_party_id *caller, const struct q931_party_redirecting *deflection,
-+ int subscription_option)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+
-+ if (!caller) {
-+ /*
-+ * We are deflecting an incoming call back to the network.
-+ * Therefore, the Caller-ID is the remote party.
-+ */
-+ caller = &call->remote_id;
-+ }
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (q931_is_ptmp(ctrl)) {
-+ end =
-+ enc_etsi_call_deflection(ctrl, buffer, buffer + sizeof(buffer), call,
-+ &deflection->to);
-+ } else {
-+ end =
-+ enc_etsi_call_rerouting(ctrl, buffer, buffer + sizeof(buffer), call,
-+ caller, deflection, subscription_option);
-+ }
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end =
-+ enc_qsig_call_rerouting(ctrl, buffer, buffer + sizeof(buffer), call, caller,
-+ deflection, subscription_option);
-+ break;
-+ default:
- return -1;
- }
-+ if (!end) {
-+ return -1;
-+ }
-
-- /* Remember that if we queue a facility IE for a facility message we
-- * have to explicitly send the facility message ourselves */
-+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
-+}
-
-- res = q931_facility(c->pri, c);
-- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c->cr);
-+/*!
-+ * \brief Send the CallRerouting/CallDeflection message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int send_reroute_request(struct pri *ctrl, q931_call *call,
-+ const struct q931_party_id *caller, const struct q931_party_redirecting *deflection,
-+ int subscription_option)
-+{
-+ if (!deflection->to.number.str[0]) {
-+ /* Must have a deflect to number. That is the point of deflection. */
- return -1;
- }
-+ if (rose_reroute_request_encode(ctrl, call, caller, deflection, subscription_option)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for CallRerouting/CallDeflection message.\n");
-+ return -1;
-+ }
-
- return 0;
- }
-+
-+/*!
-+ * \brief Send the Q.SIG CallRerouting invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Q.931 call leg.
-+ * \param dest Destination number.
-+ * \param original Original called number.
-+ * \param reason Rerouting reason: cfu, cfb, cfnr
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int qsig_cf_callrerouting(struct pri *ctrl, q931_call *call, const char *dest,
-+ const char *original, const char *reason)
-+{
-+ struct q931_party_redirecting reroute;
-+
-+ q931_party_redirecting_init(&reroute);
-+
-+ /* Rerouting to the dest number. */
-+ reroute.to.number.valid = 1;
-+ reroute.to.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
-+ reroute.to.number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ libpri_copy_string(reroute.to.number.str, dest, sizeof(reroute.to.number.str));
-+
-+ /* Rerouting from the original number. */
-+ if (original) {
-+ reroute.from.number.valid = 1;
-+ reroute.from.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
-+ libpri_copy_string(reroute.from.number.str, original, sizeof(reroute.from.number.str));
-+ } else {
-+ q931_party_address_to_id(&reroute.from, &call->called);
-+ }
-+ reroute.from.number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+
-+ /* Decode the rerouting reason. */
-+ reroute.reason = PRI_REDIR_UNKNOWN;
-+ if (!reason) {
-+ /* No reason for rerouting given. */
-+ } else if (!strcasecmp(reason, "cfu")) {
-+ reroute.reason = PRI_REDIR_UNCONDITIONAL;
-+ } else if (!strcasecmp(reason, "cfb")) {
-+ reroute.reason = PRI_REDIR_FORWARD_ON_BUSY;
-+ } else if (!strcasecmp(reason, "cfnr")) {
-+ reroute.reason = PRI_REDIR_FORWARD_ON_NO_REPLY;
-+ }
-+
-+ reroute.count = (call->redirecting.count < PRI_MAX_REDIRECTS)
-+ ? call->redirecting.count + 1 : PRI_MAX_REDIRECTS;
-+
-+ if (!call->redirecting.orig_called.number.valid) {
-+ /*
-+ * Since we do not already have an originally called party, we
-+ * must either be the first redirected to party or this call
-+ * has not been redirected before.
-+ *
-+ * Preserve who redirected to us as the originally called party.
-+ */
-+ reroute.orig_called = call->redirecting.from;
-+ reroute.orig_reason = call->redirecting.reason;
-+ } else {
-+ reroute.orig_called = call->redirecting.orig_called;
-+ reroute.orig_reason = call->redirecting.orig_reason;
-+ }
-+
-+ return send_reroute_request(ctrl, call, NULL, &reroute, 0 /* noNotification */);
-+}
- /* End QSIG CC-CallRerouting */
-
--static int anfpr_pathreplacement_respond(struct pri *pri, q931_call *call, q931_ie *ie)
-+/*
-+ * From Mantis issue 7778 description: (ETS 300 258, ISO 13863)
-+ * After both legs of the call are setup and Asterisk has a successful "tromboned" or bridged call ...
-+ * Asterisk sees both 'B' channels (from trombone) are on same PRI/technology and initiates "Path Replacement" events
-+ * a. Asterisk sends "Transfer Complete" messages to both call legs
-+ * b. QSIG Switch sends "PathReplacement" message on one of the legs (random 1-10sec timer expires - 1st leg to send is it!)
-+ * c. Asterisk rebroadcasts "PathReplacement" message to other call leg
-+ * d. QSIG Switch sends "Disconnect" message on one of the legs (same random timer sequence as above)
-+ * e. Asterisk rebroadcasts "Disconnect" message to other call leg
-+ * f. QSIG Switch disconnects Asterisk call legs - callers are now within QSIG switch
-+ *
-+ * Just need to resend the message to the other tromboned leg of the call.
-+ */
-+static int anfpr_pathreplacement_respond(struct pri *ctrl, q931_call *call, q931_ie *ie)
- {
- int res;
--
-- res = pri_call_apdu_queue_cleanup(call->bridged_call);
-- if (res) {
-- pri_message(pri, "Could not Clear queue ADPU\n");
-- return -1;
-- }
--
-+
-+ pri_call_apdu_queue_cleanup(call->bridged_call);
-+
- /* Send message */
-- res = pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len, NULL, NULL);
-+ res = pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len, NULL);
- if (res) {
-- pri_message(pri, "Could not queue ADPU in facility message\n");
-- return -1;
-+ pri_message(ctrl, "Could not queue ADPU in facility message\n");
-+ return -1;
- }
--
-+
- /* Remember that if we queue a facility IE for a facility message we
- * have to explicitly send the facility message ourselves */
--
-+
- res = q931_facility(call->bridged_call->pri, call->bridged_call);
- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", call->bridged_call->cr);
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n",
-+ call->bridged_call->cr);
- return -1;
- }
-
- return 0;
- }
-+
- /* AFN-PR */
--int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
-+/*!
-+ * \brief Start a Q.SIG path replacement.
-+ *
-+ * \note Called for PRI_SWITCH_QSIG
-+ *
-+ * \note Did all the tests to see if we're on the same PRI and
-+ * are on a compatible switchtype.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param c1 Q.931 call leg 1
-+ * \param c2 Q.931 call leg 2
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int anfpr_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
- {
-- /* Did all the tests to see if we're on the same PRI and
-- * are on a compatible switchtype */
-- /* TODO */
-- int i = 0;
-- int res = 0;
-- unsigned char buffer[255] = "";
-- unsigned short call_reference = c2->cr;
-- struct rose_component *comp = NULL, *compstk[10];
-- unsigned char buffer2[255] = "";
-- int compsp = 0;
-- static unsigned char op_tag[] = {
-- 0x0C,
-- };
--
-- /* Channel 1 */
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- /* Interpretation component */
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 2); /* reject - to get feedback from QSIG switch */
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
--
-- res = asn1_string_encode(ASN1_INTEGER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-+ unsigned char buffer[255];
-+ unsigned char *pos;
-+ unsigned char *end;
-+ int res;
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-+
-+ end = buffer + sizeof(buffer);
-+
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 2; /* rejectAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, buffer, end, &header);
-+ if (!pos) {
- return -1;
-- i += res;
--
-- ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- buffer[i++] = (0x0a);/* Enumeration endDesignation */
-- buffer[i++] = (0x01);/* Len */
-- buffer[i++] = (0x00);/* primaryEnd */
-- buffer[i++] = (0x81);/* redirectionNumber = presentationRestricted */
-- buffer[i++] = (0x00);/* Len */
-- buffer[i++] = (0x0a);/* Enumeration callStatus */
-- buffer[i++] = (0x01);/* Len */
-- buffer[i++] = (0x01);/* alerting */
-+ }
-
-- /*
-- * Where does this element come from? It is not in Q.SIG ECMA-178.
-- * We send this but we will not accept it.
-- * This seems to be a cut and paste error from eect_initiate_transfer().
-- */
-- ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CallTransferComplete;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.qsig.CallTransferComplete.end_designation = 0; /* primaryEnd */
-+ msg.args.qsig.CallTransferComplete.redirection.presentation = 1; /* presentationRestricted */
-+ msg.args.qsig.CallTransferComplete.call_status = 1; /* alerting */
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+ if (!pos) {
-+ return -1;
-+ }
-
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
-+ res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, pos - buffer, NULL);
- if (res) {
-- pri_message(pri, "Could not queue ADPU in facility message\n");
-+ pri_message(ctrl, "Could not queue ADPU in facility message\n");
- return -1;
- }
--
-+
- /* Remember that if we queue a facility IE for a facility message we
- * have to explicitly send the facility message ourselves */
--
-+
- res = q931_facility(c1->pri, c1);
- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n", c1->cr);
- return -1;
- }
--
-- /* Channel 2 */
-- i = 0;
-- res = 0;
-- compsp = 0;
--
-- buffer2[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer2, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer2, i, 0);
-- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer2, i, 0);
-- ASN1_FIXUP(compstk, compsp, buffer2, i);
--
-- /* Interpretation component */
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer2, i, 2); /* reject */
--
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer2, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer2, i, get_invokeid(pri));
--
-- res = asn1_string_encode(ASN1_INTEGER, &buffer2[i], sizeof(buffer2)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
-- if (res < 0)
-+
-+ /* Reuse the previous message header */
-+ pos = facility_encode_header(ctrl, buffer, end, &header);
-+ if (!pos) {
- return -1;
-- i += res;
--
-- ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer2, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- buffer2[i++] = (0x0a);/* Enumeration endDesignation */
-- buffer2[i++] = (0x01);/* Len */
-- buffer2[i++] = (0x01);/* secondaryEnd */
-- buffer2[i++] = (0x81);/* redirectionNumber = presentationRestricted */
-- buffer2[i++] = (0x00);/* Len */
-- buffer2[i++] = (0x0a);/* Enumeration callStatus */
-- buffer2[i++] = (0x01);/* Len */
-- buffer2[i++] = (0x01);/* alerting */
-+ }
-
-- /*
-- * Where does this element come from? It is not in Q.SIG ECMA-178.
-- * We send this but we will not accept it.
-- * This seems to be a cut and paste error from eect_initiate_transfer().
-- */
-- ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer2, i, call_reference);
-+ /* Update the previous message */
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.qsig.CallTransferComplete.end_designation = 1; /* secondaryEnd */
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+ if (!pos) {
-+ return -1;
-+ }
-
-- ASN1_FIXUP(compstk, compsp, buffer2, i);
-- ASN1_FIXUP(compstk, compsp, buffer2, i);
--
--
-- res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer2, i, NULL, NULL);
-+ res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer, pos - buffer, NULL);
- if (res) {
-- pri_message(pri, "Could not queue ADPU in facility message\n");
-+ pri_message(ctrl, "Could not queue ADPU in facility message\n");
- return -1;
- }
--
-+
- /* Remember that if we queue a facility IE for a facility message we
- * have to explicitly send the facility message ourselves */
--
-+
- res = q931_facility(c2->pri, c2);
- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n", c2->cr);
- return -1;
- }
--
-+
- return 0;
- }
- /* End AFN-PR */
-
- /* AOC */
--static int aoc_aoce_charging_request_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI AOCEChargingUnit invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param chargedunits Number of units charged to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_aoce_charging_unit(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, long chargedunits)
- {
-- int chargingcase = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL;
-- int pos1 = 0;
-+ struct rose_msg_invoke msg;
-
-- if (pri->debug & PRI_DEBUG_AOC)
-- dump_apdu (pri, data, len);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- do {
-- GET_COMPONENT(comp, pos1, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "!! Invalid AOC Charging Request argument. Expected Enumerated (0x0A) but Received 0x%02X\n");
-- ASN1_GET_INTEGER(comp, chargingcase);
-- if (chargingcase >= 0 && chargingcase <= 2) {
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "Channel %d/%d, Call %d - received AOC charging request - charging case: %i\n",
-- call->ds1no, call->channelno, call->cr, chargingcase);
-- } else {
-- pri_message(pri, "!! unkown AOC ChargingCase: 0x%02X", chargingcase);
-- chargingcase = -1;
-- }
-- NEXT_COMPONENT(comp, pos1);
-- } while (pos1 < len);
-- if (pos1 < len) {
-- pri_message(pri, "!! Only reached position %i in %i bytes long AOC-E structure:", pos1, len );
-- dump_apdu (pri, data, len);
-- return -1; /* Aborted before */
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_AOCEChargingUnit;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.etsi.AOCEChargingUnit.type = 1; /* charging_unit */
-+ if (chargedunits <= 0) {
-+ msg.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1;
-+ } else {
-+ msg.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1;
-+ msg.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].
-+ number_of_units = chargedunits;
- }
-- return 0;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
--
-
--static int aoc_aoce_charging_unit_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
-+/*!
-+ * \internal
-+ * \brief Send the ETSI AOCEChargingUnit invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode AOC.
-+ * \param chargedunits Number of units charged to encode.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int aoc_aoce_charging_unit_encode(struct pri *ctrl, q931_call *call,
-+ long chargedunits)
- {
-- long chargingunits = 0, chargetype = -1, temp, chargeIdentifier = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp1 = NULL, *comp2 = NULL, *comp3 = NULL;
-- int pos1 = 0, pos2, pos3, sublen2, sublen3;
-- struct addressingdataelements_presentednumberunscreened chargednr;
-+ unsigned char buffer[255];
-+ unsigned char *end;
-
-- if (pri->debug & PRI_DEBUG_AOC)
-- dump_apdu (pri, data, len);
-+ /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */
-
-- do {
-- GET_COMPONENT(comp1, pos1, vdata, len); /* AOCEChargingUnitInfo */
-- CHECK_COMPONENT(comp1, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but Received 0x%02X\n");
-- SUB_COMPONENT(comp1, pos1);
-- GET_COMPONENT(comp1, pos1, vdata, len);
-- switch (comp1->type) {
-- case (ASN1_SEQUENCE | ASN1_CONSTRUCTOR): /* specificChargingUnits */
-- sublen2 = comp1->len;
-- pos2 = pos1;
-- comp2 = comp1;
-- SUB_COMPONENT(comp2, pos2);
-- do {
-- GET_COMPONENT(comp2, pos2, vdata, len);
-- switch (comp2->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* RecordedUnitsList (0xA1) */
-- SUB_COMPONENT(comp2, pos2);
-- GET_COMPONENT(comp2, pos2, vdata, len);
-- CHECK_COMPONENT(comp2, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but received 0x02%X\n"); /* RecordedUnits */
-- sublen3 = pos2 + comp2->len;
-- pos3 = pos2;
-- comp3 = comp2;
-- SUB_COMPONENT(comp3, pos3);
-- do {
-- GET_COMPONENT(comp3, pos3, vdata, len);
-- switch (comp3->type) {
-- case ASN1_INTEGER: /* numberOfUnits */
-- ASN1_GET_INTEGER(comp3, temp);
-- chargingunits += temp;
-- case ASN1_NULL: /* notAvailable */
-- break;
-- default:
-- pri_message(pri, "!! Don't know how to handle 0x%02X in AOC-E RecordedUnits\n", comp3->type);
-- }
-- NEXT_COMPONENT(comp3, pos3);
-- } while (pos3 < sublen3);
-- if (pri->debug & PRI_DEBUG_AOC)
-- pri_message(pri, "Channel %d/%d, Call %d - received AOC-E charging: %i unit%s\n",
-- call->ds1no, call->channelno, call->cr, chargingunits, (chargingunits == 1) ? "" : "s");
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* AOCEBillingID (0xA2) */
-- SUB_COMPONENT(comp2, pos2);
-- GET_COMPONENT(comp2, pos2, vdata, len);
-- ASN1_GET_INTEGER(comp2, chargetype);
-- pri_message(pri, "!! not handled: Channel %d/%d, Call %d - received AOC-E billing ID: %i\n",
-- call->ds1no, call->channelno, call->cr, chargetype);
-- break;
-- default:
-- pri_message(pri, "!! Don't know how to handle 0x%02X in AOC-E RecordedUnitsList\n", comp2->type);
-- }
-- NEXT_COMPONENT(comp2, pos2);
-- } while (pos2 < sublen2);
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* freeOfCharge (0x81) */
-- if (pri->debug & PRI_DEBUG_AOC)
-- pri_message(pri, "Channel %d/%d, Call %d - received AOC-E free of charge\n", call->ds1no, call->channelno, call->cr);
-- chargingunits = 0;
-- break;
-- default:
-- pri_message(pri, "!! Invalid AOC-E specificChargingUnits. Expected Sequence (0x30) or Object Identifier (0x81/0x01) but received 0x%02X\n", comp1->type);
-- }
-- NEXT_COMPONENT(comp1, pos1);
-- GET_COMPONENT(comp1, pos1, vdata, len); /* get optional chargingAssociation. will 'break' when reached end of structure */
-- switch (comp1->type) {
-- /* TODO: charged number is untested - please report! */
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* chargedNumber (0xA0) */
-- if(rose_presented_number_unscreened_decode(pri, call, comp1->data, comp1->len, &chargednr) != 0)
-- return -1;
-- pri_message(pri, "!! not handled: Received ChargedNr '%s' \n", chargednr.partyaddress);
-- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", chargednr.ton, chargednr.pres, chargednr.npi);
-- break;
-- case ASN1_INTEGER:
-- ASN1_GET_INTEGER(comp1, chargeIdentifier);
-- break;
-- default:
-- pri_message(pri, "!! Invalid AOC-E chargingAssociation. Expected Object Identifier (0xA0) or Integer (0x02) but received 0x%02X\n", comp1->type);
-- }
-- NEXT_COMPONENT(comp1, pos1);
-- } while (pos1 < len);
-+ end =
-+ enc_etsi_aoce_charging_unit(ctrl, buffer, buffer + sizeof(buffer), chargedunits);
-+ if (!end) {
-+ return -1;
-+ }
-
-- if (pos1 < len) {
-- pri_message(pri, "!! Only reached position %i in %i bytes long AOC-E structure:", pos1, len );
-- dump_apdu (pri, data, len);
-- return -1; /* oops - aborted before */
-+ /* Remember that if we queue a facility IE for a facility message we
-+ * have to explicitly send the facility message ourselves */
-+ if (pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL)
-+ || q931_facility(call->pri, call)) {
-+ pri_message(ctrl, "Could not schedule facility message for call %d\n", call->cr);
-+ return -1;
- }
-- call->aoc_units = chargingunits;
--
-+
- return 0;
- }
-+/* End AOC */
-
--static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits)
-+/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG CallTransferComplete invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode call transfer.
-+ * \param call_status TRUE if call is alerting.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_call_transfer_complete(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, q931_call *call, int call_status)
- {
-- /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */
-- int i = 0, res = 0, compsp = 0;
-- unsigned char buffer[255] = "";
-- struct rose_component *comp = NULL, *compstk[10];
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- /* ROSE protocol (0x91)*/
-- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- /* ROSE Component (0xA1,len)*/
-- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CallTransferComplete;
-+ msg.invoke_id = get_invokeid(ctrl);
-+ msg.args.qsig.CallTransferComplete.end_designation = 0; /* primaryEnd */
-
-- /* ROSE invokeId component (0x02,len,id)*/
-- ASN1_ADD_WORDCOMP(comp, INVOKE_IDENTIFIER, buffer, i, ++pri->last_invoke);
-+ /* redirectionNumber is the local_id.number */
-+ q931_copy_presented_number_screened_to_rose(ctrl,
-+ &msg.args.qsig.CallTransferComplete.redirection, &call->local_id.number);
-
-- /* ROSE operationId component (0x02,0x01,0x24)*/
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_AOC_AOCE_CHARGING_UNIT);
-+ /* redirectionName is the local_id.name */
-+ if (call->local_id.name.valid) {
-+ msg.args.qsig.CallTransferComplete.redirection_name_present = 1;
-+ q931_copy_name_to_rose(ctrl,
-+ &msg.args.qsig.CallTransferComplete.redirection_name,
-+ &call->local_id.name);
-+ }
-
-- /* AOCEChargingUnitInfo (0x30,len) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ if (call_status) {
-+ msg.args.qsig.CallTransferComplete.call_status = 1; /* alerting */
-+ }
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- if (chargedunits > 0) {
-- /* SpecificChargingUnits (0x30,len) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-+ return pos;
-+}
-
-- /* RecordedUnitsList (0xA1,len) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- /* RecordedUnits (0x30,len) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
--
-- /* NumberOfUnits (0x02,len,charge) */
-- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, chargedunits);
-+/*!
-+ * \internal
-+ * \brief Encode the ETSI EctInform invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode inform message.
-+ * \param call_status TRUE if call is alerting.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_ect_inform(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int call_status)
-+{
-+ struct rose_msg_invoke msg;
-
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- } else {
-- /* freeOfCharge (0x81,0) */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
- }
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- if (pri->debug & PRI_DEBUG_AOC)
-- dump_apdu (pri, buffer, i);
--
-- /* code below is untested */
-- res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
-- if (res) {
-- pri_message(pri, "Could not queue APDU in facility message\n");
-- return -1;
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_ETSI_EctInform;
-+ msg.invoke_id = get_invokeid(ctrl);
-+
-+ if (!call_status) {
-+ msg.args.etsi.EctInform.status = 1;/* active */
-+
-+ /*
-+ * EctInform(active) contains the redirectionNumber
-+ * redirectionNumber is the local_id.number
-+ */
-+ msg.args.etsi.EctInform.redirection_present = 1;
-+ q931_copy_presented_number_unscreened_to_rose(ctrl,
-+ &msg.args.etsi.EctInform.redirection, &call->local_id.number);
- }
-
-- /* Remember that if we queue a facility IE for a facility message we
-- * have to explicitly send the facility message ourselves */
-- res = q931_facility(c->pri, c);
-- if (res) {
-- pri_message(pri, "Could not schedule facility message for call %d\n", c->cr);
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode and queue the CallTransferComplete/EctInform invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode call transfer.
-+ * \param call_status TRUE if call is alerting.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_call_transfer_complete_encode(struct pri *ctrl, q931_call *call,
-+ int call_status)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end =
-+ enc_etsi_ect_inform(ctrl, buffer, buffer + sizeof(buffer), call, call_status);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end =
-+ enc_qsig_call_transfer_complete(ctrl, buffer, buffer + sizeof(buffer), call,
-+ call_status);
-+ break;
-+ default:
- return -1;
- }
-+ if (!end) {
-+ return -1;
-+ }
-
-- return 0;
-+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
- }
--/* End AOC */
-
--static int rose_calling_name_decode(struct pri *pri, q931_call *call, struct rose_component *choice, int len)
-+/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG CalledName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param name Name data which to encode name.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_called_name(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct q931_party_name *name)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = choice->data;
-- int characterSet = 1;
-- switch (choice->type) {
-- case ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE:
-- memcpy(call->callername, choice->data, choice->len);
-- call->callername[choice->len] = 0;
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received simple calling name '%s'\n", call->callername);
-- return 0;
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- case ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED:
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_OCTETSTRING, "Don't know what to do if nameData is of type 0x%x\n");
-- memcpy(call->callername, comp->data, comp->len);
-- call->callername[comp->len] = 0;
-- NEXT_COMPONENT(comp, i);
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if CharacterSet is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, characterSet);
-- }
-- while (0);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_CalledName;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received extended calling name '%s', characterset %d\n", call->callername, characterSet);
-- return 0;
-- case ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE:
-- case ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED:
-- case ROSE_NAME_PRESENTATION_RESTRICTED_NULL:
-- case ROSE_NAME_NOT_AVAIL:
-- default:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "Do not handle argument of type 0x%X\n", choice->type);
-- return -1;
-- }
-+ /* CalledName */
-+ q931_copy_name_to_rose(ctrl, &msg.args.qsig.CalledName.name, name);
-+
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-+
-+ return pos;
- }
--/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
-
--static int rose_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+/*!
-+ * \internal
-+ * \brief Encode and queue the Q.SIG CalledName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode name.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rose_called_name_encode(struct pri *ctrl, q931_call *call, int messagetype)
- {
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-+ /* CalledName is the local_id.name */
-+ end = enc_qsig_called_name(ctrl, buffer, buffer + sizeof(buffer),
-+ &call->local_id.name);
-+ if (!end) {
-+ return -1;
-+ }
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-+ return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL);
-+}
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT NumberDigits -- default: unknownPartyNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: UnknownPartyNumber len=%d\n", len);
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->ton = PRI_TON_UNKNOWN;
-- break;
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG ConnectedName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param name Name data which to encode name.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_connected_name(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct q931_party_name *name)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_invoke msg;
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] IMPLICIT PublicPartyNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: PublicPartyNumber len=%d\n", len);
-- size = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_E163_E164;
-- break;
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT NumberDigits -- not used: dataPartyNumber */
-- pri_message(pri, "!! PartyNumber: dataPartyNumber is reserved!\n");
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_X121 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-- break;
-+ memset(&msg, 0, sizeof(msg));
-+ msg.operation = ROSE_QSIG_ConnectedName;
-+ msg.invoke_id = get_invokeid(ctrl);
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] IMPLICIT NumberDigits -- not used: telexPartyNumber */
-- pri_message(pri, "!! PartyNumber: telexPartyNumber is reserved!\n");
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_F69 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-- break;
-+ /* ConnectedName */
-+ q931_copy_name_to_rose(ctrl, &msg.args.qsig.ConnectedName.name, name);
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] IMPLICIT PrivatePartyNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: PrivatePartyNumber len=%d\n", len);
-- size = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_PRIVATE;
-- break;
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] IMPLICIT NumberDigits -- not used: nationalStandatdPartyNumber */
-- pri_message(pri, "!! PartyNumber: nationalStandardPartyNumber is reserved!\n");
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_NATIONAL;
-- value->ton = PRI_TON_NATIONAL;
-- break;
-+ return pos;
-+}
-
-- default:
-- pri_message(pri, "Invalid PartyNumber component 0x%X\n", comp->type);
-- return -1;
-- }
-- ASN1_FIXUP_LEN(comp, size);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: '%s' size=%d len=%d\n", value->partyaddress, size, len);
-- return size;
-+/*!
-+ * \internal
-+ * \brief Encode and queue the Q.SIG ConnectedName invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode name.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int rose_connected_name_encode(struct pri *ctrl, q931_call *call, int messagetype)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-+
-+ /* ConnectedName is the local_id.name */
-+ end = enc_qsig_connected_name(ctrl, buffer, buffer + sizeof(buffer),
-+ &call->local_id.name);
-+ if (!end) {
-+ return -1;
- }
-- while (0);
-
-- return -1;
-+ return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL);
- }
-
--
--static int rose_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
-+/*!
-+ * \brief Put the APDU on the call queue.
-+ *
-+ * \param call Call to enqueue message.
-+ * \param messagetype Q.931 message type.
-+ * \param apdu Facility ie contents buffer.
-+ * \param apdu_len Length of the contents buffer.
-+ * \param response Sender supplied information to handle APDU response messages.
-+ * NULL if don't care about responses.
-+ *
-+ * \note
-+ * Only APDU messages with an invoke component can supply a response pointer.
-+ * If any other APDU messages supply a response pointer then aliasing of the
-+ * invoke_id can occur.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len, struct apdu_callback_data *response)
- {
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ struct apdu_event *cur = NULL;
-+ struct apdu_event *new_event = NULL;
-
-- int scrind = -1;
--
-- do {
-- /* Party Number */
-- GET_COMPONENT(comp, i, vdata, len);
-- size = rose_party_number_decode(pri, call, (u_int8_t *)comp, comp->len + 2, (struct addressingdataelements_presentednumberunscreened*) value);
-- if (size < 0)
-+ if (!call || !messagetype || !apdu
-+ || apdu_len < 1 || sizeof(new_event->apdu) < apdu_len) {
-+ return -1;
-+ }
-+ switch (messagetype) {
-+ case Q931_FACILITY:
-+ break;
-+ default:
-+ if (q931_is_dummy_call(call)) {
-+ pri_error(call->pri, "!! Cannot send %s message on dummy call reference.\n",
-+ msg2str(messagetype));
- return -1;
-- comp->len = size;
-- NEXT_COMPONENT(comp, i);
-+ }
-+ break;
-+ }
-
-- /* Screening Indicator */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with NumberScreened ROSE component type 0x%x\n");
-- ASN1_GET_INTEGER(comp, scrind);
-- // Todo: scrind = screeningindicator_for_q931(pri, scrind);
-- NEXT_COMPONENT(comp, i);
-+ new_event = calloc(1, sizeof(*new_event));
-+ if (!new_event) {
-+ pri_error(call->pri, "!! Malloc failed!\n");
-+ return -1;
-+ }
-
-- value->scrind = scrind;
-+ /* Fill in the APDU event */
-+ new_event->message = messagetype;
-+ if (response) {
-+ new_event->response = *response;
-+ }
-+ new_event->call = call;
-+ new_event->apdu_len = apdu_len;
-+ memcpy(new_event->apdu, apdu, apdu_len);
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " NumberScreened: '%s' ScreeningIndicator=%d i=%d len=%d\n", value->partyaddress, scrind, i, len);
--
-- return i-2; // We do not have a sequence header here.
-+ /* Append APDU event to the end of the list. */
-+ if (call->apdus) {
-+ for (cur = call->apdus; cur->next; cur = cur->next) {
-+ }
-+ cur->next = new_event;
-+ } else {
-+ call->apdus = new_event;
- }
-- while (0);
-
-- return -1;
-+ return 0;
- }
-
--
--static int rose_presented_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
-+/* Used by q931.c to cleanup the apdu queue upon destruction of a call */
-+void pri_call_apdu_queue_cleanup(q931_call *call)
- {
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ struct apdu_event *cur_event;
-+ struct apdu_event *free_event;
-
-- /* Fill in default values */
-- value->ton = PRI_TON_UNKNOWN;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->pres = -1; /* Data is not available */
-+ if (call) {
-+ cur_event = call->apdus;
-+ call->apdus = NULL;
-+ while (cur_event) {
-+ if (cur_event->response.callback) {
-+ /* Indicate to callback that the APDU is being cleaned up. */
-+ cur_event->response.callback(APDU_CALLBACK_REASON_CLEANUP, call->pri,
-+ call, cur_event, NULL);
-
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-+ /* Stop any response timeout. */
-+ pri_schedule_del(call->pri, cur_event->timer);
-+ }
-+ free_event = cur_event;
-+ cur_event = cur_event->next;
-+ free(free_event);
-+ }
-+ }
-+}
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT presentationAllowedNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: presentationAllowedNumber comp->len=%d\n", comp->len);
-- value->pres = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
-- size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
-+/*!
-+ * \internal
-+ * \brief Find an outstanding APDU with the given invoke id.
-+ *
-+ * \param call Call to find APDU.
-+ * \param invoke_id Invoke id to match outstanding APDUs in queue.
-+ *
-+ * \retval apdu_event if found.
-+ * \retval NULL if not found.
-+ */
-+static struct apdu_event *pri_call_apdu_find(struct q931_call *call, int invoke_id)
-+{
-+ struct apdu_event *apdu;
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: presentationRestricted comp->len=%d\n", comp->len);
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
-- return -1;
-- }
-- value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-- return 2;
-+ for (apdu = call->apdus; apdu; apdu = apdu->next) {
-+ /*
-+ * Note: The APDU cannot be sent and still in the queue without a
-+ * callback and timeout timer active. Therefore, an invoke_id of
-+ * zero is valid and not just the result of a memset().
-+ */
-+ if (apdu->response.invoke_id == invoke_id && apdu->sent) {
-+ break;
-+ }
-+ }
-+ return apdu;
-+}
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: NumberNotAvailableDueToInterworking comp->len=%d\n", comp->len);
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
-- return -1;
-- }
-- value->pres = PRES_NUMBER_NOT_AVAILABLE;
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: numberNotAvailableDueToInterworking Type=0x%X i=%d len=%d size=%d\n", comp->type, i, len);
-- return 2;
-+/*!
-+ * \brief Delete the given APDU event from the given call.
-+ *
-+ * \param call Call to remove the APDU.
-+ * \param doomed APDU event to delete.
-+ *
-+ * \return Nothing
-+ */
-+void pri_call_apdu_delete(struct q931_call *call, struct apdu_event *doomed)
-+{
-+ struct apdu_event **prev;
-+ struct apdu_event *cur;
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT presentationRestrictedNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: presentationRestrictedNumber comp->len=%d\n", comp->len);
-- value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-- size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
-+ /* Find APDU in list. */
-+ for (prev = &call->apdus, cur = call->apdus;
-+ cur;
-+ prev = &cur->next, cur = cur->next) {
-+ if (cur == doomed) {
-+ /* Stop any response timeout. */
-+ pri_schedule_del(call->pri, cur->timer);
-
-- default:
-- pri_message(pri, "Invalid PresentedNumberScreened component 0x%X\n", comp->type);
-+ /* Remove APDU from list. */
-+ *prev = cur->next;
-+ free(cur);
-+ break;
- }
-- return -1;
- }
-- while (0);
--
-- return -1;
- }
-
--
--static int rose_call_transfer_complete_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+/*! \note Only called when sending the SETUP message. */
-+int pri_call_add_standard_apdus(struct pri *ctrl, q931_call *call)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = sequence->data;
-- int res = 0;
-+ if (!ctrl->sendfacility) {
-+ return 0;
-+ }
-
-- int end_designation = 0;
-- struct addressingdataelements_presentednumberscreened redirection_number;
-- char redirection_name[50] = "";
-- int call_status = 0;
-- redirection_number.partyaddress[0] = 0;
-- redirection_number.partysubaddress[0] = 0;
-- call->callername[0] = 0;
-- call->callernum[0] = 0;
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* PTMP mode */
-+ break;
-+ }
-+ /* PTP mode */
-+ if (call->redirecting.count) {
-+ rose_diverting_leg_information2_encode(ctrl, call);
-
-+ /*
-+ * Expect a DivertingLegInformation3 to update the COLR of the
-+ * redirecting-to party we are attempting to call now.
-+ */
-+ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
-+ }
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ /* For Q.SIG it does network and cpe operations */
-+ if (call->redirecting.count) {
-+ rose_diverting_leg_information2_encode(ctrl, call);
-
-- /* Data checks */
-- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-- pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
-- return -1;
-+ /*
-+ * Expect a DivertingLegInformation3 to update the COLR of the
-+ * redirecting-to party we are attempting to call now.
-+ */
-+ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
-+ }
-+ add_callername_facility_ies(ctrl, call, 1);
-+ break;
-+ case PRI_SWITCH_NI2:
-+ add_callername_facility_ies(ctrl, call, (ctrl->localtype == PRI_CPE));
-+ break;
-+ case PRI_SWITCH_DMS100:
-+ if (ctrl->localtype == PRI_CPE) {
-+ add_dms100_transfer_ability_apdu(ctrl, call);
-+ }
-+ break;
-+ default:
-+ break;
- }
-
-- if (sequence->len == ASN1_LEN_INDEF) {
-- len -= 4; /* For the 2 extra characters at the end
-- * and two characters of header */
-- } else
-- len -= 2;
-+ return 0;
-+}
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: len=%d\n", len);
-+/*!
-+ * \brief Send the CallTransferComplete/EctInform invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode call transfer.
-+ * \param call_status TRUE if call is alerting.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int send_call_transfer_complete(struct pri *ctrl, q931_call *call, int call_status)
-+{
-+ if (rose_call_transfer_complete_encode(ctrl, call, call_status)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for call transfer completed.\n");
-+ return -1;
-+ }
-
-- do {
-- /* End Designation */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid endDesignation type 0x%X of ROSE callTransferComplete component received\n");
-- ASN1_GET_INTEGER(comp, end_designation);
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received endDesignation=%d\n", end_designation);
-+ return 0;
-+}
-
-+/*!
-+ * \internal
-+ * \brief Encode a plain facility ETSI error code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode error message response.
-+ * \param invoke_id Invoke id to put in error message response.
-+ * \param code Error code to put in error message response.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_error(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int invoke_id, enum rose_error_code code)
-+{
-+ struct rose_msg_error msg;
-
-- /* Redirection Number */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
-- if (res < 0)
-- return -1;
-- comp->len = res;
-- if (res > 2) {
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
-- strncpy(call->callernum, redirection_number.partyaddress, 20);
-- call->callernum[20] = 0;
-- }
-- NEXT_COMPONENT(comp, i);
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-+ memset(&msg, 0, sizeof(msg));
-+ msg.invoke_id = invoke_id;
-+ msg.code = code;
-
--#if 0 /* This one is optional. How do we check if it is there? */
-- /* Basic Call Info Elements */
-- GET_COMPONENT(comp, i, vdata, len);
-- NEXT_COMPONENT(comp, i);
--#endif
-+ pos = rose_encode_error(ctrl, pos, end, &msg);
-
-+ return pos;
-+}
-
-- /* Redirection Name */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
-- if (res < 0)
-- return -1;
-- memcpy(call->callername, comp->data, comp->len);
-- call->callername[comp->len] = 0;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
-+/*!
-+ * \internal
-+ * \brief Encode a plain facility Q.SIG error code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode error message response.
-+ * \param invoke_id Invoke id to put in error message response.
-+ * \param code Error code to put in error message response.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_error(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int invoke_id, enum rose_error_code code)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_error msg;
-
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-- /* Call Status */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid callStatus type 0x%X of ROSE callTransferComplete component received\n");
-- ASN1_GET_INTEGER(comp, call_status);
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received callStatus=%d\n", call_status);
-+ memset(&msg, 0, sizeof(msg));
-+ msg.invoke_id = invoke_id;
-+ msg.code = code;
-
-+ pos = rose_encode_error(ctrl, pos, end, &msg);
-
-- /* Argument Extension */
--#if 0 /* Not supported */
-- GET_COMPONENT(comp, i, vdata, len);
-- switch (comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_9): /* [9] IMPLICIT Extension */
-- res = rose_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+ return pos;
-+}
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
-- res = rose_sequence_of_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+/*!
-+ * \internal
-+ * \brief Encode and queue a plain facility error code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode error message response.
-+ * \param invoke_id Invoke id to put in error message response.
-+ * \param code Error code to put in error message response.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_facility_error_encode(struct pri *ctrl, q931_call *call, int invoke_id,
-+ enum rose_error_code code)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-- default:
-- pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
-- return -1;
-- }
--#else
-- GET_COMPONENT(comp, i, vdata, len);
-- ASN1_FIXUP_LEN(comp, res);
-- NEXT_COMPONENT(comp, i);
--#endif
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end =
-+ enc_etsi_error(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id, code);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end =
-+ enc_qsig_error(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id, code);
-+ break;
-+ default:
-+ return -1;
-+ }
-+ if (!end) {
-+ return -1;
-+ }
-
-- if(i < len)
-- pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
-+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
-+}
-
-- return 0;
-+/*!
-+ * \brief Encode and send a plain facility error code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode error message response.
-+ * \param invoke_id Invoke id to put in error message response.
-+ * \param code Error code to put in error message response.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int send_facility_error(struct pri *ctrl, q931_call *call, int invoke_id,
-+ enum rose_error_code code)
-+{
-+ if (rose_facility_error_encode(ctrl, call, invoke_id, code)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for error message.\n");
-+ return -1;
- }
-- while (0);
-
-- return -1;
-+ return 0;
- }
-
--
--static int rose_call_transfer_update_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+/*!
-+ * \internal
-+ * \brief Encode a plain facility ETSI result ok.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode result ok message response.
-+ * \param invoke_id Invoke id to put in result ok message response.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_etsi_result_ok(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int invoke_id)
- {
-- int i = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = sequence->data;
-- int res = 0;
-+ struct rose_msg_result msg;
-
-- struct addressingdataelements_presentednumberscreened redirection_number;
-- redirection_number.partyaddress[0] = 0;
-- redirection_number.partysubaddress[0] = 0;
-- char redirection_name[50] = "";
-- call->callername[0] = 0;
-- call->callernum[0] = 0;
-+ pos = facility_encode_header(ctrl, pos, end, NULL);
-+ if (!pos) {
-+ return NULL;
-+ }
-
-+ memset(&msg, 0, sizeof(msg));
-+ msg.invoke_id = invoke_id;
-+ msg.operation = ROSE_None;
-
-- /* Data checks */
-- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-- pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
-- return -1;
-+ pos = rose_encode_result(ctrl, pos, end, &msg);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode a plain facility Q.SIG result ok.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param call Call leg from which to encode result ok message response.
-+ * \param invoke_id Invoke id to put in result ok message response.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *enc_qsig_result_ok(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, q931_call *call, int invoke_id)
-+{
-+ struct fac_extension_header header;
-+ struct rose_msg_result msg;
-+
-+ memset(&header, 0, sizeof(header));
-+ header.nfe_present = 1;
-+ header.nfe.source_entity = 0; /* endPINX */
-+ header.nfe.destination_entity = 0; /* endPINX */
-+ header.interpretation_present = 1;
-+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
-+ pos = facility_encode_header(ctrl, pos, end, &header);
-+ if (!pos) {
-+ return NULL;
- }
-
-- if (sequence->len == ASN1_LEN_INDEF) {
-- len -= 4; /* For the 2 extra characters at the end
-- * and two characters of header */
-- } else
-- len -= 2;
-+ memset(&msg, 0, sizeof(msg));
-+ msg.invoke_id = invoke_id;
-+ msg.operation = ROSE_None;
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: len=%d\n", len);
-+ pos = rose_encode_result(ctrl, pos, end, &msg);
-
-- do {
-- /* Redirection Number */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
-- if (res < 0)
-- return -1;
-- comp->len = res;
-- if (res > 2) {
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
-- strncpy(call->callernum, redirection_number.partyaddress, 20);
-- call->callernum[20] = 0;
-- }
-- NEXT_COMPONENT(comp, i);
-+ return pos;
-+}
-
-- /* Redirection Name */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
-- if (res < 0)
-- return -1;
-- memcpy(call->callername, comp->data, comp->len);
-- call->callername[comp->len] = 0;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
-+/*!
-+ * \internal
-+ * \brief Encode and queue a plain ROSE result ok.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode result ok message response.
-+ * \param msgtype Q.931 message type to put facility ie in.
-+ * \param invoke_id Invoke id to put in result ok message response.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int rose_result_ok_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id)
-+{
-+ unsigned char buffer[256];
-+ unsigned char *end;
-
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ end =
-+ enc_etsi_result_ok(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ end =
-+ enc_qsig_result_ok(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id);
-+ break;
-+ default:
-+ return -1;
-+ }
-+ if (!end) {
-+ return -1;
-+ }
-
--#if 0 /* This one is optional. How do we check if it is there? */
-- /* Basic Call Info Elements */
-- GET_COMPONENT(comp, i, vdata, len);
-- NEXT_COMPONENT(comp, i);
--#endif
-+ return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, NULL);
-+}
-
-+/*!
-+ * \brief Encode and send a FACILITY message with a plain ROSE result ok.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which to encode result ok message response.
-+ * \param invoke_id Invoke id to put in result ok message response.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int send_facility_result_ok(struct pri *ctrl, q931_call *call, int invoke_id)
-+{
-+ if (rose_result_ok_encode(ctrl, call, Q931_FACILITY, invoke_id)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for result OK message.\n");
-+ return -1;
-+ }
-
-- /* Argument Extension */
--#if 0 /* Not supported */
-- GET_COMPONENT(comp, i, vdata, len);
-- switch (comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_9): /* [9] IMPLICIT Extension */
-- res = rose_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+ return 0;
-+}
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
-- res = rose_sequence_of_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI_REROUTING_RSP_CODE code)
-+{
-+ enum rose_error_code rose_err;
-
-- default:
-- pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
-- return -1;
-- }
--#else
-- GET_COMPONENT(comp, i, vdata, len);
-- ASN1_FIXUP_LEN(comp, res);
-- NEXT_COMPONENT(comp, i);
--#endif
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-
-- if(i < len)
-- pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
-+ /* Convert the public rerouting response code to an error code or result ok. */
-+ rose_err = ROSE_ERROR_Gen_ResourceUnavailable;
-+ switch (code) {
-+ case PRI_REROUTING_RSP_OK_CLEAR:
-+ return rose_result_ok_encode(ctrl, call, Q931_DISCONNECT, invoke_id);
-+ case PRI_REROUTING_RSP_OK_RETAIN:
-+ return send_facility_result_ok(ctrl, call, invoke_id);
-+ case PRI_REROUTING_RSP_NOT_SUBSCRIBED:
-+ rose_err = ROSE_ERROR_Gen_NotSubscribed;
-+ break;
-+ case PRI_REROUTING_RSP_NOT_AVAILABLE:
-+ rose_err = ROSE_ERROR_Gen_NotAvailable;
-+ break;
-+ case PRI_REROUTING_RSP_NOT_ALLOWED:
-+ rose_err = ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed;
-+ break;
-+ case PRI_REROUTING_RSP_INVALID_NUMBER:
-+ rose_err = ROSE_ERROR_Div_InvalidDivertedToNr;
-+ break;
-+ case PRI_REROUTING_RSP_SPECIAL_SERVICE_NUMBER:
-+ rose_err = ROSE_ERROR_Div_SpecialServiceNr;
-+ break;
-+ case PRI_REROUTING_RSP_DIVERSION_TO_SELF:
-+ rose_err = ROSE_ERROR_Div_DiversionToServedUserNr;
-+ break;
-+ case PRI_REROUTING_RSP_MAX_DIVERSIONS_EXCEEDED:
-+ rose_err = ROSE_ERROR_Div_NumberOfDiversionsExceeded;
-+ break;
-+ case PRI_REROUTING_RSP_RESOURCE_UNAVAILABLE:
-+ rose_err = ROSE_ERROR_Gen_ResourceUnavailable;
-+ break;
-+ }
-+ return send_facility_error(ctrl, call, invoke_id, rose_err);
-+}
-
-- return 0;
-+/*!
-+ * \brief Handle the ROSE reject message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which the message came.
-+ * \param msgtype Q.931 message type ie is in.
-+ * \param ie Raw ie contents.
-+ * \param header Decoded facility header before ROSE.
-+ * \param reject Decoded ROSE reject message contents.
-+ *
-+ * \return Nothing
-+ */
-+void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
-+ const struct fac_extension_header *header, const struct rose_msg_reject *reject)
-+{
-+ struct apdu_event *apdu;
-+ union apdu_msg_data msg;
-+
-+ /* Gripe to the user about getting rejected. */
-+ pri_error(ctrl, "ROSE REJECT:\n");
-+ if (reject->invoke_id_present) {
-+ pri_error(ctrl, "\tINVOKE ID: %d\n", reject->invoke_id);
- }
-- while (0);
-+ pri_error(ctrl, "\tPROBLEM: %s\n", rose_reject2str(reject->code));
-
-- return -1;
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ /* The DMS-100 switch apparently handles invoke_id as an invoke operation. */
-+ return;
-+ default:
-+ break;
-+ }
-+
-+ if (!reject->invoke_id_present) {
-+ /*
-+ * No invoke id to look up so we cannot match it to any outstanding APDUs.
-+ * This REJECT is apparently meant for someone monitoring the link.
-+ */
-+ return;
-+ }
-+ apdu = pri_call_apdu_find(call, reject->invoke_id);
-+ if (!apdu) {
-+ return;
-+ }
-+ msg.reject = reject;
-+ if (apdu->response.callback(APDU_CALLBACK_REASON_MSG_REJECT, ctrl, call, apdu, &msg)) {
-+ pri_call_apdu_delete(call, apdu);
-+ }
- }
-
-+/*!
-+ * \brief Handle the ROSE error message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which the message came.
-+ * \param msgtype Q.931 message type ie is in.
-+ * \param ie Raw ie contents.
-+ * \param header Decoded facility header before ROSE.
-+ * \param error Decoded ROSE error message contents.
-+ *
-+ * \return Nothing
-+ */
-+void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
-+ const struct fac_extension_header *header, const struct rose_msg_error *error)
-+{
-+ const char *dms100_operation;
-+ struct apdu_event *apdu;
-+ union apdu_msg_data msg;
-
--/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
-+ /* Gripe to the user about getting an error. */
-+ pri_error(ctrl, "ROSE RETURN ERROR:\n");
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ switch (error->invoke_id) {
-+ case ROSE_DMS100_RLT_OPERATION_IND:
-+ dms100_operation = "RLT_OPERATION_IND";
-+ break;
-+ case ROSE_DMS100_RLT_THIRD_PARTY:
-+ dms100_operation = "RLT_THIRD_PARTY";
-+ break;
-+ default:
-+ dms100_operation = NULL;
-+ break;
-+ }
-+ if (dms100_operation) {
-+ pri_error(ctrl, "\tOPERATION: %s\n", dms100_operation);
-+ break;
-+ }
-+ /* fall through */
-+ default:
-+ pri_error(ctrl, "\tINVOKE ID: %d\n", error->invoke_id);
-+ break;
-+ }
-+ pri_error(ctrl, "\tERROR: %s\n", rose_error2str(error->code));
-
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ /* The DMS-100 switch apparently handles invoke_id as an invoke operation. */
-+ return;
-+ default:
-+ break;
-+ }
-
-+ apdu = pri_call_apdu_find(call, error->invoke_id);
-+ if (!apdu) {
-+ return;
-+ }
-+ msg.error = error;
-+ if (apdu->response.callback(APDU_CALLBACK_REASON_MSG_ERROR, ctrl, call, apdu, &msg)) {
-+ pri_call_apdu_delete(call, apdu);
-+ }
-+}
-
--int rose_reject_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
-+/*!
-+ * \brief Handle the ROSE result message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which the message came.
-+ * \param msgtype Q.931 message type ie is in.
-+ * \param ie Raw ie contents.
-+ * \param header Decoded facility header before ROSE.
-+ * \param result Decoded ROSE result message contents.
-+ *
-+ * \return Nothing
-+ */
-+void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
-+ const struct fac_extension_header *header, const struct rose_msg_result *result)
- {
-- int i = 0;
-- int problemtag = -1;
-- int problem = -1;
-- int invokeidvalue = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL;
-- char *problemtagstr, *problemstr;
--
-- do {
-- /* Invoke ID stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, invokeidvalue);
-- NEXT_COMPONENT(comp, i);
-+ struct apdu_event *apdu;
-+ union apdu_msg_data msg;
-
-- GET_COMPONENT(comp, i, vdata, len);
-- problemtag = comp->type;
-- problem = comp->data[0];
--
-- if (pri->switchtype == PRI_SWITCH_DMS100) {
-- switch (problemtag) {
-- case 0x80:
-- problemtagstr = "General problem";
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ /* The DMS-100 switch apparently handles invoke_id as an invoke operation. */
-+ switch (result->invoke_id) {
-+ case ROSE_DMS100_RLT_OPERATION_IND:
-+ if (result->operation != ROSE_DMS100_RLT_OperationInd) {
-+ pri_message(ctrl, "Invalid Operation value in return result! %s\n",
-+ rose_operation2str(result->operation));
- break;
-- case 0x81:
-- problemtagstr = "Invoke problem";
-- break;
-- case 0x82:
-- problemtagstr = "Return result problem";
-- break;
-- case 0x83:
-- problemtagstr = "Return error problem";
-- break;
-- default:
-- problemtagstr = "Unknown";
- }
-
-- switch (problem) {
-- case 0x00:
-- problemstr = "Unrecognized component";
-- break;
-- case 0x01:
-- problemstr = "Mistyped component";
-- break;
-- case 0x02:
-- problemstr = "Badly structured component";
-- break;
-- default:
-- problemstr = "Unknown";
-+ /* We have enough data to transfer the call */
-+ call->rlt_call_id = result->args.dms100.RLT_OperationInd.call_id;
-+ call->transferable = 1;
-+ break;
-+ case ROSE_DMS100_RLT_THIRD_PARTY:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "Successfully completed RLT transfer!\n");
- }
--
-- pri_error(pri, "ROSE REJECT:\n");
-- pri_error(pri, "\tINVOKE ID: 0x%X\n", invokeidvalue);
-- pri_error(pri, "\tPROBLEM TYPE: %s (0x%x)\n", problemtagstr, problemtag);
-- pri_error(pri, "\tPROBLEM: %s (0x%x)\n", problemstr, problem);
--
-- return 0;
-- } else {
-- pri_message(pri, "Unable to handle reject on switchtype %d!\n", pri->switchtype);
-- return -1;
-+ break;
-+ default:
-+ pri_message(ctrl, "Could not parse invoke of type %d!\n", result->invoke_id);
-+ break;
- }
-+ return;
-+ default:
-+ break;
-+ }
-
-- } while(0);
--
-- return -1;
-+ apdu = pri_call_apdu_find(call, result->invoke_id);
-+ if (!apdu) {
-+ return;
-+ }
-+ msg.result = result;
-+ if (apdu->response.callback(APDU_CALLBACK_REASON_MSG_RESULT, ctrl, call, apdu, &msg)) {
-+ pri_call_apdu_delete(call, apdu);
-+ }
- }
--int rose_return_error_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
-+
-+/*!
-+ * \brief Handle the ROSE invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param call Call leg from which the message came.
-+ * \param msgtype Q.931 message type ie is in.
-+ * \param ie Raw ie contents.
-+ * \param header Decoded facility header before ROSE.
-+ * \param invoke Decoded ROSE invoke message contents.
-+ *
-+ * \return Nothing
-+ */
-+void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
-+ const struct fac_extension_header *header, const struct rose_msg_invoke *invoke)
- {
-- int i = 0;
-- int errorvalue = -1;
-- int invokeidvalue = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL;
-- char *invokeidstr, *errorstr;
--
-- do {
-- /* Invoke ID stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, invokeidvalue);
-- NEXT_COMPONENT(comp, i);
-+ struct pri_subcommand *subcmd;
-+ struct q931_party_id party_id;
-+ struct q931_party_redirecting deflection;
-
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second component in return error is 0x%x\n");
-- ASN1_GET_INTEGER(comp, errorvalue);
-+ switch (invoke->operation) {
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_ActivationDiversion:
-+ break;
-+ case ROSE_ETSI_DeactivationDiversion:
-+ break;
-+ case ROSE_ETSI_ActivationStatusNotificationDiv:
-+ break;
-+ case ROSE_ETSI_DeactivationStatusNotificationDiv:
-+ break;
-+ case ROSE_ETSI_InterrogationDiversion:
-+ break;
-+ case ROSE_ETSI_DiversionInformation:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_CallDeflection:
-+ if (!PRI_MASTER(ctrl)->deflection_support) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_NotSubscribed);
-+ break;
-+ }
-+ if (!q931_master_pass_event(ctrl, call, msgtype)) {
-+ /* Some other user is further along to connecting than this call. */
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Div_IncomingCallAccepted);
-+ break;
-+ }
-+ if (call->master_call->deflection_in_progress) {
-+ /* Someone else is already doing a call deflection. */
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Div_RequestAlreadyAccepted);
-+ break;
-+ }
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ /*
-+ * ROSE_ERROR_Gen_ResourceUnavailable was not in the list of allowed codes,
-+ * but we will send it anyway.
-+ */
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_ResourceUnavailable);
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-
-- if (pri->switchtype == PRI_SWITCH_DMS100) {
-- switch (invokeidvalue) {
-- case RLT_OPERATION_IND:
-- invokeidstr = "RLT_OPERATION_IND";
-- break;
-- case RLT_THIRD_PARTY:
-- invokeidstr = "RLT_THIRD_PARTY";
-- break;
-- default:
-- invokeidstr = "Unknown";
-- }
-+ call->master_call->deflection_in_progress = 1;
-
-- switch (errorvalue) {
-- case 0x10:
-- errorstr = "RLT Bridge Fail";
-- break;
-- case 0x11:
-- errorstr = "RLT Call ID Not Found";
-- break;
-- case 0x12:
-- errorstr = "RLT Not Allowed";
-- break;
-- case 0x13:
-- errorstr = "RLT Switch Equip Congs";
-- break;
-- default:
-- errorstr = "Unknown";
-- }
-+ q931_party_redirecting_init(&deflection);
-
-- pri_error(pri, "ROSE RETURN ERROR:\n");
-- pri_error(pri, "\tOPERATION: %s\n", invokeidstr);
-- pri_error(pri, "\tERROR: %s\n", errorstr);
-+ /* Deflecting from the called address. */
-+ q931_party_address_to_id(&deflection.from, &call->called);
-+ if (invoke->args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present) {
-+ deflection.from.number.presentation =
-+ invoke->args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user
-+ ? PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED
-+ : PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ } else {
-+ deflection.from.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ }
-
-- return 0;
-+ /* Deflecting to the new address. */
-+ rose_copy_address_to_q931(ctrl, &deflection.to,
-+ &invoke->args.etsi.CallDeflection.deflection);
-+ deflection.to.number.presentation = deflection.from.number.presentation;
-+
-+ deflection.count = (call->redirecting.count < PRI_MAX_REDIRECTS)
-+ ? call->redirecting.count + 1 : PRI_MAX_REDIRECTS;
-+ deflection.reason = PRI_REDIR_DEFLECTION;
-+ if (deflection.count == 1) {
-+ deflection.orig_called = deflection.from;
-+ deflection.orig_reason = deflection.reason;
- } else {
-- pri_message(pri, "Unable to handle return error on switchtype %d!\n", pri->switchtype);
-+ deflection.orig_called = call->redirecting.orig_called;
-+ deflection.orig_reason = call->redirecting.orig_reason;
- }
-
-- } while(0);
--
-- return -1;
--}
-+ subcmd->cmd = PRI_SUBCMD_REROUTING;
-+ subcmd->u.rerouting.invoke_id = invoke->invoke_id;
-+ subcmd->u.rerouting.subscription_option = 3;/* notApplicable */
-+ q931_party_id_copy_to_pri(&subcmd->u.rerouting.caller, &call->local_id);
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.rerouting.deflection,
-+ &deflection);
-+ break;
-+ case ROSE_ETSI_CallRerouting:
-+ if (!PRI_MASTER(ctrl)->deflection_support) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_NotSubscribed);
-+ break;
-+ }
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_ResourceUnavailable);
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-
--int rose_return_result_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
--{
-- int i = 0;
-- int operationidvalue = -1;
-- int invokeidvalue = -1;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL;
--
-- do {
-- /* Invoke ID stuff */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, invokeidvalue);
-- NEXT_COMPONENT(comp, i);
-+ q931_party_redirecting_init(&deflection);
-
-- if (pri->switchtype == PRI_SWITCH_DMS100) {
-- switch (invokeidvalue) {
-- case RLT_THIRD_PARTY:
-- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed RLT transfer!\n");
-- return 0;
-- case RLT_OPERATION_IND:
-- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Received RLT_OPERATION_IND\n");
-- /* Have to take out the rlt_call_id */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Protocol error detected in parsing RLT_OPERATION_IND return result!\n");
-+ /* Rerouting from the last address. */
-+ rose_copy_presented_number_unscreened_to_q931(ctrl, &deflection.from.number,
-+ &invoke->args.etsi.CallRerouting.last_rerouting);
-
-- /* Traverse the contents of this sequence */
-- /* First is the Operation Value */
-- SUB_COMPONENT(comp, i);
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "RLT_OPERATION_IND should be of type ASN1_INTEGER!\n");
-- ASN1_GET_INTEGER(comp, operationidvalue);
-+ /* Rerouting to the new address. */
-+ rose_copy_address_to_q931(ctrl, &deflection.to,
-+ &invoke->args.etsi.CallRerouting.called_address);
-+ switch (invoke->args.etsi.CallRerouting.subscription_option) {
-+ default:
-+ case 0: /* noNotification */
-+ case 1: /* notificationWithoutDivertedToNr */
-+ deflection.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ case 2: /* notificationWithDivertedToNr */
-+ deflection.to.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ }
-
-- if (operationidvalue != RLT_OPERATION_IND) {
-- pri_message(pri, "Invalid Operation ID value (0x%x) in return result!\n", operationidvalue);
-- return -1;
-- }
-+ /* Calling party subaddress update. */
-+ party_id = call->local_id;
-
-- /* Next is the Call ID */
-- NEXT_COMPONENT(comp, i);
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_TAG_0, "Error check failed on Call ID!\n");
-- ASN1_GET_INTEGER(comp, call->rlt_call_id);
-- /* We have enough data to transfer the call */
-- call->transferable = 1;
-+ deflection.count = invoke->args.etsi.CallRerouting.rerouting_counter;
-+ deflection.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.etsi.CallRerouting.rerouting_reason);
-+ if (deflection.count == 1) {
-+ deflection.orig_called = deflection.from;
-+ deflection.orig_reason = deflection.reason;
-+ } else {
-+ deflection.orig_called = call->redirecting.orig_called;
-+ deflection.orig_reason = call->redirecting.orig_reason;
-+ }
-
-- return 0;
--
-- default:
-- pri_message(pri, "Could not parse invoke of type 0x%x!\n", invokeidvalue);
-- return -1;
-+ subcmd->cmd = PRI_SUBCMD_REROUTING;
-+ subcmd->u.rerouting.invoke_id = invoke->invoke_id;
-+ subcmd->u.rerouting.subscription_option =
-+ invoke->args.etsi.CallRerouting.subscription_option;
-+ q931_party_id_copy_to_pri(&subcmd->u.rerouting.caller, &party_id);
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.rerouting.deflection,
-+ &deflection);
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_InterrogateServedUserNumbers:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_DivertingLegInformation1:
-+ if (invoke->args.etsi.DivertingLegInformation1.diverted_to_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl, &party_id.number,
-+ &invoke->args.etsi.DivertingLegInformation1.diverted_to);
-+ /*
-+ * We set the presentation value since the sender cannot know the
-+ * presentation value preference of the destination party.
-+ */
-+ if (party_id.number.str[0]) {
-+ party_id.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ } else {
-+ party_id.number.presentation =
-+ PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
- }
-- } else if (pri->switchtype == PRI_SWITCH_QSIG) {
-- switch (invokeidvalue) {
-- case 0x13:
-- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed QSIG CF callRerouting!\n");
-- return 0;
-- }
- } else {
-- pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
-- return -1;
-+ q931_party_number_init(&party_id.number);
-+ party_id.number.valid = 1;
- }
-
-- } while(0);
--
-- return -1;
--}
-+ /*
-+ * Unless otherwise indicated by CONNECT, the divertedToNumber will be
-+ * the remote_id.number.
-+ */
-+ if (!call->connected_number_in_message) {
-+ call->remote_id.number = party_id.number;
-+ }
-
--int rose_invoke_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
--{
-- int i = 0;
-- int res = 0;
-- int operation_tag;
-- unsigned char *vdata = data;
-- struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
--
-- do {
-- /* Invoke ID stuff */
-- GET_COMPONENT(comp, i, vdata, len);
--#if 0
-- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
--#endif
-- invokeid = comp;
-- NEXT_COMPONENT(comp, i);
-+ /* divertedToNumber is put in redirecting.to.number */
-+ switch (invoke->args.etsi.DivertingLegInformation1.subscription_option) {
-+ default:
-+ case 0: /* noNotification */
-+ case 1: /* notificationWithoutDivertedToNr */
-+ q931_party_number_init(&call->redirecting.to.number);
-+ call->redirecting.to.number.valid = 1;
-+ call->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ case 2: /* notificationWithDivertedToNr */
-+ call->redirecting.to.number = party_id.number;
-+ break;
-+ }
-
-- /* Operation Tag */
-- GET_COMPONENT(comp, i, vdata, len);
--#if 0
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second ROSE component is of type 0x%x\n");
--#endif
-- operationid = comp;
-- ASN1_GET_INTEGER(comp, operation_tag);
-- NEXT_COMPONENT(comp, i);
-+ call->redirecting.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.etsi.DivertingLegInformation1.diversion_reason);
-+ if (call->redirecting.count < PRI_MAX_REDIRECTS) {
-+ ++call->redirecting.count;
-+ }
-+ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
-+ break;
-+ case ROSE_ETSI_DivertingLegInformation2:
-+ call->redirecting.state = Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3;
-+ call->redirecting.count =
-+ invoke->args.etsi.DivertingLegInformation2.diversion_counter;
-+ if (!call->redirecting.count) {
-+ /* To be safe, make sure that the count is non-zero. */
-+ call->redirecting.count = 1;
-+ }
-+ call->redirecting.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.etsi.DivertingLegInformation2.diversion_reason);
-
-- /* No argument - return with error */
-- if (i >= len)
-- return -1;
-+ /* divertingNr is put in redirecting.from.number */
-+ if (invoke->args.etsi.DivertingLegInformation2.diverting_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->redirecting.from.number,
-+ &invoke->args.etsi.DivertingLegInformation2.diverting);
-+ } else if (!call->redirecting_number_in_message) {
-+ q931_party_number_init(&call->redirecting.from.number);
-+ call->redirecting.from.number.valid = 1;
-+ }
-
-- /* Arguement Tag */
-- GET_COMPONENT(comp, i, vdata, len);
-- if (!comp->type)
-- return -1;
-+ call->redirecting.orig_reason = PRI_REDIR_UNKNOWN;
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " [ Handling operation %d ]\n", operation_tag);
-- switch (operation_tag) {
-- case SS_CNID_CALLINGNAME:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Handle Name display operation\n");
-- return rose_calling_name_decode(pri, call, comp, len-i);
-- case ROSE_CALL_TRANSFER_IDENTIFY:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferIdentify - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_ABANDON:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferAbandon - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_INITIATE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferInitiate - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_SETUP:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferSetup - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_ACTIVE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferActive - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_COMPLETE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- {
-- pri_message(pri, "ROSE %i: Handle CallTransferComplete\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ /* originalCalledNr is put in redirecting.orig_called.number */
-+ if (invoke->args.etsi.DivertingLegInformation2.original_called_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->redirecting.orig_called.number,
-+ &invoke->args.etsi.DivertingLegInformation2.original_called);
-+ } else {
-+ q931_party_number_init(&call->redirecting.orig_called.number);
-+ }
-+ break;
-+ case ROSE_ETSI_DivertingLegInformation3:
-+ /*
-+ * Unless otherwise indicated by CONNECT, this will be the
-+ * remote_id.number.presentation.
-+ */
-+ if (!invoke->args.etsi.DivertingLegInformation3.presentation_allowed_indicator) {
-+ call->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ if (!call->connected_number_in_message) {
-+ call->remote_id.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
- }
-- return rose_call_transfer_complete_decode(pri, call, comp, len-i);
-- case ROSE_CALL_TRANSFER_UPDATE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- {
-- pri_message(pri, "ROSE %i: Handle CallTransferUpdate\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+
-+ switch (call->redirecting.state) {
-+ case Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3:
-+ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
- }
-- return rose_call_transfer_update_decode(pri, call, comp, len-i);
-- case ROSE_SUBADDRESS_TRANSFER:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: SubaddressTransfer - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_DIVERTING_LEG_INFORMATION2:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: Handle CallingName\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return rose_diverting_leg_information2_decode(pri, call, comp, len-i);
-- case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC No Charging Info Available - not handled!", operation_tag);
-- dump_apdu (pri, comp->data, comp->len);
-- }
-- return -1;
-- case ROSE_AOC_CHARGING_REQUEST:
-- return aoc_aoce_charging_request_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
-- case ROSE_AOC_AOCS_CURRENCY:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-S Currency - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCS_SPECIAL_ARR:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-S Special Array - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCD_CURRENCY:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-D Currency - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCD_CHARGING_UNIT:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-D Charging Unit - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCE_CURRENCY:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-E Currency - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCE_CHARGING_UNIT:
-- return aoc_aoce_charging_unit_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
-- if (0) { /* the following function is currently not used - just to make the compiler happy */
-- aoc_aoce_charging_unit_encode(pri, call, call->aoc_units); /* use this function to forward the aoc-e on a bridged channel */
-- return 0;
-- }
-- case ROSE_AOC_IDENTIFICATION_OF_CHARGE:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC Identification Of Charge - not handled!", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case SS_ANFPR_PATHREPLACEMENT:
-- /* Clear Queue */
-- res = pri_call_apdu_queue_cleanup(call->bridged_call);
-- if (res) {
-- pri_message(pri, "Could not Clear queue ADPU\n");
-- return -1;
-- }
-- anfpr_pathreplacement_respond(pri, call, ie);
-- break;
-+ /* Setup redirecting subcommand */
-+ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
-+ &call->redirecting);
-+ break;
- default:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ break;
-+ }
-+ break;
-+ case ROSE_ETSI_ChargingRequest:
-+ /* Ignore messsage */
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_AOCSCurrency:
-+ break;
-+ case ROSE_ETSI_AOCSSpecialArr:
-+ break;
-+ case ROSE_ETSI_AOCDCurrency:
-+ break;
-+ case ROSE_ETSI_AOCDChargingUnit:
-+ break;
-+ case ROSE_ETSI_AOCECurrency:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_AOCEChargingUnit:
-+ call->aoc_units = 0;
-+ if (invoke->args.etsi.AOCEChargingUnit.type == 1
-+ && !invoke->args.etsi.AOCEChargingUnit.charging_unit.free_of_charge) {
-+ unsigned index;
-+
-+ for (index =
-+ invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.
-+ num_records; index--;) {
-+ if (!invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.
-+ list[index].not_available) {
-+ call->aoc_units +=
-+ invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.
-+ recorded.list[index].number_of_units;
-+ }
- }
-- return -1;
- }
-- } while(0);
--
-- return -1;
--}
-+ /* the following function is currently not used - just to make the compiler happy */
-+ if (0) {
-+ /* use this function to forward the aoc-e on a bridged channel */
-+ aoc_aoce_charging_unit_encode(ctrl, call, call->aoc_units);
-+ }
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ITU_IdentificationOfCharge:
-+ break;
-+#endif /* Not handled yet */
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_EctExecute:
-+ break;
-+ case ROSE_ETSI_ExplicitEctExecute:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_RequestSubaddress:
-+ /* Ignore since we are not handling subaddresses yet. */
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_SubaddressTransfer:
-+ break;
-+ case ROSE_ETSI_EctLinkIdRequest:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_ETSI_EctInform:
-+ /* redirectionNumber is put in remote_id.number */
-+ if (invoke->args.etsi.EctInform.redirection_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->remote_id.number, &invoke->args.etsi.EctInform.redirection);
-+ }
-+ if (!invoke->args.etsi.EctInform.status) {
-+ /* The remote party for the transfer has not answered yet. */
-+ call->incoming_ct_state = INCOMING_CT_STATE_EXPECT_CT_ACTIVE;
-+ } else {
-+ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
-+ }
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_ETSI_EctLoopTest:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_QSIG_CallingName:
-+ /* CallingName is put in remote_id.name */
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.CallingName.name);
-+ break;
-+ case ROSE_QSIG_CalledName:
-+ /* CalledName is put in remote_id.name */
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.CalledName.name);
-
--int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data)
--{
-- struct apdu_event *cur = NULL;
-- struct apdu_event *new_event = NULL;
-+ /* Setup connected line subcommand */
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-+ subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
-+ q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &call->remote_id);
-+ break;
-+ case ROSE_QSIG_ConnectedName:
-+ /* ConnectedName is put in remote_id.name */
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.ConnectedName.name);
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_BusyName:
-+ break;
-+#endif /* Not handled yet */
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_ChargeRequest:
-+ break;
-+ case ROSE_QSIG_GetFinalCharge:
-+ break;
-+ case ROSE_QSIG_AocFinal:
-+ break;
-+ case ROSE_QSIG_AocInterim:
-+ break;
-+ case ROSE_QSIG_AocRate:
-+ break;
-+ case ROSE_QSIG_AocComplete:
-+ break;
-+ case ROSE_QSIG_AocDivChargeReq:
-+ break;
-+#endif /* Not handled yet */
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_CallTransferIdentify:
-+ break;
-+ case ROSE_QSIG_CallTransferAbandon:
-+ break;
-+ case ROSE_QSIG_CallTransferInitiate:
-+ break;
-+ case ROSE_QSIG_CallTransferSetup:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_QSIG_CallTransferActive:
-+ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
-
-- if (!call || !messagetype || !apdu || (apdu_len < 1) || (apdu_len > 255))
-- return -1;
-+ /* connectedAddress is put in remote_id */
-+ rose_copy_presented_address_screened_to_q931(ctrl, &call->remote_id,
-+ &invoke->args.qsig.CallTransferActive.connected);
-
-- if (!(new_event = calloc(1, sizeof(*new_event)))) {
-- pri_error(call->pri, "!! Malloc failed!\n");
-- return -1;
-- }
-+ /* connectedName is put in remote_id.name */
-+ if (invoke->args.qsig.CallTransferActive.connected_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.CallTransferActive.connected_name);
-+ }
-+ break;
-+ case ROSE_QSIG_CallTransferComplete:
-+ /* redirectionNumber is put in remote_id.number */
-+ rose_copy_presented_number_screened_to_q931(ctrl, &call->remote_id.number,
-+ &invoke->args.qsig.CallTransferComplete.redirection);
-
-- new_event->message = messagetype;
-- new_event->callback = function;
-- new_event->data = data;
-- memcpy(new_event->apdu, apdu, apdu_len);
-- new_event->apdu_len = apdu_len;
--
-- if (call->apdus) {
-- cur = call->apdus;
-- while (cur->next) {
-- cur = cur->next;
-+ /* redirectionName is put in remote_id.name */
-+ if (invoke->args.qsig.CallTransferComplete.redirection_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
-+ &invoke->args.qsig.CallTransferComplete.redirection_name);
- }
-- cur->next = new_event;
-- } else
-- call->apdus = new_event;
-
-- return 0;
--}
-+ if (invoke->args.qsig.CallTransferComplete.call_status == 1) {
-+ /* The remote party for the transfer has not answered yet. */
-+ call->incoming_ct_state = INCOMING_CT_STATE_EXPECT_CT_ACTIVE;
-+ } else {
-+ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
-+ }
-+ break;
-+ case ROSE_QSIG_CallTransferUpdate:
-+ party_id = call->remote_id;
-
--int pri_call_apdu_queue_cleanup(q931_call *call)
--{
-- struct apdu_event *cur_event = NULL, *free_event = NULL;
-+ /* redirectionNumber is put in party_id.number */
-+ rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
-+ &invoke->args.qsig.CallTransferUpdate.redirection);
-
-- if (call && call->apdus) {
-- cur_event = call->apdus;
-- while (cur_event) {
-- /* TODO: callbacks, some way of giving return res on status of apdu */
-- free_event = cur_event;
-- cur_event = cur_event->next;
-- free(free_event);
-+ /* redirectionName is put in party_id.name */
-+ if (invoke->args.qsig.CallTransferUpdate.redirection_name_present) {
-+ rose_copy_name_to_q931(ctrl, &party_id.name,
-+ &invoke->args.qsig.CallTransferUpdate.redirection_name);
- }
-- call->apdus = NULL;
-- }
-
-- return 0;
--}
--
--int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
--{
-- if (!pri->sendfacility)
-- return 0;
--
-- if (pri->switchtype == PRI_SWITCH_QSIG) { /* For Q.SIG it does network and cpe operations */
-- if (call->redirectingnum[0])
-- rose_diverting_leg_information2_encode(pri, call);
-- add_callername_facility_ies(pri, call, 1);
-- return 0;
-- }
--
--#if 0
-- if (pri->localtype == PRI_NETWORK) {
-- switch (pri->switchtype) {
-- case PRI_SWITCH_NI2:
-- add_callername_facility_ies(pri, call, 0);
-+ if (q931_party_id_cmp(&party_id, &call->remote_id)) {
-+ /* The remote_id data has changed. */
-+ call->remote_id = party_id;
-+ switch (call->incoming_ct_state) {
-+ case INCOMING_CT_STATE_IDLE:
-+ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
- break;
- default:
- break;
-+ }
- }
-- return 0;
-- } else if (pri->localtype == PRI_CPE) {
-- switch (pri->switchtype) {
-- case PRI_SWITCH_NI2:
-- add_callername_facility_ies(pri, call, 1);
-- break;
-- default:
-- break;
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_SubaddressTransfer:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_QSIG_PathReplacement:
-+ anfpr_pathreplacement_respond(ctrl, call, ie);
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_ActivateDiversionQ:
-+ break;
-+ case ROSE_QSIG_DeactivateDiversionQ:
-+ break;
-+ case ROSE_QSIG_InterrogateDiversionQ:
-+ break;
-+ case ROSE_QSIG_CheckRestriction:
-+ break;
-+#endif /* Not handled yet */
-+ case ROSE_QSIG_CallRerouting:
-+ if (!PRI_MASTER(ctrl)->deflection_support) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_NotSubscribed);
-+ break;
- }
-- return 0;
-- }
--#else
-- if (pri->switchtype == PRI_SWITCH_NI2)
-- add_callername_facility_ies(pri, call, (pri->localtype == PRI_CPE));
--#endif
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ send_facility_error(ctrl, call, invoke->invoke_id,
-+ ROSE_ERROR_Gen_ResourceUnavailable);
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-
-- if ((pri->switchtype == PRI_SWITCH_DMS100) && (pri->localtype == PRI_CPE)) {
-- add_dms100_transfer_ability_apdu(pri, call);
-- }
-+ q931_party_redirecting_init(&deflection);
-
-+ /* Rerouting from the last address. */
-+ rose_copy_presented_number_unscreened_to_q931(ctrl, &deflection.from.number,
-+ &invoke->args.qsig.CallRerouting.last_rerouting);
-+ if (invoke->args.qsig.CallRerouting.redirecting_name_present) {
-+ rose_copy_name_to_q931(ctrl, &deflection.from.name,
-+ &invoke->args.qsig.CallRerouting.redirecting_name);
-+ }
-
-+ /* Rerouting to the new address. */
-+ rose_copy_address_to_q931(ctrl, &deflection.to,
-+ &invoke->args.qsig.CallRerouting.called);
-+ switch (invoke->args.qsig.CallRerouting.subscription_option) {
-+ default:
-+ case 0: /* noNotification */
-+ case 1: /* notificationWithoutDivertedToNr */
-+ deflection.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ case 2: /* notificationWithDivertedToNr */
-+ deflection.to.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ }
-
-- return 0;
-+ /* Calling party update. */
-+ party_id = call->local_id;
-+ rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
-+ &invoke->args.qsig.CallRerouting.calling);
-+ if (invoke->args.qsig.CallRerouting.calling_name_present) {
-+ rose_copy_name_to_q931(ctrl, &party_id.name,
-+ &invoke->args.qsig.CallRerouting.calling_name);
-+ }
-+
-+ deflection.count = invoke->args.qsig.CallRerouting.diversion_counter;
-+ deflection.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.CallRerouting.rerouting_reason);
-+
-+ /* Original called party update. */
-+ if (deflection.count == 1) {
-+ deflection.orig_called = deflection.from;
-+ deflection.orig_reason = deflection.reason;
-+ } else {
-+ deflection.orig_called = call->redirecting.orig_called;
-+ deflection.orig_reason = call->redirecting.orig_reason;
-+ }
-+ if (invoke->args.qsig.CallRerouting.original_called_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &deflection.orig_called.number,
-+ &invoke->args.qsig.CallRerouting.original_called);
-+ }
-+ if (invoke->args.qsig.CallRerouting.original_called_name_present) {
-+ rose_copy_name_to_q931(ctrl, &deflection.orig_called.name,
-+ &invoke->args.qsig.CallRerouting.original_called_name);
-+ }
-+ if (invoke->args.qsig.CallRerouting.original_rerouting_reason_present) {
-+ deflection.orig_reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.CallRerouting.original_rerouting_reason);
-+ }
-+
-+ subcmd->cmd = PRI_SUBCMD_REROUTING;
-+ subcmd->u.rerouting.invoke_id = invoke->invoke_id;
-+ subcmd->u.rerouting.subscription_option =
-+ invoke->args.qsig.CallRerouting.subscription_option;
-+ q931_party_id_copy_to_pri(&subcmd->u.rerouting.caller, &party_id);
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.rerouting.deflection,
-+ &deflection);
-+ break;
-+ case ROSE_QSIG_DivertingLegInformation1:
-+ q931_party_number_init(&party_id.number);
-+ rose_copy_number_to_q931(ctrl, &party_id.number,
-+ &invoke->args.qsig.DivertingLegInformation1.nominated_number);
-+ if (party_id.number.str[0]) {
-+ party_id.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ }
-+
-+ /*
-+ * Unless otherwise indicated by CONNECT, the nominatedNr will be
-+ * the remote_id.number.
-+ */
-+ if (!call->connected_number_in_message) {
-+ call->remote_id.number = party_id.number;
-+ }
-+
-+ /* nominatedNr is put in redirecting.to.number */
-+ switch (invoke->args.qsig.DivertingLegInformation1.subscription_option) {
-+ default:
-+ case QSIG_NO_NOTIFICATION:
-+ case QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR:
-+ q931_party_number_init(&call->redirecting.to.number);
-+ call->redirecting.to.number.valid = 1;
-+ call->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+ case QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR:
-+ call->redirecting.to.number = party_id.number;
-+ break;
-+ }
-+
-+ call->redirecting.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.DivertingLegInformation1.diversion_reason);
-+ if (call->redirecting.count < PRI_MAX_REDIRECTS) {
-+ ++call->redirecting.count;
-+ }
-+ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
-+ break;
-+ case ROSE_QSIG_DivertingLegInformation2:
-+ call->redirecting.state = Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3;
-+ call->redirecting.count =
-+ invoke->args.qsig.DivertingLegInformation2.diversion_counter;
-+ if (!call->redirecting.count) {
-+ /* To be safe, make sure that the count is non-zero. */
-+ call->redirecting.count = 1;
-+ }
-+ call->redirecting.reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.DivertingLegInformation2.diversion_reason);
-+
-+ /* divertingNr is put in redirecting.from.number */
-+ if (invoke->args.qsig.DivertingLegInformation2.diverting_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->redirecting.from.number,
-+ &invoke->args.qsig.DivertingLegInformation2.diverting);
-+ } else if (!call->redirecting_number_in_message) {
-+ q931_party_number_init(&call->redirecting.from.number);
-+ call->redirecting.from.number.valid = 1;
-+ }
-+
-+ /* redirectingName is put in redirecting.from.name */
-+ if (invoke->args.qsig.DivertingLegInformation2.redirecting_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->redirecting.from.name,
-+ &invoke->args.qsig.DivertingLegInformation2.redirecting_name);
-+ } else {
-+ q931_party_name_init(&call->redirecting.from.name);
-+ }
-+
-+ call->redirecting.orig_reason = PRI_REDIR_UNKNOWN;
-+ if (invoke->args.qsig.DivertingLegInformation2.original_diversion_reason_present) {
-+ call->redirecting.orig_reason = redirectingreason_for_q931(ctrl,
-+ invoke->args.qsig.DivertingLegInformation2.original_diversion_reason);
-+ }
-+
-+ /* originalCalledNr is put in redirecting.orig_called.number */
-+ if (invoke->args.qsig.DivertingLegInformation2.original_called_present) {
-+ rose_copy_presented_number_unscreened_to_q931(ctrl,
-+ &call->redirecting.orig_called.number,
-+ &invoke->args.qsig.DivertingLegInformation2.original_called);
-+ } else {
-+ q931_party_number_init(&call->redirecting.orig_called.number);
-+ }
-+
-+ /* originalCalledName is put in redirecting.orig_called.name */
-+ if (invoke->args.qsig.DivertingLegInformation2.original_called_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->redirecting.orig_called.name,
-+ &invoke->args.qsig.DivertingLegInformation2.original_called_name);
-+ } else {
-+ q931_party_name_init(&call->redirecting.orig_called.name);
-+ }
-+ break;
-+ case ROSE_QSIG_DivertingLegInformation3:
-+ /*
-+ * Unless otherwise indicated by CONNECT, this will be the
-+ * remote_id.number.presentation.
-+ */
-+ if (!invoke->args.qsig.DivertingLegInformation3.presentation_allowed_indicator) {
-+ call->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ if (!call->connected_number_in_message) {
-+ call->remote_id.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ }
-+ }
-+
-+ /* redirectionName is put in redirecting.to.name */
-+ if (invoke->args.qsig.DivertingLegInformation3.redirection_name_present) {
-+ rose_copy_name_to_q931(ctrl, &call->redirecting.to.name,
-+ &invoke->args.qsig.DivertingLegInformation3.redirection_name);
-+ if (!invoke->args.qsig.DivertingLegInformation3.presentation_allowed_indicator) {
-+ call->redirecting.to.name.presentation = PRI_PRES_RESTRICTED;
-+ }
-+ } else {
-+ q931_party_name_init(&call->redirecting.to.name);
-+ }
-+
-+ switch (call->redirecting.state) {
-+ case Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3:
-+ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (!subcmd) {
-+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
-+ break;
-+ }
-+ /* Setup redirecting subcommand */
-+ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
-+ &call->redirecting);
-+ break;
-+ default:
-+ break;
-+ }
-+ break;
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_CfnrDivertedLegFailed:
-+ break;
-+#endif /* Not handled yet */
-+#if 0 /* Not handled yet */
-+ case ROSE_QSIG_MWIActivate:
-+ break;
-+ case ROSE_QSIG_MWIDeactivate:
-+ break;
-+ case ROSE_QSIG_MWIInterrogate:
-+ break;
-+#endif /* Not handled yet */
-+ default:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "!! ROSE invoke operation not handled! %s\n",
-+ rose_operation2str(invoke->operation));
-+ }
-+ break;
-+ }
- }
--
-Index: pri_facility.h
-===================================================================
---- a/pri_facility.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_facility.h (.../branches/1.4) (revision 1357)
-@@ -31,123 +31,21 @@
- #define _PRI_FACILITY_H
- #include "pri_q931.h"
-
-+/* Forward declare some structs */
-+struct fac_extension_header;
-+struct rose_msg_invoke;
-+struct rose_msg_result;
-+struct rose_msg_error;
-+struct rose_msg_reject;
-+
- /* Protocol Profile field */
-+#define Q932_PROTOCOL_MASK 0x1F
- #define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
- #define Q932_PROTOCOL_CMIP 0x12 /* Q.941 */
- #define Q932_PROTOCOL_ACSE 0x13 /* X.217 & X.227 */
- #define Q932_PROTOCOL_GAT 0x16
- #define Q932_PROTOCOL_EXTENSIONS 0x1F
-
--/* Argument values */
--#define ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE 0x80
--#define ROSE_NAME_PRESENTATION_RESTRICTED_NULL 0x87
--#define ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED 0xA1
--#define ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE 0xA2
--#define ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED 0xA3
--#define ROSE_NAME_NOT_AVAIL 0x84
--
--/* Component types */
--#define COMP_TYPE_INTERPRETATION 0x8B
--#define COMP_TYPE_NETWORK_PROTOCOL_PROFILE 0x92
--#define COMP_TYPE_INVOKE 0xA1
--#define COMP_TYPE_RETURN_RESULT 0xA2
--#define COMP_TYPE_RETURN_ERROR 0xA3
--#define COMP_TYPE_REJECT 0xA4
--#define COMP_TYPE_NFE 0xAA
--
--/* Operation ID values */
--/* Q.952.7 (ECMA-178) ROSE operations (Transfer) */
--#define ROSE_CALL_TRANSFER_IDENTIFY 7
--#define ROSE_CALL_TRANSFER_ABANDON 8
--#define ROSE_CALL_TRANSFER_INITIATE 9
--#define ROSE_CALL_TRANSFER_SETUP 10
--#define ROSE_CALL_TRANSFER_ACTIVE 11
--#define ROSE_CALL_TRANSFER_COMPLETE 12
--#define ROSE_CALL_TRANSFER_UPDATE 13
--#define ROSE_SUBADDRESS_TRANSFER 14
--/* Q.952 ROSE operations (Diverting) */
--#define ROSE_DIVERTING_LEG_INFORMATION1 18
--#define ROSE_DIVERTING_LEG_INFORMATION2 0x15
--#define ROSE_DIVERTING_LEG_INFORMATION3 19
--/* Q.956 ROSE operations (Advice Of Charge) */
--#define ROSE_AOC_NO_CHARGING_INFO_AVAILABLE 26
--#define ROSE_AOC_CHARGING_REQUEST 30
--#define ROSE_AOC_AOCS_CURRENCY 31
--#define ROSE_AOC_AOCS_SPECIAL_ARR 32
--#define ROSE_AOC_AOCD_CURRENCY 33
--#define ROSE_AOC_AOCD_CHARGING_UNIT 34
--#define ROSE_AOC_AOCE_CURRENCY 35
--#define ROSE_AOC_AOCE_CHARGING_UNIT 36
--#define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
--/* Q.SIG operations */
--#define SS_CNID_CALLINGNAME 0
--#define SS_ANFPR_PATHREPLACEMENT 4
--#define SS_DIVERTING_LEG_INFORMATION2 21
--#define SS_MWI_ACTIVATE 80
--#define SS_MWI_DEACTIVATE 81
--#define SS_MWI_INTERROGATE 82
--
--/* ROSE definitions and data structures */
--#define INVOKE_IDENTIFIER 0x02
--#define INVOKE_LINKED_IDENTIFIER 0x80
--#define INVOKE_NULL_IDENTIFIER __USE_ASN1_NULL
--
--/* ASN.1 Identifier Octet - Data types */
--#define ASN1_TYPE_MASK 0x1f
--#define ASN1_BOOLEAN 0x01
--#define ASN1_INTEGER 0x02
--#define ASN1_BITSTRING 0x03
--#define ASN1_OCTETSTRING 0x04
--#define ASN1_NULL 0x05
--#define ASN1_OBJECTIDENTIFIER 0x06
--#define ASN1_OBJECTDESCRIPTOR 0x07
--#define ASN1_EXTERN 0x08
--#define ASN1_REAL 0x09
--#define ASN1_ENUMERATED 0x0a
--#define ASN1_EMBEDDEDPDV 0x0b
--#define ASN1_UTF8STRING 0x0c
--#define ASN1_RELATIVEOBJECTID 0x0d
--/* 0x0e & 0x0f are reserved for future ASN.1 editions */
--#define ASN1_SEQUENCE 0x10
--#define ASN1_SET 0x11
--#define ASN1_NUMERICSTRING 0x12
--#define ASN1_PRINTABLESTRING 0x13
--#define ASN1_TELETEXSTRING 0x14
--#define ASN1_IA5STRING 0x16
--#define ASN1_UTCTIME 0x17
--#define ASN1_GENERALIZEDTIME 0x18
--
--/* ASN.1 Identifier Octet - Tags */
--#define ASN1_TAG_0 0x00
--#define ASN1_TAG_1 0x01
--#define ASN1_TAG_2 0x02
--#define ASN1_TAG_3 0x03
--#define ASN1_TAG_4 0x04
--#define ASN1_TAG_5 0x05
--#define ASN1_TAG_6 0x06
--#define ASN1_TAG_7 0x07
--#define ASN1_TAG_8 0x08
--#define ASN1_TAG_9 0x09
--
--/* ASN.1 Identifier Octet - Primitive/Constructor Bit */
--#define ASN1_PC_MASK 0x20
--#define ASN1_PRIMITIVE 0x00
--#define ASN1_CONSTRUCTOR 0x20
--
--/* ASN.1 Identifier Octet - Clan Bits */
--#define ASN1_CLAN_MASK 0xc0
--#define ASN1_UNIVERSAL 0x00
--#define ASN1_APPLICATION 0x40
--#define ASN1_CONTEXT_SPECIFIC 0x80
--#define ASN1_PRIVATE 0xc0
--
--/* ASN.1 Length masks */
--#define ASN1_LEN_INDEF 0x80
--
--
--#define INVOKE_OPERATION_INT __USE_ASN1_INTEGER
--#define INVOKE_OBJECT_ID __USE_ASN1_OBJECTIDENTIFIER
--
- /* Q.952 Divert cause */
- #define Q952_DIVERT_REASON_UNKNOWN 0x00
- #define Q952_DIVERT_REASON_CFU 0x01
-@@ -169,138 +67,112 @@
- #define Q932_TON_SUBSCRIBER 0x04
- #define Q932_TON_ABBREVIATED 0x06
-
--/* RLT related Operations */
--#define RLT_SERVICE_ID 0x3e
--#define RLT_OPERATION_IND 0x01
--#define RLT_THIRD_PARTY 0x02
-+/* Q.SIG Subscription Option. Listed in ECMA-174 */
-+#define QSIG_NO_NOTIFICATION 0x00
-+#define QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR 0x01
-+#define QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR 0x02
-
--struct rose_component {
-- u_int8_t type;
-- u_int8_t len;
-- u_int8_t data[0];
-+/*! Reasons an APDU callback is called. */
-+enum APDU_CALLBACK_REASON {
-+ /*!
-+ * \brief Send setup error. Abort and cleanup.
-+ * \note The message may or may not actually get sent.
-+ * \note The callback cannot generate an event subcmd.
-+ * \note The callback should not send messages. Out of order messages will result.
-+ */
-+ APDU_CALLBACK_REASON_ERROR,
-+ /*!
-+ * \brief Abort and cleanup.
-+ * \note The APDU queue is being destroyed.
-+ * \note The callback cannot generate an event subcmd.
-+ * \note The callback cannot send messages as the call is likely being destroyed.
-+ */
-+ APDU_CALLBACK_REASON_CLEANUP,
-+ /*!
-+ * \brief Timeout waiting for responses to the message.
-+ * \note The callback can generate an event subcmd.
-+ * \note The callback can send messages.
-+ */
-+ APDU_CALLBACK_REASON_TIMEOUT,
-+ /*!
-+ * \brief Received a facility response message.
-+ * \note The callback can generate an event subcmd.
-+ * \note The callback can send messages.
-+ */
-+ APDU_CALLBACK_REASON_MSG_RESULT,
-+ /*!
-+ * \brief Received a facility error message.
-+ * \note The callback can generate an event subcmd.
-+ * \note The callback can send messages.
-+ */
-+ APDU_CALLBACK_REASON_MSG_ERROR,
-+ /*!
-+ * \brief Received a facility reject message.
-+ * \note The callback can generate an event subcmd.
-+ * \note The callback can send messages.
-+ */
-+ APDU_CALLBACK_REASON_MSG_REJECT,
- };
-
--#if 1
-- #define GET_COMPONENT(component, idx, ptr, length) \
-- if ((idx)+2 > (length)) \
-- break; \
-- (component) = (struct rose_component*)&((ptr)[idx]); \
-- if ((idx)+(component)->len+2 > (length)) { \
-- if ((component)->len != ASN1_LEN_INDEF) \
-- pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
-- }
--#else /* Debugging */
-- #define GET_COMPONENT(component, idx, ptr, length) \
-- if ((idx)+2 > (length)) \
-- break; \
-- (component) = (struct rose_component*)&((ptr)[idx]); \
-- if ((idx)+(component)->len+2 > (length)) { \
-- if ((component)->len != 128) \
-- pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
-- } \
-- pri_message(pri, "XX %s:%d Got component %d (0x%02X), length %d\n", __FUNCTION__, __LINE__, (component)->type, (component)->type, (component)->len); \
-- if ((component)->len > 0) { \
-- int zzz; \
-- pri_message(pri, "XX Data:"); \
-- for (zzz = 0; zzz < (component)->len; ++zzz) \
-- pri_message(pri, " %02X", (component)->data[zzz]); \
-- pri_message(pri, "\n"); \
-- }
--#endif
-+union apdu_msg_data {
-+ const struct rose_msg_result *result;
-+ const struct rose_msg_error *error;
-+ const struct rose_msg_reject *reject;
-+};
-
--#define NEXT_COMPONENT(component, idx) \
-- (idx) += (component)->len + 2
-+union apdu_callback_param {
-+ void *ptr;
-+ long value;
-+ char pad[8];
-+};
-
--#define SUB_COMPONENT(component, idx) \
-- (idx) += 2
-+struct apdu_callback_data {
-+ /*! APDU invoke id to match with any response messages. (Result/Error/Reject) */
-+ int invoke_id;
-+ /*!
-+ * \brief Time to wait for responses to APDU in ms.
-+ * \note Set to 0 if send the message only.
-+ * \note Set to less than 0 for PRI_TIMER_T_RESPONSE time.
-+ */
-+ int timeout_time;
-+ /*!
-+ * \brief APDU callback function.
-+ *
-+ * \param reason Reason callback is called.
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param apdu APDU queued entry. Do not change!
-+ * \param msg APDU response message data. (NULL if was not the reason called.)
-+ *
-+ * \note
-+ * A callback must be supplied if the sender cares about any APDU_CALLBACK_REASON.
-+ *
-+ * \return TRUE if no more responses are expected.
-+ */
-+ int (*callback)(enum APDU_CALLBACK_REASON reason, struct pri *ctrl, struct q931_call *call, struct apdu_event *apdu, const union apdu_msg_data *msg);
-+ /*! \brief Sender data for the callback function to identify the particular APDU. */
-+ union apdu_callback_param user;
-+};
-
--#define CHECK_COMPONENT(component, comptype, message) \
-- if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \
-- pri_message(pri, (message), (component)->type); \
-- asn1_dump(pri, (component), (component)->len+2); \
-- break; \
-- }
--
--#define ASN1_GET_INTEGER(component, variable) \
-- do { \
-- int comp_idx; \
-- (variable) = 0; \
-- for (comp_idx = 0; comp_idx < (component)->len; ++comp_idx) \
-- (variable) = ((variable) << 8) | (component)->data[comp_idx]; \
-- } while (0)
-+struct apdu_event {
-+ /*! Linked list pointer */
-+ struct apdu_event *next;
-+ /*! TRUE if this APDU has been sent. */
-+ int sent;
-+ /*! What message to send the ADPU in */
-+ int message;
-+ /*! Sender supplied information to handle APDU response messages. */
-+ struct apdu_callback_data response;
-+ /*! Q.931 call leg. (Needed for the APDU timeout.) */
-+ struct q931_call *call;
-+ /*! Response timeout timer. */
-+ int timer;
-+ /*! Length of ADPU */
-+ int apdu_len;
-+ /*! ADPU to send */
-+ unsigned char apdu[255];
-+};
-
--#define ASN1_FIXUP_LEN(component, size) \
-- do { \
-- if ((component)->len == ASN1_LEN_INDEF) \
-- size += 2; \
-- } while (0)
--
--#define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \
-- do { \
-- (component) = (struct rose_component *)&((ptr)[(idx)]); \
-- (component)->type = (comptype); \
-- (component)->len = 0; \
-- (idx) += 2; \
-- } while (0)
--
--#define ASN1_ADD_BYTECOMP(component, comptype, ptr, idx, value) \
-- do { \
-- (component) = (struct rose_component *)&((ptr)[(idx)]); \
-- (component)->type = (comptype); \
-- (component)->len = 1; \
-- (component)->data[0] = (value); \
-- (idx) += 3; \
-- } while (0)
--
--#define ASN1_ADD_WORDCOMP(component, comptype, ptr, idx, value) \
-- do { \
-- int __val = (value); \
-- int __i = 0; \
-- (component) = (struct rose_component *)&((ptr)[(idx)]); \
-- (component)->type = (comptype); \
-- if ((__val >> 24)) \
-- (component)->data[__i++] = (__val >> 24) & 0xff; \
-- if ((__val >> 16)) \
-- (component)->data[__i++] = (__val >> 16) & 0xff; \
-- if ((__val >> 8)) \
-- (component)->data[__i++] = (__val >> 8) & 0xff; \
-- (component)->data[__i++] = __val & 0xff; \
-- (component)->len = __i; \
-- (idx) += 2 + __i; \
-- } while (0)
--
--#define ASN1_PUSH(stack, stackpointer, component) \
-- (stack)[(stackpointer)++] = (component)
--
--#define ASN1_FIXUP(stack, stackpointer, data, idx) \
-- do { \
-- --(stackpointer); \
-- (stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \
-- } while (0)
--
--/* Decoder for the invoke ROSE component */
--int rose_invoke_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
--
--/* Decoder for the return result ROSE component */
--int rose_return_result_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
--
--/* Decoder for the return error ROSE component */
--int rose_return_error_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
--
--/* Decoder for the reject ROSE component */
--int rose_reject_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
--
--int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
--
--int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
--
--/* Get Name types from ASN.1 */
--int asn1_name_decode(void * data, int len, char *namebuf, int buflen);
--
--int typeofnumber_from_q931(struct pri *pri, int ton);
--
--int redirectingreason_from_q931(struct pri *pri, int redirectingreason);
--
- /* Queues an MWI apdu on a the given call */
- int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
-
-@@ -310,21 +182,31 @@
- int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
-
- int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason);
-+int send_reroute_request(struct pri *ctrl, q931_call *call, const struct q931_party_id *caller, const struct q931_party_redirecting *deflection, int subscription_option);
-
- /* starts a QSIG Path Replacement */
- int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
-
--/* Use this function to queue a facility-IE born APDU onto a call
-- * call is the call to use, messagetype is any one of the Q931 messages,
-- * apdu is the apdu data, apdu_len is the length of the apdu data */
--int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data);
-+int send_call_transfer_complete(struct pri *pri, q931_call *call, int call_status);
-
--/* Used by q931.c to cleanup the apdu queue upon destruction of a call */
--int pri_call_apdu_queue_cleanup(q931_call *call);
-+int rose_diverting_leg_information1_encode(struct pri *pri, q931_call *call);
-+int rose_diverting_leg_information3_encode(struct pri *pri, q931_call *call, int messagetype);
-
-+int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype);
-+int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
-+
-+int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len, struct apdu_callback_data *response);
-+void pri_call_apdu_queue_cleanup(q931_call *call);
-+void pri_call_apdu_delete(struct q931_call *call, struct apdu_event *doomed);
-+
- /* Adds the "standard" APDUs to a call */
- int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
-
--int asn1_dump(struct pri *pri, void *comp, int len);
-+void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1, const unsigned char *end);
-
-+void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_invoke *invoke);
-+void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_result *result);
-+void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_error *error);
-+void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_reject *reject);
-+
- #endif /* _PRI_FACILITY_H */
-Index: libpri.h
-===================================================================
---- a/libpri.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/libpri.h (.../branches/1.4) (revision 1357)
-@@ -26,7 +26,14 @@
- * provided with that copy of Asterisk, instead of the license
- * terms granted here.
- */
--
-+
-+/*
-+ * NOTE:
-+ * All new global identifiers that are added to this file MUST be
-+ * prefixed with PRI_ or pri_ to indicate that they are part of this
-+ * library and to reduce potential naming conflicts.
-+ */
-+
- #ifndef _LIBPRI_H
- #define _LIBPRI_H
-
-@@ -73,7 +80,8 @@
- #define PRI_EVENT_ANSWER 8 /* Call has been answered (CONNECT) */
- #define PRI_EVENT_HANGUP_ACK 9 /* Call hangup has been acknowledged */
- #define PRI_EVENT_RESTART_ACK 10 /* Restart complete on a given channel (RESTART_ACKNOWLEDGE) */
--#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility */
-+#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility (DEPRECATED) */
-+#define PRI_EVENT_FACILITY 11 /* Facility received (FACILITY) */
- #define PRI_EVENT_INFO_RECEIVED 12 /* Additional info (digits) received (INFORMATION) */
- #define PRI_EVENT_PROCEEDING 13 /* When we get CALL_PROCEEDING */
- #define PRI_EVENT_SETUP_ACK 14 /* When we get SETUP_ACKNOWLEDGE */
-@@ -81,6 +89,14 @@
- #define PRI_EVENT_NOTIFY 16 /* Notification received (NOTIFY) */
- #define PRI_EVENT_PROGRESS 17 /* When we get PROGRESS */
- #define PRI_EVENT_KEYPAD_DIGIT 18 /* When we receive during ACTIVE state (INFORMATION) */
-+#define PRI_EVENT_SERVICE 19 /* SERVICE maintenance message */
-+#define PRI_EVENT_SERVICE_ACK 20 /* SERVICE maintenance acknowledgement message */
-+#define PRI_EVENT_HOLD 21 /* HOLD request received */
-+#define PRI_EVENT_HOLD_ACK 22 /* HOLD_ACKNOWLEDGE received */
-+#define PRI_EVENT_HOLD_REJ 23 /* HOLD_REJECT received */
-+#define PRI_EVENT_RETRIEVE 24 /* RETRIEVE request received */
-+#define PRI_EVENT_RETRIEVE_ACK 25 /* RETRIEVE_ACKNOWLEDGE received */
-+#define PRI_EVENT_RETRIEVE_REJ 26 /* RETRIEVE_REJECT received */
-
- /* Simple states */
- #define PRI_STATE_DOWN 0
-@@ -101,13 +117,13 @@
- #define PRI_PROG_CALLER_RETURNED_TO_ISDN (1 << 9)
-
- /* Numbering plan identifier */
--#define PRI_NPI_UNKNOWN 0x0
--#define PRI_NPI_E163_E164 0x1
--#define PRI_NPI_X121 0x3
--#define PRI_NPI_F69 0x4
--#define PRI_NPI_NATIONAL 0x8
--#define PRI_NPI_PRIVATE 0x9
--#define PRI_NPI_RESERVED 0xF
-+#define PRI_NPI_UNKNOWN 0x0 /*!< Unknown numbering plan */
-+#define PRI_NPI_E163_E164 0x1 /*!< ISDN/telephony numbering plan (public) */
-+#define PRI_NPI_X121 0x3 /*!< Data numbering plan */
-+#define PRI_NPI_F69 0x4 /*!< Telex numbering plan */
-+#define PRI_NPI_NATIONAL 0x8 /*!< National standard numbering plan */
-+#define PRI_NPI_PRIVATE 0x9 /*!< Private numbering plan */
-+#define PRI_NPI_RESERVED 0xF /*!< Reserved for extension */
-
- /* Type of number */
- #define PRI_TON_UNKNOWN 0x0
-@@ -135,16 +151,49 @@
- #define PRI_UNKNOWN 0x0
-
- /* Presentation */
--#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
--#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
--#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
--#define PRES_ALLOWED_NETWORK_NUMBER 0x03
--#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
--#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
--#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
--#define PRES_PROHIB_NETWORK_NUMBER 0x23
--#define PRES_NUMBER_NOT_AVAILABLE 0x43
-+#define PRI_PRES_NUMBER_TYPE 0x03
-+#define PRI_PRES_USER_NUMBER_UNSCREENED 0x00
-+#define PRI_PRES_USER_NUMBER_PASSED_SCREEN 0x01
-+#define PRI_PRES_USER_NUMBER_FAILED_SCREEN 0x02
-+#define PRI_PRES_NETWORK_NUMBER 0x03
-
-+#define PRI_PRES_RESTRICTION 0x60
-+#define PRI_PRES_ALLOWED 0x00
-+#define PRI_PRES_RESTRICTED 0x20
-+#define PRI_PRES_UNAVAILABLE 0x40
-+#define PRI_PRES_RESERVED 0x60
-+
-+#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED \
-+ (PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED)
-+
-+#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN \
-+ (PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_PASSED_SCREEN)
-+
-+#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN \
-+ (PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_FAILED_SCREEN)
-+
-+#define PRES_ALLOWED_NETWORK_NUMBER \
-+ (PRI_PRES_ALLOWED | PRI_PRES_NETWORK_NUMBER)
-+
-+#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED \
-+ (PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED)
-+
-+#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN \
-+ (PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_PASSED_SCREEN)
-+
-+#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN \
-+ (PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_FAILED_SCREEN)
-+
-+#define PRES_PROHIB_NETWORK_NUMBER \
-+ (PRI_PRES_RESTRICTED | PRI_PRES_NETWORK_NUMBER)
-+
-+#define PRES_NUMBER_NOT_AVAILABLE \
-+ (PRI_PRES_UNAVAILABLE | PRI_PRES_NETWORK_NUMBER)
-+
-+/* Reverse Charging Indication */
-+#define PRI_REVERSECHARGE_NONE -1
-+#define PRI_REVERSECHARGE_REQUESTED 1
-+
- /* Causes for disconnection */
- #define PRI_CAUSE_UNALLOCATED 1
- #define PRI_CAUSE_NO_ROUTE_TRANSIT_NET 2 /* !Q.SIG */
-@@ -157,6 +206,7 @@
- #define PRI_CAUSE_NO_ANSWER 19
- #define PRI_CAUSE_CALL_REJECTED 21
- #define PRI_CAUSE_NUMBER_CHANGED 22
-+#define PRI_CAUSE_NONSELECTED_USER_CLEARING 26
- #define PRI_CAUSE_DESTINATION_OUT_OF_ORDER 27
- #define PRI_CAUSE_INVALID_NUMBER_FORMAT 28
- #define PRI_CAUSE_FACILITY_REJECTED 29 /* !Q.SIG */
-@@ -169,6 +219,7 @@
- #define PRI_CAUSE_ACCESS_INFO_DISCARDED 43 /* !Q.SIG */
- #define PRI_CAUSE_REQUESTED_CHAN_UNAVAIL 44
- #define PRI_CAUSE_PRE_EMPTED 45 /* !Q.SIG */
-+#define PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED 47
- #define PRI_CAUSE_FACILITY_NOT_SUBSCRIBED 50 /* !Q.SIG */
- #define PRI_CAUSE_OUTGOING_CALL_BARRED 52 /* !Q.SIG */
- #define PRI_CAUSE_INCOMING_CALL_BARRED 54 /* !Q.SIG */
-@@ -259,8 +310,8 @@
- #define PRI_RATE_ADAPT_ASYNC 0x40
-
- /* Notifications */
--#define PRI_NOTIFY_USER_SUSPENDED 0x00 /* User suspended */
--#define PRI_NOTIFY_USER_RESUMED 0x01 /* User resumed */
-+#define PRI_NOTIFY_USER_SUSPENDED 0x00 /* User suspended (Q.931) (Call is placed on hold) */
-+#define PRI_NOTIFY_USER_RESUMED 0x01 /* User resumed (Q.931) (Call is taken off hold) */
- #define PRI_NOTIFY_BEARER_CHANGE 0x02 /* Bearer service change (DSS1) */
- #define PRI_NOTIFY_ASN1_COMPONENT 0x03 /* ASN.1 encoded component (DSS1) */
- #define PRI_NOTIFY_COMPLETION_DELAY 0x04 /* Call completion delay */
-@@ -275,12 +326,12 @@
- #define PRI_NOTIFY_CONF_OTHER_DISCONNECTED 0x4a /* Other party disconnected */
- #define PRI_NOTIFY_CONF_FLOATING 0x4b /* Conference floating */
- #define PRI_NOTIFY_WAITING_CALL 0x60 /* Call is waiting call */
--#define PRI_NOTIFY_DIVERSION_ACTIVATED 0x68 /* Diversion activated (DSS1) */
--#define PRI_NOTIFY_TRANSFER_ALERTING 0x69 /* Call transfer, alerting */
--#define PRI_NOTIFY_TRANSFER_ACTIVE 0x6a /* Call transfer, active */
-+#define PRI_NOTIFY_DIVERSION_ACTIVATED 0x68 /* Diversion activated (DSS1) (cfu, cfb, cfnr) (EN 300 207-1 Section 7.2.1) */
-+#define PRI_NOTIFY_TRANSFER_ALERTING 0x69 /* Call transfer, alerting (EN 300 369-1 Section 7.2) */
-+#define PRI_NOTIFY_TRANSFER_ACTIVE 0x6a /* Call transfer, active(answered) (EN 300 369-1 Section 7.2) */
- #define PRI_NOTIFY_REMOTE_HOLD 0x79 /* Remote hold */
- #define PRI_NOTIFY_REMOTE_RETRIEVAL 0x7a /* Remote retrieval */
--#define PRI_NOTIFY_CALL_DIVERTING 0x7b /* Call is diverting */
-+#define PRI_NOTIFY_CALL_DIVERTING 0x7b /* Call is diverting (EN 300 207-1 Section 7.2.1) */
-
- #define PRI_COPY_DIGITS_CALLED_NUMBER
-
-@@ -305,6 +356,200 @@
-
- typedef struct q931_call q931_call;
-
-+/* Name character set enumeration values */
-+#define PRI_CHAR_SET_UNKNOWN 0
-+#define PRI_CHAR_SET_ISO8859_1 1
-+#define PRI_CHAR_SET_WITHDRAWN 2
-+#define PRI_CHAR_SET_ISO8859_2 3
-+#define PRI_CHAR_SET_ISO8859_3 4
-+#define PRI_CHAR_SET_ISO8859_4 5
-+#define PRI_CHAR_SET_ISO8859_5 6
-+#define PRI_CHAR_SET_ISO8859_7 7
-+#define PRI_CHAR_SET_ISO10646_BMPSTRING 8
-+#define PRI_CHAR_SET_ISO10646_UTF_8STRING 9
-+
-+/*! \brief Q.SIG name information. */
-+struct pri_party_name {
-+ /*! \brief TRUE if the name information is valid/present */
-+ int valid;
-+ /*!
-+ * \brief Q.931 presentation-indicator encoded field
-+ * \note Must tollerate the Q.931 screening-indicator field values being present.
-+ */
-+ int presentation;
-+ /*!
-+ * \brief Character set the name is using.
-+ * \details
-+ * unknown(0),
-+ * iso8859-1(1),
-+ * enum-value-withdrawn-by-ITU-T(2)
-+ * iso8859-2(3),
-+ * iso8859-3(4),
-+ * iso8859-4(5),
-+ * iso8859-5(6),
-+ * iso8859-7(7),
-+ * iso10646-BmpString(8),
-+ * iso10646-utf-8String(9)
-+ * \details
-+ * Set to iso8859-1(1) if unsure what to use.
-+ */
-+ int char_set;
-+ /*! \brief Name data with null terminator. */
-+ char str[64];
-+};
-+
-+struct pri_party_number {
-+ /*! \brief TRUE if the number information is valid/present */
-+ int valid;
-+ /*! \brief Q.931 presentation-indicator and screening-indicator encoded fields */
-+ int presentation;
-+ /*! \brief Q.931 Type-Of-Number and numbering-plan encoded fields */
-+ int plan;
-+ /*! \brief Number data with null terminator. */
-+ char str[64];
-+};
-+
-+/*!
-+ * \note This structure is a place holder for possible future subaddress support
-+ * to maintain ABI compatibility.
-+ */
-+struct pri_party_subaddress {
-+ /*! \brief TRUE if the subaddress information is valid/present */
-+ int valid;
-+ /*!
-+ * \brief Subaddress type.
-+ * \details
-+ * nsap(0),
-+ * user_specified(2)
-+ */
-+ int type;
-+ /*!
-+ * \brief TRUE if odd number of address signals
-+ * \note The odd/even indicator is used when the type of subaddress is
-+ * user_specified and the coding is BCD.
-+ */
-+ int odd_even_indicator;
-+ /*! \brief Length of the subaddress data */
-+ int length;
-+ /*!
-+ * \brief Subaddress data with null terminator.
-+ * \note The null terminator is a convenience only since the data could be
-+ * BCD/binary and thus have a null byte as part of the contents.
-+ */
-+ unsigned char data[32];
-+};
-+
-+/*! \brief Information needed to identify an endpoint in a call. */
-+struct pri_party_id {
-+ /*! \brief Subscriber name */
-+ struct pri_party_name name;
-+ /*! \brief Subscriber phone number */
-+ struct pri_party_number number;
-+ /*! \brief Subscriber subaddress */
-+ struct pri_party_subaddress subaddress;
-+};
-+
-+/*! \brief Connected Line/Party information */
-+struct pri_party_connected_line {
-+ /*! Connected party ID */
-+ struct pri_party_id id;
-+};
-+
-+/*!
-+ * \brief Redirecting Line information.
-+ * \details
-+ * RDNIS (Redirecting Directory Number Information Service)
-+ * Where a call diversion or transfer was invoked.
-+ */
-+struct pri_party_redirecting {
-+ /*! Who is redirecting the call (Sent to the party the call is redirected toward) */
-+ struct pri_party_id from;
-+ /*! Call is redirecting to a new party (Sent to the caller) */
-+ struct pri_party_id to;
-+ /*! Originally called party (in cases of multiple redirects) */
-+ struct pri_party_id orig_called;
-+ /*! Number of times the call was redirected */
-+ int count;
-+ /*! Original reason for redirect (in cases of multiple redirects) */
-+ int orig_reason;
-+ /*! Redirection reason */
-+ int reason;
-+};
-+
-+/*!
-+ * \brief Information for rerouting/deflecting the call.
-+ */
-+struct pri_rerouting_data {
-+ /*!
-+ * \brief Updated caller-id information.
-+ * \note The information may have been altered by procedure in the private network.
-+ */
-+ struct pri_party_id caller;
-+ /*!
-+ * \note
-+ * deflection.to is the new called number and must always be present.
-+ */
-+ struct pri_party_redirecting deflection;
-+ /*!
-+ * \brief Diverting user subscription option to specify if caller is notified.
-+ * \details
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2),
-+ * notApplicable(3) (Status only.)
-+ */
-+ int subscription_option;
-+ /*! Invocation ID to use when sending a reply to the call rerouting/deflection request. */
-+ int invoke_id;
-+};
-+
-+/* Subcommands derived from supplementary services. */
-+#define PRI_SUBCMD_REDIRECTING 1
-+#define PRI_SUBCMD_CONNECTED_LINE 2
-+#define PRI_SUBCMD_REROUTING 3
-+
-+
-+struct pri_subcommand {
-+ /*! PRI_SUBCMD_xxx defined values */
-+ int cmd;
-+ union {
-+ /*! Reserve room for possible expansion to maintain ABI compatibility. */
-+ char reserve_space[512];
-+ struct pri_party_connected_line connected_line;
-+ struct pri_party_redirecting redirecting;
-+ struct pri_rerouting_data rerouting;
-+ } u;
-+};
-+
-+/* Max number of subcommands per event message */
-+#define PRI_MAX_SUBCOMMANDS 8
-+
-+struct pri_subcommands {
-+ int counter_subcmd;
-+ struct pri_subcommand subcmd[PRI_MAX_SUBCOMMANDS];
-+};
-+
-+
-+/*
-+ * Event channel parameter encoding:
-+ * 3322 2222 2222 1111 1111 1100 0000 0000
-+ * 1098 7654 3210 9876 5432 1098 7654 3210
-+ * xxxx xxxx xxxx xEDC BBBBBBBBB AAAAAAAAA
-+ *
-+ * Bit field
-+ * A - B channel
-+ * B - Span (DS1) (0 - 127)
-+ * C - DS1 Explicit bit
-+ * D - D channel (cis_call) bit (status only)
-+ * E - Call is held bit (status only)
-+ *
-+ * B channel values:
-+ * 0 - No channel (ISDN uses for call waiting feature)
-+ * 1-127 - B channel #
-+ * 0xFF - Any channel (Also if whole channel value is -1 in event)
-+ */
-+
-+
- typedef struct pri_event_generic {
- /* Events with no additional information fall in this category */
- int e;
-@@ -328,6 +573,7 @@
- int progressmask;
- q931_call *call;
- char useruserinfo[260]; /* User->User info */
-+ struct pri_subcommands *subcmds;
- } pri_event_ringing;
-
- typedef struct pri_event_answer {
-@@ -338,8 +584,10 @@
- int progressmask;
- q931_call *call;
- char useruserinfo[260]; /* User->User info */
-+ struct pri_subcommands *subcmds;
- } pri_event_answer;
-
-+/*! Deprecated replaced by struct pri_event_facility. */
- typedef struct pri_event_facname {
- int e;
- char callingname[256];
-@@ -351,6 +599,24 @@
- int callingplan; /* Dialing plan of Calling entity */
- } pri_event_facname;
-
-+struct pri_event_facility {
-+ int e;
-+ char callingname[256]; /*!< Deprecated, preserved for struct pri_event_facname compatibility */
-+ char callingnum[256]; /*!< Deprecated, preserved for struct pri_event_facname compatibility */
-+ int channel;
-+ int cref;
-+ /*!
-+ * \brief Master call or normal call.
-+ * \note Call pointer known about by upper layer.
-+ * \note NULL if dummy call reference.
-+ */
-+ q931_call *call;
-+ int callingpres; /*!< Presentation of Calling CallerID (Deprecated, preserved for struct pri_event_facname compatibility) */
-+ int callingplan; /*!< Dialing plan of Calling entity (Deprecated, preserved for struct pri_event_facname compatibility) */
-+ struct pri_subcommands *subcmds;
-+ q931_call *subcall; /*!< Subcall to send any reply toward. */
-+};
-+
- #define PRI_CALLINGPLANANI
- #define PRI_CALLINGPLANRDNIS
- typedef struct pri_event_ring {
-@@ -376,13 +642,18 @@
- int layer1; /* User layer 1 */
- int complete; /* Have we seen "Complete" i.e. no more number? */
- q931_call *call; /* Opaque call pointer */
-- char callingsubaddr[256]; /* Calling parties subaddress */
-+ char callingsubaddr[256]; /* Calling parties subaddress, backwards compatibility */
- int progress;
- int progressmask;
- char origcalledname[256];
- char origcallednum[256];
- int callingplanorigcalled; /* Dialing plan of Originally Called Number */
- int origredirectingreason;
-+ int reversecharge;
-+ struct pri_subcommands *subcmds;
-+ struct pri_party_id calling; /* Calling Party's info, initially subaddress' */
-+ struct pri_party_subaddress called_subaddress; /* Called party's subaddress */
-+ char keypad_digits[64]; /* Keypad digits in the SETUP message. */
- } pri_event_ring;
-
- typedef struct pri_event_hangup {
-@@ -390,10 +661,23 @@
- int channel; /* Channel requested */
- int cause;
- int cref;
-- q931_call *call; /* Opaque call pointer */
-+ q931_call *call; /* Opaque call pointer of call hanging up. */
- long aoc_units; /* Advise of Charge number of charged units */
- char useruserinfo[260]; /* User->User info */
--} pri_event_hangup;
-+ struct pri_subcommands *subcmds;
-+ /*!
-+ * \brief Opaque held call pointer for possible transfer to active call.
-+ * \note The call_held and call_active pointers must not be NULL if
-+ * transfer held call on disconnect is available.
-+ */
-+ q931_call *call_held;
-+ /*!
-+ * \brief Opaque active call pointer for possible transfer with held call.
-+ * \note The call_held and call_active pointers must not be NULL if
-+ * transfer held call on disconnect is available.
-+ */
-+ q931_call *call_active;
-+} pri_event_hangup;
-
- typedef struct pri_event_restart_ack {
- int e;
-@@ -409,18 +693,22 @@
- int progressmask;
- int cause;
- q931_call *call;
-+ struct pri_subcommands *subcmds;
- } pri_event_proceeding;
--
-+
- typedef struct pri_event_setup_ack {
- int e;
- int channel;
- q931_call *call;
-+ struct pri_subcommands *subcmds;
- } pri_event_setup_ack;
-
- typedef struct pri_event_notify {
- int e;
- int channel;
- int info;
-+ struct pri_subcommands *subcmds;
-+ q931_call *call;
- } pri_event_notify;
-
- typedef struct pri_event_keypad_digit {
-@@ -428,14 +716,72 @@
- int channel;
- q931_call *call;
- char digits[64];
-+ struct pri_subcommands *subcmds;
- } pri_event_keypad_digit;
-
-+typedef struct pri_event_service {
-+ int e;
-+ int channel;
-+ int changestatus;
-+} pri_event_service;
-+
-+typedef struct pri_event_service_ack {
-+ int e;
-+ int channel;
-+ int changestatus;
-+} pri_event_service_ack;
-+
-+struct pri_event_hold {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_hold_ack {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_hold_rej {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ int cause;
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_retrieve {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ int flexible; /* Are we flexible with our channel selection? */
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_retrieve_ack {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ struct pri_subcommands *subcmds;
-+};
-+
-+struct pri_event_retrieve_rej {
-+ int e;
-+ int channel;
-+ q931_call *call;
-+ int cause;
-+ struct pri_subcommands *subcmds;
-+};
-+
- typedef union {
- int e;
- pri_event_generic gen; /* Generic view */
- pri_event_restart restart; /* Restart view */
- pri_event_error err; /* Error view */
-- pri_event_facname facname; /* Caller*ID Name on Facility */
-+ pri_event_facname facname; /* Caller*ID Name on Facility (Deprecated, use pri_event.facility) */
- pri_event_ring ring; /* Ring */
- pri_event_hangup hangup; /* Hang up */
- pri_event_ringing ringing; /* Ringing */
-@@ -445,6 +791,15 @@
- pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
- pri_event_notify notify; /* Notification */
- pri_event_keypad_digit digit; /* Digits that come during a call */
-+ pri_event_service service; /* service message */
-+ pri_event_service_ack service_ack; /* service acknowledgement message */
-+ struct pri_event_facility facility;
-+ struct pri_event_hold hold;
-+ struct pri_event_hold_ack hold_ack;
-+ struct pri_event_hold_rej hold_rej;
-+ struct pri_event_retrieve retrieve;
-+ struct pri_event_retrieve_ack retrieve_ack;
-+ struct pri_event_retrieve_rej retrieve_rej;
- } pri_event;
-
- struct pri;
-@@ -456,7 +811,7 @@
-
- /* Create a D-channel on a given file descriptor. The file descriptor must be a
- channel operating in HDLC mode with FCS computed by the fd's driver. Also it
-- must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
-+ must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
- must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
- struct pri *pri_new(int fd, int nodetype, int switchtype);
- struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype);
-@@ -521,7 +876,7 @@
-
- #define PRI_KEYPAD_FACILITY_TX
- /* Send a keypad facility string of digits */
--int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits);
-+int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
-
- /* Answer the incomplete(call without called number) call on the given channel.
- Set non-isdn to non-zero if you are not connecting to ISDN equipment */
-@@ -531,6 +886,18 @@
- Set non-isdn to non-zero if you are not connecting to ISDN equipment */
- int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
-
-+/*!
-+ * \brief Give connected line information to a call
-+ * \note Could be used instead of pri_sr_set_caller_party() before calling pri_setup().
-+ */
-+int pri_connected_line_update(struct pri *pri, q931_call *call, const struct pri_party_connected_line *connected);
-+
-+/*!
-+ * \brief Give redirection information to a call
-+ * \note Could be used instead of pri_sr_set_redirecting_parties() before calling pri_setup().
-+ */
-+int pri_redirecting_update(struct pri *pri, q931_call *call, const struct pri_party_redirecting *redirecting);
-+
- /* Set CRV reference for GR-303 calls */
-
-
-@@ -556,9 +923,20 @@
-
- int pri_reset(struct pri *pri, int channel);
-
-+/* handle b-channel maintenance messages */
-+extern int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus);
-+
- /* Create a new call */
- q931_call *pri_new_call(struct pri *pri);
-
-+/*!
-+ * \brief Deterimine if the given call control pointer is a dummy call.
-+ *
-+ * \retval TRUE if given call is a dummy call.
-+ * \retval FALSE otherwise.
-+ */
-+int pri_is_dummy_call(q931_call *call);
-+
- /* Retrieve CRV reference for GR-303 calls. Returns >0 on success. */
- int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
-
-@@ -573,8 +951,8 @@
- extern pri_event *pri_schedule_run_tv(struct pri *pri, const struct timeval *now);
-
- int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
-- int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
-- char *called,int calledplan, int ulayer1);
-+ int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
-+ char *called, int calledplan, int ulayer1);
-
- struct pri_sr *pri_sr_new(void);
- void pri_sr_free(struct pri_sr *sr);
-@@ -582,25 +960,91 @@
- int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
- int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
- int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
-+
-+/*!
-+ * \brief Set the caller party ID information in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param caller Caller party ID information to set.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller);
-+/*! \note Use pri_sr_set_caller_party() instead to pass more precise caller information. */
- int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
-+
-+/*!
-+ * \brief Set the calling subaddress information in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param subaddress information to set.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress);
-+
-+/*!
-+ * \brief Set the called subaddress information in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param subaddress information to set.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress);
-+
-+/*!
-+ * \brief Set the redirecting information in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param caller Redirecting information to set.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting);
-+/*! \note Use pri_sr_set_redirecting_parties() instead to pass more precise redirecting information. */
- int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
-+
-+/*!
-+ * \brief Set the keypad digits in the call SETUP record.
-+ *
-+ * \param sr New call SETUP record.
-+ * \param keypad_digits Keypad digits to send.
-+ *
-+ * \return Nothing
-+ */
-+void pri_sr_set_keypad_digits(struct pri_sr *sr, const char *keypad_digits);
-+
- #define PRI_USER_USER_TX
- /* Set the user user field. Warning! don't send binary data accross this field */
- void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
-+void pri_sr_set_reversecharge(struct pri_sr *sr, int requested);
-
- void pri_call_set_useruser(q931_call *sr, const char *userchars);
-
- int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
-
--/* Set a call has a call indpendent signalling connection (i.e. no bchan) */
-+/*!
-+ * \brief Set a call as a call indpendent signalling connection (i.e. no bchan)
-+ * \note Call will automaticlly disconnect after signalling sent.
-+ */
- int pri_sr_set_connection_call_independent(struct pri_sr *req);
-
-+/*!
-+ * \brief Set a call as a call indpendent signalling connection (i.e. no bchan)
-+ * \note Call will stay connected until explicitly disconnected.
-+ */
-+int pri_sr_set_no_channel_call(struct pri_sr *req);
-+
- /* Send an MWI indication to a remote location. If activate is non zero, activates, if zero, deactivates */
- int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
-
- /* Send an MWI deactivate request to a remote location */
- int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
-
-+/* Set service message support flag */
-+int pri_set_service_message_support(struct pri *pri, int supportflag);
-+
- #define PRI_2BCT
- /* Attempt to pass the channels back to the NET side if compatable and
- * suscribed. Sometimes called 2 bchannel transfer (2BCT) */
-@@ -656,48 +1100,208 @@
-
- int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason);
-
-+/*!
-+ * \brief Set the call deflection/rerouting feature enable flag.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param enable TRUE to enable call deflection/rerouting feature.
-+ *
-+ * \return Nothing
-+ */
-+void pri_reroute_enable(struct pri *ctrl, int enable);
-+
-+/*!
-+ * \brief Send the CallRerouting/CallDeflection message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
-+ * \param deflection Call rerouting/deflecting redirection data.
-+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
-+ *
-+ * \note
-+ * deflection->to is the new called number and must always be present.
-+ * \note
-+ * subscription option:
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_id *caller, const struct pri_party_redirecting *deflection, int subscription_option);
-+
-+enum PRI_REROUTING_RSP_CODE {
-+ /*!
-+ * Rerouting invocation accepted and the network provider option
-+ * "served user call retention on invocation of diversion"
-+ * is "clear call on invocation".
-+ */
-+ PRI_REROUTING_RSP_OK_CLEAR,
-+ /*!
-+ * Rerouting invocation accepted and the network provider option
-+ * "served user call retention on invocation of diversion"
-+ * is "retain call until alerting begins at the deflected-to user".
-+ */
-+ PRI_REROUTING_RSP_OK_RETAIN,
-+ PRI_REROUTING_RSP_NOT_SUBSCRIBED,
-+ PRI_REROUTING_RSP_NOT_AVAILABLE,
-+ /*! Supplementary service interaction not allowed. */
-+ PRI_REROUTING_RSP_NOT_ALLOWED,
-+ PRI_REROUTING_RSP_INVALID_NUMBER,
-+ /*! Deflection to prohibited number (e.g., operator, police, emergency). */
-+ PRI_REROUTING_RSP_SPECIAL_SERVICE_NUMBER,
-+ /*! Deflection to served user number. */
-+ PRI_REROUTING_RSP_DIVERSION_TO_SELF,
-+ PRI_REROUTING_RSP_MAX_DIVERSIONS_EXCEEDED,
-+ PRI_REROUTING_RSP_RESOURCE_UNAVAILABLE,
-+};
-+
-+/*!
-+ * \brief Send the CallRerouteing/CallDeflection response message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ * \param invoke_id Value given by the initiating request.
-+ * \param code The result to send.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI_REROUTING_RSP_CODE code);
-+
-+/*!
-+ * \brief Set the call hold feature enable flag.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param enable TRUE to enable call hold feature.
-+ *
-+ * \return Nothing
-+ */
-+void pri_hold_enable(struct pri *ctrl, int enable);
-+
-+/*!
-+ * \brief Send the HOLD message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_hold(struct pri *ctrl, q931_call *call);
-+
-+/*!
-+ * \brief Send the HOLD ACKNOWLEDGE message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_hold_ack(struct pri *ctrl, q931_call *call);
-+
-+/*!
-+ * \brief Send the HOLD REJECT message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param cause Q.931 cause code for rejecting the hold request.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause);
-+
-+/*!
-+ * \brief Send the RETRIEVE message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param channel Encoded channel id to use. If zero do not send channel id.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_retrieve(struct pri *ctrl, q931_call *call, int channel);
-+
-+/*!
-+ * \brief Send the RETRIEVE ACKNOWLEDGE message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param channel Encoded channel id to use.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel);
-+
-+/*!
-+ * \brief Send the RETRIEVE REJECT message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param cause Q.931 cause code for rejecting the retrieve request.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause);
-+
- /* Get/Set PRI Timers */
- #define PRI_GETSET_TIMERS
- int pri_set_timer(struct pri *pri, int timer, int value);
- int pri_get_timer(struct pri *pri, int timer);
--int pri_timer2idx(char *timer);
-+int pri_timer2idx(const char *timer_name);
-
--#define PRI_MAX_TIMERS 32
-+/*! New configurable timers and counters must be added to the end of the list */
-+enum PRI_TIMERS_AND_COUNTERS {
-+ PRI_TIMER_N200, /*!< Maximum numer of Q.921 retransmissions */
-+ PRI_TIMER_N201, /*!< Maximum numer of octets in an information field */
-+ PRI_TIMER_N202, /*!< Maximum numer of transmissions of the TEI identity request message */
-+ PRI_TIMER_K, /*!< Maximum number of outstanding I-frames */
-
--#define PRI_TIMER_N200 0 /* Maximum numer of q921 retransmissions */
--#define PRI_TIMER_N201 1 /* Maximum numer of octets in an information field */
--#define PRI_TIMER_N202 2 /* Maximum numer of transmissions of the TEI identity request message */
--#define PRI_TIMER_K 3 /* Maximum number of outstanding I-frames */
-+ PRI_TIMER_T200, /*!< Time between SABME's */
-+ PRI_TIMER_T201, /*!< Minimum time between retransmissions of the TEI Identity check messages */
-+ PRI_TIMER_T202, /*!< Minimum time between transmission of TEI Identity request messages */
-+ PRI_TIMER_T203, /*!< Maximum time without exchanging packets */
-
--#define PRI_TIMER_T200 4 /* time between SABME's */
--#define PRI_TIMER_T201 5 /* minimum time between retransmissions of the TEI Identity check messages */
--#define PRI_TIMER_T202 6 /* minimum time between transmission of TEI Identity request messages */
--#define PRI_TIMER_T203 7 /* maxiumum time without exchanging packets */
-+ PRI_TIMER_T300,
-+ PRI_TIMER_T301, /*!< Maximum time to respond to an ALERT */
-+ PRI_TIMER_T302,
-+ PRI_TIMER_T303, /*!< Maximum time to wait after sending a SETUP without a response */
-+ PRI_TIMER_T304,
-+ PRI_TIMER_T305, /*!< Wait for DISCONNECT acknowledge */
-+ PRI_TIMER_T306,
-+ PRI_TIMER_T307,
-+ PRI_TIMER_T308, /*!< Wait for RELEASE acknowledge */
-+ PRI_TIMER_T309, /*!< Time active calls can tollerate data link layer being down before clearing. */
-+ PRI_TIMER_T310, /*!< Maximum time between receiving a CALL_PROCEEDING and receiving a ALERT/CONNECT/DISCONNECT/PROGRESS */
-+ PRI_TIMER_T313, /*!< Wait for CONNECT acknowledge, CPE side only */
-+ PRI_TIMER_T314,
-+ PRI_TIMER_T316, /*!< Maximum time between transmitting a RESTART and receiving a RESTART ACK */
-+ PRI_TIMER_T317,
-+ PRI_TIMER_T318,
-+ PRI_TIMER_T319,
-+ PRI_TIMER_T320,
-+ PRI_TIMER_T321,
-+ PRI_TIMER_T322,
-
--#define PRI_TIMER_T300 8
--#define PRI_TIMER_T301 9 /* maximum time to respond to an ALERT */
--#define PRI_TIMER_T302 10
--#define PRI_TIMER_T303 11 /* maximum time to wait after sending a SETUP without a response */
--#define PRI_TIMER_T304 12
--#define PRI_TIMER_T305 13
--#define PRI_TIMER_T306 14
--#define PRI_TIMER_T307 15
--#define PRI_TIMER_T308 16
--#define PRI_TIMER_T309 17
--#define PRI_TIMER_T310 18 /* maximum time between receiving a CALLPROCEEDING and receiving a ALERT/CONNECT/DISCONNECT/PROGRESS */
--#define PRI_TIMER_T313 19
--#define PRI_TIMER_T314 20
--#define PRI_TIMER_T316 21 /* maximum time between transmitting a RESTART and receiving a RESTART ACK */
--#define PRI_TIMER_T317 22
--#define PRI_TIMER_T318 23
--#define PRI_TIMER_T319 24
--#define PRI_TIMER_T320 25
--#define PRI_TIMER_T321 26
--#define PRI_TIMER_T322 27
-+ PRI_TIMER_TM20, /*!< Maximum time awaiting XID response */
-+ PRI_TIMER_NM20, /*!< Number of XID retransmits */
-
--#define PRI_TIMER_TM20 28 /* maximum time avaiting XID response */
--#define PRI_TIMER_NM20 29 /* number of XID retransmits */
-+ PRI_TIMER_T_HOLD, /*!< Maximum time to wait for HOLD request response. */
-+ PRI_TIMER_T_RETRIEVE, /*!< Maximum time to wait for RETRIEVE request response. */
-
-+ PRI_TIMER_T_RESPONSE, /*!< Maximum time to wait for a typical APDU response. */
-+
-+ /* Must be last in the enum list */
-+ PRI_MAX_TIMERS
-+};
-+
- /* Get PRI version */
- const char *pri_get_version(void);
-
-Index: asn1_primitive.c
-===================================================================
---- a/asn1_primitive.c (.../tags/1.4.10.2) (revision 0)
-+++ b/asn1_primitive.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,1306 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief ASN.1 BER encode/decode primitives
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include <stdio.h>
-+#include <ctype.h>
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "asn1.h"
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Dump the memory contents indicated in printable characters. (Helper function.)
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param start Dump memory starting position.
-+ * \param end Dump memory ending position. (Not included in dump.)
-+ *
-+ * \return Nothing
-+ */
-+static void asn1_dump_mem_helper(struct pri *ctrl, const unsigned char *start,
-+ const unsigned char *end)
-+{
-+ pri_message(ctrl, " - \"");
-+ for (; start < end; ++start) {
-+ pri_message(ctrl, "%c", (isprint(*start)) ? *start : '~');
-+ }
-+ pri_message(ctrl, "\"\n");
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Dump the memory contents indicated.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param indent Number of spaces to indent for each new memory dump line.
-+ * \param pos Dump memory starting position.
-+ * \param length Number of bytes to dump.
-+ *
-+ * \return Nothing
-+ */
-+static void asn1_dump_mem(struct pri *ctrl, unsigned indent, const unsigned char *pos,
-+ unsigned length)
-+{
-+ const unsigned char *seg_start;
-+ const unsigned char *end;
-+ unsigned delimiter;
-+ unsigned count;
-+
-+ seg_start = pos;
-+ end = pos + length;
-+ if (pos < end) {
-+ delimiter = '<';
-+ for (;;) {
-+ pri_message(ctrl, "%*s", indent, "");
-+ for (count = 0; count++ < 16 && pos < end;) {
-+ pri_message(ctrl, "%c%02X", delimiter, *pos++);
-+ delimiter = (count == 8) ? '-' : ' ';
-+ }
-+ if (end <= pos) {
-+ break;
-+ }
-+ asn1_dump_mem_helper(ctrl, seg_start, pos);
-+ seg_start = pos;
-+ }
-+ } else {
-+ pri_message(ctrl, "%*s<", indent, "");
-+ }
-+ pri_message(ctrl, ">");
-+ asn1_dump_mem_helper(ctrl, seg_start, end);
-+}
-+
-+/*!
-+ * \brief Convert the given tag value to a descriptive string.
-+ *
-+ * \param tag Component tag value to convert to a string.
-+ *
-+ * \return Converted tag string.
-+ */
-+const char *asn1_tag2str(unsigned tag)
-+{
-+ static const char *primitives[32] = {
-+ [ASN1_TYPE_INDEF_TERM] = "Indefinite length terminator",
-+ [ASN1_TYPE_BOOLEAN] = "Boolean",
-+ [ASN1_TYPE_INTEGER] = "Integer",
-+ [ASN1_TYPE_BIT_STRING] = "Bit String",
-+ [ASN1_TYPE_OCTET_STRING] = "Octet String",
-+ [ASN1_TYPE_NULL] = "NULL",
-+ [ASN1_TYPE_OBJECT_IDENTIFIER] = "OID",
-+ [ASN1_TYPE_OBJECT_DESCRIPTOR] = "Object Descriptor",
-+ [ASN1_TYPE_EXTERN] = "External",
-+ [ASN1_TYPE_REAL] = "Real",
-+ [ASN1_TYPE_ENUMERATED] = "Enumerated",
-+ [ASN1_TYPE_EMBEDDED_PDV] = "Embedded PDV",
-+ [ASN1_TYPE_UTF8_STRING] = "UTF8 String",
-+ [ASN1_TYPE_RELATIVE_OID] = "Relative OID",
-+ [ASN1_TYPE_SEQUENCE] = "Sequence",
-+ [ASN1_TYPE_SET] = "Set",
-+ [ASN1_TYPE_NUMERIC_STRING] = "Numeric String",
-+ [ASN1_TYPE_PRINTABLE_STRING] = "Printable String",
-+ [ASN1_TYPE_TELETEX_STRING] = "Teletex String",
-+ [ASN1_TYPE_VIDEOTEX_STRING] = "Videotex String",
-+ [ASN1_TYPE_IA5_STRING] = "IA5 String",
-+ [ASN1_TYPE_UTC_TIME] = "UTC Time",
-+ [ASN1_TYPE_GENERALIZED_TIME] = "Generalized Time",
-+ [ASN1_TYPE_GRAPHIC_STRING] = "Graphic String",
-+ [ASN1_TYPE_VISIBLE_STRING] = "Visible/ISO646 String",
-+ [ASN1_TYPE_GENERAL_STRING] = "General String",
-+ [ASN1_TYPE_UNIVERSAL_STRING] = "Universal String",
-+ [ASN1_TYPE_CHAR_STRING] = "Character String",
-+ [ASN1_TYPE_BMP_STRING] = "BMP String",
-+ [ASN1_TYPE_EXTENSION] = "Type Extension",
-+ };
-+ static char buf[64];
-+ const char *description;
-+ unsigned asn1_constructed; /*! TRUE if the tag is constructed. */
-+ unsigned asn1_type;
-+
-+ asn1_constructed = ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED);
-+ asn1_type = tag & ASN1_TYPE_MASK;
-+
-+ switch (tag & ASN1_CLASS_MASK) {
-+ case ASN1_CLASS_UNIVERSAL:
-+ if (tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_INDEF_TERM)) {
-+ description = NULL;
-+ } else {
-+ description = primitives[asn1_type];
-+ }
-+ if (!description) {
-+ description = "Reserved";
-+ }
-+ snprintf(buf, sizeof(buf), "%s%s(%u 0x%02X)", description,
-+ asn1_constructed ? "/C" : "", tag, tag);
-+ return buf;
-+ case ASN1_CLASS_APPLICATION:
-+ description = "Application";
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC:
-+ description = "Context Specific";
-+ break;
-+ case ASN1_CLASS_PRIVATE:
-+ description = "Private";
-+ break;
-+ default:
-+ snprintf(buf, sizeof(buf), "Unknown tag (%u 0x%02X)", tag, tag);
-+ return buf;
-+ }
-+ snprintf(buf, sizeof(buf), "%s%s [%u 0x%02X]", description,
-+ asn1_constructed ? "/C" : "", asn1_type, asn1_type);
-+ return buf;
-+}
-+
-+/*!
-+ * \brief Decode the ASN.1 tag value.
-+ *
-+ * \param tag_pos ASN.1 tag starting position.
-+ * \param end End of ASN.1 encoded data buffer.
-+ * \param tag Decoded tag value returned on success.
-+ *
-+ * \retval Next octet after the tag on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_tag(const unsigned char *tag_pos, const unsigned char *end,
-+ unsigned *tag)
-+{
-+ unsigned extended_tag;
-+
-+ if (end <= tag_pos) {
-+ return NULL;
-+ }
-+ *tag = *tag_pos++;
-+ if ((*tag & ASN1_TYPE_MASK) == ASN1_TYPE_EXTENSION) {
-+ /* Extract the extended tag value */
-+ extended_tag = 0;
-+ do {
-+ if (end <= tag_pos) {
-+ return NULL;
-+ }
-+ extended_tag <<= 7;
-+ extended_tag |= *tag_pos & ~0x80;
-+ } while (*tag_pos++ & 0x80);
-+ if (extended_tag && extended_tag < ASN1_TYPE_EXTENSION) {
-+ /*
-+ * The sender did not need to use the extended format.
-+ * This is an encoding error on their part, but we will
-+ * accept it anyway.
-+ *
-+ * Note we cannot return a null tag value from this path.
-+ * We would misinterpret the indefinite length
-+ * terminator.
-+ */
-+ *tag &= ~ASN1_TYPE_MASK;
-+ *tag |= extended_tag;
-+ }
-+ }
-+
-+ return tag_pos;
-+}
-+
-+/*!
-+ * \brief Decode the length of an ASN.1 component length.
-+ *
-+ * \param len_pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param length Decoded length value returned on success. (-1 if indefinite)
-+ *
-+ * \retval Next octet after the length on success.
-+ * \retval NULL on error.
-+ *
-+ * \note The decoded length is checked to see if there is enough buffer
-+ * left for the component body.
-+ */
-+const unsigned char *asn1_dec_length(const unsigned char *len_pos,
-+ const unsigned char *end, int *length)
-+{
-+ unsigned length_size;
-+
-+ if (end <= len_pos) {
-+ /* Not enough buffer to determine how the length is encoded */
-+ return NULL;
-+ }
-+
-+ if (*len_pos < 0x80) {
-+ /* Short length encoding */
-+ *length = *len_pos++;
-+ } else if (*len_pos == 0x80) {
-+ /* Indefinite length encoding */
-+ *length = -1;
-+ ++len_pos;
-+ if (end < len_pos + ASN1_INDEF_TERM_LEN) {
-+ /* Not enough buffer for the indefinite length terminator */
-+ return NULL;
-+ }
-+ return len_pos;
-+ } else {
-+ /* Long length encoding */
-+ length_size = *len_pos++ & 0x7f;
-+ if (length_size == 0x7f) {
-+ /* Reserved extension encoding that has not been defined. */
-+ return NULL;
-+ }
-+ if (end < len_pos + length_size) {
-+ /* Not enough buffer for the length value */
-+ return NULL;
-+ }
-+ *length = 0;
-+ while (length_size--) {
-+ *length = (*length << 8) | *len_pos++;
-+ }
-+ }
-+
-+ if (end < len_pos + *length) {
-+ /* Not enough buffer for the component body. */
-+ return NULL;
-+ }
-+ return len_pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Skip to the end of an indefinite length constructed component helper.
-+ *
-+ * \param pos ASN.1 tag starting position.
-+ * \param end End of ASN.1 decoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *asn1_dec_indef_end_fixup_helper(const unsigned char *pos,
-+ const unsigned char *end)
-+{
-+ unsigned tag;
-+ int length;
-+
-+ while (pos < end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length < 0) {
-+ /* Skip over indefinite length sub-component */
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED
-+ || tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SET)
-+ || tag ==
-+ (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SEQUENCE)) {
-+ /* This is an ITU encoded indefinite length component. */
-+ ASN1_CALL(pos, asn1_dec_indef_end_fixup_helper(pos, end));
-+ } else {
-+ /* This is a non-ITU encoded indefinite length component. */
-+ while (pos < end && *pos != ASN1_INDEF_TERM) {
-+ ++pos;
-+ }
-+ pos += ASN1_INDEF_TERM_LEN;
-+ }
-+ } else {
-+ /* Skip over defininte length sub-component */
-+ pos += length;
-+ }
-+ }
-+ if (end < pos + ASN1_INDEF_TERM_LEN) {
-+ return NULL;
-+ }
-+
-+ return pos + ASN1_INDEF_TERM_LEN;
-+}
-+
-+/*!
-+ * \brief Skip to the end of an indefinite length constructed component.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param pos ASN.1 tag starting position.
-+ * \param end End of ASN.1 decoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_indef_end_fixup(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end)
-+{
-+ if (pos < end && *pos != ASN1_INDEF_TERM && (ctrl->debug & PRI_DEBUG_APDU)) {
-+ pri_message(ctrl,
-+ " Skipping unused indefinite length constructed component octets!\n");
-+ }
-+ return asn1_dec_indef_end_fixup_helper(pos, end);
-+}
-+
-+/*!
-+ * \brief Decode the boolean primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param value Decoded boolean value.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_boolean(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, int32_t *value)
-+{
-+ int length;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length != 1) {
-+ /*
-+ * The encoding rules say the length can only be one.
-+ * It is rediculus to get anything else anyway.
-+ */
-+ return NULL;
-+ }
-+
-+ *value = *pos++ ? 1 : 0;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = %d\n", name, asn1_tag2str(tag), *value);
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the integer type primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param value Decoded integer type value.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_int(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, int32_t *value)
-+{
-+ int length;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length <= 0) {
-+ /*
-+ * The encoding rules say the length can not be indefinite.
-+ * It cannot be empty for that matter either.
-+ */
-+ return NULL;
-+ }
-+
-+#if 1
-+ /* Read value as signed */
-+ if (*pos & 0x80) {
-+ /* The value is negative */
-+ *value = -1;
-+ } else {
-+ *value = 0;
-+ }
-+#else
-+ /* Read value as unsigned */
-+ *value = 0;
-+#endif
-+ while (length--) {
-+ *value = (*value << 8) | *pos;
-+ pos++;
-+ }
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = %d 0x%04X\n", name, asn1_tag2str(tag), *value,
-+ *value);
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the null primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_null(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end)
-+{
-+ int length;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length != 0) {
-+ /*
-+ * The encoding rules say the length can only be zero.
-+ * It is rediculus to get anything else anyway.
-+ */
-+ return NULL;
-+ }
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the object identifier primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param oid Decoded OID type value.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_oid(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct asn1_oid *oid)
-+{
-+ int length;
-+ unsigned num_values;
-+ unsigned value;
-+ unsigned delimiter;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length < 0) {
-+ /*
-+ * The encoding rules say the length can not be indefinite.
-+ */
-+ return NULL;
-+ }
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s =", name, asn1_tag2str(tag));
-+ }
-+ delimiter = ' ';
-+ num_values = 0;
-+ while (length) {
-+ value = 0;
-+ for (;;) {
-+ --length;
-+ value = (value << 7) | (*pos & 0x7F);
-+ if (!(*pos++ & 0x80)) {
-+ /* Last octet in the OID subidentifier value */
-+ if (num_values < ARRAY_LEN(oid->value)) {
-+ oid->value[num_values] = value;
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "%c%u", delimiter, value);
-+ }
-+ delimiter = '.';
-+ } else {
-+ /* Too many OID subidentifier values */
-+ delimiter = '~';
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "%c%u", delimiter, value);
-+ }
-+ }
-+ ++num_values;
-+ break;
-+ }
-+ if (!length) {
-+ oid->num_values = 0;
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "\n"
-+ " Last OID subidentifier value not terminated!\n");
-+ }
-+ return NULL;
-+ }
-+ }
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "\n");
-+ }
-+
-+ if (num_values <= ARRAY_LEN(oid->value)) {
-+ oid->num_values = num_values;
-+ return pos;
-+ } else {
-+ /* Need to increase the size of the OID subidentifier list. */
-+ oid->num_values = 0;
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Too many OID values!\n");
-+ }
-+ return NULL;
-+ }
-+}
-+
-+/*!
-+ * \brief Decode a binary string primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param buf_size Size of the supplied string buffer. (Must be nonzero)
-+ * \param str Where to put the decoded string.
-+ * \param str_len Length of the decoded string.
-+ *
-+ * \note The string will be null terminated just in case.
-+ * The buffer needs to have enough room for a null terminator.
-+ * \note The parse will fail if the parsed string is too large for
-+ * the supplied buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_string_bin(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
-+ unsigned char *str, size_t *str_len)
-+{
-+ int length;
-+ size_t sub_buf_size;
-+ size_t sub_str_len;
-+ unsigned char *sub_str;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length < 0) {
-+ /* This is an indefinite length string */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = Indefinite length string\n", name,
-+ asn1_tag2str(tag));
-+ }
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
-+ /*
-+ * This is an ITU encoded indefinite length string
-+ * and could contain null.
-+ */
-+
-+ /* Ensure that an empty string is null terminated. */
-+ *str = 0;
-+
-+ /* Collect all substrings into the original string buffer. */
-+ *str_len = 0;
-+ sub_str = str;
-+ sub_buf_size = buf_size;
-+ for (;;) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
-+ if (tag == ASN1_INDEF_TERM) {
-+ /* End-of-contents octets */
-+ break;
-+ }
-+
-+ /* Append the substring to the accumulated indefinite string. */
-+ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end,
-+ sub_buf_size, sub_str, &sub_str_len));
-+
-+ sub_buf_size -= sub_str_len;
-+ sub_str += sub_str_len;
-+ *str_len += sub_str_len;
-+ }
-+ } else {
-+ /*
-+ * This is a non-ITU encoded indefinite length string
-+ * and must not contain null's.
-+ */
-+ for (length = 0;; ++length) {
-+ if (end <= pos + length) {
-+ /* Not enough buffer left */
-+ return NULL;
-+ }
-+ if (pos[length] == 0) {
-+ /* Found End-of-contents octets */
-+ break;
-+ }
-+ }
-+
-+ if (buf_size - 1 < length) {
-+ /* The destination buffer is not large enough for the data */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " String buffer not large enough!\n");
-+ }
-+ return NULL;
-+ }
-+
-+ /* Extract the string and null terminate it. */
-+ memcpy(str, pos, length);
-+ str[length] = 0;
-+ *str_len = length;
-+
-+ pos += length + 1;
-+ }
-+ if (end <= pos) {
-+ /* Not enough buffer left for End-of-contents octets */
-+ return NULL;
-+ }
-+ if (*pos++ != 0) {
-+ /* We actually did not find the End-of-contents octets. */
-+ return NULL;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ /* Dump the collected string buffer contents. */
-+ pri_message(ctrl, " Completed string =\n");
-+ asn1_dump_mem(ctrl, 6, str, *str_len);
-+ }
-+ } else {
-+ /* This is a definite length string */
-+ if (buf_size - 1 < length) {
-+ /* The destination buffer is not large enough for the data */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = Buffer not large enough!\n", name,
-+ asn1_tag2str(tag));
-+ }
-+ return NULL;
-+ }
-+
-+ /* Extract the string and null terminate it. */
-+ memcpy(str, pos, length);
-+ str[length] = 0;
-+ *str_len = length;
-+
-+ pos += length;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ /* Dump the collected string buffer contents. */
-+ pri_message(ctrl, " %s %s =\n", name, asn1_tag2str(tag));
-+ asn1_dump_mem(ctrl, 4, str, *str_len);
-+ }
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode a string that can be truncated to a maximum length primitive.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this primitive.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param buf_size Size of the supplied string buffer. (Must be nonzero)
-+ * \param str Where to put the decoded null terminated string.
-+ * \param str_len Length of the decoded string.
-+ * (computed for convenience since you could just do a strlen())
-+ *
-+ * \note The parsed string will be truncated if the string buffer
-+ * cannot contain it.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *asn1_dec_string_max(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
-+ unsigned char *str, size_t *str_len)
-+{
-+ int length;
-+ size_t str_length;
-+ size_t sub_buf_size;
-+ size_t sub_str_len;
-+ unsigned char *sub_str;
-+
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ if (length < 0) {
-+ /* This is an indefinite length string */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = Indefinite length string\n", name,
-+ asn1_tag2str(tag));
-+ }
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
-+ /* This is an ITU encoded indefinite length string. */
-+
-+ /* Ensure that an empty string is null terminated. */
-+ *str = 0;
-+
-+ /* Collect all substrings into the original string buffer. */
-+ *str_len = 0;
-+ sub_str = str;
-+ sub_buf_size = buf_size;
-+ for (;;) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
-+ if (tag == ASN1_INDEF_TERM) {
-+ /* End-of-contents octets */
-+ break;
-+ }
-+
-+ /* Append the substring to the accumulated indefinite string. */
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, name, tag, pos, end,
-+ sub_buf_size, sub_str, &sub_str_len));
-+
-+ sub_buf_size -= sub_str_len;
-+ sub_str += sub_str_len;
-+ *str_len += sub_str_len;
-+ }
-+ } else {
-+ /* This is a non-ITU encoded indefinite length string. */
-+ for (length = 0;; ++length) {
-+ if (end <= pos + length) {
-+ /* Not enough buffer left */
-+ return NULL;
-+ }
-+ if (pos[length] == 0) {
-+ /* Found End-of-contents octets */
-+ break;
-+ }
-+ }
-+
-+ /* Extract the string, truncate if necessary, and terminate it. */
-+ str_length = (buf_size - 1 < length) ? buf_size - 1 : length;
-+ memcpy(str, pos, str_length);
-+ str[str_length] = 0;
-+ *str_len = str_length;
-+
-+ pos += length + 1;
-+ }
-+ if (end <= pos) {
-+ /* Not enough buffer left for End-of-contents octets */
-+ return NULL;
-+ }
-+ if (*pos++ != 0) {
-+ /* We actually did not find the End-of-contents octets. */
-+ return NULL;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Completed string = \"%s\"\n", str);
-+ }
-+ } else {
-+ /*
-+ * This is a definite length string
-+ *
-+ * Extract the string, truncate if necessary, and terminate it.
-+ */
-+ str_length = (buf_size - 1 < length) ? buf_size - 1 : length;
-+ memcpy(str, pos, str_length);
-+ str[str_length] = 0;
-+ *str_len = str_length;
-+
-+ pos += length;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s = \"%s\"\n", name, asn1_tag2str(tag), str);
-+ }
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Recursive ASN.1 buffer decoding dump helper.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param pos ASN.1 tag starting position.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param level Indentation level to use.
-+ * \param indefinite_term TRUE if to stop on an indefinite length terminator.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *asn1_dump_helper(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end, unsigned level, unsigned indefinite_term)
-+{
-+ unsigned delimiter;
-+ unsigned tag;
-+ int length;
-+ const unsigned char *len_pos;
-+
-+ while (pos < end && (!indefinite_term || *pos != ASN1_INDEF_TERM)) {
-+ /* Decode the tag */
-+ pri_message(ctrl, "%*s", 2 * level, "");
-+ len_pos = asn1_dec_tag(pos, end, &tag);
-+ if (!len_pos) {
-+ pri_message(ctrl, "Invalid tag encoding!\n");
-+ return NULL;
-+ }
-+
-+ /* Dump the tag contents. */
-+ pri_message(ctrl, "%s ", asn1_tag2str(tag));
-+ delimiter = '<';
-+ while (pos < len_pos) {
-+ pri_message(ctrl, "%c%02X", delimiter, *pos);
-+ delimiter = ' ';
-+ ++pos;
-+ }
-+ pri_message(ctrl, "> ");
-+
-+ /* Decode the length */
-+ pos = asn1_dec_length(len_pos, end, &length);
-+ if (!pos) {
-+ pri_message(ctrl, "Invalid length encoding!\n");
-+ return NULL;
-+ }
-+
-+ /* Dump the length contents. */
-+ if (length < 0) {
-+ pri_message(ctrl, "Indefinite length ");
-+ } else {
-+ pri_message(ctrl, "Len:%d ", length);
-+ }
-+ delimiter = '<';
-+ while (len_pos < pos) {
-+ pri_message(ctrl, "%c%02X", delimiter, *len_pos);
-+ delimiter = ' ';
-+ ++len_pos;
-+ }
-+ pri_message(ctrl, ">\n");
-+
-+ /* Dump the body contents */
-+ ++level;
-+ if (length < 0) {
-+ /* Indefinite length */
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
-+ /* This is an ITU encoded indefinite length component. */
-+ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, end, level, 1));
-+ } else if (tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SET)
-+ || tag ==
-+ (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SEQUENCE)) {
-+ pri_message(ctrl, "%*sThis tag must always be constructed!\n", 2 * level,
-+ "");
-+ /* Assume tag was constructed to keep going */
-+ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, end, level, 1));
-+ } else {
-+ /* This is a non-ITU encoded indefinite length component. */
-+ pri_message(ctrl, "%*sNon-ITU indefininte length component.\n",
-+ 2 * level, "");
-+ length = 0;
-+ while (pos + length < end && pos[length] != ASN1_INDEF_TERM) {
-+ ++length;
-+ }
-+ if (length) {
-+ asn1_dump_mem(ctrl, 2 * level, pos, length);
-+ pos += length;
-+ }
-+ }
-+ --level;
-+ if (end < pos + ASN1_INDEF_TERM_LEN) {
-+ pri_message(ctrl, "%*sNot enough room for the End-of-contents octets!\n",
-+ 2 * level, "");
-+ pos = end;
-+ } else {
-+ pri_message(ctrl, "%*sEnd-of-contents <%02X %02X>%s\n", 2 * level, "",
-+ pos[0], pos[1], (pos[1] != 0) ? " Invalid!" : "");
-+ pos += ASN1_INDEF_TERM_LEN;
-+ }
-+ } else {
-+ /* Defininte length */
-+ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
-+ /* Dump constructed contents */
-+ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, pos + length, level, 0));
-+ } else if (tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SET)
-+ || tag ==
-+ (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SEQUENCE)) {
-+ /* Assume tag was constructed to keep going */
-+ pri_message(ctrl, "%*sThis tag must always be constructed!\n", 2 * level,
-+ "");
-+ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, pos + length, level, 0));
-+ } else if (0 < length) {
-+ /* Dump primitive contents. */
-+ asn1_dump_mem(ctrl, 2 * level, pos, length);
-+ pos += length;
-+ }
-+ --level;
-+ }
-+
-+#if 0
-+ pri_message(ctrl, "%*sEnd\n", 2 * level, "");
-+#endif
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Dump the given ASN.1 buffer contents.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param start_asn1 First octet in the ASN.1 buffer. (ASN.1 tag starting position)
-+ * \param end One beyond the last octet in the ASN.1 buffer.
-+ *
-+ * \return Nothing
-+ */
-+void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1,
-+ const unsigned char *end)
-+{
-+ pri_message(ctrl, "ASN.1 dump\n");
-+ if (start_asn1) {
-+ asn1_dump_helper(ctrl, start_asn1, end, 1, 0);
-+ }
-+ pri_message(ctrl, "ASN.1 end\n");
-+}
-+
-+/*!
-+ * \brief Encode the length of an ASN.1 component body of predetermined size.
-+ *
-+ * \param len_pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param length Predetermined component body length.
-+ *
-+ * \note The encoding buffer does not need to be checked after calling.
-+ * It is already checked to have the requested room.
-+ *
-+ * \retval Next octet after the length on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_length(unsigned char *len_pos, unsigned char *end, size_t length)
-+{
-+ u_int32_t body_length; /* Length of component contents */
-+ u_int32_t value;
-+ u_int32_t test_mask;
-+ unsigned length_size; /* Length of the length encoding */
-+
-+ body_length = length;
-+
-+ /* Determine length encoding length */
-+ if (body_length < 128) {
-+ length_size = 1;
-+ } else {
-+ /* Find most significant octet of 32 bit integer that carries meaning. */
-+ test_mask = 0xFF000000;
-+ for (length_size = 4; --length_size;) {
-+ if (body_length & test_mask) {
-+ /*
-+ * Found the first 8 bits of a multiple octet length that
-+ * is not all zeroes.
-+ */
-+ break;
-+ }
-+ test_mask >>= 8;
-+ }
-+ length_size += 1 + 1;
-+ }
-+
-+ if (end < len_pos + length_size + body_length) {
-+ /* No room for the length and component body in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode the component body length */
-+ if (length_size == 1) {
-+ *len_pos++ = body_length;
-+ } else {
-+ *len_pos++ = 0x80 | --length_size;
-+ while (length_size--) {
-+ value = body_length;
-+ value >>= (8 * length_size);
-+ *len_pos++ = value & 0xFF;
-+ }
-+ }
-+
-+ return len_pos;
-+}
-+
-+/*!
-+ * \brief Encode the length of an already encoded ASN.1 component.
-+ *
-+ * \param len_pos Starting position of the ASN.1 component length.
-+ * \param component_end Next octet after the component body.
-+ * \param end End of ASN.1 encoding data buffer.
-+ *
-+ * \note The total component size could increase or decrease.
-+ * \note The component length field must have been initialized with
-+ * ASN1_LEN_INIT() or ASN1_CONSTRUCTED_BEGIN().
-+ *
-+ * \retval Next octet after the component body on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_length_fixup(unsigned char *len_pos,
-+ unsigned char *component_end, unsigned char *end)
-+{
-+ u_int32_t body_length; /* Length of component contents */
-+ u_int32_t value;
-+ u_int32_t test_mask;
-+ unsigned length_size; /* Length of the length encoding */
-+
-+ if (component_end < len_pos + *len_pos) {
-+ /* Sanity check */
-+ return NULL;
-+ }
-+
-+ body_length = component_end - len_pos - *len_pos;
-+
-+ /* Determine length encoding length */
-+ if (body_length < 128) {
-+ length_size = 1;
-+ } else {
-+ /* Find most significant octet of 32 bit integer that carries meaning. */
-+ test_mask = 0xFF000000;
-+ for (length_size = 4; --length_size;) {
-+ if (body_length & test_mask) {
-+ /*
-+ * Found the first 8 bits of a multiple octet length that
-+ * is not all zeroes.
-+ */
-+ break;
-+ }
-+ test_mask >>= 8;
-+ }
-+ length_size += 1 + 1;
-+ }
-+
-+ component_end = len_pos + length_size + body_length;
-+ if (end < component_end) {
-+ /* No room for the component in the buffer */
-+ return NULL;
-+ }
-+ if (length_size != *len_pos) {
-+ /* Must shift the component body */
-+ memmove(len_pos + length_size, len_pos + *len_pos, body_length);
-+ }
-+
-+ /* Encode the component body length */
-+ if (length_size == 1) {
-+ *len_pos = body_length;
-+ } else {
-+ *len_pos++ = 0x80 | --length_size;
-+ while (length_size--) {
-+ value = body_length;
-+ value >>= (8 * length_size);
-+ *len_pos++ = value & 0xFF;
-+ }
-+ }
-+
-+ return component_end;
-+}
-+
-+/*!
-+ * \brief Encode the boolean primitive.
-+ *
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * \param value Component value to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_boolean(unsigned char *pos, unsigned char *end, unsigned tag,
-+ int32_t value)
-+{
-+ if (end < pos + 3) {
-+ /* No room for the component in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode component */
-+ *pos++ = tag;
-+ *pos++ = 1;
-+ *pos++ = value ? 1 : 0;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the integer type primitive.
-+ *
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * \param value Component value to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_int(unsigned char *pos, unsigned char *end, unsigned tag,
-+ int32_t value)
-+{
-+ unsigned count;
-+ u_int32_t test_mask;
-+ u_int32_t val;
-+
-+ /* Find most significant octet of 32 bit integer that carries meaning. */
-+ test_mask = 0xFF800000;
-+ val = (u_int32_t) value;
-+ for (count = 4; --count;) {
-+ if ((val & test_mask) != test_mask && (val & test_mask) != 0) {
-+ /*
-+ * The first 9 bits of a multiple octet integer is not
-+ * all ones or zeroes.
-+ */
-+ break;
-+ }
-+ test_mask >>= 8;
-+ }
-+
-+ if (end < pos + 3 + count) {
-+ /* No room for the component in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode component */
-+ *pos++ = tag;
-+ *pos++ = count + 1;
-+ do {
-+ val = (u_int32_t) value;
-+ val >>= (8 * count);
-+ *pos++ = val & 0xFF;
-+ } while (count--);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the null type primitive.
-+ *
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_null(unsigned char *pos, unsigned char *end, unsigned tag)
-+{
-+ if (end < pos + 2) {
-+ /* No room for the component in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode component */
-+ *pos++ = tag;
-+ *pos++ = 0;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the object identifier (OID) primitive.
-+ *
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * \param oid Component value to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_oid(unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct asn1_oid *oid)
-+{
-+ unsigned char *len_pos;
-+ unsigned num_values;
-+ unsigned count;
-+ u_int32_t value;
-+
-+ if (end < pos + 2) {
-+ /* No room for the component tag and length in the buffer */
-+ return NULL;
-+ }
-+
-+ *pos++ = tag;
-+ len_pos = pos++;
-+
-+ /* For all OID subidentifer values */
-+ for (num_values = 0; num_values < oid->num_values; ++num_values) {
-+ /*
-+ * Count the number of 7 bit chunks that are needed
-+ * to encode the integer.
-+ */
-+ value = oid->value[num_values] >> 7;
-+ for (count = 0; value; ++count) {
-+ /* There are bits still set */
-+ value >>= 7;
-+ }
-+
-+ if (end < pos + count + 1) {
-+ /* No room for the component body in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Store OID subidentifier value */
-+ do {
-+ value = oid->value[num_values];
-+ value >>= (7 * count);
-+ *pos++ = (value & 0x7F) | (count ? 0x80 : 0);
-+ } while (count--);
-+ }
-+
-+ /* length */
-+ *len_pos = pos - len_pos - 1;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the binary string type primitive.
-+ *
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * \param str Binary string to encode.
-+ * \param str_len Length of binary string to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_string_bin(unsigned char *pos, unsigned char *end, unsigned tag,
-+ const unsigned char *str, size_t str_len)
-+{
-+ if (end < pos + 1) {
-+ /* No room for the component tag in the buffer */
-+ return NULL;
-+ }
-+
-+ /* Encode component */
-+ *pos++ = tag;
-+ ASN1_CALL(pos, asn1_enc_length(pos, end, str_len));
-+ memcpy(pos, str, str_len);
-+
-+ return pos + str_len;
-+}
-+
-+/*!
-+ * \brief Encode a string that can be truncated to a maximum length primitive.
-+ *
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * \param str Null terminated string to encode.
-+ * \param max_len Maximum length of string to encode.
-+ *
-+ * \note The string will be truncated if it is too long.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *asn1_enc_string_max(unsigned char *pos, unsigned char *end, unsigned tag,
-+ const unsigned char *str, size_t max_len)
-+{
-+ size_t str_len;
-+
-+ str_len = strlen((char *) str);
-+ if (max_len < str_len) {
-+ str_len = max_len;
-+ }
-+ return asn1_enc_string_bin(pos, end, tag, str, str_len);
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end asn1_primitive.c */
-
-Property changes on: asn1_primitive.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: pri.c
-===================================================================
---- a/pri.c (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri.c (.../branches/1.4) (revision 1357)
-@@ -42,8 +42,56 @@
- #include "pri_facility.h"
- #include "pri_q921.h"
- #include "pri_q931.h"
--#include "pri_timers.h"
-
-+#define PRI_BIT(a_bit) (1UL << (a_bit))
-+#define PRI_ALL_SWITCHES 0xFFFFFFFF
-+
-+struct pri_timer_table {
-+ const char *name;
-+ enum PRI_TIMERS_AND_COUNTERS number;
-+ unsigned long used_by;
-+};
-+
-+/*!
-+ * \note Sort the timer table entries in the order of the timer name so
-+ * pri_dump_info_str() can display them in a consitent order.
-+ */
-+static const struct pri_timer_table pri_timer[] = {
-+/* *INDENT-OFF* */
-+ /* timer name timer number used by switches */
-+ { "N200", PRI_TIMER_N200, PRI_ALL_SWITCHES },
-+ { "N201", PRI_TIMER_N201, PRI_ALL_SWITCHES },
-+ { "N202", PRI_TIMER_N202, PRI_ALL_SWITCHES },
-+ { "K", PRI_TIMER_K, PRI_ALL_SWITCHES },
-+ { "T200", PRI_TIMER_T200, PRI_ALL_SWITCHES },
-+ { "T202", PRI_TIMER_T202, PRI_ALL_SWITCHES },
-+ { "T203", PRI_TIMER_T203, PRI_ALL_SWITCHES },
-+ { "T300", PRI_TIMER_T300, PRI_ALL_SWITCHES },
-+ { "T301", PRI_TIMER_T301, PRI_ALL_SWITCHES },
-+ { "T302", PRI_TIMER_T302, PRI_ALL_SWITCHES },
-+ { "T303", PRI_TIMER_T303, PRI_ALL_SWITCHES },
-+ { "T304", PRI_TIMER_T304, PRI_ALL_SWITCHES },
-+ { "T305", PRI_TIMER_T305, PRI_ALL_SWITCHES },
-+ { "T306", PRI_TIMER_T306, PRI_ALL_SWITCHES },
-+ { "T307", PRI_TIMER_T307, PRI_ALL_SWITCHES },
-+ { "T308", PRI_TIMER_T308, PRI_ALL_SWITCHES },
-+ { "T309", PRI_TIMER_T309, PRI_ALL_SWITCHES },
-+ { "T310", PRI_TIMER_T310, PRI_ALL_SWITCHES },
-+ { "T313", PRI_TIMER_T313, PRI_ALL_SWITCHES },
-+ { "T314", PRI_TIMER_T314, PRI_ALL_SWITCHES },
-+ { "T316", PRI_TIMER_T316, PRI_ALL_SWITCHES },
-+ { "T317", PRI_TIMER_T317, PRI_ALL_SWITCHES },
-+ { "T318", PRI_TIMER_T318, PRI_ALL_SWITCHES },
-+ { "T319", PRI_TIMER_T319, PRI_ALL_SWITCHES },
-+ { "T320", PRI_TIMER_T320, PRI_ALL_SWITCHES },
-+ { "T321", PRI_TIMER_T321, PRI_ALL_SWITCHES },
-+ { "T322", PRI_TIMER_T322, PRI_ALL_SWITCHES },
-+ { "T-HOLD", PRI_TIMER_T_HOLD, PRI_ALL_SWITCHES },
-+ { "T-RETRIEVE", PRI_TIMER_T_RETRIEVE, PRI_ALL_SWITCHES },
-+ { "T-RESPONSE", PRI_TIMER_T_RESPONSE, PRI_ALL_SWITCHES },
-+/* *INDENT-ON* */
-+};
-+
- char *pri_node2str(int node)
- {
- switch(node) {
-@@ -84,14 +132,39 @@
- }
- }
-
--static void pri_default_timers(struct pri *pri, int switchtype)
-+static void pri_default_timers(struct pri *ctrl, int switchtype)
- {
-- static const int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL;
-- int x;
-+ unsigned idx;
-
-- for (x = 0; x<PRI_MAX_TIMERS; x++) {
-- pri->timers[x] = defaulttimers[switchtype][x];
-+ /* Initialize all timers/counters to unsupported/disabled. */
-+ for (idx = 0; idx < PRI_MAX_TIMERS; ++idx) {
-+ ctrl->timers[idx] = -1;
- }
-+
-+ /* Set timer values to standard defaults. Time is in ms. */
-+ ctrl->timers[PRI_TIMER_N200] = 3; /* Max numer of Q.921 retransmissions */
-+ ctrl->timers[PRI_TIMER_N202] = 3; /* Max numer of transmissions of the TEI identity request message */
-+ ctrl->timers[PRI_TIMER_K] = 7; /* Max number of outstanding I-frames */
-+ ctrl->timers[PRI_TIMER_T200] = 1000; /* Time between SABME's */
-+ ctrl->timers[PRI_TIMER_T202] = 10 * 1000; /* Min time between transmission of TEI Identity request messages */
-+ ctrl->timers[PRI_TIMER_T203] = 10 * 1000; /* Max time without exchanging packets */
-+ ctrl->timers[PRI_TIMER_T305] = 30 * 1000; /* Wait for DISCONNECT acknowledge */
-+ ctrl->timers[PRI_TIMER_T308] = 4 * 1000; /* Wait for RELEASE acknowledge */
-+ ctrl->timers[PRI_TIMER_T313] = 4 * 1000; /* Wait for CONNECT acknowledge, CPE side only */
-+ ctrl->timers[PRI_TIMER_TM20] = 2500; /* Max time awaiting XID response - Q.921 Appendix IV */
-+ ctrl->timers[PRI_TIMER_NM20] = 3; /* Number of XID retransmits - Q.921 Appendix IV */
-+ ctrl->timers[PRI_TIMER_T303] = 4 * 1000; /* Length between SETUP retransmissions and timeout */
-+
-+ ctrl->timers[PRI_TIMER_T_HOLD] = 4 * 1000; /* Wait for HOLD request response. */
-+ ctrl->timers[PRI_TIMER_T_RETRIEVE] = 4 * 1000;/* Wait for RETRIEVE request response. */
-+
-+ ctrl->timers[PRI_TIMER_T_RESPONSE] = 4 * 1000; /* Maximum time to wait for a typical APDU response. */
-+
-+ /* Set any switch specific override default values */
-+ switch (switchtype) {
-+ default:
-+ break;
-+ }
- }
-
- int pri_set_timer(struct pri *pri, int timer, int value)
-@@ -110,66 +183,30 @@
- return pri->timers[timer];
- }
-
--int pri_timer2idx(char *timer)
-+int pri_set_service_message_support(struct pri *pri, int supportflag)
- {
-- if (!strcasecmp(timer, "N200"))
-- return PRI_TIMER_N200;
-- else if (!strcasecmp(timer, "N201"))
-- return PRI_TIMER_N201;
-- else if (!strcasecmp(timer, "N202"))
-- return PRI_TIMER_N202;
-- else if (!strcasecmp(timer, "K"))
-- return PRI_TIMER_K;
-- else if (!strcasecmp(timer, "T200"))
-- return PRI_TIMER_T200;
-- else if (!strcasecmp(timer, "T202"))
-- return PRI_TIMER_T202;
-- else if (!strcasecmp(timer, "T203"))
-- return PRI_TIMER_T203;
-- else if (!strcasecmp(timer, "T300"))
-- return PRI_TIMER_T300;
-- else if (!strcasecmp(timer, "T301"))
-- return PRI_TIMER_T301;
-- else if (!strcasecmp(timer, "T302"))
-- return PRI_TIMER_T302;
-- else if (!strcasecmp(timer, "T303"))
-- return PRI_TIMER_T303;
-- else if (!strcasecmp(timer, "T304"))
-- return PRI_TIMER_T304;
-- else if (!strcasecmp(timer, "T305"))
-- return PRI_TIMER_T305;
-- else if (!strcasecmp(timer, "T306"))
-- return PRI_TIMER_T306;
-- else if (!strcasecmp(timer, "T307"))
-- return PRI_TIMER_T307;
-- else if (!strcasecmp(timer, "T308"))
-- return PRI_TIMER_T308;
-- else if (!strcasecmp(timer, "T309"))
-- return PRI_TIMER_T309;
-- else if (!strcasecmp(timer, "T310"))
-- return PRI_TIMER_T310;
-- else if (!strcasecmp(timer, "T313"))
-- return PRI_TIMER_T313;
-- else if (!strcasecmp(timer, "T314"))
-- return PRI_TIMER_T314;
-- else if (!strcasecmp(timer, "T316"))
-- return PRI_TIMER_T316;
-- else if (!strcasecmp(timer, "T317"))
-- return PRI_TIMER_T317;
-- else if (!strcasecmp(timer, "T318"))
-- return PRI_TIMER_T318;
-- else if (!strcasecmp(timer, "T319"))
-- return PRI_TIMER_T319;
-- else if (!strcasecmp(timer, "T320"))
-- return PRI_TIMER_T320;
-- else if (!strcasecmp(timer, "T321"))
-- return PRI_TIMER_T321;
-- else if (!strcasecmp(timer, "T322"))
-- return PRI_TIMER_T322;
-- else
-+ if (!pri) {
- return -1;
-+ }
-+ pri->service_message_support = supportflag;
-+ return 0;
- }
-
-+int pri_timer2idx(const char *timer_name)
-+{
-+ unsigned idx;
-+ enum PRI_TIMERS_AND_COUNTERS timer_number;
-+
-+ timer_number = -1;
-+ for (idx = 0; idx < ARRAY_LEN(pri_timer); ++idx) {
-+ if (!strcasecmp(timer_name, pri_timer[idx].name)) {
-+ timer_number = pri_timer[idx].number;
-+ break;
-+ }
-+ }
-+ return timer_number;
-+}
-+
- static int __pri_read(struct pri *pri, void *buf, int buflen)
- {
- int res = read(pri->fd, buf, buflen);
-@@ -192,18 +229,53 @@
- return res;
- }
-
--/* Pass in the master for this function */
- void __pri_free_tei(struct pri * p)
- {
-- free (p);
-+ if (p) {
-+ struct q931_call *call;
-+
-+ call = p->dummy_call;
-+ if (call) {
-+ pri_schedule_del(call->pri, call->retranstimer);
-+ pri_call_apdu_queue_cleanup(call);
-+ }
-+ free(p->msg_line);
-+ free(p);
-+ }
- }
-
- struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri)
- {
-+ struct d_ctrl_dummy *dummy_ctrl;
- struct pri *p;
-
-- if (!(p = calloc(1, sizeof(*p))))
-- return NULL;
-+ switch (switchtype) {
-+ case PRI_SWITCH_GR303_EOC:
-+ case PRI_SWITCH_GR303_TMC:
-+ case PRI_SWITCH_GR303_TMC_SWITCHING:
-+ case PRI_SWITCH_GR303_EOC_PATH:
-+ p = calloc(1, sizeof(*p));
-+ if (!p) {
-+ return NULL;
-+ }
-+ dummy_ctrl = NULL;
-+ break;
-+ default:
-+ dummy_ctrl = calloc(1, sizeof(*dummy_ctrl));
-+ if (!dummy_ctrl) {
-+ return NULL;
-+ }
-+ p = &dummy_ctrl->ctrl;
-+ break;
-+ }
-+ if (!master) {
-+ /* This is the master record. */
-+ p->msg_line = calloc(1, sizeof(*p->msg_line));
-+ if (!p->msg_line) {
-+ free(p);
-+ return NULL;
-+ }
-+ }
-
- p->bri = bri;
- p->fd = fd;
-@@ -231,7 +303,14 @@
- p->q931_rxcount = 0;
- p->q931_txcount = 0;
- #endif
-- if (switchtype == PRI_SWITCH_GR303_EOC) {
-+ if (dummy_ctrl) {
-+ /* Initialize the dummy call reference call record. */
-+ dummy_ctrl->ctrl.dummy_call = &dummy_ctrl->dummy_call;
-+ q931_init_call_record(&dummy_ctrl->ctrl, dummy_ctrl->ctrl.dummy_call,
-+ Q931_DUMMY_CALL_REFERENCE);
-+ }
-+ switch (switchtype) {
-+ case PRI_SWITCH_GR303_EOC:
- p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
- p->sapi = Q921_SAPI_GR303_EOC;
- p->tei = Q921_TEI_GR303_EOC_OPS;
-@@ -240,7 +319,8 @@
- free(p);
- p = NULL;
- }
-- } else if (switchtype == PRI_SWITCH_GR303_TMC) {
-+ break;
-+ case PRI_SWITCH_GR303_TMC:
- p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
- p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
- p->tei = Q921_TEI_GR303_TMC_CALLPROC;
-@@ -249,14 +329,19 @@
- free(p);
- p = NULL;
- }
-- } else if (switchtype == PRI_SWITCH_GR303_TMC_SWITCHING) {
-+ break;
-+ case PRI_SWITCH_GR303_TMC_SWITCHING:
- p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
- p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;
- p->tei = Q921_TEI_GR303_TMC_SWITCHING;
-- } else if (switchtype == PRI_SWITCH_GR303_EOC_PATH) {
-+ break;
-+ case PRI_SWITCH_GR303_EOC_PATH:
- p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
- p->sapi = Q921_SAPI_GR303_EOC;
- p->tei = Q921_TEI_GR303_EOC_PATH;
-+ break;
-+ default:
-+ break;
- }
- /* Start Q.921 layer, Wait if we're the network */
- if (p)
-@@ -327,44 +412,47 @@
-
- char *pri_event2str(int id)
- {
-- switch(id) {
-- case PRI_EVENT_DCHAN_UP:
-- return "D-Channel Up";
-- case PRI_EVENT_DCHAN_DOWN:
-- return "D-channel Down";
-- case PRI_EVENT_RESTART:
-- return "Restart channel";
-- case PRI_EVENT_RING:
-- return "Ring";
-- case PRI_EVENT_HANGUP:
-- return "Hangup";
-- case PRI_EVENT_RINGING:
-- return "Ringing";
-- case PRI_EVENT_ANSWER:
-- return "Answer";
-- case PRI_EVENT_HANGUP_ACK:
-- return "Hangup ACK";
-- case PRI_EVENT_RESTART_ACK:
-- return "Restart ACK";
-- case PRI_EVENT_FACNAME:
-- return "FacName";
-- case PRI_EVENT_INFO_RECEIVED:
-- return "Info Received";
-- case PRI_EVENT_PROCEEDING:
-- return "Proceeding";
-- case PRI_EVENT_SETUP_ACK:
-- return "Setup ACK";
-- case PRI_EVENT_HANGUP_REQ:
-- return "Hangup Req";
-- case PRI_EVENT_NOTIFY:
-- return "Notify";
-- case PRI_EVENT_PROGRESS:
-- return "Progress";
-- case PRI_EVENT_CONFIG_ERR:
-- return "Configuration Error";
-- default:
-- return "Unknown Event";
-+ unsigned idx;
-+ struct {
-+ int id;
-+ char *name;
-+ } events[] = {
-+/* *INDENT-OFF* */
-+ { PRI_EVENT_DCHAN_UP, "D-Channel Up" },
-+ { PRI_EVENT_DCHAN_DOWN, "D-channel Down" },
-+ { PRI_EVENT_RESTART, "Restart channel" },
-+ { PRI_EVENT_CONFIG_ERR, "Configuration Error" },
-+ { PRI_EVENT_RING, "Ring" },
-+ { PRI_EVENT_HANGUP, "Hangup" },
-+ { PRI_EVENT_RINGING, "Ringing" },
-+ { PRI_EVENT_ANSWER, "Answer" },
-+ { PRI_EVENT_HANGUP_ACK, "Hangup ACK" },
-+ { PRI_EVENT_RESTART_ACK, "Restart ACK" },
-+ { PRI_EVENT_FACILITY, "Facility" },
-+ { PRI_EVENT_INFO_RECEIVED, "Info Received" },
-+ { PRI_EVENT_PROCEEDING, "Proceeding" },
-+ { PRI_EVENT_SETUP_ACK, "Setup ACK" },
-+ { PRI_EVENT_HANGUP_REQ, "Hangup Req" },
-+ { PRI_EVENT_NOTIFY, "Notify" },
-+ { PRI_EVENT_PROGRESS, "Progress" },
-+ { PRI_EVENT_KEYPAD_DIGIT, "Keypad Digit" },
-+ { PRI_EVENT_SERVICE, "Service" },
-+ { PRI_EVENT_SERVICE_ACK, "Service ACK" },
-+ { PRI_EVENT_HOLD, "Hold" },
-+ { PRI_EVENT_HOLD_ACK, "Hold Ack" },
-+ { PRI_EVENT_HOLD_REJ, "Hold Rej" },
-+ { PRI_EVENT_RETRIEVE, "Retrieve" },
-+ { PRI_EVENT_RETRIEVE_ACK, "Retrieve ACK" },
-+ { PRI_EVENT_RETRIEVE_REJ, "Retrieve Rej" },
-+/* *INDENT-ON* */
-+ };
-+
-+ for (idx = 0; idx < ARRAY_LEN(events); ++idx) {
-+ if (events[idx].id == id) {
-+ return events[idx].name;
-+ }
- }
-+ return "Unknown Event";
- }
-
- pri_event *pri_check_event(struct pri *pri)
-@@ -506,7 +594,7 @@
- return q931_information(pri, call, digit);
- }
-
--int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits)
-+int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits)
- {
- if (!pri || !call || !digits || !digits[0])
- return -1;
-@@ -514,15 +602,6 @@
- return q931_keypad_facility(pri, call, digits);
- }
-
--
--int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
--{
-- if (!pri || !call)
-- return -1;
--
-- return qsig_cf_callrerouting(pri, call, dest, original, reason);
--}
--
- int pri_notify(struct pri *pri, q931_call *call, int channel, int info)
- {
- if (!pri || !call)
-@@ -533,7 +612,7 @@
- void pri_destroycall(struct pri *pri, q931_call *call)
- {
- if (pri && call)
-- __q931_destroycall(pri, call);
-+ q931_destroycall(pri, call);
- return;
- }
-
-@@ -551,6 +630,268 @@
- return q931_connect(pri, call, channel, nonisdn);
- }
-
-+/*!
-+ * \internal
-+ * \brief Copy the PRI party name to the Q.931 party name structure.
-+ *
-+ * \param q931_name Q.931 party name structure
-+ * \param pri_name PRI party name structure
-+ *
-+ * \return Nothing
-+ */
-+static void pri_copy_party_name_to_q931(struct q931_party_name *q931_name, const struct pri_party_name *pri_name)
-+{
-+ q931_party_name_init(q931_name);
-+ if (pri_name->valid) {
-+ q931_name->valid = 1;
-+ q931_name->presentation = pri_name->presentation;
-+ q931_name->char_set = pri_name->char_set;
-+ libpri_copy_string(q931_name->str, pri_name->str, sizeof(q931_name->str));
-+ }
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Copy the PRI party number to the Q.931 party number structure.
-+ *
-+ * \param q931_number Q.931 party number structure
-+ * \param pri_number PRI party number structure
-+ *
-+ * \return Nothing
-+ */
-+static void pri_copy_party_number_to_q931(struct q931_party_number *q931_number, const struct pri_party_number *pri_number)
-+{
-+ q931_party_number_init(q931_number);
-+ if (pri_number->valid) {
-+ q931_number->valid = 1;
-+ q931_number->presentation = pri_number->presentation;
-+ q931_number->plan = pri_number->plan;
-+ libpri_copy_string(q931_number->str, pri_number->str, sizeof(q931_number->str));
-+ }
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Copy the PRI party subaddress to the Q.931 party subaddress structure.
-+ *
-+ * \param q931_subaddress Q.931 party subaddress structure
-+ * \param pri_subaddress PRI party subaddress structure
-+ *
-+ * \return Nothing
-+ */
-+static void pri_copy_party_subaddress_to_q931(struct q931_party_subaddress *q931_subaddress, const struct pri_party_subaddress *pri_subaddress)
-+{
-+ int length;
-+ int maxlen = sizeof(q931_subaddress->data) - 1;
-+
-+ q931_party_subaddress_init(q931_subaddress);
-+
-+ if (!pri_subaddress->valid) {
-+ return;
-+ }
-+
-+ q931_subaddress->valid = 1;
-+ q931_subaddress->type = pri_subaddress->type;
-+
-+ length = pri_subaddress->length;
-+ if (length > maxlen){
-+ length = maxlen;
-+ } else {
-+ q931_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator;
-+ }
-+ q931_subaddress->length = length;
-+ memcpy(q931_subaddress->data, pri_subaddress->data, length);
-+ q931_subaddress->data[length] = '\0';
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Copy the PRI party id to the Q.931 party id structure.
-+ *
-+ * \param q931_id Q.931 party id structure
-+ * \param pri_id PRI party id structure
-+ *
-+ * \return Nothing
-+ */
-+static void pri_copy_party_id_to_q931(struct q931_party_id *q931_id, const struct pri_party_id *pri_id)
-+{
-+ pri_copy_party_name_to_q931(&q931_id->name, &pri_id->name);
-+ pri_copy_party_number_to_q931(&q931_id->number, &pri_id->number);
-+ pri_copy_party_subaddress_to_q931(&q931_id->subaddress, &pri_id->subaddress);
-+}
-+
-+int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pri_party_connected_line *connected)
-+{
-+ struct q931_party_id party_id;
-+ unsigned idx;
-+ struct q931_call *subcall;
-+
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+
-+ pri_copy_party_id_to_q931(&party_id, &connected->id);
-+ q931_party_id_fixup(ctrl, &party_id);
-+ if (!q931_party_id_cmp(&party_id, &call->local_id)) {
-+ /* The local party information did not change so do nothing. */
-+ return 0;
-+ }
-+ call->local_id = party_id;
-+
-+ /* Update all subcalls with new local_id. */
-+ if (call->outboundbroadcast && call->master_call == call) {
-+ for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
-+ subcall = call->subcalls[idx];
-+ if (subcall) {
-+ subcall->local_id = party_id;
-+ }
-+ }
-+ }
-+
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_CALL_INITIATED:
-+ case Q931_CALL_STATE_OVERLAP_SENDING:
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ /*
-+ * The local party transferred to someone else before
-+ * the remote end answered.
-+ */
-+ case Q931_CALL_STATE_ACTIVE:
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* PTMP mode */
-+ q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
-+ &call->local_id.number);
-+ } else {
-+ /* PTP mode */
-+ /* Immediately send EctInform APDU, callStatus=answered(0) */
-+ send_call_transfer_complete(ctrl, call, 0);
-+ }
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ /* Immediately send CallTransferComplete APDU, callStatus=answered(0) */
-+ send_call_transfer_complete(ctrl, call, 0);
-+ break;
-+ default:
-+ break;
-+ }
-+ break;
-+ default:
-+ /* Just save the data for further developments. */
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_party_redirecting *redirecting)
-+{
-+ unsigned idx;
-+ struct q931_call *subcall;
-+
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+
-+ /* Save redirecting.to information and reason. */
-+ pri_copy_party_id_to_q931(&call->redirecting.to, &redirecting->to);
-+ q931_party_id_fixup(ctrl, &call->redirecting.to);
-+ call->redirecting.reason = redirecting->reason;
-+
-+ /*
-+ * Update all subcalls with new redirecting.to information and reason.
-+ * I do not think we will ever have any subcalls when this data is relevant,
-+ * but update it just in case.
-+ */
-+ if (call->outboundbroadcast && call->master_call == call) {
-+ for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
-+ subcall = call->subcalls[idx];
-+ if (subcall) {
-+ subcall->redirecting.to = call->redirecting.to;
-+ subcall->redirecting.reason = redirecting->reason;
-+ }
-+ }
-+ }
-+
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_NULL:
-+ /* Save the remaining redirecting information before we place a call. */
-+ pri_copy_party_id_to_q931(&call->redirecting.from, &redirecting->from);
-+ q931_party_id_fixup(ctrl, &call->redirecting.from);
-+ pri_copy_party_id_to_q931(&call->redirecting.orig_called, &redirecting->orig_called);
-+ q931_party_id_fixup(ctrl, &call->redirecting.orig_called);
-+ call->redirecting.orig_reason = redirecting->orig_reason;
-+ if (redirecting->count <= 0) {
-+ if (call->redirecting.from.number.valid) {
-+ /*
-+ * We are redirecting with an unknown count
-+ * so assume the count is one.
-+ */
-+ call->redirecting.count = 1;
-+ } else {
-+ call->redirecting.count = 0;
-+ }
-+ } else if (redirecting->count < PRI_MAX_REDIRECTS) {
-+ call->redirecting.count = redirecting->count;
-+ } else {
-+ call->redirecting.count = PRI_MAX_REDIRECTS;
-+ }
-+ break;
-+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ /* This is an incoming call that has not connected yet. */
-+ if (!call->redirecting.to.number.valid) {
-+ /* Not being redirected toward valid number data. Ignore. */
-+ break;
-+ }
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* PTMP mode */
-+ q931_notify_redirection(ctrl, call, PRI_NOTIFY_CALL_DIVERTING,
-+ &call->redirecting.to.number);
-+ break;
-+ }
-+ /* PTP mode - same behaviour as Q.SIG */
-+ /* fall through */
-+ case PRI_SWITCH_QSIG:
-+ if (call->redirecting.state != Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3
-+ || strcmp(call->redirecting.to.number.str, call->called.number.str) != 0) {
-+ /* immediately send divertingLegInformation1 APDU */
-+ if (rose_diverting_leg_information1_encode(ctrl, call)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for divertingLegInfo1\n");
-+ }
-+ }
-+ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
-+
-+ /* immediately send divertingLegInformation3 APDU */
-+ if (rose_diverting_leg_information3_encode(ctrl, call, Q931_FACILITY)
-+ || q931_facility(ctrl, call)) {
-+ pri_message(ctrl,
-+ "Could not schedule facility message for divertingLegInfo3\n");
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ break;
-+ default:
-+ pri_message(ctrl, "Ignored redirecting update because call in state %s(%d).\n",
-+ q931_call_state_str(call->ourcallstate), call->ourcallstate);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
- #if 0
- /* deprecated routines, use pri_hangup */
- int pri_release(struct pri *pri, q931_call *call, int cause)
-@@ -619,7 +960,7 @@
- return -1;
- if (cause == -1)
- /* normal clear cause */
-- cause = 16;
-+ cause = PRI_CAUSE_NORMAL_CLEARING;
- return q931_hangup(pri, call, cause);
- }
-
-@@ -630,6 +971,14 @@
- return q931_restart(pri, channel);
- }
-
-+int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus)
-+{
-+ if (!pri) {
-+ return -1;
-+ }
-+ return maintenance_service(pri, span, channel, changestatus);
-+}
-+
- q931_call *pri_new_call(struct pri *pri)
- {
- if (!pri)
-@@ -637,6 +986,14 @@
- return q931_new_call(pri);
- }
-
-+int pri_is_dummy_call(q931_call *call)
-+{
-+ if (!call) {
-+ return 0;
-+ }
-+ return q931_is_dummy_call(call);
-+}
-+
- void pri_dump_event(struct pri *pri, pri_event *e)
- {
- if (!pri || !e)
-@@ -667,7 +1024,10 @@
- static void pri_sr_init(struct pri_sr *req)
- {
- memset(req, 0, sizeof(struct pri_sr));
--
-+ q931_party_redirecting_init(&req->redirecting);
-+ q931_party_id_init(&req->caller);
-+ q931_party_address_init(&req->called);
-+ req->reversecharge = PRI_REVERSECHARGE_NONE;
- }
-
- int pri_sr_set_connection_call_independent(struct pri_sr *req)
-@@ -675,10 +1035,21 @@
- if (!req)
- return -1;
-
-- req->justsignalling = 1; /* have to set justsignalling for all those pesky IEs we need to setup */
-+ req->cis_call = 1; /* have to set cis_call for all those pesky IEs we need to setup */
-+ req->cis_auto_disconnect = 1;
- return 0;
- }
-
-+int pri_sr_set_no_channel_call(struct pri_sr *req)
-+{
-+ if (!req) {
-+ return -1;
-+ }
-+
-+ req->cis_call = 1;
-+ return 0;
-+}
-+
- /* Don't call any other pri functions on this */
- int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called,
- int calledplan)
-@@ -689,14 +1060,9 @@
-
- pri_sr_init(&req);
- pri_sr_set_connection_call_independent(&req);
-+ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
-+ pri_sr_set_called(&req, called, calledplan, 0);
-
-- req.caller = caller;
-- req.callerplan = callerplan;
-- req.callername = callername;
-- req.callerpres = callerpres;
-- req.called = called;
-- req.calledplan = calledplan;
--
- if (mwi_message_send(pri, c, &req, 1) < 0) {
- pri_message(pri, "Unable to send MWI activate message\n");
- return -1;
-@@ -714,14 +1080,9 @@
-
- pri_sr_init(&req);
- pri_sr_set_connection_call_independent(&req);
-+ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
-+ pri_sr_set_called(&req, called, calledplan, 0);
-
-- req.caller = caller;
-- req.callerplan = callerplan;
-- req.callername = callername;
-- req.callerpres = callerpres;
-- req.called = called;
-- req.calledplan = calledplan;
--
- if(mwi_message_send(pri, c, &req, 0) < 0) {
- pri_message(pri, "Unable to send MWI deactivate message\n");
- return -1;
-@@ -740,22 +1101,18 @@
-
- int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
- int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called,
-- int calledplan,int ulayer1)
-+ int calledplan, int ulayer1)
- {
- struct pri_sr req;
- if (!pri || !c)
- return -1;
- pri_sr_init(&req);
-+ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
-+ pri_sr_set_called(&req, called, calledplan, 0);
- req.transmode = transmode;
- req.channel = channel;
- req.exclusive = exclusive;
- req.nonisdn = nonisdn;
-- req.caller = caller;
-- req.callerplan = callerplan;
-- req.callername = callername;
-- req.callerpres = callerpres;
-- req.called = called;
-- req.calledplan = calledplan;
- req.userl1 = ulayer1;
- return q931_setup(pri, c, &req);
- }
-@@ -773,28 +1130,85 @@
- __pri_error = func;
- }
-
--void pri_message(struct pri *pri, char *fmt, ...)
-+static void pri_old_message(struct pri *ctrl, const char *fmt, va_list *ap)
- {
- char tmp[1024];
-- va_list ap;
-- va_start(ap, fmt);
-- vsnprintf(tmp, sizeof(tmp), fmt, ap);
-- va_end(ap);
-+
-+ vsnprintf(tmp, sizeof(tmp), fmt, *ap);
- if (__pri_message)
-- __pri_message(pri, tmp);
-+ __pri_message(ctrl, tmp);
- else
- fputs(tmp, stdout);
- }
-
--void pri_error(struct pri *pri, char *fmt, ...)
-+void pri_message(struct pri *ctrl, const char *fmt, ...)
- {
-+ int added_length;
-+ va_list ap;
-+
-+ ctrl = PRI_MASTER(ctrl);
-+ if (!ctrl || !ctrl->msg_line) {
-+ /* Just have to do it the old way. */
-+ va_start(ap, fmt);
-+ pri_old_message(ctrl, fmt, &ap);
-+ va_end(ap);
-+ return;
-+ }
-+
-+ va_start(ap, fmt);
-+ added_length = vsnprintf(ctrl->msg_line->str + ctrl->msg_line->length,
-+ sizeof(ctrl->msg_line->str) - ctrl->msg_line->length, fmt, ap);
-+ va_end(ap);
-+ if (added_length < 0
-+ || sizeof(ctrl->msg_line->str) <= ctrl->msg_line->length + added_length) {
-+ static char truncated_output[] =
-+ "v-- Error building output or output was truncated. (Next line) --v\n";
-+
-+ /*
-+ * This clause should never need to run because the
-+ * output line accumulation buffer is quite large.
-+ */
-+
-+ /* vsnprintf() error or output string was truncated. */
-+ if (__pri_message) {
-+ __pri_message(ctrl, truncated_output);
-+ } else {
-+ fputs(truncated_output, stdout);
-+ }
-+
-+ /* Add a terminating '\n' to force a flush of the line. */
-+ ctrl->msg_line->length = strlen(ctrl->msg_line->str);
-+ if (ctrl->msg_line->length) {
-+ ctrl->msg_line->str[ctrl->msg_line->length - 1] = '\n';
-+ } else {
-+ ctrl->msg_line->str[0] = '\n';
-+ ctrl->msg_line->str[1] = '\0';
-+ }
-+ } else {
-+ ctrl->msg_line->length += added_length;
-+ }
-+
-+ if (ctrl->msg_line->length
-+ && ctrl->msg_line->str[ctrl->msg_line->length - 1] == '\n') {
-+ /* The accumulated output line was terminated so send it out. */
-+ ctrl->msg_line->length = 0;
-+ if (__pri_message) {
-+ __pri_message(ctrl, ctrl->msg_line->str);
-+ } else {
-+ fputs(ctrl->msg_line->str, stdout);
-+ }
-+ }
-+}
-+
-+void pri_error(struct pri *pri, const char *fmt, ...)
-+{
- char tmp[1024];
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(tmp, sizeof(tmp), fmt, ap);
- va_end(ap);
- if (__pri_error)
-- __pri_error(pri, tmp);
-+ __pri_error(PRI_MASTER(pri), tmp);
- else
- fputs(tmp, stderr);
- }
-@@ -821,49 +1235,102 @@
- return pri->fd;
- }
-
--char *pri_dump_info_str(struct pri *pri)
-+/*!
-+ * \internal
-+ * \brief Append snprintf output to the given buffer.
-+ *
-+ * \param buf Buffer currently filling.
-+ * \param buf_used Offset into buffer where to put new stuff.
-+ * \param buf_size Actual buffer size of buf.
-+ * \param format printf format string.
-+ *
-+ * \return Total buffer space used.
-+ */
-+static size_t pri_snprintf(char *buf, size_t buf_used, size_t buf_size, const char *format, ...) __attribute__((format(printf, 4, 5)));
-+static size_t pri_snprintf(char *buf, size_t buf_used, size_t buf_size, const char *format, ...)
- {
-- char buf[4096];
-- int len = 0;
-+ va_list args;
-+
-+ if (buf_used < buf_size) {
-+ va_start(args, format);
-+ buf_used += vsnprintf(buf + buf_used, buf_size - buf_used, format, args);
-+ va_end(args);
-+ }
-+ if (buf_size < buf_used) {
-+ buf_used = buf_size + 1;
-+ }
-+ return buf_used;
-+}
-+
-+char *pri_dump_info_str(struct pri *ctrl)
-+{
-+ char *buf;
-+ size_t buf_size;
-+ size_t used;
- #ifdef LIBPRI_COUNTERS
- struct q921_frame *f;
-- int q921outstanding = 0;
-+ unsigned q921outstanding;
- #endif
-- if (!pri)
-+ unsigned idx;
-+ unsigned long switch_bit;
-+
-+ if (!ctrl) {
- return NULL;
-+ }
-
-+ buf_size = 4096; /* This should be bigger than we will ever need. */
-+ buf = malloc(buf_size);
-+ if (!buf) {
-+ return NULL;
-+ }
-+
- /* Might be nice to format these a little better */
-- len += sprintf(buf + len, "Switchtype: %s\n", pri_switch2str(pri->switchtype));
-- len += sprintf(buf + len, "Type: %s\n", pri_node2str(pri->localtype));
-+ used = 0;
-+ used = pri_snprintf(buf, used, buf_size, "Switchtype: %s\n",
-+ pri_switch2str(ctrl->switchtype));
-+ used = pri_snprintf(buf, used, buf_size, "Type: %s\n", pri_node2str(ctrl->localtype));
- #ifdef LIBPRI_COUNTERS
- /* Remember that Q921 Counters include Q931 packets (and any retransmissions) */
-- len += sprintf(buf + len, "Q931 RX: %d\n", pri->q931_rxcount);
-- len += sprintf(buf + len, "Q931 TX: %d\n", pri->q931_txcount);
-- len += sprintf(buf + len, "Q921 RX: %d\n", pri->q921_rxcount);
-- len += sprintf(buf + len, "Q921 TX: %d\n", pri->q921_txcount);
-- f = pri->txqueue;
-+ used = pri_snprintf(buf, used, buf_size, "Q931 RX: %d\n", ctrl->q931_rxcount);
-+ used = pri_snprintf(buf, used, buf_size, "Q931 TX: %d\n", ctrl->q931_txcount);
-+ used = pri_snprintf(buf, used, buf_size, "Q921 RX: %d\n", ctrl->q921_rxcount);
-+ used = pri_snprintf(buf, used, buf_size, "Q921 TX: %d\n", ctrl->q921_txcount);
-+ q921outstanding = 0;
-+ f = ctrl->txqueue;
- while (f) {
- q921outstanding++;
- f = f->next;
- }
-- len += sprintf(buf + len, "Q921 Outstanding: %d\n", q921outstanding);
-+ used = pri_snprintf(buf, used, buf_size, "Q921 Outstanding: %u\n", q921outstanding);
- #endif
-- len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen, pri->window);
-- len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej);
-- len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit);
-- len += sprintf(buf + len, "Retrans: %d\n", pri->retrans);
-- len += sprintf(buf + len, "Busy: %d\n", pri->busy);
-- len += sprintf(buf + len, "Overlap Dial: %d\n", pri->overlapdial);
-- len += sprintf(buf + len, "Logical Channel Mapping: %d\n", pri->chan_mapping_logical);
-- len += sprintf(buf + len, "T200 Timer: %d\n", pri->timers[PRI_TIMER_T200]);
-- len += sprintf(buf + len, "T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]);
-- len += sprintf(buf + len, "T305 Timer: %d\n", pri->timers[PRI_TIMER_T305]);
-- len += sprintf(buf + len, "T308 Timer: %d\n", pri->timers[PRI_TIMER_T308]);
-- len += sprintf(buf + len, "T309 Timer: %d\n", pri->timers[PRI_TIMER_T309]);
-- len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]);
-- len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]);
-+ used = pri_snprintf(buf, used, buf_size, "Window Length: %d/%d\n", ctrl->windowlen,
-+ ctrl->window);
-+ used = pri_snprintf(buf, used, buf_size, "Sentrej: %d\n", ctrl->sentrej);
-+ used = pri_snprintf(buf, used, buf_size, "SolicitFbit: %d\n", ctrl->solicitfbit);
-+ used = pri_snprintf(buf, used, buf_size, "Retrans: %d\n", ctrl->retrans);
-+ used = pri_snprintf(buf, used, buf_size, "Busy: %d\n", ctrl->busy);
-+ used = pri_snprintf(buf, used, buf_size, "Overlap Dial: %d\n", ctrl->overlapdial);
-+ used = pri_snprintf(buf, used, buf_size, "Logical Channel Mapping: %d\n",
-+ ctrl->chan_mapping_logical);
-+ used = pri_snprintf(buf, used, buf_size, "Timer and counter settings:\n");
-+ switch_bit = PRI_BIT(ctrl->switchtype);
-+ for (idx = 0; idx < ARRAY_LEN(pri_timer); ++idx) {
-+ if (pri_timer[idx].used_by & switch_bit) {
-+ enum PRI_TIMERS_AND_COUNTERS tmr;
-
-- return strdup(buf);
-+ tmr = pri_timer[idx].number;
-+ if (0 <= ctrl->timers[tmr] || tmr == PRI_TIMER_T309) {
-+ used = pri_snprintf(buf, used, buf_size, " %s: %d\n",
-+ pri_timer[idx].name, ctrl->timers[tmr]);
-+ }
-+ }
-+ }
-+
-+ if (buf_size < used) {
-+ pri_message(ctrl,
-+ "pri_dump_info_str(): Produced output exceeded buffer capacity. (Truncated)\n");
-+ }
-+ return buf;
- }
-
- int pri_get_crv(struct pri *pri, q931_call *call, int *callmode)
-@@ -913,26 +1380,213 @@
-
- int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int numcomplete)
- {
-- sr->called = called;
-- sr->calledplan = calledplan;
-+ q931_party_address_init(&sr->called);
-+ if (called) {
-+ sr->called.number.valid = 1;
-+ sr->called.number.plan = calledplan;
-+ libpri_copy_string(sr->called.number.str, called, sizeof(sr->called.number.str));
-+ }
- sr->numcomplete = numcomplete;
- return 0;
- }
-
-+void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress)
-+{
-+ pri_copy_party_subaddress_to_q931(&sr->called.subaddress, subaddress);
-+}
-+
- int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres)
- {
-- sr->caller = caller;
-- sr->callername = callername;
-- sr->callerplan = callerplan;
-- sr->callerpres = callerpres;
-+ q931_party_id_init(&sr->caller);
-+ if (caller) {
-+ sr->caller.number.valid = 1;
-+ sr->caller.number.presentation = callerpres;
-+ sr->caller.number.plan = callerplan;
-+ libpri_copy_string(sr->caller.number.str, caller, sizeof(sr->caller.number.str));
-+
-+ if (callername) {
-+ sr->caller.name.valid = 1;
-+ sr->caller.name.presentation = callerpres;
-+ sr->caller.name.char_set = PRI_CHAR_SET_ISO8859_1;
-+ libpri_copy_string(sr->caller.name.str, callername,
-+ sizeof(sr->caller.name.str));
-+ }
-+ }
- return 0;
- }
-
-+void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress)
-+{
-+ pri_copy_party_subaddress_to_q931(&sr->caller.subaddress, subaddress);
-+}
-+
-+void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller)
-+{
-+ pri_copy_party_id_to_q931(&sr->caller, caller);
-+}
-+
- int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason)
- {
-- sr->redirectingnum = num;
-- sr->redirectingplan = plan;
-- sr->redirectingpres = pres;
-- sr->redirectingreason = reason;
-+ q931_party_redirecting_init(&sr->redirecting);
-+ if (num && num[0]) {
-+ sr->redirecting.from.number.valid = 1;
-+ sr->redirecting.from.number.presentation = pres;
-+ sr->redirecting.from.number.plan = plan;
-+ libpri_copy_string(sr->redirecting.from.number.str, num,
-+ sizeof(sr->redirecting.from.number.str));
-+
-+ sr->redirecting.count = 1;
-+ sr->redirecting.reason = reason;
-+ }
- return 0;
- }
-+
-+void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting)
-+{
-+ pri_copy_party_id_to_q931(&sr->redirecting.from, &redirecting->from);
-+ pri_copy_party_id_to_q931(&sr->redirecting.to, &redirecting->to);
-+ pri_copy_party_id_to_q931(&sr->redirecting.orig_called, &redirecting->orig_called);
-+ sr->redirecting.orig_reason = redirecting->orig_reason;
-+ sr->redirecting.reason = redirecting->reason;
-+ if (redirecting->count <= 0) {
-+ if (sr->redirecting.from.number.valid) {
-+ /*
-+ * We are redirecting with an unknown count
-+ * so assume the count is one.
-+ */
-+ sr->redirecting.count = 1;
-+ } else {
-+ sr->redirecting.count = 0;
-+ }
-+ } else if (redirecting->count < PRI_MAX_REDIRECTS) {
-+ sr->redirecting.count = redirecting->count;
-+ } else {
-+ sr->redirecting.count = PRI_MAX_REDIRECTS;
-+ }
-+}
-+
-+void pri_sr_set_reversecharge(struct pri_sr *sr, int requested)
-+{
-+ sr->reversecharge = requested;
-+}
-+
-+void pri_sr_set_keypad_digits(struct pri_sr *sr, const char *keypad_digits)
-+{
-+ sr->keypad_digits = keypad_digits;
-+}
-+
-+void pri_hold_enable(struct pri *ctrl, int enable)
-+{
-+ ctrl = PRI_MASTER(ctrl);
-+ if (ctrl) {
-+ ctrl->hold_support = enable ? 1 : 0;
-+ }
-+}
-+
-+int pri_hold(struct pri *ctrl, q931_call *call)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_hold(ctrl, call);
-+}
-+
-+int pri_hold_ack(struct pri *ctrl, q931_call *call)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_hold_ack(ctrl, call);
-+}
-+
-+int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_hold_rej(ctrl, call, cause);
-+}
-+
-+int pri_retrieve(struct pri *ctrl, q931_call *call, int channel)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_retrieve(ctrl, call, channel);
-+}
-+
-+int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_retrieve_ack(ctrl, call, channel);
-+}
-+
-+int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause)
-+{
-+ if (!ctrl || !call) {
-+ return -1;
-+ }
-+ return q931_send_retrieve_rej(ctrl, call, cause);
-+}
-+
-+int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
-+{
-+ if (!pri || !call || !dest)
-+ return -1;
-+
-+ return qsig_cf_callrerouting(pri, call, dest, original, reason);
-+}
-+
-+void pri_reroute_enable(struct pri *ctrl, int enable)
-+{
-+ ctrl = PRI_MASTER(ctrl);
-+ if (ctrl) {
-+ ctrl->deflection_support = enable ? 1 : 0;
-+ }
-+}
-+
-+int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_id *caller, const struct pri_party_redirecting *deflection, int subscription_option)
-+{
-+ const struct q931_party_id *caller_id;
-+ struct q931_party_id local_caller;
-+ struct q931_party_redirecting reroute;
-+
-+ if (!ctrl || !call || !deflection) {
-+ return -1;
-+ }
-+
-+ if (caller) {
-+ /* Convert the caller update information. */
-+ pri_copy_party_id_to_q931(&local_caller, caller);
-+ q931_party_id_fixup(ctrl, &local_caller);
-+ caller_id = &local_caller;
-+ } else {
-+ caller_id = NULL;
-+ }
-+
-+ /* Convert the deflection information. */
-+ q931_party_redirecting_init(&reroute);
-+ pri_copy_party_id_to_q931(&reroute.from, &deflection->from);
-+ q931_party_id_fixup(ctrl, &reroute.from);
-+ pri_copy_party_id_to_q931(&reroute.to, &deflection->to);
-+ q931_party_id_fixup(ctrl, &reroute.to);
-+ pri_copy_party_id_to_q931(&reroute.orig_called, &deflection->orig_called);
-+ q931_party_id_fixup(ctrl, &reroute.orig_called);
-+ reroute.reason = deflection->reason;
-+ reroute.orig_reason = deflection->orig_reason;
-+ if (deflection->count <= 0) {
-+ /*
-+ * We are deflecting with an unknown count
-+ * so assume the count is one.
-+ */
-+ reroute.count = 1;
-+ } else if (deflection->count < PRI_MAX_REDIRECTS) {
-+ reroute.count = deflection->count;
-+ } else {
-+ reroute.count = PRI_MAX_REDIRECTS;
-+ }
-+
-+ return send_reroute_request(ctrl, call, caller_id, &reroute, subscription_option);
-+}
-Index: Makefile
-===================================================================
---- a/Makefile (.../tags/1.4.10.2) (revision 1357)
-+++ b/Makefile (.../branches/1.4) (revision 1357)
-@@ -41,15 +41,55 @@
-
- STATIC_LIBRARY=libpri.a
- DYNAMIC_LIBRARY:=libpri.so.$(SONAME)
--STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o version.o
--DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo version.lo
--CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
-+STATIC_OBJS= \
-+ copy_string.o \
-+ pri.o \
-+ q921.o \
-+ prisched.o \
-+ q931.o \
-+ pri_facility.o \
-+ asn1_primitive.o \
-+ rose.o \
-+ rose_address.o \
-+ rose_etsi_aoc.o \
-+ rose_etsi_diversion.o \
-+ rose_etsi_ect.o \
-+ rose_other.o \
-+ rose_q931.o \
-+ rose_qsig_aoc.o \
-+ rose_qsig_ct.o \
-+ rose_qsig_diversion.o \
-+ rose_qsig_mwi.o \
-+ rose_qsig_name.o \
-+ version.o
-+DYNAMIC_OBJS= \
-+ copy_string.lo \
-+ pri.lo \
-+ q921.lo \
-+ prisched.lo \
-+ q931.lo \
-+ pri_facility.lo \
-+ asn1_primitive.lo \
-+ rose.lo \
-+ rose_address.lo \
-+ rose_etsi_aoc.lo \
-+ rose_etsi_diversion.lo \
-+ rose_etsi_ect.lo \
-+ rose_other.lo \
-+ rose_q931.lo \
-+ rose_qsig_aoc.lo \
-+ rose_qsig_ct.lo \
-+ rose_qsig_diversion.lo \
-+ rose_qsig_mwi.lo \
-+ rose_qsig_name.lo \
-+ version.lo
-+CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS) $(LIBPRI_OPT)
- INSTALL_PREFIX=$(DESTDIR)
- INSTALL_BASE=/usr
- libdir?=$(INSTALL_BASE)/lib
- SOFLAGS:=-Wl,-h$(DYNAMIC_LIBRARY)
- LDCONFIG = /sbin/ldconfig
--ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX))
-+ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX XGNUX))
- LDCONFIG_FLAGS=-n
- else
- ifeq (${OSARCH},FreeBSD)
-@@ -74,7 +114,9 @@
- #A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesnt support it.
- ifeq ($(PROC),sparc64)
- PROC=ultrasparc
--CFLAGS += -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
-+LIBPRI_OPT = -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
-+else
-+LIBPRI_OPT = -O2
- endif
-
- all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
-@@ -132,6 +174,9 @@
- pridump: pridump.o
- $(CC) -o pridump pridump.o -L. -lpri $(CFLAGS)
-
-+rosetest: rosetest.o
-+ $(CC) -o rosetest rosetest.o -L. -lpri $(CFLAGS)
-+
- MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP
-
- %.o: %.c
-Index: q931.c
-===================================================================
---- a/q931.c (.../tags/1.4.10.2) (revision 1357)
-+++ b/q931.c (.../branches/1.4) (revision 1357)
-@@ -33,6 +33,7 @@
- #include "pri_q921.h"
- #include "pri_q931.h"
- #include "pri_facility.h"
-+#include "rose.h"
-
- #include <unistd.h>
- #include <stdlib.h>
-@@ -67,7 +68,7 @@
- { Q931_RESTART_ACKNOWLEDGE, "RESTART ACKNOWLEDGE", { Q931_RESTART_INDICATOR } },
-
- /* Miscellaneous */
-- { Q931_STATUS, "STATUS", { Q931_CAUSE, Q931_CALL_STATE } },
-+ { Q931_STATUS, "STATUS", { Q931_CAUSE, Q931_IE_CALL_STATE } },
- { Q931_STATUS_ENQUIRY, "STATUS ENQUIRY" },
- { Q931_USER_INFORMATION, "USER_INFORMATION" },
- { Q931_SEGMENT, "SEGMENT" },
-@@ -79,22 +80,32 @@
- /* Call Management */
- { Q931_HOLD, "HOLD" },
- { Q931_HOLD_ACKNOWLEDGE, "HOLD ACKNOWLEDGE" },
-- { Q931_HOLD_REJECT, "HOLD REJECT" },
-+ { Q931_HOLD_REJECT, "HOLD REJECT", { Q931_CAUSE } },
- { Q931_RETRIEVE, "RETRIEVE" },
- { Q931_RETRIEVE_ACKNOWLEDGE, "RETRIEVE ACKNOWLEDGE" },
-- { Q931_RETRIEVE_REJECT, "RETRIEVE REJECT" },
-+ { Q931_RETRIEVE_REJECT, "RETRIEVE REJECT", { Q931_CAUSE } },
- { Q931_RESUME, "RESUME" },
- { Q931_RESUME_ACKNOWLEDGE, "RESUME ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
- { Q931_RESUME_REJECT, "RESUME REJECT", { Q931_CAUSE } },
- { Q931_SUSPEND, "SUSPEND" },
- { Q931_SUSPEND_ACKNOWLEDGE, "SUSPEND ACKNOWLEDGE" },
- { Q931_SUSPEND_REJECT, "SUSPEND REJECT" },
-+};
-
-- /* Maintenance */
-- { NATIONAL_SERVICE, "SERVICE" },
-- { NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" },
-+static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand);
-+static void nt_ptmp_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int *allow_event, int *allow_posthandle);
-+
-+struct msgtype att_maintenance_msgs[] = {
-+ { ATT_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
-+ { ATT_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
- };
-
-+struct msgtype national_maintenance_msgs[] = {
-+ { NATIONAL_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
-+ { NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
-+};
-+static int post_handle_maintenance_message(struct pri *ctrl, int protodisc, struct q931_mh *mh, struct q931_call *c);
-+
- static struct msgtype causes[] = {
- { PRI_CAUSE_UNALLOCATED, "Unallocated (unassigned) number" },
- { PRI_CAUSE_NO_ROUTE_TRANSIT_NET, "No route to specified transmit network" },
-@@ -107,6 +118,7 @@
- { PRI_CAUSE_NO_ANSWER, "User alerting, no answer" },
- { PRI_CAUSE_CALL_REJECTED, "Call Rejected" },
- { PRI_CAUSE_NUMBER_CHANGED, "Number changed" },
-+ { PRI_CAUSE_NONSELECTED_USER_CLEARING, "Non-selected user clearing" },
- { PRI_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order" },
- { PRI_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format" },
- { PRI_CAUSE_FACILITY_REJECTED, "Facility rejected" },
-@@ -119,13 +131,14 @@
- { PRI_CAUSE_ACCESS_INFO_DISCARDED, "Access information discarded" },
- { PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel not available" },
- { PRI_CAUSE_PRE_EMPTED, "Pre-empted" },
-+ { PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED, "Resource unavailable, unspecified" },
- { PRI_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed" },
- { PRI_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred" },
- { PRI_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred" },
- { PRI_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized" },
- { PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available" },
-+ { PRI_CAUSE_SERVICEOROPTION_NOTAVAIL, "Service or option not available, unspecified" },
- { PRI_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented" },
-- { PRI_CAUSE_SERVICEOROPTION_NOTAVAIL, "Service or option not available, unspecified" },
- { PRI_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented" },
- { PRI_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented" },
- { PRI_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference value" },
-@@ -163,8 +176,9 @@
- { PRI_NSF_CALL_REDIRECTION_SERVICE, "Call Redirection Service" }
- };
-
--#define FLAG_PREFERRED 2
--#define FLAG_EXCLUSIVE 4
-+#define FLAG_WHOLE_INTERFACE 0x01
-+#define FLAG_PREFERRED 0x02
-+#define FLAG_EXCLUSIVE 0x04
-
- #define RESET_INDICATOR_CHANNEL 0
- #define RESET_INDICATOR_DS1 6
-@@ -214,26 +228,49 @@
- #define LOC_NETWORK_BEYOND_INTERWORKING 0xa
-
- static char *ie2str(int ie);
--static char *msg2str(int msg);
-
-
--#define FUNC_DUMP(name) void ((name))(int full_ie, struct pri *pri, q931_ie *ie, int len, char prefix)
--#define FUNC_RECV(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
--#define FUNC_SEND(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+#define FUNC_DUMP(name) void (name)(int full_ie, struct pri *pri, q931_ie *ie, int len, char prefix)
-+#define FUNC_RECV(name) int (name)(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
-+#define FUNC_SEND(name) int (name)(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-
- #if 1
- /* Update call state with transition trace. */
--#define UPDATE_OURCALLSTATE(pri,c,newstate) do {\
-- if (pri->debug & (PRI_DEBUG_Q931_STATE) && c->ourcallstate != newstate) \
-- pri_message(pri, DBGHEAD "call %d on channel %d enters state %d (%s)\n", DBGINFO, \
-- c->cr, c->channelno, newstate, callstate2str(newstate)); \
-- c->ourcallstate = newstate; \
-+#define UPDATE_OURCALLSTATE(ctrl, call, newstate) \
-+ do { \
-+ if (((ctrl)->debug & PRI_DEBUG_Q931_STATE) && (call)->ourcallstate != (newstate)) { \
-+ pri_message((ctrl), \
-+ DBGHEAD "%s %d enters state %d (%s). Hold state: %s\n", \
-+ DBGINFO, ((call) == (call)->master_call) ? "Call" : "Subcall", \
-+ (call)->cr, (newstate), q931_call_state_str(newstate), \
-+ q931_hold_state_str((call)->master_call->hold_state)); \
-+ } \
-+ (call)->ourcallstate = (newstate); \
- } while (0)
- #else
- /* Update call state with no trace. */
--#define UPDATE_OURCALLSTATE(pri,c,newstate) c->ourcallstate = newstate
-+#define UPDATE_OURCALLSTATE(ctrl, call, newstate) (call)->ourcallstate = (newstate)
- #endif
-
-+#if 1
-+/* Update hold state with transition trace. */
-+#define UPDATE_HOLD_STATE(ctrl, master_call, newstate) \
-+ do { \
-+ if (((ctrl)->debug & PRI_DEBUG_Q931_STATE) \
-+ && (master_call)->hold_state != (newstate)) { \
-+ pri_message((ctrl), \
-+ DBGHEAD "Call %d in state %d (%s) enters Hold state: %s\n", \
-+ DBGINFO, (master_call)->cr, (master_call)->ourcallstate, \
-+ q931_call_state_str((master_call)->ourcallstate), \
-+ q931_hold_state_str(newstate)); \
-+ } \
-+ (master_call)->hold_state = (newstate); \
-+ } while (0)
-+#else
-+/* Update hold state with no trace. */
-+#define UPDATE_HOLD_STATE(ctrl, master_call, newstate) (master_call)->hold_state = (newstate)
-+#endif
-+
- struct ie {
- /* Maximal count of same IEs at the message (0 - any, 1..n - limited) */
- int max_count;
-@@ -249,6 +286,506 @@
- FUNC_SEND(*transmit);
- };
-
-+/*!
-+ * \internal
-+ * \brief Encode the channel id information to pass to upper level.
-+ *
-+ * \param call Q.931 call leg
-+ *
-+ * \return Encoded channel value.
-+ */
-+static int q931_encode_channel(const q931_call *call)
-+{
-+ int held_call;
-+ int channelno;
-+ int ds1no;
-+
-+ switch (call->master_call->hold_state) {
-+ case Q931_HOLD_STATE_CALL_HELD:
-+ case Q931_HOLD_STATE_RETRIEVE_REQ:
-+ case Q931_HOLD_STATE_RETRIEVE_IND:
-+ held_call = 1 << 18;
-+
-+ /* So a -1 does not wipe out the held_call flag. */
-+ channelno = call->channelno & 0xFF;
-+ ds1no = call->ds1no & 0xFF;
-+ break;
-+ default:
-+ held_call = 0;
-+ channelno = call->channelno;
-+ ds1no = call->ds1no;
-+ break;
-+ }
-+ return channelno | (ds1no << 8) | (call->ds1explicit << 16) | (call->cis_call << 17)
-+ | held_call;
-+}
-+
-+/*!
-+ * \brief Determine if layer 2 is in PTMP mode.
-+ *
-+ * \param ctrl D channel controller.
-+ *
-+ * \retval TRUE if in PTMP mode.
-+ * \retval FALSE otherwise.
-+ */
-+int q931_is_ptmp(const struct pri *ctrl)
-+{
-+ /* Check master control structure */
-+ for (; ctrl->master; ctrl = ctrl->master) {
-+ }
-+ return ctrl->tei == Q921_TEI_GROUP;
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_name
-+ *
-+ * \param name Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_name_init(struct q931_party_name *name)
-+{
-+ name->valid = 0;
-+ name->presentation = PRI_PRES_UNAVAILABLE;
-+ name->char_set = PRI_CHAR_SET_ISO8859_1;
-+ name->str[0] = '\0';
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_number
-+ *
-+ * \param number Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_number_init(struct q931_party_number *number)
-+{
-+ number->valid = 0;
-+ number->presentation = PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ number->plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
-+ number->str[0] = '\0';
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_subaddress
-+ *
-+ * \param subaddress Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_subaddress_init(struct q931_party_subaddress *subaddress)
-+{
-+ subaddress->valid = 0;
-+ subaddress->type = 0;
-+ subaddress->odd_even_indicator = 0;
-+ subaddress->length = 0;
-+ subaddress->data[0] = '\0';
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_address
-+ *
-+ * \param address Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_address_init(struct q931_party_address *address)
-+{
-+ q931_party_number_init(&address->number);
-+ q931_party_subaddress_init(&address->subaddress);
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_id
-+ *
-+ * \param id Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_id_init(struct q931_party_id *id)
-+{
-+ q931_party_name_init(&id->name);
-+ q931_party_number_init(&id->number);
-+ q931_party_subaddress_init(&id->subaddress);
-+}
-+
-+/*!
-+ * \brief Initialize the given struct q931_party_redirecting
-+ *
-+ * \param redirecting Structure to initialize
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_redirecting_init(struct q931_party_redirecting *redirecting)
-+{
-+ q931_party_id_init(&redirecting->from);
-+ q931_party_id_init(&redirecting->to);
-+ q931_party_id_init(&redirecting->orig_called);
-+ redirecting->state = Q931_REDIRECTING_STATE_IDLE;
-+ redirecting->count = 0;
-+ redirecting->orig_reason = PRI_REDIR_UNKNOWN;
-+ redirecting->reason = PRI_REDIR_UNKNOWN;
-+}
-+
-+/*!
-+ * \brief Compare the left and right party name.
-+ *
-+ * \param left Left parameter party name.
-+ * \param right Right parameter party name.
-+ *
-+ * \retval < 0 when left < right.
-+ * \retval == 0 when left == right.
-+ * \retval > 0 when left > right.
-+ */
-+int q931_party_name_cmp(const struct q931_party_name *left, const struct q931_party_name *right)
-+{
-+ int cmp;
-+
-+ if (!left->valid) {
-+ if (!right->valid) {
-+ return 0;
-+ }
-+ return -1;
-+ } else if (!right->valid) {
-+ return 1;
-+ }
-+ cmp = left->char_set - right->char_set;
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = strcmp(left->str, right->str);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = left->presentation - right->presentation;
-+ return cmp;
-+}
-+
-+/*!
-+ * \brief Compare the left and right party number.
-+ *
-+ * \param left Left parameter party number.
-+ * \param right Right parameter party number.
-+ *
-+ * \retval < 0 when left < right.
-+ * \retval == 0 when left == right.
-+ * \retval > 0 when left > right.
-+ */
-+int q931_party_number_cmp(const struct q931_party_number *left, const struct q931_party_number *right)
-+{
-+ int cmp;
-+
-+ if (!left->valid) {
-+ if (!right->valid) {
-+ return 0;
-+ }
-+ return -1;
-+ } else if (!right->valid) {
-+ return 1;
-+ }
-+ cmp = left->plan - right->plan;
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = strcmp(left->str, right->str);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = left->presentation - right->presentation;
-+ return cmp;
-+}
-+
-+/*!
-+ * \brief Compare the left and right party subaddress.
-+ *
-+ * \param left Left parameter party subaddress.
-+ * \param right Right parameter party subaddress.
-+ *
-+ * \retval < 0 when left < right.
-+ * \retval == 0 when left == right.
-+ * \retval > 0 when left > right.
-+ */
-+int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right)
-+{
-+ int cmp;
-+
-+ if (!left->valid) {
-+ if (!right->valid) {
-+ return 0;
-+ }
-+ return -1;
-+ } else if (!right->valid) {
-+ return 1;
-+ }
-+ cmp = left->type - right->type;
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = memcmp(left->data, right->data,
-+ (left->length < right->length) ? left->length : right->length);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = left->length - right->length;
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = left->odd_even_indicator - right->odd_even_indicator;
-+ return cmp;
-+}
-+
-+/*!
-+ * \brief Compare the left and right party id.
-+ *
-+ * \param left Left parameter party id.
-+ * \param right Right parameter party id.
-+ *
-+ * \retval < 0 when left < right.
-+ * \retval == 0 when left == right.
-+ * \retval > 0 when left > right.
-+ */
-+int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_id *right)
-+{
-+ int cmp;
-+
-+ cmp = q931_party_number_cmp(&left->number, &right->number);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = q931_party_subaddress_cmp(&left->subaddress, &right->subaddress);
-+ if (cmp) {
-+ return cmp;
-+ }
-+ cmp = q931_party_name_cmp(&left->name, &right->name);
-+ return cmp;
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 party name to the PRI party name structure.
-+ *
-+ * \param pri_name PRI party name structure
-+ * \param q931_name Q.931 party name structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_name_copy_to_pri(struct pri_party_name *pri_name, const struct q931_party_name *q931_name)
-+{
-+ if (q931_name->valid) {
-+ pri_name->valid = 1;
-+ pri_name->presentation = q931_name->presentation;
-+ pri_name->char_set = q931_name->char_set;
-+ libpri_copy_string(pri_name->str, q931_name->str, sizeof(pri_name->str));
-+ } else {
-+ pri_name->valid = 0;
-+ pri_name->presentation = PRI_PRES_UNAVAILABLE;
-+ pri_name->char_set = PRI_CHAR_SET_ISO8859_1;
-+ pri_name->str[0] = 0;
-+ }
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 party number to the PRI party number structure.
-+ *
-+ * \param pri_number PRI party number structure
-+ * \param q931_number Q.931 party number structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const struct q931_party_number *q931_number)
-+{
-+ if (q931_number->valid) {
-+ pri_number->valid = 1;
-+ pri_number->presentation = q931_number->presentation;
-+ pri_number->plan = q931_number->plan;
-+ libpri_copy_string(pri_number->str, q931_number->str, sizeof(pri_number->str));
-+ } else {
-+ pri_number->valid = 0;
-+ pri_number->presentation = PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ pri_number->plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
-+ pri_number->str[0] = 0;
-+ }
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 party subaddress to the PRI party subaddress structure.
-+ *
-+ * \param pri_subaddress PRI party subaddress structure
-+ * \param q931_subaddress Q.931 party subaddress structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress)
-+{
-+ int length;
-+
-+ /*
-+ * The size of pri_subaddress->data[] is not the same as the size of
-+ * q931_subaddress->data[].
-+ */
-+
-+ if (!q931_subaddress->valid) {
-+ pri_subaddress->valid = 0;
-+ pri_subaddress->type = 0;
-+ pri_subaddress->odd_even_indicator = 0;
-+ pri_subaddress->length = 0;
-+ pri_subaddress->data[0] = '\0';
-+ return;
-+ }
-+
-+ pri_subaddress->valid = 1;
-+ pri_subaddress->type = q931_subaddress->type;
-+ pri_subaddress->odd_even_indicator = q931_subaddress->odd_even_indicator;
-+
-+ length = q931_subaddress->length;
-+ pri_subaddress->length = length;
-+ memcpy(pri_subaddress->data, q931_subaddress->data, length);
-+ pri_subaddress->data[length] = '\0';
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 party id to the PRI party id structure.
-+ *
-+ * \param pri_id PRI party id structure
-+ * \param q931_id Q.931 party id structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_party_id *q931_id)
-+{
-+ q931_party_name_copy_to_pri(&pri_id->name, &q931_id->name);
-+ q931_party_number_copy_to_pri(&pri_id->number, &q931_id->number);
-+ q931_party_subaddress_copy_to_pri(&pri_id->subaddress, &q931_id->subaddress);
-+}
-+
-+/*!
-+ * \brief Copy the Q.931 redirecting data to the PRI redirecting structure.
-+ *
-+ * \param pri_redirecting PRI redirecting structure
-+ * \param q931_redirecting Q.931 redirecting structure
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_redirecting_copy_to_pri(struct pri_party_redirecting *pri_redirecting, const struct q931_party_redirecting *q931_redirecting)
-+{
-+ q931_party_id_copy_to_pri(&pri_redirecting->from, &q931_redirecting->from);
-+ q931_party_id_copy_to_pri(&pri_redirecting->to, &q931_redirecting->to);
-+ q931_party_id_copy_to_pri(&pri_redirecting->orig_called,
-+ &q931_redirecting->orig_called);
-+ pri_redirecting->count = q931_redirecting->count;
-+ pri_redirecting->orig_reason = q931_redirecting->orig_reason;
-+ pri_redirecting->reason = q931_redirecting->reason;
-+}
-+
-+/*!
-+ * \brief Fixup some values in the q931_party_id that may be objectionable by switches.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param id Party ID to tweak.
-+ *
-+ * \return Nothing
-+ */
-+void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id)
-+{
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_DMS100:
-+ case PRI_SWITCH_ATT4ESS:
-+ /* Doesn't like certain presentation types */
-+ if (id->number.valid && !(id->number.presentation & 0x7c)) {
-+ /* i.e., If presentation is allowed it must be a network number */
-+ id->number.presentation = PRES_ALLOWED_NETWORK_NUMBER;
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+/*!
-+ * \brief Determine the overall presentation value for the given party.
-+ *
-+ * \param id Party to determine the overall presentation value.
-+ *
-+ * \return Overall presentation value for the given party.
-+ */
-+int q931_party_id_presentation(const struct q931_party_id *id)
-+{
-+ int number_priority;
-+ int number_value;
-+ int number_screening;
-+ int name_priority;
-+ int name_value;
-+
-+ /* Determine name presentation priority. */
-+ if (!id->name.valid) {
-+ name_value = PRI_PRES_UNAVAILABLE;
-+ name_priority = 3;
-+ } else {
-+ name_value = id->name.presentation & PRI_PRES_RESTRICTION;
-+ switch (name_value) {
-+ case PRI_PRES_RESTRICTED:
-+ name_priority = 0;
-+ break;
-+ case PRI_PRES_ALLOWED:
-+ name_priority = 1;
-+ break;
-+ case PRI_PRES_UNAVAILABLE:
-+ name_priority = 2;
-+ break;
-+ default:
-+ name_value = PRI_PRES_UNAVAILABLE;
-+ name_priority = 3;
-+ break;
-+ }
-+ }
-+
-+ /* Determine number presentation priority. */
-+ if (!id->number.valid) {
-+ number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
-+ number_value = PRI_PRES_UNAVAILABLE;
-+ number_priority = 3;
-+ } else {
-+ number_screening = id->number.presentation & PRI_PRES_NUMBER_TYPE;
-+ number_value = id->number.presentation & PRI_PRES_RESTRICTION;
-+ switch (number_value) {
-+ case PRI_PRES_RESTRICTED:
-+ number_priority = 0;
-+ break;
-+ case PRI_PRES_ALLOWED:
-+ number_priority = 1;
-+ break;
-+ case PRI_PRES_UNAVAILABLE:
-+ number_priority = 2;
-+ break;
-+ default:
-+ number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
-+ number_value = PRI_PRES_UNAVAILABLE;
-+ number_priority = 3;
-+ break;
-+ }
-+ }
-+
-+ /* Select the wining presentation value. */
-+ if (name_priority < number_priority) {
-+ number_value = name_value;
-+ }
-+
-+ return number_value | number_screening;
-+}
-+
-+static void q931_clr_subcommands(struct pri *ctrl)
-+{
-+ ctrl->subcmds.counter_subcmd = 0;
-+}
-+
-+struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl)
-+{
-+ if (ctrl->subcmds.counter_subcmd < PRI_MAX_SUBCOMMANDS) {
-+ return &ctrl->subcmds.subcmd[ctrl->subcmds.counter_subcmd++];
-+ }
-+
-+ return NULL;
-+}
-+
- static char *code2str(int code, struct msgtype *codes, int max)
- {
- int x;
-@@ -258,15 +795,18 @@
- return "Unknown";
- }
-
--static void call_init(struct q931_call *c)
-+static char *pritype(int type)
- {
-- c->forceinvert = -1;
-- c->cr = -1;
-- c->slotmap = -1;
-- c->channelno = -1;
-- c->newcall = 1;
-- c->ourcallstate = Q931_CALL_STATE_NULL;
-- c->peercallstate = Q931_CALL_STATE_NULL;
-+ switch (type) {
-+ case PRI_CPE:
-+ return "CPE";
-+ break;
-+ case PRI_NETWORK:
-+ return "NET";
-+ break;
-+ default:
-+ return "UNKNOWN";
-+ }
- }
-
- static char *binary(int b, int len) {
-@@ -280,56 +820,85 @@
- return res;
- }
-
--static FUNC_RECV(receive_channel_id)
-+static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- int x;
-- int pos=0;
--#ifdef NO_BRI_SUPPORT
-- if (!ie->data[0] & 0x20) {
-- pri_error(pri, "!! Not PRI type!?\n");
-- return -1;
-- }
--#endif
--#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
-- if (pri->bri) {
-- if (!(ie->data[0] & 3))
-- call->justsignalling = 1;
-- else
-- call->channelno = ie->data[0] & 3;
-+ int pos = 0;
-+ int need_extended_channel_octets;/*!< TRUE if octets 3.2 and 3.3 need to be present. */
-+
-+ if (ie->data[0] & 0x08) {
-+ call->chanflags = FLAG_EXCLUSIVE;
- } else {
-- switch (ie->data[0] & 3) {
-- case 0:
-- call->justsignalling = 1;
-- break;
-- case 1:
-- break;
-- default:
-- pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
-- return -1;
-+ call->chanflags = FLAG_PREFERRED;
-+ }
-+
-+ need_extended_channel_octets = 0;
-+ if (ie->data[0] & 0x20) {
-+ /* PRI encoded interface type */
-+ switch (ie->data[0] & 0x03) {
-+ case 0x00:
-+ /* No channel */
-+ call->channelno = 0;
-+ call->chanflags = FLAG_PREFERRED;
-+ break;
-+ case 0x01:
-+ /* As indicated in following octets */
-+ need_extended_channel_octets = 1;
-+ break;
-+ case 0x03:
-+ /* Any channel */
-+ call->chanflags = FLAG_PREFERRED;
-+ break;
-+ default:
-+ pri_error(ctrl, "!! Unexpected Channel selection %d\n", ie->data[0] & 0x03);
-+ return -1;
- }
-+ } else {
-+ /* BRI encoded interface type */
-+ switch (ie->data[0] & 0x03) {
-+ case 0x00:
-+ /* No channel */
-+ call->channelno = 0;
-+ call->chanflags = FLAG_PREFERRED;
-+ break;
-+ case 0x03:
-+ /* Any channel */
-+ call->chanflags = FLAG_PREFERRED;
-+ break;
-+ default:
-+ /* Specified B channel (B1 or B2) */
-+ call->channelno = ie->data[0] & 0x03;
-+ break;
-+ }
- }
--#endif
-- if (ie->data[0] & 0x08)
-- call->chanflags = FLAG_EXCLUSIVE;
-- else
-- call->chanflags = FLAG_PREFERRED;
-+
- pos++;
- if (ie->data[0] & 0x40) {
- /* DS1 specified -- stop here */
- call->ds1no = ie->data[1] & 0x7f;
- call->ds1explicit = 1;
- pos++;
-- } else
-+ } else {
- call->ds1explicit = 0;
-+ }
-
-- if (pos+2 < len) {
-+ if (ie->data[0] & 0x04) {
-+ /* D channel call. Signaling only. */
-+ call->cis_call = 1;
-+ call->chanflags = FLAG_EXCLUSIVE;/* For safety mark this channel as exclusive. */
-+ call->channelno = 0;
-+ return 0;
-+ }
-+
-+ if (need_extended_channel_octets && pos + 2 < len) {
- /* More coming */
- if ((ie->data[pos] & 0x0f) != 3) {
-- pri_error(pri, "!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
-+ /* Channel type/mapping is not for B channel units. */
-+ pri_error(ctrl, "!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
- return -1;
- }
- if ((ie->data[pos] & 0x60) != 0) {
-- pri_error(pri, "!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
-+ pri_error(ctrl, "!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
- return -1;
- }
- if (ie->data[pos] & 0x10) {
-@@ -340,136 +909,167 @@
- call->slotmap <<= 8;
- call->slotmap |= ie->data[x + pos];
- }
-- return 0;
- } else {
- pos++;
- /* Only expect a particular channel */
- call->channelno = ie->data[pos] & 0x7f;
-- if (pri->chan_mapping_logical && call->channelno > 15)
-+ if (ctrl->chan_mapping_logical && call->channelno > 15)
- call->channelno++;
-- return 0;
- }
-- } else
-- return 0;
-- return -1;
-+ }
-+ return 0;
- }
-
--static FUNC_SEND(transmit_channel_id)
-+static int transmit_channel_id(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- int pos=0;
-+ int pos = 0;
-
--
- /* We are ready to transmit single IE only */
- if (order > 1)
- return 0;
--
-- if (call->justsignalling) {
-- ie->data[pos++] = 0xac; /* Read the standards docs to figure this out
-- ECMA-165 section 7.3 */
-+
-+ if (call->cis_call) {
-+ /*
-+ * Read the standards docs to figure this out.
-+ * Q.SIG ECMA-165 section 7.3
-+ * ITU Q.931 section 4.5.13
-+ */
-+ ie->data[pos++] = ctrl->bri ? 0x8c : 0xac;
- return pos + 2;
- }
--
-+
- /* Start with standard stuff */
-- if (pri->switchtype == PRI_SWITCH_GR303_TMC)
-+ if (ctrl->switchtype == PRI_SWITCH_GR303_TMC)
- ie->data[pos] = 0x69;
-- else if (pri->bri) {
-+ else if (ctrl->bri) {
- ie->data[pos] = 0x80;
-- if (call->channelno > -1)
-- ie->data[pos] |= (call->channelno & 0x3);
-- } else
-- ie->data[pos] = 0xa1;
-- /* Add exclusive flag if necessary */
-- if (call->chanflags & FLAG_EXCLUSIVE)
-+ ie->data[pos] |= (call->channelno & 0x3);
-+ } else {
-+ /* PRI */
-+ if (call->slotmap != -1 || (call->chanflags & FLAG_WHOLE_INTERFACE)) {
-+ /* Specified channel */
-+ ie->data[pos] = 0xa1;
-+ } else if (call->channelno < 0 || call->channelno == 0xff) {
-+ /* Any channel */
-+ ie->data[pos] = 0xa3;
-+ } else if (!call->channelno) {
-+ /* No channel */
-+ ie->data[pos] = 0xa0;
-+ } else {
-+ /* Specified channel */
-+ ie->data[pos] = 0xa1;
-+ }
-+ }
-+ if (call->chanflags & FLAG_EXCLUSIVE) {
-+ /* Channel is exclusive */
- ie->data[pos] |= 0x08;
-- else if (!(call->chanflags & FLAG_PREFERRED)) {
-+ } else if (!call->chanflags) {
- /* Don't need this IE */
- return 0;
- }
-
-- if (((pri->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit) {
-- /* Note that we are specifying the identifier */
-+ if (!ctrl->bri && (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit)) {
-+ /* We are specifying the interface. Octet 3.1 */
- ie->data[pos++] |= 0x40;
-- /* We need to use the Channel Identifier Present thingy. Just specify it and we're done */
- ie->data[pos++] = 0x80 | call->ds1no;
-- } else
-- pos++;
-+ } else {
-+ ++pos;
-+ }
-
-- if (pri->bri)
-- return pos + 2;
-+ if (!ctrl->bri && (ie->data[0] & 0x03) == 0x01 /* Specified channel */
-+ && !(call->chanflags & FLAG_WHOLE_INTERFACE)) {
-+ /* The 3.2 and 3.3 octets need to be present */
-+ ie->data[pos] = 0x83;
-+ if (call->slotmap != -1) {
-+ int octet;
-
-- if ((call->channelno > -1) || (call->slotmap != -1)) {
-- /* We'll have the octet 8.2 and 8.3's present */
-- ie->data[pos++] = 0x83;
-- if (call->channelno > -1) {
-+ /* We have to send a channel map */
-+ ie->data[pos++] |= 0x10;
-+ for (octet = 3; octet--;) {
-+ ie->data[pos++] = (call->slotmap >> (8 * octet)) & 0xff;
-+ }
-+ } else {
- /* Channel number specified */
-- if (pri->chan_mapping_logical && call->channelno > 16)
-+ ++pos;
-+ if (ctrl->chan_mapping_logical && call->channelno > 16) {
- ie->data[pos++] = 0x80 | (call->channelno - 1);
-- else
-+ } else {
- ie->data[pos++] = 0x80 | call->channelno;
-- return pos + 2;
-+ }
- }
-- /* We have to send a channel map */
-- if (call->slotmap != -1) {
-- ie->data[pos-1] |= 0x10;
-- ie->data[pos++] = (call->slotmap & 0xff0000) >> 16;
-- ie->data[pos++] = (call->slotmap & 0xff00) >> 8;
-- ie->data[pos++] = (call->slotmap & 0xff);
-- return pos + 2;
-- }
- }
-- if (call->ds1no > 0) {
-- /* We're done */
-- return pos + 2;
-- }
-- pri_error(pri, "!! No channel map, no channel, and no ds1? What am I supposed to identify?\n");
-- return -1;
-+
-+ return pos + 2;
- }
-
--static FUNC_DUMP(dump_channel_id)
-+static void dump_channel_id(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- int pos=0;
-+ int pos;
- int x;
-- int res = 0;
-- static const char* msg_chan_sel[] = {
-- "No channel selected", "B1 channel", "B2 channel","Any channel selected",
-- "No channel selected", "As indicated in following octets", "Reserved","Any channel selected"
-+ int res;
-+
-+ static const char *msg_chan_sel[] = {
-+ "No channel selected", "B1 channel", "B2 channel", "Any channel selected",
-+ "No channel selected", "As indicated in following octets", "Reserved", "Any channel selected"
- };
-
-- pri_message(pri, "%c Channel ID (len=%2d) [ Ext: %d IntID: %s %s Spare: %d %s Dchan: %d\n",
-- prefix, len, (ie->data[0] & 0x80) ? 1 : 0, (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
-- (ie->data[0] & 0x20) ? "PRI" : "Other", (ie->data[0] & 0x10) ? 1 : 0,
-- (ie->data[0] & 0x08) ? "Exclusive" : "Preferred", (ie->data[0] & 0x04) ? 1 : 0);
-- pri_message(pri, "%c ChanSel: %s\n",
-- prefix, msg_chan_sel[(ie->data[0] & 0x3) + ((ie->data[0]>>3) & 0x4)]);
-- pos++;
-- len--;
-- if (ie->data[0] & 0x40) {
-+ pri_message(ctrl,
-+ "%c Channel ID (len=%2d) [ Ext: %d IntID: %s %s Spare: %d %s Dchan: %d\n",
-+ prefix, len,
-+ (ie->data[0] & 0x80) ? 1 : 0,
-+ (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
-+ (ie->data[0] & 0x20) ? "Other(PRI)" : "BRI",
-+ (ie->data[0] & 0x10) ? 1 : 0,
-+ (ie->data[0] & 0x08) ? "Exclusive" : "Preferred",
-+ (ie->data[0] & 0x04) ? 1 : 0);
-+ pri_message(ctrl, "%c ChanSel: %s\n",
-+ prefix, msg_chan_sel[(ie->data[0] & 0x03) | ((ie->data[0] >> 3) & 0x04)]);
-+ pos = 1;
-+ len -= 2;
-+ if (ie->data[0] & 0x40) {
- /* Explicitly defined DS1 */
-- pri_message(pri, "%c Ext: %d DS1 Identifier: %d \n", prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
-- pos++;
-+ do {
-+ pri_message(ctrl, "%c Ext: %d DS1 Identifier: %d \n",
-+ prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
-+ ++pos;
-+ } while (!(ie->data[pos - 1] & 0x80) && pos < len);
- } else {
- /* Implicitly defined DS1 */
- }
-- if (pos+2 < len) {
-+ if (pos < len) {
- /* Still more information here */
-- pri_message(pri, "%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
-- prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
-- (ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
-- if (!(ie->data[pos] & 0x10)) {
-+ pri_message(ctrl,
-+ "%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
-+ prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
-+ (ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
-+ ++pos;
-+ }
-+ if (pos < len) {
-+ if (!(ie->data[pos - 1] & 0x10)) {
- /* Number specified */
-- pos++;
-- pri_message(pri, "%c Ext: %d Channel: %d ]\n", prefix, (ie->data[pos] & 0x80) >> 7,
-- (ie->data[pos]) & 0x7f);
-+ do {
-+ pri_message(ctrl,
-+ "%c Ext: %d Channel: %d Type: %s%c\n",
-+ prefix, (ie->data[pos] & 0x80) >> 7,
-+ (ie->data[pos]) & 0x7f, pritype(ctrl->localtype),
-+ (pos + 1 < len) ? ' ' : ']');
-+ ++pos;
-+ } while (pos < len);
- } else {
-- pos++;
- /* Map specified */
-- for (x=0;x<3;x++) {
-+ res = 0;
-+ x = 0;
-+ do {
- res <<= 8;
- res |= ie->data[pos++];
-- }
-- pri_message(pri, "%c Map: %s ]\n", prefix, binary(res, 24));
-+ ++x;
-+ } while (pos < len);
-+ pri_message(ctrl, "%c Map len: %d Map: %s ]\n", prefix,
-+ x, binary(res, x << 3));
- }
-- } else pri_message(pri, " ]\n");
-+ } else {
-+ pri_message(ctrl, " ]\n");
-+ }
- }
-
- static char *ri2str(int ri)
-@@ -482,20 +1082,20 @@
- return code2str(ri, ris, sizeof(ris) / sizeof(ris[0]));
- }
-
--static FUNC_DUMP(dump_restart_indicator)
-+static void dump_restart_indicator(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Restart Indentifier (len=%2d) [ Ext: %d Spare: %d Resetting %s (%d) ]\n",
-+ pri_message(ctrl, "%c Restart Indentifier (len=%2d) [ Ext: %d Spare: %d Resetting %s (%d) ]\n",
- prefix, len, (ie->data[0] & 0x80) >> 7, (ie->data[0] & 0x78) >> 3, ri2str(ie->data[0] & 0x7), ie->data[0] & 0x7);
- }
-
--static FUNC_RECV(receive_restart_indicator)
-+static int receive_restart_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- /* Pretty simple */
- call->ri = ie->data[0] & 0x7;
- return 0;
- }
-
--static FUNC_SEND(transmit_restart_indicator)
-+static int transmit_restart_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- /* Pretty simple */
- switch(call->ri) {
-@@ -509,7 +1109,7 @@
- ie->data[0] = 0xA0 | (call->ri & 0x7);
- break;
- default:
-- pri_error(pri, "!! Invalid restart indicator value %d\n", call->ri);
-+ pri_error(ctrl, "!! Invalid restart indicator value %d\n", call->ri);
- return-1;
- }
- return 3;
-@@ -607,16 +1207,16 @@
- return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
- }
-
--static FUNC_DUMP(dump_bearer_capability)
-+static void dump_bearer_capability(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int pos=2;
-- pri_message(pri, "%c Bearer Capability (len=%2d) [ Ext: %d Q.931 Std: %d Info transfer capability: %s (%d)\n",
-+ pri_message(ctrl, "%c Bearer Capability (len=%2d) [ Ext: %d Q.931 Std: %d Info transfer capability: %s (%d)\n",
- prefix, len, (ie->data[0] & 0x80 ) >> 7, (ie->data[0] & 0x60) >> 5, cap2str(ie->data[0] & 0x1f), (ie->data[0] & 0x1f));
-- pri_message(pri, "%c Ext: %d Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
-+ pri_message(ctrl, "%c Ext: %d Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
-
- /* octet 4.1 exists iff mode/rate is multirate */
- if ((ie->data[1] & 0x7f) == 0x18) {
-- pri_message(pri, "%c Ext: %d Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
-+ pri_message(ctrl, "%c Ext: %d Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
- pos++;
- }
-
-@@ -632,7 +1232,7 @@
- too, so we have to do the same for binary compatability */
- u_int8_t layer1 = ie->data[pos] & 0x7f;
-
-- pri_message(pri, "%c User information layer 1: %s (%d)\n",
-+ pri_message(ctrl, "%c User information layer 1: %s (%d)\n",
- prefix, l12str(layer1), layer1);
- pos++;
-
-@@ -640,7 +1240,7 @@
- if (pos < len && !(ie->data[pos-1] & 0x80)) {
- int ra = ie->data[pos] & 0x7f;
-
-- pri_message(pri, "%c Async: %d, Negotiation: %d, "
-+ pri_message(ctrl, "%c Async: %d, Negotiation: %d, "
- "User rate: %s (%#x)\n",
- prefix,
- ra & PRI_RATE_ADAPT_ASYNC ? 1 : 0,
-@@ -654,7 +1254,7 @@
- if (pos < len && !(ie->data[pos-1] & 0x80)) {
- u_int8_t data = ie->data[pos];
- if (layer1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
-- pri_message(pri, "%c Intermediate rate: %s (%d), "
-+ pri_message(ctrl, "%c Intermediate rate: %s (%d), "
- "NIC on Tx: %d, NIC on Rx: %d, "
- "Flow control on Tx: %d, "
- "Flow control on Rx: %d\n",
-@@ -665,7 +1265,7 @@
- (data & 0x04)?1:0,
- (data & 0x02)?1:0);
- } else if (layer1 == PRI_LAYER_1_V120_RATE_ADAPT) {
-- pri_message(pri, "%c Hdr: %d, Multiframe: %d, Mode: %d, "
-+ pri_message(ctrl, "%c Hdr: %d, Multiframe: %d, Mode: %d, "
- "LLI negot: %d, Assignor: %d, "
- "In-band neg: %d\n", prefix,
- (data & 0x40)?1:0,
-@@ -675,7 +1275,8 @@
- (data & 0x04)?1:0,
- (data & 0x02)?1:0);
- } else {
-- pri_message(pri, "%c Unknown octet 5b: 0x%x\n", data );
-+ pri_message(ctrl, "%c Unknown octet 5b: 0x%x\n",
-+ prefix, data);
- }
- pos++;
- }
-@@ -688,7 +1289,7 @@
- const char *parity[] = {"Odd","?","Even","None",
- "zero","one","?","?"};
-
-- pri_message(pri, "%c Stop bits: %s, data bits: %s, "
-+ pri_message(ctrl, "%c Stop bits: %s, data bits: %s, "
- "parity: %s\n", prefix,
- stop_bits[(data & 0x60) >> 5],
- data_bits[(data & 0x18) >> 3],
-@@ -700,7 +1301,7 @@
- /* octet 5d? */
- if (pos < len && !(ie->data[pos-1] & 0x80)) {
- u_int8_t data = ie->data[pos];
-- pri_message(pri, "%c Duplex mode: %d, modem type: %d\n",
-+ pri_message(ctrl, "%c Duplex mode: %d, modem type: %d\n",
- prefix, (data & 0x40) ? 1 : 0,data & 0x3F);
- pos++;
- }
-@@ -710,7 +1311,7 @@
- /* Look for octet 6; this is identified by bits 5,6 == 10 */
- if (pos < len &&
- (ie->data[pos] & 0x60) == 0x40) {
-- pri_message(pri, "%c User information layer 2: %s (%d)\n",
-+ pri_message(ctrl, "%c User information layer 2: %s (%d)\n",
- prefix, l22str(ie->data[pos] & 0x1f),
- ie->data[pos] & 0x1f);
- pos++;
-@@ -718,7 +1319,7 @@
-
- /* Look for octet 7; this is identified by bits 5,6 == 11 */
- if (pos < len && (ie->data[pos] & 0x60) == 0x60) {
-- pri_message(pri, "%c User information layer 3: %s (%d)\n",
-+ pri_message(ctrl, "%c User information layer 3: %s (%d)\n",
- prefix, l32str(ie->data[pos] & 0x1f),
- ie->data[pos] & 0x1f);
- pos++;
-@@ -730,18 +1331,18 @@
- proto = ((ie->data[pos] & 0xF) << 4 ) |
- (ie->data[pos+1] & 0xF);
-
-- pri_message(pri, "%c Network layer: 0x%x\n", prefix,
-+ pri_message(ctrl, "%c Network layer: 0x%x\n", prefix,
- proto );
- pos += 2;
- }
- }
- }
-
--static FUNC_RECV(receive_bearer_capability)
-+static int receive_bearer_capability(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- int pos=2;
- if (ie->data[0] & 0x60) {
-- pri_error(pri, "!! non-standard Q.931 standard field\n");
-+ pri_error(ctrl, "!! non-standard Q.931 standard field\n");
- return -1;
- }
- call->transcapability = ie->data[0] & 0x1f;
-@@ -788,7 +1389,7 @@
- return 0;
- }
-
--static FUNC_SEND(transmit_bearer_capability)
-+static int transmit_bearer_capability(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- int tc;
- int pos;
-@@ -797,20 +1398,20 @@
- if(order > 1)
- return 0;
-
-- tc = call->transcapability;
-- if (pri->subchannel && !pri->bri) {
-+ if (ctrl->subchannel && !ctrl->bri) {
- /* Bearer capability is *hard coded* in GR-303 */
- ie->data[0] = 0x88;
- ie->data[1] = 0x90;
- return 4;
- }
--
-- if (call->justsignalling) {
-+
-+ if (call->cis_call) {
- ie->data[0] = 0xa8;
- ie->data[1] = 0x80;
- return 4;
- }
--
-+
-+ tc = call->transcapability;
- ie->data[0] = 0x80 | tc;
- ie->data[1] = call->transmoderate | 0x80;
-
-@@ -820,7 +1421,7 @@
- ie->data[pos++] = call->transmultiple | 0x80;
- }
-
-- if ((tc & PRI_TRANS_CAP_DIGITAL) && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&
-+ if ((tc & PRI_TRANS_CAP_DIGITAL) && (ctrl->switchtype == PRI_SWITCH_EUROISDN_E1) &&
- (call->transmoderate == TRANS_MODE_PACKET)) {
- /* Apparently EuroISDN switches don't seem to like user layer 2/3 */
- return 4;
-@@ -833,7 +1434,7 @@
-
- if (call->transmoderate != TRANS_MODE_PACKET) {
- /* If you have an AT&T 4ESS, you don't send any more info */
-- if ((pri->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
-+ if ((ctrl->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
- ie->data[pos++] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
- if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
- ie->data[pos++] = call->rateadaption | 0x80;
-@@ -908,6 +1509,30 @@
- return code2str(plan, plans, sizeof(plans) / sizeof(plans[0]));
- }
-
-+/* Calling Party Category (Definitions from Q.763) */
-+static char *cpc2str(int plan)
-+{
-+ static struct msgtype plans[] = {
-+ { 0, "Unknown Source" },
-+ { 1, "Operator French" },
-+ { 2, "Operator English" },
-+ { 3, "Operator German" },
-+ { 4, "Operator Russian" },
-+ { 5, "Operator Spanish" },
-+ { 6, "Mut Agree Chinese" },
-+ { 7, "Mut Agreement" },
-+ { 8, "Mut Agree Japanese" },
-+ { 9, "National Operator" },
-+ { 10, "Ordinary Toll Caller" },
-+ { 11, "Priority Toll Caller" },
-+ { 12, "Data Call" },
-+ { 13, "Test Call" },
-+ { 14, "Spare" },
-+ { 15, "Pay Phone" },
-+ };
-+ return code2str(plan, plans, ARRAY_LEN(plans));
-+}
-+
- char *pri_pres2str(int pres)
- {
- static struct msgtype press[] = {
-@@ -934,51 +1559,134 @@
- num[len] = 0;
- }
-
--static FUNC_DUMP(dump_called_party_number)
-+static void q931_get_subaddr_specific(unsigned char *num, int maxlen, unsigned char *src, int len, char oddflag)
- {
-- unsigned char cnum[256];
-+ /* User Specified */
-+ int x;
-+ char *ptr = (char *) num;
-
-- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-- pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
-- prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+ if (len <= 0) {
-+ num[0] = '\0';
-+ return;
-+ }
-+
-+ if (((len * 2) + 1) > maxlen) {
-+ len = (maxlen / 2) - 1;
-+ }
-+
-+ for (x = 0; x < (len - 1); ++x) {
-+ ptr += sprintf(ptr, "%02x", src[x]);
-+ }
-+
-+ if (oddflag) {
-+ /* ODD */
-+ sprintf(ptr, "%01x", (src[len - 1]) >> 4);
-+ } else {
-+ /* EVEN */
-+ sprintf(ptr, "%02x", src[len - 1]);
-+ }
- }
-
--static FUNC_DUMP(dump_called_party_subaddr)
-+static int transmit_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, int msgtype, q931_ie *ie, int offset, int len, int order)
- {
-+ size_t datalen;
-+
-+ if (!q931_subaddress->valid) {
-+ return 0;
-+ }
-+
-+ datalen = q931_subaddress->length;
-+ if (!q931_subaddress->type) {
-+ /* 0 = NSAP */
-+ /* 0 = Odd/Even indicator */
-+ ie->data[0] = 0x80;
-+ } else {
-+ /* 2 = User Specified */
-+ ie->data[0] = q931_subaddress->odd_even_indicator ? 0xA8 : 0xA0;
-+ }
-+ memcpy(ie->data + offset, q931_subaddress->data, datalen);
-+
-+ return datalen + (offset + 2);
-+}
-+
-+static int receive_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, int msgtype, q931_ie *ie, int offset, int len)
-+{
-+ if (len <= 0) {
-+ return -1;
-+ }
-+
-+ q931_subaddress->valid = 1;
-+ q931_subaddress->length = len;
-+ /* type: 0 = NSAP, 2 = User Specified */
-+ q931_subaddress->type = ((ie->data[0] & 0x70) >> 4);
-+ q931_subaddress->odd_even_indicator = (ie->data[0] & 0x08) ? 1 : 0;
-+ q931_get_number(q931_subaddress->data, sizeof(q931_subaddress->data),
-+ ie->data + offset, len);
-+
-+ return 0;
-+}
-+
-+static void dump_subaddr_helper(int full_ie, struct pri *ctrl, q931_ie *ie, int offset, int len, int datalen, char prefix, const char *named)
-+{
- unsigned char cnum[256];
-- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-- pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
-- prefix, len, ie->data[0] >> 7,
-+
-+ if (!(ie->data[0] & 0x70)) {
-+ /* NSAP */
-+ q931_get_number(cnum, sizeof(cnum), ie->data + offset, datalen);
-+ } else {
-+ /* User Specified */
-+ q931_get_subaddr_specific(cnum, sizeof(cnum), ie->data + offset, datalen,
-+ ie->data[0] & 0x08);
-+ }
-+
-+ pri_message(ctrl,
-+ "%c %s Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
-+ prefix, named, len, ie->data[0] >> 7,
- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- (ie->data[0] & 0x08) >> 3, cnum);
- }
-
--static FUNC_DUMP(dump_calling_party_number)
-+static void dump_called_party_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- unsigned char cnum[256];
-+
-+ q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-+ pri_message(ctrl, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
-+ prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+}
-+
-+static void dump_called_party_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Called");
-+}
-+
-+static void dump_calling_party_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ unsigned char cnum[256];
- if (ie->data[0] & 0x80)
- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
- else
- q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-- pri_message(pri, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
-+ pri_message(ctrl, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- if (ie->data[0] & 0x80)
-- pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
-+ pri_message(ctrl, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
- else
-- pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
-+ pri_message(ctrl, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
- }
-
--static FUNC_DUMP(dump_calling_party_subaddr)
-+static void dump_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- unsigned char cnum[256];
-- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-- pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
-- prefix, len, ie->data[0] >> 7,
-- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
-- (ie->data[0] & 0x08) >> 3, cnum);
-+ dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Calling");
- }
-
--static FUNC_DUMP(dump_redirecting_number)
-+static void dump_calling_party_category(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-+ pri_message(ctrl, "%c Calling Party Category (len=%2d) [ Ext: %d Cat: %s (%d) ]\n",
-+ prefix, len, ie->data[0] >> 7, cpc2str(ie->data[0] & 0x0F), ie->data[0] & 0x0F);
-+}
-+
-+static void dump_redirecting_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
- unsigned char cnum[256];
- int i = 0;
- /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-@@ -986,172 +1694,369 @@
- do {
- switch(i) {
- case 0: /* Octet 3 */
-- pri_message(pri, "%c Redirecting Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
-+ pri_message(ctrl, "%c Redirecting Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
- prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- break;
- case 1: /* Octet 3a */
-- pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
-+ pri_message(ctrl, "\n%c Ext: %d Presentation: %s (%d)",
- prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
- break;
- case 2: /* Octet 3b */
-- pri_message(pri, "\n%c Ext: %d Reason: %s (%d)",
-+ pri_message(ctrl, "\n%c Ext: %d Reason: %s (%d)",
- prefix, ie->data[2] >> 7, redirection_reason2str(ie->data[2] & 0x7f), ie->data[2] & 0x7f);
- break;
- }
-- }
-- while(!(ie->data[i++]& 0x80));
-+ } while(!(ie->data[i++]& 0x80));
- q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
-- pri_message(pri, " '%s' ]\n", cnum);
-+ pri_message(ctrl, " '%s' ]\n", cnum);
- }
-
--static FUNC_DUMP(dump_connected_number)
-+static void dump_redirection_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- unsigned char cnum[256];
- int i = 0;
- /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
- walking through all bytes until one with ext bit (8) set to 1 */
- do {
-+ switch (i) {
-+ case 0: /* Octet 3 */
-+ pri_message(ctrl,
-+ "%c Redirection Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
-+ prefix, len, ie->data[0] >> 7,
-+ ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07,
-+ npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
-+ break;
-+ case 1: /* Octet 3a */
-+ pri_message(ctrl, "\n%c Ext: %d Presentation: %s (%d)",
-+ prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
-+ break;
-+ }
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
-+ pri_message(ctrl, " '%s' ]\n", cnum);
-+}
-+
-+static int receive_connected_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ int i = 0;
-+
-+ call->connected_number_in_message = 1;
-+ call->remote_id.number.valid = 1;
-+ call->remote_id.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-+ walking through all bytes until one with ext bit (8) set to 1 */
-+ do {
-+ switch (i) {
-+ case 0:
-+ call->remote_id.number.plan = ie->data[i] & 0x7f;
-+ break;
-+ case 1:
-+ /* Keep only the presentation and screening fields */
-+ call->remote_id.number.presentation =
-+ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
-+ break;
-+ }
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number((unsigned char *) call->remote_id.number.str, sizeof(call->remote_id.number.str), ie->data + i, ie->len - i);
-+
-+ return 0;
-+}
-+
-+static int transmit_connected_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
-+ size_t datalen;
-+
-+ if (!call->local_id.number.valid) {
-+ return 0;
-+ }
-+
-+ datalen = strlen(call->local_id.number.str);
-+ ie->data[0] = call->local_id.number.plan;
-+ ie->data[1] = 0x80 | call->local_id.number.presentation;
-+ memcpy(ie->data + 2, call->local_id.number.str, datalen);
-+ return datalen + (2 + 2);
-+}
-+
-+static void dump_connected_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ unsigned char cnum[256];
-+ int i = 0;
-+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-+ walking through all bytes until one with ext bit (8) set to 1 */
-+ do {
- switch(i) {
- case 0: /* Octet 3 */
-- pri_message(pri, "%c Connected Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
-+ pri_message(ctrl, "%c Connected Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
- prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- break;
- case 1: /* Octet 3a */
-- pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
-+ pri_message(ctrl, "\n%c Ext: %d Presentation: %s (%d)",
- prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
- break;
- }
-- }
-- while(!(ie->data[i++]& 0x80));
-+ } while(!(ie->data[i++]& 0x80));
- q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
-- pri_message(pri, " '%s' ]\n", cnum);
-+ pri_message(ctrl, " '%s' ]\n", cnum);
- }
-
-+static int receive_connected_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ if (len < 3) {
-+ return -1;
-+ }
-
--static FUNC_RECV(receive_redirecting_number)
-+ return receive_subaddr_helper(full_ie, ctrl, &call->remote_id.subaddress, msgtype, ie,
-+ 1, len - 3);
-+}
-+
-+static int transmit_connected_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-+ return transmit_subaddr_helper(full_ie, ctrl, &call->local_id.subaddress, msgtype, ie,
-+ 1, len, order);
-+}
-+
-+static void dump_connected_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Connected");
-+}
-+
-+static int receive_redirecting_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
- int i = 0;
-
-+ call->redirecting_number_in_message = 1;
-+ call->redirecting.from.number.valid = 1;
-+ call->redirecting.from.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ call->redirecting.reason = PRI_REDIR_UNKNOWN;
- /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
- walking through all bytes until one with ext bit (8) set to 1 */
- do {
-- switch(i) {
-+ switch (i) {
- case 0:
-- call->redirectingplan = ie->data[i] & 0x7f;
-+ call->redirecting.from.number.plan = ie->data[i] & 0x7f;
- break;
- case 1:
-- call->redirectingpres = ie->data[i] & 0x7f;
-+ /* Keep only the presentation and screening fields */
-+ call->redirecting.from.number.presentation =
-+ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
- break;
- case 2:
-- call->redirectingreason = ie->data[i] & 0x0f;
-+ call->redirecting.reason = ie->data[i] & 0x0f;
- break;
- }
-- }
-- while(!(ie->data[i++] & 0x80));
-- q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number((unsigned char *) call->redirecting.from.number.str, sizeof(call->redirecting.from.number.str), ie->data + i, ie->len - i);
- return 0;
- }
-
--static FUNC_SEND(transmit_redirecting_number)
-+static int transmit_redirecting_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-+ size_t datalen;
-+
- if (order > 1)
- return 0;
-- if (call->redirectingnum && *call->redirectingnum) {
-- ie->data[0] = call->redirectingplan;
-- ie->data[1] = call->redirectingpres;
-- ie->data[2] = (call->redirectingreason & 0x0f) | 0x80;
-- memcpy(ie->data + 3, call->redirectingnum, strlen(call->redirectingnum));
-- return strlen(call->redirectingnum) + 3 + 2;
-+ if (!call->redirecting.from.number.valid) {
-+ return 0;
- }
-- return 0;
-+
-+ datalen = strlen(call->redirecting.from.number.str);
-+ ie->data[0] = call->redirecting.from.number.plan;
-+#if 1
-+ /* ETSI and Q.952 do not define the screening field */
-+ ie->data[1] = call->redirecting.from.number.presentation & PRI_PRES_RESTRICTION;
-+#else
-+ /* Q.931 defines the screening field */
-+ ie->data[1] = call->redirecting.from.number.presentation;
-+#endif
-+ ie->data[2] = (call->redirecting.reason & 0x0f) | 0x80;
-+ memcpy(ie->data + 3, call->redirecting.from.number.str, datalen);
-+ return datalen + (3 + 2);
- }
-
--static FUNC_DUMP(dump_redirecting_subaddr)
-+static void dump_redirecting_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- unsigned char cnum[256];
-- q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-- pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
-- prefix, len, ie->data[0] >> 7,
-- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
-- (ie->data[0] & 0x08) >> 3, cnum);
-+ dump_subaddr_helper(full_ie, ctrl, ie, 2, len, len - 4, prefix, "Redirecting");
- }
-
--static FUNC_RECV(receive_calling_party_subaddr)
-+static int receive_redirection_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
-- /* copy digits to call->callingsubaddr */
-- q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3);
-+ int i = 0;
-+
-+ call->redirection_number.valid = 1;
-+ call->redirection_number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-+ walking through all bytes until one with ext bit (8) set to 1 */
-+ do {
-+ switch (i) {
-+ case 0:
-+ call->redirection_number.plan = ie->data[i] & 0x7f;
-+ break;
-+ case 1:
-+ /* Keep only the presentation and screening fields */
-+ call->redirection_number.presentation =
-+ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
-+ break;
-+ }
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number((unsigned char *) call->redirection_number.str, sizeof(call->redirection_number.str), ie->data + i, ie->len - i);
- return 0;
- }
-
--static FUNC_RECV(receive_called_party_number)
-+static int transmit_redirection_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- /* copy digits to call->callednum */
-- q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
-- call->calledplan = ie->data[0] & 0x7f;
-- return 0;
-+ size_t datalen;
-+
-+ if (order > 1) {
-+ return 0;
-+ }
-+ if (!call->redirection_number.valid) {
-+ return 0;
-+ }
-+
-+ datalen = strlen(call->redirection_number.str);
-+ ie->data[0] = call->redirection_number.plan;
-+ ie->data[1] = (call->redirection_number.presentation & PRI_PRES_RESTRICTION) | 0x80;
-+ memcpy(ie->data + 2, call->redirection_number.str, datalen);
-+ return datalen + (2 + 2);
- }
-
--static FUNC_SEND(transmit_called_party_number)
-+static int receive_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
-- ie->data[0] = 0x80 | call->calledplan;
-- if (*call->callednum)
-- memcpy(ie->data + 1, call->callednum, strlen(call->callednum));
-- return strlen(call->callednum) + 3;
-+ if (len < 3) {
-+ return -1;
-+ }
-+
-+ return receive_subaddr_helper(full_ie, ctrl, &call->remote_id.subaddress, msgtype, ie,
-+ 1, len - 3);
- }
-
--static FUNC_RECV(receive_calling_party_number)
-+static int transmit_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- u_int8_t *data;
-- size_t length;
--
-- if (ie->data[0] & 0x80) {
-- data = ie->data + 1;
-- length = len - 3;
-- call->callerpres = 0; /* PI presentation allowed SI user-provided, not screened */
-- } else {
-- data = ie->data + 2;
-- length = len - 4;
-- call->callerpres = ie->data[1] & 0x7f;
-+ return transmit_subaddr_helper(full_ie, ctrl, &call->local_id.subaddress, msgtype, ie,
-+ 1, len, order);
-+}
-+
-+static int receive_called_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ if (len < 3) {
-+ return -1;
- }
-+ return receive_subaddr_helper(full_ie, ctrl, &call->called.subaddress, msgtype, ie, 1,
-+ len - 3);
-+}
-
-- if (call->callerpres == PRES_ALLOWED_NETWORK_NUMBER ||
-- call->callerpres == PRES_PROHIB_NETWORK_NUMBER) {
-- q931_get_number((u_int8_t *)call->callerani, sizeof(call->callerani), data, length);
-- call->callerplanani = ie->data[0] & 0x7f;
-+static int transmit_called_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
-+ return transmit_subaddr_helper(full_ie, ctrl, &call->called.subaddress, msgtype, ie,
-+ 1, len, order);
-+}
-
-- if (!*call->callernum) { /*Copy ANI to CallerID if CallerID is not already set */
-- libpri_copy_string(call->callernum, call->callerani, sizeof(call->callernum));
-- call->callerplan = call->callerplanani;
-+static int receive_called_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ size_t called_len;
-+ size_t max_len;
-+ char *called_end;
-+
-+ if (len < 3) {
-+ return -1;
-+ }
-+
-+ call->called.number.valid = 1;
-+ call->called.number.plan = ie->data[0] & 0x7f;
-+ if (msgtype == Q931_SETUP) {
-+ q931_get_number((unsigned char *) call->called.number.str,
-+ sizeof(call->called.number.str), ie->data + 1, len - 3);
-+ } else if (call->ourcallstate == Q931_CALL_STATE_OVERLAP_RECEIVING) {
-+ /*
-+ * Since we are receiving overlap digits now, we need to append
-+ * them to any previously received digits in call->called.number.str.
-+ */
-+ called_len = strlen(call->called.number.str);
-+ called_end = call->called.number.str + called_len;
-+ max_len = (sizeof(call->called.number.str) - 1) - called_len;
-+ if (max_len < len - 3) {
-+ called_len = max_len;
-+ } else {
-+ called_len = len - 3;
- }
--
-- } else {
-- q931_get_number((u_int8_t *)call->callernum, sizeof(call->callernum), data, length);
-- call->callerplan = ie->data[0] & 0x7f;
-+ strncat(called_end, (char *) ie->data + 1, called_len);
- }
-
-+ q931_get_number((unsigned char *) call->overlap_digits, sizeof(call->overlap_digits),
-+ ie->data + 1, len - 3);
- return 0;
- }
-
--static FUNC_SEND(transmit_calling_party_number)
-+static int transmit_called_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- ie->data[0] = call->callerplan;
-- ie->data[1] = 0x80 | call->callerpres;
-- if (*call->callernum)
-- memcpy(ie->data + 2, call->callernum, strlen(call->callernum));
-- return strlen(call->callernum) + 4;
-+ size_t datalen;
-+
-+ if (!call->called.number.valid) {
-+ return 0;
-+ }
-+
-+ datalen = strlen(call->overlap_digits);
-+ ie->data[0] = 0x80 | call->called.number.plan;
-+ memcpy(ie->data + 1, call->overlap_digits, datalen);
-+ return datalen + (1 + 2);
- }
-
--static FUNC_DUMP(dump_user_user)
-+static int receive_calling_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
-+ int i = 0;
-+
-+ call->remote_id.number.valid = 1;
-+ call->remote_id.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
-+ walking through all bytes until one with ext bit (8) set to 1 */
-+ do {
-+ switch (i) {
-+ case 0:
-+ call->remote_id.number.plan = ie->data[i] & 0x7f;
-+ break;
-+ case 1:
-+ /* Keep only the presentation and screening fields */
-+ call->remote_id.number.presentation =
-+ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
-+ break;
-+ }
-+ } while (!(ie->data[i++] & 0x80));
-+ q931_get_number((unsigned char *) call->remote_id.number.str,
-+ sizeof(call->remote_id.number.str), ie->data + i, ie->len - i);
-+
-+ return 0;
-+}
-+
-+static int transmit_calling_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
-+ size_t datalen;
-+
-+ if (!call->local_id.number.valid) {
-+ return 0;
-+ }
-+
-+ datalen = strlen(call->local_id.number.str);
-+ ie->data[0] = call->local_id.number.plan;
-+ ie->data[1] = 0x80 | call->local_id.number.presentation;
-+ memcpy(ie->data + 2, call->local_id.number.str, datalen);
-+ return datalen + (2 + 2);
-+}
-+
-+static void dump_user_user(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
- int x;
-- pri_message(pri, "%c User-User Information (len=%2d) [", prefix, len);
-+ pri_message(ctrl, "%c User-User Information (len=%2d) [", prefix, len);
- for (x=0;x<ie->len;x++)
-- pri_message(pri, " %02x", ie->data[x] & 0x7f);
-- pri_message(pri, " ]\n");
-+ pri_message(ctrl, " %02x", ie->data[x] & 0x7f);
-+ pri_message(ctrl, " ]\n");
- }
-
-
--static FUNC_RECV(receive_user_user)
-+static int receive_user_user(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->useruserprotocoldisc = ie->data[0] & 0xff;
- if (call->useruserprotocoldisc == 4) /* IA5 */
-@@ -1159,7 +2064,7 @@
- return 0;
- }
-
--static FUNC_SEND(transmit_user_user)
-+static int transmit_user_user(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- int datalen = strlen(call->useruserinfo);
- if (datalen > 0) {
-@@ -1180,6 +2085,29 @@
- return 0;
- }
-
-+static void dump_change_status(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ int x;
-+
-+ pri_message(ctrl, "%c Change Status Information (len=%2d) [", prefix, len);
-+ for (x=0; x<ie->len; x++) {
-+ pri_message(ctrl, " %02x", ie->data[x] & 0x7f);
-+ }
-+ pri_message(ctrl, " ]\n");
-+}
-+
-+static int receive_change_status(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ call->changestatus = ie->data[0] & 0x0f;
-+ return 0;
-+}
-+
-+static int transmit_change_status(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
-+ ie->data[0] = 0xc0 | call->changestatus;
-+ return 3;
-+}
-+
- static char *prog2str(int prog)
- {
- static struct msgtype progs[] = {
-@@ -1222,47 +2150,83 @@
- return code2str(loc, locs, sizeof(locs) / sizeof(locs[0]));
- }
-
--static FUNC_DUMP(dump_progress_indicator)
-+static void dump_progress_indicator(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
-+ pri_message(ctrl, "%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
- prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
- (ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
-- pri_message(pri, "%c Ext: %d Progress Description: %s (%d) ]\n",
-+ pri_message(ctrl, "%c Ext: %d Progress Description: %s (%d) ]\n",
- prefix, ie->data[1] >> 7, prog2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
- }
-
--static FUNC_RECV(receive_display)
-+static int receive_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- unsigned char *data;
-+
-+ switch (msgtype) {
-+ case Q931_SETUP:
-+ case Q931_CONNECT:
-+ /*
-+ * Only keep the display message on SETUP and CONNECT messages
-+ * as the remote name.
-+ */
-+ break;
-+ default:
-+ return 0;
-+ }
-+
-+ call->remote_id.name.valid = 1;
-+
- data = ie->data;
- if (data[0] & 0x80) {
- /* Skip over character set */
- data++;
- len--;
- }
-- q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
-+ call->remote_id.name.char_set = PRI_CHAR_SET_ISO8859_1;
-+
-+ q931_get_number((unsigned char *) call->remote_id.name.str, sizeof(call->remote_id.name.str), data, len - 2);
-+ if (call->remote_id.name.str[0]) {
-+ call->remote_id.name.presentation = PRI_PRES_ALLOWED;
-+ } else {
-+ call->remote_id.name.presentation = PRI_PRES_RESTRICTED;
-+ }
- return 0;
- }
-
--static FUNC_SEND(transmit_display)
-+static int transmit_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-+ size_t datalen;
- int i;
--
-- if ((pri->switchtype == PRI_SWITCH_QSIG) ||
-- ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) && (pri->localtype == PRI_CPE)) ||
-- !call->callername[0])
-- return 0;
-
- i = 0;
-- if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
-+
-+ if (!call->local_id.name.valid || !call->local_id.name.str[0]) {
-+ return 0;
-+ }
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_QSIG:
-+ /* Q.SIG supports names */
-+ return 0;
-+ case PRI_SWITCH_EUROISDN_E1:
-+ case PRI_SWITCH_EUROISDN_T1:
-+ if (ctrl->localtype == PRI_CPE) {
-+ return 0;
-+ }
-+ break;
-+ default:
-+ /* Prefix name with character set indicator. */
- ie->data[0] = 0xb1;
- ++i;
-+ break;
- }
-- memcpy(ie->data + i, call->callername, strlen(call->callername));
-- return 2 + i + strlen(call->callername);
-+
-+ datalen = strlen(call->local_id.name.str);
-+ memcpy(ie->data + i, call->local_id.name.str, datalen);
-+ return 2 + i + datalen;
- }
-
--static FUNC_RECV(receive_progress_indicator)
-+static int receive_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->progloc = ie->data[0] & 0xf;
- call->progcode = (ie->data[0] & 0x60) >> 5;
-@@ -1298,153 +2262,204 @@
- call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
- break;
- default:
-- pri_error(pri, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
-+ pri_error(ctrl, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
- break;
- }
- return 0;
- }
-
--static FUNC_SEND(transmit_facility)
-+static void q931_apdu_timeout(void *data);
-+
-+static int transmit_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- struct apdu_event *tmp;
-- int i = 0;
-+ struct apdu_event **prev;
-+ struct apdu_event *cur;
-+ int apdu_len;
-
-- for (tmp = call->apdus; tmp; tmp = tmp->next) {
-- if ((tmp->message == msgtype) && !tmp->sent)
-+ for (prev = &call->apdus, cur = call->apdus;
-+ cur;
-+ prev = &cur->next, cur = cur->next) {
-+ if (!cur->sent && cur->message == msgtype) {
- break;
-+ }
- }
--
-- if (!tmp) /* No APDU found */
-+ if (!cur) {
-+ /* No APDU found */
- return 0;
-+ }
-
-- if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */
-- pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "Adding facility ie contents to send in %s message:\n",
-+ msg2str(msgtype));
-+ facility_decode_dump(ctrl, cur->apdu, cur->apdu_len);
-+ }
-+
-+ if (len < cur->apdu_len) {
-+ pri_error(ctrl,
-+ "Could not fit facility ie in message. Size needed:%d Available space:%d\n",
-+ cur->apdu_len + 2, len);
-+
-+ /* Remove APDU from list. */
-+ *prev = cur->next;
-+
-+ if (cur->response.callback) {
-+ /* Indicate to callback that the APDU had a problem getting sent. */
-+ cur->response.callback(APDU_CALLBACK_REASON_ERROR, ctrl, call, cur, NULL);
-+ }
-+
-+ free(cur);
- return 0;
- }
--
-- memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len);
-- i += tmp->apdu_len;
-- tmp->sent = 1;
-
-- return i + 2;
-+ memcpy(ie->data, cur->apdu, cur->apdu_len);
-+ apdu_len = cur->apdu_len;
-+ cur->sent = 1;
-+
-+ if (cur->response.callback && cur->response.timeout_time) {
-+ int duration;
-+
-+ if (0 < cur->response.timeout_time) {
-+ /* Sender specified timeout duration. */
-+ duration = cur->response.timeout_time;
-+ } else {
-+ /* Sender wants to use the typical timeout duration. */
-+ duration = ctrl->timers[PRI_TIMER_T_RESPONSE];
-+ }
-+ cur->timer = pri_schedule_event(ctrl, duration, q931_apdu_timeout, cur);
-+ if (!cur->timer) {
-+ /* Remove APDU from list. */
-+ *prev = cur->next;
-+
-+ /* Indicate to callback that the APDU had a problem getting sent. */
-+ cur->response.callback(APDU_CALLBACK_REASON_ERROR, ctrl, call, cur, NULL);
-+
-+ free(cur);
-+ }
-+ } else if (!cur->timer) {
-+ /* Remove APDU from list. */
-+ *prev = cur->next;
-+ free(cur);
-+ }
-+
-+ return apdu_len + 2;
- }
-
--static FUNC_RECV(receive_facility)
-+static int receive_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
-- int i = 0;
-- int protocol, next_protocol;
-- struct rose_component *comp = NULL;
-- enum {
-- Q932_STATE_NFE, /* Network facility extension */
-- Q932_STATE_NPP, /* Network protocol profile */
-- Q932_STATE_INTERPRETATION, /* Interpretation component */
-- Q932_STATE_SERVICE /* Service component(s) */
-- } state = Q932_STATE_SERVICE;
--#define Q932_HANDLE_PROC(component, my_state, name, handler) \
-- case component: \
-- if(state > my_state) { \
-- pri_error(pri, "!! %s component received in wrong place\n"); \
-- break; \
-- } \
-- state = my_state; \
-- if (pri->debug) \
-- pri_message(pri, "Handle Q.932 %s component\n", name); \
-- (handler)(pri, call, ie, comp->data, comp->len); \
-- break;
--#define Q932_HANDLE_NULL(component, my_state, name, handle) \
-- case component: \
-- if(state > my_state) { \
-- pri_error(pri, "!! %s component received in wrong place\n"); \
-- break; \
-- } \
-- state = my_state; \
-- if (pri->debug & PRI_DEBUG_APDU) \
-- pri_message(pri, "Q.932 %s component is not handled\n", name); \
-- break;
--
-- if (ie->len < 1)
-+ /* Delay processing facility ie's till after all other ie's are processed. */
-+ if (MAX_FACILITY_IES <= ctrl->facility.count) {
-+ pri_message(ctrl, "!! Too many facility ie's to delay.\n");
- return -1;
-+ }
-+ /* Make sure we have enough room for the protocol profile ie octet(s) */
-+ if (ie->data + ie->len < ie->data + 2) {
-+ return -1;
-+ }
-
-- switch(next_protocol = protocol = (ie->data[i] & 0x1f)) {
-- case Q932_PROTOCOL_CMIP:
-- case Q932_PROTOCOL_ACSE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "!! Don't know how to handle Q.932 Protocol Profile of type 0x%X\n", protocol);
-+ /* Save the facility ie location for delayed decode. */
-+ ctrl->facility.ie[ctrl->facility.count] = ie;
-+ ctrl->facility.codeset[ctrl->facility.count] = Q931_IE_CODESET((unsigned) full_ie);
-+ ++ctrl->facility.count;
-+ return 0;
-+}
-+
-+static int process_facility(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie)
-+{
-+ struct fac_extension_header header;
-+ struct rose_message rose;
-+ const unsigned char *pos;
-+ const unsigned char *end;
-+
-+ pos = ie->data;
-+ end = ie->data + ie->len;
-+
-+ /* Make sure we have enough room for the protocol profile ie octet(s) */
-+ if (end < pos + 2) {
- return -1;
-+ }
-+ switch (*pos & Q932_PROTOCOL_MASK) {
-+ case Q932_PROTOCOL_ROSE:
- case Q932_PROTOCOL_EXTENSIONS:
-- state = Q932_STATE_NFE;
-- next_protocol = Q932_PROTOCOL_ROSE;
- break;
-- case Q932_PROTOCOL_ROSE:
-- break;
- default:
-- pri_error(pri, "!! Invalid Q.932 Protocol Profile of type 0x%X received\n", protocol);
-+ case Q932_PROTOCOL_CMIP:
-+ case Q932_PROTOCOL_ACSE:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl,
-+ "!! Don't know how to handle Q.932 Protocol Profile type 0x%X\n",
-+ *pos & Q932_PROTOCOL_MASK);
-+ }
- return -1;
- }
-- /* Service indicator octet - Just ignore for now */
-- if (!(ie->data[i] & 0x80))
-- i++;
-- i++;
-+ if (!(*pos & 0x80)) {
-+ /* DMS-100 Service indicator octet - Just ignore for now */
-+ ++pos;
-+ }
-+ ++pos;
-
-- if (ie->len < 3)
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ asn1_dump(ctrl, pos, end);
-+ }
-+
-+ pos = fac_dec_extension_header(ctrl, pos, end, &header);
-+ if (!pos) {
- return -1;
--
-- while ((i+1 < ie->len) && (&ie->data[i])) {
-- comp = (struct rose_component*)&ie->data[i];
-- if (comp->type) {
-- if (protocol == Q932_PROTOCOL_EXTENSIONS) {
-- switch (comp->type) {
-- Q932_HANDLE_NULL(COMP_TYPE_INTERPRETATION, Q932_STATE_INTERPRETATION, "Interpretation", NULL);
-- Q932_HANDLE_NULL(COMP_TYPE_NFE, Q932_STATE_NFE, "Network facility extensions", NULL);
-- Q932_HANDLE_NULL(COMP_TYPE_NETWORK_PROTOCOL_PROFILE, Q932_STATE_NPP, "Network protocol profile", NULL);
-- default:
-- protocol = next_protocol;
-- break;
-- }
-- }
-- switch (protocol) {
-- case Q932_PROTOCOL_ROSE:
-- switch (comp->type) {
-- Q932_HANDLE_PROC(COMP_TYPE_INVOKE, Q932_STATE_SERVICE, "ROSE Invoke", rose_invoke_decode);
-- Q932_HANDLE_PROC(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", rose_return_result_decode);
-- Q932_HANDLE_PROC(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", rose_return_error_decode);
-- Q932_HANDLE_PROC(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", rose_reject_decode);
-- default:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "Don't know how to handle ROSE component of type 0x%X\n", comp->type);
-- break;
-- }
-- break;
-- case Q932_PROTOCOL_CMIP:
-- switch (comp->type) {
-- default:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "Don't know how to handle CMIP component of type 0x%X\n", comp->type);
-- break;
-- }
-- break;
-- case Q932_PROTOCOL_ACSE:
-- switch (comp->type) {
-- default:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "Don't know how to handle ACSE component of type 0x%X\n", comp->type);
-- break;
-- }
-- break;
-- }
-+ }
-+ if (header.npp_present) {
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl,
-+ "!! Don't know how to handle Network Protocol Profile type 0x%X\n",
-+ header.npp);
- }
-- i += (comp->len + 2);
-+ return -1;
- }
--#undef Q932_HANDLE
-
-+ pos = rose_decode(ctrl, pos, end, &rose);
-+ if (!pos) {
-+ return -1;
-+ }
-+ switch (rose.type) {
-+ case ROSE_COMP_TYPE_INVOKE:
-+ rose_handle_invoke(ctrl, call, msgtype, ie, &header, &rose.component.invoke);
-+ break;
-+ case ROSE_COMP_TYPE_RESULT:
-+ rose_handle_result(ctrl, call, msgtype, ie, &header, &rose.component.result);
-+ break;
-+ case ROSE_COMP_TYPE_ERROR:
-+ rose_handle_error(ctrl, call, msgtype, ie, &header, &rose.component.error);
-+ break;
-+ case ROSE_COMP_TYPE_REJECT:
-+ rose_handle_reject(ctrl, call, msgtype, ie, &header, &rose.component.reject);
-+ break;
-+ default:
-+ return -1;
-+ }
- return 0;
- }
-
--static FUNC_SEND(transmit_progress_indicator)
-+static void q931_handle_facilities(struct pri *ctrl, q931_call *call, int msgtype)
- {
-+ unsigned idx;
-+ unsigned codeset;
-+ unsigned full_ie;
-+ q931_ie *ie;
-+
-+ for (idx = 0; idx < ctrl->facility.count; ++idx) {
-+ ie = ctrl->facility.ie[idx];
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ codeset = ctrl->facility.codeset[idx];
-+ full_ie = Q931_FULL_IE(codeset, ie->ie);
-+ pri_message(ctrl, "-- Delayed processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
-+ }
-+ process_facility(ctrl, call, msgtype, ie);
-+ }
-+}
-+
-+static int transmit_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
- int code, mask;
- /* Can't send progress indicator on GR-303 -- EVER! */
-- if (pri->subchannel && !pri->bri)
-+ if (ctrl->subchannel && !ctrl->bri)
- return 0;
- if (call->progressmask > 0) {
- if (call->progressmask & (mask = PRI_PROG_CALL_NOT_E2E_ISDN))
-@@ -1467,7 +2482,7 @@
- code = Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
- else {
- code = 0;
-- pri_error(pri, "XXX Undefined progress bit: %x\n", call->progressmask);
-+ pri_error(ctrl, "XXX Undefined progress bit: %x\n", call->progressmask);
- }
- if (code) {
- ie->data[0] = 0x80 | (call->progcode << 5) | (call->progloc);
-@@ -1479,82 +2494,139 @@
- /* Leave off */
- return 0;
- }
--static FUNC_SEND(transmit_call_state)
-+static int transmit_call_state(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- if (call->ourcallstate > -1 ) {
-+ ie->data[0] = Q931_CALL_STATE_NULL;
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_NULL:
-+ case Q931_CALL_STATE_CALL_INITIATED:
-+ case Q931_CALL_STATE_OVERLAP_SENDING:
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_CALL_PRESENT:
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_ACTIVE:
-+ case Q931_CALL_STATE_DISCONNECT_REQUEST:
-+ case Q931_CALL_STATE_DISCONNECT_INDICATION:
-+ case Q931_CALL_STATE_SUSPEND_REQUEST:
-+ case Q931_CALL_STATE_RESUME_REQUEST:
-+ case Q931_CALL_STATE_RELEASE_REQUEST:
-+ case Q931_CALL_STATE_CALL_ABORT:
-+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
-+ case Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE:
-+ case Q931_CALL_STATE_RESTART_REQUEST:
-+ case Q931_CALL_STATE_RESTART:
- ie->data[0] = call->ourcallstate;
-- return 3;
-+ break;
-+ case Q931_CALL_STATE_NOT_SET:
-+ break;
- }
-- return 0;
-+ return 3;
- }
-
--static FUNC_RECV(receive_call_state)
-+static int receive_call_state(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->sugcallstate = ie->data[0] & 0x3f;
- return 0;
- }
-
--static char *callstate2str(int callstate)
-+/*!
-+ * \brief Convert the internal Q.931 call state to a string.
-+ *
-+ * \param callstate Internal Q.931 call state.
-+ *
-+ * \return String equivalent of the given Q.931 call state.
-+ */
-+const char *q931_call_state_str(enum Q931_CALL_STATE callstate)
- {
- static struct msgtype callstates[] = {
-- { 0, "Null" },
-- { 1, "Call Initiated" },
-- { 2, "Overlap sending" },
-- { 3, "Outgoing call Proceeding" },
-- { 4, "Call Delivered" },
-- { 6, "Call Present" },
-- { 7, "Call Received" },
-- { 8, "Connect Request" },
-- { 9, "Incoming Call Proceeding" },
-- { 10, "Active" },
-- { 11, "Disconnect Request" },
-- { 12, "Disconnect Indication" },
-- { 15, "Suspend Request" },
-- { 17, "Resume Request" },
-- { 19, "Release Request" },
-- { 22, "Call Abort" },
-- { 25, "Overlap Receiving" },
-- { 61, "Restart Request" },
-- { 62, "Restart" },
-+/* *INDENT-OFF* */
-+ { Q931_CALL_STATE_NULL, "Null" },
-+ { Q931_CALL_STATE_CALL_INITIATED, "Call Initiated" },
-+ { Q931_CALL_STATE_OVERLAP_SENDING, "Overlap Sending" },
-+ { Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING, "Outgoing Call Proceeding" },
-+ { Q931_CALL_STATE_CALL_DELIVERED, "Call Delivered" },
-+ { Q931_CALL_STATE_CALL_PRESENT, "Call Present" },
-+ { Q931_CALL_STATE_CALL_RECEIVED, "Call Received" },
-+ { Q931_CALL_STATE_CONNECT_REQUEST, "Connect Request" },
-+ { Q931_CALL_STATE_INCOMING_CALL_PROCEEDING, "Incoming Call Proceeding" },
-+ { Q931_CALL_STATE_ACTIVE, "Active" },
-+ { Q931_CALL_STATE_DISCONNECT_REQUEST, "Disconnect Request" },
-+ { Q931_CALL_STATE_DISCONNECT_INDICATION, "Disconnect Indication" },
-+ { Q931_CALL_STATE_SUSPEND_REQUEST, "Suspend Request" },
-+ { Q931_CALL_STATE_RESUME_REQUEST, "Resume Request" },
-+ { Q931_CALL_STATE_RELEASE_REQUEST, "Release Request" },
-+ { Q931_CALL_STATE_CALL_ABORT, "Call Abort" },
-+ { Q931_CALL_STATE_OVERLAP_RECEIVING, "Overlap Receiving" },
-+ { Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE, "Call Independent Service" },
-+ { Q931_CALL_STATE_RESTART_REQUEST, "Restart Request" },
-+ { Q931_CALL_STATE_RESTART, "Restart" },
-+ { Q931_CALL_STATE_NOT_SET, "Not set. Internal use only." },
-+/* *INDENT-ON* */
- };
-- return code2str(callstate, callstates, sizeof(callstates) / sizeof(callstates[0]));
-+ return code2str(callstate, callstates, ARRAY_LEN(callstates));
- }
-
--static FUNC_DUMP(dump_call_state)
-+/*!
-+ * \internal
-+ * \brief Convert the Q.932 supplementary hold state to a string.
-+ *
-+ * \param state Q.932 supplementary hold state.
-+ *
-+ * \return String equivalent of the given hold state.
-+ */
-+static const char *q931_hold_state_str(enum Q931_HOLD_STATE state)
- {
-- pri_message(pri, "%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
-+ static struct msgtype hold_states[] = {
-+/* *INDENT-OFF* */
-+ { Q931_HOLD_STATE_IDLE, "Idle" },
-+ { Q931_HOLD_STATE_HOLD_REQ, "Hold Request" },
-+ { Q931_HOLD_STATE_HOLD_IND, "Hold Indication" },
-+ { Q931_HOLD_STATE_CALL_HELD, "Call Held" },
-+ { Q931_HOLD_STATE_RETRIEVE_REQ, "Retrieve Request" },
-+ { Q931_HOLD_STATE_RETRIEVE_IND, "Retrieve Indication" },
-+/* *INDENT-ON* */
-+ };
-+ return code2str(state, hold_states, ARRAY_LEN(hold_states));
-+}
-+
-+static void dump_call_state(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ pri_message(ctrl, "%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
- prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0xC0) >> 6), (ie->data[0] & 0xC0) >> 6,
-- callstate2str(ie->data[0] & 0x3f), ie->data[0] & 0x3f);
-+ q931_call_state_str(ie->data[0] & 0x3f), ie->data[0] & 0x3f);
- }
-
--static FUNC_DUMP(dump_call_identity)
-+static void dump_call_identity(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int x;
-- pri_message(pri, "%c Call Identity (len=%2d) [ ", prefix, len);
-+ pri_message(ctrl, "%c Call Identity (len=%2d) [ ", prefix, len);
- for (x=0;x<ie->len;x++)
-- pri_message(pri, "0x%02X ", ie->data[x]);
-- pri_message(pri, " ]\n");
-+ pri_message(ctrl, "0x%02X ", ie->data[x]);
-+ pri_message(ctrl, " ]\n");
- }
-
--static FUNC_DUMP(dump_time_date)
-+static void dump_time_date(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Time Date (len=%2d) [ ", prefix, len);
-+ pri_message(ctrl, "%c Time Date (len=%2d) [ ", prefix, len);
- if (ie->len > 0)
-- pri_message(pri, "%02d", ie->data[0]);
-+ pri_message(ctrl, "%02d", ie->data[0]);
- if (ie->len > 1)
-- pri_message(pri, "-%02d", ie->data[1]);
-+ pri_message(ctrl, "-%02d", ie->data[1]);
- if (ie->len > 2)
-- pri_message(pri, "-%02d", ie->data[2]);
-+ pri_message(ctrl, "-%02d", ie->data[2]);
- if (ie->len > 3)
-- pri_message(pri, " %02d", ie->data[3]);
-+ pri_message(ctrl, " %02d", ie->data[3]);
- if (ie->len > 4)
-- pri_message(pri, ":%02d", ie->data[4]);
-+ pri_message(ctrl, ":%02d", ie->data[4]);
- if (ie->len > 5)
-- pri_message(pri, ":%02d", ie->data[5]);
-- pri_message(pri, " ]\n");
-+ pri_message(ctrl, ":%02d", ie->data[5]);
-+ pri_message(ctrl, " ]\n");
- }
-
--static FUNC_DUMP(dump_keypad_facility)
-+static void dump_keypad_facility(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- char tmp[64];
-
-@@ -1563,10 +2635,10 @@
-
- memcpy(tmp, ie->data, ie->len);
- tmp[ie->len] = '\0';
-- pri_message(pri, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );
-+ pri_message(ctrl, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );
- }
-
--static FUNC_RECV(receive_keypad_facility)
-+static int receive_keypad_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- int mylen;
-
-@@ -1584,27 +2656,19 @@
- return 0;
- }
-
--static FUNC_SEND(transmit_keypad_facility)
-+static int transmit_keypad_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- int sublen;
-
- sublen = strlen(call->keypad_digits);
--
-- if (sublen > 32) {
-- sublen = 32;
-- call->keypad_digits[32] = '\0';
-- }
--
- if (sublen) {
-- libpri_copy_string((char *)ie->data, (char *)call->keypad_digits, sizeof(call->keypad_digits));
-- /* Make sure we clear the field */
-- call->keypad_digits[0] = '\0';
-+ libpri_copy_string((char *) ie->data, call->keypad_digits, sizeof(call->keypad_digits));
- return sublen + 2;
- } else
- return 0;
- }
-
--static FUNC_DUMP(dump_display)
-+static void dump_display(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int x, y;
- char *buf = malloc(len + 1);
-@@ -1618,7 +2682,7 @@
- for (y=x; x<ie->len; x++)
- buf[x] = ie->data[x] & 0x7f;
- buf[x] = '\0';
-- pri_message(pri, "%c Display (len=%2d) %s[ %s ]\n", prefix, ie->len, tmp, &buf[y]);
-+ pri_message(ctrl, "%c Display (len=%2d) %s[ %s ]\n", prefix, ie->len, tmp, &buf[y]);
- free(buf);
- }
- }
-@@ -1626,10 +2690,10 @@
- #define CHECK_OVERFLOW(limit) \
- if (tmpptr - tmp + limit >= sizeof(tmp)) { \
- *tmpptr = '\0'; \
-- pri_message(pri, "%s", tmpptr = tmp); \
-+ pri_message(ctrl, "%s", tmpptr = tmp); \
- }
-
--static void dump_ie_data(struct pri *pri, unsigned char *c, int len)
-+static void dump_ie_data(struct pri *ctrl, unsigned char *c, int len)
- {
- static char hexs[16] = "0123456789ABCDEF";
- char tmp[1024], *tmpptr;
-@@ -1665,47 +2729,54 @@
- if (lastascii)
- *tmpptr++ = '\'';
- *tmpptr = '\0';
-- pri_message(pri, "%s", tmp);
-+ pri_message(ctrl, "%s", tmp);
- }
-
--static FUNC_DUMP(dump_facility)
-+static void dump_facility(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- int dataat = (ie->data[0] & 0x80) ? 1 : 2;
-- pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
-- dump_ie_data(pri, ie->data, ie->len);
-- pri_message(NULL, " ]\n");
-+ pri_message(ctrl, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
-+ dump_ie_data(ctrl, ie->data, ie->len);
-+ pri_message(ctrl, " ]\n");
-+#if 0 /* Lets not dump parse of facility contents here anymore. */
-+ /*
-+ * The ASN.1 decode dump has already been done when the facility ie was added to the outgoing
-+ * message or the ASN.1 decode dump will be done when the facility ie is processed on incoming
-+ * messages. This dump is redundant and very noisy.
-+ */
- if (ie->len > 1) {
-- pri_message(pri, "PROTOCOL %02X\n", ie->data[0] & ASN1_TYPE_MASK);
-- asn1_dump(pri, &ie->data[dataat], ie->len - dataat);
-+ int dataat = (ie->data[0] & 0x80) ? 1 : 2;
-+
-+ pri_message(ctrl, "PROTOCOL %02X\n", ie->data[0] & Q932_PROTOCOL_MASK);
-+ asn1_dump(ctrl, ie->data + dataat, ie->data + ie->len);
- }
--
-+#endif /* Lets not dump parse of facility contents here anymore. */
- }
-
--static FUNC_DUMP(dump_network_spec_fac)
-+static void dump_network_spec_fac(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
-+ pri_message(ctrl, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
- if (ie->data[0] == 0x00) {
-- pri_message(pri, "%s", code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
-+ pri_message(ctrl, "%s", code2str(ie->data[1], facilities, ARRAY_LEN(facilities)));
- }
- else
-- dump_ie_data(pri, ie->data, ie->len);
-- pri_message(pri, " ]\n");
-+ dump_ie_data(ctrl, ie->data, ie->len);
-+ pri_message(ctrl, " ]\n");
- }
-
--static FUNC_RECV(receive_network_spec_fac)
-+static int receive_network_spec_fac(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- return 0;
- }
-
--static FUNC_SEND(transmit_network_spec_fac)
-+static int transmit_network_spec_fac(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- /* We are ready to transmit single IE only */
- if (order > 1)
- return 0;
-
-- if (pri->nsf != PRI_NSF_NONE) {
-+ if (ctrl->nsf != PRI_NSF_NONE) {
- ie->data[0] = 0x00;
-- ie->data[1] = pri->nsf;
-+ ie->data[1] = ctrl->nsf;
- return 4;
- }
- /* Leave off */
-@@ -1732,13 +2803,13 @@
- return code2str(cause, causeclasses, sizeof(causeclasses) / sizeof(causeclasses[0]));
- }
-
--static FUNC_DUMP(dump_cause)
-+static void dump_cause(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int x;
-- pri_message(pri, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) Spare: %d Location: %s (%d)\n",
-+ pri_message(ctrl, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) Spare: %d Location: %s (%d)\n",
- prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
- (ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
-- pri_message(pri, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
-+ pri_message(ctrl, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
- prefix, (ie->data[1] >> 7), pri_cause2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f,
- pri_causeclass2str((ie->data[1] & 0x7f) >> 4), (ie->data[1] & 0x7f) >> 4);
- if (ie->len < 3)
-@@ -1747,29 +2818,29 @@
- switch(ie->data[1] & 0x7f) {
- case PRI_CAUSE_IE_NONEXIST:
- for (x=2;x<ie->len;x++)
-- pri_message(pri, "%c Cause data %d: %02x (%d, %s IE)\n", prefix, x-1, ie->data[x], ie->data[x], ie2str(ie->data[x]));
-+ pri_message(ctrl, "%c Cause data %d: %02x (%d, %s IE)\n", prefix, x-1, ie->data[x], ie->data[x], ie2str(ie->data[x]));
- break;
- case PRI_CAUSE_WRONG_CALL_STATE:
- for (x=2;x<ie->len;x++)
-- pri_message(pri, "%c Cause data %d: %02x (%d, %s message)\n", prefix, x-1, ie->data[x], ie->data[x], msg2str(ie->data[x]));
-+ pri_message(ctrl, "%c Cause data %d: %02x (%d, %s message)\n", prefix, x-1, ie->data[x], ie->data[x], msg2str(ie->data[x]));
- break;
- case PRI_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
-- pri_message(pri, "%c Cause data:", prefix);
-+ pri_message(ctrl, "%c Cause data:", prefix);
- for (x=2;x<ie->len;x++)
-- pri_message(pri, " %02x", ie->data[x]);
-- pri_message(pri, " (Timer T");
-+ pri_message(ctrl, " %02x", ie->data[x]);
-+ pri_message(ctrl, " (Timer T");
- for (x=2;x<ie->len;x++)
-- pri_message(pri, "%c", ((ie->data[x] >= ' ') && (ie->data[x] < 0x7f)) ? ie->data[x] : '.');
-- pri_message(pri, ")\n");
-+ pri_message(ctrl, "%c", ((ie->data[x] >= ' ') && (ie->data[x] < 0x7f)) ? ie->data[x] : '.');
-+ pri_message(ctrl, ")\n");
- break;
- default:
- for (x=2;x<ie->len;x++)
-- pri_message(pri, "%c Cause data %d: %02x (%d)\n", prefix, x-1, ie->data[x], ie->data[x]);
-+ pri_message(ctrl, "%c Cause data %d: %02x (%d)\n", prefix, x-1, ie->data[x], ie->data[x]);
- break;
- }
- }
-
--static FUNC_RECV(receive_cause)
-+static int receive_cause(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->causeloc = ie->data[0] & 0xf;
- call->causecode = (ie->data[0] & 0x60) >> 5;
-@@ -1777,7 +2848,7 @@
- return 0;
- }
-
--static FUNC_SEND(transmit_cause)
-+static int transmit_cause(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- /* We are ready to transmit single IE only */
- if (order > 1)
-@@ -1793,23 +2864,23 @@
- }
- }
-
--static FUNC_DUMP(dump_sending_complete)
-+static void dump_sending_complete(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Sending Complete (len=%2d)\n", prefix, len);
-+ pri_message(ctrl, "%c Sending Complete (len=%2d)\n", prefix, len);
- }
-
--static FUNC_RECV(receive_sending_complete)
-+static int receive_sending_complete(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- /* We've got a "Complete" message: Exect no further digits. */
- call->complete = 1;
- return 0;
- }
-
--static FUNC_SEND(transmit_sending_complete)
-+static int transmit_sending_complete(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
-- if ((pri->overlapdial && call->complete) || /* Explicit */
-- (!pri->overlapdial && ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) ||
-- /* Implicit */ (pri->switchtype == PRI_SWITCH_EUROISDN_T1)))) {
-+ if ((ctrl->overlapdial && call->complete) || /* Explicit */
-+ (!ctrl->overlapdial && ((ctrl->switchtype == PRI_SWITCH_EUROISDN_E1) ||
-+ /* Implicit */ (ctrl->switchtype == PRI_SWITCH_EUROISDN_T1)))) {
- /* Include this single-byte IE */
- return 1;
- }
-@@ -1846,18 +2917,18 @@
- return code2str(info, notifies, sizeof(notifies) / sizeof(notifies[0]));
- }
-
--static FUNC_DUMP(dump_notify)
-+static void dump_notify(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Notification indicator (len=%2d): Ext: %d %s (%d)\n", prefix, len, ie->data[0] >> 7, notify2str(ie->data[0] & 0x7f), ie->data[0] & 0x7f);
-+ pri_message(ctrl, "%c Notification indicator (len=%2d): Ext: %d %s (%d)\n", prefix, len, ie->data[0] >> 7, notify2str(ie->data[0] & 0x7f), ie->data[0] & 0x7f);
- }
-
--static FUNC_RECV(receive_notify)
-+static int receive_notify(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->notify = ie->data[0] & 0x7F;
- return 0;
- }
-
--static FUNC_SEND(transmit_notify)
-+static int transmit_notify(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- if (call->notify >= 0) {
- ie->data[0] = 0x80 | call->notify;
-@@ -1866,9 +2937,9 @@
- return 0;
- }
-
--static FUNC_DUMP(dump_shift)
-+static void dump_shift(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c %sLocking Shift (len=%02d): Requested codeset %d\n", prefix, (full_ie & 8) ? "Non-" : "", len, full_ie & 7);
-+ pri_message(ctrl, "%c %sLocking Shift (len=%02d): Requested codeset %d\n", prefix, (full_ie & 8) ? "Non-" : "", len, full_ie & 7);
- }
-
- static char *lineinfo2str(int info)
-@@ -1903,21 +2974,21 @@
- return code2str(info, lineinfo, sizeof(lineinfo) / sizeof(lineinfo[0]));
- }
-
--static FUNC_DUMP(dump_line_information)
-+static void dump_line_information(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Originating Line Information (len=%02d): %s (%d)\n", prefix, len, lineinfo2str(ie->data[0]), ie->data[0]);
-+ pri_message(ctrl, "%c Originating Line Information (len=%02d): %s (%d)\n", prefix, len, lineinfo2str(ie->data[0]), ie->data[0]);
- }
-
--static FUNC_RECV(receive_line_information)
-+static int receive_line_information(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- call->ani2 = ie->data[0];
- return 0;
- }
-
--static FUNC_SEND(transmit_line_information)
-+static int transmit_line_information(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- #if 0 /* XXX Is this IE possible for 4ESS only? XXX */
-- if(pri->switchtype == PRI_SWITCH_ATT4ESS) {
-+ if(ctrl->switchtype == PRI_SWITCH_ATT4ESS) {
- ie->data[0] = 0;
- return 3;
- }
-@@ -1953,53 +3024,54 @@
- return code2str(type, gdtype, sizeof(gdtype) / sizeof(gdtype[0]));
- }
-
--static FUNC_DUMP(dump_generic_digits)
-+static void dump_generic_digits(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- int encoding;
- int type;
- int idx;
- int value;
- if (len < 3) {
-- pri_message(pri, "%c Generic Digits (len=%02d): Invalid length\n", prefix, len);
-+ pri_message(ctrl, "%c Generic Digits (len=%02d): Invalid length\n", prefix, len);
- return;
- }
- encoding = (ie->data[0] >> 5) & 7;
- type = ie->data[0] & 0x1F;
-- pri_message(pri, "%c Generic Digits (len=%02d): Encoding %s Type %s\n", prefix, len, gdencoding2str(encoding), gdtype2str(type));
-+ pri_message(ctrl, "%c Generic Digits (len=%02d): Encoding %s Type %s\n", prefix, len, gdencoding2str(encoding), gdtype2str(type));
- if (encoding == 3) { /* Binary */
-- pri_message(pri, "%c Don't know how to handle binary encoding\n");
-+ pri_message(ctrl, "%c Don't know how to handle binary encoding\n",
-+ prefix);
- return;
- }
- if (len == 3) /* No number information */
- return;
-- pri_message(pri, "%c Digits: ");
-+ pri_message(ctrl, "%c Digits: ", prefix);
- value = 0;
- for(idx = 3; idx < len; ++idx) {
- switch(encoding) {
- case 0: /* BCD even */
- case 1: /* BCD odd */
-- pri_message(pri, "%d", ie->data[idx-2] & 0x0f);
-+ pri_message(ctrl, "%d", ie->data[idx-2] & 0x0f);
- value = value * 10 + (ie->data[idx-2] & 0x0f);
- if(!encoding || (idx+1 < len)) { /* Special handling for BCD odd */
-- pri_message(pri, "%d", (ie->data[idx-2] >> 4) & 0x0f);
-+ pri_message(ctrl, "%d", (ie->data[idx-2] >> 4) & 0x0f);
- value = value * 10 + ((ie->data[idx-2] >> 4) & 0x0f);
- }
- break;
- case 2: /* IA5 */
-- pri_message(pri, "%c", ie->data[idx-2]);
-+ pri_message(ctrl, "%c", ie->data[idx-2]);
- value = value * 10 + ie->data[idx-2] - '0';
- break;
- }
- }
- switch(type) {
- case 4: /* Info Digits */
-- pri_message(pri, " - %s", lineinfo2str(value));
-+ pri_message(ctrl, " - %s", lineinfo2str(value));
- break;
- }
-- pri_message(pri, "\n");
-+ pri_message(ctrl, "\n");
- }
-
--static FUNC_RECV(receive_generic_digits)
-+static int receive_generic_digits(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
- {
- int encoding;
- int type;
-@@ -2009,13 +3081,13 @@
- char number[260];
-
- if (len < 3) {
-- pri_error(pri, "Invalid length of Generic Digits IE\n");
-+ pri_error(ctrl, "Invalid length of Generic Digits IE\n");
- return -1;
- }
- encoding = (ie->data[0] >> 5) & 7;
- type = ie->data[0] & 0x1F;
- if (encoding == 3) { /* Binary */
-- pri_message(pri, "!! Unable to handle binary encoded Generic Digits IE\n");
-+ pri_message(ctrl, "!! Unable to handle binary encoded Generic Digits IE\n");
- return 0;
- }
- if (len == 3) /* No number information */
-@@ -2063,10 +3135,13 @@
- break;
- #if 0
- case 5: /* Callid */
-- if (!call->callernum[0]) {
-- memcpy(call->callernum, number, sizeof(call->callernum)-1);
-- call->callerpres = 0;
-- call->callerplan = 0;
-+ if (!call->remote_id.number.valid) {
-+ call->remote_id.number.valid = 1;
-+ call->remote_id.number.presentation =
-+ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ call->remote_id.number.plan = PRI_UNKNOWN;
-+ libpri_copy_string(call->remote_id.number.str, number,
-+ sizeof(call->remote_id.number.str));
- }
- break;
- #endif
-@@ -2074,13 +3149,13 @@
- return 0;
- }
-
--static FUNC_SEND(transmit_generic_digits)
-+static int transmit_generic_digits(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
- {
- #if 0 /* XXX Is this IE possible for other switches? XXX */
- if (order > 1)
- return 0;
-
-- if(pri->switchtype == PRI_SWITCH_NI1) {
-+ if(ctrl->switchtype == PRI_SWITCH_NI1) {
- ie->data[0] = 0x04; /* BCD even, Info Digits */
- ie->data[1] = 0x00; /* POTS */
- return 4;
-@@ -2119,35 +3194,54 @@
- }
-
-
--static FUNC_DUMP(dump_signal)
-+static void dump_signal(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
-- pri_message(pri, "%c Signal (len=%02d): ", prefix, len);
-+ pri_message(ctrl, "%c Signal (len=%02d): ", prefix, len);
- if (len < 3) {
-- pri_message(pri, "Invalid length\n");
-+ pri_message(ctrl, "Invalid length\n");
- return;
- }
-- pri_message(pri, "Signal %s (%d)\n", signal2str(ie->data[0]), ie->data[0]);
-+ pri_message(ctrl, "Signal %s (%d)\n", signal2str(ie->data[0]), ie->data[0]);
- }
-
--static FUNC_DUMP(dump_transit_count)
-+static void dump_transit_count(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
- {
- /* Defined in ECMA-225 */
-- pri_message(pri, "%c Transit Count (len=%02d): ", prefix, len);
-+ pri_message(ctrl, "%c Transit Count (len=%02d): ", prefix, len);
- if (len < 3) {
-- pri_message(pri, "Invalid length\n");
-+ pri_message(ctrl, "Invalid length\n");
- return;
- }
-- pri_message(pri, "Count=%d (0x%02x)\n", ie->data[0] & 0x1f, ie->data[0] & 0x1f);
-+ pri_message(ctrl, "Count=%d (0x%02x)\n", ie->data[0] & 0x1f, ie->data[0] & 0x1f);
- }
-
-+static void dump_reverse_charging_indication(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
-+{
-+ pri_message(ctrl, "%c Reverse Charging Indication (len=%02d): %d\n", prefix, len, ie->data[0] & 0x7);
-+}
-
-+static int receive_reverse_charging_indication(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+ call->reversecharge = ie->data[0] & 0x7;
-+ return 0;
-+}
-+
-+static int transmit_reverse_charging_indication(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
-+{
-+ if (call->reversecharge != PRI_REVERSECHARGE_NONE) {
-+ ie->data[0] = 0x80 | (call->reversecharge & 0x7);
-+ return 3;
-+ }
-+ return 0;
-+}
-+
- static struct ie ies[] = {
- /* Codeset 0 - Common */
-- { 1, NATIONAL_CHANGE_STATUS, "Change Status" },
-+ { 1, NATIONAL_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status },
- { 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift },
- { 0, Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability },
- { 0, Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause },
-- { 1, Q931_CALL_STATE, "Call State", dump_call_state, receive_call_state, transmit_call_state },
-+ { 1, Q931_IE_CALL_STATE, "Call State", dump_call_state, receive_call_state, transmit_call_state },
- { 0, Q931_CHANNEL_IDENT, "Channel Identification", dump_channel_id, receive_channel_id, transmit_channel_id },
- { 0, Q931_PROGRESS_INDICATOR, "Progress Indicator", dump_progress_indicator, receive_progress_indicator, transmit_progress_indicator },
- { 0, Q931_NETWORK_SPEC_FAC, "Network-Specific Facilities", dump_network_spec_fac, receive_network_spec_fac, transmit_network_spec_fac },
-@@ -2157,11 +3251,11 @@
- { 1, Q931_BINARY_PARAMETERS, "Packet-layer Binary Parameters" },
- { 1, Q931_WINDOW_SIZE, "Packet-layer Window Size" },
- { 1, Q931_CLOSED_USER_GROUP, "Closed User Group" },
-- { 1, Q931_REVERSE_CHARGE_INDIC, "Reverse Charging Indication" },
-+ { 1, Q931_REVERSE_CHARGE_INDIC, "Reverse Charging Indication", dump_reverse_charging_indication, receive_reverse_charging_indication, transmit_reverse_charging_indication },
- { 1, Q931_CALLING_PARTY_NUMBER, "Calling Party Number", dump_calling_party_number, receive_calling_party_number, transmit_calling_party_number },
-- { 1, Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr, receive_calling_party_subaddr },
-+ { 1, Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr, receive_calling_party_subaddr, transmit_calling_party_subaddr },
- { 1, Q931_CALLED_PARTY_NUMBER, "Called Party Number", dump_called_party_number, receive_called_party_number, transmit_called_party_number },
-- { 1, Q931_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr },
-+ { 1, Q931_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr, receive_called_party_subaddr, transmit_called_party_subaddr },
- { 0, Q931_REDIRECTING_NUMBER, "Redirecting Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
- { 1, Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr },
- { 0, Q931_TRANSIT_NET_SELECT, "Transit Network Selection" },
-@@ -2170,7 +3264,7 @@
- { 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
- { 1, Q931_PACKET_SIZE, "Packet Size" },
- { 0, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
-- { 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
-+ { 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number", dump_redirection_number, receive_redirection_number, transmit_redirection_number },
- { 1, Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
- { 1, Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
- { 1, Q931_IE_INFO_REQUEST, "Feature Request" },
-@@ -2187,15 +3281,18 @@
- { 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user, transmit_user_user },
- { 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
- { 1, Q931_IE_CALL_STATUS, "Call Status" },
-- { 1, Q931_IE_CHANGE_STATUS, "Change Status" },
-+ { 1, Q931_IE_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status },
- { 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number },
-- { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number },
-+ { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number, receive_connected_number, transmit_connected_number },
-+ { 1, Q931_IE_CONNECTED_SUBADDR, "Connected Subaddress", dump_connected_subaddr, receive_connected_subaddr, transmit_connected_subaddr },
- { 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
- { 1, Q931_IE_USER_USER_FACILITY, "User-User Facility" },
- { 1, Q931_IE_UPDATE, "Update" },
- { 1, Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
- /* Codeset 4 - Q.SIG specific */
- { 1, QSIG_IE_TRANSIT_COUNT | Q931_CODESET(4), "Transit Count", dump_transit_count },
-+ /* Codeset 5 - National specific (ETSI PISN specific) */
-+ { 1, Q931_CALLING_PARTY_CATEGORY, "Calling Party Category", dump_calling_party_category },
- /* Codeset 6 - Network specific */
- { 1, Q931_IE_ORIGINATING_LINE_INFO, "Originating Line Information", dump_line_information, receive_line_information, transmit_line_information },
- { 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility },
-@@ -2264,7 +3361,7 @@
- return 2 + ie->len;
- }
-
--static char *msg2str(int msg)
-+const char *msg2str(int msg)
- {
- unsigned int x;
- for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++)
-@@ -2273,35 +3370,64 @@
- return "Unknown Message Type";
- }
-
-+static char *maintenance_msg2str(int msg, int pd)
-+{
-+ unsigned int x, max;
-+ struct msgtype *m = NULL;
-+
-+ if (pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) {
-+ m = att_maintenance_msgs;
-+ max = ARRAY_LEN(att_maintenance_msgs);
-+ } else {
-+ m = national_maintenance_msgs;
-+ max = ARRAY_LEN(national_maintenance_msgs);
-+ }
-+
-+ for (x = 0; x < max; x++) {
-+ if (m[x].msgnum == msg) {
-+ return m[x].name;
-+ }
-+ }
-+ return "Unknown Message Type";
-+}
-+
-+/* Decode the call reference */
- static inline int q931_cr(q931_h *h)
- {
-- int cr = 0;
-+ int cr;
- int x;
-+
- if (h->crlen > 3) {
- pri_error(NULL, "Call Reference Length Too long: %d\n", h->crlen);
-- return -1;
-+ return Q931_DUMMY_CALL_REFERENCE;
- }
- switch (h->crlen) {
-- case 2:
-- for (x=0;x<h->crlen;x++) {
-- cr <<= 8;
-- cr |= h->crv[x];
-- }
-- break;
-- case 1:
-- cr = h->crv[0];
-- if (cr & 0x80) {
-- cr &= ~0x80;
-- cr |= 0x8000;
-- }
-- break;
-- default:
-- pri_error(NULL, "Call Reference Length not supported: %d\n", h->crlen);
-+ case 2:
-+ cr = 0;
-+ for (x = 0; x < h->crlen; ++x) {
-+ cr <<= 8;
-+ cr |= h->crv[x];
-+ }
-+ break;
-+ case 1:
-+ cr = h->crv[0];
-+ if (cr & 0x80) {
-+ cr &= ~0x80;
-+ cr |= 0x8000;
-+ }
-+ break;
-+ case 0:
-+ cr = Q931_DUMMY_CALL_REFERENCE;
-+ break;
-+ default:
-+ pri_error(NULL, "Call Reference Length not supported: %d\n", h->crlen);
-+ cr = Q931_DUMMY_CALL_REFERENCE;
-+ break;
- }
- return cr;
- }
-
--static inline void q931_dumpie(struct pri *pri, int codeset, q931_ie *ie, char prefix)
-+static inline void q931_dumpie(struct pri *ctrl, int codeset, q931_ie *ie, char prefix)
- {
- unsigned int x;
- int full_ie = Q931_FULL_IE(codeset, ie->ie);
-@@ -2315,7 +3441,7 @@
- for (x = 0; x + 2 < ielen(ie); ++x)
- buflen += sprintf(buf + buflen, " %02x", ie->data[x]);
- }
-- pri_message(pri, "%c [%02x%s]\n", prefix, ie->ie, buf);
-+ pri_message(ctrl, "%c [%02x%s]\n", prefix, ie->ie, buf);
- free(buf);
-
- /* Special treatment for shifts */
-@@ -2324,130 +3450,306 @@
-
- base_ie = (((full_ie & ~0x7f) == Q931_FULL_IE(0, 0x80)) && ((full_ie & 0x70) != 0x20)) ? full_ie & ~0x0f : full_ie;
-
-- for (x=0;x<sizeof(ies) / sizeof(ies[0]); x++)
-+ for (x = 0; x < ARRAY_LEN(ies); ++x)
- if (ies[x].ie == base_ie) {
- if (ies[x].dump)
-- ies[x].dump(full_ie, pri, ie, ielen(ie), prefix);
-+ ies[x].dump(full_ie, ctrl, ie, ielen(ie), prefix);
- else
-- pri_message(pri, "%c IE: %s (len = %d)\n", prefix, ies[x].name, ielen(ie));
-+ pri_message(ctrl, "%c IE: %s (len = %d)\n", prefix, ies[x].name, ielen(ie));
- return;
- }
-
-- pri_error(pri, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie));
-+ pri_error(ctrl, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie));
- }
-
--static q931_call *q931_getcall(struct pri *pri, int cr, int outboundnew)
-+/*!
-+ * \brief Initialize the call record.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ *
-+ * \note The call record is assumed to already be memset() to zero.
-+ *
-+ * \return Nothing
-+ */
-+void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr)
- {
-- q931_call *cur, *prev;
-+ call->cr = cr;
-+ call->slotmap = -1;
-+ call->channelno = -1;
-+ if (cr != Q931_DUMMY_CALL_REFERENCE) {
-+ call->newcall = 1;
-+ }
-+ call->ourcallstate = Q931_CALL_STATE_NULL;
-+ call->peercallstate = Q931_CALL_STATE_NULL;
-+ call->sugcallstate = Q931_CALL_STATE_NOT_SET;
-+ call->ri = -1;
-+ call->transcapability = -1;
-+ call->transmoderate = -1;
-+ call->transmultiple = -1;
-+ call->userl1 = -1;
-+ call->userl2 = -1;
-+ call->userl3 = -1;
-+ call->rateadaption = -1;
-+ call->progress = -1;
-+ call->causecode = -1;
-+ call->causeloc = -1;
-+ call->cause = -1;
-+ call->useruserprotocoldisc = -1;
-+ call->aoc_units = -1;
-+ call->changestatus = -1;
-+ call->reversecharge = -1;
-+ call->pri_winner = -1;
-+ call->master_call = call;
-+ q931_party_number_init(&call->redirection_number);
-+ q931_party_address_init(&call->called);
-+ q931_party_id_init(&call->local_id);
-+ q931_party_id_init(&call->remote_id);
-+ q931_party_redirecting_init(&call->redirecting);
-+
-+ /* PRI is set to whoever called us */
-+ if (BRI_TE_PTMP(ctrl)) {
-+ /*
-+ * Point to the master to avoid stale pointer problems if
-+ * the TEI is removed later.
-+ */
-+ call->pri = PRI_MASTER(ctrl);
-+ } else {
-+ call->pri = ctrl;
-+ }
-+}
-+
-+static q931_call *q931_getcall(struct pri *ctrl, int cr)
-+{
-+ q931_call *cur;
-+ q931_call *prev;
- struct pri *master;
-
-+ if (cr == Q931_DUMMY_CALL_REFERENCE) {
-+ return ctrl->dummy_call;
-+ }
-+
- /* Find the master - He has the call pool */
-- if (pri->master)
-- master = pri->master;
-- else
-- master = pri;
--
-+ master = PRI_MASTER(ctrl);
-+
- cur = *master->callpool;
- prev = NULL;
-- while(cur) {
-- if (cur->cr == cr)
-+ while (cur) {
-+ if (cur->cr == cr) {
-+ /* Found existing call. */
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_GR303_EOC:
-+ case PRI_SWITCH_GR303_EOC_PATH:
-+ case PRI_SWITCH_GR303_TMC:
-+ case PRI_SWITCH_GR303_TMC_SWITCHING:
-+ break;
-+ default:
-+ if (!ctrl->bri) {
-+ /* PRI is set to whoever called us */
-+ cur->pri = ctrl;
-+ }
-+ break;
-+ }
- return cur;
-+ }
- prev = cur;
- cur = cur->next;
- }
-+
- /* No call exists, make a new one */
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "-- Making new call for cr %d\n", cr);
--
-- if (!(cur = calloc(1, sizeof(*cur))))
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "-- Making new call for cr %d\n", cr);
-+ }
-+
-+ cur = calloc(1, sizeof(*cur));
-+ if (!cur) {
- return NULL;
-+ }
-
-- call_init(cur);
-- /* Call reference */
-- cur->cr = cr;
-- /* PRI is set to whoever called us */
-- if (pri->bri && (pri->localtype == PRI_CPE) && pri->subchannel && outboundnew)
-- cur->pri = pri->subchannel;
-- else
-- cur->pri = pri;
-+ /* Initialize call structure. */
-+ q931_init_call_record(ctrl, cur, cr);
-
- /* Append to end of list */
-- if (prev)
-+ if (prev) {
- prev->next = cur;
-- else
-+ } else {
- *master->callpool = cur;
--
-+ }
-+
- return cur;
- }
-
--q931_call *q931_new_call(struct pri *pri)
-+q931_call *q931_new_call(struct pri *ctrl)
- {
- q931_call *cur;
-
- do {
-- cur = *pri->callpool;
-- pri->cref++;
-- if (!pri->bri) {
-- if (pri->cref > 32767)
-- pri->cref = 1;
-+ cur = *ctrl->callpool;
-+ ctrl->cref++;
-+ if (!ctrl->bri) {
-+ if (ctrl->cref > 32767)
-+ ctrl->cref = 1;
- } else {
-- if (pri->cref > 127)
-- pri->cref = 1;
-+ if (ctrl->cref > 127)
-+ ctrl->cref = 1;
- }
- while(cur) {
-- if (cur->cr == (0x8000 | pri->cref))
-+ if (cur->cr == (0x8000 | ctrl->cref))
- break;
- cur = cur->next;
- }
- } while(cur);
-
-- return q931_getcall(pri, pri->cref | 0x8000, 1);
-+ return q931_getcall(ctrl, ctrl->cref | 0x8000);
- }
-
--static void q931_destroy(struct pri *pri, int cr, q931_call *c)
-+static void stop_t303(struct q931_call *call);
-+
-+static void cleanup_and_free_call(struct q931_call *cur)
- {
-- q931_call *cur, *prev;
-+ stop_t303(cur);
-+ pri_schedule_del(cur->pri, cur->retranstimer);
-+ pri_call_apdu_queue_cleanup(cur);
-+ free(cur);
-+}
-
-+static void pri_create_fake_clearing(struct q931_call *c, struct pri *master);
-+
-+void q931_destroycall(struct pri *ctrl, q931_call *c)
-+{
-+ q931_call *cur;
-+ q931_call *prev;
-+ q931_call *slave;
-+ int i;
-+ int slavesleft;
-+ int slaveidx;
-+
-+ if (q931_is_dummy_call(c)) {
-+ /* Cannot destroy the dummy call. */
-+ return;
-+ }
-+ if (c->master_call != c) {
-+ slave = c;
-+ c = slave->master_call;
-+ } else {
-+ slave = NULL;
-+ }
-+
- /* For destroying, make sure we are using the master span, since it maintains the call pool */
-- for (;pri->master; pri = pri->master);
-+ ctrl = PRI_MASTER(ctrl);
-
- prev = NULL;
-- cur = *pri->callpool;
-- while(cur) {
-- if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
-+ cur = *ctrl->callpool;
-+ while (cur) {
-+ if (cur == c) {
-+ slaveidx = -1;
-+ if (slave) {
-+ for (i = 0; i < Q931_MAX_TEI; i++) {
-+ if (cur->subcalls[i] == slave) {
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "Destroying subcall %p of call %p at %d\n",
-+ slave, cur, i);
-+ }
-+ cleanup_and_free_call(slave);
-+ cur->subcalls[i] = NULL;
-+ slaveidx = i;
-+ break;
-+ }
-+ }
-+ }
-+
-+ slavesleft = 0;
-+ for (i = 0; i < Q931_MAX_TEI; i++) {
-+ if (cur->subcalls[i]) {
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "Subcall still present at %d\n", i);
-+ }
-+ slavesleft++;
-+ }
-+ }
-+
-+ /* We have 3 different phases to deal with:
-+ * 1.) Sent outbound call, but no response, indicated by t203 present
-+ * 2.) Sent outbound call, with responses, indicated by lack of t203 and subcalls present
-+ * 3.) Outbound call connected, indicated by pri_winner > -1
-+ *
-+ * If chan_dahdi hangs up in phase:
-+ * 1.) T303 will be present, and we will fake clear in this case
-+ * 2.) pri_winner will be < 0 and subcalls will be present.
-+ * 3.) pri_winner will be > -1 and we will free the master when the winner dies.
-+ *
-+ * If remote ends hang up in phase:
-+ * 1.) Impossible, defined by phase.
-+ * 2.) When last end hangs up, we should cause a fake clearing.
-+ * 3.) Pass events to winner up and be freed when winner is freed
-+ *
-+ * Exceptional conditions in phase:
-+ * 1.) None.
-+ * 2.) None.
-+ * 3.) We hang up a call so quickly that it hangs up before other competing lines finish hangup sequence
-+ * Subcalls present still even though we have hung up the winner.
-+ *
-+ * So, we could say:
-+ * If, when the library user hangs up the master call, and there are more than one subcall up, we fake clear
-+ * regardless of whether or not we drop down to one subcall left in the clearing process.
-+ *
-+ * If there are only one call up, we mirror what it does.
-+ *
-+ * OR
-+ *
-+ * Phase 2. them clearing:
-+ * For handling of Phase 2 (indicated by not running and pri_winner not present):
-+ * We create a fake hangup sequence after all the subcalls have been destroyed and after
-+ *
-+ * "" us clearing:
-+ * For we need to start the fake clearing, but it needs to be half of a fake clearing, not a full one (since we already had a hangup).
-+ *
-+ * For handling of Phase 3 plus exceptions:
-+ *
-+ * If pri_winner exists, we mirror him in terms of events (which provides our hangup sequence), and when we have the complete
-+ * hangup sequence completed (destroy called on master call), if there still exist non winner subcalls at this time, we declare the master
-+ * call as dead and free it when the last subcall clears.
-+ */
-+
-+ if ((slave && !slavesleft) &&
-+ ((cur->pri_winner < 0) || (slave && slaveidx != cur->pri_winner))) {
-+ pri_create_fake_clearing(cur, ctrl);
-+ return;
-+ }
-+
-+ if (slavesleft) {
-+ return;
-+ }
-+
-+ /* Master call or normal call destruction. */
-+ if ((cur->pri_winner > -1) && cur->outboundbroadcast) {
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl,
-+ "Since we already had a winner, we should just be able to kill the call anyways\n");
-+ }
-+ }
- if (prev)
- prev->next = cur->next;
- else
-- *pri->callpool = cur->next;
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate));
-- if (cur->retranstimer)
-- pri_schedule_del(pri, cur->retranstimer);
-- pri_call_apdu_queue_cleanup(cur);
-- free(cur);
-+ *ctrl->callpool = cur->next;
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl,
-+ "NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s, hold-state %s\n",
-+ q931_call_state_str(cur->ourcallstate),
-+ q931_call_state_str(cur->peercallstate),
-+ q931_hold_state_str(cur->hold_state));
-+ pri_schedule_del(ctrl, cur->hold_timer);
-+ cleanup_and_free_call(cur);
- return;
- }
- prev = cur;
- cur = cur->next;
- }
-- pri_error(pri, "Can't destroy call %d!\n", cr);
-+ pri_error(ctrl, "Can't destroy call %p cref:%d!\n", c, c->cr);
- }
-
--static void q931_destroycall(struct pri *pri, int cr)
-+static int add_ie(struct pri *ctrl, q931_call *call, int msgtype, int ie, q931_ie *iet, int maxlen, int *codeset)
- {
-- return q931_destroy(pri, cr, NULL);
--}
--
--
--void __q931_destroycall(struct pri *pri, q931_call *c)
--{
-- if (pri && c)
-- q931_destroy(pri,0, c);
-- return;
--}
--
--static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie *iet, int maxlen, int *codeset)
--{
- unsigned int x;
- int res, total_res;
- int have_shift;
-@@ -2473,7 +3775,7 @@
- total_res = 0;
- do {
- iet->ie = ie;
-- res = ies[x].transmit(ie, pri, call, msgtype, iet, maxlen, ++order);
-+ res = ies[x].transmit(ie, ctrl, call, msgtype, iet, maxlen, ++order);
- /* Error if res < 0 or ignored if res == 0 */
- if (res < 0)
- return res;
-@@ -2484,8 +3786,7 @@
- maxlen -= res;
- iet = (q931_ie *)((char *)iet + res);
- }
-- }
-- while (res > 0 && order < ies_count);
-+ } while (res > 0 && order < ies_count);
- if (have_shift && total_res) {
- if (Q931_IE_CODESET(ies[x].ie))
- *codeset = Q931_IE_CODESET(ies[x].ie);
-@@ -2493,12 +3794,12 @@
- }
- return total_res;
- } else {
-- pri_error(pri, "!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);
-+ pri_error(ctrl, "!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);
- return -1;
- }
- }
- }
-- pri_error(pri, "!! Unknown IE %d (%s)\n", ie, ie2str(ie));
-+ pri_error(ctrl, "!! Unknown IE %d (%s)\n", ie, ie2str(ie));
- return -1;
- }
-
-@@ -2513,25 +3814,37 @@
- return code2str(disc, discs, sizeof(discs) / sizeof(discs[0]));
- }
-
--void q931_dump(struct pri *pri, q931_h *h, int len, int txrx)
-+void q931_dump(struct pri *ctrl, q931_h *h, int len, int txrx)
- {
- q931_mh *mh;
- char c;
- int x=0, r;
- int cur_codeset;
- int codeset;
-+ int cref;
-+
- c = txrx ? '>' : '<';
-- pri_message(pri, "%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
-- pri_message(pri, "%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n", c, h->crlen, q931_cr(h) & 0x7FFF, q931_cr(h) & 0x7FFF, (h->crv[0] & 0x80) ? "Terminator" : "Originator");
-+ pri_message(ctrl, "%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
-+ cref = q931_cr(h);
-+ pri_message(ctrl, "%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n",
-+ c, h->crlen, cref & 0x7FFF, cref & 0x7FFF,
-+ (cref == Q931_DUMMY_CALL_REFERENCE)
-+ ? "Dummy"
-+ : (cref & 0x8000) ? "Terminator" : "Originator");
-+
- /* Message header begins at the end of the call reference number */
- mh = (q931_mh *)(h->contents + h->crlen);
-- pri_message(pri, "%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
-+ if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
-+ pri_message(ctrl, "%c Message Type: %s (%d)\n", c, maintenance_msg2str(mh->msg, h->pd), mh->msg);
-+ } else {
-+ pri_message(ctrl, "%c Message Type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
-+ }
- /* Drop length of header, including call reference */
- len -= (h->crlen + 3);
- codeset = cur_codeset = 0;
- while(x < len) {
- r = ielen((q931_ie *)(mh->data + x));
-- q931_dumpie(pri, cur_codeset, (q931_ie *)(mh->data + x), c);
-+ q931_dumpie(ctrl, cur_codeset, (q931_ie *)(mh->data + x), c);
- switch (mh->data[x] & 0xf8) {
- case Q931_LOCKING_SHIFT:
- if ((mh->data[x] & 7) > 0)
-@@ -2547,86 +3860,106 @@
- x += r;
- }
- if (x > len)
-- pri_error(pri, "XXX Message longer than it should be?? XXX\n");
-+ pri_error(ctrl, "XXX Message longer than it should be?? XXX\n");
- }
-
--static int q931_handle_ie(int codeset, struct pri *pri, q931_call *c, int msg, q931_ie *ie)
-+static int q931_handle_ie(int codeset, struct pri *ctrl, q931_call *c, int msg, q931_ie *ie)
- {
- unsigned int x;
- int full_ie = Q931_FULL_IE(codeset, ie->ie);
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl, "-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
- for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
- if (full_ie == ies[x].ie) {
- if (ies[x].receive)
-- return ies[x].receive(full_ie, pri, c, msg, ie, ielen(ie));
-+ return ies[x].receive(full_ie, ctrl, c, msg, ie, ielen(ie));
- else {
-- if (pri->debug & PRI_DEBUG_Q931_ANOMALY)
-- pri_error(pri, "!! No handler for IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
-+ if (ctrl->debug & PRI_DEBUG_Q931_ANOMALY)
-+ pri_error(ctrl, "!! No handler for IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
- return -1;
- }
- }
- }
-- pri_message(pri, "!! Unknown IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
-+ pri_message(ctrl, "!! Unknown IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
- return -1;
- }
-
--static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len)
-+/* Returns header and message header and modifies length in place */
-+static void init_header(struct pri *ctrl, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len, int protodisc)
- {
-- /* Returns header and message header and modifies length in place */
-- q931_h *h = (q931_h *)buf;
-- q931_mh * mh;
-- h->pd = pri->protodisc;
-+ q931_h *h = (q931_h *) buf;
-+ q931_mh *mh;
-+ unsigned crv;
-+
-+ if (protodisc) {
-+ h->pd = protodisc;
-+ } else {
-+ h->pd = ctrl->protodisc;
-+ }
- h->x0 = 0; /* Reserved 0 */
-- if (!pri->bri) {
-- h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */
-- if (call->cr || call->forceinvert) {
-- h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
-- h->crv[1] = (call->cr & 0xff);
-- } else {
-- /* Unless of course this has no call reference */
-- h->crv[0] = 0;
-- h->crv[1] = 0;
-- }
-- if (pri->subchannel && !pri->bri) {
-+ if (q931_is_dummy_call(call)) {
-+ h->crlen = 0;
-+ } else if (!ctrl->bri) {
-+ /* Two bytes of Call Reference. */
-+ h->crlen = 2;
-+ /* Invert the top bit to make it from our sense */
-+ crv = (unsigned) call->cr;
-+ h->crv[0] = ((crv >> 8) ^ 0x80) & 0xff;
-+ h->crv[1] = crv & 0xff;
-+ if (ctrl->subchannel && !ctrl->bri) {
- /* On GR-303, top bit is always 0 */
- h->crv[0] &= 0x7f;
- }
- } else {
- h->crlen = 1;
-- if (call->cr || call->forceinvert) {
-- h->crv[0] = (((call->cr ^ 0x8000) & 0x8000) >> 8) | (call->cr & 0x7f);
-- } else {
-- /* Unless of course this has no call reference */
-- h->crv[0] = 0;
-- }
-+ /* Invert the top bit to make it from our sense */
-+ crv = (unsigned) call->cr;
-+ h->crv[0] = (((crv >> 8) ^ 0x80) & 0x80) | (crv & 0x7f);
- }
-- mh = (q931_mh *)(h->contents + h->crlen);
-+ *hb = h;
-+
-+ *len -= 3;/* Protocol discriminator, call reference length, message type id */
-+ *len -= h->crlen;
-+
-+ mh = (q931_mh *) (h->contents + h->crlen);
- mh->f = 0;
-- *hb = h;
- *mhb = mh;
-- if (h->crlen == 2)
-- *len -= 5;
-- else
-- *len -= 4;
--
- }
-
--static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr)
-+static int q931_xmit(struct pri *ctrl, q931_h *h, int len, int cr, int uiframe)
- {
-- q921_transmit_iframe(pri, h, len, cr);
-+ if (uiframe) {
-+ q921_transmit_uiframe(ctrl, h, len);
-+ } else {
-+ q921_transmit_iframe(ctrl, h, len, cr);
-+ }
- /* The transmit operation might dump the q921 header, so logging the q931
- message body after the transmit puts the sections of the message in the
- right order in the log */
-- if (pri->debug & PRI_DEBUG_Q931_DUMP)
-- q931_dump(pri, h, len, 1);
-+ if (ctrl->debug & PRI_DEBUG_Q931_DUMP)
-+ q931_dump(ctrl, h, len, 1);
- #ifdef LIBPRI_COUNTERS
-- pri->q931_txcount++;
-+ ctrl->q931_txcount++;
- #endif
- return 0;
- }
-
--static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
-+/*!
-+ * \internal
-+ * \brief Build and send the requested message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param msgtype Q.931 message type to build.
-+ * \param ies List of ie's to put in the message.
-+ *
-+ * \note The ie's in the ie list must be in numerical order.
-+ * See Q.931 section 4.5.1 coding rules.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[])
- {
- unsigned char buf[1024];
- q931_h *h;
-@@ -2636,18 +3969,24 @@
- int offset=0;
- int x;
- int codeset;
--
-+
-+ if (call->outboundbroadcast && call->master_call == call && msgtype != Q931_SETUP) {
-+ pri_error(ctrl,
-+ "Attempting to use master call record to send %s on BRI PTMP NT %p\n",
-+ msg2str(msgtype), ctrl);
-+ return -1;
-+ }
-+
- memset(buf, 0, sizeof(buf));
- len = sizeof(buf);
-- init_header(pri, c, buf, &h, &mh, &len);
-- mh->msg = msgtype;
-+ init_header(ctrl, call, buf, &h, &mh, &len, (msgtype >> 8));
-+ mh->msg = msgtype & 0x00ff;
- x=0;
- codeset = 0;
- while(ies[x] > -1) {
-- res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
--
-+ res = add_ie(ctrl, call, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
- if (res < 0) {
-- pri_error(pri, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
-+ pri_error(ctrl, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
- return -1;
- }
-
-@@ -2657,20 +3996,121 @@
- }
- /* Invert the logic */
- len = sizeof(buf) - len;
-- q931_xmit(c->pri, h, len, 1);
-- c->acked = 1;
-+
-+ ctrl = call->pri;
-+ if (BRI_TE_PTMP(ctrl)) {
-+ /*
-+ * Must use the BRI subchannel structure to send with the correct TEI.
-+ * Note: If the subchannel is NULL then there is no TEI assigned and
-+ * we should not be sending anything out at this time.
-+ */
-+ ctrl = ctrl->subchannel;
-+ }
-+ if (ctrl) {
-+ int uiframe;
-+
-+ switch (msgtype) {
-+ case Q931_SETUP:
-+ /*
-+ * For NT-PTMP mode, we need to check the following:
-+ * MODE = NT-PTMP
-+ * MESSAGE = SETUP
-+ *
-+ * If those are true, we need to send the SETUP in a UI frame
-+ * instead of an I-frame.
-+ */
-+ if (BRI_NT_PTMP(ctrl))
-+ uiframe = 1;
-+ else
-+ uiframe = 0;
-+ break;
-+ case Q931_FACILITY:
-+ if (ctrl->tei == Q921_TEI_GROUP) {
-+ /* Broadcast TEI. */
-+ if (q931_is_dummy_call(call)) {
-+ /*
-+ * This is a FACILITY message on the dummy call reference
-+ * for the broadcast TEI.
-+ */
-+ uiframe = 1;
-+ } else {
-+ pri_error(ctrl,
-+ "Attempting to broadcast %s on cref %d\n",
-+ msg2str(msgtype), call->cr);
-+ return -1;
-+ }
-+ } else {
-+ uiframe = 0;
-+ }
-+ break;
-+ default:
-+ uiframe = 0;
-+ break;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl,
-+ "Sending message for call %p on %p TEI/SAPI %d/%d, call->pri is %p, TEI/SAPI %d/%d\n",
-+ call,
-+ ctrl, ctrl->tei, ctrl->sapi,
-+ call->pri, call->pri->tei, call->pri->sapi);
-+ }
-+ q931_xmit(ctrl, h, len, 1, uiframe);
-+ }
-+ call->acked = 1;
- return 0;
- }
-
--static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };
-+static int maintenance_service_ies[] = { Q931_IE_CHANGE_STATUS, Q931_CHANNEL_IDENT, -1 };
-
--static int q931_status(struct pri *pri, q931_call *c, int cause)
-+int maintenance_service_ack(struct pri *ctrl, q931_call *c)
- {
-+ int pd = MAINTENANCE_PROTOCOL_DISCRIMINATOR_1;
-+ int mt = ATT_SERVICE_ACKNOWLEDGE;
-+
-+ if (ctrl->switchtype == PRI_SWITCH_NI2) {
-+ pd = MAINTENANCE_PROTOCOL_DISCRIMINATOR_2;
-+ mt = NATIONAL_SERVICE_ACKNOWLEDGE;
-+ }
-+ return send_message(ctrl, c, (pd << 8) | mt, maintenance_service_ies);
-+}
-+
-+int maintenance_service(struct pri *ctrl, int span, int channel, int changestatus)
-+{
-+ struct q931_call *c;
-+ int pd = MAINTENANCE_PROTOCOL_DISCRIMINATOR_1;
-+ int mt = ATT_SERVICE;
-+
-+ c = q931_getcall(ctrl, 0 | 0x8000);
-+ if (!c) {
-+ return -1;
-+ }
-+ if (channel > -1) {
-+ c->channelno = channel & 0xff;
-+ c->chanflags = FLAG_EXCLUSIVE;
-+ } else {
-+ c->channelno = channel;
-+ c->chanflags = FLAG_EXCLUSIVE | FLAG_WHOLE_INTERFACE;
-+ }
-+ c->ds1no = span;
-+ c->ds1explicit = 0;
-+ c->changestatus = changestatus;
-+
-+ if (ctrl->switchtype == PRI_SWITCH_NI2) {
-+ pd = MAINTENANCE_PROTOCOL_DISCRIMINATOR_2;
-+ mt = NATIONAL_SERVICE;
-+ }
-+ return send_message(ctrl, c, (pd << 8) | mt, maintenance_service_ies);
-+}
-+
-+static int status_ies[] = { Q931_CAUSE, Q931_IE_CALL_STATE, -1 };
-+
-+static int q931_status(struct pri *ctrl, q931_call *c, int cause)
-+{
- q931_call *cur = NULL;
- if (!cause)
- cause = PRI_CAUSE_RESPONSE_TO_STATUS_ENQUIRY;
- if (c->cr > -1)
-- cur = *pri->callpool;
-+ cur = *ctrl->callpool;
- while(cur) {
- if (cur->cr == c->cr) {
- cur->cause=cause;
-@@ -2681,79 +4121,156 @@
- cur = cur->next;
- }
- if (!cur) {
-- pri_message(pri, "YYY Here we get reset YYY\n");
-+ pri_message(ctrl, "YYY Here we get reset YYY\n");
- /* something went wrong, respond with "no such call" */
- c->ourcallstate = Q931_CALL_STATE_NULL;
- c->peercallstate = Q931_CALL_STATE_NULL;
- cur=c;
- }
-- return send_message(pri, cur, Q931_STATUS, status_ies);
-+ return send_message(ctrl, cur, Q931_STATUS, status_ies);
- }
-
--static int information_ies[] = { Q931_IE_KEYPAD_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 };
-+static int information_ies[] = { Q931_CALLED_PARTY_NUMBER, -1 };
-
--int q931_information(struct pri *pri, q931_call *c, char digit)
-+int q931_information(struct pri *ctrl, q931_call *c, char digit)
- {
-- c->callednum[0] = digit;
-- c->callednum[1] = '\0';
-- return send_message(pri, c, Q931_INFORMATION, information_ies);
-+ c->overlap_digits[0] = digit;
-+ c->overlap_digits[1] = '\0';
-+
-+ /*
-+ * Since we are doing overlap dialing now, we need to accumulate
-+ * the digits into call->called.number.str.
-+ */
-+ c->called.number.valid = 1;
-+ if (strlen(c->called.number.str) < sizeof(c->called.number.str) - 1) {
-+ /* There is enough room for the new digit. */
-+ strcat(c->called.number.str, c->overlap_digits);
-+ }
-+
-+ return send_message(ctrl, c, Q931_INFORMATION, information_ies);
- }
-
- static int keypad_facility_ies[] = { Q931_IE_KEYPAD_FACILITY, -1 };
-
--int q931_keypad_facility(struct pri *pri, q931_call *call, char *digits)
-+int q931_keypad_facility(struct pri *ctrl, q931_call *call, const char *digits)
- {
- libpri_copy_string(call->keypad_digits, digits, sizeof(call->keypad_digits));
-- return send_message(pri, call, Q931_INFORMATION, keypad_facility_ies);
-+ return send_message(ctrl, call, Q931_INFORMATION, keypad_facility_ies);
- }
-
- static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
-
--static int restart_ack(struct pri *pri, q931_call *c)
-+static int restart_ack(struct pri *ctrl, q931_call *c)
- {
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
- c->peercallstate = Q931_CALL_STATE_NULL;
-- return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
-+ return send_message(ctrl, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
- }
-
- static int facility_ies[] = { Q931_IE_FACILITY, -1 };
-
--int q931_facility(struct pri*pri, q931_call *c)
-+int q931_facility(struct pri*ctrl, q931_call *c)
- {
-- return send_message(pri, c, Q931_FACILITY, facility_ies);
-+ return send_message(ctrl, c, Q931_FACILITY, facility_ies);
- }
-
--static int notify_ies[] = { Q931_IE_NOTIFY_IND, -1 };
-+static int notify_ies[] = { Q931_IE_NOTIFY_IND, Q931_IE_REDIRECTION_NUMBER, -1 };
-
--int q931_notify(struct pri *pri, q931_call *c, int channel, int info)
-+/*!
-+ * \internal
-+ * \brief Actually send a NOTIFY message with optional redirection number.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param notify Notification indicator
-+ * \param number Redirection number to send if not NULL.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int q931_notify_redirection_helper(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number)
- {
-- if ((pri->switchtype == PRI_SWITCH_EUROISDN_T1) || (pri->switchtype != PRI_SWITCH_EUROISDN_E1)) {
-- if ((info > 0x2) || (info < 0x00))
-+ if (number) {
-+ call->redirection_number = *number;
-+ } else {
-+ q931_party_number_init(&call->redirection_number);
-+ }
-+ call->notify = notify;
-+ return send_message(ctrl, call, Q931_NOTIFY, notify_ies);
-+}
-+
-+/*!
-+ * \brief Send a NOTIFY message with optional redirection number.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg
-+ * \param notify Notification indicator
-+ * \param number Redirection number to send if not NULL.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number)
-+{
-+ int status;
-+ unsigned idx;
-+ struct q931_call *subcall;
-+
-+ if (call->outboundbroadcast && call->master_call == call) {
-+ status = 0;
-+ for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
-+ subcall = call->subcalls[idx];
-+ if (subcall) {
-+ /* Send to all subcalls that have given a positive response. */
-+ switch (subcall->ourcallstate) {
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_ACTIVE:
-+ if (q931_notify_redirection_helper(ctrl, subcall, notify, number)) {
-+ status = -1;
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ }
-+ } else {
-+ status = q931_notify_redirection_helper(ctrl, call, notify, number);
-+ }
-+ return status;
-+}
-+
-+int q931_notify(struct pri *ctrl, q931_call *c, int channel, int info)
-+{
-+ if ((ctrl->switchtype == PRI_SWITCH_EUROISDN_T1) || (ctrl->switchtype != PRI_SWITCH_EUROISDN_E1)) {
-+ if ((info > 0x2) || (info < 0x00)) {
- return 0;
-+ }
- }
-
-- if (info >= 0)
-- c->notify = info & 0x7F;
-- else
-- c->notify = -1;
-- return send_message(pri, c, Q931_NOTIFY, notify_ies);
-+ if (info >= 0) {
-+ info = info & 0x7F;
-+ } else {
-+ info = -1;
-+ }
-+ return q931_notify_redirection(ctrl, c, info, NULL);
- }
-
- #ifdef ALERTING_NO_PROGRESS
- static int call_progress_ies[] = { -1 };
- #else
--static int call_progress_with_cause_ies[] = { Q931_PROGRESS_INDICATOR, Q931_CAUSE, -1 };
-+static int call_progress_with_cause_ies[] = { Q931_CAUSE, Q931_PROGRESS_INDICATOR, -1 };
-
- static int call_progress_ies[] = { Q931_PROGRESS_INDICATOR, -1 };
- #endif
-
--int q931_call_progress(struct pri *pri, q931_call *c, int channel, int info)
-+int q931_call_progress(struct pri *ctrl, q931_call *c, int channel, int info)
- {
- if (channel) {
- c->ds1no = (channel & 0xff00) >> 8;
- c->ds1explicit = (channel & 0x10000) >> 16;
-- channel &= 0xff;
-- c->channelno = channel;
-+ c->channelno = channel & 0xff;
- }
-
- if (info) {
-@@ -2762,21 +4279,20 @@
- c->progressmask = PRI_PROG_INBAND_AVAILABLE;
- } else {
- /* PI is mandatory IE for PROGRESS message - Q.931 3.1.8 */
-- pri_error(pri, "XXX Progress message requested but no information is provided\n");
-+ pri_error(ctrl, "XXX Progress message requested but no information is provided\n");
- c->progressmask = 0;
- }
-
- c->alive = 1;
-- return send_message(pri, c, Q931_PROGRESS, call_progress_ies);
-+ return send_message(ctrl, c, Q931_PROGRESS, call_progress_ies);
- }
-
--int q931_call_progress_with_cause(struct pri *pri, q931_call *c, int channel, int info, int cause)
-+int q931_call_progress_with_cause(struct pri *ctrl, q931_call *c, int channel, int info, int cause)
- {
- if (channel) {
- c->ds1no = (channel & 0xff00) >> 8;
- c->ds1explicit = (channel & 0x10000) >> 16;
-- channel &= 0xff;
-- c->channelno = channel;
-+ c->channelno = channel & 0xff;
- }
-
- if (info) {
-@@ -2785,7 +4301,7 @@
- c->progressmask = PRI_PROG_INBAND_AVAILABLE;
- } else {
- /* PI is mandatory IE for PROGRESS message - Q.931 3.1.8 */
-- pri_error(pri, "XXX Progress message requested but no information is provided\n");
-+ pri_error(ctrl, "XXX Progress message requested but no information is provided\n");
- c->progressmask = 0;
- }
-
-@@ -2794,7 +4310,7 @@
- c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-
- c->alive = 1;
-- return send_message(pri, c, Q931_PROGRESS, call_progress_with_cause_ies);
-+ return send_message(ctrl, c, Q931_PROGRESS, call_progress_with_cause_ies);
- }
-
- #ifdef ALERTING_NO_PROGRESS
-@@ -2803,17 +4319,16 @@
- static int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
- #endif
-
--int q931_call_proceeding(struct pri *pri, q931_call *c, int channel, int info)
-+int q931_call_proceeding(struct pri *ctrl, q931_call *c, int channel, int info)
- {
- if (channel) {
- c->ds1no = (channel & 0xff00) >> 8;
- c->ds1explicit = (channel & 0x10000) >> 16;
-- channel &= 0xff;
-- c->channelno = channel;
-+ c->channelno = channel & 0xff;
- }
- c->chanflags &= ~FLAG_PREFERRED;
- c->chanflags |= FLAG_EXCLUSIVE;
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_INCOMING_CALL_PROCEEDING);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_INCOMING_CALL_PROCEEDING);
- c->peercallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
- if (info) {
- c->progloc = LOC_PRIV_NET_LOCAL_USER;
-@@ -2823,62 +4338,73 @@
- c->progressmask = 0;
- c->proc = 1;
- c->alive = 1;
-- return send_message(pri, c, Q931_CALL_PROCEEDING, call_proceeding_ies);
-+ return send_message(ctrl, c, Q931_CALL_PROCEEDING, call_proceeding_ies);
- }
- #ifndef ALERTING_NO_PROGRESS
--static int alerting_ies[] = { Q931_PROGRESS_INDICATOR, Q931_IE_USER_USER, -1 };
-+static int alerting_ies[] = { Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_IE_USER_USER, -1 };
- #else
--static int alerting_ies[] = { -1 };
-+static int alerting_ies[] = { Q931_IE_FACILITY, -1 };
- #endif
-
--int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
-+int q931_alerting(struct pri *ctrl, q931_call *c, int channel, int info)
- {
- if (!c->proc)
-- q931_call_proceeding(pri, c, channel, 0);
-+ q931_call_proceeding(ctrl, c, channel, 0);
- if (info) {
- c->progloc = LOC_PRIV_NET_LOCAL_USER;
- c->progcode = CODE_CCITT;
- c->progressmask = PRI_PROG_INBAND_AVAILABLE;
- } else
- c->progressmask = 0;
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_RECEIVED);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_RECEIVED);
- c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
- c->alive = 1;
-- return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_QSIG:
-+ if (c->local_id.name.valid) {
-+ /* Send calledName with ALERTING */
-+ rose_called_name_encode(ctrl, c, Q931_ALERTING);
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return send_message(ctrl, c, Q931_ALERTING, alerting_ies);
- }
-
--static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
-+static int setup_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, -1 };
-
--int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
-+int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn)
- {
- if (channel) {
- c->ds1no = (channel & 0xff00) >> 8;
- c->ds1explicit = (channel & 0x10000) >> 16;
-- channel &= 0xff;
-- c->channelno = channel;
-+ c->channelno = channel & 0xff;
- }
- c->chanflags &= ~FLAG_PREFERRED;
- c->chanflags |= FLAG_EXCLUSIVE;
-- if (nonisdn && (pri->switchtype != PRI_SWITCH_DMS100)) {
-+ if (nonisdn && (ctrl->switchtype != PRI_SWITCH_DMS100)) {
- c->progloc = LOC_PRIV_NET_LOCAL_USER;
- c->progcode = CODE_CCITT;
- c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
- } else
- c->progressmask = 0;
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OVERLAP_RECEIVING);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OVERLAP_RECEIVING);
- c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
- c->alive = 1;
-- return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
-+ return send_message(ctrl, c, Q931_SETUP_ACKNOWLEDGE, setup_ack_ies);
- }
-
- /* T313 expiry, first time */
- static void pri_connect_timeout(void *data)
- {
- struct q931_call *c = data;
-- struct pri *pri = c->pri;
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "Timed out looking for connect acknowledge\n");
-- q931_disconnect(pri, c, PRI_CAUSE_NORMAL_CLEARING);
-+ struct pri *ctrl = c->pri;
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl, "Timed out looking for connect acknowledge\n");
-+ q931_disconnect(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
-
- }
-
-@@ -2886,85 +4412,120 @@
- static void pri_release_timeout(void *data)
- {
- struct q931_call *c = data;
-- struct pri *pri = c->pri;
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "Timed out looking for release complete\n");
-+ struct pri *ctrl = c->pri;
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl, "Timed out looking for release complete\n");
- c->t308_timedout++;
- c->alive = 1;
-
- /* The call to q931_release will re-schedule T308 */
-- q931_release(pri, c, c->cause);
-+ q931_release(ctrl, c, c->cause);
- }
-
- /* T308 expiry, second time */
- static void pri_release_finaltimeout(void *data)
- {
- struct q931_call *c = data;
-- struct pri *pri = c->pri;
-+ struct pri *ctrl = c->pri;
- c->alive = 1;
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "Final time-out looking for release complete\n");
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl, "Final time-out looking for release complete\n");
- c->t308_timedout++;
- c->ourcallstate = Q931_CALL_STATE_NULL;
- c->peercallstate = Q931_CALL_STATE_NULL;
-- pri->schedev = 1;
-- pri->ev.e = PRI_EVENT_HANGUP_ACK;
-- pri->ev.hangup.channel = c->channelno;
-- pri->ev.hangup.cause = c->cause;
-- pri->ev.hangup.cref = c->cr;
-- pri->ev.hangup.call = c;
-- pri->ev.hangup.aoc_units = c->aoc_units;
-- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
-- q931_hangup(pri, c, c->cause);
-+ q931_clr_subcommands(ctrl);
-+ ctrl->schedev = 1;
-+ ctrl->ev.e = PRI_EVENT_HANGUP_ACK;
-+ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
-+ ctrl->ev.hangup.channel = q931_encode_channel(c);
-+ ctrl->ev.hangup.cause = c->cause;
-+ ctrl->ev.hangup.cref = c->cr;
-+ ctrl->ev.hangup.call = c->master_call;
-+ ctrl->ev.hangup.aoc_units = c->aoc_units;
-+ ctrl->ev.hangup.call_held = NULL;
-+ ctrl->ev.hangup.call_active = NULL;
-+ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
-+ pri_hangup(ctrl, c, c->cause);
- }
-
- /* T305 expiry, first time */
- static void pri_disconnect_timeout(void *data)
- {
- struct q931_call *c = data;
-- struct pri *pri = c->pri;
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "Timed out looking for release\n");
-+ struct pri *ctrl = c->pri;
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl, "Timed out looking for release\n");
- c->alive = 1;
-- q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
-+ q931_release(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
- }
-
--int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
-+static int connect_ies[] = {
-+ Q931_CHANNEL_IDENT,
-+ Q931_IE_FACILITY,
-+ Q931_PROGRESS_INDICATOR,
-+ Q931_DISPLAY,
-+ Q931_IE_CONNECTED_NUM,
-+ Q931_IE_CONNECTED_SUBADDR,
-+ -1
-+};
-+
-+int q931_connect(struct pri *ctrl, q931_call *c, int channel, int nonisdn)
- {
- if (channel) {
- c->ds1no = (channel & 0xff00) >> 8;
- c->ds1explicit = (channel & 0x10000) >> 16;
-- channel &= 0xff;
-- c->channelno = channel;
-+ c->channelno = channel & 0xff;
- }
- c->chanflags &= ~FLAG_PREFERRED;
- c->chanflags |= FLAG_EXCLUSIVE;
-- if (nonisdn && (pri->switchtype != PRI_SWITCH_DMS100)) {
-+ if (nonisdn && (ctrl->switchtype != PRI_SWITCH_DMS100)) {
- c->progloc = LOC_PRIV_NET_LOCAL_USER;
- c->progcode = CODE_CCITT;
- c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
- } else
- c->progressmask = 0;
-- if(pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG)
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
-+ if(ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG)
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
- else
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CONNECT_REQUEST);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CONNECT_REQUEST);
- c->peercallstate = Q931_CALL_STATE_ACTIVE;
- c->alive = 1;
- /* Connect request timer */
-- if (c->retranstimer)
-- pri_schedule_del(pri, c->retranstimer);
-+ pri_schedule_del(ctrl, c->retranstimer);
- c->retranstimer = 0;
-- if ((c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && (pri->bri || (!pri->subchannel)))
-- c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T313], pri_connect_timeout, c);
-- return send_message(pri, c, Q931_CONNECT, connect_ies);
-+ if ((c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && (ctrl->bri || (!ctrl->subchannel)))
-+ c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T313], pri_connect_timeout, c);
-+
-+ if (c->redirecting.state == Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3) {
-+ c->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
-+ /* Send DivertingLegInformation3 with CONNECT. */
-+ c->redirecting.to = c->local_id;
-+ if (!c->redirecting.to.number.valid) {
-+ q931_party_number_init(&c->redirecting.to.number);
-+ c->redirecting.to.number.valid = 1;
-+ c->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ }
-+ rose_diverting_leg_information3_encode(ctrl, c, Q931_CONNECT);
-+ }
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_QSIG:
-+ if (c->local_id.name.valid) {
-+ /* Send connectedName with CONNECT */
-+ rose_connected_name_encode(ctrl, c, Q931_CONNECT);
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ return send_message(ctrl, c, Q931_CONNECT, connect_ies);
- }
-
- static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
-
--int q931_release(struct pri *pri, q931_call *c, int cause)
-+int q931_release(struct pri *ctrl, q931_call *c, int cause)
- {
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RELEASE_REQUEST);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_RELEASE_REQUEST);
- /* c->peercallstate stays the same */
- if (c->alive) {
- c->alive = 0;
-@@ -2972,26 +4533,26 @@
- c->causecode = CODE_CCITT;
- c->causeloc = LOC_PRIV_NET_LOCAL_USER;
- if (c->acked) {
-- if (c->retranstimer)
-- pri_schedule_del(pri, c->retranstimer);
-+ pri_schedule_del(ctrl, c->retranstimer);
- if (!c->t308_timedout) {
-- c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T308], pri_release_timeout, c);
-+ c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T308], pri_release_timeout, c);
- } else {
-- c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T308], pri_release_finaltimeout, c);
-+ c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T308], pri_release_finaltimeout, c);
- }
-- return send_message(pri, c, Q931_RELEASE, release_ies);
-+ return send_message(ctrl, c, Q931_RELEASE, release_ies);
- } else
-- return send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies); /* Yes, release_ies, not release_complete_ies */
-+ return send_message(ctrl, c, Q931_RELEASE_COMPLETE, release_ies); /* Yes, release_ies, not release_complete_ies */
- } else
- return 0;
- }
-
- static int restart_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
-
--int q931_restart(struct pri *pri, int channel)
-+int q931_restart(struct pri *ctrl, int channel)
- {
- struct q931_call *c;
-- c = q931_getcall(pri, 0 | 0x8000, 1);
-+
-+ c = q931_getcall(ctrl, 0 | 0x8000);
- if (!c)
- return -1;
- if (!channel)
-@@ -2999,20 +4560,19 @@
- c->ri = 0;
- c->ds1no = (channel & 0xff00) >> 8;
- c->ds1explicit = (channel & 0x10000) >> 16;
-- channel &= 0xff;
-- c->channelno = channel;
-+ c->channelno = channel & 0xff;
- c->chanflags &= ~FLAG_PREFERRED;
- c->chanflags |= FLAG_EXCLUSIVE;
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_RESTART);
- c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
-- return send_message(pri, c, Q931_RESTART, restart_ies);
-+ return send_message(ctrl, c, Q931_RESTART, restart_ies);
- }
-
--static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
-+static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_FACILITY, Q931_IE_USER_USER, -1 };
-
--int q931_disconnect(struct pri *pri, q931_call *c, int cause)
-+int q931_disconnect(struct pri *ctrl, q931_call *c, int cause)
- {
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_DISCONNECT_REQUEST);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_DISCONNECT_REQUEST);
- c->peercallstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
- if (c->alive) {
- c->alive = 0;
-@@ -3020,27 +4580,125 @@
- c->causecode = CODE_CCITT;
- c->causeloc = LOC_PRIV_NET_LOCAL_USER;
- c->sendhangupack = 1;
-- if (c->retranstimer)
-- pri_schedule_del(pri, c->retranstimer);
-- c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T305], pri_disconnect_timeout, c);
-- return send_message(pri, c, Q931_DISCONNECT, disconnect_ies);
-+ pri_schedule_del(ctrl, c->retranstimer);
-+ c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T305], pri_disconnect_timeout, c);
-+ return send_message(ctrl, c, Q931_DISCONNECT, disconnect_ies);
- } else
- return 0;
- }
-
--static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY,
-- Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_IE_USER_USER, Q931_SENDING_COMPLETE,
-- Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, -1 };
-+static int setup_ies[] = {
-+ Q931_BEARER_CAPABILITY,
-+ Q931_CHANNEL_IDENT,
-+ Q931_IE_FACILITY,
-+ Q931_PROGRESS_INDICATOR,
-+ Q931_NETWORK_SPEC_FAC,
-+ Q931_DISPLAY,
-+ Q931_IE_KEYPAD_FACILITY,
-+ Q931_REVERSE_CHARGE_INDIC,
-+ Q931_CALLING_PARTY_NUMBER,
-+ Q931_CALLING_PARTY_SUBADDR,
-+ Q931_CALLED_PARTY_NUMBER,
-+ Q931_CALLED_PARTY_SUBADDR,
-+ Q931_REDIRECTING_NUMBER,
-+ Q931_IE_USER_USER,
-+ Q931_SENDING_COMPLETE,
-+ Q931_IE_ORIGINATING_LINE_INFO,
-+ Q931_IE_GENERIC_DIGITS,
-+ -1
-+};
-
--static int gr303_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
-+static int gr303_setup_ies[] = {
-+ Q931_BEARER_CAPABILITY,
-+ Q931_CHANNEL_IDENT,
-+ -1
-+};
-
--static int cis_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 };
-+/*! Call Independent Signalling SETUP ie's */
-+static int cis_setup_ies[] = {
-+ Q931_BEARER_CAPABILITY,
-+ Q931_CHANNEL_IDENT,
-+ Q931_IE_FACILITY,
-+ Q931_IE_KEYPAD_FACILITY,
-+ Q931_CALLING_PARTY_NUMBER,
-+ Q931_CALLING_PARTY_SUBADDR,
-+ Q931_CALLED_PARTY_NUMBER,
-+ Q931_CALLED_PARTY_SUBADDR,
-+ Q931_SENDING_COMPLETE,
-+ -1
-+};
-
--int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
-+static void stop_t303(struct q931_call *call)
- {
-+ /* T303 should only be running on the master call */
-+ pri_schedule_del(call->master_call->pri, call->master_call->t303_timer);
-+ call->master_call->t303_timer = 0;
-+}
-+
-+static void t303_expiry(void *data);
-+
-+static void start_t303(struct q931_call *call)
-+{
-+ if (call->t303_timer) {
-+ pri_error(call->pri, "Should not have T303 set when starting again. Stopping first\n");
-+ stop_t303(call);
-+ }
-+
-+ //pri_error(call->pri, "T303 should be %d\n", call->pri->timers[PRI_TIMER_T303]);
-+ call->t303_timer = pri_schedule_event(call->pri, call->pri->timers[PRI_TIMER_T303], t303_expiry, call);
-+}
-+
-+static void pri_fake_clearing(void *data);
-+
-+static void t303_expiry(void *data)
-+{
-+ struct q931_call *c = data;
-+ struct pri *ctrl = c->pri;
- int res;
--
--
-+
-+ c->t303_expirycnt++;
-+ c->t303_timer = 0;
-+
-+ if (c->cause != -1) {
-+ /* We got a DISCONNECT, RELEASE, or RELEASE_COMPLETE and no other responses. */
-+ pri_fake_clearing(c);
-+ } else if (c->t303_expirycnt < 2) {
-+ if (ctrl->subchannel && !ctrl->bri)
-+ res = send_message(ctrl, c, Q931_SETUP, gr303_setup_ies);
-+ else if (c->cis_call)
-+ res = send_message(ctrl, c, Q931_SETUP, cis_setup_ies);
-+ else
-+ res = send_message(ctrl, c, Q931_SETUP, setup_ies);
-+
-+ if (res) {
-+ pri_error(c->pri, "Error resending setup message!\n");
-+ }
-+ start_t303(c);
-+ } else {
-+ c->cause = PRI_CAUSE_NO_USER_RESPONSE;
-+ pri_fake_clearing(c);
-+ }
-+}
-+
-+int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
-+{
-+ int res;
-+
-+ if (!req->called.number.valid && (!req->keypad_digits || !req->keypad_digits[0])) {
-+ /* No called number or keypad digits to send. */
-+ return -1;
-+ }
-+
-+ c->called = req->called;
-+ libpri_copy_string(c->overlap_digits, req->called.number.str, sizeof(c->overlap_digits));
-+
-+ if (req->keypad_digits) {
-+ libpri_copy_string(c->keypad_digits, req->keypad_digits,
-+ sizeof(c->keypad_digits));
-+ } else {
-+ c->keypad_digits[0] = '\0';
-+ }
-+
- c->transcapability = req->transmode;
- c->transmoderate = TRANS_MODE_64_CIRCUIT;
- if (!req->userl1)
-@@ -3050,89 +4708,68 @@
- c->userl3 = -1;
- c->ds1no = (req->channel & 0xff00) >> 8;
- c->ds1explicit = (req->channel & 0x10000) >> 16;
-- req->channel &= 0xff;
-- if ((pri->localtype == PRI_CPE) && pri->subchannel && !pri->bri) {
-- req->channel = 0;
-- req->exclusive = 0;
-+ if ((ctrl->localtype == PRI_CPE) && ctrl->subchannel && !ctrl->bri) {
-+ c->channelno = 0;
-+ c->chanflags = 0;
-+ } else {
-+ c->channelno = req->channel & 0xff;
-+ if (req->exclusive) {
-+ c->chanflags = FLAG_EXCLUSIVE;
-+ } else {
-+ c->chanflags = FLAG_PREFERRED;
-+ }
- }
--
-- c->channelno = req->channel;
-+
- c->slotmap = -1;
- c->nonisdn = req->nonisdn;
- c->newcall = 0;
-- c->justsignalling = req->justsignalling;
-+ c->cis_call = req->cis_call;
-+ c->cis_auto_disconnect = req->cis_auto_disconnect;
- c->complete = req->numcomplete;
-- if (req->exclusive)
-- c->chanflags = FLAG_EXCLUSIVE;
-- else if (c->channelno)
-- c->chanflags = FLAG_PREFERRED;
-- if (req->caller) {
-- libpri_copy_string(c->callernum, req->caller, sizeof(c->callernum));
-- c->callerplan = req->callerplan;
-- if (req->callername)
-- libpri_copy_string(c->callername, req->callername, sizeof(c->callername));
-- else
-- c->callername[0] = '\0';
-- if ((pri->switchtype == PRI_SWITCH_DMS100) ||
-- (pri->switchtype == PRI_SWITCH_ATT4ESS)) {
-- /* Doesn't like certain presentation types */
-- if (!(req->callerpres & 0x7c))
-- req->callerpres = PRES_ALLOWED_NETWORK_NUMBER;
-- }
-- c->callerpres = req->callerpres;
-- } else {
-- c->callernum[0] = '\0';
-- c->callername[0] = '\0';
-- c->callerplan = PRI_UNKNOWN;
-- c->callerpres = PRES_NUMBER_NOT_AVAILABLE;
-+
-+ if (req->caller.number.valid) {
-+ c->local_id = req->caller;
-+ q931_party_id_fixup(ctrl, &c->local_id);
- }
-- if (req->redirectingnum) {
-- libpri_copy_string(c->redirectingnum, req->redirectingnum, sizeof(c->redirectingnum));
-- c->redirectingplan = req->redirectingplan;
-- if ((pri->switchtype == PRI_SWITCH_DMS100) ||
-- (pri->switchtype == PRI_SWITCH_ATT4ESS)) {
-- /* Doesn't like certain presentation types */
-- if (!(req->redirectingpres & 0x7c))
-- req->redirectingpres = PRES_ALLOWED_NETWORK_NUMBER;
-- }
-- c->redirectingpres = req->redirectingpres;
-- c->redirectingreason = req->redirectingreason;
-- } else {
-- c->redirectingnum[0] = '\0';
-- c->redirectingplan = PRI_UNKNOWN;
-- c->redirectingpres = PRES_NUMBER_NOT_AVAILABLE;
-- c->redirectingreason = PRI_REDIR_UNKNOWN;
-+
-+ if (req->redirecting.from.number.valid) {
-+ c->redirecting = req->redirecting;
-+ q931_party_id_fixup(ctrl, &c->redirecting.from);
-+ q931_party_id_fixup(ctrl, &c->redirecting.to);
-+ q931_party_id_fixup(ctrl, &c->redirecting.orig_called);
- }
-- if (req->called) {
-- libpri_copy_string(c->callednum, req->called, sizeof(c->callednum));
-- c->calledplan = req->calledplan;
-- } else
-- return -1;
-
- if (req->useruserinfo)
- libpri_copy_string(c->useruserinfo, req->useruserinfo, sizeof(c->useruserinfo));
- else
- c->useruserinfo[0] = '\0';
-
-- if (req->nonisdn && (pri->switchtype == PRI_SWITCH_NI2))
-+ if (req->nonisdn && (ctrl->switchtype == PRI_SWITCH_NI2))
- c->progressmask = PRI_PROG_CALLER_NOT_ISDN;
- else
- c->progressmask = 0;
-
-- pri_call_add_standard_apdus(pri, c);
-+ c->reversecharge = req->reversecharge;
-
-- if (pri->subchannel && !pri->bri)
-- res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
-- else if (c->justsignalling)
-- res = send_message(pri, c, Q931_SETUP, cis_setup_ies);
-+ pri_call_add_standard_apdus(ctrl, c);
-+
-+ if (ctrl->subchannel && !ctrl->bri)
-+ res = send_message(ctrl, c, Q931_SETUP, gr303_setup_ies);
-+ else if (c->cis_call)
-+ res = send_message(ctrl, c, Q931_SETUP, cis_setup_ies);
- else
-- res = send_message(pri, c, Q931_SETUP, setup_ies);
-+ res = send_message(ctrl, c, Q931_SETUP, setup_ies);
- if (!res) {
- c->alive = 1;
- /* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */
- c->sendhangupack = 1;
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_INITIATED);
-- c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_INITIATED);
-+ c->peercallstate = Q931_CALL_STATE_CALL_PRESENT;
-+ c->t303_expirycnt = 0;
-+ if (BRI_NT_PTMP(ctrl)) {
-+ c->outboundbroadcast = 1;
-+ }
-+ start_t303(c);
- }
- return res;
-
-@@ -3140,22 +4777,22 @@
-
- static int release_complete_ies[] = { Q931_IE_USER_USER, -1 };
-
--static int q931_release_complete(struct pri *pri, q931_call *c, int cause)
-+static int q931_release_complete(struct pri *ctrl, q931_call *c, int cause)
- {
- int res = 0;
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
- c->peercallstate = Q931_CALL_STATE_NULL;
- if (cause > -1) {
- c->cause = cause;
- c->causecode = CODE_CCITT;
- c->causeloc = LOC_PRIV_NET_LOCAL_USER;
- /* release_ies has CAUSE in it */
-- res = send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies);
-+ res = send_message(ctrl, c, Q931_RELEASE_COMPLETE, release_ies);
- } else
-- res = send_message(pri, c, Q931_RELEASE_COMPLETE, release_complete_ies);
-+ res = send_message(ctrl, c, Q931_RELEASE_COMPLETE, release_complete_ies);
- c->alive = 0;
- /* release the structure */
-- res += q931_hangup(pri,c,cause);
-+ res += pri_hangup(ctrl, c, cause);
- return res;
- }
-
-@@ -3163,46 +4800,553 @@
-
- static int gr303_connect_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 };
-
--static int q931_connect_acknowledge(struct pri *pri, q931_call *c)
-+static int q931_connect_acknowledge(struct pri *ctrl, q931_call *c)
- {
-- if (pri->subchannel && !pri->bri) {
-- if (pri->localtype == PRI_CPE)
-- return send_message(pri, c, Q931_CONNECT_ACKNOWLEDGE, gr303_connect_acknowledge_ies);
-+ if (ctrl->subchannel && !ctrl->bri) {
-+ if (ctrl->localtype == PRI_CPE)
-+ return send_message(ctrl, c, Q931_CONNECT_ACKNOWLEDGE, gr303_connect_acknowledge_ies);
- } else
-- return send_message(pri, c, Q931_CONNECT_ACKNOWLEDGE, connect_acknowledge_ies);
-+ return send_message(ctrl, c, Q931_CONNECT_ACKNOWLEDGE, connect_acknowledge_ies);
- return 0;
- }
-
--int q931_hangup(struct pri *pri, q931_call *c, int cause)
-+/*!
-+ * \internal
-+ * \brief Find the winning subcall if it exists or current call if not outboundbroadcast.
-+ *
-+ * \param call Starting Q.931 call record of search.
-+ *
-+ * \retval winning-call or given call if not outboundbroadcast.
-+ * \retval NULL if no winning call yet.
-+ */
-+static struct q931_call *q931_find_winning_call(struct q931_call *call)
- {
-+ struct q931_call *master;
-+
-+ master = call->master_call;
-+ if (master->outboundbroadcast) {
-+ /* We have potential subcalls. Now get the winning call if declared yet. */
-+ if (master->pri_winner < 0) {
-+ /* Winner not declared yet.*/
-+ call = NULL;
-+ } else {
-+ call = master->subcalls[master->pri_winner];
-+ }
-+ }
-+ return call;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Send HOLD message response wait timeout.
-+ *
-+ * \param data Q.931 call leg. (Master Q.931 subcall structure)
-+ *
-+ * \return Nothing
-+ */
-+static void q931_hold_timeout(void *data)
-+{
-+ struct q931_call *call = data;
-+ struct pri *ctrl = call->pri;
-+
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "Time-out waiting for HOLD response\n");
-+ }
-+
-+ /* Ensure that the timer is deleted. */
-+ pri_schedule_del(ctrl, call->hold_timer);
-+ call->hold_timer = 0;
-+
-+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
-+
-+ q931_clr_subcommands(ctrl);
-+ ctrl->schedev = 1;
-+ ctrl->ev.e = PRI_EVENT_HOLD_REJ;
-+ ctrl->ev.hold_rej.channel = q931_encode_channel(call);
-+ ctrl->ev.hold_rej.call = call;
-+ ctrl->ev.hold_rej.cause = PRI_CAUSE_MESSAGE_TYPE_NONEXIST;
-+ ctrl->ev.hold_rej.subcmds = &ctrl->subcmds;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Determine if a hold request is allowed now.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
-+ *
-+ * \retval TRUE if we can send a HOLD request.
-+ * \retval FALSE if not allowed.
-+ */
-+static int q931_is_hold_allowed(const struct pri *ctrl, const struct q931_call *call)
-+{
-+ int allowed;
-+
-+ allowed = 0;
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* HOLD request only allowed in these states if point-to-point mode. */
-+ break;
-+ }
-+ /* Fall through */
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_ACTIVE:
-+ switch (call->hold_state) {
-+ case Q931_HOLD_STATE_IDLE:
-+ allowed = 1;
-+ break;
-+ default:
-+ break;
-+ }
-+ break;
-+ case Q931_CALL_STATE_DISCONNECT_INDICATION:
-+ case Q931_CALL_STATE_RELEASE_REQUEST:
-+ /* Ignore HOLD request in these states. */
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return allowed;
-+}
-+
-+static int hold_ies[] = {
-+ -1
-+};
-+
-+/*!
-+ * \brief Send the HOLD message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int q931_send_hold(struct pri *ctrl, struct q931_call *call)
-+{
-+ struct q931_call *winner;
-+
-+ winner = q931_find_winning_call(call);
-+ if (!winner || !q931_is_hold_allowed(ctrl, call)) {
-+ return -1;
-+ }
-+ pri_schedule_del(ctrl, call->hold_timer);
-+ call->hold_timer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T_HOLD],
-+ q931_hold_timeout, call);
-+ if (send_message(ctrl, winner, Q931_HOLD, hold_ies)) {
-+ pri_schedule_del(ctrl, call->hold_timer);
-+ call->hold_timer = 0;
-+ return -1;
-+ }
-+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_HOLD_REQ);
-+ return 0;
-+}
-+
-+static int hold_ack_ies[] = {
-+ -1
-+};
-+
-+/*!
-+ * \brief Send the HOLD ACKNOWLEDGE message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call)
-+{
-+ struct q931_call *winner;
-+
-+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
-+
-+ winner = q931_find_winning_call(call);
-+ if (!winner) {
-+ return -1;
-+ }
-+
-+ /* Call is now on hold so forget the channel. */
-+ winner->channelno = 0;/* No channel */
-+ winner->ds1no = 0;
-+ winner->ds1explicit = 0;
-+ winner->chanflags = 0;
-+
-+ return send_message(ctrl, winner, Q931_HOLD_ACKNOWLEDGE, hold_ack_ies);
-+}
-+
-+static int hold_reject_ies[] = {
-+ Q931_CAUSE,
-+ -1
-+};
-+
-+/*!
-+ * \internal
-+ * \brief Send the HOLD REJECT message only.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (subcall)
-+ * \param cause Q.931 cause code for rejecting the hold request.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int q931_send_hold_rej_msg(struct pri *ctrl, struct q931_call *call, int cause)
-+{
-+ call->cause = cause;
-+ call->causecode = CODE_CCITT;
-+ call->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+ return send_message(ctrl, call, Q931_HOLD_REJECT, hold_reject_ies);
-+}
-+
-+/*!
-+ * \brief Send the HOLD REJECT message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
-+ * \param cause Q.931 cause code for rejecting the hold request.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int q931_send_hold_rej(struct pri *ctrl, struct q931_call *call, int cause)
-+{
-+ struct q931_call *winner;
-+
-+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
-+
-+ winner = q931_find_winning_call(call);
-+ if (!winner) {
-+ return -1;
-+ }
-+
-+ return q931_send_hold_rej_msg(ctrl, winner, cause);
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Send RETRIEVE message response wait timeout.
-+ *
-+ * \param data Q.931 call leg. (Master Q.931 subcall structure)
-+ *
-+ * \return Nothing
-+ */
-+static void q931_retrieve_timeout(void *data)
-+{
-+ struct q931_call *call = data;
-+ struct pri *ctrl = call->pri;
-+ struct q931_call *winner;
-+
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "Time-out waiting for RETRIEVE response\n");
-+ }
-+
-+ /* Ensure that the timer is deleted. */
-+ pri_schedule_del(ctrl, call->hold_timer);
-+ call->hold_timer = 0;
-+
-+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
-+
-+ winner = q931_find_winning_call(call);
-+ if (winner) {
-+ /* Call is still on hold so forget the channel. */
-+ winner->channelno = 0;/* No channel */
-+ winner->ds1no = 0;
-+ winner->ds1explicit = 0;
-+ winner->chanflags = 0;
-+ }
-+
-+ q931_clr_subcommands(ctrl);
-+ ctrl->schedev = 1;
-+ ctrl->ev.e = PRI_EVENT_RETRIEVE_REJ;
-+ ctrl->ev.retrieve_rej.channel = q931_encode_channel(call);
-+ ctrl->ev.retrieve_rej.call = call;
-+ ctrl->ev.retrieve_rej.cause = PRI_CAUSE_MESSAGE_TYPE_NONEXIST;
-+ ctrl->ev.retrieve_rej.subcmds = &ctrl->subcmds;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Determine if a retrieve request is allowed now.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
-+ *
-+ * \retval TRUE if we can send a RETRIEVE request.
-+ * \retval FALSE if not allowed.
-+ */
-+static int q931_is_retrieve_allowed(const struct pri *ctrl, const struct q931_call *call)
-+{
-+ int allowed;
-+
-+ allowed = 0;
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* RETRIEVE request only allowed in these states if point-to-point mode. */
-+ break;
-+ }
-+ /* Fall through */
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_ACTIVE:
-+ switch (call->hold_state) {
-+ case Q931_HOLD_STATE_CALL_HELD:
-+ allowed = 1;
-+ break;
-+ default:
-+ break;
-+ }
-+ break;
-+ case Q931_CALL_STATE_DISCONNECT_INDICATION:
-+ case Q931_CALL_STATE_RELEASE_REQUEST:
-+ /* Ignore RETRIEVE request in these states. */
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return allowed;
-+}
-+
-+static int retrieve_ies[] = {
-+ Q931_CHANNEL_IDENT,
-+ -1
-+};
-+
-+/*!
-+ * \brief Send the RETRIEVE message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
-+ * \param channel Encoded channel id to use. If zero do not send channel id.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int q931_send_retrieve(struct pri *ctrl, struct q931_call *call, int channel)
-+{
-+ struct q931_call *winner;
-+
-+ winner = q931_find_winning_call(call);
-+ if (!winner || !q931_is_retrieve_allowed(ctrl, call)) {
-+ return -1;
-+ }
-+
-+ if (channel) {
-+ winner->ds1no = (channel & 0xff00) >> 8;
-+ winner->ds1explicit = (channel & 0x10000) >> 16;
-+ winner->channelno = channel & 0xff;
-+ if (ctrl->localtype == PRI_NETWORK) {
-+ winner->chanflags = FLAG_EXCLUSIVE;
-+ } else {
-+ winner->chanflags = FLAG_PREFERRED;
-+ }
-+ } else {
-+ /* Do not send Q931_CHANNEL_IDENT */
-+ winner->chanflags = 0;
-+ }
-+
-+ pri_schedule_del(ctrl, call->hold_timer);
-+ call->hold_timer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T_RETRIEVE],
-+ q931_retrieve_timeout, call);
-+ if (send_message(ctrl, winner, Q931_RETRIEVE, retrieve_ies)) {
-+ pri_schedule_del(ctrl, call->hold_timer);
-+ call->hold_timer = 0;
-+
-+ /* Call is still on hold so forget the channel. */
-+ winner->channelno = 0;/* No channel */
-+ winner->ds1no = 0;
-+ winner->ds1explicit = 0;
-+ winner->chanflags = 0;
-+ return -1;
-+ }
-+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_RETRIEVE_REQ);
-+ return 0;
-+}
-+
-+static int retrieve_ack_ies[] = {
-+ Q931_CHANNEL_IDENT,
-+ -1
-+};
-+
-+/*!
-+ * \brief Send the RETRIEVE ACKNOWLEDGE message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
-+ * \param channel Encoded channel id to use.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int q931_send_retrieve_ack(struct pri *ctrl, struct q931_call *call, int channel)
-+{
-+ struct q931_call *winner;
-+
-+ winner = q931_find_winning_call(call);
-+ if (!winner) {
-+ return -1;
-+ }
-+
-+ winner->ds1no = (channel & 0xff00) >> 8;
-+ winner->ds1explicit = (channel & 0x10000) >> 16;
-+ winner->channelno = channel & 0xff;
-+ winner->chanflags = FLAG_EXCLUSIVE;
-+
-+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
-+
-+ return send_message(ctrl, winner, Q931_RETRIEVE_ACKNOWLEDGE, retrieve_ack_ies);
-+}
-+
-+static int retrieve_reject_ies[] = {
-+ Q931_CAUSE,
-+ -1
-+};
-+
-+/*!
-+ * \internal
-+ * \brief Send the RETRIEVE REJECT message only.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (subcall)
-+ * \param cause Q.931 cause code for rejecting the retrieve request.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int q931_send_retrieve_rej_msg(struct pri *ctrl, struct q931_call *call, int cause)
-+{
-+ call->cause = cause;
-+ call->causecode = CODE_CCITT;
-+ call->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+ return send_message(ctrl, call, Q931_RETRIEVE_REJECT, retrieve_reject_ies);
-+}
-+
-+/*!
-+ * \brief Send the RETRIEVE REJECT message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
-+ * \param cause Q.931 cause code for rejecting the retrieve request.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+int q931_send_retrieve_rej(struct pri *ctrl, struct q931_call *call, int cause)
-+{
-+ struct q931_call *winner;
-+
-+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
-+
-+ winner = q931_find_winning_call(call);
-+ if (!winner) {
-+ return -1;
-+ }
-+
-+ /* Call is still on hold so forget the channel. */
-+ winner->channelno = 0;/* No channel */
-+ winner->ds1no = 0;
-+ winner->ds1explicit = 0;
-+ winner->chanflags = 0;
-+
-+ return q931_send_retrieve_rej_msg(ctrl, winner, cause);
-+}
-+
-+static int pri_internal_clear(void *data);
-+
-+/* Fake RELEASE for NT-PTMP initiated SETUPs w/o response */
-+static void pri_fake_clearing(void *data)
-+{
-+ struct q931_call *c = data;
-+ struct pri *ctrl = c->pri;
-+
-+ c->performing_fake_clearing = 1;
-+ if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
-+ ctrl->schedev = 1;
-+}
-+
-+static void pri_create_fake_clearing(struct q931_call *c, struct pri *master)
-+{
-+ c->pri = master;
-+
-+ pri_schedule_del(master, c->retranstimer);
-+ c->retranstimer = pri_schedule_event(master, 0, pri_fake_clearing, c);
-+}
-+
-+//static int q931_get_subcall_count(struct q931_call *call);
-+
-+static int __q931_hangup(struct pri *ctrl, q931_call *c, int cause)
-+{
- int disconnect = 1;
- int release_compl = 0;
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "NEW_HANGUP DEBUG: Calling q931_hangup, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
-- if (!pri || !c)
-+ int t303_was_running = c->master_call->t303_timer;
-+
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl,
-+ "NEW_HANGUP DEBUG: Calling q931_hangup, ourstate %s, peerstate %s, hold-state %s\n",
-+ q931_call_state_str(c->ourcallstate),
-+ q931_call_state_str(c->peercallstate),
-+ q931_hold_state_str(c->master_call->hold_state));
-+ if (!ctrl || !c)
- return -1;
- /* If mandatory IE was missing, insist upon that cause code */
- if (c->cause == PRI_CAUSE_MANDATORY_IE_MISSING)
- cause = c->cause;
-- if (cause == 34 || cause == 44 || cause == 82 || cause == 1 || cause == 81) {
-+ switch (cause) {
-+ case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-+ case PRI_CAUSE_REQUESTED_CHAN_UNAVAIL:
-+ case PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST:
-+ case PRI_CAUSE_UNALLOCATED:
-+ case PRI_CAUSE_INVALID_CALL_REFERENCE:
- /* We'll send RELEASE_COMPLETE with these causes */
- disconnect = 0;
- release_compl = 1;
-- }
-- if (cause == 6 || cause == 7 || cause == 26) {
-+ break;
-+ case PRI_CAUSE_CHANNEL_UNACCEPTABLE:
-+ case PRI_CAUSE_CALL_AWARDED_DELIVERED:
-+ case PRI_CAUSE_NONSELECTED_USER_CLEARING:
- /* We'll send RELEASE with these causes */
- disconnect = 0;
-+ break;
-+ default:
-+ break;
- }
-+ if (c->cis_call) {
-+ disconnect = 0;
-+ }
-+
-+ c->hangupinitiated = 1;
-+ stop_t303(c);
-+
- /* All other causes we send with DISCONNECT */
- switch(c->ourcallstate) {
- case Q931_CALL_STATE_NULL:
- if (c->peercallstate == Q931_CALL_STATE_NULL)
- /* free the resources if we receive or send REL_COMPL */
-- q931_destroycall(pri, c->cr);
-+ pri_destroycall(ctrl, c);
- else if (c->peercallstate == Q931_CALL_STATE_RELEASE_REQUEST)
-- q931_release_complete(pri,c,cause);
-+ q931_release_complete(ctrl,c,cause);
- break;
- case Q931_CALL_STATE_CALL_INITIATED:
-+ if (c->outboundbroadcast && c->master_call == c && t303_was_running) {
-+ //c->fakeclearing = 1;
-+ //c->alive = 0;
-+ /* We need to fake a received clearing sequence in this case... */
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "Faking clearing\n");
-+ }
-+ pri_create_fake_clearing(c, PRI_MASTER(ctrl));
-+ /* This means that we never got a response from a TEI */
-+ return 0;
-+ }
- /* we sent SETUP */
- case Q931_CALL_STATE_OVERLAP_SENDING:
- /* received SETUP_ACKNOWLEDGE */
-@@ -3221,29 +5365,45 @@
- case Q931_CALL_STATE_OVERLAP_RECEIVING:
- /* received SETUP_ACKNOWLEDGE */
- /* send DISCONNECT in general */
-- if (c->peercallstate != Q931_CALL_STATE_NULL && c->peercallstate != Q931_CALL_STATE_DISCONNECT_REQUEST && c->peercallstate != Q931_CALL_STATE_DISCONNECT_INDICATION && c->peercallstate != Q931_CALL_STATE_RELEASE_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART) {
-+ switch (c->peercallstate) {
-+ default:
- if (disconnect)
-- q931_disconnect(pri,c,cause);
-+ q931_disconnect(ctrl,c,cause);
- else if (release_compl)
-- q931_release_complete(pri,c,cause);
-+ q931_release_complete(ctrl,c,cause);
- else
-- q931_release(pri,c,cause);
-- } else
-- pri_error(pri, "Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
-+ q931_release(ctrl,c,cause);
-+ break;
-+ case Q931_CALL_STATE_NULL:
-+ case Q931_CALL_STATE_DISCONNECT_REQUEST:
-+ case Q931_CALL_STATE_DISCONNECT_INDICATION:
-+ case Q931_CALL_STATE_RELEASE_REQUEST:
-+ case Q931_CALL_STATE_RESTART_REQUEST:
-+ case Q931_CALL_STATE_RESTART:
-+ pri_error(ctrl,
-+ "Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",
-+ q931_call_state_str(c->ourcallstate),
-+ q931_call_state_str(c->peercallstate));
-+ break;
-+ }
- break;
- case Q931_CALL_STATE_ACTIVE:
- /* received CONNECT */
-- q931_disconnect(pri,c,cause);
-+ if (c->cis_call) {
-+ q931_release(ctrl, c, cause);
-+ break;
-+ }
-+ q931_disconnect(ctrl,c,cause);
- break;
- case Q931_CALL_STATE_DISCONNECT_REQUEST:
- /* sent DISCONNECT */
-- q931_release(pri,c,cause);
-+ q931_release(ctrl,c,cause);
- break;
- case Q931_CALL_STATE_DISCONNECT_INDICATION:
- /* received DISCONNECT */
- if (c->peercallstate == Q931_CALL_STATE_DISCONNECT_REQUEST) {
- c->alive = 1;
-- q931_release(pri,c,cause);
-+ q931_release(ctrl,c,cause);
- }
- break;
- case Q931_CALL_STATE_RELEASE_REQUEST:
-@@ -3253,75 +5413,129 @@
- case Q931_CALL_STATE_RESTART:
- case Q931_CALL_STATE_RESTART_REQUEST:
- /* sent RESTART */
-- pri_error(pri, "q931_hangup shouldn't be called in this state, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
-+ pri_error(ctrl,
-+ "q931_hangup shouldn't be called in this state, ourstate %s, peerstate %s\n",
-+ q931_call_state_str(c->ourcallstate),
-+ q931_call_state_str(c->peercallstate));
- break;
- default:
-- pri_error(pri, "We're not yet handling hanging up when our state is %d, contact support@digium.com, ourstate %s, peerstate %s\n",
-- c->ourcallstate,
-- callstate2str(c->ourcallstate),
-- callstate2str(c->peercallstate));
-+ pri_error(ctrl,
-+ "We're not yet handling hanging up when our state is %d, contact support@digium.com, ourstate %s, peerstate %s\n",
-+ c->ourcallstate,
-+ q931_call_state_str(c->ourcallstate),
-+ q931_call_state_str(c->peercallstate));
- return -1;
- }
- /* we did handle hangup properly at this point */
- return 0;
- }
-
--int q931_receive(struct pri *pri, q931_h *h, int len)
-+static void initiate_hangup_if_needed(struct pri *pri, q931_call *call, int cause);
-+
-+int q931_hangup(struct pri *ctrl, q931_call *call, int cause)
- {
-- q931_mh *mh;
-- q931_call *c;
-- q931_ie *ie;
-- unsigned int x;
-- int y;
-- int res;
-- int r;
-- int mandies[MAX_MAND_IES];
-- int missingmand;
-- int codeset, cur_codeset;
-- int last_ie[8];
-- struct apdu_event *cur = NULL;
-+ int i;
-
-- memset(last_ie, 0, sizeof(last_ie));
-- if (pri->debug & PRI_DEBUG_Q931_DUMP)
-- q931_dump(pri, h, len, 0);
--#ifdef LIBPRI_COUNTERS
-- pri->q931_rxcount++;
--#endif
-- mh = (q931_mh *)(h->contents + h->crlen);
-- if ((h->pd == 0x3) || (h->pd == 0x43)) {
-- /* This is the weird maintenance stuff. We majorly
-- KLUDGE this by changing byte 4 from a 0xf (SERVICE)
-- to a 0x7 (SERVICE ACKNOWLEDGE) */
-- h->raw[h->crlen + 2] -= 0x8;
-- q931_xmit(pri, h, len, 1);
-- return 0;
-- } else if (h->pd != pri->protodisc) {
-- pri_error(pri, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
-- return 0;
-+ if (call->master_call->outboundbroadcast) {
-+ if (call->master_call == call) {
-+ int slaves = 0;
-+
-+ /* Master is called with hangup - initiate hangup with slaves */
-+ for (i = 0; i < Q931_MAX_TEI; i++) {
-+ if (call->subcalls[i]) {
-+ slaves++;
-+ if (i == call->master_call->pri_winner) {
-+ __q931_hangup(call->subcalls[i]->pri, call->subcalls[i], cause);
-+ } else {
-+ initiate_hangup_if_needed(call->subcalls[i]->pri, call->subcalls[i], cause);
-+ }
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "%s: Hanging up %d, winner %d\n", __FUNCTION__,
-+ i, call->master_call->pri_winner);
-+ }
-+ }
-+ }
-+
-+ call->hangupinitiated = 1;
-+
-+ if ((!slaves && (call->master_call->pri_winner < 0)) || (call->performing_fake_clearing)) {
-+ __q931_hangup(ctrl, call, cause);
-+ }
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "%s: Slaves %d\n", __FUNCTION__, slaves);
-+ }
-+ return 0;
-+ } else {
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "%s: Slave hangup\n", __FUNCTION__);
-+ }
-+ return __q931_hangup(ctrl, call, cause);
-+ }
-+ } else {
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "%s: other hangup\n", __FUNCTION__);
-+ }
-+ return __q931_hangup(ctrl, call, cause);
- }
-- c = q931_getcall(pri, q931_cr(h), 0);
-- if (!c) {
-- pri_error(pri, "Unable to locate call %d\n", q931_cr(h));
-+ return 0;
-+}
-+
-+static int prepare_to_handle_maintenance_message(struct pri *ctrl, q931_mh *mh, q931_call *c)
-+{
-+ if ((!ctrl) || (!mh) || (!c)) {
- return -1;
- }
-- /* Preliminary handling */
-+ /* SERVICE messages are a superset of messages that can take b-channels
-+ * or entire d-channels in and out of service */
- switch(mh->msg) {
-+ /* the ATT_SERVICE/ATT_SERVICE_ACKNOWLEDGE and NATIONAL_SERVICE/NATIONAL_SERVICE_ACKNOWLEDGE
-+ * are mirrors of each other. We only have to check for one type because they are pre-handled
-+ * the same way as each other */
-+ case ATT_SERVICE:
-+ case ATT_SERVICE_ACKNOWLEDGE:
-+ c->channelno = -1;
-+ c->slotmap = -1;
-+ c->chanflags = 0;
-+ c->ds1explicit = 0;
-+ c->ds1no = 0;
-+ c->cis_call = 0;
-+ c->ri = -1;
-+ c->changestatus = -1;
-+ break;
-+ default:
-+ pri_error(ctrl, "!! Don't know how to pre-handle maintenance message type '%d'\n", mh->msg);
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_call *c)
-+{
-+ if ((!ctrl) || (!mh) || (!c)) {
-+ return -1;
-+ }
-+
-+ switch(mh->msg) {
- case Q931_RESTART:
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "-- Processing Q.931 Restart\n");
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl, "-- Processing Q.931 Restart\n");
- /* Reset information */
- c->channelno = -1;
- c->slotmap = -1;
- c->chanflags = 0;
- c->ds1no = 0;
-+ c->ds1explicit = 0;
-+ c->cis_call = 0;
- c->ri = -1;
- break;
- case Q931_FACILITY:
-- c->callername[0] = '\0';
-+ if (q931_is_dummy_call(c)) {
-+ q931_party_address_init(&c->called);
-+ }
- break;
- case Q931_SETUP:
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, "-- Processing Q.931 Call Setup\n");
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl, "-- Processing Q.931 Call Setup\n");
- c->channelno = -1;
- c->slotmap = -1;
- c->chanflags = 0;
-@@ -3334,29 +5548,25 @@
- c->userl2 = -1;
- c->userl3 = -1;
- c->rateadaption = -1;
-- c->calledplan = -1;
-- c->callerplan = -1;
-- c->callerpres = -1;
-- c->callernum[0] = '\0';
-- c->callednum[0] = '\0';
-- c->callername[0] = '\0';
-- c->callerani[0] = '\0';
-- c->callerplanani = -1;
-- c->redirectingplan = -1;
-- c->redirectingpres = -1;
-- c->redirectingreason = -1;
-- c->origcalledplan = -1;
-- c->origcalledpres = -1;
-- c->origredirectingreason = -1;
-- c->redirectingnum[0] = '\0';
-- c->origcallednum[0] = '\0';
-- c->redirectingname[0] = '\0';
-- c->origcalledname[0] = '\0';
-+
-+ q931_party_address_init(&c->called);
-+ q931_party_id_init(&c->local_id);
-+ q931_party_id_init(&c->remote_id);
-+ q931_party_redirecting_init(&c->redirecting);
-+
-+ /*
-+ * Make sure that keypad and overlap digit buffers are empty in
-+ * case they are not in the message.
-+ */
-+ c->keypad_digits[0] = '\0';
-+ c->overlap_digits[0] = '\0';
-+
- c->useruserprotocoldisc = -1;
- c->useruserinfo[0] = '\0';
- c->complete = 0;
- c->nonisdn = 0;
- c->aoc_units = -1;
-+ c->reversecharge = -1;
- /* Fall through */
- case Q931_CONNECT:
- case Q931_ALERTING:
-@@ -3369,8 +5579,7 @@
- c->progressmask = 0;
- break;
- case Q931_CONNECT_ACKNOWLEDGE:
-- if (c->retranstimer)
-- pri_schedule_del(pri, c->retranstimer);
-+ pri_schedule_del(ctrl, c->retranstimer);
- c->retranstimer = 0;
- break;
- case Q931_RELEASE:
-@@ -3379,14 +5588,12 @@
- c->causecode = -1;
- c->causeloc = -1;
- c->aoc_units = -1;
-- if (c->retranstimer)
-- pri_schedule_del(pri, c->retranstimer);
-+ pri_schedule_del(ctrl, c->retranstimer);
- c->retranstimer = 0;
- c->useruserinfo[0] = '\0';
- break;
- case Q931_RELEASE_COMPLETE:
-- if (c->retranstimer)
-- pri_schedule_del(pri, c->retranstimer);
-+ pri_schedule_del(ctrl, c->retranstimer);
- c->retranstimer = 0;
- c->useruserinfo[0] = '\0';
- /* Fall through */
-@@ -3394,45 +5601,252 @@
- c->cause = -1;
- c->causecode = -1;
- c->causeloc = -1;
-- c->sugcallstate = -1;
-+ c->sugcallstate = Q931_CALL_STATE_NOT_SET;
- c->aoc_units = -1;
- break;
- case Q931_RESTART_ACKNOWLEDGE:
- c->channelno = -1;
-+ c->ds1no = 0;
-+ c->ds1explicit = 0;
-+ c->cis_call = 0;
- break;
- case Q931_INFORMATION:
-- c->callednum[0] = '\0';
-+ /*
-+ * Make sure that keypad and overlap digit buffers are empty in
-+ * case they are not in the message.
-+ */
-+ c->keypad_digits[0] = '\0';
-+ c->overlap_digits[0] = '\0';
- break;
- case Q931_STATUS_ENQUIRY:
- break;
- case Q931_SETUP_ACKNOWLEDGE:
- break;
- case Q931_NOTIFY:
-+ q931_party_number_init(&c->redirection_number);
- break;
-- case Q931_USER_INFORMATION:
-- case Q931_SEGMENT:
-- case Q931_CONGESTION_CONTROL:
- case Q931_HOLD:
-+ break;
- case Q931_HOLD_ACKNOWLEDGE:
-+ break;
- case Q931_HOLD_REJECT:
-+ c->cause = -1;
-+ break;
- case Q931_RETRIEVE:
-+ c->channelno = 0xFF;
-+ c->ds1no = 0;
-+ c->ds1explicit = 0;
-+ break;
- case Q931_RETRIEVE_ACKNOWLEDGE:
-+ break;
- case Q931_RETRIEVE_REJECT:
-+ c->cause = -1;
-+ break;
-+ case Q931_USER_INFORMATION:
-+ case Q931_SEGMENT:
-+ case Q931_CONGESTION_CONTROL:
- case Q931_RESUME:
- case Q931_RESUME_ACKNOWLEDGE:
- case Q931_RESUME_REJECT:
- case Q931_SUSPEND:
- case Q931_SUSPEND_ACKNOWLEDGE:
- case Q931_SUSPEND_REJECT:
-- pri_error(pri, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-+ pri_error(ctrl, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
- /* Fall through */
- default:
-- pri_error(pri, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-- q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
-+ pri_error(ctrl, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-+ q931_status(ctrl,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
- if (c->newcall)
-- q931_destroycall(pri,c->cr);
-+ pri_destroycall(ctrl, c);
- return -1;
- }
-+ return 0;
-+}
-+
-+static struct q931_call *q931_get_subcall_winner(struct q931_call *master)
-+{
-+ if (master->pri_winner < 0) {
-+ return NULL;
-+ } else {
-+ return master->subcalls[master->pri_winner];
-+ }
-+}
-+
-+static void initiate_hangup_if_needed(struct pri *pri, q931_call *call, int cause)
-+{
-+ if (!call->hangupinitiated) {
-+ q931_hangup(pri, call, cause);
-+ call->alive = 0;
-+ }
-+}
-+
-+#if 0
-+static int q931_get_subcall_count(struct q931_call *call)
-+{
-+ int count = 0;
-+ int i;
-+
-+ call = call->master_call;
-+ for (i = 0; i < Q931_MAX_TEI; i++) {
-+ if (call->subcalls[i])
-+ count++;
-+ }
-+
-+ return count;
-+}
-+#endif
-+
-+static void q931_set_subcall_winner(struct q931_call *subcall)
-+{
-+ struct q931_call *realcall = subcall->master_call;
-+ int i;
-+
-+ /* Set the winner first */
-+ for (i = 0; i < Q931_MAX_TEI; i++) {
-+ if (realcall->subcalls[i] && realcall->subcalls[i] == subcall) {
-+ realcall->pri_winner = i;
-+ }
-+ }
-+ if (realcall->pri_winner < 0) {
-+ pri_error(subcall->pri, "We should always find the winner in the list!\n");
-+ return;
-+ }
-+
-+ /* Start tear down of calls that were not chosen */
-+ for (i = 0; i < Q931_MAX_TEI; i++) {
-+ if (realcall->subcalls[i] && realcall->subcalls[i] != subcall) {
-+ initiate_hangup_if_needed(realcall->subcalls[i]->pri, realcall->subcalls[i],
-+ PRI_CAUSE_NONSELECTED_USER_CLEARING);
-+ }
-+ }
-+}
-+
-+static struct q931_call *q931_get_subcall(struct pri *ctrl, struct q931_call *master_call)
-+{
-+ int i;
-+ struct q931_call *cur;
-+ int firstfree = -1;
-+
-+ /* First try to locate our subcall */
-+ for (i = 0; i < Q931_MAX_TEI; i++) {
-+ if (master_call->subcalls[i]) {
-+ if (master_call->subcalls[i]->pri == ctrl) {
-+ return master_call->subcalls[i];
-+ }
-+ } else if (firstfree == -1) {
-+ firstfree = i;
-+ }
-+ }
-+ if (firstfree < 0) {
-+ pri_error(ctrl, "Tried to add more than %d TEIs to call and failed\n",
-+ Q931_MAX_TEI);
-+ return NULL;
-+ }
-+
-+ /* Create new subcall. */
-+ cur = malloc(sizeof(*cur));
-+ if (!cur) {
-+ pri_error(ctrl, "Unable to allocate call\n");
-+ return NULL;
-+ }
-+ *cur = *master_call;
-+ cur->pri = ctrl;
-+ cur->next = NULL;
-+ cur->apdus = NULL;
-+ cur->bridged_call = NULL;
-+ //cur->master_call = master_call; /* We get this assignment for free. */
-+ for (i = 0; i < Q931_MAX_TEI; ++i) {
-+ cur->subcalls[i] = NULL;
-+ }
-+ cur->t303_timer = 0;/* T303 should only be on on the master call */
-+ cur->hold_timer = 0;
-+ cur->retranstimer = 0;
-+
-+ /* Assume we sent a SETUP and this is the first response to it from this peer. */
-+ cur->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
-+ cur->peercallstate = Q931_CALL_STATE_CALL_PRESENT;
-+
-+ master_call->subcalls[firstfree] = cur;
-+
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "Adding subcall %p for TEI %d to call %p at position %d\n",
-+ cur, ctrl->tei, master_call, firstfree);
-+ }
-+ /* Should only get here if the TEI is not found */
-+ return cur;
-+}
-+
-+int q931_receive(struct pri *ctrl, q931_h *h, int len)
-+{
-+ q931_mh *mh;
-+ q931_call *c;
-+ q931_ie *ie;
-+ unsigned int x;
-+ int y;
-+ int res;
-+ int r;
-+ int mandies[MAX_MAND_IES];
-+ int missingmand;
-+ int codeset, cur_codeset;
-+ int last_ie[8];
-+ int cref;
-+
-+ memset(last_ie, 0, sizeof(last_ie));
-+ if (ctrl->debug & PRI_DEBUG_Q931_DUMP)
-+ q931_dump(ctrl, h, len, 0);
-+#ifdef LIBPRI_COUNTERS
-+ ctrl->q931_rxcount++;
-+#endif
-+ mh = (q931_mh *)(h->contents + h->crlen);
-+ if ((h->pd != ctrl->protodisc) && (h->pd != MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) && (h->pd != MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
-+ pri_error(ctrl, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
-+ return 0;
-+ }
-+ if (((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) && (!ctrl->service_message_support)) {
-+ /* Real service message support has not been enabled (and is OFF in libpri by default),
-+ * so we have to revert to the 'traditional' KLUDGE of changing byte 4 from a 0xf (SERVICE)
-+ * to a 0x7 (SERVICE ACKNOWLEDGE) */
-+ /* This is the weird maintenance stuff. We majorly
-+ KLUDGE this by changing byte 4 from a 0xf (SERVICE)
-+ to a 0x7 (SERVICE ACKNOWLEDGE) */
-+ h->raw[h->crlen + 2] -= 0x8;
-+ q931_xmit(ctrl, h, len, 1, 0);
-+ return 0;
-+ }
-+
-+ cref = q931_cr(h);
-+ c = q931_getcall(ctrl, cref);
-+ if (!c) {
-+ pri_error(ctrl, "Unable to locate call %d\n", cref);
-+ return -1;
-+ }
-+ if (c->master_call->outboundbroadcast && ctrl != PRI_MASTER(ctrl)) {
-+ c = q931_get_subcall(ctrl, c->master_call);
-+ if (!c) {
-+ pri_error(ctrl, "Unable to locate subcall for %d\n", cref);
-+ return -1;
-+ }
-+ }
-+
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl,
-+ "Received message for call %p on %p TEI/SAPI %d/%d, call->pri is %p TEI/SAPI %d/%d\n",
-+ c,
-+ ctrl, ctrl->tei, ctrl->sapi,
-+ c->pri, c->pri->tei, c->pri->sapi);
-+ }
-+
-+ /* Preliminary handling */
-+ ctrl->facility.count = 0;
-+ c->connected_number_in_message = 0;
-+ c->redirecting_number_in_message = 0;
-+ if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
-+ prepare_to_handle_maintenance_message(ctrl, mh, c);
-+ } else {
-+ prepare_to_handle_q931_message(ctrl, mh, c);
-+ }
-+ q931_clr_subcommands(ctrl);
-+
- /* Handle IEs */
- memset(mandies, 0, sizeof(mandies));
- missingmand = 0;
-@@ -3453,7 +5867,7 @@
- }
- r = ielen(ie);
- if (r > len) {
-- pri_error(pri, "XXX Message longer than it should be?? XXX\n");
-+ pri_error(ctrl, "XXX Message longer than it should be?? XXX\n");
- return -1;
- }
- /* Special processing for codeset shifts */
-@@ -3461,16 +5875,16 @@
- case Q931_LOCKING_SHIFT:
- y = ie->ie & 7; /* Requested codeset */
- /* Locking shifts couldn't go to lower codeset, and couldn't follows non-locking shifts - verify this */
-- if ((cur_codeset != codeset) && (pri->debug & PRI_DEBUG_Q931_ANOMALY))
-- pri_message(pri, "XXX Locking shift immediately follows non-locking shift (from %d through %d to %d) XXX\n", codeset, cur_codeset, y);
-+ if ((cur_codeset != codeset) && (ctrl->debug & PRI_DEBUG_Q931_ANOMALY))
-+ pri_message(ctrl, "XXX Locking shift immediately follows non-locking shift (from %d through %d to %d) XXX\n", codeset, cur_codeset, y);
- if (y > 0) {
-- if ((y < codeset) && (pri->debug & PRI_DEBUG_Q931_ANOMALY))
-- pri_error(pri, "!! Trying to locked downshift codeset from %d to %d !!\n", codeset, y);
-+ if ((y < codeset) && (ctrl->debug & PRI_DEBUG_Q931_ANOMALY))
-+ pri_error(ctrl, "!! Trying to locked downshift codeset from %d to %d !!\n", codeset, y);
- codeset = cur_codeset = y;
- }
- else {
- /* Locking shift to codeset 0 is forbidden by all specifications */
-- pri_error(pri, "!! Invalid locking shift to codeset 0 !!\n");
-+ pri_error(ctrl, "!! Invalid locking shift to codeset 0 !!\n");
- }
- break;
- case Q931_NON_LOCKING_SHIFT:
-@@ -3480,24 +5894,24 @@
- /* Sanity check for IE code order */
- if (!(ie->ie & 0x80)) {
- if (last_ie[cur_codeset] > ie->ie) {
-- if ((pri->debug & PRI_DEBUG_Q931_ANOMALY))
-- pri_message(pri, "XXX Out-of-order IE %d at codeset %d (last was %d)\n", ie->ie, cur_codeset, last_ie[cur_codeset]);
-+ if ((ctrl->debug & PRI_DEBUG_Q931_ANOMALY))
-+ pri_message(ctrl, "XXX Out-of-order IE %d at codeset %d (last was %d)\n", ie->ie, cur_codeset, last_ie[cur_codeset]);
- }
- else
- last_ie[cur_codeset] = ie->ie;
- }
- /* Ignore non-locking shifts for TR41459-based signalling */
-- switch (pri->switchtype) {
-+ switch (ctrl->switchtype) {
- case PRI_SWITCH_LUCENT5E:
- case PRI_SWITCH_ATT4ESS:
- if (cur_codeset != codeset) {
-- if ((pri->debug & PRI_DEBUG_Q931_DUMP))
-- pri_message(pri, "XXX Ignoring IE %d for temporary codeset %d XXX\n", ie->ie, cur_codeset);
-+ if ((ctrl->debug & PRI_DEBUG_Q931_DUMP))
-+ pri_message(ctrl, "XXX Ignoring IE %d for temporary codeset %d XXX\n", ie->ie, cur_codeset);
- break;
- }
- /* Fall through */
- default:
-- y = q931_handle_ie(cur_codeset, pri, c, mh->msg, ie);
-+ y = q931_handle_ie(cur_codeset, ctrl, c, mh->msg, ie);
- /* XXX Applicable to codeset 0 only? XXX */
- if (!cur_codeset && !(ie->ie & 0xf0) && (y < 0))
- mandies[MAX_MAND_IES - 1] = Q931_FULL_IE(cur_codeset, ie->ie);
-@@ -3512,33 +5926,562 @@
- for (x=0;x<MAX_MAND_IES;x++) {
- if (mandies[x]) {
- /* check if there is no channel identification when we're configured as network -> that's not an error */
-- if (((pri->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) &&
-+ if (((ctrl->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) &&
- ((mh->msg != Q931_PROGRESS) || (mandies[x] != Q931_PROGRESS_INDICATOR))) {
-- pri_error(pri, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
-+ pri_error(ctrl, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
- missingmand++;
- }
- }
- }
--
-+
-+ /* Now handle the facility ie's after all the other ie's were processed. */
-+ q931_handle_facilities(ctrl, c, mh->msg);
-+
- /* Post handling */
-+ if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
-+ res = post_handle_maintenance_message(ctrl, h->pd, mh, c);
-+ } else {
-+ int allow_event = 1, allow_posthandle = 1;
-+
-+ if (c->master_call->outboundbroadcast) {
-+ nt_ptmp_handle_q931_message(ctrl, mh, c, &allow_event, &allow_posthandle);
-+ }
-+
-+ if (allow_posthandle) {
-+ res = post_handle_q931_message(ctrl, mh, c, missingmand);
-+
-+ if (res == Q931_RES_HAVEEVENT && !allow_event) {
-+ res = 0;
-+ }
-+ } else {
-+ res = 0;
-+ }
-+ }
-+ return res;
-+}
-+
-+static int post_handle_maintenance_message(struct pri *ctrl, int protodisc, struct q931_mh *mh, struct q931_call *c)
-+{
-+ /* Do some maintenance stuff */
-+ if (((protodisc == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) && (mh->msg == ATT_SERVICE))
-+ || ((protodisc == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2) && (mh->msg == NATIONAL_SERVICE))) {
-+ if (c->channelno > 0) {
-+ ctrl->ev.e = PRI_EVENT_SERVICE;
-+ ctrl->ev.service.channel = q931_encode_channel(c);
-+ ctrl->ev.service.changestatus = 0x0f & c->changestatus;
-+ } else {
-+ switch (0x0f & c->changestatus) {
-+ case SERVICE_CHANGE_STATUS_INSERVICE:
-+ ctrl->ev.e = PRI_EVENT_DCHAN_UP;
-+ q921_dchannel_up(ctrl);
-+ break;
-+ case SERVICE_CHANGE_STATUS_OUTOFSERVICE:
-+ ctrl->ev.e = PRI_EVENT_DCHAN_DOWN;
-+ q921_dchannel_down(ctrl);
-+ break;
-+ default:
-+ pri_error(ctrl, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus));
-+ return -1;
-+ }
-+ }
-+ maintenance_service_ack(ctrl, c);
-+ return Q931_RES_HAVEEVENT;
-+ }
-+ if (((protodisc == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) && (mh->msg == ATT_SERVICE_ACKNOWLEDGE))
-+ || ((protodisc == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2) && (mh->msg == NATIONAL_SERVICE_ACKNOWLEDGE))) {
-+ if (c->channelno > 0) {
-+ ctrl->ev.e = PRI_EVENT_SERVICE_ACK;
-+ ctrl->ev.service_ack.channel = q931_encode_channel(c);
-+ ctrl->ev.service_ack.changestatus = 0x0f & c->changestatus;
-+ } else {
-+ switch (0x0f & c->changestatus) {
-+ case SERVICE_CHANGE_STATUS_INSERVICE:
-+ ctrl->ev.e = PRI_EVENT_DCHAN_UP;
-+ q921_dchannel_up(ctrl);
-+ break;
-+ case SERVICE_CHANGE_STATUS_OUTOFSERVICE:
-+ ctrl->ev.e = PRI_EVENT_DCHAN_DOWN;
-+ q921_dchannel_down(ctrl);
-+ break;
-+ default:
-+ pri_error(ctrl, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus));
-+ return -1;
-+ }
-+ }
-+ return Q931_RES_HAVEEVENT;
-+ }
-+
-+ pri_error(ctrl, "!! Don't know how to post-handle maintenance message type %d\n", mh->msg);
-+ return -1;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Rank the given Q.931 call state for call etablishment.
-+ *
-+ * \param state Q.931 call state to rank for competing PTMP NT calls.
-+ *
-+ * \return Call establishment state ranking.
-+ */
-+static enum Q931_RANKED_CALL_STATE q931_rank_state(enum Q931_CALL_STATE state)
-+{
-+ enum Q931_RANKED_CALL_STATE rank;
-+
-+ switch (state) {
-+ case Q931_CALL_STATE_CALL_INITIATED:
-+ case Q931_CALL_STATE_CALL_PRESENT:
-+ rank = Q931_RANKED_CALL_STATE_PRESENT;
-+ break;
-+ case Q931_CALL_STATE_OVERLAP_SENDING:
-+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
-+ rank = Q931_RANKED_CALL_STATE_OVERLAP;
-+ break;
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ rank = Q931_RANKED_CALL_STATE_PROCEEDING;
-+ break;
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ rank = Q931_RANKED_CALL_STATE_ALERTING;
-+ break;
-+ case Q931_CALL_STATE_ACTIVE:
-+ case Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE:
-+ rank = Q931_RANKED_CALL_STATE_CONNECT;
-+ break;
-+ default:
-+ rank = Q931_RANKED_CALL_STATE_OTHER;
-+ break;
-+ }
-+
-+ return rank;
-+}
-+
-+/*!
-+ * \brief Determine if the master will pass an event to the upper layer.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param subcall Q.931 call leg.
-+ * \param msg_type Current message type being processed.
-+ *
-+ * \note This function must parallel nt_ptmp_handle_q931_message().
-+ *
-+ * \retval TRUE if the master will pass an event to the upper layer.
-+ * \retval FALSE if the event will be blocked.
-+ */
-+int q931_master_pass_event(struct pri *ctrl, struct q931_call *subcall, int msg_type)
-+{
-+ struct q931_call *winner;
-+ struct q931_call *master;
-+ enum Q931_RANKED_CALL_STATE master_rank;
-+ enum Q931_RANKED_CALL_STATE subcall_rank;
-+ int will_pass; /*!< TRUE if the master will pass an event to the upper layer. */
-+
-+ master = subcall->master_call;
-+ if (subcall == master) {
-+ /* We are the master call so of course the master will pass an event. */
-+ return 1;
-+ }
-+
-+ winner = q931_get_subcall_winner(master);
-+ if (winner && subcall == winner) {
-+ /* We are the winner so of course the master will pass an event. */
-+ return 1;
-+ }
-+
-+ master_rank = q931_rank_state(master->ourcallstate);
-+ will_pass = 0;
-+ switch (msg_type) {
-+ case Q931_SETUP_ACKNOWLEDGE:
-+#if 0 /* Overlap dialing in PTMP NT mode not supported at the present time. */
-+ if (master_rank < Q931_RANKED_CALL_STATE_OVERLAP) {
-+ will_pass = 1;
-+ }
-+#endif /* Overlap dialing in PTMP NT mode not supported at the present time. */
-+ break;
-+ case Q931_CALL_PROCEEDING:
-+ if (master_rank < Q931_RANKED_CALL_STATE_PROCEEDING) {
-+ will_pass = 1;
-+ }
-+ break;
-+ case Q931_PROGRESS:
-+ /*
-+ * We will just ignore this message since there could be multiple devices
-+ * competing for this call. Who has access to the B channel at this time
-+ * to give in-band signals anyway?
-+ */
-+ break;
-+ case Q931_ALERTING:
-+ if (master_rank < Q931_RANKED_CALL_STATE_ALERTING) {
-+ will_pass = 1;
-+ }
-+ break;
-+ case Q931_CONNECT:
-+ if (master_rank < Q931_RANKED_CALL_STATE_CONNECT) {
-+ /* We are expected to be the winner for the next message. */
-+ will_pass = 1;
-+ }
-+ break;
-+ case Q931_DISCONNECT:
-+ case Q931_RELEASE:
-+ case Q931_RELEASE_COMPLETE:
-+ /* Only deal with the winner. */
-+ break;
-+ case Q931_FACILITY:
-+ case Q931_NOTIFY:
-+ if (!winner) {
-+ /* The overlap rank does not count here. */
-+ if (master_rank == Q931_RANKED_CALL_STATE_OVERLAP) {
-+ master_rank = Q931_RANKED_CALL_STATE_PRESENT;
-+ }
-+ subcall_rank = q931_rank_state(subcall->ourcallstate);
-+ if (subcall_rank == Q931_RANKED_CALL_STATE_OVERLAP) {
-+ subcall_rank = Q931_RANKED_CALL_STATE_PRESENT;
-+ }
-+ if (master_rank == subcall_rank) {
-+ /*
-+ * No winner yet but the subcall is as advanced as the master.
-+ * Allow the supplementary service event to pass.
-+ */
-+ will_pass = 1;
-+ }
-+ }
-+ break;
-+ default:
-+ /* Only deal with the winner. */
-+ break;
-+ }
-+
-+ return will_pass;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Handle outboundbroadcast incoming messages for the master_call's state.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param mh Q.931 message type header.
-+ * \param subcall Q.931 call leg.
-+ * \param allow_event Where to set the allow event to upper layer flag.
-+ * \param allow_posthandle Where to set the allow post handle event flag.
-+ *
-+ * \details
-+ * This is where we interact the subcalls state with the master_call's state.
-+ *
-+ * \note This function must parallel q931_master_pass_event().
-+ *
-+ * \return Nothing
-+ */
-+static void nt_ptmp_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *subcall, int *allow_event, int *allow_posthandle)
-+{
-+ struct q931_call *master = subcall->master_call;
-+ struct q931_call *winner = q931_get_subcall_winner(master);
-+ enum Q931_RANKED_CALL_STATE master_rank;
-+ enum Q931_RANKED_CALL_STATE subcall_rank;
-+ enum Q931_CALL_STATE newstate;
-+
-+ /* For broadcast calls, we default to not allowing events to keep events received to a minimum
-+ * and to allow post processing, since that is where hangup and subcall state handling and other processing is done */
-+ *allow_event = 0;
-+ *allow_posthandle = 1;
-+
-+ master_rank = q931_rank_state(master->ourcallstate);
-+
-+ switch (mh->msg) {
-+ case Q931_SETUP_ACKNOWLEDGE:
-+#if 0 /* Overlap dialing in PTMP NT mode not supported at the present time. */
-+ if (master_rank < Q931_RANKED_CALL_STATE_OVERLAP) {
-+ *allow_event = 1;
-+ UPDATE_OURCALLSTATE(ctrl, master, Q931_CALL_STATE_OVERLAP_SENDING);
-+ }
-+#endif /* Overlap dialing in PTMP NT mode not supported at the present time. */
-+ break;
-+ case Q931_CALL_PROCEEDING:
-+ if (master_rank < Q931_RANKED_CALL_STATE_PROCEEDING) {
-+ *allow_event = 1;
-+ UPDATE_OURCALLSTATE(ctrl, master, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING);
-+ }
-+ break;
-+ case Q931_PROGRESS:
-+ /*
-+ * We will just ignore this message since there could be multiple devices
-+ * competing for this call. Who has access to the B channel at this time
-+ * to give in-band signals anyway?
-+ */
-+ break;
-+ case Q931_ALERTING:
-+ if (master_rank < Q931_RANKED_CALL_STATE_ALERTING) {
-+ *allow_event = 1;
-+ UPDATE_OURCALLSTATE(ctrl, master, Q931_CALL_STATE_CALL_DELIVERED);
-+ }
-+ break;
-+ case Q931_CONNECT:
-+ if (master_rank < Q931_RANKED_CALL_STATE_CONNECT) {
-+ UPDATE_OURCALLSTATE(ctrl, master, Q931_CALL_STATE_ACTIVE);
-+ q931_set_subcall_winner(subcall);
-+ *allow_event = 1;
-+ } else {
-+ /* Call clearing of non selected calls occurs in
-+ * q931_set_subcall_winner() - All we need to do is make sure
-+ * that this connect is not acknowledged */
-+ *allow_posthandle = 0;
-+ }
-+ break;
-+ case Q931_DISCONNECT:
-+ newstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
-+ goto process_hangup;
-+ case Q931_RELEASE:
-+ case Q931_RELEASE_COMPLETE:
-+ newstate = Q931_CALL_STATE_NULL;
-+process_hangup:
-+ if (!winner) {
-+ /* If there's not a winner, we just take the cause and pass it up to the
-+ * master_call */
-+ master->cause = subcall->cause;
-+ } else {
-+ /* There *is* a winner */
-+ if (subcall == winner) {
-+ /* .. and we're it: */
-+ *allow_event = 1;
-+ UPDATE_OURCALLSTATE(ctrl, master, newstate);
-+ }
-+ }
-+ break;
-+ case Q931_FACILITY:
-+ case Q931_NOTIFY:
-+ if (winner) {
-+ if (subcall == winner) {
-+ /* Only deal with the winner. */
-+ *allow_event = 1;
-+ }
-+ } else {
-+ /* The overlap rank does not count here. */
-+ if (master_rank == Q931_RANKED_CALL_STATE_OVERLAP) {
-+ master_rank = Q931_RANKED_CALL_STATE_PRESENT;
-+ }
-+ subcall_rank = q931_rank_state(subcall->ourcallstate);
-+ if (subcall_rank == Q931_RANKED_CALL_STATE_OVERLAP) {
-+ subcall_rank = Q931_RANKED_CALL_STATE_PRESENT;
-+ }
-+ if (master_rank == subcall_rank) {
-+ /*
-+ * No winner yet but the subcall is as advanced as the master.
-+ * Allow the supplementary service event to pass.
-+ */
-+ *allow_event = 1;
-+ }
-+ }
-+ break;
-+ default:
-+ if (winner && subcall == winner) {
-+ /* Only deal with the winner. */
-+ *allow_event = 1;
-+ }
-+ break;
-+ }
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Fill in the FACILITY event fields.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param call Q.931 call leg.
-+ *
-+ * \return Nothing
-+ */
-+static void q931_fill_facility_event(struct pri *ctrl, struct q931_call *call)
-+{
-+ ctrl->ev.e = PRI_EVENT_FACILITY;
-+ ctrl->ev.facility.subcmds = &ctrl->subcmds;
-+ ctrl->ev.facility.channel = q931_encode_channel(call);
-+ ctrl->ev.facility.cref = call->cr;
-+ ctrl->ev.facility.call = call->master_call;
-+ ctrl->ev.facility.subcall = call;
-+
-+ /* Need to do this for backward compatibility with struct pri_event_facname */
-+ libpri_copy_string(ctrl->ev.facility.callingname, call->remote_id.name.str,
-+ sizeof(ctrl->ev.facility.callingname));
-+ libpri_copy_string(ctrl->ev.facility.callingnum, call->remote_id.number.str,
-+ sizeof(ctrl->ev.facility.callingnum));
-+ ctrl->ev.facility.callingpres = q931_party_id_presentation(&call->remote_id);
-+ ctrl->ev.facility.callingplan = call->remote_id.number.plan;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief APDU wait for response message timeout.
-+ *
-+ * \param data Callback data pointer.
-+ *
-+ * \return Nothing
-+ */
-+static void q931_apdu_timeout(void *data)
-+{
-+ struct apdu_event *apdu;
-+ struct pri *ctrl;
-+ struct q931_call *call;
-+
-+ apdu = data;
-+ call = apdu->call;
-+ ctrl = call->pri;
-+
-+ q931_clr_subcommands(ctrl);
-+ apdu->response.callback(APDU_CALLBACK_REASON_TIMEOUT, ctrl, call, apdu, NULL);
-+ if (ctrl->subcmds.counter_subcmd) {
-+ q931_fill_facility_event(ctrl, call);
-+ ctrl->schedev = 1;
-+ }
-+
-+ pri_call_apdu_delete(call, apdu);
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Find the active call given the held call.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param held_call Held call to help locate a compatible active call.
-+ *
-+ * \retval master-active-call on success.
-+ * \retval NULL on error.
-+ */
-+static struct q931_call *q931_find_held_active_call(struct pri *ctrl, struct q931_call *held_call)
-+{
-+ struct pri *master;
-+ struct q931_call *cur;
-+ struct q931_call *winner;
-+ struct q931_call *match;
-+
-+ match = NULL;
-+ master = PRI_MASTER(ctrl);
-+ for (cur = *master->callpool; cur; cur = cur->next) {
-+ if (cur->hold_state == Q931_HOLD_STATE_IDLE) {
-+ /* Found an active call. */
-+ winner = q931_find_winning_call(cur);
-+ if (!winner || (BRI_NT_PTMP(ctrl) && winner->pri != held_call->pri)) {
-+ /* There is no winner or the active call does not go to the same TEI. */
-+ continue;
-+ }
-+ switch (winner->ourcallstate) {
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_ACTIVE:
-+ break;
-+ default:
-+ /* Active call not in a good state to transfer. */
-+ continue;
-+ }
-+ if (q931_party_number_cmp(&winner->remote_id.number,
-+ &held_call->remote_id.number)) {
-+ /* The remote party number does not match. This is a weak match. */
-+ match = cur;
-+ continue;
-+ }
-+ /* Found an exact match. */
-+ match = cur;
-+ break;
-+ }
-+ }
-+
-+ return match;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Find the held call given the active call.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param active_call Active call to help locate a compatible held call.
-+ *
-+ * \retval master-held-call on success.
-+ * \retval NULL on error.
-+ */
-+static struct q931_call *q931_find_held_call(struct pri *ctrl, struct q931_call *active_call)
-+{
-+ struct pri *master;
-+ struct q931_call *cur;
-+ struct q931_call *winner;
-+ struct q931_call *match;
-+
-+ match = NULL;
-+ master = PRI_MASTER(ctrl);
-+ for (cur = *master->callpool; cur; cur = cur->next) {
-+ if (cur->hold_state == Q931_HOLD_STATE_CALL_HELD) {
-+ /* Found a held call. */
-+ winner = q931_find_winning_call(cur);
-+ if (!winner || (BRI_NT_PTMP(ctrl) && winner->pri != active_call->pri)) {
-+ /* There is no winner or the held call does not go to the same TEI. */
-+ continue;
-+ }
-+ switch (winner->ourcallstate) {
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_ACTIVE:
-+ break;
-+ default:
-+ /* Held call not in a good state to transfer. */
-+ continue;
-+ }
-+ if (q931_party_number_cmp(&winner->remote_id.number,
-+ &active_call->remote_id.number)) {
-+ /* The remote party number does not match. This is a weak match. */
-+ match = cur;
-+ continue;
-+ }
-+ /* Found an exact match. */
-+ match = cur;
-+ break;
-+ }
-+ }
-+
-+ return match;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Process the decoded information in the Q.931 message.
-+ *
-+ * \param ctrl D channel controller.
-+ * \param mh Q.931 message header.
-+ * \param c Q.931 call leg.
-+ * \param missingmand Number of missing mandatory ie's.
-+ *
-+ * \retval 0 if no error or event.
-+ * \retval Q931_RES_HAVEEVENT if have an event.
-+ * \retval -1 on error.
-+ */
-+static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand)
-+{
-+ int res;
-+ struct apdu_event *cur = NULL;
-+ struct pri_subcommand *subcmd;
-+ struct q931_call *master_call;
-+
- switch(mh->msg) {
- case Q931_RESTART:
- if (missingmand) {
-- q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-- q931_destroycall(pri, c->cr);
-+ q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-+ pri_destroycall(ctrl, c);
- break;
- }
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_RESTART);
- c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
- /* Send back the Restart Acknowledge */
-- restart_ack(pri, c);
-+ restart_ack(ctrl, c);
- /* Notify user of restart event */
-- pri->ev.e = PRI_EVENT_RESTART;
-- pri->ev.restart.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-+ ctrl->ev.e = PRI_EVENT_RESTART;
-+ ctrl->ev.restart.channel = q931_encode_channel(c);
- return Q931_RES_HAVEEVENT;
- case Q931_SETUP:
- if (missingmand) {
-- q931_release_complete(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-+ q931_release_complete(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
- break;
- }
- /* Must be new call */
-@@ -3548,185 +6491,279 @@
- if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
- c->nonisdn = 1;
- c->newcall = 0;
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_PRESENT);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_PRESENT);
- c->peercallstate = Q931_CALL_STATE_CALL_INITIATED;
- /* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */
- c->alive = 0;
- if (c->transmoderate != TRANS_MODE_64_CIRCUIT) {
-- q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
-+ q931_release_complete(ctrl, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
- break;
- }
-- pri->ev.e = PRI_EVENT_RING;
-- pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.ring.callingpres = c->callerpres;
-- pri->ev.ring.callingplan = c->callerplan;
-- pri->ev.ring.callingplanani = c->callerplanani;
-- pri->ev.ring.callingplanrdnis = c->redirectingplan;
-- pri->ev.ring.callingplanorigcalled = c->origcalledplan;
-- pri->ev.ring.ani2 = c->ani2;
-- libpri_copy_string(pri->ev.ring.callingani, c->callerani, sizeof(pri->ev.ring.callingani));
-- libpri_copy_string(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum));
-- libpri_copy_string(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname));
-- pri->ev.ring.calledplan = c->calledplan;
-- libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
-- libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
-- libpri_copy_string(pri->ev.ring.origcalledname, c->origcalledname, sizeof(pri->ev.ring.origcalledname));
-- libpri_copy_string(pri->ev.ring.origcallednum, c->origcallednum, sizeof(pri->ev.ring.origcallednum));
-- libpri_copy_string(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum));
-- libpri_copy_string(pri->ev.ring.redirectingname, c->redirectingname, sizeof(pri->ev.ring.redirectingname));
-- libpri_copy_string(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
-+
-+ if (c->redirecting.from.number.valid && !c->redirecting.count) {
-+ /*
-+ * This is most likely because the redirecting number came in
-+ * with the redirecting ie only and not a DivertingLegInformation2.
-+ */
-+ c->redirecting.count = 1;
-+ }
-+ if (c->redirecting.state == Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3) {
-+ /*
-+ * Valid for Q.SIG and ETSI PRI/BRI-PTP modes:
-+ * Setup the redirecting.to informtion so we can identify
-+ * if the user wants to manually supply the COLR for this
-+ * redirected to number if further redirects could happen.
-+ *
-+ * All the user needs to do is set the REDIRECTING(to-pres)
-+ * to the COLR and REDIRECTING(to-num) = complete-dialed-number
-+ * (i.e. CALLERID(dnid)) to be safe after determining that the
-+ * incoming call was redirected by checking if the
-+ * REDIRECTING(count) is nonzero.
-+ */
-+ c->redirecting.to.number = c->called.number;
-+ c->redirecting.to.number.presentation =
-+ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-+ }
-+
-+ ctrl->ev.e = PRI_EVENT_RING;
-+ ctrl->ev.ring.subcmds = &ctrl->subcmds;
-+ ctrl->ev.ring.channel = q931_encode_channel(c);
-+
-+ /* Calling party information */
-+ ctrl->ev.ring.callingpres = q931_party_id_presentation(&c->remote_id);
-+ ctrl->ev.ring.callingplan = c->remote_id.number.plan;
-+ if (c->remote_id.number.valid
-+ && (c->remote_id.number.presentation == PRES_ALLOWED_NETWORK_NUMBER
-+ || c->remote_id.number.presentation == PRES_PROHIB_NETWORK_NUMBER)) {
-+ ctrl->ev.ring.callingplanani = c->remote_id.number.plan;
-+ libpri_copy_string(ctrl->ev.ring.callingani, c->remote_id.number.str, sizeof(ctrl->ev.ring.callingani));
-+ } else {
-+ ctrl->ev.ring.callingplanani = -1;
-+ ctrl->ev.ring.callingani[0] = '\0';
-+ }
-+ libpri_copy_string(ctrl->ev.ring.callingnum, c->remote_id.number.str, sizeof(ctrl->ev.ring.callingnum));
-+ libpri_copy_string(ctrl->ev.ring.callingname, c->remote_id.name.str, sizeof(ctrl->ev.ring.callingname));
-+ q931_party_id_copy_to_pri(&ctrl->ev.ring.calling, &c->remote_id);
-+ /* for backwards compatibility, still need ctrl->ev.ring.callingsubaddr */
-+ if (!c->remote_id.subaddress.type) { /* NSAP: Type = 0 */
-+ libpri_copy_string(ctrl->ev.ring.callingsubaddr, (char *) c->remote_id.subaddress.data, sizeof(ctrl->ev.ring.callingsubaddr));
-+ } else {
-+ ctrl->ev.ring.callingsubaddr[0] = '\0';
-+ }
-+
-+ ctrl->ev.ring.ani2 = c->ani2;
-+
-+ /* Called party information */
-+ ctrl->ev.ring.calledplan = c->called.number.plan;
-+ libpri_copy_string(ctrl->ev.ring.callednum, c->called.number.str, sizeof(ctrl->ev.ring.callednum));
-+ q931_party_subaddress_copy_to_pri(&ctrl->ev.ring.called_subaddress, &c->called.subaddress);
-+
-+ /* Original called party information (For backward compatibility) */
-+ libpri_copy_string(ctrl->ev.ring.origcalledname, c->redirecting.orig_called.name.str, sizeof(ctrl->ev.ring.origcalledname));
-+ libpri_copy_string(ctrl->ev.ring.origcallednum, c->redirecting.orig_called.number.str, sizeof(ctrl->ev.ring.origcallednum));
-+ ctrl->ev.ring.callingplanorigcalled = c->redirecting.orig_called.number.plan;
-+ if (c->redirecting.orig_called.number.valid
-+ || c->redirecting.orig_called.name.valid) {
-+ ctrl->ev.ring.origredirectingreason = c->redirecting.orig_reason;
-+ } else {
-+ ctrl->ev.ring.origredirectingreason = -1;
-+ }
-+
-+ /* Redirecting from party information (For backward compatibility) */
-+ ctrl->ev.ring.callingplanrdnis = c->redirecting.from.number.plan;
-+ libpri_copy_string(ctrl->ev.ring.redirectingnum, c->redirecting.from.number.str, sizeof(ctrl->ev.ring.redirectingnum));
-+ libpri_copy_string(ctrl->ev.ring.redirectingname, c->redirecting.from.name.str, sizeof(ctrl->ev.ring.redirectingname));
-+
-+ ctrl->ev.ring.redirectingreason = c->redirecting.reason;
-+
-+ libpri_copy_string(ctrl->ev.ring.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.ring.useruserinfo));
- c->useruserinfo[0] = '\0';
-- pri->ev.ring.redirectingreason = c->redirectingreason;
-- pri->ev.ring.origredirectingreason = c->origredirectingreason;
-- pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
-- pri->ev.ring.cref = c->cr;
-- pri->ev.ring.call = c;
-- pri->ev.ring.layer1 = c->userl1;
-- pri->ev.ring.complete = c->complete;
-- pri->ev.ring.ctype = c->transcapability;
-- pri->ev.ring.redirectingreason = c->redirectingreason;
-- pri->ev.ring.progress = c->progress;
-- pri->ev.ring.progressmask = c->progressmask;
-+
-+ libpri_copy_string(ctrl->ev.ring.keypad_digits, c->keypad_digits,
-+ sizeof(ctrl->ev.ring.keypad_digits));
-+
-+ ctrl->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
-+ ctrl->ev.ring.cref = c->cr;
-+ ctrl->ev.ring.call = c->master_call;
-+ ctrl->ev.ring.layer1 = c->userl1;
-+ ctrl->ev.ring.complete = c->complete;
-+ ctrl->ev.ring.ctype = c->transcapability;
-+ ctrl->ev.ring.progress = c->progress;
-+ ctrl->ev.ring.progressmask = c->progressmask;
-+ ctrl->ev.ring.reversecharge = c->reversecharge;
-+
-+ if (c->redirecting.count) {
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (subcmd) {
-+ /* Setup redirecting subcommand */
-+ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
-+ &c->redirecting);
-+ }
-+ }
-+
- return Q931_RES_HAVEEVENT;
- case Q931_ALERTING:
-+ stop_t303(c);
- if (c->newcall) {
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- break;
- }
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_DELIVERED);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_DELIVERED);
- c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
-- pri->ev.e = PRI_EVENT_RINGING;
-- pri->ev.ringing.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.ringing.cref = c->cr;
-- pri->ev.ringing.call = c;
-- pri->ev.ringing.progress = c->progress;
-- pri->ev.ringing.progressmask = c->progressmask;
-- libpri_copy_string(pri->ev.ringing.useruserinfo, c->useruserinfo, sizeof(pri->ev.ringing.useruserinfo));
-+ ctrl->ev.e = PRI_EVENT_RINGING;
-+ ctrl->ev.ringing.subcmds = &ctrl->subcmds;
-+ ctrl->ev.ringing.channel = q931_encode_channel(c);
-+ ctrl->ev.ringing.cref = c->cr;
-+ ctrl->ev.ringing.call = c->master_call;
-+ ctrl->ev.ringing.progress = c->progress;
-+ ctrl->ev.ringing.progressmask = c->progressmask;
-+
-+ libpri_copy_string(ctrl->ev.ringing.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.ringing.useruserinfo));
- c->useruserinfo[0] = '\0';
-
-- cur = c->apdus;
-- while (cur) {
-+ for (cur = c->apdus; cur; cur = cur->next) {
- if (!cur->sent && cur->message == Q931_FACILITY) {
-- q931_facility(pri, c);
-+ q931_facility(ctrl, c);
- break;
- }
-- cur = cur->next;
- }
-
- return Q931_RES_HAVEEVENT;
- case Q931_CONNECT:
-+ stop_t303(c);
- if (c->newcall) {
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- break;
- }
- if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) {
-- q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
-+ q931_status(ctrl, c, PRI_CAUSE_WRONG_MESSAGE);
- break;
- }
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
- c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
-- pri->ev.e = PRI_EVENT_ANSWER;
-- pri->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.answer.cref = c->cr;
-- pri->ev.answer.call = c;
-- pri->ev.answer.progress = c->progress;
-- pri->ev.answer.progressmask = c->progressmask;
-- libpri_copy_string(pri->ev.answer.useruserinfo, c->useruserinfo, sizeof(pri->ev.answer.useruserinfo));
-+
-+ ctrl->ev.e = PRI_EVENT_ANSWER;
-+ ctrl->ev.answer.subcmds = &ctrl->subcmds;
-+ ctrl->ev.answer.channel = q931_encode_channel(c);
-+ ctrl->ev.answer.cref = c->cr;
-+ ctrl->ev.answer.call = c->master_call;
-+ ctrl->ev.answer.progress = c->progress;
-+ ctrl->ev.answer.progressmask = c->progressmask;
-+ libpri_copy_string(ctrl->ev.answer.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.answer.useruserinfo));
- c->useruserinfo[0] = '\0';
-- q931_connect_acknowledge(pri, c);
-- if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */
-- q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
-+
-+ q931_connect_acknowledge(ctrl, c);
-+
-+ if (c->cis_auto_disconnect && c->cis_call) {
-+ /* Make sure WE release when we initiate a signalling only connection */
-+ q931_hangup(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
- break;
-- } else
-+ } else {
-+ c->incoming_ct_state = INCOMING_CT_STATE_IDLE;
-+
-+ /* Setup connected line subcommand */
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (subcmd) {
-+ subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
-+ q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &c->remote_id);
-+ }
-+
- return Q931_RES_HAVEEVENT;
-+ }
- case Q931_FACILITY:
- if (c->newcall) {
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- break;
- }
-- pri->ev.e = PRI_EVENT_FACNAME;
-- libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname));
-- libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingnum));
-- pri->ev.facname.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.facname.callingpres = c->callerpres;
-- pri->ev.facname.callingplan = c->callerplan;
-- pri->ev.facname.cref = c->cr;
-- pri->ev.facname.call = c;
--#if 0
-- pri_message(pri, "Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum);
--#endif
-- return Q931_RES_HAVEEVENT;
-+ switch (c->incoming_ct_state) {
-+ case INCOMING_CT_STATE_POST_CONNECTED_LINE:
-+ c->incoming_ct_state = INCOMING_CT_STATE_IDLE;
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (subcmd) {
-+ subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
-+ q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &c->remote_id);
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ if (ctrl->subcmds.counter_subcmd) {
-+ q931_fill_facility_event(ctrl, c);
-+ return Q931_RES_HAVEEVENT;
-+ }
-+ break;
- case Q931_PROGRESS:
- if (missingmand) {
-- q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-- q931_destroycall(pri, c->cr);
-+ q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-+ pri_destroycall(ctrl, c);
- break;
- }
-- pri->ev.e = PRI_EVENT_PROGRESS;
-- pri->ev.proceeding.cause = c->cause;
-+ ctrl->ev.e = PRI_EVENT_PROGRESS;
-+ ctrl->ev.proceeding.cause = c->cause;
- /* Fall through */
- case Q931_CALL_PROCEEDING:
-+ stop_t303(c);
-+ ctrl->ev.proceeding.subcmds = &ctrl->subcmds;
- if (c->newcall) {
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- break;
- }
- if ((c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED) &&
- (c->ourcallstate != Q931_CALL_STATE_OVERLAP_SENDING) &&
- (c->ourcallstate != Q931_CALL_STATE_CALL_DELIVERED) &&
- (c->ourcallstate != Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING)) {
-- q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
-+ q931_status(ctrl,c,PRI_CAUSE_WRONG_MESSAGE);
- break;
- }
-- pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-+ ctrl->ev.proceeding.channel = q931_encode_channel(c);
- if (mh->msg == Q931_CALL_PROCEEDING) {
-- pri->ev.e = PRI_EVENT_PROCEEDING;
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING);
-+ ctrl->ev.e = PRI_EVENT_PROCEEDING;
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING);
- c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
- }
-- pri->ev.proceeding.progress = c->progress;
-- pri->ev.proceeding.progressmask = c->progressmask;
-- pri->ev.proceeding.cref = c->cr;
-- pri->ev.proceeding.call = c;
-+ ctrl->ev.proceeding.progress = c->progress;
-+ ctrl->ev.proceeding.progressmask = c->progressmask;
-+ ctrl->ev.proceeding.cref = c->cr;
-+ ctrl->ev.proceeding.call = c->master_call;
-
-- cur = c->apdus;
-- while (cur) {
-+ for (cur = c->apdus; cur; cur = cur->next) {
- if (!cur->sent && cur->message == Q931_FACILITY) {
-- q931_facility(pri, c);
-+ q931_facility(ctrl, c);
- break;
- }
-- cur = cur->next;
- }
- return Q931_RES_HAVEEVENT;
- case Q931_CONNECT_ACKNOWLEDGE:
- if (c->newcall) {
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- break;
- }
- if (!(c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) &&
- !(c->ourcallstate == Q931_CALL_STATE_ACTIVE &&
-- (pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG))) {
-- q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
-+ (ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG))) {
-+ q931_status(ctrl,c,PRI_CAUSE_WRONG_MESSAGE);
- break;
- }
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
- c->peercallstate = Q931_CALL_STATE_ACTIVE;
- break;
- case Q931_STATUS:
- if (missingmand) {
-- q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-- q931_destroycall(pri, c->cr);
-+ q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-+ pri_destroycall(ctrl, c);
- break;
- }
- if (c->newcall) {
- if (c->cr & 0x7fff)
-- q931_release_complete(pri,c,PRI_CAUSE_WRONG_CALL_STATE);
-+ q931_release_complete(ctrl,c,PRI_CAUSE_WRONG_CALL_STATE);
- break;
- }
- /* Do nothing */
- /* Also when the STATUS asks for the call of an unexisting reference send RELEASE_COMPL */
-- if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) &&
-+ if ((ctrl->debug & PRI_DEBUG_Q931_ANOMALY) &&
- (c->cause != PRI_CAUSE_INTERWORKING))
-- pri_error(pri, "Received unsolicited status: %s\n", pri_cause2str(c->cause));
-+ pri_error(ctrl, "Received unsolicited status: %s\n", pri_cause2str(c->cause));
- /* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */
- #if 0
- if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) {
-@@ -3737,25 +6774,28 @@
-
- if (!c->sugcallstate) {
- #endif
-- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.hangup.cause = c->cause;
-- pri->ev.hangup.cref = c->cr;
-- pri->ev.hangup.call = c;
-- pri->ev.hangup.aoc_units = c->aoc_units;
-- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
-+ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
-+ ctrl->ev.hangup.channel = q931_encode_channel(c);
-+ ctrl->ev.hangup.cause = c->cause;
-+ ctrl->ev.hangup.cref = c->cr;
-+ ctrl->ev.hangup.call = c->master_call;
-+ ctrl->ev.hangup.aoc_units = c->aoc_units;
-+ ctrl->ev.hangup.call_held = NULL;
-+ ctrl->ev.hangup.call_active = NULL;
-+ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
- /* Free resources */
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
- c->peercallstate = Q931_CALL_STATE_NULL;
- if (c->alive) {
-- pri->ev.e = PRI_EVENT_HANGUP;
-+ ctrl->ev.e = PRI_EVENT_HANGUP;
- res = Q931_RES_HAVEEVENT;
- c->alive = 0;
- } else if (c->sendhangupack) {
- res = Q931_RES_HAVEEVENT;
-- pri->ev.e = PRI_EVENT_HANGUP_ACK;
-- q931_hangup(pri, c, c->cause);
-+ ctrl->ev.e = PRI_EVENT_HANGUP_ACK;
-+ pri_hangup(ctrl, c, c->cause);
- } else {
-- q931_hangup(pri, c, c->cause);
-+ pri_hangup(ctrl, c, c->cause);
- res = 0;
- }
- if (res)
-@@ -3763,32 +6803,38 @@
- }
- break;
- case Q931_RELEASE_COMPLETE:
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
-+ c->hangupinitiated = 1;
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
- c->peercallstate = Q931_CALL_STATE_NULL;
-- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.hangup.cause = c->cause;
-- pri->ev.hangup.cref = c->cr;
-- pri->ev.hangup.call = c;
-- pri->ev.hangup.aoc_units = c->aoc_units;
-- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
-+ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
-+ ctrl->ev.hangup.channel = q931_encode_channel(c);
-+ ctrl->ev.hangup.cause = c->cause;
-+ ctrl->ev.hangup.cref = c->cr;
-+ ctrl->ev.hangup.call = c->master_call;
-+ ctrl->ev.hangup.aoc_units = c->aoc_units;
-+ ctrl->ev.hangup.call_held = NULL;
-+ ctrl->ev.hangup.call_active = NULL;
-+ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
- c->useruserinfo[0] = '\0';
- /* Free resources */
- if (c->alive) {
-- pri->ev.e = PRI_EVENT_HANGUP;
-+ ctrl->ev.e = PRI_EVENT_HANGUP;
- res = Q931_RES_HAVEEVENT;
- c->alive = 0;
- } else if (c->sendhangupack) {
- res = Q931_RES_HAVEEVENT;
-- pri->ev.e = PRI_EVENT_HANGUP_ACK;
-- pri_hangup(pri, c, c->cause);
-+ ctrl->ev.e = PRI_EVENT_HANGUP_ACK;
-+ pri_hangup(ctrl, c, c->cause);
- } else
- res = 0;
-+
- if (res)
- return res;
- else
-- q931_hangup(pri,c,c->cause);
-+ pri_hangup(ctrl,c,c->cause);
- break;
- case Q931_RELEASE:
-+ c->hangupinitiated = 1;
- if (missingmand) {
- /* Force cause to be mandatory IE missing */
- c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
-@@ -3798,59 +6844,113 @@
- else {
- c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST;
- }
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
-- pri->ev.e = PRI_EVENT_HANGUP;
-- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.hangup.cause = c->cause;
-- pri->ev.hangup.cref = c->cr;
-- pri->ev.hangup.call = c;
-- pri->ev.hangup.aoc_units = c->aoc_units;
-- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
-+ ctrl->ev.e = PRI_EVENT_HANGUP;
-+ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
-+ ctrl->ev.hangup.channel = q931_encode_channel(c);
-+ ctrl->ev.hangup.cause = c->cause;
-+ ctrl->ev.hangup.cref = c->cr;
-+ ctrl->ev.hangup.call = c->master_call;
-+ ctrl->ev.hangup.aoc_units = c->aoc_units;
-+ ctrl->ev.hangup.call_held = NULL;
-+ ctrl->ev.hangup.call_active = NULL;
-+ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
- c->useruserinfo[0] = '\0';
- /* Don't send release complete if they send us release
- while we sent it, assume a NULL state */
- if (c->newcall)
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-- else
-+ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ else if (c->outboundbroadcast && (c != q931_get_subcall_winner(c->master_call)))
-+ return pri_hangup(ctrl, c, -1);
-+ else
- return Q931_RES_HAVEEVENT;
- break;
- case Q931_DISCONNECT:
-+ c->hangupinitiated = 1;
- if (missingmand) {
- /* Still let user call release */
- c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
- }
- if (c->newcall) {
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- break;
- }
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_DISCONNECT_INDICATION);
-+
-+ /*
-+ * Determine if there are any calls that can be proposed for
-+ * a transfer of held call on disconnect.
-+ */
-+ ctrl->ev.hangup.call_held = NULL;
-+ ctrl->ev.hangup.call_active = NULL;
-+ switch (c->ourcallstate) {
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_ACTIVE:
-+ if (c->master_call->hold_state == Q931_HOLD_STATE_CALL_HELD) {
-+ /* Held call is being disconnected first. */
-+ ctrl->ev.hangup.call_held = c->master_call;
-+ ctrl->ev.hangup.call_active = q931_find_held_active_call(ctrl, c);
-+ } else {
-+ /* Active call is being disconnected first. */
-+ if (q931_find_winning_call(c) == c) {
-+ /*
-+ * Only a normal call or the winning call of a broadcast SETUP
-+ * can participate in a transfer of held call on disconnet.
-+ */
-+ ctrl->ev.hangup.call_active = c->master_call;
-+ ctrl->ev.hangup.call_held = q931_find_held_call(ctrl, c);
-+ }
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ if (ctrl->ev.hangup.call_held) {
-+ pri_message(ctrl, "-- Found held call: %p cref:%d\n",
-+ ctrl->ev.hangup.call_held, ctrl->ev.hangup.call_held->cr);
-+ }
-+ if (ctrl->ev.hangup.call_active) {
-+ pri_message(ctrl, "-- Found active call: %p cref:%d\n",
-+ ctrl->ev.hangup.call_active, ctrl->ev.hangup.call_active->cr);
-+ }
-+ if (ctrl->ev.hangup.call_held && ctrl->ev.hangup.call_active) {
-+ pri_message(ctrl, "-- Transfer held call on disconnect possible.\n");
-+ }
-+ }
-+
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_DISCONNECT_INDICATION);
- c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
- c->sendhangupack = 1;
-
- /* wait for a RELEASE so that sufficient time has passed
- for the inband audio to be heard */
-- if (pri->acceptinbanddisconnect && (c->progressmask & PRI_PROG_INBAND_AVAILABLE))
-+ if (ctrl->acceptinbanddisconnect && (c->progressmask & PRI_PROG_INBAND_AVAILABLE))
- break;
-
- /* Return such an event */
-- pri->ev.e = PRI_EVENT_HANGUP_REQ;
-- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.hangup.cause = c->cause;
-- pri->ev.hangup.cref = c->cr;
-- pri->ev.hangup.call = c;
-- pri->ev.hangup.aoc_units = c->aoc_units;
-- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
-+ ctrl->ev.e = PRI_EVENT_HANGUP_REQ;
-+ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
-+ ctrl->ev.hangup.channel = q931_encode_channel(c);
-+ ctrl->ev.hangup.cause = c->cause;
-+ ctrl->ev.hangup.cref = c->cr;
-+ ctrl->ev.hangup.call = c->master_call;
-+ ctrl->ev.hangup.aoc_units = c->aoc_units;
-+ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
- c->useruserinfo[0] = '\0';
- if (c->alive)
- return Q931_RES_HAVEEVENT;
- else
-- q931_hangup(pri,c,c->cause);
-+ pri_hangup(ctrl,c,c->cause);
- break;
- case Q931_RESTART_ACKNOWLEDGE:
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
- c->peercallstate = Q931_CALL_STATE_NULL;
-- pri->ev.e = PRI_EVENT_RESTART_ACK;
-- pri->ev.restartack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-+ ctrl->ev.e = PRI_EVENT_RESTART_ACK;
-+ ctrl->ev.restartack.channel = q931_encode_channel(c);
- return Q931_RES_HAVEEVENT;
- case Q931_INFORMATION:
- /* XXX We're handling only INFORMATION messages that contain
-@@ -3858,80 +6958,376 @@
- + the "Complete" msg which is basically an EOF on further digits
- XXX */
- if (c->newcall) {
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- break;
- }
- if (c->ourcallstate != Q931_CALL_STATE_OVERLAP_RECEIVING) {
-- pri->ev.e = PRI_EVENT_KEYPAD_DIGIT;
-- pri->ev.digit.call = c;
-- pri->ev.digit.channel = c->channelno | (c->ds1no << 8);
-- libpri_copy_string(pri->ev.digit.digits, c->keypad_digits, sizeof(pri->ev.digit.digits));
-- /* Make sure we clear it out before we return */
-- c->keypad_digits[0] = '\0';
-+ ctrl->ev.e = PRI_EVENT_KEYPAD_DIGIT;
-+ ctrl->ev.digit.subcmds = &ctrl->subcmds;
-+ ctrl->ev.digit.call = c->master_call;
-+ ctrl->ev.digit.channel = q931_encode_channel(c);
-+ libpri_copy_string(ctrl->ev.digit.digits, c->keypad_digits, sizeof(ctrl->ev.digit.digits));
- return Q931_RES_HAVEEVENT;
- }
-- pri->ev.e = PRI_EVENT_INFO_RECEIVED;
-- pri->ev.ring.call = c;
-- pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
-- libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
-- pri->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */
-+ ctrl->ev.e = PRI_EVENT_INFO_RECEIVED;
-+ ctrl->ev.ring.subcmds = &ctrl->subcmds;
-+ ctrl->ev.ring.call = c->master_call;
-+ ctrl->ev.ring.channel = q931_encode_channel(c);
-+ libpri_copy_string(ctrl->ev.ring.callednum, c->overlap_digits, sizeof(ctrl->ev.ring.callednum));
-+
-+ q931_party_id_copy_to_pri(&ctrl->ev.ring.calling, &c->remote_id);
-+ /* for backwards compatibility, still need ctrl->ev.ring.callingsubaddr */
-+ if (!c->remote_id.subaddress.type) { /* NSAP: Type = 0 */
-+ libpri_copy_string(ctrl->ev.ring.callingsubaddr, (char *) c->remote_id.subaddress.data, sizeof(ctrl->ev.ring.callingsubaddr));
-+ } else {
-+ ctrl->ev.ring.callingsubaddr[0] = '\0';
-+ }
-+
-+ ctrl->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */
- return Q931_RES_HAVEEVENT;
- case Q931_STATUS_ENQUIRY:
- if (c->newcall) {
-- q931_release_complete(pri, c, PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ q931_release_complete(ctrl, c, PRI_CAUSE_INVALID_CALL_REFERENCE);
- } else
-- q931_status(pri,c, 0);
-+ q931_status(ctrl,c, 0);
- break;
- case Q931_SETUP_ACKNOWLEDGE:
-+ stop_t303(c);
- if (c->newcall) {
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- break;
- }
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OVERLAP_SENDING);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OVERLAP_SENDING);
- c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
-- pri->ev.e = PRI_EVENT_SETUP_ACK;
-- pri->ev.setup_ack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.setup_ack.call = c;
-+ ctrl->ev.e = PRI_EVENT_SETUP_ACK;
-+ ctrl->ev.setup_ack.subcmds = &ctrl->subcmds;
-+ ctrl->ev.setup_ack.channel = q931_encode_channel(c);
-+ ctrl->ev.setup_ack.call = c->master_call;
-
-- cur = c->apdus;
-- while (cur) {
-+ for (cur = c->apdus; cur; cur = cur->next) {
- if (!cur->sent && cur->message == Q931_FACILITY) {
-- q931_facility(pri, c);
-+ q931_facility(ctrl, c);
- break;
- }
-- cur = cur->next;
- }
-
- return Q931_RES_HAVEEVENT;
- case Q931_NOTIFY:
-- pri->ev.e = PRI_EVENT_NOTIFY;
-- pri->ev.notify.channel = c->channelno;
-- pri->ev.notify.info = c->notify;
-- return Q931_RES_HAVEEVENT;
-- case Q931_USER_INFORMATION:
-- case Q931_SEGMENT:
-- case Q931_CONGESTION_CONTROL:
-+ res = 0;
-+ switch (c->notify) {
-+ case PRI_NOTIFY_CALL_DIVERTING:
-+ if (c->redirection_number.valid) {
-+ c->redirecting.to.number = c->redirection_number;
-+ if (c->redirecting.count < PRI_MAX_REDIRECTS) {
-+ ++c->redirecting.count;
-+ }
-+ switch (c->ourcallstate) {
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ /* Call is deflecting after we have seen an ALERTING message */
-+ c->redirecting.reason = PRI_REDIR_FORWARD_ON_NO_REPLY;
-+ break;
-+ default:
-+ /* Call is deflecting for call forwarding unconditional or busy reason. */
-+ c->redirecting.reason = PRI_REDIR_UNKNOWN;
-+ break;
-+ }
-+
-+ /* Setup redirecting subcommand */
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (subcmd) {
-+ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
-+ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
-+ &c->redirecting);
-+ }
-+ }
-+
-+ if (ctrl->subcmds.counter_subcmd) {
-+ q931_fill_facility_event(ctrl, c);
-+ res = Q931_RES_HAVEEVENT;
-+ }
-+ break;
-+ case PRI_NOTIFY_TRANSFER_ALERTING:
-+ case PRI_NOTIFY_TRANSFER_ACTIVE:
-+ if (c->redirection_number.valid
-+ && q931_party_number_cmp(&c->remote_id.number, &c->redirection_number)) {
-+ /* The remote party information changed. */
-+ c->remote_id.number = c->redirection_number;
-+
-+ /* Setup connected line subcommand */
-+ subcmd = q931_alloc_subcommand(ctrl);
-+ if (subcmd) {
-+ subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
-+ q931_party_id_copy_to_pri(&subcmd->u.connected_line.id,
-+ &c->remote_id);
-+ }
-+ }
-+
-+ if (ctrl->subcmds.counter_subcmd) {
-+ q931_fill_facility_event(ctrl, c);
-+ res = Q931_RES_HAVEEVENT;
-+ }
-+ break;
-+ default:
-+ ctrl->ev.e = PRI_EVENT_NOTIFY;
-+ ctrl->ev.notify.subcmds = &ctrl->subcmds;
-+ ctrl->ev.notify.channel = q931_encode_channel(c);
-+ ctrl->ev.notify.info = c->notify;
-+ ctrl->ev.notify.call = c->master_call;
-+ res = Q931_RES_HAVEEVENT;
-+ break;
-+ }
-+ return res;
- case Q931_HOLD:
-+ res = 0;
-+ if (!PRI_MASTER(ctrl)->hold_support) {
-+ /*
-+ * Blocking any calls from getting on HOLD effectively
-+ * disables HOLD/RETRIEVE.
-+ */
-+ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_FACILITY_NOT_IMPLEMENTED);
-+ break;
-+ }
-+ switch (c->ourcallstate) {
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* HOLD request only allowed in these states if point-to-point mode. */
-+ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
-+ break;
-+ }
-+ /* Fall through */
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_ACTIVE:
-+ if (!q931_find_winning_call(c)) {
-+ /*
-+ * Only the winning call of a broadcast SETUP can do hold since the
-+ * call must be answered first.
-+ */
-+ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
-+ break;
-+ }
-+ master_call = c->master_call;
-+ switch (master_call->hold_state) {
-+ case Q931_HOLD_STATE_HOLD_REQ:
-+ if (ctrl->localtype == PRI_NETWORK) {
-+ /* The network ignores HOLD request on a hold collision. */
-+ break;
-+ }
-+ /* Fall through */
-+ case Q931_HOLD_STATE_IDLE:
-+ ctrl->ev.e = PRI_EVENT_HOLD;
-+ ctrl->ev.hold.channel = q931_encode_channel(c);
-+ ctrl->ev.hold.call = master_call;
-+ ctrl->ev.hold.subcmds = &ctrl->subcmds;
-+ res = Q931_RES_HAVEEVENT;
-+
-+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_HOLD_IND);
-+
-+ /* Stop any T-HOLD timer from possible hold collision. */
-+ pri_schedule_del(ctrl, master_call->hold_timer);
-+ master_call->hold_timer = 0;
-+ break;
-+ default:
-+ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
-+ break;
-+ }
-+ break;
-+ case Q931_CALL_STATE_DISCONNECT_INDICATION:
-+ case Q931_CALL_STATE_RELEASE_REQUEST:
-+ /* Ignore HOLD request in these states. */
-+ break;
-+ default:
-+ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
-+ break;
-+ }
-+ return res;
- case Q931_HOLD_ACKNOWLEDGE:
-+ res = 0;
-+ master_call = c->master_call;
-+ switch (master_call->hold_state) {
-+ case Q931_HOLD_STATE_HOLD_REQ:
-+ ctrl->ev.e = PRI_EVENT_HOLD_ACK;
-+ ctrl->ev.hold_ack.channel = q931_encode_channel(c);
-+ ctrl->ev.hold_ack.call = master_call;
-+ ctrl->ev.hold_ack.subcmds = &ctrl->subcmds;
-+ res = Q931_RES_HAVEEVENT;
-+
-+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_CALL_HELD);
-+
-+ /* Call is now on hold so forget the channel. */
-+ c->channelno = 0;/* No channel */
-+ c->ds1no = 0;
-+ c->ds1explicit = 0;
-+ c->chanflags = 0;
-+
-+ /* Stop T-HOLD timer */
-+ pri_schedule_del(ctrl, master_call->hold_timer);
-+ master_call->hold_timer = 0;
-+ break;
-+ default:
-+ /* Ignore response. Response is late or spurrious. */
-+ break;
-+ }
-+ return res;
- case Q931_HOLD_REJECT:
-+ res = 0;
-+ master_call = c->master_call;
-+ switch (master_call->hold_state) {
-+ case Q931_HOLD_STATE_HOLD_REQ:
-+ if (missingmand) {
-+ /* Still, let hold rejection continue. */
-+ c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
-+ }
-+ ctrl->ev.e = PRI_EVENT_HOLD_REJ;
-+ ctrl->ev.hold_rej.channel = q931_encode_channel(c);
-+ ctrl->ev.hold_rej.call = master_call;
-+ ctrl->ev.hold_rej.cause = c->cause;
-+ ctrl->ev.hold_rej.subcmds = &ctrl->subcmds;
-+ res = Q931_RES_HAVEEVENT;
-+
-+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_IDLE);
-+
-+ /* Stop T-HOLD timer */
-+ pri_schedule_del(ctrl, master_call->hold_timer);
-+ master_call->hold_timer = 0;
-+ break;
-+ default:
-+ /* Ignore response. Response is late or spurrious. */
-+ break;
-+ }
-+ return res;
- case Q931_RETRIEVE:
-+ res = 0;
-+ switch (c->ourcallstate) {
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ case Q931_CALL_STATE_CONNECT_REQUEST:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ if (q931_is_ptmp(ctrl)) {
-+ /* RETRIEVE request only allowed in these states if point-to-point mode. */
-+ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
-+ break;
-+ }
-+ /* Fall through */
-+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
-+ case Q931_CALL_STATE_CALL_DELIVERED:
-+ case Q931_CALL_STATE_ACTIVE:
-+ if (!q931_find_winning_call(c)) {
-+ /*
-+ * Only the winning call of a broadcast SETUP can do hold since the
-+ * call must be answered first.
-+ */
-+ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
-+ break;
-+ }
-+ master_call = c->master_call;
-+ switch (master_call->hold_state) {
-+ case Q931_HOLD_STATE_RETRIEVE_REQ:
-+ if (ctrl->localtype == PRI_NETWORK) {
-+ /* The network ignores RETRIEVE request on a retrieve collision. */
-+ break;
-+ }
-+ /* Fall through */
-+ case Q931_HOLD_STATE_CALL_HELD:
-+ ctrl->ev.e = PRI_EVENT_RETRIEVE;
-+ ctrl->ev.retrieve.channel = q931_encode_channel(c);
-+ ctrl->ev.retrieve.call = master_call;
-+ ctrl->ev.retrieve.flexible = !(c->chanflags & FLAG_EXCLUSIVE);
-+ ctrl->ev.retrieve.subcmds = &ctrl->subcmds;
-+ res = Q931_RES_HAVEEVENT;
-+
-+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_RETRIEVE_IND);
-+
-+ /* Stop any T-RETRIEVE timer from possible retrieve collision. */
-+ pri_schedule_del(ctrl, master_call->hold_timer);
-+ master_call->hold_timer = 0;
-+ break;
-+ default:
-+ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
-+ break;
-+ }
-+ break;
-+ case Q931_CALL_STATE_DISCONNECT_INDICATION:
-+ case Q931_CALL_STATE_RELEASE_REQUEST:
-+ /* Ignore RETRIEVE request in these states. */
-+ break;
-+ default:
-+ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
-+ break;
-+ }
-+ return res;
- case Q931_RETRIEVE_ACKNOWLEDGE:
-+ res = 0;
-+ master_call = c->master_call;
-+ switch (master_call->hold_state) {
-+ case Q931_HOLD_STATE_RETRIEVE_REQ:
-+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_IDLE);
-+
-+ /* Stop T-RETRIEVE timer */
-+ pri_schedule_del(ctrl, master_call->hold_timer);
-+ master_call->hold_timer = 0;
-+
-+ ctrl->ev.e = PRI_EVENT_RETRIEVE_ACK;
-+ ctrl->ev.retrieve_ack.channel = q931_encode_channel(c);
-+ ctrl->ev.retrieve_ack.call = master_call;
-+ ctrl->ev.retrieve_ack.subcmds = &ctrl->subcmds;
-+ res = Q931_RES_HAVEEVENT;
-+ break;
-+ default:
-+ /* Ignore response. Response is late or spurrious. */
-+ break;
-+ }
-+ return res;
- case Q931_RETRIEVE_REJECT:
-+ res = 0;
-+ master_call = c->master_call;
-+ switch (master_call->hold_state) {
-+ case Q931_HOLD_STATE_RETRIEVE_REQ:
-+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_CALL_HELD);
-+
-+ /* Call is still on hold so forget the channel. */
-+ c->channelno = 0;/* No channel */
-+ c->ds1no = 0;
-+ c->ds1explicit = 0;
-+ c->chanflags = 0;
-+
-+ /* Stop T-RETRIEVE timer */
-+ pri_schedule_del(ctrl, master_call->hold_timer);
-+ master_call->hold_timer = 0;
-+
-+ if (missingmand) {
-+ /* Still, let retrive rejection continue. */
-+ c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
-+ }
-+ ctrl->ev.e = PRI_EVENT_RETRIEVE_REJ;
-+ ctrl->ev.retrieve_rej.channel = q931_encode_channel(c);
-+ ctrl->ev.retrieve_rej.call = master_call;
-+ ctrl->ev.retrieve_rej.cause = c->cause;
-+ ctrl->ev.retrieve_rej.subcmds = &ctrl->subcmds;
-+ res = Q931_RES_HAVEEVENT;
-+ break;
-+ default:
-+ /* Ignore response. Response is late or spurrious. */
-+ break;
-+ }
-+ return res;
-+ case Q931_USER_INFORMATION:
-+ case Q931_SEGMENT:
-+ case Q931_CONGESTION_CONTROL:
- case Q931_RESUME:
- case Q931_RESUME_ACKNOWLEDGE:
- case Q931_RESUME_REJECT:
- case Q931_SUSPEND:
- case Q931_SUSPEND_ACKNOWLEDGE:
- case Q931_SUSPEND_REJECT:
-- pri_error(pri, "!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-+ pri_error(ctrl, "!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
- /* Fall through */
- default:
--
-- pri_error(pri, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-- q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
-+ pri_error(ctrl, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-+ q931_status(ctrl,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
- if (c->newcall)
-- q931_destroycall(pri,c->cr);
-+ pri_destroycall(ctrl, c);
- return -1;
- }
- return 0;
-@@ -3941,40 +7337,46 @@
- static int pri_internal_clear(void *data)
- {
- struct q931_call *c = data;
-- struct pri *pri = c->pri;
-+ struct pri *ctrl = c->pri;
- int res;
-
-- if (c->retranstimer)
-- pri_schedule_del(pri, c->retranstimer);
-+ pri_schedule_del(ctrl, c->retranstimer);
- c->retranstimer = 0;
- c->useruserinfo[0] = '\0';
-- c->cause = -1;
-+ //c->cause = -1;
- c->causecode = -1;
- c->causeloc = -1;
-- c->sugcallstate = -1;
-+ c->sugcallstate = Q931_CALL_STATE_NOT_SET;
- c->aoc_units = -1;
-
-- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
-+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
- c->peercallstate = Q931_CALL_STATE_NULL;
-- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.hangup.cause = c->cause;
-- pri->ev.hangup.cref = c->cr;
-- pri->ev.hangup.call = c;
-- pri->ev.hangup.aoc_units = c->aoc_units;
-- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
-+ q931_clr_subcommands(ctrl);
-+ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
-+ ctrl->ev.hangup.channel = q931_encode_channel(c);
-+ ctrl->ev.hangup.cause = c->cause;
-+ ctrl->ev.hangup.cref = c->cr;
-+ ctrl->ev.hangup.call = c->master_call;
-+ ctrl->ev.hangup.aoc_units = c->aoc_units;
-+ ctrl->ev.hangup.call_held = NULL;
-+ ctrl->ev.hangup.call_active = NULL;
-+ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
-
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-+ pri_message(ctrl, "clearing, alive %d, hangupack %d\n", c->alive, c->sendhangupack);
-+ }
- /* Free resources */
- if (c->alive) {
-- pri->ev.e = PRI_EVENT_HANGUP;
-+ ctrl->ev.e = PRI_EVENT_HANGUP;
- res = Q931_RES_HAVEEVENT;
- c->alive = 0;
- } else if (c->sendhangupack) {
- res = Q931_RES_HAVEEVENT;
-- pri->ev.e = PRI_EVENT_HANGUP_ACK;
-- q931_hangup(pri, c, c->cause);
-+ ctrl->ev.e = PRI_EVENT_HANGUP_ACK;
-+ pri_hangup(ctrl, c, c->cause);
- } else {
- res = 0;
-- q931_hangup(pri, c, c->cause);
-+ pri_hangup(ctrl, c, c->cause);
- }
-
- return res;
-@@ -3984,94 +7386,97 @@
- static void pri_dl_down_timeout(void *data)
- {
- struct q931_call *c = data;
-- struct pri *pri = c->pri;
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, DBGHEAD "Timed out waiting for data link re-establishment\n", DBGINFO);
-+ struct pri *ctrl = c->pri;
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl, DBGHEAD "Timed out waiting for data link re-establishment\n", DBGINFO);
-
- c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
- if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
-- pri->schedev = 1;
-+ ctrl->schedev = 1;
- }
-
- /* Handle Layer 2 down event for a non active call. */
- static void pri_dl_down_cancelcall(void *data)
- {
- struct q931_call *c = data;
-- struct pri *pri = c->pri;
-- if (pri->debug & PRI_DEBUG_Q931_STATE)
-- pri_message(pri, DBGHEAD "Cancel non active call after data link failure\n", DBGINFO);
-+ struct pri *ctrl = c->pri;
-+ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(ctrl, DBGHEAD "Cancel non active call after data link failure\n", DBGINFO);
-
- c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
- if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
-- pri->schedev = 1;
-+ ctrl->schedev = 1;
- }
-
- /* Receive an indication from Layer 2 */
--void q931_dl_indication(struct pri *pri, int event)
-+void q931_dl_indication(struct pri *ctrl, int event)
- {
- q931_call *cur = NULL;
-
- /* Just return if T309 is not enabled. */
-- if (!pri || pri->timers[PRI_TIMER_T309] < 0)
-+ if (!ctrl || ctrl->timers[PRI_TIMER_T309] < 0)
- return;
-
- switch (event) {
- case PRI_EVENT_DCHAN_DOWN:
-- pri_message(pri, DBGHEAD "link is DOWN\n", DBGINFO);
-- cur = *pri->callpool;
-+ pri_message(ctrl, DBGHEAD "link is DOWN\n", DBGINFO);
-+ cur = *ctrl->callpool;
- while(cur) {
- if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE) {
- /* For a call in Active state, activate T309 only if there is no timer already running. */
- if (!cur->retranstimer) {
-- pri_message(pri, DBGHEAD "activate T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
-- cur->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T309], pri_dl_down_timeout, cur);
-+ pri_message(ctrl, DBGHEAD "activate T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
-+ cur->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T309], pri_dl_down_timeout, cur);
- }
- } else if (cur->ourcallstate != Q931_CALL_STATE_NULL) {
- /* For a call that is not in Active state, schedule internal clearing of the call 'ASAP' (delay 0). */
-- pri_message(pri, DBGHEAD "cancel call %d on channel %d in state %d (%s)\n", DBGINFO,
-- cur->cr, cur->channelno, cur->ourcallstate, callstate2str(cur->ourcallstate));
-- if (cur->retranstimer)
-- pri_schedule_del(pri, cur->retranstimer);
-- cur->retranstimer = pri_schedule_event(pri, 0, pri_dl_down_cancelcall, cur);
-+ pri_message(ctrl, DBGHEAD "cancel call %d on channel %d in state %d (%s)\n", DBGINFO,
-+ cur->cr, cur->channelno, cur->ourcallstate,
-+ q931_call_state_str(cur->ourcallstate));
-+ pri_schedule_del(ctrl, cur->retranstimer);
-+ cur->retranstimer = pri_schedule_event(ctrl, 0, pri_dl_down_cancelcall, cur);
- }
- cur = cur->next;
- }
- break;
- case PRI_EVENT_DCHAN_UP:
-- pri_message(pri, DBGHEAD "link is UP\n", DBGINFO);
-- cur = *pri->callpool;
-+ pri_message(ctrl, DBGHEAD "link is UP\n", DBGINFO);
-+ cur = *ctrl->callpool;
- while(cur) {
- if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE && cur->retranstimer) {
-- pri_message(pri, DBGHEAD "cancel T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
-- pri_schedule_del(pri, cur->retranstimer);
-+ pri_message(ctrl, DBGHEAD "cancel T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
-+ pri_schedule_del(ctrl, cur->retranstimer);
- cur->retranstimer = 0;
-- q931_status(pri, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
-+ q931_status(ctrl, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
- } else if (cur->ourcallstate != Q931_CALL_STATE_NULL &&
- cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_REQUEST &&
- cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_INDICATION &&
- cur->ourcallstate != Q931_CALL_STATE_RELEASE_REQUEST) {
-
- /* The STATUS message sent here is not required by Q.931, but it may help anyway. */
-- q931_status(pri, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
-+ q931_status(ctrl, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
- }
- cur = cur->next;
- }
- break;
- default:
-- pri_message(pri, DBGHEAD "unexpected event %d.\n", DBGINFO, event);
-+ pri_message(ctrl, DBGHEAD "unexpected event %d.\n", DBGINFO, event);
- }
- }
-
--int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode)
-+int q931_call_getcrv(struct pri *ctrl, q931_call *call, int *callmode)
- {
- if (callmode)
- *callmode = call->cr & 0x7;
- return ((call->cr & 0x7fff) >> 3);
- }
-
--int q931_call_setcrv(struct pri *pri, q931_call *call, int crv, int callmode)
-+int q931_call_setcrv(struct pri *ctrl, q931_call *call, int crv, int callmode)
- {
-- call->cr = (crv << 3) & 0x7fff;
-- call->cr |= (callmode & 0x7);
-+ /* Do not allow changing the dummy call reference */
-+ if (!q931_is_dummy_call(call)) {
-+ call->cr = (crv << 3) & 0x7fff;
-+ call->cr |= (callmode & 0x7);
-+ }
- return 0;
- }
-Index: asn1.h
-===================================================================
---- a/asn1.h (.../tags/1.4.10.2) (revision 0)
-+++ b/asn1.h (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,257 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief ASN.1 definitions and prototypes
-+ *
-+ * \details
-+ * This file contains all ASN.1 primitive data structures and
-+ * definitions needed for ROSE component encoding and decoding.
-+ *
-+ * ROSE - Remote Operations Service Element
-+ * ASN.1 - Abstract Syntax Notation 1
-+ * APDU - Application Protocol Data Unit
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+#ifndef _LIBPRI_ASN1_H
-+#define _LIBPRI_ASN1_H
-+
-+#include <string.h>
-+#include <sys/types.h>
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*! ASN.1 Identifier Octet - Tag class bits */
-+#define ASN1_CLASS_MASK 0xc0
-+#define ASN1_CLASS_UNIVERSAL 0x00 /*!< Universal primitive data types */
-+#define ASN1_CLASS_APPLICATION 0x40 /*!< Application wide data tag */
-+#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 /*!< Context specifc data tag */
-+#define ASN1_CLASS_PRIVATE 0xc0 /*!< Private organization data tag */
-+
-+/*! ASN.1 Identifier Octet - Primitive/Constructor bit */
-+#define ASN1_PC_MASK 0x20
-+#define ASN1_PC_PRIMITIVE 0x00
-+#define ASN1_PC_CONSTRUCTED 0x20
-+
-+/*! ASN.1 Identifier Octet - Universal data types */
-+#define ASN1_TYPE_MASK 0x1f
-+#define ASN1_TYPE_INDEF_TERM 0x00 /* 0 */
-+#define ASN1_TYPE_BOOLEAN 0x01 /* 1 */
-+#define ASN1_TYPE_INTEGER 0x02 /* 2 */
-+#define ASN1_TYPE_BIT_STRING 0x03 /* 3 */
-+#define ASN1_TYPE_OCTET_STRING 0x04 /* 4 */
-+#define ASN1_TYPE_NULL 0x05 /* 5 */
-+#define ASN1_TYPE_OBJECT_IDENTIFIER 0x06 /* 6 */
-+#define ASN1_TYPE_OBJECT_DESCRIPTOR 0x07 /* 7 */
-+#define ASN1_TYPE_EXTERN 0x08 /* 8 */
-+#define ASN1_TYPE_REAL 0x09 /* 9 */
-+#define ASN1_TYPE_ENUMERATED 0x0a /* 10 */
-+#define ASN1_TYPE_EMBEDDED_PDV 0x0b /* 11 */
-+#define ASN1_TYPE_UTF8_STRING 0x0c /* 12 */
-+#define ASN1_TYPE_RELATIVE_OID 0x0d /* 13 */
-+/* 0x0e & 0x0f are reserved for future ASN.1 editions */
-+#define ASN1_TYPE_SEQUENCE 0x10 /* 16 */
-+#define ASN1_TYPE_SET 0x11 /* 17 */
-+#define ASN1_TYPE_NUMERIC_STRING 0x12 /* 18 */
-+#define ASN1_TYPE_PRINTABLE_STRING 0x13 /* 19 */
-+#define ASN1_TYPE_TELETEX_STRING 0x14 /* 20 */
-+#define ASN1_TYPE_VIDEOTEX_STRING 0x15 /* 21 */
-+#define ASN1_TYPE_IA5_STRING 0x16 /* 22 */
-+#define ASN1_TYPE_UTC_TIME 0x17 /* 23 */
-+#define ASN1_TYPE_GENERALIZED_TIME 0x18 /* 24 */
-+#define ASN1_TYPE_GRAPHIC_STRING 0x19 /* 25 */
-+#define ASN1_TYPE_VISIBLE_STRING 0x1a /* 26 */
-+#define ASN1_TYPE_ISO646_STRING 0x1a /* 26 */
-+#define ASN1_TYPE_GENERAL_STRING 0x1b /* 27 */
-+#define ASN1_TYPE_UNIVERSAL_STRING 0x1c /* 28 */
-+#define ASN1_TYPE_CHAR_STRING 0x1d /* 29 */
-+#define ASN1_TYPE_BMP_STRING 0x1e /* 30 */
-+#define ASN1_TYPE_EXTENSION 0x1f /* 31 */
-+
-+#define ASN1_TAG_SEQUENCE (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_SEQUENCE)
-+#define ASN1_TAG_SET (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_SET)
-+
-+#define ASN1_INDEF_TERM (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_INDEF_TERM)
-+#define ASN1_INDEF_TERM_LEN 2
-+
-+struct asn1_oid {
-+ /*! \brief Number of subidentifier values in OID list */
-+ u_int16_t num_values;
-+
-+ /*!
-+ * \brief OID subidentifier value list
-+ * \note The first value is really the first two OID subidentifiers.
-+ * They are compressed using this formula:
-+ * First_Value = (First_Subidentifier * 40) + Second_Subidentifier
-+ */
-+ u_int16_t value[10];
-+};
-+
-+#define ASN1_CALL(new_pos, do_it) \
-+ do \
-+ { \
-+ (new_pos) = (do_it); \
-+ if (!(new_pos)) { \
-+ return NULL; \
-+ } \
-+ } while (0)
-+
-+/*! \brief Determine the ending position of the set or sequence to verify the length. */
-+#define ASN1_END_SETUP(component_end, offset, length, pos, end) \
-+ do { \
-+ if ((length) < 0) { \
-+ (offset) = ASN1_INDEF_TERM_LEN; \
-+ (component_end) = (end); \
-+ } else { \
-+ (offset) = 0; \
-+ (component_end) = (pos) + (length); \
-+ } \
-+ } while (0)
-+
-+/*! \brief Account for the indefinite length terminator of the set or sequence. */
-+#define ASN1_END_FIXUP(ctrl, pos, offset, component_end, end) \
-+ do { \
-+ if (offset) { \
-+ ASN1_CALL((pos), asn1_dec_indef_end_fixup((ctrl), (pos), (end))); \
-+ } else if ((pos) != (component_end)) { \
-+ if ((ctrl)->debug & PRI_DEBUG_APDU) { \
-+ pri_message((ctrl), \
-+ " Skipping unused constructed component octets!\n"); \
-+ } \
-+ (pos) = (component_end); \
-+ } \
-+ } while (0)
-+
-+#define ASN1_DID_NOT_EXPECT_TAG(ctrl, tag) \
-+ do { \
-+ if ((ctrl)->debug & PRI_DEBUG_APDU) { \
-+ pri_message((ctrl), " Did not expect: %s\n", asn1_tag2str(tag)); \
-+ } \
-+ } while (0)
-+
-+#define ASN1_CHECK_TAG(ctrl, actual_tag, match_tag, expected_tag) \
-+ do { \
-+ if ((match_tag) != (expected_tag)) { \
-+ ASN1_DID_NOT_EXPECT_TAG((ctrl), (actual_tag)); \
-+ return NULL; \
-+ } \
-+ } while (0)
-+
-+
-+const unsigned char *asn1_dec_tag(const unsigned char *tag_pos, const unsigned char *end,
-+ unsigned *tag);
-+const unsigned char *asn1_dec_length(const unsigned char *len_pos,
-+ const unsigned char *end, int *length);
-+const unsigned char *asn1_dec_indef_end_fixup(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end);
-+
-+const unsigned char *asn1_dec_boolean(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, int32_t *value);
-+const unsigned char *asn1_dec_int(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, int32_t *value);
-+const unsigned char *asn1_dec_null(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end);
-+const unsigned char *asn1_dec_oid(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct asn1_oid *oid);
-+const unsigned char *asn1_dec_string_bin(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
-+ unsigned char *str, size_t *str_len);
-+const unsigned char *asn1_dec_string_max(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
-+ unsigned char *str, size_t *str_len);
-+
-+const char *asn1_tag2str(unsigned tag);
-+void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1,
-+ const unsigned char *end);
-+
-+
-+#define ASN1_LEN_FORM_SHORT 1 /*!< Hint that the final length will be less than 128 octets */
-+#define ASN1_LEN_FORM_LONG_U8 2 /*!< Hint that the final length will be less than 256 octets */
-+#define ASN1_LEN_FORM_LONG_U16 3 /*!< Hint that the final length will be less than 65536 octets */
-+#define ASN1_LEN_INIT(len_pos, end, form_hint) \
-+ do { \
-+ if ((end) < (len_pos) + (form_hint)) { \
-+ return NULL; \
-+ } \
-+ *(len_pos) = (form_hint); \
-+ (len_pos) += (form_hint); \
-+ } while (0)
-+
-+#define ASN1_LEN_FIXUP(len_pos, component_end, end) \
-+ ASN1_CALL((component_end), asn1_enc_length_fixup((len_pos), (component_end), (end)))
-+
-+/*! \brief Use to begin encoding explicit tags, SET, and SEQUENCE constructed groupings. */
-+#define ASN1_CONSTRUCTED_BEGIN(len_pos_save, pos, end, tag) \
-+ do { \
-+ if ((end) < (pos) + (1 + ASN1_LEN_FORM_SHORT)) { \
-+ return NULL; \
-+ } \
-+ *(pos)++ = (tag) | ASN1_PC_CONSTRUCTED; \
-+ (len_pos_save) = (pos); \
-+ *(pos) = ASN1_LEN_FORM_SHORT; \
-+ (pos) += ASN1_LEN_FORM_SHORT; \
-+ } while (0)
-+
-+/*! \brief Use to end encoding explicit tags, SET, and SEQUENCE constructed groupings. */
-+#define ASN1_CONSTRUCTED_END(len_pos, component_end, end) \
-+ ASN1_CALL((component_end), asn1_enc_length_fixup((len_pos), (component_end), (end)))
-+
-+#define ASN1_ENC_ERROR(ctrl, msg) \
-+ pri_error((ctrl), "%s error: %s\n", __FUNCTION__, (msg))
-+
-+unsigned char *asn1_enc_length(unsigned char *len_pos, unsigned char *end,
-+ size_t str_len);
-+unsigned char *asn1_enc_length_fixup(unsigned char *len_pos,
-+ unsigned char *component_end, unsigned char *end);
-+
-+unsigned char *asn1_enc_boolean(unsigned char *pos, unsigned char *end, unsigned tag,
-+ int32_t value);
-+unsigned char *asn1_enc_int(unsigned char *pos, unsigned char *end, unsigned tag,
-+ int32_t value);
-+unsigned char *asn1_enc_null(unsigned char *pos, unsigned char *end, unsigned tag);
-+unsigned char *asn1_enc_oid(unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct asn1_oid *oid);
-+unsigned char *asn1_enc_string_bin(unsigned char *pos, unsigned char *end, unsigned tag,
-+ const unsigned char *str, size_t str_len);
-+unsigned char *asn1_enc_string_max(unsigned char *pos, unsigned char *end, unsigned tag,
-+ const unsigned char *str, size_t max_len);
-+
-+/* ------------------------------------------------------------------- */
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif /* _LIBPRI_ASN1_H */
-+/* ------------------------------------------------------------------- */
-+/* end asn1.h */
-
-Property changes on: asn1.h
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose.c
-===================================================================
---- a/rose.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,2464 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Remote Operations Service Element (ROSE) main controlling functions
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include <stdio.h>
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+#include "pri_facility.h"
-+
-+
-+#define ROSE_TAG_COMPONENT_INVOKE (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1)
-+#define ROSE_TAG_COMPONENT_RESULT (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2)
-+#define ROSE_TAG_COMPONENT_ERROR (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3)
-+#define ROSE_TAG_COMPONENT_REJECT (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4)
-+
-+/*! \brief Structure to convert a code value to a string */
-+struct rose_code_strings {
-+ /*! \brief Code value to convert to a string */
-+ int code;
-+ /*! \brief String equivalent of the associated code value */
-+ const char *name;
-+};
-+
-+/*! \brief ROSE invoke/result message conversion table entry. */
-+struct rose_convert_msg {
-+ /*! \brief library encoded operation-value */
-+ enum rose_operation operation;
-+ /*!
-+ * \brief OID prefix values to use when encoding/decoding the operation-value OID
-+ * \note NULL if operation-value is a localValue.
-+ */
-+ const struct asn1_oid *oid_prefix;
-+ /*! \brief Last OID value or localValue for the encoded operation-value */
-+ u_int16_t value;
-+
-+ /*!
-+ * \brief Encode the ROSE invoke operation-value arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ *
-+ * \note The function pointer is NULL if there are no arguments to encode.
-+ */
-+ unsigned char *(*encode_invoke_args)(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args);
-+ /*!
-+ * \brief Encode the ROSE result operation-value arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ *
-+ * \note The function pointer is NULL if there are no arguments to encode.
-+ */
-+ unsigned char *(*encode_result_args)(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args);
-+
-+ /*!
-+ * \brief Decode the ROSE invoke operation-value arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ *
-+ * \note The function pointer is NULL if there are no arguments to decode.
-+ */
-+ const unsigned char *(*decode_invoke_args)(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args);
-+ /*!
-+ * \brief Decode the ROSE result operation-value arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ *
-+ * \note The function pointer is NULL if there are no arguments to decode.
-+ */
-+ const unsigned char *(*decode_result_args)(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args);
-+};
-+
-+/*! \brief ROSE error code conversion table entry. */
-+struct rose_convert_error {
-+ /*! \brief library encoded error-value */
-+ enum rose_error_code code;
-+ /*!
-+ * \brief OID prefix values to use when encoding/decoding the error-value OID
-+ * \note NULL if error-value is a localValue.
-+ */
-+ const struct asn1_oid *oid_prefix;
-+ /*! \brief Last OID value or localValue for the encoded error-value */
-+ u_int16_t value;
-+
-+ /*!
-+ * \brief Encode the ROSE error parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ *
-+ * \note The function pointer is NULL if there are no arguments to encode.
-+ */
-+ unsigned char *(*encode_error_args)(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_error_args *args);
-+
-+ /*!
-+ * \brief Decode the ROSE error parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ *
-+ * \note The function pointer is NULL if there are no arguments to decode.
-+ */
-+ const unsigned char *(*decode_error_args)(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_error_args *args);
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * Note the first value in oid.values[] is really the first two
-+ * OID subidentifiers. They are compressed using this formula:
-+ * First_Value = (First_Subidentifier * 40) + Second_Subidentifier
-+ */
-+
-+/*! \brief ETSI Explicit Call Transfer OID prefix. */
-+static const struct asn1_oid rose_etsi_ect = {
-+/* *INDENT-OFF* */
-+ /* {ccitt(0) identified-organization(4) etsi(0) 369 operations-and-errors(1)} */
-+ 4, { 4, 0, 369, 1 }
-+/* *INDENT-ON* */
-+};
-+
-+/*! \brief ETSI specific invoke/result encode/decode message table */
-+static const struct rose_convert_msg rose_etsi_msgs[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * operation, oid_prefix, value,
-+ * encode_invoke_args, encode_result_args,
-+ * decode_invoke_args, decode_result_args
-+ */
-+ /*
-+ * localValue's from Diversion-Operations
-+ * {ccitt identified-organization etsi(0) 207 operations-and-errors(1)}
-+ */
-+ {
-+ ROSE_ETSI_ActivationDiversion, NULL, 7,
-+ rose_enc_etsi_ActivationDiversion_ARG, NULL,
-+ rose_dec_etsi_ActivationDiversion_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_DeactivationDiversion, NULL, 8,
-+ rose_enc_etsi_DeactivationDiversion_ARG,NULL,
-+ rose_dec_etsi_DeactivationDiversion_ARG,NULL
-+ },
-+ {
-+ ROSE_ETSI_ActivationStatusNotificationDiv, NULL, 9,
-+ rose_enc_etsi_ActivationStatusNotificationDiv_ARG,NULL,
-+ rose_dec_etsi_ActivationStatusNotificationDiv_ARG,NULL
-+ },
-+ {
-+ ROSE_ETSI_DeactivationStatusNotificationDiv,NULL, 10,
-+ rose_enc_etsi_DeactivationStatusNotificationDiv_ARG,NULL,
-+ rose_dec_etsi_DeactivationStatusNotificationDiv_ARG,NULL
-+ },
-+ {
-+ ROSE_ETSI_InterrogationDiversion, NULL, 11,
-+ rose_enc_etsi_InterrogationDiversion_ARG,rose_enc_etsi_InterrogationDiversion_RES,
-+ rose_dec_etsi_InterrogationDiversion_ARG,rose_dec_etsi_InterrogationDiversion_RES
-+ },
-+ {
-+ ROSE_ETSI_DiversionInformation, NULL, 12,
-+ rose_enc_etsi_DiversionInformation_ARG, NULL,
-+ rose_dec_etsi_DiversionInformation_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_CallDeflection, NULL, 13,
-+ rose_enc_etsi_CallDeflection_ARG, NULL,
-+ rose_dec_etsi_CallDeflection_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_CallRerouting, NULL, 14,
-+ rose_enc_etsi_CallRerouting_ARG, NULL,
-+ rose_dec_etsi_CallRerouting_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_DivertingLegInformation2, NULL, 15,
-+ rose_enc_etsi_DivertingLegInformation2_ARG,NULL,
-+ rose_dec_etsi_DivertingLegInformation2_ARG,NULL
-+ },
-+ {
-+ ROSE_ETSI_InterrogateServedUserNumbers, NULL, 17,
-+ NULL, rose_enc_etsi_InterrogateServedUserNumbers_RES,
-+ NULL, rose_dec_etsi_InterrogateServedUserNumbers_RES
-+ },
-+ {
-+ ROSE_ETSI_DivertingLegInformation1, NULL, 18,
-+ rose_enc_etsi_DivertingLegInformation1_ARG,NULL,
-+ rose_dec_etsi_DivertingLegInformation1_ARG,NULL
-+ },
-+ {
-+ ROSE_ETSI_DivertingLegInformation3, NULL, 19,
-+ rose_enc_etsi_DivertingLegInformation3_ARG,NULL,
-+ rose_dec_etsi_DivertingLegInformation3_ARG,NULL
-+ },
-+
-+ /*
-+ * localValue's from Advice-of-Charge-Operations
-+ * {ccitt identified-organization etsi (0) 182 operations-and-errors (1)}
-+ *
-+ * Advice-Of-Charge-at-call-Setup(AOCS)
-+ * Advice-Of-Charge-During-the-call(AOCD)
-+ * Advice-Of-Charge-at-the-End-of-the-call(AOCE)
-+ */
-+ {
-+ ROSE_ETSI_ChargingRequest, NULL, 30,
-+ rose_enc_etsi_ChargingRequest_ARG, rose_enc_etsi_ChargingRequest_RES,
-+ rose_dec_etsi_ChargingRequest_ARG, rose_dec_etsi_ChargingRequest_RES
-+ },
-+ {
-+ ROSE_ETSI_AOCSCurrency, NULL, 31,
-+ rose_enc_etsi_AOCSCurrency_ARG, NULL,
-+ rose_dec_etsi_AOCSCurrency_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_AOCSSpecialArr, NULL, 32,
-+ rose_enc_etsi_AOCSSpecialArr_ARG, NULL,
-+ rose_dec_etsi_AOCSSpecialArr_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_AOCDCurrency, NULL, 33,
-+ rose_enc_etsi_AOCDCurrency_ARG, NULL,
-+ rose_dec_etsi_AOCDCurrency_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_AOCDChargingUnit, NULL, 34,
-+ rose_enc_etsi_AOCDChargingUnit_ARG, NULL,
-+ rose_dec_etsi_AOCDChargingUnit_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_AOCECurrency, NULL, 35,
-+ rose_enc_etsi_AOCECurrency_ARG, NULL,
-+ rose_dec_etsi_AOCECurrency_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_AOCEChargingUnit, NULL, 36,
-+ rose_enc_etsi_AOCEChargingUnit_ARG, NULL,
-+ rose_dec_etsi_AOCEChargingUnit_ARG, NULL
-+ },
-+
-+ /*
-+ * localValue's from Explicit-Call-Transfer-Operations-and-Errors
-+ * {ccitt identified-organization etsi(0) 369 operations-and-errors(1)}
-+ */
-+ {
-+ ROSE_ETSI_EctExecute, NULL, 6,
-+ NULL, NULL,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * globalValue's (OIDs) from Explicit-Call-Transfer-Operations-and-Errors
-+ * {ccitt identified-organization etsi(0) 369 operations-and-errors(1)}
-+ */
-+ {
-+ ROSE_ETSI_ExplicitEctExecute, &rose_etsi_ect, 1,
-+ rose_enc_etsi_ExplicitEctExecute_ARG, NULL,
-+ rose_dec_etsi_ExplicitEctExecute_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_RequestSubaddress, &rose_etsi_ect, 2,
-+ NULL, NULL,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ETSI_SubaddressTransfer, &rose_etsi_ect, 3,
-+ rose_enc_etsi_SubaddressTransfer_ARG, NULL,
-+ rose_dec_etsi_SubaddressTransfer_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_EctLinkIdRequest, &rose_etsi_ect, 4,
-+ NULL, rose_enc_etsi_EctLinkIdRequest_RES,
-+ NULL, rose_dec_etsi_EctLinkIdRequest_RES
-+ },
-+ {
-+ ROSE_ETSI_EctInform, &rose_etsi_ect, 5,
-+ rose_enc_etsi_EctInform_ARG, NULL,
-+ rose_dec_etsi_EctInform_ARG, NULL
-+ },
-+ {
-+ ROSE_ETSI_EctLoopTest, &rose_etsi_ect, 6,
-+ rose_enc_etsi_EctLoopTest_ARG, rose_enc_etsi_EctLoopTest_RES,
-+ rose_dec_etsi_EctLoopTest_ARG, rose_dec_etsi_EctLoopTest_RES
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+/*! \brief ETSI specific error-value converion table */
-+static const struct rose_convert_error rose_etsi_errors[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * error-code, oid_prefix, value
-+ * encode_error_args, decode_error_args
-+ */
-+ /*
-+ * localValue Errors from General-Errors
-+ * {ccitt identified-organization etsi(0) 196 general-errors(2)}
-+ */
-+ {
-+ ROSE_ERROR_Gen_NotSubscribed, NULL, 0,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_NotAvailable, NULL, 3,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_NotImplemented, NULL, 4,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_InvalidServedUserNr, NULL, 6,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_InvalidCallState, NULL, 7,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_BasicServiceNotProvided, NULL, 8,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_NotIncomingCall, NULL, 9,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,NULL, 10,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_ResourceUnavailable, NULL, 11,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * localValue Errors from Diversion-Operations
-+ * {ccitt identified-organization etsi(0) 207 operations-and-errors(1)}
-+ */
-+ {
-+ ROSE_ERROR_Div_InvalidDivertedToNr, NULL, 12,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Div_SpecialServiceNr, NULL, 14,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Div_DiversionToServedUserNr, NULL, 15,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Div_IncomingCallAccepted, NULL, 23,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Div_NumberOfDiversionsExceeded, NULL, 24,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Div_NotActivated, NULL, 46,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Div_RequestAlreadyAccepted, NULL, 48,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * localValue Errors from Advice-of-Charge-Operations
-+ * {ccitt identified-organization etsi (0) 182 operations-and-errors (1)}
-+ */
-+ {
-+ ROSE_ERROR_AOC_NoChargingInfoAvailable, NULL, 26,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * globalValue Errors (OIDs) from Explicit-Call-Transfer-Operations-and-Errors
-+ * {ccitt identified-organization etsi(0) 369 operations-and-errors(1)}
-+ */
-+ {
-+ ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork, &rose_etsi_ect, 21,
-+ NULL, NULL
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*! \brief Q.SIG specific invoke/result encode/decode message table */
-+static const struct rose_convert_msg rose_qsig_msgs[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * operation, oid_prefix, value,
-+ * encode_invoke_args, encode_result_args,
-+ * decode_invoke_args, decode_result_args
-+ */
-+ /*
-+ * localValue's from Q.SIG Name-Operations
-+ * { iso(1) standard(0) pss1-name(13868) name-operations(0) }
-+ */
-+ {
-+ ROSE_QSIG_CallingName, NULL, 0,
-+ rose_enc_qsig_CallingName_ARG, NULL,
-+ rose_dec_qsig_CallingName_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_CalledName, NULL, 1,
-+ rose_enc_qsig_CalledName_ARG, NULL,
-+ rose_dec_qsig_CalledName_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_ConnectedName, NULL, 2,
-+ rose_enc_qsig_ConnectedName_ARG, NULL,
-+ rose_dec_qsig_ConnectedName_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_BusyName, NULL, 3,
-+ rose_enc_qsig_BusyName_ARG, NULL,
-+ rose_dec_qsig_BusyName_ARG, NULL
-+ },
-+
-+ /*
-+ * localValue's from Q.SIG SS-AOC-Operations
-+ * { iso(1) standard(0) pss1-advice-of-charge(15050) advice-of-charge-operations(0) }
-+ */
-+ {
-+ ROSE_QSIG_ChargeRequest, NULL, 59,
-+ rose_enc_qsig_ChargeRequest_ARG, rose_enc_qsig_ChargeRequest_RES,
-+ rose_dec_qsig_ChargeRequest_ARG, rose_dec_qsig_ChargeRequest_RES
-+ },
-+ {
-+ ROSE_QSIG_GetFinalCharge, NULL, 60,
-+ rose_enc_qsig_DummyArg_ARG, NULL,
-+ rose_dec_qsig_DummyArg_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_AocFinal, NULL, 61,
-+ rose_enc_qsig_AocFinal_ARG, NULL,
-+ rose_dec_qsig_AocFinal_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_AocInterim, NULL, 62,
-+ rose_enc_qsig_AocInterim_ARG, NULL,
-+ rose_dec_qsig_AocInterim_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_AocRate, NULL, 63,
-+ rose_enc_qsig_AocRate_ARG, NULL,
-+ rose_dec_qsig_AocRate_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_AocComplete, NULL, 64,
-+ rose_enc_qsig_AocComplete_ARG, rose_enc_qsig_AocComplete_RES,
-+ rose_dec_qsig_AocComplete_ARG, rose_dec_qsig_AocComplete_RES
-+ },
-+ {
-+ ROSE_QSIG_AocDivChargeReq, NULL, 65,
-+ rose_enc_qsig_AocDivChargeReq_ARG, NULL,
-+ rose_dec_qsig_AocDivChargeReq_ARG, NULL
-+ },
-+
-+ /*
-+ * localValue's from Q.SIG Call-Transfer-Operations
-+ * { iso(1) standard(0) pss1-call-transfer(13869) call-transfer-operations(0) }
-+ */
-+ {
-+ ROSE_QSIG_CallTransferIdentify, NULL, 7,
-+ rose_enc_qsig_DummyArg_ARG, rose_enc_qsig_CallTransferIdentify_RES,
-+ rose_dec_qsig_DummyArg_ARG, rose_dec_qsig_CallTransferIdentify_RES
-+ },
-+ {
-+ ROSE_QSIG_CallTransferAbandon, NULL, 8,
-+ rose_enc_qsig_DummyArg_ARG, NULL,
-+ rose_dec_qsig_DummyArg_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_CallTransferInitiate, NULL, 9,
-+ rose_enc_qsig_CallTransferInitiate_ARG, rose_enc_qsig_DummyRes_RES,
-+ rose_dec_qsig_CallTransferInitiate_ARG, rose_dec_qsig_DummyRes_RES
-+ },
-+ {
-+ ROSE_QSIG_CallTransferSetup, NULL, 10,
-+ rose_enc_qsig_CallTransferSetup_ARG, rose_enc_qsig_DummyRes_RES,
-+ rose_dec_qsig_CallTransferSetup_ARG, rose_dec_qsig_DummyRes_RES
-+ },
-+ {
-+ ROSE_QSIG_CallTransferActive, NULL, 11,
-+ rose_enc_qsig_CallTransferActive_ARG, NULL,
-+ rose_dec_qsig_CallTransferActive_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_CallTransferComplete, NULL, 12,
-+ rose_enc_qsig_CallTransferComplete_ARG, NULL,
-+ rose_dec_qsig_CallTransferComplete_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_CallTransferUpdate, NULL, 13,
-+ rose_enc_qsig_CallTransferUpdate_ARG, NULL,
-+ rose_dec_qsig_CallTransferUpdate_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_SubaddressTransfer, NULL, 14,
-+ rose_enc_qsig_SubaddressTransfer_ARG, NULL,
-+ rose_dec_qsig_SubaddressTransfer_ARG, NULL
-+ },
-+
-+ /*
-+ * NOTE: I do not have the specification needed to fully support this
-+ * message. Fortunately, all I have to do for this message is to switch
-+ * it to the bridged call leg for 2BCT support.
-+ */
-+ {
-+ ROSE_QSIG_PathReplacement, NULL, 4,
-+ NULL, NULL,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * localValue's from Q.SIG Call-Diversion-Operations
-+ * { iso(1) standard(0) pss1-call-diversion(13873) call-diversion-operations(0) }
-+ */
-+ {
-+ ROSE_QSIG_ActivateDiversionQ, NULL, 15,
-+ rose_enc_qsig_ActivateDiversionQ_ARG, rose_enc_qsig_DummyRes_RES,
-+ rose_dec_qsig_ActivateDiversionQ_ARG, rose_dec_qsig_DummyRes_RES
-+ },
-+ {
-+ ROSE_QSIG_DeactivateDiversionQ, NULL, 16,
-+ rose_enc_qsig_DeactivateDiversionQ_ARG, rose_enc_qsig_DummyRes_RES,
-+ rose_dec_qsig_DeactivateDiversionQ_ARG, rose_dec_qsig_DummyRes_RES
-+ },
-+ {
-+ ROSE_QSIG_InterrogateDiversionQ, NULL, 17,
-+ rose_enc_qsig_InterrogateDiversionQ_ARG,rose_enc_qsig_InterrogateDiversionQ_RES,
-+ rose_dec_qsig_InterrogateDiversionQ_ARG,rose_dec_qsig_InterrogateDiversionQ_RES
-+ },
-+ {
-+ ROSE_QSIG_CheckRestriction, NULL, 18,
-+ rose_enc_qsig_CheckRestriction_ARG, rose_enc_qsig_DummyRes_RES,
-+ rose_dec_qsig_CheckRestriction_ARG, rose_dec_qsig_DummyRes_RES
-+ },
-+ {
-+ ROSE_QSIG_CallRerouting, NULL, 19,
-+ rose_enc_qsig_CallRerouting_ARG, rose_enc_qsig_DummyRes_RES,
-+ rose_dec_qsig_CallRerouting_ARG, rose_dec_qsig_DummyRes_RES
-+ },
-+ {
-+ ROSE_QSIG_DivertingLegInformation1, NULL, 20,
-+ rose_enc_qsig_DivertingLegInformation1_ARG,NULL,
-+ rose_dec_qsig_DivertingLegInformation1_ARG,NULL
-+ },
-+ {
-+ ROSE_QSIG_DivertingLegInformation2, NULL, 21,
-+ rose_enc_qsig_DivertingLegInformation2_ARG,NULL,
-+ rose_dec_qsig_DivertingLegInformation2_ARG,NULL
-+ },
-+ {
-+ ROSE_QSIG_DivertingLegInformation3, NULL, 22,
-+ rose_enc_qsig_DivertingLegInformation3_ARG,NULL,
-+ rose_dec_qsig_DivertingLegInformation3_ARG,NULL
-+ },
-+ {
-+ ROSE_QSIG_CfnrDivertedLegFailed, NULL, 23,
-+ rose_enc_qsig_DummyArg_ARG, NULL,
-+ rose_dec_qsig_DummyArg_ARG, NULL
-+ },
-+
-+ /*
-+ * localValue's from Q.SIG SS-MWI-Operations
-+ * { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
-+ */
-+ {
-+ ROSE_QSIG_MWIActivate, NULL, 80,
-+ rose_enc_qsig_MWIActivate_ARG, rose_enc_qsig_DummyRes_RES,
-+ rose_dec_qsig_MWIActivate_ARG, rose_dec_qsig_DummyRes_RES
-+ },
-+ {
-+ ROSE_QSIG_MWIDeactivate, NULL, 81,
-+ rose_enc_qsig_MWIDeactivate_ARG, rose_enc_qsig_DummyRes_RES,
-+ rose_dec_qsig_MWIDeactivate_ARG, rose_dec_qsig_DummyRes_RES
-+ },
-+ {
-+ ROSE_QSIG_MWIInterrogate, NULL, 82,
-+ rose_enc_qsig_MWIInterrogate_ARG, rose_enc_qsig_MWIInterrogate_RES,
-+ rose_dec_qsig_MWIInterrogate_ARG, rose_dec_qsig_MWIInterrogate_RES
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+/*! \brief Q.SIG specific error-value converion table */
-+static const struct rose_convert_error rose_qsig_errors[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * error-code, oid_prefix, value
-+ * encode_error_args, decode_error_args
-+ */
-+ /*
-+ * localValue Errors from General-Error-List
-+ * {ccitt identified-organization q 950 general-error-list(1)}
-+ */
-+ {
-+ ROSE_ERROR_Gen_NotSubscribed, NULL, 0,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_RejectedByNetwork, NULL, 1,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_RejectedByUser, NULL, 2,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_NotAvailable, NULL, 3,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_InsufficientInformation, NULL, 5,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_InvalidServedUserNr, NULL, 6,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_InvalidCallState, NULL, 7,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_BasicServiceNotProvided, NULL, 8,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_NotIncomingCall, NULL, 9,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,NULL, 10,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_ResourceUnavailable, NULL, 11,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_CallFailure, NULL, 25,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_ProceduralError, NULL, 43,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * From various Q.SIG specifications.
-+ * We will ignore the manufacturer specific extension information.
-+ */
-+ {
-+ ROSE_ERROR_QSIG_Unspecified, NULL, 1008,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * localValue Errors from Q.SIG SS-AOC-Operations
-+ * { iso(1) standard(0) pss1-advice-of-charge(15050) advice-of-charge-operations(0) }
-+ */
-+ {
-+ ROSE_ERROR_QSIG_AOC_FreeOfCharge, NULL, 1016,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * localValue's from Q.SIG Call-Transfer-Operations
-+ * { iso(1) standard(0) pss1-call-transfer(13869) call-transfer-operations(0) }
-+ */
-+ {
-+ ROSE_ERROR_QSIG_CT_InvalidReroutingNumber, NULL, 1004,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_QSIG_CT_UnrecognizedCallIdentity,NULL, 1005,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_QSIG_CT_EstablishmentFailure, NULL, 1006,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * localValue's from Q.SIG Call-Diversion-Operations
-+ * { iso(1) standard(0) pss1-call-diversion(13873) call-diversion-operations(0) }
-+ */
-+ {
-+ ROSE_ERROR_Div_InvalidDivertedToNr, NULL, 12,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Div_SpecialServiceNr, NULL, 14,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Div_DiversionToServedUserNr, NULL, 15,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Div_NumberOfDiversionsExceeded, NULL, 24,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_QSIG_Div_TemporarilyUnavailable, NULL, 1000,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_QSIG_Div_NotAuthorized, NULL, 1007,
-+ NULL, NULL
-+ },
-+
-+ /*
-+ * localValue's from Q.SIG SS-MWI-Operations
-+ * { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
-+ */
-+ {
-+ ROSE_ERROR_QSIG_InvalidMsgCentreId, NULL, 1018,
-+ NULL, NULL
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*! \brief DMS-100 specific invoke/result encode/decode message table */
-+static const struct rose_convert_msg rose_dms100_msgs[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * operation, oid_prefix, value,
-+ * encode_invoke_args, encode_result_args,
-+ * decode_invoke_args, decode_result_args
-+ */
-+ {
-+ ROSE_DMS100_RLT_OperationInd, NULL, ROSE_DMS100_RLT_OPERATION_IND,
-+ NULL, rose_enc_dms100_RLT_OperationInd_RES,
-+ NULL, rose_dec_dms100_RLT_OperationInd_RES
-+ },
-+ {
-+ ROSE_DMS100_RLT_ThirdParty, NULL, ROSE_DMS100_RLT_THIRD_PARTY,
-+ rose_enc_dms100_RLT_ThirdParty_ARG, NULL,
-+ rose_dec_dms100_RLT_ThirdParty_ARG, NULL
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+/*! \brief DMS-100 specific error-value converion table */
-+static const struct rose_convert_error rose_dms100_errors[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * error-code, oid_prefix, value
-+ * encode_error_args, decode_error_args
-+ */
-+ {
-+ ROSE_ERROR_DMS100_RLT_BridgeFail, NULL, 0x10,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_DMS100_RLT_CallIDNotFound, NULL, 0x11,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_DMS100_RLT_NotAllowed, NULL, 0x12,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_DMS100_RLT_SwitchEquipCongs, NULL, 0x13,
-+ NULL, NULL
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * Note the first value in oid.values[] is really the first two
-+ * OID subidentifiers. They are compressed using this formula:
-+ * First_Value = (First_Subidentifier * 40) + Second_Subidentifier
-+ */
-+
-+static const struct asn1_oid rose_ni2_oid = {
-+/* *INDENT-OFF* */
-+ /* { iso(1) member-body(2) usa(840) ansi-t1(10005) operations(0) } */
-+ 4, { 42, 840, 10005, 0 }
-+/* *INDENT-ON* */
-+};
-+
-+/*! \brief NI2 specific invoke/result encode/decode message table */
-+static const struct rose_convert_msg rose_ni2_msgs[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * operation, oid_prefix, value,
-+ * encode_invoke_args, encode_result_args,
-+ * decode_invoke_args, decode_result_args
-+ */
-+ /* NI2 seems to have pirated several Q.SIG messages */
-+ /*
-+ * localValue's from Q.SIG Name-Operations
-+ * { iso(1) standard(0) pss1-name(13868) name-operations(0) }
-+ */
-+ {
-+ ROSE_QSIG_CallingName, NULL, 0,
-+ rose_enc_qsig_CallingName_ARG, NULL,
-+ rose_dec_qsig_CallingName_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_CalledName, NULL, 1,
-+ rose_enc_qsig_CalledName_ARG, NULL,
-+ rose_dec_qsig_CalledName_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_ConnectedName, NULL, 2,
-+ rose_enc_qsig_ConnectedName_ARG, NULL,
-+ rose_dec_qsig_ConnectedName_ARG, NULL
-+ },
-+ {
-+ ROSE_QSIG_BusyName, NULL, 3,
-+ rose_enc_qsig_BusyName_ARG, NULL,
-+ rose_dec_qsig_BusyName_ARG, NULL
-+ },
-+
-+ {
-+ ROSE_NI2_InformationFollowing, &rose_ni2_oid, 4,
-+ rose_enc_ni2_InformationFollowing_ARG, NULL,
-+ rose_dec_ni2_InformationFollowing_ARG, NULL
-+ },
-+
-+ /* Also used by PRI_SWITCH_ATT4ESS and PRI_SWITCH_LUCENT5E */
-+ {
-+ ROSE_NI2_InitiateTransfer, &rose_ni2_oid, 8,
-+ rose_enc_ni2_InitiateTransfer_ARG, NULL,
-+ rose_dec_ni2_InitiateTransfer_ARG, NULL
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+/*! \brief NI2 specific error-value converion table */
-+static const struct rose_convert_error rose_ni2_errors[] = {
-+/* *INDENT-OFF* */
-+/*
-+ * error-code, oid_prefix, value
-+ * encode_error_args, decode_error_args
-+ */
-+ /*
-+ * localValue Errors from General-Error-List
-+ * {ccitt identified-organization q 950 general-error-list(1)}
-+ */
-+ {
-+ ROSE_ERROR_Gen_NotSubscribed, NULL, 0,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_RejectedByNetwork, NULL, 1,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_RejectedByUser, NULL, 2,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_NotAvailable, NULL, 3,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_InsufficientInformation, NULL, 5,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_InvalidServedUserNr, NULL, 6,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_InvalidCallState, NULL, 7,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_BasicServiceNotProvided, NULL, 8,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_NotIncomingCall, NULL, 9,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,NULL, 10,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_ResourceUnavailable, NULL, 11,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_CallFailure, NULL, 25,
-+ NULL, NULL
-+ },
-+ {
-+ ROSE_ERROR_Gen_ProceduralError, NULL, 43,
-+ NULL, NULL
-+ },
-+/* *INDENT-ON* */
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Convert the given code value to a string.
-+ *
-+ * \param code Code value to convert to a string.
-+ * \param arr Array to convert the code to a string.
-+ * \param num_elements Number of elements in the conversion array.
-+ *
-+ * \retval String version of the given code value.
-+ */
-+static const char *rose_code2str(int code, const struct rose_code_strings *arr,
-+ unsigned num_elements)
-+{
-+ static char invalid_code[40];
-+
-+ unsigned index;
-+
-+ for (index = 0; index < num_elements; ++index) {
-+ if (arr[index].code == code) {
-+ return arr[index].name;
-+ }
-+ }
-+
-+ snprintf(invalid_code, sizeof(invalid_code), "Invalid code:%d 0x%X", code, code);
-+ return invalid_code;
-+}
-+
-+/*!
-+ * \brief Convert the given operation-value to a string.
-+ *
-+ * \param operation Operation-value to convert to a string.
-+ *
-+ * \retval String version of the given operation-value.
-+ */
-+const char *rose_operation2str(enum rose_operation operation)
-+{
-+ static const struct rose_code_strings arr[] = {
-+/* *INDENT-OFF* */
-+ { ROSE_None, "ROSE_None" },
-+ { ROSE_Unknown, "ROSE_Unknown" },
-+
-+ { ROSE_ETSI_ActivationDiversion, "ROSE_ETSI_ActivationDiversion" },
-+ { ROSE_ETSI_DeactivationDiversion, "ROSE_ETSI_DeactivationDiversion" },
-+ { ROSE_ETSI_ActivationStatusNotificationDiv,"ROSE_ETSI_ActivationStatusNotificationDiv" },
-+ { ROSE_ETSI_DeactivationStatusNotificationDiv,"ROSE_ETSI_DeactivationStatusNotificationDiv" },
-+ { ROSE_ETSI_InterrogationDiversion, "ROSE_ETSI_InterrogationDiversion" },
-+ { ROSE_ETSI_DiversionInformation, "ROSE_ETSI_DiversionInformation" },
-+ { ROSE_ETSI_CallDeflection, "ROSE_ETSI_CallDeflection" },
-+ { ROSE_ETSI_CallRerouting, "ROSE_ETSI_CallRerouting" },
-+ { ROSE_ETSI_DivertingLegInformation2, "ROSE_ETSI_DivertingLegInformation2" },
-+ { ROSE_ETSI_InterrogateServedUserNumbers, "ROSE_ETSI_InterrogateServedUserNumbers" },
-+ { ROSE_ETSI_DivertingLegInformation1, "ROSE_ETSI_DivertingLegInformation1" },
-+ { ROSE_ETSI_DivertingLegInformation3, "ROSE_ETSI_DivertingLegInformation3" },
-+
-+ { ROSE_ETSI_EctExecute, "ROSE_ETSI_EctExecute" },
-+ { ROSE_ETSI_ExplicitEctExecute, "ROSE_ETSI_ExplicitEctExecute" },
-+ { ROSE_ETSI_RequestSubaddress, "ROSE_ETSI_RequestSubaddress" },
-+ { ROSE_ETSI_SubaddressTransfer, "ROSE_ETSI_SubaddressTransfer" },
-+ { ROSE_ETSI_EctLinkIdRequest, "ROSE_ETSI_EctLinkIdRequest" },
-+ { ROSE_ETSI_EctInform, "ROSE_ETSI_EctInform" },
-+ { ROSE_ETSI_EctLoopTest, "ROSE_ETSI_EctLoopTest" },
-+
-+ { ROSE_ETSI_ChargingRequest, "ROSE_ETSI_ChargingRequest" },
-+ { ROSE_ETSI_AOCSCurrency, "ROSE_ETSI_AOCSCurrency" },
-+ { ROSE_ETSI_AOCSSpecialArr, "ROSE_ETSI_AOCSSpecialArr" },
-+ { ROSE_ETSI_AOCDCurrency, "ROSE_ETSI_AOCDCurrency" },
-+ { ROSE_ETSI_AOCDChargingUnit, "ROSE_ETSI_AOCDChargingUnit" },
-+ { ROSE_ETSI_AOCECurrency, "ROSE_ETSI_AOCECurrency" },
-+ { ROSE_ETSI_AOCEChargingUnit, "ROSE_ETSI_AOCEChargingUnit" },
-+
-+ { ROSE_QSIG_CallingName, "ROSE_QSIG_CallingName" },
-+ { ROSE_QSIG_CalledName, "ROSE_QSIG_CalledName" },
-+ { ROSE_QSIG_ConnectedName, "ROSE_QSIG_ConnectedName" },
-+ { ROSE_QSIG_BusyName, "ROSE_QSIG_BusyName" },
-+
-+ { ROSE_QSIG_ChargeRequest, "ROSE_QSIG_ChargeRequest" },
-+ { ROSE_QSIG_GetFinalCharge, "ROSE_QSIG_GetFinalCharge" },
-+ { ROSE_QSIG_AocFinal, "ROSE_QSIG_AocFinal" },
-+ { ROSE_QSIG_AocInterim, "ROSE_QSIG_AocInterim" },
-+ { ROSE_QSIG_AocRate, "ROSE_QSIG_AocRate" },
-+ { ROSE_QSIG_AocComplete, "ROSE_QSIG_AocComplete" },
-+ { ROSE_QSIG_AocDivChargeReq, "ROSE_QSIG_AocDivChargeReq" },
-+
-+ { ROSE_QSIG_CallTransferIdentify, "ROSE_QSIG_CallTransferIdentify" },
-+ { ROSE_QSIG_CallTransferAbandon, "ROSE_QSIG_CallTransferAbandon" },
-+ { ROSE_QSIG_CallTransferInitiate, "ROSE_QSIG_CallTransferInitiate" },
-+ { ROSE_QSIG_CallTransferSetup, "ROSE_QSIG_CallTransferSetup" },
-+ { ROSE_QSIG_CallTransferActive, "ROSE_QSIG_CallTransferActive" },
-+ { ROSE_QSIG_CallTransferComplete, "ROSE_QSIG_CallTransferComplete" },
-+ { ROSE_QSIG_CallTransferUpdate, "ROSE_QSIG_CallTransferUpdate" },
-+ { ROSE_QSIG_SubaddressTransfer, "ROSE_QSIG_SubaddressTransfer" },
-+
-+ { ROSE_QSIG_PathReplacement, "ROSE_QSIG_PathReplacement" },
-+
-+ { ROSE_QSIG_ActivateDiversionQ, "ROSE_QSIG_ActivateDiversionQ" },
-+ { ROSE_QSIG_DeactivateDiversionQ, "ROSE_QSIG_DeactivateDiversionQ" },
-+ { ROSE_QSIG_InterrogateDiversionQ, "ROSE_QSIG_InterrogateDiversionQ" },
-+ { ROSE_QSIG_CheckRestriction, "ROSE_QSIG_CheckRestriction" },
-+ { ROSE_QSIG_CallRerouting, "ROSE_QSIG_CallRerouting" },
-+ { ROSE_QSIG_DivertingLegInformation1, "ROSE_QSIG_DivertingLegInformation1" },
-+ { ROSE_QSIG_DivertingLegInformation2, "ROSE_QSIG_DivertingLegInformation2" },
-+ { ROSE_QSIG_DivertingLegInformation3, "ROSE_QSIG_DivertingLegInformation3" },
-+ { ROSE_QSIG_CfnrDivertedLegFailed, "ROSE_QSIG_CfnrDivertedLegFailed" },
-+
-+ { ROSE_QSIG_MWIActivate, "ROSE_QSIG_MWIActivate" },
-+ { ROSE_QSIG_MWIDeactivate, "ROSE_QSIG_MWIDeactivate" },
-+ { ROSE_QSIG_MWIInterrogate, "ROSE_QSIG_MWIInterrogate" },
-+
-+ { ROSE_DMS100_RLT_OperationInd, "ROSE_DMS100_RLT_OperationInd" },
-+ { ROSE_DMS100_RLT_ThirdParty, "ROSE_DMS100_RLT_ThirdParty" },
-+
-+ { ROSE_NI2_InformationFollowing, "ROSE_NI2_InformationFollowing" },
-+ { ROSE_NI2_InitiateTransfer, "ROSE_NI2_InitiateTransfer" },
-+/* *INDENT-ON* */
-+ };
-+
-+ return rose_code2str(operation, arr, ARRAY_LEN(arr));
-+}
-+
-+/*!
-+ * \brief Convert the given error-value to a string.
-+ *
-+ * \param code Error-value to convert to a string.
-+ *
-+ * \retval String version of the given error-value.
-+ */
-+const char *rose_error2str(enum rose_error_code code)
-+{
-+ static const struct rose_code_strings arr[] = {
-+/* *INDENT-OFF* */
-+ { ROSE_ERROR_None, "No error occurred" },
-+ { ROSE_ERROR_Unknown, "Unknown error-value code" },
-+
-+ { ROSE_ERROR_Gen_NotSubscribed, "General: Not Subscribed" },
-+ { ROSE_ERROR_Gen_NotAvailable, "General: Not Available" },
-+ { ROSE_ERROR_Gen_NotImplemented, "General: Not Implemented" },
-+ { ROSE_ERROR_Gen_InvalidServedUserNr, "General: Invalid Served User Number" },
-+ { ROSE_ERROR_Gen_InvalidCallState, "General: Invalid Call State" },
-+ { ROSE_ERROR_Gen_BasicServiceNotProvided, "General: Basic Service Not Provided" },
-+ { ROSE_ERROR_Gen_NotIncomingCall, "General: Not Incoming Call" },
-+ { ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
-+ { ROSE_ERROR_Gen_ResourceUnavailable, "General: Resource Unavailable" },
-+
-+ /* Additional Q.950 General-Errors for Q.SIG */
-+ { ROSE_ERROR_Gen_RejectedByNetwork, "General: Rejected By Network" },
-+ { ROSE_ERROR_Gen_RejectedByUser, "General: Rejected By User" },
-+ { ROSE_ERROR_Gen_InsufficientInformation, "General: Insufficient Information" },
-+ { ROSE_ERROR_Gen_CallFailure, "General: Call Failure" },
-+ { ROSE_ERROR_Gen_ProceduralError, "General: Procedural Error" },
-+
-+ { ROSE_ERROR_Div_InvalidDivertedToNr, "Diversion: Invalid Diverted To Number" },
-+ { ROSE_ERROR_Div_SpecialServiceNr, "Diversion: Special Service Number" },
-+ { ROSE_ERROR_Div_DiversionToServedUserNr, "Diversion: Diversion To Served User Number" },
-+ { ROSE_ERROR_Div_IncomingCallAccepted, "Diversion: Incoming Call Accepted" },
-+ { ROSE_ERROR_Div_NumberOfDiversionsExceeded, "Diversion: Number Of Diversions Exceeded" },
-+ { ROSE_ERROR_Div_NotActivated, "Diversion: Not Activated" },
-+ { ROSE_ERROR_Div_RequestAlreadyAccepted, "Diversion: Request Already Accepted" },
-+
-+ { ROSE_ERROR_AOC_NoChargingInfoAvailable, "AOC: No Charging Info Available" },
-+
-+ { ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
-+
-+ /* Q.SIG specific errors */
-+ { ROSE_ERROR_QSIG_Unspecified, "Unspecified" },
-+
-+ { ROSE_ERROR_QSIG_AOC_FreeOfCharge, "AOC: FreeOfCharge" },
-+
-+ { ROSE_ERROR_QSIG_CT_InvalidReroutingNumber, "CT: Invalid Rerouting Number" },
-+ { ROSE_ERROR_QSIG_CT_UnrecognizedCallIdentity,"CT: Unrecognized Call Identity" },
-+ { ROSE_ERROR_QSIG_CT_EstablishmentFailure, "CT: Establishment Failure" },
-+
-+ { ROSE_ERROR_QSIG_Div_TemporarilyUnavailable, "Diversion: Temporarily Unavailable" },
-+ { ROSE_ERROR_QSIG_Div_NotAuthorized, "Diversion: Not Authorized" },
-+
-+ { ROSE_ERROR_QSIG_InvalidMsgCentreId, "MWI: Invalid Message Center ID" },
-+
-+ /* DMS-100 specific errors */
-+ { ROSE_ERROR_DMS100_RLT_BridgeFail, "RLT: Bridge Fail" },
-+ { ROSE_ERROR_DMS100_RLT_CallIDNotFound, "RLT: Call ID Not Found" },
-+ { ROSE_ERROR_DMS100_RLT_NotAllowed, "RLT: Not Allowed" },
-+ { ROSE_ERROR_DMS100_RLT_SwitchEquipCongs, "RLT: Switch Equip Congs" },
-+/* *INDENT-ON* */
-+ };
-+
-+ return rose_code2str(code, arr, ARRAY_LEN(arr));
-+}
-+
-+/*!
-+ * \brief Convert the given reject problem-value to a string.
-+ *
-+ * \param code Reject problem-value to convert to a string.
-+ *
-+ * \retval String version of the given reject problem-value.
-+ */
-+const char *rose_reject2str(enum rose_reject_code code)
-+{
-+ static const struct rose_code_strings arr[] = {
-+/* *INDENT-OFF* */
-+ { ROSE_REJECT_None, "No reject occurred" },
-+ { ROSE_REJECT_Unknown, "Unknown reject code" },
-+
-+ { ROSE_REJECT_Gen_UnrecognizedComponent, "General: Unrecognized Component" },
-+ { ROSE_REJECT_Gen_MistypedComponent, "General: Mistyped Component" },
-+ { ROSE_REJECT_Gen_BadlyStructuredComponent, "General: Badly Structured Component" },
-+
-+ { ROSE_REJECT_Inv_DuplicateInvocation, "Invoke: Duplicate Invocation" },
-+ { ROSE_REJECT_Inv_UnrecognizedOperation, "Invoke: Unrecognized Operation" },
-+ { ROSE_REJECT_Inv_MistypedArgument, "Invoke: Mistyped Argument" },
-+ { ROSE_REJECT_Inv_ResourceLimitation, "Invoke: Resource Limitation" },
-+ { ROSE_REJECT_Inv_InitiatorReleasing, "Invoke: Initiator Releasing" },
-+ { ROSE_REJECT_Inv_UnrecognizedLinkedID, "Invoke: Unrecognized Linked ID" },
-+ { ROSE_REJECT_Inv_LinkedResponseUnexpected, "Invoke: Linked Response Unexpected" },
-+ { ROSE_REJECT_Inv_UnexpectedChildOperation, "Invoke: Unexpected Child Operation" },
-+
-+ { ROSE_REJECT_Res_UnrecognizedInvocation, "Result: Unrecognized Invocation" },
-+ { ROSE_REJECT_Res_ResultResponseUnexpected, "Result: Result Response Unexpected" },
-+ { ROSE_REJECT_Res_MistypedResult, "Result: Mistyped Result" },
-+
-+ { ROSE_REJECT_Err_UnrecognizedInvocation, "Error: Unrecognized Invocation" },
-+ { ROSE_REJECT_Err_ErrorResponseUnexpected, "Error: Error Response Unexpected" },
-+ { ROSE_REJECT_Err_UnrecognizedError, "Error: Unrecognized Error" },
-+ { ROSE_REJECT_Err_UnexpectedError, "Error: Unexpected Error" },
-+ { ROSE_REJECT_Err_MistypedParameter, "Error: Mistyped Parameter" },
-+/* *INDENT-ON* */
-+ };
-+
-+ return rose_code2str(code, arr, ARRAY_LEN(arr));
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Find an operation message conversion entry using the operation code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param operation Library operation-value code.
-+ *
-+ * \retval Message conversion entry on success.
-+ * \retval NULL on error.
-+ */
-+static const struct rose_convert_msg *rose_find_msg_by_op_code(struct pri *ctrl,
-+ enum rose_operation operation)
-+{
-+ const struct rose_convert_msg *found;
-+ const struct rose_convert_msg *table;
-+ size_t num_entries;
-+ size_t index;
-+
-+ /* Determine which message conversion table to use */
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_T1:
-+ case PRI_SWITCH_EUROISDN_E1:
-+ table = rose_etsi_msgs;
-+ num_entries = ARRAY_LEN(rose_etsi_msgs);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ table = rose_qsig_msgs;
-+ num_entries = ARRAY_LEN(rose_qsig_msgs);
-+ break;
-+ case PRI_SWITCH_DMS100:
-+ table = rose_dms100_msgs;
-+ num_entries = ARRAY_LEN(rose_dms100_msgs);
-+ break;
-+ case PRI_SWITCH_ATT4ESS:
-+ case PRI_SWITCH_LUCENT5E:
-+ case PRI_SWITCH_NI2:
-+ table = rose_ni2_msgs;
-+ num_entries = ARRAY_LEN(rose_ni2_msgs);
-+ break;
-+ default:
-+ return NULL;
-+ }
-+
-+ /* Search for the table entry */
-+ found = NULL;
-+ for (index = 0; index < num_entries; ++index) {
-+ if (table[index].operation == operation) {
-+ found = &table[index];
-+ break;
-+ }
-+ }
-+
-+ return found;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Find an operation message conversion entry using the
-+ * operation-value OID value or localValue.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param oid Search for the full OID if not NULL.
-+ * \param local Search for the localValue if OID is NULL.
-+ *
-+ * \retval Message conversion entry on success.
-+ * \retval NULL on error.
-+ */
-+static const struct rose_convert_msg *rose_find_msg_by_op_val(struct pri *ctrl,
-+ const struct asn1_oid *oid, unsigned local)
-+{
-+ const struct rose_convert_msg *found;
-+ const struct rose_convert_msg *table;
-+ size_t num_entries;
-+ size_t index;
-+ int sub_index;
-+
-+ /* Determine which message conversion table to use */
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_T1:
-+ case PRI_SWITCH_EUROISDN_E1:
-+ table = rose_etsi_msgs;
-+ num_entries = ARRAY_LEN(rose_etsi_msgs);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ table = rose_qsig_msgs;
-+ num_entries = ARRAY_LEN(rose_qsig_msgs);
-+ break;
-+ case PRI_SWITCH_DMS100:
-+ table = rose_dms100_msgs;
-+ num_entries = ARRAY_LEN(rose_dms100_msgs);
-+ break;
-+ case PRI_SWITCH_ATT4ESS:
-+ case PRI_SWITCH_LUCENT5E:
-+ case PRI_SWITCH_NI2:
-+ table = rose_ni2_msgs;
-+ num_entries = ARRAY_LEN(rose_ni2_msgs);
-+ break;
-+ default:
-+ return NULL;
-+ }
-+
-+ /* Search for the table entry */
-+ found = NULL;
-+ if (oid) {
-+ /* Search for an OID entry */
-+ local = oid->value[oid->num_values - 1];
-+ for (index = 0; index < num_entries; ++index) {
-+ if (table[index].value == local && table[index].oid_prefix
-+ && table[index].oid_prefix->num_values == oid->num_values - 1) {
-+ /* Now lets match the OID prefix subidentifiers */
-+ for (sub_index = oid->num_values - 2; 0 <= sub_index; --sub_index) {
-+ if (oid->value[sub_index]
-+ != table[index].oid_prefix->value[sub_index]) {
-+ break;
-+ }
-+ }
-+ if (sub_index == -1) {
-+ /* All of the OID subidentifiers matched */
-+ found = &table[index];
-+ break;
-+ }
-+ }
-+ }
-+ } else {
-+ /* Search for a localValue entry */
-+ for (index = 0; index < num_entries; ++index) {
-+ if (table[index].value == local && !table[index].oid_prefix) {
-+ found = &table[index];
-+ break;
-+ }
-+ }
-+ }
-+
-+ return found;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Find an error conversion entry using the error code.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param code Library error-value code.
-+ *
-+ * \retval Error conversion entry on success.
-+ * \retval NULL on error.
-+ */
-+static const struct rose_convert_error *rose_find_error_by_op_code(struct pri *ctrl,
-+ enum rose_error_code code)
-+{
-+ const struct rose_convert_error *found;
-+ const struct rose_convert_error *table;
-+ size_t num_entries;
-+ size_t index;
-+
-+ /* Determine which error conversion table to use */
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_T1:
-+ case PRI_SWITCH_EUROISDN_E1:
-+ table = rose_etsi_errors;
-+ num_entries = ARRAY_LEN(rose_etsi_errors);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ table = rose_qsig_errors;
-+ num_entries = ARRAY_LEN(rose_qsig_errors);
-+ break;
-+ case PRI_SWITCH_DMS100:
-+ table = rose_dms100_errors;
-+ num_entries = ARRAY_LEN(rose_dms100_errors);
-+ break;
-+ case PRI_SWITCH_ATT4ESS:
-+ case PRI_SWITCH_LUCENT5E:
-+ case PRI_SWITCH_NI2:
-+ table = rose_ni2_errors;
-+ num_entries = ARRAY_LEN(rose_ni2_errors);
-+ break;
-+ default:
-+ return NULL;
-+ }
-+
-+ /* Search for the table entry */
-+ found = NULL;
-+ for (index = 0; index < num_entries; ++index) {
-+ if (table[index].code == code) {
-+ found = &table[index];
-+ break;
-+ }
-+ }
-+
-+ return found;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Find an error conversion entry using the
-+ * error-value OID value or localValue.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param oid Search for the full OID if not NULL.
-+ * \param local Search for the localValue if OID is NULL.
-+ *
-+ * \retval Error conversion entry on success.
-+ * \retval NULL on error.
-+ */
-+static const struct rose_convert_error *rose_find_error_by_op_val(struct pri *ctrl,
-+ const struct asn1_oid *oid, unsigned local)
-+{
-+ const struct rose_convert_error *found;
-+ const struct rose_convert_error *table;
-+ size_t num_entries;
-+ size_t index;
-+ int sub_index;
-+
-+ /* Determine which error conversion table to use */
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_T1:
-+ case PRI_SWITCH_EUROISDN_E1:
-+ table = rose_etsi_errors;
-+ num_entries = ARRAY_LEN(rose_etsi_errors);
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ table = rose_qsig_errors;
-+ num_entries = ARRAY_LEN(rose_qsig_errors);
-+ break;
-+ case PRI_SWITCH_DMS100:
-+ table = rose_dms100_errors;
-+ num_entries = ARRAY_LEN(rose_dms100_errors);
-+ break;
-+ case PRI_SWITCH_ATT4ESS:
-+ case PRI_SWITCH_LUCENT5E:
-+ case PRI_SWITCH_NI2:
-+ table = rose_ni2_errors;
-+ num_entries = ARRAY_LEN(rose_ni2_errors);
-+ break;
-+ default:
-+ return NULL;
-+ }
-+
-+ /* Search for the table entry */
-+ found = NULL;
-+ if (oid) {
-+ /* Search for an OID entry */
-+ local = oid->value[oid->num_values - 1];
-+ for (index = 0; index < num_entries; ++index) {
-+ if (table[index].value == local && table[index].oid_prefix
-+ && table[index].oid_prefix->num_values == oid->num_values - 1) {
-+ /* Now lets match the OID prefix subidentifiers */
-+ for (sub_index = oid->num_values - 2; 0 <= sub_index; --sub_index) {
-+ if (oid->value[sub_index]
-+ != table[index].oid_prefix->value[sub_index]) {
-+ break;
-+ }
-+ }
-+ if (sub_index == -1) {
-+ /* All of the OID subidentifiers matched */
-+ found = &table[index];
-+ break;
-+ }
-+ }
-+ }
-+ } else {
-+ /* Search for a localValue entry */
-+ for (index = 0; index < num_entries; ++index) {
-+ if (table[index].value == local && !table[index].oid_prefix) {
-+ found = &table[index];
-+ break;
-+ }
-+ }
-+ }
-+
-+ return found;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Facility ie component operation-value.
-+ *
-+ * \param pos Starting position to encode the operation-value.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param oid_prefix Encode as an OID if not NULL.
-+ * \param local Encode as a localValue if oid_prefix is NULL
-+ * else it is the last OID subidentifier.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_operation_value(unsigned char *pos, unsigned char *end,
-+ const struct asn1_oid *oid_prefix, unsigned local)
-+{
-+ struct asn1_oid oid;
-+
-+ if (oid_prefix) {
-+ if (ARRAY_LEN(oid_prefix->value) <= oid_prefix->num_values) {
-+ return NULL;
-+ }
-+ oid = *oid_prefix;
-+ oid.value[oid.num_values++] = local;
-+ return asn1_enc_oid(pos, end, ASN1_TYPE_OBJECT_IDENTIFIER, &oid);
-+ } else {
-+ return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, local);
-+ }
-+}
-+
-+/*! \brief Mapped to rose_enc_operation_value() */
-+#define rose_enc_error_value(pos, end, oid_prefix, local) \
-+ rose_enc_operation_value(pos, end, oid_prefix, local)
-+
-+/*!
-+ * \brief Encode the invoke component for a ROSE message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 message.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param msg ROSE invoke message to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_encode_invoke(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rose_msg_invoke *msg)
-+{
-+ const struct rose_convert_msg *convert;
-+ unsigned char *seq_len;
-+
-+ convert = rose_find_msg_by_op_code(ctrl, msg->operation);
-+ if (!convert) {
-+ return NULL;
-+ }
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_INVOKE);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
-+ if (msg->linked_id_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
-+ msg->linked_id));
-+ }
-+ ASN1_CALL(pos, rose_enc_operation_value(pos, end, convert->oid_prefix,
-+ convert->value));
-+
-+ if (convert->encode_invoke_args) {
-+ ASN1_CALL(pos, convert->encode_invoke_args(ctrl, pos, end, &msg->args));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the result component for a ROSE message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 message.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param msg ROSE result message to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_encode_result(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rose_msg_result *msg)
-+{
-+ const struct rose_convert_msg *convert;
-+ unsigned char *seq_len;
-+ unsigned char *op_seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_RESULT);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
-+
-+ if (msg->operation != ROSE_None) {
-+ convert = rose_find_msg_by_op_code(ctrl, msg->operation);
-+ if (!convert) {
-+ return NULL;
-+ }
-+
-+ ASN1_CONSTRUCTED_BEGIN(op_seq_len, pos, end, ASN1_TYPE_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_operation_value(pos, end, convert->oid_prefix,
-+ convert->value));
-+
-+ if (convert->encode_result_args) {
-+ ASN1_CALL(pos, convert->encode_result_args(ctrl, pos, end, &msg->args));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(op_seq_len, pos, end);
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the error component for a ROSE message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 message.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param msg ROSE error message to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_encode_error(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rose_msg_error *msg)
-+{
-+ const struct rose_convert_error *convert;
-+ unsigned char *seq_len;
-+
-+ convert = rose_find_error_by_op_code(ctrl, msg->code);
-+ if (!convert) {
-+ return NULL;
-+ }
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_ERROR);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
-+ ASN1_CALL(pos, rose_enc_error_value(pos, end, convert->oid_prefix, convert->value));
-+ if (convert->encode_error_args) {
-+ ASN1_CALL(pos, convert->encode_error_args(ctrl, pos, end, &msg->args));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the reject component for a ROSE message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 message.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param msg ROSE reject message to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_encode_reject(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rose_msg_reject *msg)
-+{
-+ unsigned char *seq_len;
-+ unsigned tag;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_REJECT);
-+
-+ /* Encode Invoke ID */
-+ if (msg->invoke_id_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
-+ } else {
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ }
-+
-+ /* Encode the reject problem */
-+ switch (msg->code & ~0xFF) {
-+ case ROSE_REJECT_BASE(ROSE_REJECT_BASE_General):
-+ tag = ASN1_CLASS_CONTEXT_SPECIFIC | 0;
-+ break;
-+ case ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke):
-+ tag = ASN1_CLASS_CONTEXT_SPECIFIC | 1;
-+ break;
-+ case ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result):
-+ tag = ASN1_CLASS_CONTEXT_SPECIFIC | 2;
-+ break;
-+ case ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error):
-+ tag = ASN1_CLASS_CONTEXT_SPECIFIC | 3;
-+ break;
-+ default:
-+ return NULL;
-+ }
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, tag, msg->code & 0xFF));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the ROSE message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 message.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param msg ROSE message to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ *
-+ * \note This function only encodes the ROSE contents. It does not include
-+ * the protocol profile, NFE, NPP, and interpretation octets defined in
-+ * a facility ie that may precede the ROSE contents. These header octets
-+ * may already be stored in the encompassing buffer before the starting
-+ * position given here.
-+ */
-+unsigned char *rose_encode(struct pri *ctrl, unsigned char *pos, unsigned char *end,
-+ const struct rose_message *msg)
-+{
-+ switch (msg->type) {
-+ case ROSE_COMP_TYPE_INVOKE:
-+ pos = rose_encode_invoke(ctrl, pos, end, &msg->component.invoke);
-+ break;
-+ case ROSE_COMP_TYPE_RESULT:
-+ pos = rose_encode_result(ctrl, pos, end, &msg->component.result);
-+ break;
-+ case ROSE_COMP_TYPE_ERROR:
-+ pos = rose_encode_error(ctrl, pos, end, &msg->component.error);
-+ break;
-+ case ROSE_COMP_TYPE_REJECT:
-+ pos = rose_encode_reject(ctrl, pos, end, &msg->component.reject);
-+ break;
-+ default:
-+ pos = NULL;
-+ break;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the NetworkFacilityExtension type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param nfe Network Facility Extension information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *fac_enc_nfe(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct facNetworkFacilityExtension *nfe)
-+{
-+ unsigned char *seq_len;
-+ unsigned char *explicit_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 10);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
-+ nfe->source_entity));
-+ if (nfe->source_number.length) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &nfe->source_number));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ nfe->destination_entity));
-+ if (nfe->destination_number.length) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &nfe->destination_number));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the facility extension header.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param header Facility extension information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *fac_enc_extension_header(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct fac_extension_header *header)
-+{
-+ if (header->nfe_present) {
-+ ASN1_CALL(pos, fac_enc_nfe(ctrl, pos, end, &header->nfe));
-+ }
-+ if (header->npp_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 18,
-+ header->npp));
-+ }
-+ if (header->interpretation_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 11,
-+ header->interpretation));
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the facility ie contents header.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode the facility ie contents.
-+ * \param end End of facility ie contents encoding data buffer.
-+ * \param header Facility extension header data to encode (NULL if none).
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *facility_encode_header(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct fac_extension_header *header)
-+{
-+ /* Make sure we have some room. */
-+ if (end < pos + 2) {
-+ return NULL;
-+ }
-+
-+ switch (ctrl->switchtype) {
-+ case PRI_SWITCH_EUROISDN_T1:
-+ case PRI_SWITCH_EUROISDN_E1:
-+ *pos++ = 0x80 | Q932_PROTOCOL_ROSE;
-+ header = NULL;
-+ break;
-+ case PRI_SWITCH_QSIG:
-+ *pos++ = 0x80 | Q932_PROTOCOL_EXTENSIONS;
-+ break;
-+ case PRI_SWITCH_DMS100:
-+ *pos++ = Q932_PROTOCOL_ROSE; /* DON'T set the EXT bit yet. */
-+ *pos++ = 0x80 | ROSE_DMS100_RLT_SERVICE_ID;
-+ header = NULL;
-+ break;
-+ case PRI_SWITCH_ATT4ESS:
-+ case PRI_SWITCH_LUCENT5E:
-+ case PRI_SWITCH_NI2:
-+ if (header) {
-+ *pos++ = 0x80 | Q932_PROTOCOL_EXTENSIONS;
-+ } else {
-+ *pos++ = 0x80 | Q932_PROTOCOL_ROSE;
-+ }
-+ break;
-+ default:
-+ return NULL;
-+ }
-+
-+ if (header) {
-+ ASN1_CALL(pos, fac_enc_extension_header(ctrl, pos, end, header));
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the ROSE invoke message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param msg ROSE invoke message data to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_decode_invoke(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct rose_msg_invoke *msg)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ const struct rose_convert_msg *convert;
-+ struct asn1_oid oid;
-+ unsigned local;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "INVOKE Component %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
-+ msg->invoke_id = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | 0)) {
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "linkedId", tag, pos, seq_end, &value));
-+ msg->linked_id = value;
-+ msg->linked_id_present = 1;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ } else {
-+ msg->linked_id_present = 0;
-+ }
-+
-+ /* Decode operation-value */
-+ switch (tag) {
-+ case ASN1_TYPE_INTEGER:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "operationValue", tag, pos, seq_end, &value));
-+ local = value;
-+ oid.num_values = 0;
-+ break;
-+ case ASN1_TYPE_OBJECT_IDENTIFIER:
-+ ASN1_CALL(pos, asn1_dec_oid(ctrl, "operationValue", tag, pos, seq_end, &oid));
-+ local = 0;
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+ convert = rose_find_msg_by_op_val(ctrl, (oid.num_values == 0) ? NULL : &oid, local);
-+ if (convert) {
-+ msg->operation = convert->operation;
-+ } else {
-+ msg->operation = ROSE_Unknown;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " operationValue = %s\n", rose_operation2str(msg->operation));
-+ }
-+
-+ /* Decode any expected invoke arguments */
-+ if (convert && convert->decode_invoke_args) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, convert->decode_invoke_args(ctrl, tag, pos, seq_end, &msg->args));
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the ROSE result message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param msg ROSE result message data to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_decode_result(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct rose_msg_result *msg)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ int op_seq_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *op_seq_end;
-+ const struct rose_convert_msg *convert;
-+ struct asn1_oid oid;
-+ unsigned local;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "RESULT Component %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
-+ msg->invoke_id = value;
-+
-+ /* Decode optional operation sequence */
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " operation %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(op_seq_end, op_seq_offset, length, pos, seq_end);
-+
-+ /* Decode operation-value */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, op_seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_TYPE_INTEGER:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "operationValue", tag, pos, op_seq_end,
-+ &value));
-+ local = value;
-+ oid.num_values = 0;
-+ break;
-+ case ASN1_TYPE_OBJECT_IDENTIFIER:
-+ ASN1_CALL(pos, asn1_dec_oid(ctrl, "operationValue", tag, pos, op_seq_end,
-+ &oid));
-+ local = 0;
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+ convert =
-+ rose_find_msg_by_op_val(ctrl, (oid.num_values == 0) ? NULL : &oid, local);
-+ if (convert) {
-+ msg->operation = convert->operation;
-+ } else {
-+ msg->operation = ROSE_Unknown;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " operationValue = %s\n",
-+ rose_operation2str(msg->operation));
-+ }
-+
-+ /* Decode any expected result arguments */
-+ if (convert && convert->decode_result_args) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, op_seq_end, &tag));
-+ ASN1_CALL(pos, convert->decode_result_args(ctrl, tag, pos, op_seq_end,
-+ &msg->args));
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, op_seq_offset, op_seq_end, seq_end);
-+ } else {
-+ msg->operation = ROSE_None;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the ROSE error message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param msg ROSE error message data to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_decode_error(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct rose_msg_error *msg)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ const struct rose_convert_error *convert;
-+ struct asn1_oid oid;
-+ unsigned local;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "ERROR Component %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
-+ msg->invoke_id = value;
-+
-+ /* Decode error-value */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_TYPE_INTEGER:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "errorValue", tag, pos, seq_end, &value));
-+ local = value;
-+ oid.num_values = 0;
-+ break;
-+ case ASN1_TYPE_OBJECT_IDENTIFIER:
-+ ASN1_CALL(pos, asn1_dec_oid(ctrl, "errorValue", tag, pos, seq_end, &oid));
-+ local = 0;
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+ convert =
-+ rose_find_error_by_op_val(ctrl, (oid.num_values == 0) ? NULL : &oid, local);
-+ if (convert) {
-+ msg->code = convert->code;
-+ } else {
-+ msg->code = ROSE_ERROR_Unknown;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " errorValue = %s\n", rose_error2str(msg->code));
-+ }
-+
-+ /* Decode any expected error parameters */
-+ if (convert && convert->decode_error_args) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, convert->decode_error_args(ctrl, tag, pos, seq_end, &msg->args));
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the ROSE reject message.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param msg ROSE reject message data to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_decode_reject(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct rose_msg_reject *msg)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, "REJECT Component %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ /* Invoke ID choice */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_TYPE_INTEGER:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
-+ msg->invoke_id = value;
-+ msg->invoke_id_present = 1;
-+ break;
-+ case ASN1_TYPE_NULL:
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "invokeId", tag, pos, seq_end));
-+ msg->invoke_id_present = 0;
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ /* Problem choice */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "problemGeneral", tag, pos, seq_end, &value));
-+ msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_General) | (value & 0xFF);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "problemInvoke", tag, pos, seq_end, &value));
-+ msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) | (value & 0xFF);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "problemResult", tag, pos, seq_end, &value));
-+ msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result) | (value & 0xFF);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "problemError", tag, pos, seq_end, &value));
-+ msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) | (value & 0xFF);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " problem = %s\n", rose_reject2str(msg->code));
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the ROSE message into the given buffer.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position of the ASN.1 component.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param msg Decoded ROSE message contents.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ *
-+ * \note This function only decodes the ROSE contents. It does not check
-+ * for the protocol profile, NFE, NPP, and interpretation octets defined in
-+ * a facility ie that may preceed the ROSE contents. These header octets
-+ * may already have been consumed from the encompasing buffer before the
-+ * buffer given here.
-+ */
-+const unsigned char *rose_decode(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end, struct rose_message *msg)
-+{
-+ unsigned tag;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
-+ switch (tag) {
-+ case ROSE_TAG_COMPONENT_INVOKE:
-+ msg->type = ROSE_COMP_TYPE_INVOKE;
-+ ASN1_CALL(pos, rose_decode_invoke(ctrl, tag, pos, end, &msg->component.invoke));
-+ break;
-+ case ROSE_TAG_COMPONENT_RESULT:
-+ msg->type = ROSE_COMP_TYPE_RESULT;
-+ ASN1_CALL(pos, rose_decode_result(ctrl, tag, pos, end, &msg->component.result));
-+ break;
-+ case ROSE_TAG_COMPONENT_ERROR:
-+ msg->type = ROSE_COMP_TYPE_ERROR;
-+ ASN1_CALL(pos, rose_decode_error(ctrl, tag, pos, end, &msg->component.error));
-+ break;
-+ case ROSE_TAG_COMPONENT_REJECT:
-+ msg->type = ROSE_COMP_TYPE_REJECT;
-+ ASN1_CALL(pos, rose_decode_reject(ctrl, tag, pos, end, &msg->component.reject));
-+ break;
-+ default:
-+ msg->type = ROSE_COMP_TYPE_INVALID;
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ if (pos < end) {
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %u byte(s) of trailing data not consumed.\n",
-+ (unsigned) (end - pos));
-+ }
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the NetworkFacilityExtension argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param nfe Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *fac_dec_nfe(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end,
-+ struct facNetworkFacilityExtension *nfe)
-+{
-+ int length;
-+ int seq_offset;
-+ int explicit_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *explicit_end;
-+ const unsigned char *save_pos;
-+ int32_t value;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s NetworkFacilityExtension %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "sourceEntity", tag, pos, seq_end, &value));
-+ nfe->source_entity = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1)) {
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "sourceEntityAddress", tag, pos,
-+ seq_end, &nfe->source_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ } else {
-+ nfe->source_number.length = 0;
-+ }
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "destinationEntity", tag, pos, seq_end, &value));
-+ nfe->destination_entity = value;
-+
-+ nfe->destination_number.length = 0;
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3)) {
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "destinationEntityAddress", tag,
-+ pos, seq_end, &nfe->destination_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ } else {
-+ pos = save_pos;
-+ }
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the extension header argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param pos Starting position of the ASN.1 component.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param header Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *fac_dec_extension_header(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end, struct fac_extension_header *header)
-+{
-+ int32_t value;
-+ unsigned tag;
-+ const unsigned char *save_pos;
-+
-+ /*
-+ * For simplicity we are not checking the order of
-+ * the optional header components.
-+ */
-+ header->nfe_present = 0;
-+ header->npp_present = 0;
-+ header->interpretation_present = 0;
-+ while (pos < end) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 10:
-+ ASN1_CALL(pos, fac_dec_nfe(ctrl, "nfe", tag, pos, end, &header->nfe));
-+ header->nfe_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 18:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "networkProtocolProfile", tag, pos, end,
-+ &value));
-+ header->npp = value;
-+ header->npp_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 11:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "interpretation", tag, pos, end, &value));
-+ header->interpretation = value;
-+ header->interpretation_present = 1;
-+ break;
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the facility ie contents header.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param pos Starting position of the facility ie contents.
-+ * \param end End of facility ie contents.
-+ * \param header Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success (ROSE message).
-+ * \retval NULL on error.
-+ */
-+const unsigned char *facility_decode_header(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end, struct fac_extension_header *header)
-+{
-+ /* Make sure we have enough room for the protocol profile ie octet(s) */
-+ if (end < pos + 2) {
-+ return NULL;
-+ }
-+ switch (*pos & Q932_PROTOCOL_MASK) {
-+ case Q932_PROTOCOL_ROSE:
-+ case Q932_PROTOCOL_EXTENSIONS:
-+ break;
-+ default:
-+ return NULL;
-+ }
-+ if (!(*pos & 0x80)) {
-+ /* DMS-100 Service indicator octet - Just ignore for now */
-+ ++pos;
-+ }
-+ ++pos;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ asn1_dump(ctrl, pos, end);
-+ }
-+
-+ pos = fac_dec_extension_header(ctrl, pos, end, header);
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the facility ie contents for debug purposes.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param buf Buffer containing the facility ie contents.
-+ * \param length Length of facility ie contents.
-+ *
-+ * \return Nothing
-+ *
-+ * \note Should only be called if PRI_DEBUG_APDU is enabled. Otherwise,
-+ * it it does nothing useful.
-+ */
-+void facility_decode_dump(struct pri *ctrl, const unsigned char *buf, size_t length)
-+{
-+ const unsigned char *pos;
-+ const unsigned char *end;
-+ union {
-+ struct fac_extension_header header;
-+ struct rose_message rose;
-+ } discard;
-+
-+ end = buf + length;
-+ pos = facility_decode_header(ctrl, buf, end, &discard.header);
-+ while (pos && pos < end) {
-+ pos = rose_decode(ctrl, pos, end, &discard.rose);
-+ }
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose.c */
-
-Property changes on: rose.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_other.c
-===================================================================
---- a/rose_other.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_other.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,277 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Switch type operations for: NI2, 4ESS, 5ESS, DMS-100
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \brief Encode the DMS-100 RLT_OperationInd result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ return asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
-+ args->dms100.RLT_OperationInd.call_id);
-+}
-+
-+/*!
-+ * \brief Encode the DMS-100 RLT_ThirdParty invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseDms100RLTThirdParty_ARG *rlt_thirdparty;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ rlt_thirdparty = &args->dms100.RLT_ThirdParty;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
-+ rlt_thirdparty->call_id));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ rlt_thirdparty->reason));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the DMS-100 RLT_OperationInd result argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
-+{
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "callId", tag, pos, end, &value));
-+ args->dms100.RLT_OperationInd.call_id = value;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the DMS-100 RLT_ThirdParty invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseDms100RLTThirdParty_ARG *rlt_third_party;
-+
-+ rlt_third_party = &args->dms100.RLT_ThirdParty;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " RLT_ThirdParty %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "callId", tag, pos, seq_end, &value));
-+ rlt_third_party->call_id = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "reason", tag, pos, seq_end, &value));
-+ rlt_third_party->reason = value;
-+
-+ /* Fixup will skip over any OPTIONAL information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the NI2 InformationFollowing invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_ni2_InformationFollowing_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ /* Encode the unknown enumeration value. */
-+ return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ args->ni2.InformationFollowing.value);
-+}
-+
-+/*!
-+ * \brief Encode the NI2 InitiateTransfer invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseNi2InitiateTransfer_ARG *initiate_transfer;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ initiate_transfer = &args->ni2.InitiateTransfer;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ initiate_transfer->call_reference));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the NI2 InformationFollowing invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_ni2_InformationFollowing_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "unknown", tag, pos, end, &value));
-+ args->ni2.InformationFollowing.value = value;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the NI2 InitiateTransfer invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseNi2InitiateTransfer_ARG *initiate_transfer;
-+
-+ initiate_transfer = &args->ni2.InitiateTransfer;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " InitiateTransfer %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "callReference", tag, pos, seq_end, &value));
-+ initiate_transfer->call_reference = value;
-+
-+ /* Fixup will skip over any OPTIONAL information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_other.c */
-
-Property changes on: rose_other.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: pri_q931.h
-===================================================================
---- a/pri_q931.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_q931.h (.../branches/1.4) (revision 1357)
-@@ -30,44 +30,6 @@
- #ifndef _PRI_Q931_H
- #define _PRI_Q931_H
-
--typedef enum q931_state {
-- /* User states */
-- U0_NULL_STATE,
-- U1_CALL_INITIATED,
-- U2_OVERLAP_SENDING,
-- U3_OUTGOING_CALL_PROCEEDING,
-- U4_CALL_DELIVERED,
-- U6_CALL_PRESENT,
-- U7_CALL_RECEIVED,
-- U8_CONNECT_REQUEST,
-- U9_INCOMING_CALL_PROCEEDING,
-- U10_ACTIVE,
-- U11_DISCONNECT_REQUEST,
-- U12_DISCONNECT_INDICATION,
-- U15_SUSPEND_REQUEST,
-- U17_RESUME_REQUEST,
-- U19_RELEASE_REQUEST,
-- U25_OVERLAP_RECEIVING,
-- /* Network states */
-- N0_NULL_STATE,
-- N1_CALL_INITIATED,
-- N2_OVERLAP_SENDING,
-- N3_OUTGOING_CALL_PROCEEDING,
-- N4_CALL_DELIVERED,
-- N6_CALL_PRESENT,
-- N7_CALL_RECEIVED,
-- N8_CONNECT_REQUEST,
-- N9_INCOMING_CALL_PROCEEDING,
-- N10_ACTIVE,
-- N11_DISCONNECT_REQUEST,
-- N12_DISCONNECT_INDICATION,
-- N15_SUSPEND_REQUEST,
-- N17_RESUME_REQUEST,
-- N19_RELEASE_REQUEST,
-- N22_CALL_ABORT,
-- N25_OVERLAP_RECEIVING
--} q931_state;
--
- typedef enum q931_mode {
- UNKNOWN_MODE,
- CIRCUIT_MODE,
-@@ -79,13 +41,13 @@
- u_int8_t pd; /* Protocol Discriminator */
- #if __BYTE_ORDER == __BIG_ENDIAN
- u_int8_t x0:4;
-- u_int8_t crlen:4;
-+ u_int8_t crlen:4;/*!< Call reference length */
- #else
-- u_int8_t crlen:4;
-+ u_int8_t crlen:4;/*!< Call reference length */
- u_int8_t x0:4;
- #endif
- u_int8_t contents[0];
-- u_int8_t crv[3];
-+ u_int8_t crv[3];/*!< Call reference value */
- } __attribute__ ((packed)) q931_h;
-
-
-@@ -113,6 +75,10 @@
-
- #define Q931_PROTOCOL_DISCRIMINATOR 0x08
- #define GR303_PROTOCOL_DISCRIMINATOR 0x4f
-+/* AT&T Maintenance Protocol Discriminator */
-+#define MAINTENANCE_PROTOCOL_DISCRIMINATOR_1 0x03
-+/* National Maintenance Protocol Discriminator */
-+#define MAINTENANCE_PROTOCOL_DISCRIMINATOR_2 0x43
-
- /* Q.931 / National ISDN Message Types */
-
-@@ -157,9 +123,17 @@
- #define Q931_SUSPEND_REJECT 0x21
-
- /* Maintenance messages (codeset 0 only) */
--#define NATIONAL_SERVICE 0x0f
--#define NATIONAL_SERVICE_ACKNOWLEDGE 0x07
-+#define ATT_SERVICE 0x0f
-+#define ATT_SERVICE_ACKNOWLEDGE 0x07
-+#define NATIONAL_SERVICE 0x07
-+#define NATIONAL_SERVICE_ACKNOWLEDGE 0x0f
-
-+#define SERVICE_CHANGE_STATUS_INSERVICE 0
-+#define SERVICE_CHANGE_STATUS_LOOPBACK 1 /* not supported */
-+#define SERVICE_CHANGE_STATUS_OUTOFSERVICE 2
-+#define SERVICE_CHANGE_STATUS_REQCONTINUITYCHECK 3 /* not supported */
-+#define SERVICE_CHANGE_STATUS_SHUTDOWN 4 /* not supported */
-+
- /* Special codeset 0 IE */
- #define NATIONAL_CHANGE_STATUS 0x1
-
-@@ -168,10 +142,11 @@
- #define Q931_NON_LOCKING_SHIFT 0x98
- #define Q931_BEARER_CAPABILITY 0x04
- #define Q931_CAUSE 0x08
--#define Q931_CALL_STATE 0x14
-+#define Q931_IE_CALL_STATE 0x14
- #define Q931_CHANNEL_IDENT 0x18
- #define Q931_PROGRESS_INDICATOR 0x1e
- #define Q931_NETWORK_SPEC_FAC 0x20
-+#define Q931_CALLING_PARTY_CATEGORY (0x32 | Q931_CODESET(5))
- #define Q931_INFORMATION_RATE 0x40
- #define Q931_TRANSIT_DELAY 0x42
- #define Q931_TRANS_DELAY_SELECT 0x43
-@@ -200,8 +175,9 @@
- #define Q931_IE_SEGMENTED_MSG 0x00
- #define Q931_IE_CHANGE_STATUS 0x01
- #define Q931_IE_ORIGINATING_LINE_INFO (0x01 | Q931_CODESET(6))
--#define Q931_IE_CONNECTED_ADDR 0x0C
--#define Q931_IE_CONNECTED_NUM 0x4C
-+#define Q931_IE_CONNECTED_ADDR 0x0c
-+#define Q931_IE_CONNECTED_NUM 0x4c
-+#define Q931_IE_CONNECTED_SUBADDR 0x4d
- #define Q931_IE_CALL_IDENTITY 0x10
- #define Q931_IE_FACILITY 0x1c
- #define Q931_IE_ENDPOINT_ID 0x26
-@@ -224,31 +200,255 @@
- #define Q931_IE_ESCAPE_FOR_EXT 0x7F
-
-
--/* Call state stuff */
--#define Q931_CALL_STATE_NULL 0
--#define Q931_CALL_STATE_CALL_INITIATED 1
--#define Q931_CALL_STATE_OVERLAP_SENDING 2
--#define Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING 3
--#define Q931_CALL_STATE_CALL_DELIVERED 4
--#define Q931_CALL_STATE_CALL_PRESENT 6
--#define Q931_CALL_STATE_CALL_RECEIVED 7
--#define Q931_CALL_STATE_CONNECT_REQUEST 8
--#define Q931_CALL_STATE_INCOMING_CALL_PROCEEDING 9
--#define Q931_CALL_STATE_ACTIVE 10
--#define Q931_CALL_STATE_DISCONNECT_REQUEST 11
--#define Q931_CALL_STATE_DISCONNECT_INDICATION 12
--#define Q931_CALL_STATE_SUSPEND_REQUEST 15
--#define Q931_CALL_STATE_RESUME_REQUEST 17
--#define Q931_CALL_STATE_RELEASE_REQUEST 19
--#define Q931_CALL_STATE_OVERLAP_RECEIVING 25
--#define Q931_CALL_STATE_RESTART_REQUEST 61
--#define Q931_CALL_STATE_RESTART 62
-+/*! Q.931 call states */
-+enum Q931_CALL_STATE {
-+ /*!
-+ * \details
-+ * null state (U0):
-+ * No call exists.
-+ * \details
-+ * null state (N0):
-+ * No call exists.
-+ */
-+ Q931_CALL_STATE_NULL = 0,
-+ /*!
-+ * \details
-+ * call initiated (U1):
-+ * This state exists for an outgoing call, when the user requests
-+ * call establishment from the network.
-+ * \details
-+ * call initiated (N1):
-+ * This state exists for an outgoing call when the network has received
-+ * a call establishment request but has not yet responded.
-+ */
-+ Q931_CALL_STATE_CALL_INITIATED = 1,
-+ /*!
-+ * \details
-+ * overlap sending (U2):
-+ * This state exists for an outgoing call when the user has
-+ * received acknowledgement of the call establishment request which
-+ * permits the user to send additional call information to the network
-+ * in overlap mode.
-+ * \details
-+ * overlap sending (N2):
-+ * This state exists for an outgoing call when the network has acknowledged
-+ * the call establishment request and is prepared to receive additional
-+ * call information (if any) in overlap mode.
-+ */
-+ Q931_CALL_STATE_OVERLAP_SENDING = 2,
-+ /*!
-+ * \details
-+ * outgoing call proceeding (U3):
-+ * This state exists for an outgoing call when the user has
-+ * received acknowledgement that the network has received all
-+ * call information necessary to effect call establishment.
-+ * \details
-+ * outgoing call proceeding (N3):
-+ * This state exists for an outgoing call when the network has sent
-+ * acknowledgement that the network has received all call information
-+ * necessary to effect call establishment.
-+ */
-+ Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING = 3,
-+ /*!
-+ * \details
-+ * call delivered (U4):
-+ * This state exists for an outgoing call when the calling user has
-+ * received an indication that remote user alerting has been initiated.
-+ * \details
-+ * call delivered (N4):
-+ * This state exists for an outgoing call when the network has indicated
-+ * that remote user alerting has been initiated.
-+ */
-+ Q931_CALL_STATE_CALL_DELIVERED = 4,
-+ /*!
-+ * \details
-+ * call present (U6):
-+ * This state exists for an incoming call when the user has received a
-+ * call establishment request but has not yet responded.
-+ * \details
-+ * call present (N6):
-+ * This state exists for an incoming call when the network has sent a
-+ * call establishment request but has not yet received a satisfactory
-+ * response.
-+ */
-+ Q931_CALL_STATE_CALL_PRESENT = 6,
-+ /*!
-+ * \details
-+ * call received (U7):
-+ * This state exists for an incoming call when the user has indicated
-+ * alerting but has not yet answered.
-+ * \details
-+ * call received (N7):
-+ * This state exists for an incoming call when the network has received
-+ * an indication that the user is alerting but has not yet received an
-+ * answer.
-+ */
-+ Q931_CALL_STATE_CALL_RECEIVED = 7,
-+ /*!
-+ * \details
-+ * connect request (U8):
-+ * This state exists for an incoming call when the user has answered
-+ * the call and is waiting to be awarded the call.
-+ * \details
-+ * connect request (N8):
-+ * This state exists for an incoming call when the network has received
-+ * an answer but the network has not yet awarded the call.
-+ */
-+ Q931_CALL_STATE_CONNECT_REQUEST = 8,
-+ /*!
-+ * \details
-+ * incoming call proceeding (U9):
-+ * This state exists for an incoming call when the user has sent
-+ * acknowledgement that the user has received all call information
-+ * necessary to effect call establishment.
-+ * \details
-+ * incoming call proceeding (N9):
-+ * This state exists for an incoming call when the network has received
-+ * acknowledgement that the user has received all call information
-+ * necessary to effect call establishment.
-+ */
-+ Q931_CALL_STATE_INCOMING_CALL_PROCEEDING = 9,
-+ /*!
-+ * \details
-+ * active (U10):
-+ * This state exists for an incoming call when the user has received
-+ * an acknowledgement from the network that the user has been awarded
-+ * the call. This state exists for an outgoing call when the user has
-+ * received an indication that the remote user has answered the call.
-+ * \details
-+ * active (N10):
-+ * This state exists for an incoming call when the network has awarded
-+ * the call to the called user. This state exists for an outgoing call
-+ * when the network has indicated that the remote user has answered
-+ * the call.
-+ */
-+ Q931_CALL_STATE_ACTIVE = 10,
-+ /*!
-+ * \details
-+ * disconnect request (U11):
-+ * This state exists when the user has requested the network to clear
-+ * the end-to-end connection (if any) and is waiting for a response.
-+ * \details
-+ * disconnect request (N11):
-+ * This state exists when the network has received a request from the
-+ * user to clear the end-to-end connection (if any).
-+ */
-+ Q931_CALL_STATE_DISCONNECT_REQUEST = 11,
-+ /*!
-+ * \details
-+ * disconnect indication (U12):
-+ * This state exists when the user has received an invitation to
-+ * disconnect because the network has disconnected the end-to-end
-+ * connection (if any).
-+ * \details
-+ * disconnect indication (N12):
-+ * This state exists when the network has disconnected the end-to-end
-+ * connection (if any) and has sent an invitation to disconnect the
-+ * user-network connection.
-+ */
-+ Q931_CALL_STATE_DISCONNECT_INDICATION = 12,
-+ /*!
-+ * \details
-+ * suspend request (U15):
-+ * This state exists when the user has requested the network to suspend
-+ * the call and is waiting for a response.
-+ * \details
-+ * suspend request (N15):
-+ * This state exists when the network has received a request to suspend
-+ * the call but has not yet responded.
-+ */
-+ Q931_CALL_STATE_SUSPEND_REQUEST = 15,
-+ /*!
-+ * \details
-+ * resume request (U17):
-+ * This state exists when the user has requested the network to resume
-+ * a previously suspended call and is waiting for a response.
-+ * \details
-+ * resume request (N17):
-+ * This state exists when the network has received a request to resume
-+ * a previously suspended call but has not yet responded.
-+ */
-+ Q931_CALL_STATE_RESUME_REQUEST = 17,
-+ /*!
-+ * \details
-+ * release request (U19):
-+ * This state exists when the user has requested the network to release
-+ * and is waiting for a response.
-+ * \details
-+ * release request (N19):
-+ * This state exists when the network has requested the user to release
-+ * and is waiting for a response.
-+ */
-+ Q931_CALL_STATE_RELEASE_REQUEST = 19,
-+ /*!
-+ * \details
-+ * call abort (N22):
-+ * This state exists for an incoming call for the point-to-multipoint
-+ * configuration when the call is being cleared before any user has been
-+ * awarded the call.
-+ */
-+ Q931_CALL_STATE_CALL_ABORT = 22,
-+ /*!
-+ * \details
-+ * overlap receiving (U25):
-+ * This state exists for an incoming call when the user has acknowledged
-+ * the call establishment request from the network and is prepared to
-+ * receive additional call information (if any) in overlap mode.
-+ * \details
-+ * overlap receiving (N25):
-+ * This state exists for an incoming call when the network has received
-+ * acknowledgement of the call establishment request which permits the
-+ * network to send additional call information (if any) in the overlap
-+ * mode.
-+ */
-+ Q931_CALL_STATE_OVERLAP_RECEIVING = 25,
-+ /*!
-+ * \details
-+ * call independent service (U31): (From Q.932)
-+ * This state exists when a call independent supplementary service
-+ * signalling connection is established.
-+ * \details
-+ * call independent service (N31): (From Q.932)
-+ * This state exists when a call independent supplementary service
-+ * signalling connection is established.
-+ */
-+ Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE = 31,
-+ Q931_CALL_STATE_RESTART_REQUEST = 61,
-+ Q931_CALL_STATE_RESTART = 62,
-+ /*!
-+ * \details
-+ * Call state has not been set.
-+ * Call state does not exist.
-+ * Call state not initialized.
-+ * Call state internal use only.
-+ */
-+ Q931_CALL_STATE_NOT_SET = 0xFF,
-+};
-
-+/*! Q.931 call establishment state ranking for competing calls in PTMP NT mode. */
-+enum Q931_RANKED_CALL_STATE {
-+ /*! Call is present but has no response yet. */
-+ Q931_RANKED_CALL_STATE_PRESENT,
-+ /*! Call is collecting digits. */
-+ Q931_RANKED_CALL_STATE_OVERLAP,
-+ /*! Call routing is happening. */
-+ Q931_RANKED_CALL_STATE_PROCEEDING,
-+ /*! Called party is being alerted of the call. */
-+ Q931_RANKED_CALL_STATE_ALERTING,
-+ /*! Call is connected. A winner has been declared. */
-+ Q931_RANKED_CALL_STATE_CONNECT,
-+ /*! Call is in some non-call establishment state (likely disconnecting). */
-+ Q931_RANKED_CALL_STATE_OTHER,
-+};
-
- /* EuroISDN */
- #define Q931_SENDING_COMPLETE 0xa1
-
-+extern int maintenance_service(struct pri *pri, int span, int channel, int changestatus);
-
-+extern int maintenance_service_ack(struct pri *pri, q931_call *call);
-+
-+
- /* Q.SIG specific */
- #define QSIG_IE_TRANSIT_COUNT 0x31
-
-@@ -268,7 +468,7 @@
-
- extern int q931_information(struct pri *pri, q931_call *call, char digit);
-
--extern int q931_keypad_facility(struct pri *pri, q931_call *call, char *digits);
-+extern int q931_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
-
- extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
-
-@@ -291,8 +491,16 @@
- extern int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req);
- extern void q931_dump(struct pri *pri, q931_h *h, int len, int txrx);
-
--extern void __q931_destroycall(struct pri *pri, q931_call *c);
-+void q931_destroycall(struct pri *pri, q931_call *c);
-
- extern void q931_dl_indication(struct pri *pri, int event);
-
-+int q931_send_hold(struct pri *ctrl, struct q931_call *call);
-+int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call);
-+int q931_send_hold_rej(struct pri *ctrl, struct q931_call *call, int cause);
-+
-+int q931_send_retrieve(struct pri *ctrl, struct q931_call *call, int channel);
-+int q931_send_retrieve_ack(struct pri *ctrl, struct q931_call *call, int channel);
-+int q931_send_retrieve_rej(struct pri *ctrl, struct q931_call *call, int cause);
-+
- #endif
-Index: rose_qsig_diversion.c
-===================================================================
---- a/rose_qsig_diversion.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_qsig_diversion.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,1390 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Q.SIG ROSE Call-Diversion-Operations
-+ *
-+ * Call-Diversion-Operations ECMA-174 Annex F Table F.1
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the IntResult type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param int_result Forwarding record information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_IntResult(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseQsigForwardingRecord *int_result)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &int_result->served_user_number));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ int_result->basic_service));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, int_result->procedure));
-+ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &int_result->diverted_to));
-+ if (int_result->remote_enabled) {
-+ /* Not the DEFAULT value */
-+ ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
-+ int_result->remote_enabled));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the IntResultList type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SET unless the caller implicitly
-+ * tags it otherwise.
-+ * \param int_result_list Forwarding record list information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_IntResultList(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag,
-+ const struct roseQsigForwardingList *int_result_list)
-+{
-+ unsigned index;
-+ unsigned char *set_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(set_len, pos, end, tag);
-+
-+ for (index = 0; index < int_result_list->num_records; ++index) {
-+ ASN1_CALL(pos, rose_enc_qsig_IntResult(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &int_result_list->list[index]));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(set_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the ActivateDiversionQ invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigActivateDiversionQ_ARG *activate_diversion_q;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ activate_diversion_q = &args->qsig.ActivateDiversionQ;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ activate_diversion_q->procedure));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ activate_diversion_q->basic_service));
-+ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &activate_diversion_q->diverted_to));
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &activate_diversion_q->served_user_number));
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &activate_diversion_q->activating_user_number));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the DeactivateDiversionQ invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigDeactivateDiversionQ_ARG *deactivate_diversion_q;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ deactivate_diversion_q = &args->qsig.DeactivateDiversionQ;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ deactivate_diversion_q->procedure));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ deactivate_diversion_q->basic_service));
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &deactivate_diversion_q->served_user_number));
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &deactivate_diversion_q->deactivating_user_number));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the InterrogateDiversionQ invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigInterrogateDiversionQ_ARG *interrogate_diversion_q;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ interrogate_diversion_q = &args->qsig.InterrogateDiversionQ;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ interrogate_diversion_q->procedure));
-+ if (interrogate_diversion_q->basic_service) {
-+ /* Not the DEFAULT value */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ interrogate_diversion_q->basic_service));
-+ }
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &interrogate_diversion_q->served_user_number));
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &interrogate_diversion_q->interrogating_user_number));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the InterrogateDiversionQ result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ return rose_enc_qsig_IntResultList(ctrl, pos, end, ASN1_TAG_SET,
-+ &args->qsig.InterrogateDiversionQ);
-+}
-+
-+/*!
-+ * \brief Encode the CheckRestriction invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigCheckRestriction_ARG *check_restriction;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ check_restriction = &args->qsig.CheckRestriction;
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &check_restriction->served_user_number));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ check_restriction->basic_service));
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &check_restriction->diverted_to_number));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the CallRerouting invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigCallRerouting_ARG *call_rerouting;
-+ unsigned char *seq_len;
-+ unsigned char *exp_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ call_rerouting = &args->qsig.CallRerouting;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ call_rerouting->rerouting_reason));
-+ if (call_rerouting->original_rerouting_reason_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
-+ call_rerouting->original_rerouting_reason));
-+ }
-+ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &call_rerouting->called));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ call_rerouting->diversion_counter));
-+ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
-+ &call_rerouting->q931ie));
-+
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &call_rerouting->last_rerouting));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ call_rerouting->subscription_option));
-+
-+ if (call_rerouting->calling_subaddress.length) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
-+ &call_rerouting->calling_subaddress));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberScreened(ctrl, pos, end,
-+ &call_rerouting->calling));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+
-+ if (call_rerouting->calling_name_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
-+ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
-+ &call_rerouting->calling_name));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ if (call_rerouting->original_called_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &call_rerouting->original_called));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ if (call_rerouting->redirecting_name_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 7);
-+ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
-+ &call_rerouting->redirecting_name));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ if (call_rerouting->original_called_name_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 8);
-+ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
-+ &call_rerouting->original_called_name));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the DivertingLegInformation1 invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigDivertingLegInformation1_ARG *diverting_leg_information_1;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ diverting_leg_information_1 = &args->qsig.DivertingLegInformation1;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ diverting_leg_information_1->diversion_reason));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ diverting_leg_information_1->subscription_option));
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &diverting_leg_information_1->nominated_number));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the DivertingLegInformation2 invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigDivertingLegInformation2_ARG *diverting_leg_information_2;
-+ unsigned char *seq_len;
-+ unsigned char *exp_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ diverting_leg_information_2 = &args->qsig.DivertingLegInformation2;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ diverting_leg_information_2->diversion_counter));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ diverting_leg_information_2->diversion_reason));
-+ if (diverting_leg_information_2->original_diversion_reason_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
-+ diverting_leg_information_2->original_diversion_reason));
-+ }
-+
-+ if (diverting_leg_information_2->diverting_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &diverting_leg_information_2->diverting));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ if (diverting_leg_information_2->original_called_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &diverting_leg_information_2->original_called));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ if (diverting_leg_information_2->redirecting_name_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
-+ &diverting_leg_information_2->redirecting_name));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ if (diverting_leg_information_2->original_called_name_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
-+ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
-+ &diverting_leg_information_2->original_called_name));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the DivertingLegInformation3 invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseQsigDivertingLegInformation3_ARG *diverting_leg_information_3;
-+ unsigned char *seq_len;
-+ unsigned char *exp_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ diverting_leg_information_3 = &args->qsig.DivertingLegInformation3;
-+ ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
-+ diverting_leg_information_3->presentation_allowed_indicator));
-+
-+ if (diverting_leg_information_3->redirection_name_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
-+ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
-+ &diverting_leg_information_3->redirection_name));
-+ ASN1_CONSTRUCTED_END(exp_len, pos, end);
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the IntResult argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param int_result Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_IntResult(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigForwardingRecord *int_result)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s IntResult %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
-+ &int_result->served_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ int_result->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ int_result->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_Address(ctrl, "divertedToAddress", tag, pos, seq_end,
-+ &int_result->diverted_to));
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ int_result->remote_enabled = 0; /* DEFAULT FALSE */
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_TYPE_BOOLEAN:
-+ /* Must not be constructed but we will not check for it for simplicity. */
-+ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "remoteEnabled", tag, pos, seq_end,
-+ &value));
-+ int_result->remote_enabled = value;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " extension %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the IntResultList argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param int_result_list Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_IntResultList(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigForwardingList *int_result_list)
-+{
-+ int length;
-+ int set_offset;
-+ const unsigned char *set_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s IntResultList %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(set_end, set_offset, length, pos, end);
-+
-+ int_result_list->num_records = 0;
-+ while (pos < set_end && *pos != ASN1_INDEF_TERM) {
-+ if (int_result_list->num_records < ARRAY_LEN(int_result_list->list)) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, set_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_qsig_IntResult(ctrl, "listEntry", tag, pos, set_end,
-+ &int_result_list->list[int_result_list->num_records]));
-+ ++int_result_list->num_records;
-+ } else {
-+ /* Too many records */
-+ return NULL;
-+ }
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, set_offset, set_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG ActivateDiversionQ invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigActivateDiversionQ_ARG *activate_diversion_q;
-+
-+ activate_diversion_q = &args->qsig.ActivateDiversionQ;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " ActivateDiversionQ %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ activate_diversion_q->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ activate_diversion_q->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_Address(ctrl, "divertedToAddress", tag, pos, seq_end,
-+ &activate_diversion_q->diverted_to));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
-+ &activate_diversion_q->served_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "activatingUserNr", tag, pos, seq_end,
-+ &activate_diversion_q->activating_user_number));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG DeactivateDiversionQ invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigDeactivateDiversionQ_ARG *deactivate_diversion_q;
-+
-+ deactivate_diversion_q = &args->qsig.DeactivateDiversionQ;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " DeactivateDiversionQ %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ deactivate_diversion_q->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ deactivate_diversion_q->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
-+ &deactivate_diversion_q->served_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "deactivatingUserNr", tag, pos, seq_end,
-+ &deactivate_diversion_q->deactivating_user_number));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG InterrogateDiversionQ invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigInterrogateDiversionQ_ARG *interrogate_diversion_q;
-+
-+ interrogate_diversion_q = &args->qsig.InterrogateDiversionQ;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " InterrogateDiversionQ %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ interrogate_diversion_q->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ if (tag == ASN1_TYPE_ENUMERATED) {
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ interrogate_diversion_q->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ } else {
-+ interrogate_diversion_q->basic_service = 0; /* allServices */
-+ }
-+
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
-+ &interrogate_diversion_q->served_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "interrogatingUserNr", tag, pos, seq_end,
-+ &interrogate_diversion_q->interrogating_user_number));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG InterrogateDiversionQ result argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args)
-+{
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SET);
-+ return rose_dec_qsig_IntResultList(ctrl, "InterrogateDiversionQ", tag, pos, end,
-+ &args->qsig.InterrogateDiversionQ);
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CheckRestriction invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigCheckRestriction_ARG *check_restriction;
-+
-+ check_restriction = &args->qsig.CheckRestriction;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CheckRestriction %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
-+ &check_restriction->served_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ check_restriction->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "divertedToNr", tag, pos, seq_end,
-+ &check_restriction->diverted_to_number));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CallRerouting invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ int explicit_offset;
-+ const unsigned char *explicit_end;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigCallRerouting_ARG *call_rerouting;
-+
-+ call_rerouting = &args->qsig.CallRerouting;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CallRerouting %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "reroutingReason", tag, pos, seq_end, &value));
-+ call_rerouting->rerouting_reason = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | 0)) {
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "originalReroutingReason", tag, pos, seq_end,
-+ &value));
-+ call_rerouting->original_rerouting_reason = value;
-+ call_rerouting->original_rerouting_reason_present = 1;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ } else {
-+ call_rerouting->original_rerouting_reason_present = 0;
-+ }
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_Address(ctrl, "calledAddress", tag, pos, seq_end,
-+ &call_rerouting->called));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionCounter", tag, pos, seq_end, &value));
-+ call_rerouting->diversion_counter = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_CLASS_APPLICATION | 0);
-+ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "pSS1InfoElement", tag, pos, seq_end,
-+ &call_rerouting->q931ie, sizeof(call_rerouting->q931ie_contents)));
-+
-+ /* Remove EXPLICIT tag */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "lastReroutingNr", tag, pos,
-+ explicit_end, &call_rerouting->last_rerouting));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "subscriptionOption", tag, pos, seq_end, &value));
-+ call_rerouting->subscription_option = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3)) {
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "callingPartySubaddress", tag, pos,
-+ explicit_end, &call_rerouting->calling_subaddress));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ } else {
-+ call_rerouting->calling_subaddress.length = 0;
-+ }
-+
-+ /* Remove EXPLICIT tag */
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberScreened(ctrl, "callingNumber", tag, pos,
-+ explicit_end, &call_rerouting->calling));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ call_rerouting->calling_name_present = 0;
-+ call_rerouting->redirecting_name_present = 0;
-+ call_rerouting->original_called_name_present = 0;
-+ call_rerouting->original_called_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "callingName", tag, pos,
-+ explicit_end, &call_rerouting->calling_name));
-+ call_rerouting->calling_name_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "originalCalledNr",
-+ tag, pos, explicit_end, &call_rerouting->original_called));
-+ call_rerouting->original_called_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 7:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectingName", tag, pos,
-+ explicit_end, &call_rerouting->redirecting_name));
-+ call_rerouting->redirecting_name_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 8:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "originalCalledName", tag, pos,
-+ explicit_end, &call_rerouting->original_called_name));
-+ call_rerouting->original_called_name_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 9:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 10:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " extension %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG DivertingLegInformation1 invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigDivertingLegInformation1_ARG *diverting_leg_information_1;
-+
-+ diverting_leg_information_1 = &args->qsig.DivertingLegInformation1;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " DivertingLegInformation1 %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
-+ diverting_leg_information_1->diversion_reason = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "subscriptionOption", tag, pos, seq_end, &value));
-+ diverting_leg_information_1->subscription_option = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "nominatedNr", tag, pos, seq_end,
-+ &diverting_leg_information_1->nominated_number));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG DivertingLegInformation2 invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ int explicit_offset;
-+ const unsigned char *explicit_end;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigDivertingLegInformation2_ARG *diverting_leg_information_2;
-+
-+ diverting_leg_information_2 = &args->qsig.DivertingLegInformation2;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " DivertingLegInformation2 %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionCounter", tag, pos, seq_end, &value));
-+ diverting_leg_information_2->diversion_counter = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
-+ diverting_leg_information_2->diversion_reason = value;
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ diverting_leg_information_2->original_diversion_reason_present = 0;
-+ diverting_leg_information_2->diverting_present = 0;
-+ diverting_leg_information_2->original_called_present = 0;
-+ diverting_leg_information_2->redirecting_name_present = 0;
-+ diverting_leg_information_2->original_called_name_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "originalDiversionReason", tag, pos,
-+ seq_end, &value));
-+ diverting_leg_information_2->original_diversion_reason = value;
-+ diverting_leg_information_2->original_diversion_reason_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "divertingNr", tag,
-+ pos, explicit_end, &diverting_leg_information_2->diverting));
-+ diverting_leg_information_2->diverting_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "originalCalledNr",
-+ tag, pos, explicit_end, &diverting_leg_information_2->original_called));
-+ diverting_leg_information_2->original_called_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectingName", tag, pos,
-+ explicit_end, &diverting_leg_information_2->redirecting_name));
-+ diverting_leg_information_2->redirecting_name_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "originalCalledName", tag, pos,
-+ explicit_end, &diverting_leg_information_2->original_called_name));
-+ diverting_leg_information_2->original_called_name_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " extension %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG DivertingLegInformation3 invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ int explicit_offset;
-+ const unsigned char *explicit_end;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigDivertingLegInformation3_ARG *diverting_leg_information_3;
-+
-+ diverting_leg_information_3 = &args->qsig.DivertingLegInformation3;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " DivertingLegInformation3 %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN);
-+ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "presentationAllowedIndicator", tag, pos,
-+ seq_end, &value));
-+ diverting_leg_information_3->presentation_allowed_indicator = value;
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ diverting_leg_information_3->redirection_name_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectionName", tag, pos,
-+ explicit_end, &diverting_leg_information_3->redirection_name));
-+ diverting_leg_information_3->redirection_name_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " extension %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_qsig_diversion.c */
-
-Property changes on: rose_qsig_diversion.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose.h
-===================================================================
---- a/rose.h (.../tags/1.4.10.2) (revision 0)
-+++ b/rose.h (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,3580 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief ROSE definitions and prototypes
-+ *
-+ * \details
-+ * This file contains all of the data structures and definitions needed
-+ * for ROSE component encoding and decoding.
-+ *
-+ * ROSE - Remote Operations Service Element
-+ * ASN.1 - Abstract Syntax Notation 1
-+ * APDU - Application Protocol Data Unit
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+#ifndef _LIBPRI_ROSE_H
-+#define _LIBPRI_ROSE_H
-+
-+#include <string.h>
-+#include <sys/types.h>
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/* Northern Telecom DMS-100 RLT related operations */
-+#define ROSE_DMS100_RLT_SERVICE_ID 0x3e
-+#define ROSE_DMS100_RLT_OPERATION_IND 0x01
-+#define ROSE_DMS100_RLT_THIRD_PARTY 0x02
-+
-+/*! \brief ROSE operation-value function code */
-+enum rose_operation {
-+ /*! \brief No ROSE operation */
-+ ROSE_None,
-+ /*! \brief Unknown OID/localValue operation-value code */
-+ ROSE_Unknown,
-+
-+/* *INDENT-OFF* */
-+ /* ETSI Diversion-Operations */
-+ ROSE_ETSI_ActivationDiversion, /*!< Invoke/Result */
-+ ROSE_ETSI_DeactivationDiversion, /*!< Invoke/Result */
-+ ROSE_ETSI_ActivationStatusNotificationDiv,/*!< Invoke only */
-+ ROSE_ETSI_DeactivationStatusNotificationDiv,/*!< Invoke only */
-+ ROSE_ETSI_InterrogationDiversion, /*!< Invoke/Result */
-+ ROSE_ETSI_DiversionInformation, /*!< Invoke only */
-+ ROSE_ETSI_CallDeflection, /*!< Invoke/Result */
-+ ROSE_ETSI_CallRerouting, /*!< Invoke/Result */
-+ ROSE_ETSI_InterrogateServedUserNumbers, /*!< Invoke/Result */
-+ ROSE_ETSI_DivertingLegInformation1, /*!< Invoke only */
-+ ROSE_ETSI_DivertingLegInformation2, /*!< Invoke only */
-+ ROSE_ETSI_DivertingLegInformation3, /*!< Invoke only */
-+
-+ /*
-+ * ETSI Advice-of-Charge-Operations
-+ *
-+ * Advice-Of-Charge-at-call-Setup(AOCS)
-+ * Advice-Of-Charge-During-the-call(AOCD)
-+ * Advice-Of-Charge-at-the-End-of-the-call(AOCE)
-+ */
-+ ROSE_ETSI_ChargingRequest, /*!< Invoke/Result */
-+ ROSE_ETSI_AOCSCurrency, /*!< Invoke only */
-+ ROSE_ETSI_AOCSSpecialArr, /*!< Invoke only */
-+ ROSE_ETSI_AOCDCurrency, /*!< Invoke only */
-+ ROSE_ETSI_AOCDChargingUnit, /*!< Invoke only */
-+ ROSE_ETSI_AOCECurrency, /*!< Invoke only */
-+ ROSE_ETSI_AOCEChargingUnit, /*!< Invoke only */
-+
-+ /* ETSI Explicit-Call-Transfer-Operations-and-Errors */
-+ ROSE_ETSI_EctExecute, /*!< Invoke/Result */
-+ ROSE_ETSI_ExplicitEctExecute, /*!< Invoke/Result */
-+ ROSE_ETSI_RequestSubaddress, /*!< Invoke only */
-+ ROSE_ETSI_SubaddressTransfer, /*!< Invoke only */
-+ ROSE_ETSI_EctLinkIdRequest, /*!< Invoke/Result */
-+ ROSE_ETSI_EctInform, /*!< Invoke only */
-+ ROSE_ETSI_EctLoopTest, /*!< Invoke/Result */
-+
-+ /* Q.SIG Name-Operations */
-+ ROSE_QSIG_CallingName, /*!< Invoke only */
-+ ROSE_QSIG_CalledName, /*!< Invoke only */
-+ ROSE_QSIG_ConnectedName, /*!< Invoke only */
-+ ROSE_QSIG_BusyName, /*!< Invoke only */
-+
-+ /* Q.SIG SS-AOC-Operations */
-+ ROSE_QSIG_ChargeRequest, /*!< Invoke/Result */
-+ ROSE_QSIG_GetFinalCharge, /*!< Invoke only */
-+ ROSE_QSIG_AocFinal, /*!< Invoke only */
-+ ROSE_QSIG_AocInterim, /*!< Invoke only */
-+ ROSE_QSIG_AocRate, /*!< Invoke only */
-+ ROSE_QSIG_AocComplete, /*!< Invoke/Result */
-+ ROSE_QSIG_AocDivChargeReq, /*!< Invoke only */
-+
-+ /* Q.SIG Call-Transfer-Operations (CT) */
-+ ROSE_QSIG_CallTransferIdentify, /*!< Invoke/Result */
-+ ROSE_QSIG_CallTransferAbandon, /*!< Invoke only */
-+ ROSE_QSIG_CallTransferInitiate, /*!< Invoke/Result */
-+ ROSE_QSIG_CallTransferSetup, /*!< Invoke/Result */
-+ ROSE_QSIG_CallTransferActive, /*!< Invoke only */
-+ ROSE_QSIG_CallTransferComplete, /*!< Invoke only */
-+ ROSE_QSIG_CallTransferUpdate, /*!< Invoke only */
-+ ROSE_QSIG_SubaddressTransfer, /*!< Invoke only */
-+
-+ ROSE_QSIG_PathReplacement, /*!< Invoke only */
-+
-+ /* Q.SIG Call-Diversion-Operations */
-+ ROSE_QSIG_ActivateDiversionQ, /*!< Invoke/Result */
-+ ROSE_QSIG_DeactivateDiversionQ, /*!< Invoke/Result */
-+ ROSE_QSIG_InterrogateDiversionQ, /*!< Invoke/Result */
-+ ROSE_QSIG_CheckRestriction, /*!< Invoke/Result */
-+ ROSE_QSIG_CallRerouting, /*!< Invoke/Result */
-+ ROSE_QSIG_DivertingLegInformation1, /*!< Invoke only */
-+ ROSE_QSIG_DivertingLegInformation2, /*!< Invoke only */
-+ ROSE_QSIG_DivertingLegInformation3, /*!< Invoke only */
-+ ROSE_QSIG_CfnrDivertedLegFailed, /*!< Invoke only */
-+
-+ /* Q.SIG SS-MWI-Operations */
-+ ROSE_QSIG_MWIActivate, /*!< Invoke/Result */
-+ ROSE_QSIG_MWIDeactivate, /*!< Invoke/Result */
-+ ROSE_QSIG_MWIInterrogate, /*!< Invoke/Result */
-+
-+ /* Northern Telecom DMS-100 RLT related operations */
-+ /*! Invoke/Result: Must set invokeId to ROSE_DMS100_RLT_OPERATION_IND */
-+ ROSE_DMS100_RLT_OperationInd,
-+ /*! Invoke/Result: Must set invokeId to ROSE_DMS100_RLT_THIRD_PARTY */
-+ ROSE_DMS100_RLT_ThirdParty,
-+
-+ ROSE_NI2_InformationFollowing, /*!< Invoke only? */
-+ ROSE_NI2_InitiateTransfer, /*!< Invoke only? Is this correct operation name? */
-+
-+ ROSE_Num_Operation_Codes /*!< Must be last in the enumeration */
-+/* *INDENT-ON* */
-+};
-+
-+enum rose_error_code {
-+ /*! \brief No error occurred */
-+ ROSE_ERROR_None,
-+ /*! \brief Unknown OID/localValue error-value code */
-+ ROSE_ERROR_Unknown,
-+
-+ /* General-Errors (ETS 300 196) and General-Error-List(Q.950) */
-+ ROSE_ERROR_Gen_NotSubscribed, /*!< also: UserNotSubscribed */
-+ ROSE_ERROR_Gen_NotAvailable,
-+ ROSE_ERROR_Gen_NotImplemented, /*!< Not in Q.950 */
-+ ROSE_ERROR_Gen_InvalidServedUserNr,
-+ ROSE_ERROR_Gen_InvalidCallState,
-+ ROSE_ERROR_Gen_BasicServiceNotProvided,
-+ ROSE_ERROR_Gen_NotIncomingCall,
-+ ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,
-+ ROSE_ERROR_Gen_ResourceUnavailable,
-+
-+ /* Additional General-Error-List(Q.950) */
-+ ROSE_ERROR_Gen_RejectedByNetwork,
-+ ROSE_ERROR_Gen_RejectedByUser,
-+ ROSE_ERROR_Gen_InsufficientInformation,
-+ ROSE_ERROR_Gen_CallFailure,
-+ ROSE_ERROR_Gen_ProceduralError,
-+
-+ /* ETSI Diversion-Operations */
-+ ROSE_ERROR_Div_InvalidDivertedToNr,
-+ ROSE_ERROR_Div_SpecialServiceNr,
-+ ROSE_ERROR_Div_DiversionToServedUserNr,
-+ ROSE_ERROR_Div_IncomingCallAccepted,
-+ ROSE_ERROR_Div_NumberOfDiversionsExceeded,
-+ ROSE_ERROR_Div_NotActivated,
-+ ROSE_ERROR_Div_RequestAlreadyAccepted,
-+
-+ /* ETSI Advice-of-Charge-Operations */
-+ ROSE_ERROR_AOC_NoChargingInfoAvailable,
-+
-+ /* ETSI Explicit-Call-Transfer-Operations-and-Errors */
-+ ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork,
-+
-+ /* Q.SIG from various specifications */
-+ ROSE_ERROR_QSIG_Unspecified,
-+
-+ /* Q.SIG SS-AOC-Operations */
-+ ROSE_ERROR_QSIG_AOC_FreeOfCharge,
-+
-+ /* Q.SIG Call-Transfer-Operations (CT) */
-+ ROSE_ERROR_QSIG_CT_InvalidReroutingNumber,
-+ ROSE_ERROR_QSIG_CT_UnrecognizedCallIdentity,
-+ ROSE_ERROR_QSIG_CT_EstablishmentFailure,
-+
-+ /* Q.SIG Call-Diversion-Operations (Additional Q.SIG specific errors) */
-+ ROSE_ERROR_QSIG_Div_TemporarilyUnavailable,
-+ ROSE_ERROR_QSIG_Div_NotAuthorized,
-+
-+ /* Q.SIG SS-MWI-Operations */
-+ ROSE_ERROR_QSIG_InvalidMsgCentreId,
-+
-+ /* Northern Telecom DMS-100 RLT related operations */
-+ ROSE_ERROR_DMS100_RLT_BridgeFail,
-+ ROSE_ERROR_DMS100_RLT_CallIDNotFound,
-+ ROSE_ERROR_DMS100_RLT_NotAllowed,
-+ ROSE_ERROR_DMS100_RLT_SwitchEquipCongs,
-+
-+ ROSE_ERROR_Num_Codes /*!< Must be last in the enumeration */
-+};
-+
-+#define ROSE_REJECT_BASE(base) ((base) * 0x100)
-+enum rose_reject_base {
-+ ROSE_REJECT_BASE_General,
-+ ROSE_REJECT_BASE_Invoke,
-+ ROSE_REJECT_BASE_Result,
-+ ROSE_REJECT_BASE_Error,
-+
-+ /*! \brief Must be last in the list */
-+ ROSE_REJECT_BASE_Last
-+};
-+
-+/*!
-+ * \brief From Facility-Information-Element-Components
-+ * {itu-t identified-organization etsi(0) 196 facility-information-element-component(3)}
-+ */
-+enum rose_reject_code {
-+ /*! \brief Not rejected */
-+ ROSE_REJECT_None = -1,
-+ /*! \brief Unknown reject code */
-+ ROSE_REJECT_Unknown = -2,
-+
-+/* *INDENT-OFF* */
-+ ROSE_REJECT_Gen_UnrecognizedComponent = ROSE_REJECT_BASE(ROSE_REJECT_BASE_General) + 0,
-+ ROSE_REJECT_Gen_MistypedComponent = ROSE_REJECT_BASE(ROSE_REJECT_BASE_General) + 1,
-+ ROSE_REJECT_Gen_BadlyStructuredComponent = ROSE_REJECT_BASE(ROSE_REJECT_BASE_General) + 2,
-+
-+ ROSE_REJECT_Inv_DuplicateInvocation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 0,
-+ ROSE_REJECT_Inv_UnrecognizedOperation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 1,
-+ ROSE_REJECT_Inv_MistypedArgument = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 2,
-+ ROSE_REJECT_Inv_ResourceLimitation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 3,
-+ ROSE_REJECT_Inv_InitiatorReleasing = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 4,
-+ ROSE_REJECT_Inv_UnrecognizedLinkedID = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 5,
-+ ROSE_REJECT_Inv_LinkedResponseUnexpected = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 6,
-+ ROSE_REJECT_Inv_UnexpectedChildOperation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 7,
-+
-+ ROSE_REJECT_Res_UnrecognizedInvocation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result) + 0,
-+ ROSE_REJECT_Res_ResultResponseUnexpected = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result) + 1,
-+ ROSE_REJECT_Res_MistypedResult = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result) + 2,
-+
-+ ROSE_REJECT_Err_UnrecognizedInvocation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 0,
-+ ROSE_REJECT_Err_ErrorResponseUnexpected = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 1,
-+ ROSE_REJECT_Err_UnrecognizedError = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 2,
-+ ROSE_REJECT_Err_UnexpectedError = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 3,
-+ ROSE_REJECT_Err_MistypedParameter = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 4,
-+/* *INDENT-ON* */
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * Q931InformationElement ::= [APPLICATION 0] IMPLICIT OCTET STRING
-+ */
-+struct roseQ931ie {
-+ /*!
-+ * \brief The Q.931 ie is present if length is nonzero.
-+ * (If this field is optional in the message.)
-+ */
-+ u_int8_t length;
-+
-+ /*!
-+ * \brief We mostly just need to store the contents so we will defer
-+ * decoding/encoding.
-+ *
-+ * \note To reduce the size of the structure, the memory for the
-+ * ie contents is "allocated" after the structure.
-+ * \note Remember the "allocated" memory needs to have room for a
-+ * null terminator.
-+ */
-+ unsigned char contents[0];
-+};
-+
-+enum {
-+ /*! Bearer Capability has a max length of 12. */
-+ ROSE_Q931_MAX_BC = 12,
-+ /*! High Layer Compatibility has a max length of 5. */
-+ ROSE_Q931_MAX_HLC = 5,
-+ /*! Low Layer Compatibility has a max length of 18. */
-+ ROSE_Q931_MAX_LLC = 18,
-+ /*!
-+ * User-User Information has a network dependent maximum.
-+ * The network dependent maximum is either 35 or 131 octets
-+ * in non-USER-INFORMATION messages.
-+ */
-+ ROSE_Q931_MAX_USER = 131,
-+ /*!
-+ * Progress Indicator has a max length of 4.
-+ * There can be multiple progress indicator ies.
-+ * Q.SIG allows up to 3.
-+ * ITU-T allows up to 2.
-+ */
-+ ROSE_Q931_MAX_PROGRESS = 3 * 4,
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * PartyNumber ::= CHOICE {
-+ * -- the numbering plan is the default numbering plan of
-+ * -- the network. It is recommended that this value is
-+ * -- used.
-+ * unknownPartyNumber [0] IMPLICIT NumberDigits,
-+ *
-+ * -- the numbering plan is according to
-+ * -- ITU-T Recommendation E.164.
-+ * publicPartyNumber [1] IMPLICIT PublicPartyNumber,
-+ *
-+ * -- ATM endsystem address encoded as an NSAP address.
-+ * nsapEncodedNumber [2] IMPLICIT NsapEncodedNumber,
-+ *
-+ * -- not used, value reserved.
-+ * dataPartyNumber [3] IMPLICIT NumberDigits,
-+ *
-+ * -- not used, value reserved.
-+ * telexPartyNumber [4] IMPLICIT NumberDigits,
-+ * privatePartyNumber [5] IMPLICIT PrivatePartyNumber,
-+ *
-+ * -- not used, value reserved.
-+ * nationalStandardPartyNumber [8] IMPLICIT NumberDigits
-+ * }
-+ */
-+struct rosePartyNumber {
-+ /*!
-+ * \brief Party numbering plan
-+ * \details
-+ * unknown(0),
-+ * public(1) - The numbering plan is according to ITU-T E.164,
-+ * nsapEncoded(2),
-+ * data(3) - Reserved,
-+ * telex(4) - Reserved,
-+ * private(5),
-+ * nationalStandard(8) - Reserved
-+ */
-+ u_int8_t plan;
-+
-+ /*!
-+ * \brief Type-Of-Number valid for public and private party number plans
-+ * \details
-+ * public:
-+ * unknown(0),
-+ * internationalNumber(1),
-+ * nationalNumber(2),
-+ * networkSpecificNumber(3) - Reserved,
-+ * subscriberNumber(4) - Reserved,
-+ * abbreviatedNumber(6)
-+ * \details
-+ * private:
-+ * unknown(0),
-+ * level2RegionalNumber(1),
-+ * level1RegionalNumber(2),
-+ * pTNSpecificNumber/pISNSpecificNumber(3),
-+ * localNumber(4),
-+ * abbreviatedNumber(6)
-+ */
-+ u_int8_t ton;
-+
-+ /*! \brief Number present if length is nonzero. */
-+ u_int8_t length;
-+
-+ /*! \brief Number string data. */
-+ unsigned char str[20 + 1];
-+};
-+
-+/*
-+ * NumberScreened ::= SEQUENCE {
-+ * partyNumber PartyNumber,
-+ * screeningIndicator ScreeningIndicator
-+ * }
-+ */
-+struct roseNumberScreened {
-+ struct rosePartyNumber number;
-+
-+ /*!
-+ * \details
-+ * userProvidedNotScreened(0),
-+ * userProvidedVerifiedAndPassed(1),
-+ * userProvidedVerifiedAndFailed(2) (Not used, value reserved),
-+ * networkProvided(3)
-+ */
-+ u_int8_t screening_indicator;
-+};
-+
-+/*
-+ * PartySubaddress ::= CHOICE {
-+ * -- not recommended
-+ * UserSpecifiedSubaddress,
-+ *
-+ * -- according to ITU-T Recommendation X.213
-+ * NSAPSubaddress
-+ * }
-+ *
-+ * UserSpecifiedSubaddress ::= SEQUENCE {
-+ * SubaddressInformation,
-+ *
-+ * -- used when the coding of subaddress is BCD
-+ * oddCountIndicator BOOLEAN OPTIONAL
-+ * }
-+ *
-+ * -- specified according to ITU-T Recommendation X.213. Some
-+ * -- networks may limit the subaddress value to some other
-+ * -- length, e.g. 4 octets
-+ * NSAPSubaddress ::= OCTET STRING (SIZE(1..20))
-+ *
-+ * -- coded according to user requirements. Some networks may
-+ * -- limit the subaddress value to some other length,
-+ * -- e.g. 4 octets
-+ * SubaddressInformation ::= OCTET STRING (SIZE(1..20))
-+ */
-+struct rosePartySubaddress {
-+ /*! \brief Subaddress type UserSpecified(0), NSAP(1) */
-+ u_int8_t type;
-+
-+ /*! \brief Subaddress present if length is nonzero */
-+ u_int8_t length;
-+
-+ union {
-+ /*! \brief Specified according to ITU-T Recommendation X.213 */
-+ unsigned char nsap[20 + 1];
-+
-+ /*! \brief Use of this formatting is not recommended */
-+ struct {
-+ /*! \brief TRUE if OddCount present */
-+ u_int8_t odd_count_present;
-+
-+ /*!
-+ * \brief TRUE if odd number of BCD digits (optional)
-+ * \note Used when the coding of subaddress is BCD.
-+ */
-+ u_int8_t odd_count;
-+ unsigned char information[20 + 1];
-+ } user_specified;
-+ } u;
-+};
-+
-+/*
-+ * Address ::= SEQUENCE {
-+ * PartyNumber,
-+ * PartySubaddress OPTIONAL
-+ * }
-+ */
-+struct roseAddress {
-+ struct rosePartyNumber number;
-+
-+ /*! \brief Subaddress (Optional) */
-+ struct rosePartySubaddress subaddress;
-+};
-+
-+/*
-+ * AddressScreened ::= SEQUENCE {
-+ * PartyNumber,
-+ * ScreeningIndicator,
-+ * PartySubaddress OPTIONAL
-+ * }
-+ */
-+struct roseAddressScreened {
-+ struct rosePartyNumber number;
-+
-+ /*! \brief Subaddress (Optional) */
-+ struct rosePartySubaddress subaddress;
-+
-+ /*!
-+ * \details
-+ * userProvidedNotScreened(0),
-+ * userProvidedVerifiedAndPassed(1),
-+ * userProvidedVerifiedAndFailed(2) (Not used, value reserved),
-+ * networkProvided(3)
-+ */
-+ u_int8_t screening_indicator;
-+};
-+
-+/*
-+ * PresentedNumberUnscreened ::= CHOICE {
-+ * presentationAllowedNumber [0] EXPLICIT PartyNumber,
-+ * presentationRestricted [1] IMPLICIT NULL,
-+ * numberNotAvailableDueToInterworking [2] IMPLICIT NULL,
-+ * presentationRestrictedNumber [3] EXPLICIT PartyNumber
-+ * }
-+ */
-+struct rosePresentedNumberUnscreened {
-+ struct rosePartyNumber number;
-+ /*!
-+ * \brief Number presentation type
-+ * \details
-+ * presentationAllowedNumber(0),
-+ * presentationRestricted(1),
-+ * numberNotAvailableDueToInterworking(2),
-+ * presentationRestrictedNumber(3)
-+ */
-+ u_int8_t presentation;
-+};
-+
-+/*
-+ * PresentedNumberScreened ::= CHOICE {
-+ * presentationAllowedNumber [0] IMPLICIT NumberScreened,
-+ * presentationRestricted [1] IMPLICIT NULL,
-+ * numberNotAvailableDueToInterworking [2] IMPLICIT NULL,
-+ * presentationRestrictedNumber [3] IMPLICIT NumberScreened
-+ * }
-+ */
-+struct rosePresentedNumberScreened {
-+ /*! \brief Screened number */
-+ struct roseNumberScreened screened;
-+ /*!
-+ * \brief Number presentation type
-+ * \details
-+ * presentationAllowedNumber(0),
-+ * presentationRestricted(1),
-+ * numberNotAvailableDueToInterworking(2),
-+ * presentationRestrictedNumber(3)
-+ */
-+ u_int8_t presentation;
-+};
-+
-+/*
-+ * PresentedAddressScreened ::= CHOICE {
-+ * presentationAllowedAddress [0] IMPLICIT AddressScreened,
-+ * presentationRestricted [1] IMPLICIT NULL,
-+ * numberNotAvailableDueToInterworking [2] IMPLICIT NULL,
-+ * presentationRestrictedAddress [3] IMPLICIT AddressScreened
-+ * }
-+ */
-+struct rosePresentedAddressScreened {
-+ /*! \breif Screened address */
-+ struct roseAddressScreened screened;
-+ /*!
-+ * \brief Address presentation type
-+ * \details
-+ * presentationAllowedAddress(0),
-+ * presentationRestricted(1),
-+ * numberNotAvailableDueToInterworking(2),
-+ * presentationRestrictedAddress(3)
-+ */
-+ u_int8_t presentation;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * Time ::= SEQUENCE {
-+ * lengthOfTimeUnit [1] IMPLICIT LengthOfTimeUnit,
-+ * scale [2] IMPLICIT Scale
-+ * }
-+ */
-+struct roseEtsiAOCTime {
-+ /*! LengthOfTimeUnit ::= INTEGER (0..16777215) -- 24 bit number */
-+ u_int32_t length;
-+ /*!
-+ * \details
-+ * oneHundredthSecond(0),
-+ * oneTenthSecond(1),
-+ * oneSecond(2),
-+ * tenSeconds(3),
-+ * oneMinute(4),
-+ * oneHour(5),
-+ * twentyFourHours(6)
-+ */
-+ u_int8_t scale;
-+};
-+
-+/*
-+ * Amount ::= SEQUENCE {
-+ * currencyAmount [1] IMPLICIT CurrencyAmount,
-+ * multiplier [2] IMPLICIT Multiplier
-+ * }
-+ */
-+struct roseEtsiAOCAmount {
-+ /*! CurrencyAmount ::= INTEGER (0..16777215) -- 24 bit number */
-+ u_int32_t currency;
-+ /*!
-+ * \details
-+ * oneThousandth(0),
-+ * oneHundredth(1),
-+ * oneTenth(2),
-+ * one(3),
-+ * ten(4),
-+ * hundred(5),
-+ * thousand(6)
-+ */
-+ u_int8_t multiplier;
-+};
-+
-+/*
-+ * DurationCurrency ::= SEQUENCE {
-+ * dCurrency [1] IMPLICIT Currency,
-+ * dAmount [2] IMPLICIT Amount,
-+ * dChargingType [3] IMPLICIT ChargingType,
-+ * dTime [4] IMPLICIT Time,
-+ * dGranularity [5] IMPLICIT Time OPTIONAL
-+ * }
-+ */
-+struct roseEtsiAOCDurationCurrency {
-+ struct roseEtsiAOCAmount amount;
-+ struct roseEtsiAOCTime time;
-+ /*! \breif dGranularity (optional) */
-+ struct roseEtsiAOCTime granularity;
-+ /*! Currency ::= IA5String (SIZE (1..10)) -- Name of currency. */
-+ unsigned char currency[10 + 1];
-+ /*!
-+ * \details
-+ * continuousCharging(0),
-+ * stepFunction(1)
-+ */
-+ u_int8_t charging_type;
-+ /*! TRUE if granularity time is present */
-+ u_int8_t granularity_present;
-+};
-+
-+/*
-+ * FlatRateCurrency ::= SEQUENCE {
-+ * fRCurrency [1] IMPLICIT Currency,
-+ * fRAmount [2] IMPLICIT Amount
-+ * }
-+ */
-+struct roseEtsiAOCFlatRateCurrency {
-+ struct roseEtsiAOCAmount amount;
-+ /*! Currency ::= IA5String (SIZE (1..10)) -- Name of currency. */
-+ unsigned char currency[10 + 1];
-+};
-+
-+/*
-+ * VolumeRateCurrency ::= SEQUENCE {
-+ * vRCurrency [1] IMPLICIT Currency,
-+ * vRAmount [2] IMPLICIT Amount,
-+ * vRVolumeUnit [3] IMPLICIT VolumeUnit
-+ * }
-+ */
-+struct roseEtsiAOCVolumeRateCurrency {
-+ struct roseEtsiAOCAmount amount;
-+ /*! Currency ::= IA5String (SIZE (1..10)) -- Name of currency. */
-+ unsigned char currency[10 + 1];
-+ /*!
-+ * \brief Volume rate volume unit
-+ * \details
-+ * octet(0),
-+ * segment(1),
-+ * message(2)
-+ */
-+ u_int8_t unit;
-+};
-+
-+/*
-+ * AOCSCurrencyInfo ::= SEQUENCE {
-+ * chargedItem ChargedItem,
-+ * CHOICE {
-+ * specialChargingCode SpecialChargingCode,
-+ * durationCurrency [1] IMPLICIT DurationCurrency,
-+ * flatRateCurrency [2] IMPLICIT FlatRateCurrency,
-+ * volumeRateCurrency [3] IMPLICIT VolumeRateCurrency
-+ * freeOfCharge [4] IMPLICIT NULL,
-+ * currencyInfoNotAvailable [5] IMPLICIT NULL
-+ * }
-+ * }
-+ */
-+struct roseEtsiAOCSCurrencyInfo {
-+ union {
-+ struct roseEtsiAOCDurationCurrency duration;
-+ struct roseEtsiAOCFlatRateCurrency flat_rate;
-+ struct roseEtsiAOCVolumeRateCurrency volume_rate;
-+ /*! SpecialChargingCode ::= INTEGER (1..10) */
-+ u_int8_t special_charging_code;
-+ } u;
-+ /*!
-+ * \brief Determine what is stored in the union.
-+ * \details
-+ * specialChargingCode(0),
-+ * durationCurrency(1),
-+ * flatRateCurrency(2),
-+ * volumeRateCurrency(3),
-+ * freeOfCharge(4),
-+ * currencyInfoNotAvailable(5),
-+ */
-+ u_int8_t currency_type;
-+ /*!
-+ * \brief What service is being billed.
-+ * \details
-+ * basicCommunication(0),
-+ * callAttempt(1),
-+ * callSetup(2),
-+ * userToUserInfo(3),
-+ * operationOfSupplementaryServ(4)
-+ */
-+ u_int8_t charged_item;
-+};
-+
-+/*
-+ * AOCSCurrencyInfoList ::= SEQUENCE SIZE (1..10) OF AOCSCurrencyInfo
-+ */
-+struct roseEtsiAOCSCurrencyInfoList {
-+ /*! \brief SEQUENCE SIZE (1..10) OF AOCSCurrencyInfo */
-+ struct roseEtsiAOCSCurrencyInfo list[10];
-+
-+ /*! \brief Number of AOCSCurrencyInfo records present */
-+ u_int8_t num_records;
-+};
-+
-+/*
-+ * RecordedCurrency ::= SEQUENCE {
-+ * rCurrency [1] IMPLICIT Currency,
-+ * rAmount [2] IMPLICIT Amount
-+ * }
-+ */
-+struct roseEtsiAOCRecordedCurrency {
-+ /*! Amount of currency involved. */
-+ struct roseEtsiAOCAmount amount;
-+ /*! Currency ::= IA5String (SIZE (1..10)) -- Name of currency. */
-+ unsigned char currency[10 + 1];
-+};
-+
-+/*
-+ * RecordedUnits ::= SEQUENCE {
-+ * CHOICE {
-+ * recordedNumberOfUnits NumberOfUnits,
-+ * notAvailable NULL
-+ * },
-+ * recordedTypeOfUnits TypeOfUnit OPTIONAL
-+ * }
-+ */
-+struct roseEtsiAOCRecordedUnits {
-+ /*! \brief recordedNumberOfUnits INTEGER (0..16777215) -- 24 bit number */
-+ u_int32_t number_of_units;
-+ /*! \brief TRUE if number_of_units is not available (not present) */
-+ u_int8_t not_available;
-+ /*! \brief recordedTypeOfUnits INTEGER (1..16) (optional) */
-+ u_int8_t type_of_unit;
-+ /*! \brief TRUE if type_of_unit is present */
-+ u_int8_t type_of_unit_present;
-+};
-+
-+/*
-+ * RecordedUnitsList ::= SEQUENCE SIZE (1..32) OF RecordedUnits
-+ */
-+struct roseEtsiAOCRecordedUnitsList {
-+ /*! \brief SEQUENCE SIZE (1..32) OF RecordedUnits */
-+ struct roseEtsiAOCRecordedUnits list[32];
-+
-+ /*! \brief Number of RecordedUnits records present */
-+ u_int8_t num_records;
-+};
-+
-+/*
-+ * ChargingAssociation ::= CHOICE {
-+ * chargedNumber [0] EXPLICIT PartyNumber,
-+ * chargeIdentifier ChargeIdentifier
-+ * }
-+ */
-+struct roseEtsiAOCChargingAssociation {
-+ /*! chargeIdentifier: INTEGER (-32768..32767) -- 16 bit number */
-+ int16_t id;
-+ /*! chargedNumber */
-+ struct rosePartyNumber number;
-+ /*!
-+ * \details
-+ * charge_identifier(0),
-+ * charged_number(1)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * AOCECurrencyInfo ::= SEQUENCE {
-+ * CHOICE {
-+ * freeOfCharge [1] IMPLICIT NULL,
-+ * specificCurrency SEQUENCE {
-+ * recordedCurrency [1] IMPLICIT RecordedCurrency,
-+ * aOCEBillingId [2] IMPLICIT AOCEBillingId OPTIONAL
-+ * }
-+ * },
-+ * chargingAssociation ChargingAssociation OPTIONAL
-+ * }
-+ */
-+struct roseEtsiAOCECurrencyInfo {
-+ struct {
-+ /*! \brief recorded currency */
-+ struct roseEtsiAOCRecordedCurrency recorded;
-+ /*!
-+ * \brief AOCEBillingId (optional)
-+ * \details
-+ * normalCharging(0),
-+ * reverseCharging(1),
-+ * creditCardCharging(2),
-+ * callForwardingUnconditional(3),
-+ * callForwardingBusy(4),
-+ * callForwardingNoReply(5),
-+ * callDeflection(6),
-+ * callTransfer(7)
-+ */
-+ u_int8_t billing_id;
-+ /*! \brief TRUE if billing id is present */
-+ u_int8_t billing_id_present;
-+ } specific;
-+
-+ /*! \brief chargingAssociation (optional) */
-+ struct roseEtsiAOCChargingAssociation charging_association;
-+
-+ /*! \brief TRUE if charging_association is present */
-+ u_int8_t charging_association_present;
-+
-+ /*!
-+ * \brief TRUE if this is free of charge.
-+ * \note When TRUE, the contents of specific are not valid.
-+ */
-+ u_int8_t free_of_charge;
-+};
-+
-+/*
-+ * AOCEChargingUnitInfo ::= SEQUENCE {
-+ * CHOICE {
-+ * freeOfCharge [1] IMPLICIT NULL,
-+ * specificChargingUnits SEQUENCE
-+ * {
-+ * recordedUnitsList [1] IMPLICIT RecordedUnitsList,
-+ * aOCEBillingId [2] IMPLICIT AOCEBillingId OPTIONAL
-+ * }
-+ * },
-+ * chargingAssociation ChargingAssociation OPTIONAL
-+ * }
-+ */
-+struct roseEtsiAOCEChargingUnitInfo {
-+ /*! \brief Not valid if free_of_charge is TRUE */
-+ struct {
-+ /*! \brief RecordedUnitsList */
-+ struct roseEtsiAOCRecordedUnitsList recorded;
-+ /*!
-+ * \brief AOCEBillingId (optional)
-+ * \details
-+ * normalCharging(0),
-+ * reverseCharging(1),
-+ * creditCardCharging(2),
-+ * callForwardingUnconditional(3),
-+ * callForwardingBusy(4),
-+ * callForwardingNoReply(5),
-+ * callDeflection(6),
-+ * callTransfer(7)
-+ */
-+ u_int8_t billing_id;
-+ /*! \brief TRUE if billing id is present */
-+ u_int8_t billing_id_present;
-+ } specific;
-+
-+ /*! \brief chargingAssociation (optional) */
-+ struct roseEtsiAOCChargingAssociation charging_association;
-+
-+ /*! \brief TRUE if charging_association is present */
-+ u_int8_t charging_association_present;
-+
-+ /*!
-+ * \brief TRUE if this is free of charge.
-+ * \note When TRUE, the contents of specific are not valid.
-+ */
-+ u_int8_t free_of_charge;
-+};
-+
-+/*
-+ * ARGUMENT ChargingCase
-+ */
-+struct roseEtsiChargingRequest_ARG {
-+ /*!
-+ * \details
-+ * chargingInformationAtCallSetup(0),
-+ * chargingDuringACall(1),
-+ * chargingAtTheEndOfACall(2)
-+ */
-+ u_int8_t charging_case;
-+};
-+
-+/*
-+ * RESULT CHOICE {
-+ * AOCSCurrencyInfoList,
-+ * AOCSSpecialArrInfo,
-+ * chargingInfoFollows NULL
-+ * }
-+ */
-+struct roseEtsiChargingRequest_RES {
-+ union {
-+ struct roseEtsiAOCSCurrencyInfoList currency_info;
-+
-+ /*! AOCSSpecialArrInfo ::= INTEGER (1..10) */
-+ u_int8_t special_arrangement;
-+ } u;
-+ /*!
-+ * \details
-+ * currency_info_list(0),
-+ * special_arrangement_info(1),
-+ * charging_info_follows(2)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * ARGUMENT CHOICE {
-+ * chargeNotAvailable NULL,
-+ * AOCSCurrencyInfoList
-+ * }
-+ */
-+struct roseEtsiAOCSCurrency_ARG {
-+ struct roseEtsiAOCSCurrencyInfoList currency_info;
-+ /*!
-+ * \details
-+ * charge_not_available(0),
-+ * currency_info_list(1)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * ARGUMENT CHOICE {
-+ * chargeNotAvailable NULL,
-+ * AOCSSpecialArrInfo
-+ * }
-+ */
-+struct roseEtsiAOCSSpecialArr_ARG {
-+ /*!
-+ * \details
-+ * charge_not_available(0),
-+ * special_arrangement_info(1)
-+ */
-+ u_int8_t type;
-+ /*! AOCSSpecialArrInfo ::= INTEGER (1..10) */
-+ u_int8_t special_arrangement;
-+};
-+
-+/*
-+ * ARGUMENT CHOICE {
-+ * chargeNotAvailable NULL,
-+ * aOCDCurrencyInfo CHOICE {
-+ * freeOfCharge [1] IMPLICIT NULL,
-+ * specificCurrency SEQUENCE {
-+ * recordedCurrency [1] IMPLICIT RecordedCurrency,
-+ * typeOfChargingInfo [2] IMPLICIT TypeOfChargingInfo,
-+ * aOCDBillingId [3] IMPLICIT AOCDBillingId OPTIONAL
-+ * }
-+ * }
-+ * }
-+ */
-+struct roseEtsiAOCDCurrency_ARG {
-+ struct {
-+ /*! \brief recorded currency */
-+ struct roseEtsiAOCRecordedCurrency recorded;
-+ /*!
-+ * \brief Type of recorded charging information.
-+ * \details
-+ * subTotal(0),
-+ * total(1)
-+ */
-+ u_int8_t type_of_charging_info;
-+ /*!
-+ * \brief AOCDBillingId (optional)
-+ * \details
-+ * normalCharging(0),
-+ * reverseCharging(1),
-+ * creditCardCharging(2)
-+ */
-+ u_int8_t billing_id;
-+ /*! \brief TRUE if billing id is present */
-+ u_int8_t billing_id_present;
-+ } specific;
-+ /*!
-+ * \details
-+ * charge_not_available(0),
-+ * free_of_charge(1),
-+ * specific_currency(2)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * ARGUMENT CHOICE {
-+ * chargeNotAvailable NULL,
-+ * aOCDChargingUnitInfo CHOICE {
-+ * freeOfCharge [1] IMPLICIT NULL,
-+ * specificChargingUnits SEQUENCE {
-+ * recordedUnitsList [1] IMPLICIT RecordedUnitsList,
-+ * typeOfChargingInfo [2] IMPLICIT TypeOfChargingInfo,
-+ * aOCDBillingId [3] IMPLICIT AOCDBillingId OPTIONAL
-+ * }
-+ * }
-+ * }
-+ */
-+struct roseEtsiAOCDChargingUnit_ARG {
-+ struct {
-+ /*! \brief RecordedUnitsList */
-+ struct roseEtsiAOCRecordedUnitsList recorded;
-+ /*!
-+ * \brief Type of recorded charging information.
-+ * \details
-+ * subTotal(0),
-+ * total(1)
-+ */
-+ u_int8_t type_of_charging_info;
-+ /*!
-+ * \brief AOCDBillingId (optional)
-+ * \details
-+ * normalCharging(0),
-+ * reverseCharging(1),
-+ * creditCardCharging(2)
-+ */
-+ u_int8_t billing_id;
-+ /*! \brief TRUE if billing id is present */
-+ u_int8_t billing_id_present;
-+ } specific;
-+ /*!
-+ * \details
-+ * charge_not_available(0),
-+ * free_of_charge(1),
-+ * specific_charging_units(2)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * ARGUMENT CHOICE {
-+ * chargeNotAvailable NULL,
-+ * AOCECurrencyInfo
-+ * }
-+ */
-+struct roseEtsiAOCECurrency_ARG {
-+ struct roseEtsiAOCECurrencyInfo currency_info;
-+ /*!
-+ * \details
-+ * charge_not_available(0),
-+ * currency_info(1)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * ARGUMENT CHOICE {
-+ * chargeNotAvailable NULL,
-+ * AOCEChargingUnitInfo
-+ * }
-+ */
-+struct roseEtsiAOCEChargingUnit_ARG {
-+ struct roseEtsiAOCEChargingUnitInfo charging_unit;
-+ /*!
-+ * \details
-+ * charge_not_available(0),
-+ * charging_unit(1)
-+ */
-+ u_int8_t type;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * procedure Procedure,
-+ * basicService BasicService,
-+ * forwardedToAddress Address,
-+ * servedUserNr ServedUserNr
-+ * }
-+ */
-+struct roseEtsiActivationDiversion_ARG {
-+ /*! \brief Forwarded to address */
-+ struct roseAddress forwarded_to;
-+
-+ /*! \brief Forward all numbers if not present (Number length is zero). */
-+ struct rosePartyNumber served_user_number;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3k1Hz(3),
-+ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
-+ * multirate(5),
-+ * telephony3k1Hz(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * telephony7kHz(38),
-+ * euroFileTransfer(39),
-+ * fileTransferAndAccessManagement(40),
-+ * videoconference(41),
-+ * audioGraphicConference(42)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * procedure Procedure,
-+ * basicService BasicService,
-+ * servedUserNr ServedUserNr
-+ * }
-+ */
-+struct roseEtsiDeactivationDiversion_ARG {
-+ /*! \brief Forward all numbers if not present (Number length is zero). */
-+ struct rosePartyNumber served_user_number;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3k1Hz(3),
-+ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
-+ * multirate(5),
-+ * telephony3k1Hz(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * telephony7kHz(38),
-+ * euroFileTransfer(39),
-+ * fileTransferAndAccessManagement(40),
-+ * videoconference(41),
-+ * audioGraphicConference(42)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * procedure Procedure,
-+ * basicService BasicService,
-+ * forwardedToAddresss Address,
-+ * servedUserNr ServedUserNr
-+ * }
-+ */
-+struct roseEtsiActivationStatusNotificationDiv_ARG {
-+ /*! \brief Forwarded to address */
-+ struct roseAddress forwarded_to;
-+
-+ /*! \brief Forward all numbers if not present (Number length is zero). */
-+ struct rosePartyNumber served_user_number;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3k1Hz(3),
-+ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
-+ * multirate(5),
-+ * telephony3k1Hz(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * telephony7kHz(38),
-+ * euroFileTransfer(39),
-+ * fileTransferAndAccessManagement(40),
-+ * videoconference(41),
-+ * audioGraphicConference(42)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * procedure Procedure,
-+ * basicService BasicService,
-+ * servedUserNr ServedUserNr
-+ * }
-+ */
-+struct roseEtsiDeactivationStatusNotificationDiv_ARG {
-+ /*! \brief Forward all numbers if not present (Number length is zero). */
-+ struct rosePartyNumber served_user_number;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3k1Hz(3),
-+ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
-+ * multirate(5),
-+ * telephony3k1Hz(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * telephony7kHz(38),
-+ * euroFileTransfer(39),
-+ * fileTransferAndAccessManagement(40),
-+ * videoconference(41),
-+ * audioGraphicConference(42)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * procedure Procedure,
-+ * basicService BasicService DEFAULT allServices,
-+ * servedUserNr ServedUserNr
-+ * }
-+ */
-+struct roseEtsiInterrogationDiversion_ARG {
-+ /*! \brief Forward all numbers if not present (Number length is zero). */
-+ struct rosePartyNumber served_user_number;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*!
-+ * \details
-+ * DEFAULT allServices
-+ *
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3k1Hz(3),
-+ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
-+ * multirate(5),
-+ * telephony3k1Hz(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * telephony7kHz(38),
-+ * euroFileTransfer(39),
-+ * fileTransferAndAccessManagement(40),
-+ * videoconference(41),
-+ * audioGraphicConference(42)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+/*
-+ * IntResult ::= SEQUENCE {
-+ * servedUserNr ServedUserNr,
-+ * basicService BasicService,
-+ * procedure Procedure,
-+ * forwardedToAddress Address
-+ * }
-+ */
-+struct roseEtsiForwardingRecord {
-+ /*! \brief Forwarded to address */
-+ struct roseAddress forwarded_to;
-+
-+ /*! \brief Forward all numbers if not present (Number length is zero). */
-+ struct rosePartyNumber served_user_number;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3k1Hz(3),
-+ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
-+ * multirate(5),
-+ * telephony3k1Hz(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * telephony7kHz(38),
-+ * euroFileTransfer(39),
-+ * fileTransferAndAccessManagement(40),
-+ * videoconference(41),
-+ * audioGraphicConference(42)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+/*
-+ * roseInterrogationDiversion_RES
-+ * IntResultList ::= SET SIZE (0..29) OF IntResult
-+ */
-+struct roseEtsiForwardingList {
-+ /*!
-+ * \brief SET SIZE (0..29) OF Forwarding Records
-+ * \note Reduced the size of the array to conserve
-+ * potential stack usage.
-+ */
-+ struct roseEtsiForwardingRecord list[10];
-+
-+ /*! \brief Number of Forwarding records present */
-+ u_int8_t num_records;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * diversionReason DiversionReason,
-+ * basicService BasicService,
-+ * servedUserSubaddress PartySubaddress OPTIONAL,
-+ * callingAddress [0] EXPLICIT PresentedAddressScreened OPTIONAL,
-+ * originalCalledNr [1] EXPLICIT PresentedNumberUnscreened OPTIONAL,
-+ * lastDivertingNr [2] EXPLICIT PresentedNumberUnscreened OPTIONAL,
-+ * lastDivertingReason [3] EXPLICIT DiversionReason OPTIONAL,
-+ *
-+ * -- The User-user information element, as specified
-+ * -- in ETS 300 102-1 [11], subclause 4.5.29, shall
-+ * -- be embedded in the userInfo parameter.
-+ * userInfo Q931InformationElement OPTIONAL
-+ * }
-+ */
-+struct roseEtsiDiversionInformation_ARG {
-+ /*! \brief Served user subaddress (Optional) */
-+ struct rosePartySubaddress served_user_subaddress;
-+
-+ /*! \brief Calling address (Optional) */
-+ struct rosePresentedAddressScreened calling;
-+
-+ /*! \brief Original called number (Optional) */
-+ struct rosePresentedNumberUnscreened original_called;
-+
-+ /*! \brief Last diverting number (Optional) */
-+ struct rosePresentedNumberUnscreened last_diverting;
-+
-+ /*! \brief User-User information embedded in Q.931 IE (Optional) */
-+ struct roseQ931ie q931ie;
-+ /*! \brief q931ie.contents "allocated" after the stucture. */
-+ unsigned char q931ie_contents[ROSE_Q931_MAX_USER + 1];
-+
-+ /*!
-+ * \brief Last diverting reason (Optional)
-+ *
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3),
-+ * cdAlerting(4),
-+ * cdImmediate(5)
-+ */
-+ u_int8_t last_diverting_reason;
-+
-+ /*! \brief TRUE if CallingAddress is present */
-+ u_int8_t calling_present;
-+
-+ /*! \brief TRUE if OriginalCalled is present */
-+ u_int8_t original_called_present;
-+
-+ /*! \brief TRUE if LastDiverting is present */
-+ u_int8_t last_diverting_present;
-+
-+ /*! \brief TRUE if LastDivertingReason is present */
-+ u_int8_t last_diverting_reason_present;
-+
-+ /*!
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3),
-+ * cdAlerting(4),
-+ * cdImmediate(5)
-+ */
-+ u_int8_t diversion_reason;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3k1Hz(3),
-+ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
-+ * multirate(5),
-+ * telephony3k1Hz(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * telephony7kHz(38),
-+ * euroFileTransfer(39),
-+ * fileTransferAndAccessManagement(40),
-+ * videoconference(41),
-+ * audioGraphicConference(42)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * deflectionAddress Address,
-+ * presentationAllowedDivertedToUser PresentationAllowedIndicator OPTIONAL
-+ * }
-+ */
-+struct roseEtsiCallDeflection_ARG {
-+ /*! \brief Deflection address (Deflected-To address) */
-+ struct roseAddress deflection;
-+
-+ /*! \brief TRUE if PresentationAllowedToDivertedToUser is present */
-+ u_int8_t presentation_allowed_to_diverted_to_user_present;
-+
-+ /*! \brief TRUE if presentation is allowed (Optional) */
-+ u_int8_t presentation_allowed_to_diverted_to_user;
-+};
-+
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * reroutingReason DiversionReason,
-+ * calledAddress Address,
-+ * reroutingCounter DiversionCounter,
-+ *
-+ * -- The User-user information element (optional),
-+ * -- High layer compatibility information element (optional),
-+ * -- Bearer capability information element
-+ * -- and Low layer compatibility information element (optional)
-+ * -- as specified in ETS 300 102-1 [11] subclause 4.5 shall be
-+ * -- embedded in the q931InfoElement.
-+ * q931InfoElement Q931InformationElement,
-+ * lastReroutingNr [1] EXPLICIT PresentedNumberUnscreened,
-+ * subscriptionOption [2] EXPLICIT SubscriptionOption DEFAULT noNotification,
-+ * callingPartySubaddress [3] EXPLICIT PartySubaddress OPTIONAL
-+ * }
-+ */
-+struct roseEtsiCallRerouting_ARG {
-+ struct roseAddress called_address;
-+
-+ /*! \brief The BC, HLC (optional), LLC (optional), and User-user (optional) information */
-+ struct roseQ931ie q931ie;
-+ /*! \brief q931ie.contents "allocated" after the stucture. */
-+ unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
-+ ROSE_Q931_MAX_LLC + ROSE_Q931_MAX_USER + 1];
-+
-+ /*! \brief Last rerouting number */
-+ struct rosePresentedNumberUnscreened last_rerouting;
-+
-+ /*! \brief Calling party subaddress (Optional) */
-+ struct rosePartySubaddress calling_subaddress;
-+
-+ /*!
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3),
-+ * cdAlerting(4),
-+ * cdImmediate(5)
-+ */
-+ u_int8_t rerouting_reason;
-+
-+ /*! \brief Range 1-5 */
-+ u_int8_t rerouting_counter;
-+
-+ /*!
-+ * \details
-+ * DEFAULT noNotification
-+ *
-+ * \details
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ */
-+ u_int8_t subscription_option;
-+};
-+
-+
-+/*
-+ * roseInterrogateServedUserNumbers_RES
-+ * ServedUserNumberList ::= SET SIZE (0..99) OF PartyNumber
-+ */
-+struct roseEtsiServedUserNumberList {
-+ /*!
-+ * \brief SET SIZE (0..99) OF Served user numbers
-+ * \note Reduced the size of the array to conserve
-+ * potential stack usage.
-+ */
-+ struct rosePartyNumber number[20];
-+
-+ /*! \brief Number of Served user numbers present */
-+ u_int8_t num_records;
-+};
-+
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * diversionReason DiversionReason,
-+ * subscriptionOption SubscriptionOption,
-+ * divertedToNumber PresentedNumberUnscreened OPTIONAL
-+ * }
-+ */
-+struct roseEtsiDivertingLegInformation1_ARG {
-+ /*! \brief Diverted to number (Optional) */
-+ struct rosePresentedNumberUnscreened diverted_to;
-+
-+ /*! \brief TRUE if DivertedTo is present */
-+ u_int8_t diverted_to_present;
-+
-+ /*!
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3),
-+ * cdAlerting(4),
-+ * cdImmediate(5)
-+ */
-+ u_int8_t diversion_reason;
-+
-+ /*!
-+ * \details
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ */
-+ u_int8_t subscription_option;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * diversionCounter DiversionCounter,
-+ * diversionReason DiversionReason,
-+ * divertingNr [1] EXPLICIT PresentedNumberUnscreened OPTIONAL,
-+ * originalCalledNr [2] EXPLICIT PresentedNumberUnscreened OPTIONAL
-+ * }
-+ */
-+struct roseEtsiDivertingLegInformation2_ARG {
-+ /*! \brief Diverting number (Optional) */
-+ struct rosePresentedNumberUnscreened diverting;
-+
-+ /*! \brief Original called number (Optional) */
-+ struct rosePresentedNumberUnscreened original_called;
-+
-+ /*! \brief TRUE if Diverting number is present */
-+ u_int8_t diverting_present;
-+
-+ /*! \brief TRUE if OriginalCalled is present */
-+ u_int8_t original_called_present;
-+
-+ /*!
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3),
-+ * cdAlerting(4),
-+ * cdImmediate(5)
-+ */
-+ u_int8_t diversion_reason;
-+
-+ /*! \brief Range 1-5 */
-+ u_int8_t diversion_counter;
-+};
-+
-+/*
-+ * ARGUMENT presentationAllowedIndicator PresentationAllowedIndicator
-+ */
-+struct roseEtsiDivertingLegInformation3_ARG {
-+ /*! \brief TRUE if presentation is allowed */
-+ u_int8_t presentation_allowed_indicator;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * ARGUMENT LinkId
-+ */
-+struct roseEtsiExplicitEctExecute_ARG {
-+ int16_t link_id;
-+};
-+
-+/*
-+ * ARGUMENT transferredToSubaddress PartySubaddress
-+ */
-+struct roseEtsiSubaddressTransfer_ARG {
-+ /*! \brief Transferred to subaddress */
-+ struct rosePartySubaddress subaddress;
-+};
-+
-+
-+/*
-+ * RESULT LinkId
-+ */
-+struct roseEtsiEctLinkIdRequest_RES {
-+ int16_t link_id;
-+};
-+
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * ENUMERATED {
-+ * alerting (0),
-+ * active (1)
-+ * },
-+ * redirectionNumber PresentedNumberUnscreened OPTIONAL
-+ * }
-+ */
-+struct roseEtsiEctInform_ARG {
-+ /*! \brief Redirection Number (Optional) */
-+ struct rosePresentedNumberUnscreened redirection;
-+
-+ /*! \brief TRUE if the Redirection Number is present */
-+ u_int8_t redirection_present;
-+
-+ /*! \details alerting(0), active(1) */
-+ u_int8_t status;
-+};
-+
-+
-+/*
-+ * ARGUMENT CallTransferIdentity
-+ */
-+struct roseEtsiEctLoopTest_ARG {
-+ int8_t call_transfer_id;
-+};
-+
-+/*
-+ * RESULT LoopResult
-+ */
-+struct roseEtsiEctLoopTest_RES {
-+ /*!
-+ * \details
-+ * insufficientInformation(0),
-+ * noLoopExists(1),
-+ * simultaneousTransfer(2)
-+ */
-+ u_int8_t loop_result;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * Name ::= CHOICE {
-+ * -- iso8859-1 is implied in namePresentationAllowedSimple.
-+ * namePresentationAllowedSimple [0] IMPLICIT NameData,
-+ * namePresentationAllowedExtended [1] IMPLICIT NameSet,
-+ *
-+ * -- iso8859-1 is implied in namePresentationRestrictedSimple.
-+ * namePresentationRestrictedSimple [2] IMPLICIT NameData,
-+ * namePresentationRestrictedExtended [3] IMPLICIT NameSet,
-+ *
-+ * -- namePresentationRestrictedNull shall only be used in the
-+ * -- case of interworking where the other network provides an
-+ * -- indication that the name is restricted without the name itself.
-+ * namePresentationRestrictedNull [7] IMPLICIT NULL,
-+ *
-+ * nameNotAvailable [4] IMPLICIT NULL
-+ * }
-+ *
-+ * NameSet ::= SEQUENCE {
-+ * nameData NameData,
-+ *
-+ * -- If characterSet is not included, iso8859-1 is implied.
-+ * characterSet CharacterSet OPTIONAL -- DEFAULT iso8859-1
-+ * }
-+ *
-+ * -- The maximum allowed size of the name field is 50 octets.
-+ * -- The minimum required size of the name field is 1 octet.
-+ * NameData ::= OCTET STRING (SIZE (1..50))
-+ */
-+struct roseQsigName {
-+ /*!
-+ * \details
-+ * optional_name_not_present(0),
-+ * presentation_allowed(1),
-+ * presentation_restricted(2),
-+ * presentation_restricted_null(3),
-+ * name_not_available(4)
-+ */
-+ u_int8_t presentation;
-+
-+ /*!
-+ * \details
-+ * Set to iso8859-1 if not present in the encoding.
-+ *
-+ * \details
-+ * unknown(0),
-+ * iso8859-1(1),
-+ * enum-value-withdrawn-by-ITU-T(2)
-+ * iso8859-2(3),
-+ * iso8859-3(4),
-+ * iso8859-4(5),
-+ * iso8859-5(6),
-+ * iso8859-7(7),
-+ * iso10646-BmpString(8),
-+ * iso10646-utf-8String(9)
-+ */
-+ u_int8_t char_set;
-+
-+ /*! \brief Length of name data */
-+ u_int8_t length;
-+
-+ /*! \brief Name string data */
-+ unsigned char data[50 + 1];
-+};
-+
-+/*
-+ * NOTE: We are not going to record the Extension information
-+ * since it is manufacturer specific.
-+ *
-+ * ARGUMENT CHOICE {
-+ * Name,
-+ * SEQUENCE {
-+ * Name,
-+ * CHOICE {
-+ * [5] IMPLICIT Extension,
-+ * [6] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ * }
-+ */
-+struct roseQsigPartyName_ARG {
-+ struct roseQsigName name;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * Time ::= SEQUENCE {
-+ * lengthOfTimeUnit [1] IMPLICIT LengthOfTimeUnit,
-+ * scale [2] IMPLICIT Scale
-+ * }
-+ */
-+struct roseQsigAOCTime {
-+ /*! LengthOfTimeUnit ::= INTEGER (0..16777215) -- 24 bit number */
-+ u_int32_t length;
-+ /*!
-+ * \details
-+ * oneHundredthSecond(0),
-+ * oneTenthSecond(1),
-+ * oneSecond(2),
-+ * tenSeconds(3),
-+ * oneMinute(4),
-+ * oneHour(5),
-+ * twentyFourHours(6)
-+ */
-+ u_int8_t scale;
-+};
-+
-+/*
-+ * Amount ::= SEQUENCE {
-+ * currencyAmount [1] IMPLICIT CurrencyAmount,
-+ * multiplier [2] IMPLICIT Multiplier
-+ * }
-+ */
-+struct roseQsigAOCAmount {
-+ /*! CurrencyAmount ::= INTEGER (0..16777215) -- 24 bit number */
-+ u_int32_t currency;
-+ /*!
-+ * \details
-+ * oneThousandth(0),
-+ * oneHundredth(1),
-+ * oneTenth(2),
-+ * one(3),
-+ * ten(4),
-+ * hundred(5),
-+ * thousand(6)
-+ */
-+ u_int8_t multiplier;
-+};
-+
-+/*
-+ * DurationCurrency ::= SEQUENCE {
-+ * dCurrency [1] IMPLICIT Currency,
-+ * dAmount [2] IMPLICIT Amount,
-+ * dChargingType [3] IMPLICIT ChargingType,
-+ * dTime [4] IMPLICIT Time,
-+ * dGranularity [5] IMPLICIT Time OPTIONAL
-+ * }
-+ */
-+struct roseQsigAOCDurationCurrency {
-+ struct roseQsigAOCAmount amount;
-+ struct roseQsigAOCTime time;
-+ /*! \brief dGranularity (optional) */
-+ struct roseQsigAOCTime granularity;
-+ /*!
-+ * \brief Name of currency
-+ * \details
-+ * Currency ::= IA5String (SIZE (0..10))
-+ * \note The empty string is the default currency for the network.
-+ */
-+ unsigned char currency[10 + 1];
-+ /*!
-+ * \details
-+ * continuousCharging(0),
-+ * stepFunction(1)
-+ */
-+ u_int8_t charging_type;
-+ /*! TRUE if granularity time is present */
-+ u_int8_t granularity_present;
-+};
-+
-+/*
-+ * FlatRateCurrency ::= SEQUENCE {
-+ * fRCurrency [1] IMPLICIT Currency,
-+ * fRAmount [2] IMPLICIT Amount
-+ * }
-+ */
-+struct roseQsigAOCFlatRateCurrency {
-+ struct roseQsigAOCAmount amount;
-+ /*!
-+ * \brief Name of currency
-+ * \details
-+ * Currency ::= IA5String (SIZE (0..10))
-+ * \note The empty string is the default currency for the network.
-+ */
-+ unsigned char currency[10 + 1];
-+};
-+
-+/*
-+ * VolumeRateCurrency ::= SEQUENCE {
-+ * vRCurrency [1] IMPLICIT Currency,
-+ * vRAmount [2] IMPLICIT Amount,
-+ * vRVolumeUnit [3] IMPLICIT VolumeUnit
-+ * }
-+ */
-+struct roseQsigAOCVolumeRateCurrency {
-+ struct roseQsigAOCAmount amount;
-+ /*!
-+ * \brief Name of currency
-+ * \details
-+ * Currency ::= IA5String (SIZE (0..10))
-+ * \note The empty string is the default currency for the network.
-+ */
-+ unsigned char currency[10 + 1];
-+ /*!
-+ * \brief Volume rate volume unit
-+ * \details
-+ * octet(0),
-+ * segment(1),
-+ * message(2)
-+ */
-+ u_int8_t unit;
-+};
-+
-+/*
-+ * AOCSCurrencyInfo ::= SEQUENCE {
-+ * chargedItem ChargedItem,
-+ * rateType CHOICE {
-+ * durationCurrency [1] IMPLICIT DurationCurrency,
-+ * flatRateCurrency [2] IMPLICIT FlatRateCurrency,
-+ * volumeRateCurrency [3] IMPLICIT VolumeRateCurrency,
-+ * specialChargingCode SpecialChargingCode,
-+ * freeOfCharge [4] IMPLICIT NULL,
-+ * currencyInfoNotAvailable [5] IMPLICIT NULL,
-+ * freeOfChargefromBeginning [6] IMPLICIT NULL
-+ * }
-+ * }
-+ */
-+struct roseQsigAOCSCurrencyInfo {
-+ union {
-+ struct roseQsigAOCDurationCurrency duration;
-+ struct roseQsigAOCFlatRateCurrency flat_rate;
-+ struct roseQsigAOCVolumeRateCurrency volume_rate;
-+ /*! SpecialChargingCode ::= INTEGER (1..10) */
-+ u_int8_t special_charging_code;
-+ } u;
-+ /*!
-+ * \brief Determine what is stored in the union.
-+ * \details
-+ * specialChargingCode(0),
-+ * durationCurrency(1),
-+ * flatRateCurrency(2),
-+ * volumeRateCurrency(3),
-+ * freeOfCharge(4),
-+ * currencyInfoNotAvailable(5),
-+ * freeOfChargeFromBeginning(6)
-+ */
-+ u_int8_t currency_type;
-+ /*!
-+ * \brief What service is being billed.
-+ * \details
-+ * basicCommunication(0),
-+ * callAttempt(1),
-+ * callSetup(2),
-+ * userToUserInfo(3),
-+ * operationOfSupplementaryServ(4)
-+ */
-+ u_int8_t charged_item;
-+};
-+
-+/*
-+ * AOCSCurrencyInfoList ::= SEQUENCE SIZE (1..10) OF AOCSCurrencyInfo
-+ */
-+struct roseQsigAOCSCurrencyInfoList {
-+ /*! \brief SEQUENCE SIZE (1..10) OF AOCSCurrencyInfo */
-+ struct roseQsigAOCSCurrencyInfo list[10];
-+
-+ /*! \brief Number of AOCSCurrencyInfo records present */
-+ u_int8_t num_records;
-+};
-+
-+/*
-+ * RecordedCurrency ::= SEQUENCE {
-+ * rCurrency [1] IMPLICIT Currency,
-+ * rAmount [2] IMPLICIT Amount
-+ * }
-+ */
-+struct roseQsigAOCRecordedCurrency {
-+ /*! Amount of currency involved. */
-+ struct roseQsigAOCAmount amount;
-+ /*!
-+ * \brief Name of currency
-+ * \details
-+ * Currency ::= IA5String (SIZE (0..10))
-+ * \note The empty string is the default currency for the network.
-+ */
-+ unsigned char currency[10 + 1];
-+};
-+
-+/*
-+ * ChargingAssociation ::= CHOICE {
-+ * chargedNumber [0] EXPLICIT PartyNumber,
-+ * chargeIdentifier ChargeIdentifier
-+ * }
-+ */
-+struct roseQsigAOCChargingAssociation {
-+ /*! chargeIdentifier: INTEGER (-32768..32767) -- 16 bit number */
-+ int16_t id;
-+ /*! chargedNumber */
-+ struct rosePartyNumber number;
-+ /*!
-+ * \details
-+ * charge_identifier(0)
-+ * charged_number(1),
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * AocRateArg ::= SEQUENCE {
-+ * aocRate CHOICE
-+ * {
-+ * chargeNotAvailable NULL,
-+ * aocSCurrencyInfoList AOCSCurrencyInfoList
-+ * },
-+ * rateArgExtension CHOICE {
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigAocRateArg_ARG {
-+ struct roseQsigAOCSCurrencyInfoList currency_info;
-+ /*!
-+ * \details
-+ * charge_not_available(0),
-+ * currency_info_list(1)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * AocInterimArg ::= SEQUENCE {
-+ * interimCharge CHOICE {
-+ * chargeNotAvailable [0] IMPLICIT NULL,
-+ * freeOfCharge [1] IMPLICIT NULL,
-+ * specificCurrency SEQUENCE {
-+ * recordedCurrency [1] IMPLICIT RecordedCurrency,
-+ * interimBillingId [2] IMPLICIT InterimBillingId OPTIONAL
-+ * }
-+ * },
-+ * interimArgExtension CHOICE {
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigAocInterimArg_ARG {
-+ struct {
-+ /*! \brief recorded currency */
-+ struct roseQsigAOCRecordedCurrency recorded;
-+ /*!
-+ * \brief InterimBillingId (optional)
-+ * \details
-+ * normalCharging(0),
-+ * creditCardCharging(2)
-+ */
-+ u_int8_t billing_id;
-+ /*! \brief TRUE if billing id is present */
-+ u_int8_t billing_id_present;
-+ } specific;
-+ /*!
-+ * \details
-+ * charge_not_available(0),
-+ * free_of_charge(1),
-+ * specific_currency(2)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * AocFinalArg ::= SEQUENCE {
-+ * finalCharge CHOICE {
-+ * chargeNotAvailable [0] IMPLICIT NULL,
-+ * freeOfCharge [1] IMPLICIT NULL,
-+ * specificCurrency SEQUENCE {
-+ * recordedCurrency [1] IMPLICIT RecordedCurrency,
-+ * finalBillingId [2] IMPLICIT FinalBillingId OPTIONAL
-+ * }
-+ * },
-+ * chargingAssociation ChargingAssociation OPTIONAL,
-+ * finalArgExtension CHOICE {
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigAocFinalArg_ARG {
-+ struct {
-+ /*! \brief recorded currency */
-+ struct roseQsigAOCRecordedCurrency recorded;
-+ /*!
-+ * \brief FinalBillingId (optional)
-+ * \details
-+ * normalCharging(0),
-+ * creditCardCharging(2),
-+ * callForwardingUnconditional(3),
-+ * callForwardingBusy(4),
-+ * callForwardingNoReply(5),
-+ * callDeflection(6),
-+ * callTransfer(7)
-+ */
-+ u_int8_t billing_id;
-+ /*! \brief TRUE if billing id is present */
-+ u_int8_t billing_id_present;
-+ } specific;
-+
-+ /*! \brief chargingAssociation (optional) */
-+ struct roseQsigAOCChargingAssociation charging_association;
-+
-+ /*! \brief TRUE if charging_association is present */
-+ u_int8_t charging_association_present;
-+
-+ /*!
-+ * \details
-+ * charge_not_available(0),
-+ * free_of_charge(1),
-+ * specific_currency(2)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * ChargeRequestArg ::= SEQUENCE {
-+ * adviceModeCombinations SEQUENCE SIZE(0..7) OF AdviceModeCombination,
-+ * chargeReqArgExtension CHOICE {
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigChargeRequestArg_ARG {
-+ /*!
-+ * \brief SEQUENCE SIZE(0..7) OF AdviceModeCombination
-+ * \details
-+ * rate(0) <charge rate provision>,
-+ * rateInterim(1) <charge rate and interim charge provision>,
-+ * rateFinal(2) <charge rate and final charge provision>,
-+ * interim(3) <interim charge provision>,
-+ * final(4) <final charge provision>,
-+ * interimFinal(5) <interim charge and final charge provision>,
-+ * rateInterimFinal(6) <charge rate, interim charge and final charge provision>
-+ */
-+ u_int8_t advice_mode_combinations[7];
-+
-+ /*! \brief Number of AdviceModeCombination values present */
-+ u_int8_t num_records;
-+};
-+
-+/*
-+ * ChargeRequestRes ::= SEQUENCE {
-+ * adviceModeCombination AdviceModeCombination,
-+ * chargeReqResExtension CHOICE {
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigChargeRequestRes_RES {
-+ /*!
-+ * \details
-+ * rate(0) <charge rate provision>,
-+ * rateInterim(1) <charge rate and interim charge provision>,
-+ * rateFinal(2) <charge rate and final charge provision>,
-+ * interim(3) <interim charge provision>,
-+ * final(4) <final charge provision>,
-+ * interimFinal(5) <interim charge and final charge provision>,
-+ * rateInterimFinal(6) <charge rate, interim charge and final charge provision>
-+ */
-+ u_int8_t advice_mode_combination;
-+};
-+
-+/*
-+ * AocCompleteArg ::= SEQUENCE {
-+ * chargedUser PartyNumber,
-+ * chargingAssociation ChargingAssociation OPTIONAL,
-+ * completeArgExtension CHOICE {
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigAocCompleteArg_ARG {
-+ /*! \brief chargingAssociation (optional) */
-+ struct roseQsigAOCChargingAssociation charging_association;
-+
-+ struct rosePartyNumber charged_user_number;
-+
-+ /*! \brief TRUE if charging_association is present */
-+ u_int8_t charging_association_present;
-+};
-+
-+/*
-+ * AocCompleteRes ::= SEQUENCE {
-+ * chargingOption ChargingOption,
-+ * completeResExtension CHOICE {
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigAocCompleteRes_RES {
-+ /*!
-+ * \details
-+ * aocFreeOfCharge(0),
-+ * aocContinueCharging(1),
-+ * aocStopCharging(2)
-+ */
-+ u_int8_t charging_option;
-+};
-+
-+/*
-+ * AocDivChargeReqArg ::= SEQUENCE {
-+ * divertingUser PartyNumber,
-+ * chargingAssociation ChargingAssociation OPTIONAL,
-+ * diversionType DiversionType,
-+ * aocDivChargeReqArgExt CHOICE {
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigAocDivChargeReqArg_ARG {
-+ /*! \brief chargingAssociation (optional) */
-+ struct roseQsigAOCChargingAssociation charging_association;
-+
-+ struct rosePartyNumber diverting_user_number;
-+
-+ /*! \brief TRUE if charging_association is present */
-+ u_int8_t charging_association_present;
-+
-+ /*!
-+ * \details
-+ * callForwardingUnconditional(0),
-+ * callForwardingBusy(1),
-+ * callForwardingNoReply(2),
-+ * callDeflection(3)
-+ */
-+ u_int8_t diversion_type;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * CTIdentifyRes ::= SEQUENCE {
-+ * callIdentity CallIdentity,
-+ * reroutingNumber PartyNumber,
-+ * resultExtension CHOICE {
-+ * [6] IMPLICIT Extension,
-+ * [7] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigCTIdentifyRes_RES {
-+ struct rosePartyNumber rerouting_number;
-+
-+ /*! \brief CallIdentity ::= NumericString (SIZE (1..4)) */
-+ unsigned char call_id[4 + 1];
-+};
-+
-+/*
-+ * CTInitiateArg ::= SEQUENCE {
-+ * callIdentity CallIdentity,
-+ * reroutingNumber PartyNumber,
-+ * argumentExtension CHOICE {
-+ * [6] IMPLICIT Extension,
-+ * [7] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigCTInitiateArg_ARG {
-+ struct rosePartyNumber rerouting_number;
-+
-+ /*! \brief CallIdentity ::= NumericString (SIZE (1..4)) */
-+ unsigned char call_id[4 + 1];
-+};
-+
-+/*
-+ * CTSetupArg ::= SEQUENCE {
-+ * callIdentity CallIdentity,
-+ * argumentExtension CHOICE {
-+ * [0] IMPLICIT Extension,
-+ * [1] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigCTSetupArg_ARG {
-+ /*! \brief CallIdentity ::= NumericString (SIZE (1..4)) */
-+ unsigned char call_id[4 + 1];
-+};
-+
-+/*
-+ * CTActiveArg ::= SEQUENCE {
-+ * connectedAddress PresentedAddressScreened,
-+ *
-+ * -- ISO/IEC 11572 information elements Party
-+ * -- category and Progress indicator are conveyed
-+ * basicCallInfoElements PSS1InformationElement OPTIONAL,
-+ * connectedName Name OPTIONAL,
-+ * argumentExtension CHOICE {
-+ * [9] IMPLICIT Extension,
-+ * [10] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigCTActiveArg_ARG {
-+ /*! \brief connectedAddress */
-+ struct rosePresentedAddressScreened connected;
-+
-+ /*! \brief basicCallInfoElements (optional) */
-+ struct roseQ931ie q931ie;
-+ /*! \brief q931ie.contents "allocated" after the stucture. */
-+ unsigned char q931ie_contents[ROSE_Q931_MAX_PROGRESS + 1];
-+
-+ /*! \brief connectedName (optional) */
-+ struct roseQsigName connected_name;
-+
-+ /*! \brief TRUE if connected_name is present */
-+ u_int8_t connected_name_present;
-+};
-+
-+/*
-+ * CTCompleteArg ::= SEQUENCE {
-+ * endDesignation EndDesignation,
-+ * redirectionNumber PresentedNumberScreened,
-+ *
-+ * -- ISO/IEC 11572 information elements Party
-+ * -- category and Progress indicator are conveyed
-+ * basicCallInfoElements PSS1InformationElement OPTIONAL,
-+ * redirectionName Name OPTIONAL,
-+ * callStatus CallStatus DEFAULT answered,
-+ * argumentExtension CHOICE {
-+ * [9] IMPLICIT Extension,
-+ * [10] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigCTCompleteArg_ARG {
-+ /*! \brief redirectionNumber */
-+ struct rosePresentedNumberScreened redirection;
-+
-+ /*! \brief basicCallInfoElements (optional) */
-+ struct roseQ931ie q931ie;
-+ /*! \brief q931ie.contents "allocated" after the stucture. */
-+ unsigned char q931ie_contents[ROSE_Q931_MAX_PROGRESS + 1];
-+
-+ /*! \brief redirectionName (optional) */
-+ struct roseQsigName redirection_name;
-+
-+ /*! \brief TRUE if redirection_name is present */
-+ u_int8_t redirection_name_present;
-+
-+ /*!
-+ * \brief endDesignation
-+ * \details
-+ * primaryEnd(0),
-+ * secondaryEnd(1)
-+ */
-+ u_int8_t end_designation;
-+
-+ /*!
-+ * \brief callStatus
-+ * \details
-+ * DEFAULT answered
-+ *
-+ * \details
-+ * answered(0),
-+ * alerting(1)
-+ */
-+ u_int8_t call_status;
-+};
-+
-+/*
-+ * CTUpdateArg ::= SEQUENCE {
-+ * redirectionNumber PresentedNumberScreened,
-+ * redirectionName Name OPTIONAL,
-+ *
-+ * -- ISO/IEC 11572 information elements Party
-+ * -- category and Progress indicator are conveyed
-+ * basicCallInfoElements PSS1InformationElement OPTIONAL,
-+ * argumentExtension CHOICE {
-+ * [9] IMPLICIT Extension,
-+ * [10] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigCTUpdateArg_ARG {
-+ /*! \brief redirectionNumber */
-+ struct rosePresentedNumberScreened redirection;
-+
-+ /*! \brief basicCallInfoElements (optional) */
-+ struct roseQ931ie q931ie;
-+ /*! \brief q931ie.contents "allocated" after the stucture. */
-+ unsigned char q931ie_contents[ROSE_Q931_MAX_PROGRESS + 1];
-+
-+ /*! \brief redirectionName (optional) */
-+ struct roseQsigName redirection_name;
-+
-+ /*! \brief TRUE if redirection_name is present */
-+ u_int8_t redirection_name_present;
-+};
-+
-+/*
-+ * SubaddressTransferArg ::= SEQUENCE {
-+ * redirectionSubaddress PartySubaddress,
-+ * argumentExtension CHOICE {
-+ * [0] IMPLICIT Extension,
-+ * [1] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigSubaddressTransferArg_ARG {
-+ struct rosePartySubaddress redirection_subaddress;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * IntResult ::= SEQUENCE {
-+ * servedUserNr PartyNumber,
-+ * basicService BasicService,
-+ * procedure Procedure,
-+ * divertedToAddress Address,
-+ * remoteEnabled BOOLEAN DEFAULT FALSE,
-+ * extension CHOICE {
-+ * [1] IMPLICIT Extension,
-+ * [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigForwardingRecord {
-+ /*! \brief Diverted to address */
-+ struct roseAddress diverted_to;
-+
-+ struct rosePartyNumber served_user_number;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3100Hz(3),
-+ * telephony(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36)
-+ */
-+ u_int8_t basic_service;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*! \brief remoteEnabled BOOLEAN DEFAULT FALSE */
-+ u_int8_t remote_enabled;
-+};
-+
-+/*
-+ * roseQsigInterrogateDiversionQ_REQ
-+ * IntResultList ::= SET SIZE (0..29) OF IntResult
-+ */
-+struct roseQsigForwardingList {
-+ /*!
-+ * \brief SET SIZE (0..29) OF Forwarding Records
-+ * \note Reduced the size of the array to conserve
-+ * potential stack usage.
-+ */
-+ struct roseQsigForwardingRecord list[10];
-+
-+ /*! \brief Number of Forwarding records present */
-+ u_int8_t num_records;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * procedure Procedure,
-+ * basicService BasicService,
-+ * divertedToAddress Address,
-+ * servedUserNr PartyNumber,
-+ * activatingUserNr PartyNumber,
-+ * extension CHOICE {
-+ * [1] IMPLICIT Extension,
-+ * [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigActivateDiversionQ_ARG {
-+ /*! \brief divertedToAddress */
-+ struct roseAddress diverted_to;
-+
-+ struct rosePartyNumber served_user_number;
-+ struct rosePartyNumber activating_user_number;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3100Hz(3),
-+ * telephony(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * procedure Procedure,
-+ * basicService BasicService,
-+ * servedUserNr PartyNumber,
-+ * deactivatingUserNr PartyNumber,
-+ * extension CHOICE {
-+ * [1] IMPLICIT Extension,
-+ * [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigDeactivateDiversionQ_ARG {
-+ struct rosePartyNumber served_user_number;
-+ struct rosePartyNumber deactivating_user_number;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3100Hz(3),
-+ * telephony(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * procedure Procedure,
-+ * basicService BasicService DEFAULT allServices,
-+ * servedUserNr PartyNumber,
-+ * interrogatingUserNr PartyNumber,
-+ * extension CHOICE {
-+ * [1] IMPLICIT Extension,
-+ * [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigInterrogateDiversionQ_ARG {
-+ struct rosePartyNumber served_user_number;
-+ struct rosePartyNumber interrogating_user_number;
-+
-+ /*! \details cfu(0), cfb(1), cfnr(2) */
-+ u_int8_t procedure;
-+
-+ /*!
-+ * \details
-+ * DEFAULT allServices
-+ *
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3100Hz(3),
-+ * telephony(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * servedUserNr PartyNumber,
-+ * basicService BasicService,
-+ * divertedToNr PartyNumber,
-+ * extension CHOICE {
-+ * [1] IMPLICIT Extension,
-+ * [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigCheckRestriction_ARG {
-+ struct rosePartyNumber served_user_number;
-+ struct rosePartyNumber diverted_to_number;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3100Hz(3),
-+ * telephony(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotexSyntaxBased(35),
-+ * videotelephony(36)
-+ */
-+ u_int8_t basic_service;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * reroutingReason DiversionReason,
-+ * originalReroutingReason [0] IMPLICIT DiversionReason OPTIONAL,
-+ * calledAddress Address,
-+ * diversionCounter INTEGER (1..15),
-+ *
-+ * -- The basic call information elements Bearer capability,
-+ * -- High layer compatibility, Low layer compatibity
-+ * -- and Progress indicator can be embedded in the
-+ * -- pSS1InfoElement in accordance with 6.5.3.1.5.
-+ * pSS1InfoElement PSS1InformationElement,
-+ * lastReroutingNr [1] EXPLICIT PresentedNumberUnscreened,
-+ * subscriptionOption [2] IMPLICIT SubscriptionOption,
-+ * callingPartySubaddress [3] EXPLICIT PartySubaddress OPTIONAL,
-+ * callingNumber [4] EXPLICIT PresentedNumberScreened,
-+ * callingName [5] EXPLICIT Name OPTIONAL,
-+ * originalCalledNr [6] EXPLICIT PresentedNumberUnscreened OPTIONAL,
-+ * redirectingName [7] EXPLICIT Name OPTIONAL,
-+ * originalCalledName [8] EXPLICIT Name OPTIONAL,
-+ * extension CHOICE {
-+ * [9] IMPLICIT Extension,
-+ * [10] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigCallRerouting_ARG {
-+ /*! \brief calledAddress */
-+ struct roseAddress called;
-+
-+ /*! \brief lastReroutingNr */
-+ struct rosePresentedNumberUnscreened last_rerouting;
-+
-+ /*! \brief originalCalledNr (optional) */
-+ struct rosePresentedNumberUnscreened original_called;
-+
-+ /*!
-+ * \brief callingPartySubaddress (optional)
-+ * The subaddress is present if the length is nonzero.
-+ */
-+ struct rosePartySubaddress calling_subaddress;
-+
-+ /*! \brief callingNumber */
-+ struct rosePresentedNumberScreened calling;
-+
-+ /*! \brief callingName (optional) */
-+ struct roseQsigName calling_name;
-+
-+ /*! \brief redirectingName (optional) */
-+ struct roseQsigName redirecting_name;
-+
-+ /*! \brief originalCalledName (optional) */
-+ struct roseQsigName original_called_name;
-+
-+ /*!
-+ * \brief The BC, HLC (optional), LLC (optional),
-+ * and progress indicator(s) information.
-+ */
-+ struct roseQ931ie q931ie;
-+ /*! \brief q931ie.contents "allocated" after the stucture. */
-+ unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
-+ ROSE_Q931_MAX_LLC + ROSE_Q931_MAX_PROGRESS + 1];
-+
-+ /*! \brief TRUE if calling_name is present */
-+ u_int8_t calling_name_present;
-+
-+ /*! \brief TRUE if redirecting_name is present */
-+ u_int8_t redirecting_name_present;
-+
-+ /*! \brief TRUE if original_called_name is present */
-+ u_int8_t original_called_name_present;
-+
-+ /*! \brief TRUE if original_called number is present */
-+ u_int8_t original_called_present;
-+
-+ /*!
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3)
-+ *
-+ * \note The value unknown is only used if received from
-+ * another network when interworking.
-+ */
-+ u_int8_t rerouting_reason;
-+
-+ /*!
-+ * \brief originalReroutingReason (optional)
-+ *
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3)
-+ *
-+ * \note The value unknown is only used if received from
-+ * another network when interworking.
-+ */
-+ u_int8_t original_rerouting_reason;
-+
-+ /*! \brief TRUE if original_rerouting_reason is present */
-+ u_int8_t original_rerouting_reason_present;
-+
-+ /*! \brief diversionCounter INTEGER (1..15) */
-+ u_int8_t diversion_counter;
-+
-+ /*!
-+ * \brief subscriptionOption
-+ *
-+ * \details
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ */
-+ u_int8_t subscription_option;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * diversionReason DiversionReason,
-+ * subscriptionOption SubscriptionOption,
-+ * nominatedNr PartyNumber,
-+ * extension CHOICE {
-+ * [9] IMPLICIT Extension,
-+ * [10] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigDivertingLegInformation1_ARG {
-+ struct rosePartyNumber nominated_number;
-+
-+ /*!
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3)
-+ *
-+ * \note The value unknown is only used if received from
-+ * another network when interworking.
-+ */
-+ u_int8_t diversion_reason;
-+
-+ /*!
-+ * \brief subscriptionOption
-+ *
-+ * \details
-+ * noNotification(0),
-+ * notificationWithoutDivertedToNr(1),
-+ * notificationWithDivertedToNr(2)
-+ */
-+ u_int8_t subscription_option;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * diversionCounter INTEGER (1..15),
-+ * diversionReason DiversionReason,
-+ * originalDiversionReason [0] IMPLICIT DiversionReason OPTIONAL,
-+ *
-+ * -- The divertingNr element is mandatory except in the case
-+ * -- of interworking.
-+ * divertingNr [1] EXPLICIT PresentedNumberUnscreened OPTIONAL,
-+ * originalCalledNr [2] EXPLICIT PresentedNumberUnscreened OPTIONAL,
-+ * redirectingName [3] EXPLICIT Name OPTIONAL,
-+ * originalCalledName [4] EXPLICIT Name OPTIONAL,
-+ * extension CHOICE {
-+ * [5] IMPLICIT Extension,
-+ * [6] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigDivertingLegInformation2_ARG {
-+ /*! \brief divertingNr (optional) */
-+ struct rosePresentedNumberUnscreened diverting;
-+
-+ /*! \brief originalCalledNr (optional) */
-+ struct rosePresentedNumberUnscreened original_called;
-+
-+ /*! \brief redirectingName (optional) */
-+ struct roseQsigName redirecting_name;
-+
-+ /*! \brief originalCalledName (optional) */
-+ struct roseQsigName original_called_name;
-+
-+ /*! \brief diversionCounter INTEGER (1..15) */
-+ u_int8_t diversion_counter;
-+
-+ /*!
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3)
-+ *
-+ * \note The value unknown is only used if received from
-+ * another network when interworking.
-+ */
-+ u_int8_t diversion_reason;
-+
-+ /*!
-+ * \brief originalDiversionReason (optional)
-+ *
-+ * \details
-+ * unknown(0),
-+ * cfu(1),
-+ * cfb(2),
-+ * cfnr(3)
-+ *
-+ * \note The value unknown is only used if received from
-+ * another network when interworking.
-+ */
-+ u_int8_t original_diversion_reason;
-+
-+ /*! \brief TRUE if original_diversion_reason is present */
-+ u_int8_t original_diversion_reason_present;
-+
-+ /*! \brief TRUE if diverting number is present */
-+ u_int8_t diverting_present;
-+
-+ /*! \brief TRUE if original_called number is present */
-+ u_int8_t original_called_present;
-+
-+ /*! \brief TRUE if redirecting_name is present */
-+ u_int8_t redirecting_name_present;
-+
-+ /*! \brief TRUE if original_called_name is present */
-+ u_int8_t original_called_name_present;
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * presentationAllowedIndicator PresentationAllowedIndicator, -- BOOLEAN
-+ * redirectionName [0] EXPLICIT Name OPTIONAL,
-+ * extension CHOICE {
-+ * [1] IMPLICIT Extension,
-+ * [2] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigDivertingLegInformation3_ARG {
-+ /*! \brief redirectionName (optional) */
-+ struct roseQsigName redirection_name;
-+
-+ /*! \brief TRUE if redirection_name is present */
-+ u_int8_t redirection_name_present;
-+
-+ /*! \brief TRUE if presentation is allowed */
-+ u_int8_t presentation_allowed_indicator;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * MsgCentreId ::= CHOICE {
-+ * integer [0] IMPLICIT INTEGER (0..65535),
-+ *
-+ * -- The party number must be a complete number as required
-+ * -- for routing purposes.
-+ * partyNumber [1] EXPLICIT PartyNumber,
-+ * numericString [2] IMPLICIT NumericString (SIZE (1..10))
-+ * }
-+ */
-+struct roseQsigMsgCentreId {
-+ union {
-+ /*! \brief INTEGER (0..65535) */
-+ u_int16_t integer;
-+
-+ /*!
-+ * \note The party number must be a complete number as required
-+ * for routing purposes.
-+ */
-+ struct rosePartyNumber number;
-+
-+ /*! \brief NumericString (SIZE (1..10)) */
-+ unsigned char str[10 + 1];
-+ } u;
-+
-+ /*!
-+ * \details
-+ * integer(0),
-+ * partyNumber(1),
-+ * numericString(2)
-+ */
-+ u_int8_t type;
-+};
-+
-+/*
-+ * MWIActivateArg ::= SEQUENCE {
-+ * servedUserNr PartyNumber,
-+ * basicService BasicService,
-+ * msgCentreId MsgCentreId OPTIONAL,
-+ * nbOfMessages [3] IMPLICIT NbOfMessages OPTIONAL,
-+ * originatingNr [4] EXPLICIT PartyNumber OPTIONAL,
-+ * timestamp TimeStamp OPTIONAL,
-+ *
-+ * -- The value 0 means the highest priority and 9 the lowest
-+ * priority [5] IMPLICIT INTEGER (0..9) OPTIONAL,
-+ * argumentExt CHOICE {
-+ * extension [6] IMPLICIT Extension,
-+ * multipleExtension [7] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigMWIActivateArg {
-+ /*! \brief NbOfMessages ::= INTEGER (0..65535) (optional) */
-+ u_int16_t number_of_messages;
-+
-+ /*! \brief msgCentreId (optional) */
-+ struct roseQsigMsgCentreId msg_centre_id;
-+
-+ struct rosePartyNumber served_user_number;
-+
-+ /*! \brief originatingNr (optional) (Number present if length is nonzero) */
-+ struct rosePartyNumber originating_number;
-+
-+ /*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
-+ unsigned char timestamp[19 + 1];
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3100Hz(3),
-+ * telephony(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotextSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * reservedNotUsed1(38),
-+ * reservedNotUsed2(39),
-+ * reservedNotUsed3(40),
-+ * reservedNotUsed4(41),
-+ * reservedNotUsed5(42),
-+ * email(51),
-+ * video(52),
-+ * fileTransfer(53),
-+ * shortMessageService(54),
-+ * speechAndVideo(55),
-+ * speechAndFax(56),
-+ * speechAndEmail(57),
-+ * videoAndFax(58),
-+ * videoAndEmail(59),
-+ * faxAndEmail(60),
-+ * speechVideoAndFax(61),
-+ * speechVideoAndEmail(62),
-+ * speechFaxAndEmail(63),
-+ * videoFaxAndEmail(64),
-+ * speechVideoFaxAndEmail(65),
-+ * multimediaUnknown(66),
-+ * serviceUnknown(67),
-+ * futureReserve1(68),
-+ * futureReserve2(69),
-+ * futureReserve3(70),
-+ * futureReserve4(71),
-+ * futureReserve5(72),
-+ * futureReserve6(73),
-+ * futureReserve7(74),
-+ * futureReserve8(75)
-+ */
-+ u_int8_t basic_service;
-+
-+ /*!
-+ * \brief INTEGER (0..9) (optional)
-+ * \note The value 0 means the highest priority and 9 the lowest.
-+ */
-+ u_int8_t priority;
-+
-+ /*! \brief TRUE if msg_centre_id is present */
-+ u_int8_t msg_centre_id_present;
-+
-+ /*! \brief TRUE if number_of_messages is present */
-+ u_int8_t number_of_messages_present;
-+
-+ /*! \brief TRUE if timestamp is present */
-+ u_int8_t timestamp_present;
-+
-+ /*! \brief TRUE if priority is present */
-+ u_int8_t priority_present;
-+};
-+
-+/*
-+ * MWIDeactivateArg ::= SEQUENCE {
-+ * servedUserNr PartyNumber,
-+ * basicService BasicService,
-+ * msgCentreId MsgCentreId OPTIONAL,
-+ * argumentExt CHOICE {
-+ * extension [3] IMPLICIT Extension,
-+ * multipleExtension [4] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigMWIDeactivateArg {
-+ /*! \brief msgCentreId (optional) */
-+ struct roseQsigMsgCentreId msg_centre_id;
-+
-+ struct rosePartyNumber served_user_number;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3100Hz(3),
-+ * telephony(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotextSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * reservedNotUsed1(38),
-+ * reservedNotUsed2(39),
-+ * reservedNotUsed3(40),
-+ * reservedNotUsed4(41),
-+ * reservedNotUsed5(42),
-+ * email(51),
-+ * video(52),
-+ * fileTransfer(53),
-+ * shortMessageService(54),
-+ * speechAndVideo(55),
-+ * speechAndFax(56),
-+ * speechAndEmail(57),
-+ * videoAndFax(58),
-+ * videoAndEmail(59),
-+ * faxAndEmail(60),
-+ * speechVideoAndFax(61),
-+ * speechVideoAndEmail(62),
-+ * speechFaxAndEmail(63),
-+ * videoFaxAndEmail(64),
-+ * speechVideoFaxAndEmail(65),
-+ * multimediaUnknown(66),
-+ * serviceUnknown(67),
-+ * futureReserve1(68),
-+ * futureReserve2(69),
-+ * futureReserve3(70),
-+ * futureReserve4(71),
-+ * futureReserve5(72),
-+ * futureReserve6(73),
-+ * futureReserve7(74),
-+ * futureReserve8(75)
-+ */
-+ u_int8_t basic_service;
-+
-+ /*! \brief TRUE if msg_centre_id is present */
-+ u_int8_t msg_centre_id_present;
-+};
-+
-+/*
-+ * MWIInterrogateArg ::= SEQUENCE {
-+ * servedUserNr PartyNumber,
-+ * basicService BasicService,
-+ * msgCentreId MsgCentreId OPTIONAL,
-+ * argumentExt CHOICE {
-+ * extension [3] IMPLICIT Extension,
-+ * multipleExtension [4] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigMWIInterrogateArg {
-+ /*! \brief msgCentreId (optional) */
-+ struct roseQsigMsgCentreId msg_centre_id;
-+
-+ struct rosePartyNumber served_user_number;
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3100Hz(3),
-+ * telephony(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotextSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * reservedNotUsed1(38),
-+ * reservedNotUsed2(39),
-+ * reservedNotUsed3(40),
-+ * reservedNotUsed4(41),
-+ * reservedNotUsed5(42),
-+ * email(51),
-+ * video(52),
-+ * fileTransfer(53),
-+ * shortMessageService(54),
-+ * speechAndVideo(55),
-+ * speechAndFax(56),
-+ * speechAndEmail(57),
-+ * videoAndFax(58),
-+ * videoAndEmail(59),
-+ * faxAndEmail(60),
-+ * speechVideoAndFax(61),
-+ * speechVideoAndEmail(62),
-+ * speechFaxAndEmail(63),
-+ * videoFaxAndEmail(64),
-+ * speechVideoFaxAndEmail(65),
-+ * multimediaUnknown(66),
-+ * serviceUnknown(67),
-+ * futureReserve1(68),
-+ * futureReserve2(69),
-+ * futureReserve3(70),
-+ * futureReserve4(71),
-+ * futureReserve5(72),
-+ * futureReserve6(73),
-+ * futureReserve7(74),
-+ * futureReserve8(75)
-+ */
-+ u_int8_t basic_service;
-+
-+ /*! \brief TRUE if msg_centre_id is present */
-+ u_int8_t msg_centre_id_present;
-+};
-+
-+/*
-+ * MWIInterrogateResElt ::= SEQUENCE {
-+ * basicService BasicService,
-+ * msgCentreId MsgCentreId OPTIONAL,
-+ * nbOfMessages [3] IMPLICIT NbOfMessages OPTIONAL,
-+ * originatingNr [4] EXPLICIT PartyNumber OPTIONAL,
-+ * timestamp TimeStamp OPTIONAL,
-+ *
-+ * -- The value 0 means the highest priority and 9 the lowest
-+ * priority [5] IMPLICIT INTEGER (0..9) OPTIONAL,
-+ * argumentExt CHOICE {
-+ * extension [6] IMPLICIT Extension,
-+ * multipleExtension [7] IMPLICIT SEQUENCE OF Extension
-+ * } OPTIONAL
-+ * }
-+ */
-+struct roseQsigMWIInterrogateResElt {
-+ /*! \brief NbOfMessages ::= INTEGER (0..65535) (optional) */
-+ u_int16_t number_of_messages;
-+
-+ /*! \brief msgCentreId (optional) */
-+ struct roseQsigMsgCentreId msg_centre_id;
-+
-+ /*! \brief originatingNr (optional) (Number present if length is nonzero) */
-+ struct rosePartyNumber originating_number;
-+
-+ /*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
-+ unsigned char timestamp[19 + 1];
-+
-+ /*!
-+ * \details
-+ * allServices(0),
-+ * speech(1),
-+ * unrestrictedDigitalInformation(2),
-+ * audio3100Hz(3),
-+ * telephony(32),
-+ * teletex(33),
-+ * telefaxGroup4Class1(34),
-+ * videotextSyntaxBased(35),
-+ * videotelephony(36),
-+ * telefaxGroup2-3(37),
-+ * reservedNotUsed1(38),
-+ * reservedNotUsed2(39),
-+ * reservedNotUsed3(40),
-+ * reservedNotUsed4(41),
-+ * reservedNotUsed5(42),
-+ * email(51),
-+ * video(52),
-+ * fileTransfer(53),
-+ * shortMessageService(54),
-+ * speechAndVideo(55),
-+ * speechAndFax(56),
-+ * speechAndEmail(57),
-+ * videoAndFax(58),
-+ * videoAndEmail(59),
-+ * faxAndEmail(60),
-+ * speechVideoAndFax(61),
-+ * speechVideoAndEmail(62),
-+ * speechFaxAndEmail(63),
-+ * videoFaxAndEmail(64),
-+ * speechVideoFaxAndEmail(65),
-+ * multimediaUnknown(66),
-+ * serviceUnknown(67),
-+ * futureReserve1(68),
-+ * futureReserve2(69),
-+ * futureReserve3(70),
-+ * futureReserve4(71),
-+ * futureReserve5(72),
-+ * futureReserve6(73),
-+ * futureReserve7(74),
-+ * futureReserve8(75)
-+ */
-+ u_int8_t basic_service;
-+
-+ /*!
-+ * \brief INTEGER (0..9) (optional)
-+ * \note The value 0 means the highest priority and 9 the lowest.
-+ */
-+ u_int8_t priority;
-+
-+ /*! \brief TRUE if msg_centre_id is present */
-+ u_int8_t msg_centre_id_present;
-+
-+ /*! \brief TRUE if number_of_messages is present */
-+ u_int8_t number_of_messages_present;
-+
-+ /*! \brief TRUE if timestamp is present */
-+ u_int8_t timestamp_present;
-+
-+ /*! \brief TRUE if priority is present */
-+ u_int8_t priority_present;
-+};
-+
-+/*
-+ * MWIInterrogateRes ::= SEQUENCE SIZE(1..10) OF MWIInterrogateResElt
-+ */
-+struct roseQsigMWIInterrogateRes {
-+ /*! \brief SEQUENCE SIZE(1..10) OF MWIInterrogateResElt */
-+ struct roseQsigMWIInterrogateResElt list[10];
-+
-+ /*! \brief Number of MWIInterrogateResElt records present */
-+ u_int8_t num_records;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*
-+ * Northern Telecom DMS-100 transfer ability result
-+ *
-+ * callId [0] IMPLICIT INTEGER (0..16777215) -- 24 bit number
-+ */
-+struct roseDms100RLTOperationInd_RES {
-+ /*! INTEGER (0..16777215) -- 24 bit number */
-+ u_int32_t call_id;
-+};
-+
-+/*
-+ * Northern Telecom DMS-100 transfer invoke
-+ *
-+ * ARGUMENT SEQUENCE {
-+ * callId [0] IMPLICIT INTEGER (0..16777215), -- 24 bit number
-+ * reason [1] IMPLICIT INTEGER
-+ * }
-+ */
-+struct roseDms100RLTThirdParty_ARG {
-+ /*! INTEGER (0..16777215) -- 24 bit number */
-+ u_int32_t call_id;
-+
-+ /*! Reason for redirect */
-+ u_int8_t reason;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/* ARGUMENT ENUMERATED */
-+struct roseNi2InformationFollowing_ARG {
-+ u_int8_t value; /*!< Unknown enumerated value */
-+};
-+
-+/*
-+ * ARGUMENT SEQUENCE {
-+ * callReference INTEGER -- 16 bit number
-+ * }
-+ */
-+struct roseNi2InitiateTransfer_ARG {
-+ u_int16_t call_reference;
-+};
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+/*! \brief Facility ie invoke etsi messages with arguments. */
-+union rose_msg_invoke_etsi_args {
-+ /* ETSI Advice Of Charge (AOC) */
-+ struct roseEtsiChargingRequest_ARG ChargingRequest;
-+ struct roseEtsiAOCSCurrency_ARG AOCSCurrency;
-+ struct roseEtsiAOCSSpecialArr_ARG AOCSSpecialArr;
-+ struct roseEtsiAOCDCurrency_ARG AOCDCurrency;
-+ struct roseEtsiAOCDChargingUnit_ARG AOCDChargingUnit;
-+ struct roseEtsiAOCECurrency_ARG AOCECurrency;
-+ struct roseEtsiAOCEChargingUnit_ARG AOCEChargingUnit;
-+
-+ /* ETSI Call Diversion */
-+ struct roseEtsiActivationDiversion_ARG ActivationDiversion;
-+ struct roseEtsiDeactivationDiversion_ARG DeactivationDiversion;
-+ struct roseEtsiActivationStatusNotificationDiv_ARG ActivationStatusNotificationDiv;
-+ struct roseEtsiDeactivationStatusNotificationDiv_ARG
-+ DeactivationStatusNotificationDiv;
-+ struct roseEtsiInterrogationDiversion_ARG InterrogationDiversion;
-+ struct roseEtsiDiversionInformation_ARG DiversionInformation;
-+ struct roseEtsiCallDeflection_ARG CallDeflection;
-+ struct roseEtsiCallRerouting_ARG CallRerouting;
-+ struct roseEtsiDivertingLegInformation1_ARG DivertingLegInformation1;
-+ struct roseEtsiDivertingLegInformation2_ARG DivertingLegInformation2;
-+ struct roseEtsiDivertingLegInformation3_ARG DivertingLegInformation3;
-+
-+ /* ETSI Explicit Call Transfer (ECT) */
-+ struct roseEtsiExplicitEctExecute_ARG ExplicitEctExecute;
-+ struct roseEtsiSubaddressTransfer_ARG SubaddressTransfer;
-+ struct roseEtsiEctInform_ARG EctInform;
-+ struct roseEtsiEctLoopTest_ARG EctLoopTest;
-+};
-+
-+/*! \brief Facility ie result etsi messages with arguments. */
-+union rose_msg_result_etsi_args {
-+ /* ETSI Advice Of Charge (AOC) */
-+ struct roseEtsiChargingRequest_RES ChargingRequest;
-+
-+ /* ETSI Call Diversion */
-+ struct roseEtsiForwardingList InterrogationDiversion;
-+ struct roseEtsiServedUserNumberList InterrogateServedUserNumbers;
-+
-+ /* ETSI Explicit Call Transfer (ECT) */
-+ struct roseEtsiEctLinkIdRequest_RES EctLinkIdRequest;
-+ struct roseEtsiEctLoopTest_RES EctLoopTest;
-+};
-+
-+/*! \brief Facility ie invoke qsig messages with arguments. */
-+union rose_msg_invoke_qsig_args {
-+ /* Q.SIG Name-Operations */
-+ struct roseQsigPartyName_ARG CallingName;
-+ struct roseQsigPartyName_ARG CalledName;
-+ struct roseQsigPartyName_ARG ConnectedName;
-+ struct roseQsigPartyName_ARG BusyName;
-+
-+ /* Q.SIG SS-AOC-Operations */
-+ struct roseQsigChargeRequestArg_ARG ChargeRequest;
-+ struct roseQsigAocFinalArg_ARG AocFinal;
-+ struct roseQsigAocInterimArg_ARG AocInterim;
-+ struct roseQsigAocRateArg_ARG AocRate;
-+ struct roseQsigAocCompleteArg_ARG AocComplete;
-+ struct roseQsigAocDivChargeReqArg_ARG AocDivChargeReq;
-+
-+ /* Q.SIG Call-Transfer-Operations */
-+ struct roseQsigCTInitiateArg_ARG CallTransferInitiate;
-+ struct roseQsigCTSetupArg_ARG CallTransferSetup;
-+ struct roseQsigCTActiveArg_ARG CallTransferActive;
-+ struct roseQsigCTCompleteArg_ARG CallTransferComplete;
-+ struct roseQsigCTUpdateArg_ARG CallTransferUpdate;
-+ struct roseQsigSubaddressTransferArg_ARG SubaddressTransfer;
-+
-+ /* Q.SIG Call-Diversion-Operations */
-+ struct roseQsigActivateDiversionQ_ARG ActivateDiversionQ;
-+ struct roseQsigDeactivateDiversionQ_ARG DeactivateDiversionQ;
-+ struct roseQsigInterrogateDiversionQ_ARG InterrogateDiversionQ;
-+ struct roseQsigCheckRestriction_ARG CheckRestriction;
-+ struct roseQsigCallRerouting_ARG CallRerouting;
-+ struct roseQsigDivertingLegInformation1_ARG DivertingLegInformation1;
-+ struct roseQsigDivertingLegInformation2_ARG DivertingLegInformation2;
-+ struct roseQsigDivertingLegInformation3_ARG DivertingLegInformation3;
-+
-+ /* Q.SIG SS-MWI-Operations */
-+ struct roseQsigMWIActivateArg MWIActivate;
-+ struct roseQsigMWIDeactivateArg MWIDeactivate;
-+ struct roseQsigMWIInterrogateArg MWIInterrogate;
-+};
-+
-+/*! \brief Facility ie result qsig messages with arguments. */
-+union rose_msg_result_qsig_args {
-+ /* Q.SIG SS-AOC-Operations */
-+ struct roseQsigChargeRequestRes_RES ChargeRequest;
-+ struct roseQsigAocCompleteRes_RES AocComplete;
-+
-+ /* Q.SIG Call-Transfer-Operations */
-+ struct roseQsigCTIdentifyRes_RES CallTransferIdentify;
-+
-+ /* Q.SIG Call-Diversion-Operations */
-+ struct roseQsigForwardingList InterrogateDiversionQ;
-+
-+ /* Q.SIG SS-MWI-Operations */
-+ struct roseQsigMWIInterrogateRes MWIInterrogate;
-+};
-+
-+/*! \brief Facility ie invoke DMS-100 messages with arguments. */
-+union rose_msg_invoke_dms100_args {
-+ struct roseDms100RLTThirdParty_ARG RLT_ThirdParty;
-+};
-+
-+/*! \brief Facility ie result DMS-100 messages with arguments. */
-+union rose_msg_result_dms100_args {
-+ struct roseDms100RLTOperationInd_RES RLT_OperationInd;
-+};
-+
-+/*! \brief Facility ie invoke NI2 messages with arguments. */
-+union rose_msg_invoke_ni2_args {
-+ struct roseNi2InformationFollowing_ARG InformationFollowing;
-+ struct roseNi2InitiateTransfer_ARG InitiateTransfer;
-+};
-+
-+/*! \brief Facility ie result NI2 messages with arguments. */
-+union rose_msg_result_ni2_args {
-+ int dummy; /*!< place holder until there are results with parameters */
-+};
-+
-+/*! \brief Facility ie invoke messages with arguments. */
-+union rose_msg_invoke_args {
-+ union rose_msg_invoke_etsi_args etsi;
-+ union rose_msg_invoke_qsig_args qsig;
-+ union rose_msg_invoke_dms100_args dms100;
-+ union rose_msg_invoke_ni2_args ni2;
-+};
-+
-+/*! \brief Facility ie result messages with arguments. */
-+union rose_msg_result_args {
-+ union rose_msg_result_etsi_args etsi;
-+ union rose_msg_result_qsig_args qsig;
-+ union rose_msg_result_dms100_args dms100;
-+ union rose_msg_result_ni2_args ni2;
-+};
-+
-+/*! \brief Facility ie error messages with parameters. */
-+union rose_msg_error_args {
-+ int dummy; /*!< place holder until there are errors with parameters */
-+};
-+
-+struct rose_msg_invoke {
-+ /*! \brief Invoke ID (-32768..32767) */
-+ int16_t invoke_id;
-+ /*! \brief Linked ID (-32768..32767) (optional) */
-+ int16_t linked_id;
-+ /*! \brief library encoded operation-value */
-+ enum rose_operation operation;
-+ /*! \brief TRUE if the Linked ID is present */
-+ u_int8_t linked_id_present;
-+ union rose_msg_invoke_args args;
-+};
-+
-+struct rose_msg_result {
-+ /*! \brief Invoke ID (-32768..32767) */
-+ int16_t invoke_id;
-+ /*!
-+ * \brief library encoded operation-value
-+ * \note Set to ROSE_None if the operation sequence is not present.
-+ * \note ETSI and Q.SIG imply that if a return result does not have
-+ * any arguments then you must rely upon the invokeId value to
-+ * distinguish between return results because the operation-value is
-+ * not present.
-+ */
-+ enum rose_operation operation;
-+ union rose_msg_result_args args;
-+};
-+
-+struct rose_msg_error {
-+ /*! \brief Invoke ID (-32768..32767) */
-+ int16_t invoke_id;
-+ /*! \brief library encoded error-value */
-+ enum rose_error_code code;
-+ union rose_msg_error_args args;
-+};
-+
-+struct rose_msg_reject {
-+ /*! \brief Invoke ID (-32768..32767) (optional) */
-+ int16_t invoke_id;
-+ /*! \brief TRUE if the Invoke ID is present */
-+ u_int8_t invoke_id_present;
-+ /*! \brief library encoded problem-value */
-+ enum rose_reject_code code;
-+};
-+
-+enum rose_component_type {
-+ ROSE_COMP_TYPE_INVALID,
-+ ROSE_COMP_TYPE_INVOKE,
-+ ROSE_COMP_TYPE_RESULT,
-+ ROSE_COMP_TYPE_ERROR,
-+ ROSE_COMP_TYPE_REJECT
-+};
-+
-+struct rose_message {
-+ /*! \brief invoke, result, error, reject */
-+ enum rose_component_type type;
-+ union {
-+ struct rose_msg_invoke invoke;
-+ struct rose_msg_result result;
-+ struct rose_msg_error error;
-+ struct rose_msg_reject reject;
-+ } component;
-+};
-+
-+/*
-+ * NetworkFacilityExtension ::= [10] IMPLICIT SEQUENCE {
-+ * sourceEntity [0] IMPLICIT EntityType,
-+ * sourceEntityAddress [1] EXPLICIT AddressInformation OPTIONAL,
-+ * destinationEntity [2] IMPLICIT EntityType,
-+ * destinationEntityAddress [3] EXPLICIT AddressInformation OPTIONAL
-+ * }
-+ *
-+ * AddressInformation ::= PartyNumber
-+ */
-+struct facNetworkFacilityExtension {
-+ /*! \brief sourceEntityAddress (optional) (Number present if length is nonzero) */
-+ struct rosePartyNumber source_number;
-+ /*! \brief destinationEntityAddress (optional) (Number present if length is nonzero) */
-+ struct rosePartyNumber destination_number;
-+
-+ /*!
-+ * \details
-+ * endPINX(0),
-+ * anyTypeOfPINX(1)
-+ */
-+ u_int8_t source_entity;
-+
-+ /*!
-+ * \details
-+ * endPINX(0),
-+ * anyTypeOfPINX(1)
-+ */
-+ u_int8_t destination_entity;
-+};
-+
-+/*
-+ * The network extensions header is a sequence of the following components:
-+ *
-+ * nfe NetworkFacilityExtension OPTIONAL,
-+ * npp NetworkProtocolProfile OPTIONAL,
-+ * interpretation InterpretationApdu OPTIONAL
-+ *
-+ * NetworkProtocolProfile ::= [18] IMPLICIT INTEGER (0..254)
-+ *
-+ * InterpretationApdu ::= [11] IMPLICIT ENUMERATED {
-+ * discardAnyUnrecognisedInvokePdu(0),
-+ *
-+ * -- this value also applies to Call independent signalling connections
-+ * -- see clause 8.1.2 (ECMA-165)
-+ * clearCallIfAnyInvokePduNotRecognised(1),
-+ *
-+ * -- this coding is implied by the absence of an
-+ * -- interpretation APDU.
-+ * rejectAnyUnrecognisedInvokePdu(2)
-+ * }
-+ */
-+struct fac_extension_header {
-+ /*! \brief Network Facility Extension component */
-+ struct facNetworkFacilityExtension nfe;
-+
-+ /*! \brief Network Protocol Profile component */
-+ u_int8_t npp;
-+
-+ /*!
-+ * \brief interpretation component
-+ *
-+ * \details
-+ * discardAnyUnrecognisedInvokePdu(0),
-+ * clearCallIfAnyInvokePduNotRecognised(1),
-+ * rejectAnyUnrecognisedInvokePdu(2)
-+ */
-+ u_int8_t interpretation;
-+
-+ /*! \brief TRUE if nfe is present */
-+ u_int8_t nfe_present;
-+
-+ /*! \brief TRUE if npp is present */
-+ u_int8_t npp_present;
-+
-+ /*! \brief TRUE if interpretation is present */
-+ u_int8_t interpretation_present;
-+};
-+
-+const char *rose_operation2str(enum rose_operation operation);
-+const char *rose_error2str(enum rose_error_code code);
-+const char *rose_reject2str(enum rose_reject_code code);
-+
-+unsigned char *rose_encode_invoke(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rose_msg_invoke *msg);
-+unsigned char *rose_encode_result(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rose_msg_result *msg);
-+unsigned char *rose_encode_error(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rose_msg_error *msg);
-+unsigned char *rose_encode_reject(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rose_msg_reject *msg);
-+
-+unsigned char *rose_encode(struct pri *ctrl, unsigned char *pos, unsigned char *end,
-+ const struct rose_message *msg);
-+const unsigned char *rose_decode(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end, struct rose_message *msg);
-+
-+unsigned char *fac_enc_extension_header(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct fac_extension_header *header);
-+unsigned char *facility_encode_header(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct fac_extension_header *header);
-+
-+const unsigned char *fac_dec_extension_header(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end, struct fac_extension_header *header);
-+const unsigned char *facility_decode_header(struct pri *ctrl, const unsigned char *pos,
-+ const unsigned char *end, struct fac_extension_header *header);
-+
-+void facility_decode_dump(struct pri *ctrl, const unsigned char *buf, size_t length);
-+
-+/* ------------------------------------------------------------------- */
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif /* _LIBPRI_ROSE_H */
-+/* ------------------------------------------------------------------- */
-+/* end rose.h */
-
-Property changes on: rose.h
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_address.c
-===================================================================
---- a/rose_address.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_address.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,983 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief ROSE Addressing-Data-Elements
-+ *
-+ * Addressing-Data-Elements ETS 300 196-1 D.3
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the public or private network PartyNumber type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param number
-+ * \param length_of_number
-+ * \param type_of_number
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_NetworkPartyNumber(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const unsigned char *number,
-+ size_t length_of_number, u_int8_t type_of_number)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, type_of_number));
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_NUMERIC_STRING, number,
-+ length_of_number));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the PartyNumber type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param party_number
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_PartyNumber(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePartyNumber *party_number)
-+{
-+ switch (party_number->plan) {
-+ case 0: /* Unknown PartyNumber */
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
-+ party_number->str, party_number->length));
-+ break;
-+ case 1: /* Public PartyNumber */
-+ ASN1_CALL(pos, rose_enc_NetworkPartyNumber(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, party_number->str, party_number->length,
-+ party_number->ton));
-+ break;
-+ case 2: /* NSAP encoded PartyNumber */
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ party_number->str, party_number->length));
-+ break;
-+ case 3: /* Data PartyNumber (Not used) */
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
-+ party_number->str, party_number->length));
-+ break;
-+ case 4: /* Telex PartyNumber (Not used) */
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4,
-+ party_number->str, party_number->length));
-+ break;
-+ case 5: /* Private PartyNumber */
-+ ASN1_CALL(pos, rose_enc_NetworkPartyNumber(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 5, party_number->str, party_number->length,
-+ party_number->ton));
-+ break;
-+ case 8: /* National Standard PartyNumber (Not used) */
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 8,
-+ party_number->str, party_number->length));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown numbering plan");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the PartySubaddress type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param party_subaddress
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_PartySubaddress(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePartySubaddress *party_subaddress)
-+{
-+ unsigned char *seq_len;
-+
-+ switch (party_subaddress->type) {
-+ case 0: /* UserSpecified */
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_OCTET_STRING,
-+ party_subaddress->u.user_specified.information, party_subaddress->length));
-+ if (party_subaddress->u.user_specified.odd_count_present) {
-+ ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
-+ party_subaddress->u.user_specified.odd_count));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+ break;
-+ case 1: /* NSAP */
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_OCTET_STRING,
-+ party_subaddress->u.nsap, party_subaddress->length));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown subaddress type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Address type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param address
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_Address(struct pri *ctrl, unsigned char *pos, unsigned char *end,
-+ unsigned tag, const struct roseAddress *address)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &address->number));
-+ if (address->subaddress.length) {
-+ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end, &address->subaddress));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the PresentedNumberUnscreened type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param party
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_PresentedNumberUnscreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePresentedNumberUnscreened *party)
-+{
-+ unsigned char *seq_len;
-+
-+ switch (party->presentation) {
-+ case 0: /* presentationAllowedNumber */
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &party->number));
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+ break;
-+ case 1: /* presentationRestricted */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
-+ break;
-+ case 2: /* numberNotAvailableDueToInterworking */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2));
-+ break;
-+ case 3: /* presentationRestrictedNumber */
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &party->number));
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown presentation type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the NumberScreened type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param screened
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_NumberScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseNumberScreened *screened)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &screened->number));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ screened->screening_indicator));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the PresentedNumberScreened type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param party
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_PresentedNumberScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePresentedNumberScreened *party)
-+{
-+ switch (party->presentation) {
-+ case 0: /* presentationAllowedNumber */
-+ ASN1_CALL(pos, rose_enc_NumberScreened(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 0, &party->screened));
-+ break;
-+ case 1: /* presentationRestricted */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
-+ break;
-+ case 2: /* numberNotAvailableDueToInterworking */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2));
-+ break;
-+ case 3: /* presentationRestrictedNumber */
-+ ASN1_CALL(pos, rose_enc_NumberScreened(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 3, &party->screened));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown presentation type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the AddressScreened type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param screened
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_AddressScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseAddressScreened *screened)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &screened->number));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ screened->screening_indicator));
-+ if (screened->subaddress.length) {
-+ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end, &screened->subaddress));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the PresentedAddressScreened type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param party
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_PresentedAddressScreened(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct rosePresentedAddressScreened *party)
-+{
-+ switch (party->presentation) {
-+ case 0: /* presentationAllowedAddress */
-+ ASN1_CALL(pos, rose_enc_AddressScreened(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 0, &party->screened));
-+ break;
-+ case 1: /* presentationRestricted */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
-+ break;
-+ case 2: /* numberNotAvailableDueToInterworking */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2));
-+ break;
-+ case 3: /* presentationRestrictedAddress */
-+ ASN1_CALL(pos, rose_enc_AddressScreened(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 3, &party->screened));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown presentation type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the NumberDigits PartyNumber argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party_number Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_NumberDigits(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartyNumber *party_number)
-+{
-+ size_t str_len;
-+
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, name, tag, pos, end,
-+ sizeof(party_number->str), party_number->str, &str_len));
-+ party_number->length = str_len;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the NSAP PartyNumber argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party_number Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_NSAPPartyNumber(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartyNumber *party_number)
-+{
-+ size_t str_len;
-+
-+ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end,
-+ sizeof(party_number->str), party_number->str, &str_len));
-+ party_number->length = str_len;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the public or private network PartyNumber argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party_number Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_NetworkPartyNumber(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartyNumber *party_number)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfNumber", tag, pos, seq_end, &value));
-+ party_number->ton = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_NUMERIC_STRING);
-+ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "numberDigits", tag, pos, seq_end,
-+ party_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the PartyNumber argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party_number Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_PartyNumber(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartyNumber *party_number)
-+{
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s PartyNumber\n", name);
-+ }
-+ party_number->ton = 0; /* unknown */
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ party_number->plan = 0; /* Unknown PartyNumber */
-+ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "unknownPartyNumber", tag, pos, end,
-+ party_number));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ /* Must be constructed but we will not check for it for simplicity. */
-+ party_number->plan = 1; /* Public PartyNumber */
-+ ASN1_CALL(pos, rose_dec_NetworkPartyNumber(ctrl, "publicPartyNumber", tag, pos,
-+ end, party_number));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ party_number->plan = 2; /* NSAP encoded PartyNumber */
-+ ASN1_CALL(pos, rose_dec_NSAPPartyNumber(ctrl, "nsapEncodedPartyNumber", tag, pos,
-+ end, party_number));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ party_number->plan = 3; /* Data PartyNumber (Not used) */
-+ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "dataPartyNumber", tag, pos, end,
-+ party_number));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ party_number->plan = 4; /* Telex PartyNumber (Not used) */
-+ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "telexPartyNumber", tag, pos, end,
-+ party_number));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
-+ /* Must be constructed but we will not check for it for simplicity. */
-+ party_number->plan = 5; /* Private PartyNumber */
-+ ASN1_CALL(pos, rose_dec_NetworkPartyNumber(ctrl, "privatePartyNumber", tag, pos,
-+ end, party_number));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 8:
-+ party_number->plan = 8; /* National Standard PartyNumber (Not used) */
-+ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "nationalStandardPartyNumber", tag,
-+ pos, end, party_number));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the User PartySubaddress argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party_subaddress Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_UserSubaddress(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartySubaddress *party_subaddress)
-+{
-+ size_t str_len;
-+ int32_t odd_count;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ party_subaddress->type = 0; /* UserSpecified */
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s UserSpecified %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ /* SubaddressInformation */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_OCTET_STRING);
-+ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, "subaddressInformation", tag, pos, seq_end,
-+ sizeof(party_subaddress->u.user_specified.information),
-+ party_subaddress->u.user_specified.information, &str_len));
-+ party_subaddress->length = str_len;
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ /*
-+ * The optional odd count indicator must be present since there
-+ * is something left.
-+ */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN);
-+ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "oddCount", tag, pos, seq_end,
-+ &odd_count));
-+ party_subaddress->u.user_specified.odd_count = odd_count;
-+ party_subaddress->u.user_specified.odd_count_present = 1;
-+ } else {
-+ party_subaddress->u.user_specified.odd_count = 0;
-+ party_subaddress->u.user_specified.odd_count_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the NSAP PartySubaddress argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party_subaddress Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_NSAPSubaddress(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartySubaddress *party_subaddress)
-+{
-+ size_t str_len;
-+
-+ party_subaddress->type = 1; /* NSAP */
-+
-+ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end,
-+ sizeof(party_subaddress->u.nsap), party_subaddress->u.nsap, &str_len));
-+ party_subaddress->length = str_len;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the PartySubaddress argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party_subaddress Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_PartySubaddress(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartySubaddress *party_subaddress)
-+{
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s PartySubaddress\n", name);
-+ }
-+ switch (tag) {
-+ case ASN1_TAG_SEQUENCE:
-+ ASN1_CALL(pos, rose_dec_UserSubaddress(ctrl, "user", tag, pos, end,
-+ party_subaddress));
-+ break;
-+ case ASN1_TYPE_OCTET_STRING:
-+ case ASN1_TYPE_OCTET_STRING | ASN1_PC_CONSTRUCTED:
-+ ASN1_CALL(pos, rose_dec_NSAPSubaddress(ctrl, "nsap", tag, pos, end,
-+ party_subaddress));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Address argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param address Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_Address(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct roseAddress *address)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s Address %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end,
-+ &address->number));
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ /* The optional subaddress must be present since there is something left. */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "partySubaddress", tag, pos,
-+ seq_end, &address->subaddress));
-+ } else {
-+ address->subaddress.length = 0; /* Subaddress not present */
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the PresentedNumberUnscreened argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_PresentedNumberUnscreened(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePresentedNumberUnscreened *party)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s PresentedNumberUnscreened\n", name);
-+ }
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ party->presentation = 0; /* presentationAllowedNumber */
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "presentationAllowedNumber", tag, pos,
-+ seq_end, &party->number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ party->presentation = 1; /* presentationRestricted */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ party->presentation = 2; /* numberNotAvailableDueToInterworking */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag,
-+ pos, end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ party->presentation = 3; /* presentationRestrictedNumber */
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "presentationRestrictedNumber", tag,
-+ pos, seq_end, &party->number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the NumberScreened argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param screened Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_NumberScreened(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseNumberScreened *screened)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s NumberScreened %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end,
-+ &screened->number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "screeningIndicator", tag, pos, seq_end, &value));
-+ screened->screening_indicator = value;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the PresentedNumberScreened argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_PresentedNumberScreened(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePresentedNumberScreened *party)
-+{
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s PresentedNumberScreened\n", name);
-+ }
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ party->presentation = 0; /* presentationAllowedNumber */
-+ ASN1_CALL(pos, rose_dec_NumberScreened(ctrl, "presentationAllowedNumber", tag,
-+ pos, end, &party->screened));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ party->presentation = 1; /* presentationRestricted */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ party->presentation = 2; /* numberNotAvailableDueToInterworking */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag,
-+ pos, end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
-+ party->presentation = 3; /* presentationRestrictedNumber */
-+ ASN1_CALL(pos, rose_dec_NumberScreened(ctrl, "presentationRestrictedNumber", tag,
-+ pos, end, &party->screened));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the AddressScreened argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param screened Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_AddressScreened(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseAddressScreened *screened)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s AddressScreened %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end,
-+ &screened->number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "screeningIndicator", tag, pos, seq_end, &value));
-+ screened->screening_indicator = value;
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ /* The optional subaddress must be present since there is something left. */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "partySubaddress", tag, pos,
-+ seq_end, &screened->subaddress));
-+ } else {
-+ screened->subaddress.length = 0; /* Subaddress not present */
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the PresentedAddressScreened argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_PresentedAddressScreened(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePresentedAddressScreened *party)
-+{
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s PresentedAddressScreened\n", name);
-+ }
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ party->presentation = 0; /* presentationAllowedAddress */
-+ ASN1_CALL(pos, rose_dec_AddressScreened(ctrl, "presentationAllowedAddress", tag,
-+ pos, end, &party->screened));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ party->presentation = 1; /* presentationRestricted */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ party->presentation = 2; /* numberNotAvailableDueToInterworking */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag,
-+ pos, end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
-+ party->presentation = 3; /* presentationRestrictedAddress */
-+ ASN1_CALL(pos, rose_dec_AddressScreened(ctrl, "presentationRestrictedAddress",
-+ tag, pos, end, &party->screened));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_address.c */
-
-Property changes on: rose_address.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_qsig_aoc.c
-===================================================================
---- a/rose_qsig_aoc.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_qsig_aoc.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,1714 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Q.SIG ROSE Advice-Of-Charge (AOC) operations
-+ *
-+ * SS-AOC-Operations ECMA-212 Annex E Table E.1
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Time type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param time Time information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_AOC_Time(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseQsigAOCTime *time)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ time->length));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2, time->scale));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Amount type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param amount Amount information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_AOC_Amount(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseQsigAOCAmount *amount)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ amount->currency));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ amount->multiplier));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the RecordedCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param recorded Recorded currency information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_AOC_RecordedCurrency(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseQsigAOCRecordedCurrency *recorded)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ recorded->currency, sizeof(recorded->currency) - 1));
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &recorded->amount));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the DurationCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param duration Duration currency information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_AOC_DurationCurrency(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseQsigAOCDurationCurrency *duration)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ duration->currency, sizeof(duration->currency) - 1));
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &duration->amount));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
-+ duration->charging_type));
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_Time(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 4, &duration->time));
-+ if (duration->granularity_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_Time(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 5, &duration->granularity));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the FlatRateCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param flat_rate Flat rate currency information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_AOC_FlatRateCurrency(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseQsigAOCFlatRateCurrency *flat_rate)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ flat_rate->currency, sizeof(flat_rate->currency) - 1));
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &flat_rate->amount));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the VolumeRateCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param volume_rate Volume rate currency information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_AOC_VolumeRateCurrency(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseQsigAOCVolumeRateCurrency *volume_rate)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ volume_rate->currency, sizeof(volume_rate->currency) - 1));
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &volume_rate->amount));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
-+ volume_rate->unit));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the AOCSCurrencyInfo type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param currency_info Currency information record to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_AOCSCurrencyInfo(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseQsigAOCSCurrencyInfo *currency_info)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ currency_info->charged_item));
-+
-+ switch (currency_info->currency_type) {
-+ case 0: /* specialChargingCode */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ currency_info->u.special_charging_code));
-+ break;
-+ case 1: /* durationCurrency */
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_DurationCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &currency_info->u.duration));
-+ break;
-+ case 2: /* flatRateCurrency */
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_FlatRateCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &currency_info->u.flat_rate));
-+ break;
-+ case 3: /* volumeRateCurrency */
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_VolumeRateCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 3, &currency_info->u.volume_rate));
-+ break;
-+ case 4: /* freeOfCharge */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4));
-+ break;
-+ case 5: /* currencyInfoNotAvailable */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5));
-+ break;
-+ case 6: /* freeOfChargeFromBeginning */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown currency type");
-+ return NULL;
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the AOCSCurrencyInfoList type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param currency_info Currency information list to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_AOCSCurrencyInfoList(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseQsigAOCSCurrencyInfoList *currency_info)
-+{
-+ unsigned index;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ for (index = 0; index < currency_info->num_records; ++index) {
-+ ASN1_CALL(pos, rose_enc_qsig_AOCSCurrencyInfo(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &currency_info->list[index]));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the ChargingAssociation type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param charging Charging association information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_AOC_ChargingAssociation(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end,
-+ const struct roseQsigAOCChargingAssociation *charging)
-+{
-+ unsigned char *explicit_len;
-+
-+ switch (charging->type) {
-+ case 0: /* charge_identifier */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, charging->id));
-+ break;
-+ case 1: /* charged_number */
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &charging->number));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown ChargingAssociation type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG ChargeRequest invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned index;
-+ unsigned char *seq_len;
-+ unsigned char *advice_len;
-+ const struct roseQsigChargeRequestArg_ARG *charge_request;
-+
-+ charge_request = &args->qsig.ChargeRequest;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ /* SEQUENCE SIZE(0..7) OF AdviceModeCombination */
-+ ASN1_CONSTRUCTED_BEGIN(advice_len, pos, end, ASN1_TAG_SEQUENCE);
-+ for (index = 0; index < charge_request->num_records; ++index) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ charge_request->advice_mode_combinations[index]));
-+ }
-+ ASN1_CONSTRUCTED_END(advice_len, pos, end);
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG ChargeRequest result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigChargeRequestRes_RES *charge_request;
-+
-+ charge_request = &args->qsig.ChargeRequest;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ charge_request->advice_mode_combination));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG AocFinal invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_AocFinal_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ unsigned char *specific_len;
-+ const struct roseQsigAocFinalArg_ARG *aoc_final;
-+
-+ aoc_final = &args->qsig.AocFinal;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ switch (aoc_final->type) {
-+ case 0: /* charge_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0));
-+ break;
-+ case 1: /* free_of_charge */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
-+ break;
-+ case 2: /* specific_currency */
-+ ASN1_CONSTRUCTED_BEGIN(specific_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_RecordedCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_final->specific.recorded));
-+
-+ if (aoc_final->specific.billing_id_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ aoc_final->specific.billing_id));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(specific_len, pos, end);
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown AocFinal type");
-+ return NULL;
-+ }
-+
-+ if (aoc_final->charging_association_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_ChargingAssociation(ctrl, pos, end,
-+ &aoc_final->charging_association));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG AocInterim invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_AocInterim_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ unsigned char *specific_len;
-+ const struct roseQsigAocInterimArg_ARG *aoc_interim;
-+
-+ aoc_interim = &args->qsig.AocInterim;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ switch (aoc_interim->type) {
-+ case 0: /* charge_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0));
-+ break;
-+ case 1: /* free_of_charge */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
-+ break;
-+ case 2: /* specific_currency */
-+ ASN1_CONSTRUCTED_BEGIN(specific_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_RecordedCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_interim->specific.recorded));
-+
-+ if (aoc_interim->specific.billing_id_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ aoc_interim->specific.billing_id));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(specific_len, pos, end);
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown AocInterim type");
-+ return NULL;
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG AocRate invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_AocRate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigAocRateArg_ARG *aoc_rate;
-+
-+ aoc_rate = &args->qsig.AocRate;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ switch (aoc_rate->type) {
-+ case 0: /* charge_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ break;
-+ case 1: /* currency_info_list */
-+ ASN1_CALL(pos, rose_enc_qsig_AOCSCurrencyInfoList(ctrl, pos, end,
-+ ASN1_TAG_SEQUENCE, &aoc_rate->currency_info));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown AocRate type");
-+ return NULL;
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG AocComplete invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_AocComplete_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigAocCompleteArg_ARG *aoc_complete;
-+
-+ aoc_complete = &args->qsig.AocComplete;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &aoc_complete->charged_user_number));
-+
-+ if (aoc_complete->charging_association_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_ChargingAssociation(ctrl, pos, end,
-+ &aoc_complete->charging_association));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG AocComplete result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_AocComplete_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigAocCompleteRes_RES *aoc_complete;
-+
-+ aoc_complete = &args->qsig.AocComplete;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ aoc_complete->charging_option));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG AocDivChargeReq invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigAocDivChargeReqArg_ARG *aoc_div_charge_req;
-+
-+ aoc_div_charge_req = &args->qsig.AocDivChargeReq;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &aoc_div_charge_req->diverting_user_number));
-+
-+ if (aoc_div_charge_req->charging_association_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_AOC_ChargingAssociation(ctrl, pos, end,
-+ &aoc_div_charge_req->charging_association));
-+ }
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ aoc_div_charge_req->diversion_type));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the Time type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param time Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_AOC_Time(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigAOCTime *time)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s Time %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "lengthOfTimeUnit", tag, pos, seq_end, &value));
-+ time->length = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "scale", tag, pos, seq_end, &value));
-+ time->scale = value;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the Amount type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param amount Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_AOC_Amount(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigAOCAmount *amount)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s Amount %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "currencyAmount", tag, pos, seq_end, &value));
-+ amount->currency = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "multiplier", tag, pos, seq_end, &value));
-+ amount->multiplier = value;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the RecordedCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param recorded Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_AOC_RecordedCurrency(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigAOCRecordedCurrency *recorded)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ size_t str_len;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s RecordedCurrency %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "rCurrency", tag, pos, seq_end,
-+ sizeof(recorded->currency), recorded->currency, &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "rAmount", tag, pos, seq_end,
-+ &recorded->amount));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the DurationCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param duration Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_AOC_DurationCurrency(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigAOCDurationCurrency *duration)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ size_t str_len;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s DurationCurrency %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "dCurrency", tag, pos, seq_end,
-+ sizeof(duration->currency), duration->currency, &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "dAmount", tag, pos, seq_end,
-+ &duration->amount));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "dChargingType", tag, pos, seq_end, &value));
-+ duration->charging_type = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4);
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_Time(ctrl, "dTime", tag, pos, seq_end,
-+ &duration->time));
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5);
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_Time(ctrl, "dGranularity", tag, pos, seq_end,
-+ &duration->granularity));
-+ duration->granularity_present = 1;
-+ } else {
-+ duration->granularity_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the FlatRateCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param flat_rate Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_AOC_FlatRateCurrency(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigAOCFlatRateCurrency *flat_rate)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ size_t str_len;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s FlatRateCurrency %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "fRCurrency", tag, pos, seq_end,
-+ sizeof(flat_rate->currency), flat_rate->currency, &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "fRAmount", tag, pos, seq_end,
-+ &flat_rate->amount));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the VolumeRateCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param volume_rate Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_AOC_VolumeRateCurrency(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigAOCVolumeRateCurrency *volume_rate)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ size_t str_len;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s VolumeRateCurrency %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "vRCurrency", tag, pos, seq_end,
-+ sizeof(volume_rate->currency), volume_rate->currency, &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "vRAmount", tag, pos, seq_end,
-+ &volume_rate->amount));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "vRVolumeUnit", tag, pos, seq_end, &value));
-+ volume_rate->unit = value;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the AOCSCurrencyInfo type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param currency_info Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_AOCSCurrencyInfo(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigAOCSCurrencyInfo *currency_info)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s AOCSCurrencyInfo %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargedItem", tag, pos, seq_end, &value));
-+ currency_info->charged_item = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_TYPE_INTEGER:
-+ currency_info->currency_type = 0; /* specialChargingCode */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "specialChargingCode", tag, pos, seq_end,
-+ &value));
-+ currency_info->u.special_charging_code = value;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ currency_info->currency_type = 1; /* durationCurrency */
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_DurationCurrency(ctrl, "durationCurrency", tag,
-+ pos, seq_end, &currency_info->u.duration));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ currency_info->currency_type = 2; /* flatRateCurrency */
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_FlatRateCurrency(ctrl, "flatRateCurrency", tag,
-+ pos, seq_end, &currency_info->u.flat_rate));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
-+ currency_info->currency_type = 3; /* volumeRateCurrency */
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_VolumeRateCurrency(ctrl, "volumeRateCurrency",
-+ tag, pos, seq_end, &currency_info->u.volume_rate));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ currency_info->currency_type = 4; /* freeOfCharge */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
-+ currency_info->currency_type = 5; /* currencyInfoNotAvailable */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "currencyInfoNotAvailable", tag, pos,
-+ seq_end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
-+ currency_info->currency_type = 6; /* freeOfChargeFromBeginning */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfChargeFromBeginning", tag, pos,
-+ seq_end));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the AOCSCurrencyInfoList type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param currency_info Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_AOCSCurrencyInfoList(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigAOCSCurrencyInfoList *currency_info)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s AOCSCurrencyInfoList %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ currency_info->num_records = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ if (currency_info->num_records < ARRAY_LEN(currency_info->list)) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_qsig_AOCSCurrencyInfo(ctrl, "listEntry", tag, pos,
-+ seq_end, &currency_info->list[currency_info->num_records]));
-+ ++currency_info->num_records;
-+ } else {
-+ /* Too many records */
-+ return NULL;
-+ }
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the ChargingAssociation type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param charging Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_AOC_ChargingAssociation(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigAOCChargingAssociation *charging)
-+{
-+ int32_t value;
-+ int length;
-+ int explicit_offset;
-+ const unsigned char *explicit_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s ChargingAssociation\n", name);
-+ }
-+ switch (tag) {
-+ case ASN1_TYPE_INTEGER:
-+ charging->type = 0; /* charge_identifier */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargeIdentifier", tag, pos, end, &value));
-+ charging->id = value;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ charging->type = 1; /* charged_number */
-+
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "chargedNumber", tag, pos,
-+ explicit_end, &charging->number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG ChargeRequest invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ int advice_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *advice_end;
-+ struct roseQsigChargeRequestArg_ARG *charge_request;
-+
-+ charge_request = &args->qsig.ChargeRequest;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " ChargeRequest %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ /* SEQUENCE SIZE(0..7) OF AdviceModeCombination */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " adviceModeCombinations %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(advice_end, advice_offset, length, pos, seq_end);
-+
-+ /* Decode SIZE(0..7) OF AdviceModeCombination */
-+ charge_request->num_records = 0;
-+ while (pos < advice_end && *pos != ASN1_INDEF_TERM) {
-+ if (charge_request->num_records <
-+ ARRAY_LEN(charge_request->advice_mode_combinations)) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, advice_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "adviceModeCombination", tag, pos,
-+ advice_end, &value));
-+ charge_request->advice_mode_combinations[charge_request->num_records] =
-+ value;
-+ ++charge_request->num_records;
-+ } else {
-+ /* Too many records */
-+ return NULL;
-+ }
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, advice_offset, advice_end, seq_end);
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG ChargeRequest result argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigChargeRequestRes_RES *charge_request;
-+
-+ charge_request = &args->qsig.ChargeRequest;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " ChargeRequest %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "adviceModeCombination", tag, pos, seq_end,
-+ &value));
-+ charge_request->advice_mode_combination = value;
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG AocFinal invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_AocFinal_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ int specific_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *specific_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigAocFinalArg_ARG *aoc_final;
-+
-+ aoc_final = &args->qsig.AocFinal;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " AocFinal %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ aoc_final->type = 0; /* charge_not_available */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, seq_end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ aoc_final->type = 1; /* free_of_charge */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ aoc_final->type = 2; /* specific_currency */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
-+ pos, specific_end, &aoc_final->specific.recorded));
-+
-+ if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "finalBillingId", tag, pos, specific_end,
-+ &value));
-+ aoc_final->specific.billing_id = value;
-+ aoc_final->specific.billing_id_present = 1;
-+ } else {
-+ aoc_final->specific.billing_id_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ aoc_final->charging_association_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ case ASN1_TYPE_INTEGER:
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_ChargingAssociation(ctrl,
-+ "chargingAssociation", tag, pos, seq_end,
-+ &aoc_final->charging_association));
-+ aoc_final->charging_association_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " finalArgExtension %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG AocInterim invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_AocInterim_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ int specific_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *specific_end;
-+ struct roseQsigAocInterimArg_ARG *aoc_interim;
-+
-+ aoc_interim = &args->qsig.AocInterim;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " AocInterim %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ aoc_interim->type = 0; /* charge_not_available */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, seq_end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ aoc_interim->type = 1; /* free_of_charge */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ aoc_interim->type = 2; /* specific_currency */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
-+ pos, specific_end, &aoc_interim->specific.recorded));
-+
-+ if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "interimBillingId", tag, pos, specific_end,
-+ &value));
-+ aoc_interim->specific.billing_id = value;
-+ aoc_interim->specific.billing_id_present = 1;
-+ } else {
-+ aoc_interim->specific.billing_id_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG AocRate invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_AocRate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigAocRateArg_ARG *aoc_rate;
-+
-+ aoc_rate = &args->qsig.AocRate;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " AocRate %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_TYPE_NULL:
-+ aoc_rate->type = 0; /* charge_not_available */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, seq_end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ aoc_rate->type = 1; /* currency_info_list */
-+ ASN1_CALL(pos, rose_dec_qsig_AOCSCurrencyInfoList(ctrl, "aocSCurrencyInfoList",
-+ tag, pos, seq_end, &aoc_rate->currency_info));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG AocComplete invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_AocComplete_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigAocCompleteArg_ARG *aoc_complete;
-+
-+ aoc_complete = &args->qsig.AocComplete;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " AocComplete %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "chargedUser", tag, pos, seq_end,
-+ &aoc_complete->charged_user_number));
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ aoc_complete->charging_association_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ case ASN1_TYPE_INTEGER:
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_ChargingAssociation(ctrl,
-+ "chargingAssociation", tag, pos, seq_end,
-+ &aoc_complete->charging_association));
-+ aoc_complete->charging_association_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " completeArgExtension %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG AocComplete result argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_AocComplete_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigAocCompleteRes_RES *aoc_complete;
-+
-+ aoc_complete = &args->qsig.AocComplete;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " AocComplete %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargingOption", tag, pos, seq_end, &value));
-+ aoc_complete->charging_option = value;
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG AocDivChargeReq invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigAocDivChargeReqArg_ARG *aoc_div_charge_req;
-+
-+ aoc_div_charge_req = &args->qsig.AocDivChargeReq;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " AocDivChargeReq %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "divertingUser", tag, pos, seq_end,
-+ &aoc_div_charge_req->diverting_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ case ASN1_TYPE_INTEGER:
-+ ASN1_CALL(pos, rose_dec_qsig_AOC_ChargingAssociation(ctrl, "chargingAssociation",
-+ tag, pos, seq_end, &aoc_div_charge_req->charging_association));
-+ aoc_div_charge_req->charging_association_present = 1;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ break;
-+ default:
-+ aoc_div_charge_req->charging_association_present = 0;
-+ break;
-+ }
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionType", tag, pos, seq_end, &value));
-+ aoc_div_charge_req->diversion_type = value;
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_qsig_aoc.c */
-
-Property changes on: rose_qsig_aoc.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_etsi_aoc.c
-===================================================================
---- a/rose_etsi_aoc.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_etsi_aoc.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,1929 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief ROSE Advice Of Charge (AOC) operations
-+ *
-+ * Advice of Charge (AOC) supplementary service EN 300 182-1
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Time type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param time Time information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOC_Time(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseEtsiAOCTime *time)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ time->length));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2, time->scale));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Amount type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param amount Amount information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOC_Amount(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseEtsiAOCAmount *amount)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ amount->currency));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ amount->multiplier));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the RecordedCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param recorded Recorded currency information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOC_RecordedCurrency(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCRecordedCurrency *recorded)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ recorded->currency, sizeof(recorded->currency) - 1));
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &recorded->amount));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the DurationCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param duration Duration currency information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOC_DurationCurrency(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCDurationCurrency *duration)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ duration->currency, sizeof(duration->currency) - 1));
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &duration->amount));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
-+ duration->charging_type));
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_Time(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 4, &duration->time));
-+ if (duration->granularity_present) {
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_Time(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 5, &duration->granularity));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the FlatRateCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param flat_rate Flat rate currency information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOC_FlatRateCurrency(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCFlatRateCurrency *flat_rate)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ flat_rate->currency, sizeof(flat_rate->currency) - 1));
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &flat_rate->amount));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the VolumeRateCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param volume_rate Volume rate currency information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOC_VolumeRateCurrency(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCVolumeRateCurrency *volume_rate)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
-+ volume_rate->currency, sizeof(volume_rate->currency) - 1));
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &volume_rate->amount));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
-+ volume_rate->unit));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the AOCSCurrencyInfo type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param currency_info Currency information record to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOCSCurrencyInfo(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCSCurrencyInfo *currency_info)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ currency_info->charged_item));
-+
-+ switch (currency_info->currency_type) {
-+ case 0: /* specialChargingCode */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ currency_info->u.special_charging_code));
-+ break;
-+ case 1: /* durationCurrency */
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_DurationCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &currency_info->u.duration));
-+ break;
-+ case 2: /* flatRateCurrency */
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_FlatRateCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &currency_info->u.flat_rate));
-+ break;
-+ case 3: /* volumeRateCurrency */
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_VolumeRateCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 3, &currency_info->u.volume_rate));
-+ break;
-+ case 4: /* freeOfCharge */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4));
-+ break;
-+ case 5: /* currencyInfoNotAvailable */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown currency type");
-+ return NULL;
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the AOCSCurrencyInfoList type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param currency_info Currency information list to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOCSCurrencyInfoList(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCSCurrencyInfoList *currency_info)
-+{
-+ unsigned index;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ for (index = 0; index < currency_info->num_records; ++index) {
-+ ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfo(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &currency_info->list[index]));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the RecordedUnits type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param recorded Recorded units information record to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOC_RecordedUnits(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCRecordedUnits *recorded)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ if (recorded->not_available) {
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ } else {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ recorded->number_of_units));
-+ }
-+
-+ if (recorded->type_of_unit_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ recorded->type_of_unit));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the RecordedUnitsList type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param recorded_info Recorded units information list to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOC_RecordedUnitsList(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCRecordedUnitsList *recorded_info)
-+{
-+ unsigned index;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ for (index = 0; index < recorded_info->num_records; ++index) {
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedUnits(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &recorded_info->list[index]));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the ChargingAssociation type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param charging Charging association information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOC_ChargingAssociation(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end,
-+ const struct roseEtsiAOCChargingAssociation *charging)
-+{
-+ unsigned char *explicit_len;
-+
-+ switch (charging->type) {
-+ case 0: /* charge_identifier */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, charging->id));
-+ break;
-+ case 1: /* charged_number */
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &charging->number));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown ChargingAssociation type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the AOCECurrencyInfo type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param currency_info Currency information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOCECurrencyInfo(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCECurrencyInfo *currency_info)
-+{
-+ unsigned char *seq_len;
-+ unsigned char *specific_seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ if (currency_info->free_of_charge) {
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
-+ } else {
-+ ASN1_CONSTRUCTED_BEGIN(specific_seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &currency_info->specific.recorded));
-+
-+ if (currency_info->specific.billing_id_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ currency_info->specific.billing_id));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(specific_seq_len, pos, end);
-+ }
-+
-+ if (currency_info->charging_association_present) {
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_ChargingAssociation(ctrl, pos, end,
-+ &currency_info->charging_association));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the AOCEChargingUnitInfo type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param charging_unit Charging unit information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_AOCEChargingUnitInfo(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiAOCEChargingUnitInfo *charging_unit)
-+{
-+ unsigned char *seq_len;
-+ unsigned char *specific_seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ if (charging_unit->free_of_charge) {
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
-+ } else {
-+ ASN1_CONSTRUCTED_BEGIN(specific_seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedUnitsList(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &charging_unit->specific.recorded));
-+
-+ if (charging_unit->specific.billing_id_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ charging_unit->specific.billing_id));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(specific_seq_len, pos, end);
-+ }
-+
-+ if (charging_unit->charging_association_present) {
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_ChargingAssociation(ctrl, pos, end,
-+ &charging_unit->charging_association));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the ChargingRequest invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ args->etsi.ChargingRequest.charging_case);
-+}
-+
-+/*!
-+ * \brief Encode the ChargingRequest result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ switch (args->etsi.ChargingRequest.type) {
-+ case 0: /* currency_info_list */
-+ ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
-+ ASN1_TAG_SEQUENCE, &args->etsi.ChargingRequest.u.currency_info));
-+ break;
-+ case 1: /* special_arrangement_info */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ args->etsi.ChargingRequest.u.special_arrangement));
-+ break;
-+ case 2: /* charging_info_follows */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown ChargingRequst type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the AOCSCurrency invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ switch (args->etsi.AOCSCurrency.type) {
-+ case 0: /* charge_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ break;
-+ case 1: /* currency_info_list */
-+ ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
-+ ASN1_TAG_SEQUENCE, &args->etsi.AOCSCurrency.currency_info));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown AOCSCurrency type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the AOCSSpecialArr invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ switch (args->etsi.AOCSSpecialArr.type) {
-+ case 0: /* charge_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ break;
-+ case 1: /* special_arrangement_info */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ args->etsi.AOCSSpecialArr.special_arrangement));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown AOCSSpecialArr type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the AOCDCurrency invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiAOCDCurrency_ARG *aoc_d;
-+ unsigned char *seq_len;
-+
-+ aoc_d = &args->etsi.AOCDCurrency;
-+ switch (aoc_d->type) {
-+ case 0: /* charge_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ break;
-+ case 1: /* free_of_charge */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
-+ break;
-+ case 2: /* specific_currency */
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedCurrency(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_d->specific.recorded));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ aoc_d->specific.type_of_charging_info));
-+ if (aoc_d->specific.billing_id_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
-+ aoc_d->specific.billing_id));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown AOCDCurrency type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the AOCDChargingUnit invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiAOCDChargingUnit_ARG *aoc_d;
-+ unsigned char *seq_len;
-+
-+ aoc_d = &args->etsi.AOCDChargingUnit;
-+ switch (aoc_d->type) {
-+ case 0: /* charge_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ break;
-+ case 1: /* free_of_charge */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
-+ break;
-+ case 2: /* specific_charging_units */
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedUnitsList(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_d->specific.recorded));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ aoc_d->specific.type_of_charging_info));
-+ if (aoc_d->specific.billing_id_present) {
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
-+ aoc_d->specific.billing_id));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown AOCDChargingUnit type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the AOCECurrency invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ switch (args->etsi.AOCECurrency.type) {
-+ case 0: /* charge_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ break;
-+ case 1: /* currency_info */
-+ ASN1_CALL(pos, rose_enc_etsi_AOCECurrencyInfo(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &args->etsi.AOCECurrency.currency_info));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown AOCECurrency type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the AOCEChargingUnit invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ switch (args->etsi.AOCEChargingUnit.type) {
-+ case 0: /* charge_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
-+ break;
-+ case 1: /* charging_unit */
-+ ASN1_CALL(pos, rose_enc_etsi_AOCEChargingUnitInfo(ctrl, pos, end,
-+ ASN1_TAG_SEQUENCE, &args->etsi.AOCEChargingUnit.charging_unit));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown AOCEChargingUnit type");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the Time type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param time Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOC_Time(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCTime *time)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s Time %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "lengthOfTimeUnit", tag, pos, seq_end, &value));
-+ time->length = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "scale", tag, pos, seq_end, &value));
-+ time->scale = value;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the Amount type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param amount Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOC_Amount(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCAmount *amount)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s Amount %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "currencyAmount", tag, pos, seq_end, &value));
-+ amount->currency = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "multiplier", tag, pos, seq_end, &value));
-+ amount->multiplier = value;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the RecordedCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param recorded Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOC_RecordedCurrency(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCRecordedCurrency *recorded)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ size_t str_len;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s RecordedCurrency %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "rCurrency", tag, pos, seq_end,
-+ sizeof(recorded->currency), recorded->currency, &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "rAmount", tag, pos, seq_end,
-+ &recorded->amount));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the DurationCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param duration Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOC_DurationCurrency(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCDurationCurrency *duration)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ size_t str_len;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s DurationCurrency %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "dCurrency", tag, pos, seq_end,
-+ sizeof(duration->currency), duration->currency, &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "dAmount", tag, pos, seq_end,
-+ &duration->amount));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "dChargingType", tag, pos, seq_end, &value));
-+ duration->charging_type = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_Time(ctrl, "dTime", tag, pos, seq_end,
-+ &duration->time));
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_Time(ctrl, "dGranularity", tag, pos, seq_end,
-+ &duration->granularity));
-+ duration->granularity_present = 1;
-+ } else {
-+ duration->granularity_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the FlatRateCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param flat_rate Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOC_FlatRateCurrency(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCFlatRateCurrency *flat_rate)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ size_t str_len;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s FlatRateCurrency %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "fRCurrency", tag, pos, seq_end,
-+ sizeof(flat_rate->currency), flat_rate->currency, &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "fRAmount", tag, pos, seq_end,
-+ &flat_rate->amount));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the VolumeRateCurrency type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param volume_rate Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOC_VolumeRateCurrency(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCVolumeRateCurrency *volume_rate)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ size_t str_len;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s VolumeRateCurrency %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "vRCurrency", tag, pos, seq_end,
-+ sizeof(volume_rate->currency), volume_rate->currency, &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "vRAmount", tag, pos, seq_end,
-+ &volume_rate->amount));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "vRVolumeUnit", tag, pos, seq_end, &value));
-+ volume_rate->unit = value;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the AOCSCurrencyInfo type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param currency_info Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOCSCurrencyInfo(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCSCurrencyInfo *currency_info)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s AOCSCurrencyInfo %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargedItem", tag, pos, seq_end, &value));
-+ currency_info->charged_item = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_TYPE_INTEGER:
-+ currency_info->currency_type = 0; /* specialChargingCode */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "specialChargingCode", tag, pos, seq_end,
-+ &value));
-+ currency_info->u.special_charging_code = value;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ currency_info->currency_type = 1; /* durationCurrency */
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_DurationCurrency(ctrl, "durationCurrency", tag,
-+ pos, seq_end, &currency_info->u.duration));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ currency_info->currency_type = 2; /* flatRateCurrency */
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_FlatRateCurrency(ctrl, "flatRateCurrency", tag,
-+ pos, seq_end, &currency_info->u.flat_rate));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
-+ currency_info->currency_type = 3; /* volumeRateCurrency */
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_VolumeRateCurrency(ctrl, "volumeRateCurrency",
-+ tag, pos, seq_end, &currency_info->u.volume_rate));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ currency_info->currency_type = 4; /* freeOfCharge */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
-+ currency_info->currency_type = 5; /* currencyInfoNotAvailable */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "currencyInfoNotAvailable", tag, pos,
-+ seq_end));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the AOCSCurrencyInfoList type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param currency_info Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOCSCurrencyInfoList(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCSCurrencyInfoList *currency_info)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s AOCSCurrencyInfoList %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ currency_info->num_records = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ if (currency_info->num_records < ARRAY_LEN(currency_info->list)) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_etsi_AOCSCurrencyInfo(ctrl, "listEntry", tag, pos,
-+ seq_end, &currency_info->list[currency_info->num_records]));
-+ ++currency_info->num_records;
-+ } else {
-+ /* Too many records */
-+ return NULL;
-+ }
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the RecordedUnits type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param recorded Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOC_RecordedUnits(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCRecordedUnits *recorded)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s RecordedUnits %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_TYPE_INTEGER:
-+ recorded->not_available = 0;
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "recordedNumberOfUnits", tag, pos, seq_end,
-+ &value));
-+ recorded->number_of_units = value;
-+ break;
-+ case ASN1_TYPE_NULL:
-+ recorded->not_available = 1;
-+ recorded->number_of_units = 0;
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "notAvailable", tag, pos, seq_end));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "recordedTypeOfUnits", tag, pos, seq_end,
-+ &value));
-+ recorded->type_of_unit = value;
-+ recorded->type_of_unit_present = 1;
-+ } else {
-+ recorded->type_of_unit_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the RecordedUnitsList type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param recorded_info Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOC_RecordedUnitsList(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCRecordedUnitsList *recorded_info)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s RecordedUnitsList %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ recorded_info->num_records = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ if (recorded_info->num_records < ARRAY_LEN(recorded_info->list)) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedUnits(ctrl, "listEntry", tag, pos,
-+ seq_end, &recorded_info->list[recorded_info->num_records]));
-+ ++recorded_info->num_records;
-+ } else {
-+ /* Too many records */
-+ return NULL;
-+ }
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the ChargingAssociation type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param charging Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOC_ChargingAssociation(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCChargingAssociation *charging)
-+{
-+ int32_t value;
-+ int length;
-+ int explicit_offset;
-+ const unsigned char *explicit_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s ChargingAssociation\n", name);
-+ }
-+ switch (tag) {
-+ case ASN1_TYPE_INTEGER:
-+ charging->type = 0; /* charge_identifier */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargeIdentifier", tag, pos, end, &value));
-+ charging->id = value;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ charging->type = 1; /* charged_number */
-+
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "chargedNumber", tag, pos,
-+ explicit_end, &charging->number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the AOCECurrencyInfo type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param currency_info Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOCECurrencyInfo(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCECurrencyInfo *currency_info)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ int specific_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *specific_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s AOCECurrencyInfo %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ currency_info->free_of_charge = 1;
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ currency_info->free_of_charge = 0;
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
-+ pos, specific_end, &currency_info->specific.recorded));
-+
-+ if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, specific_end,
-+ &value));
-+ currency_info->specific.billing_id = value;
-+ currency_info->specific.billing_id_present = 1;
-+ } else {
-+ currency_info->specific.billing_id_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_ChargingAssociation(ctrl, "chargingAssociation",
-+ tag, pos, seq_end, &currency_info->charging_association));
-+ currency_info->charging_association_present = 1;
-+ } else {
-+ currency_info->charging_association_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the AOCEChargingUnitInfo type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param charging_unit Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_AOCEChargingUnitInfo(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiAOCEChargingUnitInfo *charging_unit)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ int specific_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *specific_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s AOCEChargingUnitInfo %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ charging_unit->free_of_charge = 1;
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ charging_unit->free_of_charge = 0;
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " specificChargingUnits %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedUnitsList(ctrl, "recordedUnitsList",
-+ tag, pos, specific_end, &charging_unit->specific.recorded));
-+
-+ if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, specific_end,
-+ &value));
-+ charging_unit->specific.billing_id = value;
-+ charging_unit->specific.billing_id_present = 1;
-+ } else {
-+ charging_unit->specific.billing_id_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_ChargingAssociation(ctrl, "chargingAssociation",
-+ tag, pos, seq_end, &charging_unit->charging_association));
-+ charging_unit->charging_association_present = 1;
-+ } else {
-+ charging_unit->charging_association_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the ChargingRequest invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargingCase", tag, pos, end, &value));
-+ args->etsi.ChargingRequest.charging_case = value;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the ChargingRequest result parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
-+{
-+ struct roseEtsiChargingRequest_RES *charging_request;
-+ int32_t value;
-+
-+ charging_request = &args->etsi.ChargingRequest;
-+ switch (tag) {
-+ case ASN1_TAG_SEQUENCE:
-+ charging_request->type = 0; /* currency_info_list */
-+ ASN1_CALL(pos, rose_dec_etsi_AOCSCurrencyInfoList(ctrl, "currencyList", tag, pos,
-+ end, &charging_request->u.currency_info));
-+ break;
-+ case ASN1_TYPE_INTEGER:
-+ charging_request->type = 1; /* special_arrangement_info */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "specialArrangement", tag, pos, end, &value));
-+ charging_request->u.special_arrangement = value;
-+ break;
-+ case ASN1_TYPE_NULL:
-+ charging_request->type = 2; /* charging_info_follows */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargingInfoFollows", tag, pos, end));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the AOCSCurrency invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiAOCSCurrency_ARG *aoc_s;
-+
-+ aoc_s = &args->etsi.AOCSCurrency;
-+ switch (tag) {
-+ case ASN1_TYPE_NULL:
-+ aoc_s->type = 0; /* charge_not_available */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ aoc_s->type = 1; /* currency_info_list */
-+ ASN1_CALL(pos, rose_dec_etsi_AOCSCurrencyInfoList(ctrl, "currencyInfo", tag, pos,
-+ end, &aoc_s->currency_info));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the AOCSSpecialArr invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiAOCSSpecialArr_ARG *aoc_s;
-+ int32_t value;
-+
-+ aoc_s = &args->etsi.AOCSSpecialArr;
-+ switch (tag) {
-+ case ASN1_TYPE_NULL:
-+ aoc_s->type = 0; /* charge_not_available */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
-+ break;
-+ case ASN1_TYPE_INTEGER:
-+ aoc_s->type = 1; /* special_arrangement_info */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "specialArrangement", tag, pos, end, &value));
-+ aoc_s->special_arrangement = value;
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the AOCDCurrency invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiAOCDCurrency_ARG *aoc_d;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ aoc_d = &args->etsi.AOCDCurrency;
-+ switch (tag) {
-+ case ASN1_TYPE_NULL:
-+ aoc_d->type = 0; /* charge_not_available */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ aoc_d->type = 1; /* free_of_charge */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ aoc_d->type = 2; /* specific_currency */
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
-+ pos, seq_end, &aoc_d->specific.recorded));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfChargingInfo", tag, pos, seq_end,
-+ &value));
-+ aoc_d->specific.type_of_charging_info = value;
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, seq_end, &value));
-+ aoc_d->specific.billing_id = value;
-+ aoc_d->specific.billing_id_present = 1;
-+ } else {
-+ aoc_d->specific.billing_id_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the AOCDChargingUnit invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiAOCDChargingUnit_ARG *aoc_d;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ aoc_d = &args->etsi.AOCDChargingUnit;
-+ switch (tag) {
-+ case ASN1_TYPE_NULL:
-+ aoc_d->type = 0; /* charge_not_available */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ aoc_d->type = 1; /* free_of_charge */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ aoc_d->type = 2; /* specific_charging_units */
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " specificChargingUnits %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
-+ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedUnitsList(ctrl, "recordedUnitsList",
-+ tag, pos, seq_end, &aoc_d->specific.recorded));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfChargingInfo", tag, pos, seq_end,
-+ &value));
-+ aoc_d->specific.type_of_charging_info = value;
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, seq_end, &value));
-+ aoc_d->specific.billing_id = value;
-+ aoc_d->specific.billing_id_present = 1;
-+ } else {
-+ aoc_d->specific.billing_id_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the AOCECurrency invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiAOCECurrency_ARG *aoc_e;
-+
-+ aoc_e = &args->etsi.AOCECurrency;
-+ switch (tag) {
-+ case ASN1_TYPE_NULL:
-+ aoc_e->type = 0; /* charge_not_available */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ aoc_e->type = 1; /* currency_info */
-+ ASN1_CALL(pos, rose_dec_etsi_AOCECurrencyInfo(ctrl, "currencyInfo", tag, pos,
-+ end, &aoc_e->currency_info));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the AOCEChargingUnit invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiAOCEChargingUnit_ARG *aoc_e;
-+
-+ aoc_e = &args->etsi.AOCEChargingUnit;
-+ switch (tag) {
-+ case ASN1_TYPE_NULL:
-+ aoc_e->type = 0; /* charge_not_available */
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
-+ break;
-+ case ASN1_TAG_SEQUENCE:
-+ aoc_e->type = 1; /* charging_unit */
-+ ASN1_CALL(pos, rose_dec_etsi_AOCEChargingUnitInfo(ctrl, "chargingUnitInfo", tag,
-+ pos, end, &aoc_e->charging_unit));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_etsi_aoc.c */
-
-Property changes on: rose_etsi_aoc.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_etsi_diversion.c
-===================================================================
---- a/rose_etsi_diversion.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_etsi_diversion.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,1623 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief ROSE Call diversion operations
-+ *
-+ * Diversion Supplementary Services ETS 300 207-1 Table 3
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the ServedUserNr type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param served_user_number Served user number information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_ServedUserNumber(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end,
-+ const struct rosePartyNumber *served_user_number)
-+{
-+ if (served_user_number->length) {
-+ /* Forward this number */
-+ pos = rose_enc_PartyNumber(ctrl, pos, end, served_user_number);
-+ } else {
-+ /* Forward all numbers */
-+ pos = asn1_enc_null(pos, end, ASN1_TYPE_NULL);
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the IntResult type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
-+ * tags it otherwise.
-+ * \param int_result Forwarding record information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_IntResult(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseEtsiForwardingRecord *int_result)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
-+ &int_result->served_user_number));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ int_result->basic_service));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, int_result->procedure));
-+ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &int_result->forwarded_to));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the IntResultList type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SET unless the caller implicitly
-+ * tags it otherwise.
-+ * \param int_result_list Forwarding record list information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_IntResultList(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag,
-+ const struct roseEtsiForwardingList *int_result_list)
-+{
-+ unsigned index;
-+ unsigned char *set_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(set_len, pos, end, tag);
-+
-+ for (index = 0; index < int_result_list->num_records; ++index) {
-+ ASN1_CALL(pos, rose_enc_etsi_IntResult(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &int_result_list->list[index]));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(set_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the ServedUserNumberList type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SET unless the caller implicitly
-+ * tags it otherwise.
-+ * \param served_user_number_list Served user record list information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_etsi_ServedUserNumberList(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, unsigned tag,
-+ const struct roseEtsiServedUserNumberList *served_user_number_list)
-+{
-+ unsigned index;
-+ unsigned char *set_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(set_len, pos, end, tag);
-+
-+ for (index = 0; index < served_user_number_list->num_records; ++index) {
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &served_user_number_list->number[index]));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(set_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the ActivationDiversion invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_ActivationDiversion_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiActivationDiversion_ARG *activation_diversion;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ activation_diversion = &args->etsi.ActivationDiversion;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ activation_diversion->procedure));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ activation_diversion->basic_service));
-+ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &activation_diversion->forwarded_to));
-+ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
-+ &activation_diversion->served_user_number));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the DeactivationDiversion invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiDeactivationDiversion_ARG *deactivation_diversion;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ deactivation_diversion = &args->etsi.DeactivationDiversion;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ deactivation_diversion->procedure));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ deactivation_diversion->basic_service));
-+ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
-+ &deactivation_diversion->served_user_number));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the ActivationStatusNotificationDiv invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiActivationStatusNotificationDiv_ARG
-+ *activation_status_notification_div;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ activation_status_notification_div = &args->etsi.ActivationStatusNotificationDiv;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ activation_status_notification_div->procedure));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ activation_status_notification_div->basic_service));
-+ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &activation_status_notification_div->forwarded_to));
-+ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
-+ &activation_status_notification_div->served_user_number));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the DeactivationStatusNotificationDiv invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_DeactivationStatusNotificationDiv_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiDeactivationStatusNotificationDiv_ARG
-+ *deactivation_status_notification_div;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ deactivation_status_notification_div = &args->etsi.DeactivationStatusNotificationDiv;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ deactivation_status_notification_div->procedure));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ deactivation_status_notification_div->basic_service));
-+ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
-+ &deactivation_status_notification_div->served_user_number));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the InterrogationDiversion invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiInterrogationDiversion_ARG *interrogation_diversion;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ interrogation_diversion = &args->etsi.InterrogationDiversion;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ interrogation_diversion->procedure));
-+ if (interrogation_diversion->basic_service) {
-+ /* Not the DEFAULT value */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ interrogation_diversion->basic_service));
-+ }
-+ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
-+ &interrogation_diversion->served_user_number));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the InterrogationDiversion result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_InterrogationDiversion_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ return rose_enc_etsi_IntResultList(ctrl, pos, end, ASN1_TAG_SET,
-+ &args->etsi.InterrogationDiversion);
-+}
-+
-+/*!
-+ * \brief Encode the DiversionInformation invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_DiversionInformation_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiDiversionInformation_ARG *diversion_information;
-+ unsigned char *seq_len;
-+ unsigned char *explicit_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ diversion_information = &args->etsi.DiversionInformation;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ diversion_information->diversion_reason));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ diversion_information->basic_service));
-+ if (diversion_information->served_user_subaddress.length) {
-+ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
-+ &diversion_information->served_user_subaddress));
-+ }
-+ if (diversion_information->calling_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
-+ ASN1_CALL(pos, rose_enc_PresentedAddressScreened(ctrl, pos, end,
-+ &diversion_information->calling));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+ if (diversion_information->original_called_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &diversion_information->original_called));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+ if (diversion_information->last_diverting_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &diversion_information->last_diverting));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+ if (diversion_information->last_diverting_reason_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ diversion_information->last_diverting_reason));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+ if (diversion_information->q931ie.length) {
-+ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
-+ &diversion_information->q931ie));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the CallDeflection invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiCallDeflection_ARG *call_deflection;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ call_deflection = &args->etsi.CallDeflection;
-+ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &call_deflection->deflection));
-+ if (call_deflection->presentation_allowed_to_diverted_to_user_present) {
-+ ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
-+ call_deflection->presentation_allowed_to_diverted_to_user));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the CallRerouting invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiCallRerouting_ARG *call_rerouting;
-+ unsigned char *seq_len;
-+ unsigned char *explicit_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ call_rerouting = &args->etsi.CallRerouting;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ call_rerouting->rerouting_reason));
-+ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
-+ &call_rerouting->called_address));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ call_rerouting->rerouting_counter));
-+ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
-+ &call_rerouting->q931ie));
-+
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &call_rerouting->last_rerouting));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+
-+ if (call_rerouting->subscription_option) {
-+ /* Not the DEFAULT value */
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ call_rerouting->subscription_option));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+
-+ if (call_rerouting->calling_subaddress.length) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
-+ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
-+ &call_rerouting->calling_subaddress));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the InterrogateServedUserNumbers result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ return rose_enc_etsi_ServedUserNumberList(ctrl, pos, end, ASN1_TAG_SET,
-+ &args->etsi.InterrogateServedUserNumbers);
-+}
-+
-+/*!
-+ * \brief Encode the DivertingLegInformation1 invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiDivertingLegInformation1_ARG *diverting_leg_information_1;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ diverting_leg_information_1 = &args->etsi.DivertingLegInformation1;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ diverting_leg_information_1->diversion_reason));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ diverting_leg_information_1->subscription_option));
-+ if (diverting_leg_information_1->diverted_to_present) {
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &diverting_leg_information_1->diverted_to));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the DivertingLegInformation2 invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiDivertingLegInformation2_ARG *diverting_leg_information_2;
-+ unsigned char *seq_len;
-+ unsigned char *explicit_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ diverting_leg_information_2 = &args->etsi.DivertingLegInformation2;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ diverting_leg_information_2->diversion_counter));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ diverting_leg_information_2->diversion_reason));
-+
-+ if (diverting_leg_information_2->diverting_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &diverting_leg_information_2->diverting));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+
-+ if (diverting_leg_information_2->original_called_present) {
-+ /* EXPLICIT tag */
-+ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &diverting_leg_information_2->original_called));
-+ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the DivertingLegInformation3 invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
-+ args->etsi.DivertingLegInformation3.presentation_allowed_indicator);
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the ServedUserNr argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param served_user_number Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_ServedUserNumber(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct rosePartyNumber *served_user_number)
-+{
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s ServedUserNumber\n", name);
-+ }
-+ if (tag == ASN1_TYPE_NULL) {
-+ served_user_number->length = 0;
-+ pos = asn1_dec_null(ctrl, "allNumbers", tag, pos, end);
-+ } else {
-+ /* Must be a PartyNumber (Which is itself a CHOICE) */
-+ pos =
-+ rose_dec_PartyNumber(ctrl, "individualNumber", tag, pos, end,
-+ served_user_number);
-+ }
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the IntResult argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param int_result Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_IntResult(struct pri *ctrl, const char *name,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiForwardingRecord *int_result)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s IntResult %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
-+ seq_end, &int_result->served_user_number));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ int_result->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ int_result->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_Address(ctrl, "forwardedToAddress", tag, pos, seq_end,
-+ &int_result->forwarded_to));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the IntResultList argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param int_result_list Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_IntResultList(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiForwardingList *int_result_list)
-+{
-+ int length;
-+ int set_offset;
-+ const unsigned char *set_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s IntResultList %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(set_end, set_offset, length, pos, end);
-+
-+ int_result_list->num_records = 0;
-+ while (pos < set_end && *pos != ASN1_INDEF_TERM) {
-+ if (int_result_list->num_records < ARRAY_LEN(int_result_list->list)) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, set_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_etsi_IntResult(ctrl, "listEntry", tag, pos, set_end,
-+ &int_result_list->list[int_result_list->num_records]));
-+ ++int_result_list->num_records;
-+ } else {
-+ /* Too many records */
-+ return NULL;
-+ }
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, set_offset, set_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the ServedUserNumberList argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param served_user_number_list Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_etsi_ServedUserNumberList(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseEtsiServedUserNumberList *served_user_number_list)
-+{
-+ int length;
-+ int set_offset;
-+ const unsigned char *set_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s ServedUserNumberList %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(set_end, set_offset, length, pos, end);
-+
-+ served_user_number_list->num_records = 0;
-+ while (pos < set_end && *pos != ASN1_INDEF_TERM) {
-+ if (served_user_number_list->num_records <
-+ ARRAY_LEN(served_user_number_list->number)) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, set_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "listEntry", tag, pos, set_end,
-+ &served_user_number_list->number[served_user_number_list->num_records]));
-+ ++served_user_number_list->num_records;
-+ } else {
-+ /* Too many records */
-+ return NULL;
-+ }
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, set_offset, set_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the ActivationDiversion invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_ActivationDiversion_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiActivationDiversion_ARG *activation_diversion;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " ActivationDiversion %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ activation_diversion = &args->etsi.ActivationDiversion;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ activation_diversion->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ activation_diversion->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_Address(ctrl, "forwardedToAddress", tag, pos, seq_end,
-+ &activation_diversion->forwarded_to));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
-+ seq_end, &activation_diversion->served_user_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the DeactivationDiversion invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiDeactivationDiversion_ARG *deactivation_diversion;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " DeactivationDiversion %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ deactivation_diversion = &args->etsi.DeactivationDiversion;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ deactivation_diversion->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ deactivation_diversion->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
-+ seq_end, &deactivation_diversion->served_user_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the ActivationStatusNotificationDiv invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiActivationStatusNotificationDiv_ARG
-+ *activation_status_notification_div;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " ActivationStatusNotificationDiv %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ activation_status_notification_div = &args->etsi.ActivationStatusNotificationDiv;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ activation_status_notification_div->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ activation_status_notification_div->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_Address(ctrl, "forwardedToAddress", tag, pos, seq_end,
-+ &activation_status_notification_div->forwarded_to));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
-+ seq_end, &activation_status_notification_div->served_user_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the DeactivationStatusNotificationDiv invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_DeactivationStatusNotificationDiv_ARG(struct pri
-+ *ctrl, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiDeactivationStatusNotificationDiv_ARG
-+ *deactivation_status_notification_div;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " DeactivationStatusNotificationDiv %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ deactivation_status_notification_div = &args->etsi.DeactivationStatusNotificationDiv;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ deactivation_status_notification_div->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ deactivation_status_notification_div->basic_service = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "forwardedToAddress", tag, pos,
-+ seq_end, &deactivation_status_notification_div->served_user_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the InterrogationDiversion invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiInterrogationDiversion_ARG *interrogation_diversion;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " InterrogationDiversion %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ interrogation_diversion = &args->etsi.InterrogationDiversion;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
-+ interrogation_diversion->procedure = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ if (tag == ASN1_TYPE_ENUMERATED) {
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ } else {
-+ value = 0; /* DEFAULT BasicService value (allServices) */
-+ }
-+ interrogation_diversion->basic_service = value;
-+
-+ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
-+ seq_end, &interrogation_diversion->served_user_number));
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the InterrogationDiversion result parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_InterrogationDiversion_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args)
-+{
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SET);
-+ return rose_dec_etsi_IntResultList(ctrl, "diversionList", tag, pos, end,
-+ &args->etsi.InterrogationDiversion);
-+}
-+
-+/*!
-+ * \brief Decode the DiversionInformation invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_DiversionInformation_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiDiversionInformation_ARG *diversion_information;
-+ int length;
-+ int seq_offset;
-+ int explicit_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *explicit_end;
-+ const unsigned char *save_pos;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " DiversionInformation %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ diversion_information = &args->etsi.DiversionInformation;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
-+ diversion_information->diversion_reason = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
-+ diversion_information->basic_service = value;
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ diversion_information->served_user_subaddress.length = 0;
-+ diversion_information->calling_present = 0;
-+ diversion_information->original_called_present = 0;
-+ diversion_information->last_diverting_present = 0;
-+ diversion_information->last_diverting_reason_present = 0;
-+ diversion_information->q931ie.length = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_TAG_SEQUENCE:
-+ case ASN1_TYPE_OCTET_STRING:
-+ case ASN1_TYPE_OCTET_STRING | ASN1_PC_CONSTRUCTED:
-+ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "servedUserSubaddress", tag,
-+ pos, seq_end, &diversion_information->served_user_subaddress));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedAddressScreened(ctrl, "callingAddress", tag,
-+ pos, explicit_end, &diversion_information->calling));
-+ diversion_information->calling_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "originalCalledNr",
-+ tag, pos, explicit_end, &diversion_information->original_called));
-+ diversion_information->original_called_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "lastDivertingNr",
-+ tag, pos, explicit_end, &diversion_information->last_diverting));
-+ diversion_information->last_diverting_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "lastDivertingReason", tag, pos,
-+ explicit_end, &value));
-+ diversion_information->last_diverting_reason = value;
-+ diversion_information->last_diverting_reason_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_APPLICATION | 0:
-+ case ASN1_CLASS_APPLICATION | ASN1_PC_CONSTRUCTED | 0:
-+ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "userInfo", tag, pos, seq_end,
-+ &diversion_information->q931ie,
-+ sizeof(diversion_information->q931ie_contents)));
-+ break;
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the CallDeflection invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiCallDeflection_ARG *call_deflection;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CallDeflection %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ call_deflection = &args->etsi.CallDeflection;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_Address(ctrl, "deflectionAddress", tag, pos, seq_end,
-+ &call_deflection->deflection));
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN);
-+ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "presentationAllowedDivertedToUser", tag,
-+ pos, seq_end, &value));
-+ call_deflection->presentation_allowed_to_diverted_to_user = value;
-+ call_deflection->presentation_allowed_to_diverted_to_user_present = 1;
-+ } else {
-+ call_deflection->presentation_allowed_to_diverted_to_user_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the CallRerouting invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiCallRerouting_ARG *call_rerouting;
-+ int length;
-+ int seq_offset;
-+ int explicit_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *explicit_end;
-+ const unsigned char *save_pos;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CallRerouting %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ call_rerouting = &args->etsi.CallRerouting;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "reroutingReason", tag, pos, seq_end, &value));
-+ call_rerouting->rerouting_reason = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ ASN1_CALL(pos, rose_dec_Address(ctrl, "calledAddress", tag, pos, seq_end,
-+ &call_rerouting->called_address));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "reroutingCounter", tag, pos, seq_end, &value));
-+ call_rerouting->rerouting_counter = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_CLASS_APPLICATION | 0);
-+ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "q931ie", tag, pos, seq_end,
-+ &call_rerouting->q931ie, sizeof(call_rerouting->q931ie_contents)));
-+
-+ /* Remove EXPLICIT tag */
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "lastReroutingNr", tag, pos,
-+ explicit_end, &call_rerouting->last_rerouting));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ call_rerouting->subscription_option = 0; /* DEFAULT value noNotification */
-+ call_rerouting->calling_subaddress.length = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "subscriptionOption", tag, pos,
-+ explicit_end, &value));
-+ call_rerouting->subscription_option = value;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "callingPartySubaddress", tag,
-+ pos, explicit_end, &call_rerouting->calling_subaddress));
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the InterrogateServedUserNumbers result parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args)
-+{
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SET);
-+ return rose_dec_etsi_ServedUserNumberList(ctrl, "interrogateServedUserNumbers", tag,
-+ pos, end, &args->etsi.InterrogateServedUserNumbers);
-+}
-+
-+/*!
-+ * \brief Decode the DivertingLegInformation1 invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiDivertingLegInformation1_ARG *diverting_leg_informtion_1;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " DivertingLegInformation1 %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ diverting_leg_informtion_1 = &args->etsi.DivertingLegInformation1;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
-+ diverting_leg_informtion_1->diversion_reason = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "subscriptionOption", tag, pos, seq_end, &value));
-+ diverting_leg_informtion_1->subscription_option = value;
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "divertedToNumber", tag,
-+ pos, seq_end, &diverting_leg_informtion_1->diverted_to));
-+ diverting_leg_informtion_1->diverted_to_present = 1;
-+ } else {
-+ diverting_leg_informtion_1->diverted_to_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the DivertingLegInformation2 invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiDivertingLegInformation2_ARG *diverting_leg_information_2;
-+ int length;
-+ int seq_offset;
-+ int explicit_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *explicit_end;
-+ const unsigned char *save_pos;
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " DivertingLegInformation2 %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ diverting_leg_information_2 = &args->etsi.DivertingLegInformation2;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionCounter", tag, pos, seq_end, &value));
-+ diverting_leg_information_2->diversion_counter = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
-+ diverting_leg_information_2->diversion_reason = value;
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ diverting_leg_information_2->diverting_present = 0;
-+ diverting_leg_information_2->original_called_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "divertingNr", tag,
-+ pos, explicit_end, &diverting_leg_information_2->diverting));
-+ diverting_leg_information_2->diverting_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ /* Remove EXPLICIT tag */
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
-+ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "originalCalledNr",
-+ tag, pos, explicit_end, &diverting_leg_information_2->original_called));
-+ diverting_leg_information_2->original_called_present = 1;
-+
-+ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
-+ break;
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the DivertingLegInformation3 invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN);
-+ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "presentationAllowedIndicator", tag, pos, end,
-+ &value));
-+ args->etsi.DivertingLegInformation3.presentation_allowed_indicator = value;
-+
-+ return pos;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_etsi_diversion.c */
-
-Property changes on: rose_etsi_diversion.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_qsig_ct.c
-===================================================================
---- a/rose_qsig_ct.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_qsig_ct.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,883 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Q.SIG ROSE Call-Transfer-Operations (CT)
-+ *
-+ * Call-Transfer-Operations ECMA-178 Annex F Table F.1
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \brief Encode the Q.SIG CallTransferIdentify result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CallTransferIdentify_RES(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigCTIdentifyRes_RES *call_transfer_identify;
-+
-+ call_transfer_identify = &args->qsig.CallTransferIdentify;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_NUMERIC_STRING,
-+ call_transfer_identify->call_id, sizeof(call_transfer_identify->call_id) - 1));
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &call_transfer_identify->rerouting_number));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG CallTransferInitiate invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigCTInitiateArg_ARG *call_transfer_initiate;
-+
-+ call_transfer_initiate = &args->qsig.CallTransferInitiate;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_NUMERIC_STRING,
-+ call_transfer_initiate->call_id, sizeof(call_transfer_initiate->call_id) - 1));
-+ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
-+ &call_transfer_initiate->rerouting_number));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG CallTransferSetup invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigCTSetupArg_ARG *call_transfer_setup;
-+
-+ call_transfer_setup = &args->qsig.CallTransferSetup;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_NUMERIC_STRING,
-+ call_transfer_setup->call_id, sizeof(call_transfer_setup->call_id) - 1));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG CallTransferActive invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigCTActiveArg_ARG *call_transfer_active;
-+
-+ call_transfer_active = &args->qsig.CallTransferActive;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_PresentedAddressScreened(ctrl, pos, end,
-+ &call_transfer_active->connected));
-+
-+ if (call_transfer_active->q931ie.length) {
-+ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
-+ &call_transfer_active->q931ie));
-+ }
-+
-+ if (call_transfer_active->connected_name_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
-+ &call_transfer_active->connected_name));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG CallTransferComplete invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CallTransferComplete_ARG(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigCTCompleteArg_ARG *call_transfer_complete;
-+
-+ call_transfer_complete = &args->qsig.CallTransferComplete;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ call_transfer_complete->end_designation));
-+
-+ ASN1_CALL(pos, rose_enc_PresentedNumberScreened(ctrl, pos, end,
-+ &call_transfer_complete->redirection));
-+
-+ if (call_transfer_complete->q931ie.length) {
-+ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
-+ &call_transfer_complete->q931ie));
-+ }
-+
-+ if (call_transfer_complete->redirection_name_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
-+ &call_transfer_complete->redirection_name));
-+ }
-+
-+ if (call_transfer_complete->call_status) {
-+ /* Not the DEFAULT value */
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ call_transfer_complete->call_status));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG CallTransferUpdate invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigCTUpdateArg_ARG *call_transfer_update;
-+
-+ call_transfer_update = &args->qsig.CallTransferUpdate;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_PresentedNumberScreened(ctrl, pos, end,
-+ &call_transfer_update->redirection));
-+
-+ if (call_transfer_update->redirection_name_present) {
-+ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
-+ &call_transfer_update->redirection_name));
-+ }
-+
-+ if (call_transfer_update->q931ie.length) {
-+ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
-+ &call_transfer_update->q931ie));
-+ }
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG SubaddressTransfer invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ unsigned char *seq_len;
-+ const struct roseQsigSubaddressTransferArg_ARG *subaddress_transfer;
-+
-+ subaddress_transfer = &args->qsig.SubaddressTransfer;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
-+ &subaddress_transfer->redirection_subaddress));
-+
-+ /* No extension to encode */
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG DummyArg invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ *
-+ * \details
-+ * DummyArg ::= CHOICE {
-+ * none NULL,
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * }
-+ */
-+unsigned char *rose_enc_qsig_DummyArg_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return asn1_enc_null(pos, end, ASN1_TYPE_NULL);
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG DummyRes result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ *
-+ * \details
-+ * DummyRes ::= CHOICE {
-+ * none NULL,
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * }
-+ */
-+unsigned char *rose_enc_qsig_DummyRes_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ return asn1_enc_null(pos, end, ASN1_TYPE_NULL);
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CallTransferIdentify result argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CallTransferIdentify_RES(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_result_args *args)
-+{
-+ size_t str_len;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigCTIdentifyRes_RES *call_transfer_identify;
-+
-+ call_transfer_identify = &args->qsig.CallTransferIdentify;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CallTransferIdentify %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_NUMERIC_STRING);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "callIdentity", tag, pos, seq_end,
-+ sizeof(call_transfer_identify->call_id), call_transfer_identify->call_id,
-+ &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "reroutingNumber", tag, pos, seq_end,
-+ &call_transfer_identify->rerouting_number));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CallTransferInitiate invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ size_t str_len;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigCTInitiateArg_ARG *call_transfer_initiate;
-+
-+ call_transfer_initiate = &args->qsig.CallTransferInitiate;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CallTransferInitiate %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_NUMERIC_STRING);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "callIdentity", tag, pos, seq_end,
-+ sizeof(call_transfer_initiate->call_id), call_transfer_initiate->call_id,
-+ &str_len));
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "reroutingNumber", tag, pos, seq_end,
-+ &call_transfer_initiate->rerouting_number));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CallTransferSetup invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ size_t str_len;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigCTSetupArg_ARG *call_transfer_setup;
-+
-+ call_transfer_setup = &args->qsig.CallTransferSetup;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CallTransferSetup %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_NUMERIC_STRING);
-+ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "callIdentity", tag, pos, seq_end,
-+ sizeof(call_transfer_setup->call_id), call_transfer_setup->call_id, &str_len));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CallTransferActive invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigCTActiveArg_ARG *call_transfer_active;
-+
-+ call_transfer_active = &args->qsig.CallTransferActive;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CallTransferActive %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedAddressScreened(ctrl, "connectedAddress", tag, pos,
-+ seq_end, &call_transfer_active->connected));
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ call_transfer_active->q931ie.length = 0;
-+ call_transfer_active->connected_name_present = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_CLASS_APPLICATION | 0:
-+ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "basicCallInfoElements", tag, pos,
-+ seq_end, &call_transfer_active->q931ie,
-+ sizeof(call_transfer_active->q931ie_contents)));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "connectedName", tag, pos, seq_end,
-+ &call_transfer_active->connected_name));
-+ call_transfer_active->connected_name_present = 1;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 10:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " argumentExtension %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CallTransferComplete invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CallTransferComplete_ARG(struct pri *ctrl,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigCTCompleteArg_ARG *call_transfer_complete;
-+
-+ call_transfer_complete = &args->qsig.CallTransferComplete;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CallTransferComplete %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "endDesignation", tag, pos, seq_end, &value));
-+ call_transfer_complete->end_designation = value;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberScreened(ctrl, "redirectionNumber", tag, pos,
-+ seq_end, &call_transfer_complete->redirection));
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ call_transfer_complete->q931ie.length = 0;
-+ call_transfer_complete->redirection_name_present = 0;
-+ call_transfer_complete->call_status = 0; /* DEFAULT answered */
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_CLASS_APPLICATION | 0:
-+ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "basicCallInfoElements", tag, pos,
-+ seq_end, &call_transfer_complete->q931ie,
-+ sizeof(call_transfer_complete->q931ie_contents)));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectionName", tag, pos, seq_end,
-+ &call_transfer_complete->redirection_name));
-+ call_transfer_complete->redirection_name_present = 1;
-+ break;
-+ case ASN1_TYPE_ENUMERATED:
-+ /* Must not be constructed but we will not check for it for simplicity. */
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "callStatus", tag, pos, seq_end, &value));
-+ call_transfer_complete->call_status = value;
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 10:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " argumentExtension %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CallTransferUpdate invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ const unsigned char *save_pos;
-+ struct roseQsigCTUpdateArg_ARG *call_transfer_update;
-+
-+ call_transfer_update = &args->qsig.CallTransferUpdate;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " CallTransferUpdate %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberScreened(ctrl, "redirectionNumber", tag, pos,
-+ seq_end, &call_transfer_update->redirection));
-+
-+ /*
-+ * A sequence specifies an ordered list of component types.
-+ * However, for simplicity we are not checking the order of
-+ * the remaining optional components.
-+ */
-+ call_transfer_update->redirection_name_present = 0;
-+ call_transfer_update->q931ie.length = 0;
-+ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ save_pos = pos;
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectionName", tag, pos, seq_end,
-+ &call_transfer_update->redirection_name));
-+ call_transfer_update->redirection_name_present = 1;
-+ break;
-+ case ASN1_CLASS_APPLICATION | 0:
-+ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "basicCallInfoElements", tag, pos,
-+ seq_end, &call_transfer_update->q931ie,
-+ sizeof(call_transfer_update->q931ie_contents)));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 10:
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " argumentExtension %s\n", asn1_tag2str(tag));
-+ }
-+ /* Fixup will skip over the manufacturer extension information */
-+ default:
-+ pos = save_pos;
-+ goto cancel_options;
-+ }
-+ }
-+cancel_options:;
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG SubaddressTransfer invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ struct roseQsigSubaddressTransferArg_ARG *subaddress_transfer;
-+
-+ subaddress_transfer = &args->qsig.SubaddressTransfer;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " SubaddressTransfer %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "redirectionSubaddress", tag, pos,
-+ seq_end, &subaddress_transfer->redirection_subaddress));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG DummyArg invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ *
-+ * \details
-+ * DummyArg ::= CHOICE {
-+ * none NULL,
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * }
-+ */
-+const unsigned char *rose_dec_qsig_DummyArg_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ const char *name;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ switch (tag) {
-+ case ASN1_TYPE_NULL:
-+ return asn1_dec_null(ctrl, "none", tag, pos, end);
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ name = "extension Extension";
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ name = "multipleExtension SEQUENCE OF Extension";
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ /* Fixup will skip over the manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG DummyRes result argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ *
-+ * \details
-+ * DummyRes ::= CHOICE {
-+ * none NULL,
-+ * extension [1] IMPLICIT Extension,
-+ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
-+ * }
-+ */
-+const unsigned char *rose_dec_qsig_DummyRes_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
-+{
-+ const char *name;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ switch (tag) {
-+ case ASN1_TYPE_NULL:
-+ return asn1_dec_null(ctrl, "none", tag, pos, end);
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
-+ name = "extension Extension";
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
-+ name = "multipleExtension SEQUENCE OF Extension";
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ /* Fixup will skip over the manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_qsig_ct.c */
-
-Property changes on: rose_qsig_ct.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_q931.c
-===================================================================
---- a/rose_q931.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_q931.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,100 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief ROSE Q.931 ie encode/decode functions
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \brief Encode the Q.931 ie value.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_CLASS_APPLICATION | 0 unless the caller
-+ * implicitly tags it otherwise.
-+ * \param q931ie Q931 ie information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_Q931ie(struct pri *ctrl, unsigned char *pos, unsigned char *end,
-+ unsigned tag, const struct roseQ931ie *q931ie)
-+{
-+ return asn1_enc_string_bin(pos, end, tag, q931ie->contents, q931ie->length);
-+}
-+
-+/*!
-+ * \brief Decode the Q.931 ie value.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param q931ie Parameter storage to fill.
-+ * \param contents_size Amount of space "allocated" for the q931ie->contents
-+ * element. Must have enough room for a null terminator.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_Q931ie(struct pri *ctrl, const char *name, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, struct roseQ931ie *q931ie,
-+ size_t contents_size)
-+{
-+ size_t str_len;
-+
-+ /* NOTE: The q931ie->contents memory is "allocated" after the struct. */
-+ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end, contents_size,
-+ q931ie->contents, &str_len));
-+ q931ie->length = str_len;
-+
-+ /*
-+ * NOTE: We may want to do some basic decoding of the Q.931 ie list
-+ * for debug purposes.
-+ */
-+
-+ return pos;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_q931.c */
-
-Property changes on: rose_q931.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: rose_etsi_ect.c
-===================================================================
---- a/rose_etsi_ect.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_etsi_ect.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,332 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief ROSE Explicit Call Transfer operations.
-+ *
-+ * Explicit Call Transfer (ECT) Supplementary Services ETS 300 369-1
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \brief Encode the ExplicitEctExecute invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ args->etsi.ExplicitEctExecute.link_id);
-+}
-+
-+/*!
-+ * \brief Encode the SubaddressTransfer invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return rose_enc_PartySubaddress(ctrl, pos, end,
-+ &args->etsi.SubaddressTransfer.subaddress);
-+}
-+
-+/*!
-+ * \brief Encode the EctLinkIdRequest result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ args->etsi.EctLinkIdRequest.link_id);
-+}
-+
-+/*!
-+ * \brief Encode the EctInform invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_EctInform_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ const struct roseEtsiEctInform_ARG *ect_inform;
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
-+
-+ ect_inform = &args->etsi.EctInform;
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, ect_inform->status));
-+ if (ect_inform->redirection_present) {
-+ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
-+ &ect_inform->redirection));
-+ }
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the EctLoopTest invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
-+ args->etsi.EctLoopTest.call_transfer_id);
-+}
-+
-+/*!
-+ * \brief Encode the EctLoopTest result facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_result_args *args)
-+{
-+ return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
-+ args->etsi.EctLoopTest.loop_result);
-+}
-+
-+/*!
-+ * \brief Decode the ExplicitEctExecute invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "linkId", tag, pos, end, &value));
-+ args->etsi.ExplicitEctExecute.link_id = value;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the SubaddressTransfer invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ return rose_dec_PartySubaddress(ctrl, "transferredToSubaddress", tag, pos, end,
-+ &args->etsi.SubaddressTransfer.subaddress);
-+}
-+
-+/*!
-+ * \brief Decode the EctLinkIdRequest result argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
-+{
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "linkId", tag, pos, end, &value));
-+ args->etsi.EctLinkIdRequest.link_id = value;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the EctInform invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_EctInform_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ struct roseEtsiEctInform_ARG *ect_inform;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+ int32_t value;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " EctInform %s\n", asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ect_inform = &args->etsi.EctInform;
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "callStatus", tag, pos, seq_end, &value));
-+ ect_inform->status = value;
-+
-+ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "redirectionNumber", tag,
-+ pos, seq_end, &ect_inform->redirection));
-+ ect_inform->redirection_present = 1;
-+ } else {
-+ ect_inform->redirection_present = 0;
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the EctLoopTest invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "callTransferId", tag, pos, end, &value));
-+ args->etsi.EctLoopTest.call_transfer_id = value;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the EctLoopTest result argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
-+{
-+ int32_t value;
-+
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "loopResult", tag, pos, end, &value));
-+ args->etsi.EctLoopTest.loop_result = value;
-+
-+ return pos;
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_etsi_ect.c */
-
-Property changes on: rose_etsi_ect.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: pri_internal.h
-===================================================================
---- a/pri_internal.h (.../tags/1.4.10.2) (revision 1357)
-+++ b/pri_internal.h (.../branches/1.4) (revision 1357)
-@@ -32,30 +32,45 @@
-
- #include <stddef.h>
- #include <sys/time.h>
-+#include "pri_q921.h"
-+#include "pri_q931.h"
-
-+#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))
-+
- #define DBGHEAD __FILE__ ":%d %s: "
- #define DBGINFO __LINE__,__PRETTY_FUNCTION__
-
-+/* Forward declare some structs */
-+struct apdu_event;
-+
- struct pri_sched {
- struct timeval when;
- void (*callback)(void *data);
- void *data;
- };
-
--struct q921_frame;
--enum q931_state;
--enum q931_mode;
--
--/* No more than 128 scheduled events */
-+/*! Maximum number of scheduled events active at the same time. */
- #define MAX_SCHED 128
-
--#define MAX_TIMERS 32
-+/*! Maximum number of facility ie's to handle per incoming message. */
-+#define MAX_FACILITY_IES 8
-
-+/*! Accumulated pri_message() line until a '\n' is seen on the end. */
-+struct pri_msg_line {
-+ /*! Accumulated buffer used. */
-+ unsigned length;
-+ /*! Accumulated pri_message() contents. */
-+ char str[2048];
-+};
-+
-+/*! \brief D channel controller structure */
- struct pri {
- int fd; /* File descriptor for D-Channel */
- pri_io_cb read_func; /* Read data callback */
- pri_io_cb write_func; /* Write data callback */
- void *userdata;
-+ /*! Accumulated pri_message() line. (Valid in master record only) */
-+ struct pri_msg_line *msg_line;
- struct pri *subchannel; /* Sub-channel if appropriate */
- struct pri *master; /* Master channel if appropriate */
- struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */
-@@ -71,7 +86,9 @@
- int protodisc;
- unsigned int bri:1;
- unsigned int acceptinbanddisconnect:1; /* Should we allow inband progress after DISCONNECT? */
--
-+ unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */
-+ unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */
-+
- /* Q.921 State */
- int q921_state;
- int window; /* Max window size */
-@@ -97,12 +114,14 @@
- int ri;
- int t200_timer; /* T-200 retransmission timer */
- /* All ISDN Timer values */
-- int timers[MAX_TIMERS];
-+ int timers[PRI_MAX_TIMERS];
-
- /* Used by scheduler */
- struct timeval tv;
- int schedev;
- pri_event ev; /* Static event thingy */
-+ /*! Subcommands for static event thingy. */
-+ struct pri_subcommands subcmds;
-
- /* Q.921 Re-transmission queue */
- struct q921_frame *txqueue;
-@@ -111,9 +130,19 @@
- q931_call **callpool;
- q931_call *localpool;
-
-+ /*!
-+ * \brief Q.931 Dummy call reference call associated with this TEI.
-+ * \note If present then this call is allocated as part of the
-+ * D channel control structure.
-+ */
-+ q931_call *dummy_call;
-+
- /* do we do overlap dialing */
- int overlapdial;
-
-+ /* do we support SERVICE messages */
-+ int service_message_support;
-+
- /* do not skip channel 16 */
- int chan_mapping_logical;
-
-@@ -125,52 +154,227 @@
- unsigned int q931_rxcount;
- #endif
-
-- unsigned char last_invoke; /* Last ROSE invoke ID */
-+ short last_invoke; /* Last ROSE invoke ID (Valid in master record only) */
- unsigned char sendfacility;
-+
-+ /*! For delayed processing of facility ie's. */
-+ struct {
-+ /*! Array of facility ie locations in the current received message. */
-+ q931_ie *ie[MAX_FACILITY_IES];
-+ /*! Codeset facility ie found within. */
-+ unsigned char codeset[MAX_FACILITY_IES];
-+ /*! Number of facility ie's in the array from the current received message. */
-+ unsigned char count;
-+ } facility;
- };
-
-+/*! \brief Maximum name length plus null terminator (From ECMA-164) */
-+#define PRI_MAX_NAME_LEN (50 + 1)
-+
-+/*! \brief Q.SIG name information. */
-+struct q931_party_name {
-+ /*! \brief TRUE if name data is valid */
-+ unsigned char valid;
-+ /*!
-+ * \brief Q.931 presentation-indicator encoded field
-+ * \note Must tollerate the Q.931 screening-indicator field values being present.
-+ */
-+ unsigned char presentation;
-+ /*!
-+ * \brief Character set the name is using.
-+ * \details
-+ * unknown(0),
-+ * iso8859-1(1),
-+ * enum-value-withdrawn-by-ITU-T(2)
-+ * iso8859-2(3),
-+ * iso8859-3(4),
-+ * iso8859-4(5),
-+ * iso8859-5(6),
-+ * iso8859-7(7),
-+ * iso10646-BmpString(8),
-+ * iso10646-utf-8String(9)
-+ */
-+ unsigned char char_set;
-+ /*! \brief Name data with null terminator. */
-+ char str[PRI_MAX_NAME_LEN];
-+};
-+
-+/*! \brief Maximum phone number (address) length plus null terminator */
-+#define PRI_MAX_NUMBER_LEN (31 + 1)
-+
-+struct q931_party_number {
-+ /*! \brief TRUE if number data is valid */
-+ unsigned char valid;
-+ /*! \brief Q.931 presentation-indicator and screening-indicator encoded fields */
-+ unsigned char presentation;
-+ /*! \brief Q.931 Type-Of-Number and numbering-plan encoded fields */
-+ unsigned char plan;
-+ /*! \brief Number data with terminator. */
-+ char str[PRI_MAX_NUMBER_LEN];
-+};
-+
-+/*! \brief Maximum subaddress length plus null terminator */
-+#define PRI_MAX_SUBADDRESS_LEN (20 + 1)
-+
-+struct q931_party_subaddress {
-+ /*! \brief TRUE if the subaddress information is valid/present */
-+ unsigned char valid;
-+ /*!
-+ * \brief Subaddress type.
-+ * \details
-+ * nsap(0),
-+ * user_specified(2)
-+ */
-+ unsigned char type;
-+ /*!
-+ * \brief TRUE if odd number of address signals
-+ * \note The odd/even indicator is used when the type of subaddress is
-+ * user_specified and the coding is BCD.
-+ */
-+ unsigned char odd_even_indicator;
-+ /*! \brief Length of the subaddress data */
-+ unsigned char length;
-+ /*!
-+ * \brief Subaddress data with null terminator.
-+ * \note The null terminator is a convenience only since the data could be
-+ * BCD/binary and thus have a null byte as part of the contents.
-+ */
-+ unsigned char data[PRI_MAX_SUBADDRESS_LEN];
-+};
-+
-+struct q931_party_address {
-+ /*! \brief Subscriber phone number */
-+ struct q931_party_number number;
-+ /*! \brief Subscriber subaddress */
-+ struct q931_party_subaddress subaddress;
-+};
-+
-+/*! \brief Information needed to identify an endpoint in a call. */
-+struct q931_party_id {
-+ /*! \brief Subscriber name */
-+ struct q931_party_name name;
-+ /*! \brief Subscriber phone number */
-+ struct q931_party_number number;
-+ /*! \brief Subscriber subaddress */
-+ struct q931_party_subaddress subaddress;
-+};
-+
-+enum Q931_REDIRECTING_STATE {
-+ /*!
-+ * \details
-+ * CDO-Idle/CDF-Inv-Idle
-+ */
-+ Q931_REDIRECTING_STATE_IDLE,
-+ /*!
-+ * \details
-+ * CDF-Inv-Wait - A DivLeg2 has been received and
-+ * we are waiting for valid presentation restriction information to send.
-+ */
-+ Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3,
-+ /*!
-+ * \details
-+ * CDO-Divert - A DivLeg1 has been received and
-+ * we are waiting for the presentation restriction information to come in.
-+ */
-+ Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3,
-+};
-+
-+/*!
-+ * \brief Do not increment above this count.
-+ * \details
-+ * It is not our responsibility to enforce the maximum number of redirects.
-+ * However, we cannot allow an increment past this number without breaking things.
-+ * Besides, more than 255 redirects is probably not a good thing.
-+ */
-+#define PRI_MAX_REDIRECTS 0xFF
-+
-+/*! \brief Redirecting information struct */
-+struct q931_party_redirecting {
-+ enum Q931_REDIRECTING_STATE state;
-+ /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */
-+ struct q931_party_id from;
-+ /*! \brief Call is redirecting to a new party (Sent to the caller) */
-+ struct q931_party_id to;
-+ /*! Originally called party (in cases of multiple redirects) */
-+ struct q931_party_id orig_called;
-+ /*!
-+ * \brief Number of times the call was redirected
-+ * \note The call is being redirected if the count is non-zero.
-+ */
-+ unsigned char count;
-+ /*! Original reason for redirect (in cases of multiple redirects) */
-+ unsigned char orig_reason;
-+ /*! \brief Redirection reasons */
-+ unsigned char reason;
-+};
-+
-+/*! \brief New call setup parameter structure */
- struct pri_sr {
- int transmode;
- int channel;
- int exclusive;
- int nonisdn;
-- char *caller;
-- int callerplan;
-- char *callername;
-- int callerpres;
-- char *called;
-- int calledplan;
-+ struct q931_party_redirecting redirecting;
-+ struct q931_party_id caller;
-+ struct q931_party_address called;
- int userl1;
- int numcomplete;
-- char *redirectingnum;
-- int redirectingplan;
-- int redirectingpres;
-- int redirectingreason;
-- int justsignalling;
-+ int cis_call;
-+ int cis_auto_disconnect;
- const char *useruserinfo;
-+ const char *keypad_digits;
- int transferable;
-+ int reversecharge;
- };
-
- /* Internal switch types */
- #define PRI_SWITCH_GR303_EOC_PATH 19
- #define PRI_SWITCH_GR303_TMC_SWITCHING 20
-
--struct apdu_event {
-- int message; /* What message to send the ADPU in */
-- void (*callback)(void *data); /* Callback function for when response is received */
-- void *data; /* Data to callback */
-- unsigned char apdu[255]; /* ADPU to send */
-- int apdu_len; /* Length of ADPU */
-- int sent; /* Have we been sent already? */
-- struct apdu_event *next; /* Linked list pointer */
-+#define Q931_MAX_TEI 8
-+
-+/*! \brief Incoming call transfer states. */
-+enum INCOMING_CT_STATE {
-+ /*!
-+ * \details
-+ * Incoming call transfer is not active.
-+ */
-+ INCOMING_CT_STATE_IDLE,
-+ /*!
-+ * \details
-+ * We have seen an incoming CallTransferComplete(alerting)
-+ * so we are waiting for the expected CallTransferActive
-+ * before updating the connected line about the remote party id.
-+ */
-+ INCOMING_CT_STATE_EXPECT_CT_ACTIVE,
-+ /*!
-+ * \details
-+ * A call transfer message came in that updated the remote party id
-+ * that we need to post a connected line update.
-+ */
-+ INCOMING_CT_STATE_POST_CONNECTED_LINE
- };
-
-+/*! Call hold supplementary states. */
-+enum Q931_HOLD_STATE {
-+ /*! \brief No call hold activity. */
-+ Q931_HOLD_STATE_IDLE,
-+ /*! \brief Request made to hold call. */
-+ Q931_HOLD_STATE_HOLD_REQ,
-+ /*! \brief Request received to hold call. */
-+ Q931_HOLD_STATE_HOLD_IND,
-+ /*! \brief Call is held. */
-+ Q931_HOLD_STATE_CALL_HELD,
-+ /*! \brief Request made to retrieve call. */
-+ Q931_HOLD_STATE_RETRIEVE_REQ,
-+ /*! \brief Request received to retrieve call. */
-+ Q931_HOLD_STATE_RETRIEVE_IND,
-+};
-+
- /* q931_call datastructure */
--
- struct q931_call {
- struct pri *pri; /* PRI */
- int cr; /* Call Reference */
-- int forceinvert; /* Force inversion of call number even if 0 */
- q931_call *next;
- /* Slotmap specified (bitmap of channels 31/24-1) (Channel Identifier IE) (-1 means not specified) */
- int slotmap;
-@@ -199,73 +403,144 @@
- int userl2;
- int userl3;
- int rateadaption;
--
-- int sentchannel;
-- int justsignalling; /* for a signalling-only connection */
-
-+ /*!
-+ * \brief TRUE if the call is a Call Independent Signalling connection.
-+ * \note The call has no B channel associated with it. (Just signalling)
-+ */
-+ int cis_call;
-+ /*! \brief TRUE if we will auto disconnect the cis_call we originated. */
-+ int cis_auto_disconnect;
-+
- int progcode; /* Progress coding */
- int progloc; /* Progress Location */
- int progress; /* Progress indicator */
- int progressmask; /* Progress Indicator bitmask */
-
-- int notify; /* Notification */
-+ int notify; /* Notification indicator. */
-
- int causecode; /* Cause Coding */
- int causeloc; /* Cause Location */
- int cause; /* Cause of clearing */
-
-- int peercallstate; /* Call state of peer as reported */
-- int ourcallstate; /* Our call state */
-- int sugcallstate; /* Status call state */
--
-- int callerplan;
-- int callerplanani;
-- int callerpres; /* Caller presentation */
-- char callerani[256]; /* Caller */
-- char callernum[256];
-- char callername[256];
-+ enum Q931_CALL_STATE peercallstate; /* Call state of peer as reported */
-+ enum Q931_CALL_STATE ourcallstate; /* Our call state */
-+ enum Q931_CALL_STATE sugcallstate; /* Status call state */
-
-- char keypad_digits[64]; /* Buffer for digits that come in KEYPAD_FACILITY */
-+ int ani2; /* ANI II */
-
-- int ani2; /* ANI II */
--
-- int calledplan;
-+ /*! Buffer for digits that come in KEYPAD_FACILITY */
-+ char keypad_digits[32 + 1];
-+
-+ /*! Current dialed digits to be sent or just received. */
-+ char overlap_digits[PRI_MAX_NUMBER_LEN];
-+
-+ /*!
-+ * \brief Local party ID
-+ * \details
-+ * The Caller-ID and connected-line ID are just roles the local and remote party
-+ * play while a call is being established. Which roll depends upon the direction
-+ * of the call.
-+ * Outgoing party info is to identify the local party to the other end.
-+ * (Caller-ID for originated or connected-line for answered calls.)
-+ * Incoming party info is to identify the remote party to us.
-+ * (Caller-ID for answered or connected-line for originated calls.)
-+ */
-+ struct q931_party_id local_id;
-+ /*!
-+ * \brief Remote party ID
-+ * \details
-+ * The Caller-ID and connected-line ID are just roles the local and remote party
-+ * play while a call is being established. Which roll depends upon the direction
-+ * of the call.
-+ * Outgoing party info is to identify the local party to the other end.
-+ * (Caller-ID for originated or connected-line for answered calls.)
-+ * Incoming party info is to identify the remote party to us.
-+ * (Caller-ID for answered or connected-line for originated calls.)
-+ */
-+ struct q931_party_id remote_id;
-+
-+ /*!
-+ * \brief Staging place for the Q.931 redirection number ie.
-+ * \note
-+ * The number could be the remote_id.number or redirecting.to.number
-+ * depending upon the notification indicator.
-+ */
-+ struct q931_party_number redirection_number;
-+
-+ /*!
-+ * \brief Called party address.
-+ * \note The called.number.str is the accumulated overlap dial digits
-+ * and enbloc digits.
-+ * \note The called.number.presentation value is not used.
-+ */
-+ struct q931_party_address called;
- int nonisdn;
-- char callednum[256]; /* Called Number */
- int complete; /* no more digits coming */
- int newcall; /* if the received message has a new call reference value */
-
- int retranstimer; /* Timer for retransmitting DISC */
- int t308_timedout; /* Whether t308 timed out once */
-
-- int redirectingplan;
-- int redirectingpres;
-- int redirectingreason;
-- char redirectingnum[256]; /* Number of redirecting party */
-- char redirectingname[256]; /* Name of redirecting party */
-+ struct q931_party_redirecting redirecting;
-
-- /* Filled in cases of multiple diversions */
-- int origcalledplan;
-- int origcalledpres;
-- int origredirectingreason; /* Original reason for redirect (in cases of multiple redirects) */
-- char origcalledname[256]; /* Original name of person being called */
-- char origcallednum[256]; /* Orignal number of person being called */
-+ /*! \brief Incoming call transfer state. */
-+ enum INCOMING_CT_STATE incoming_ct_state;
-+ /*! Call hold supplementary state. */
-+ enum Q931_HOLD_STATE hold_state;
-+ /*! Call hold event timer */
-+ int hold_timer;
-
-+ int deflection_in_progress; /*!< CallDeflection for NT PTMP in progress. */
-+ /*! TRUE if the connected number ie was in the current received message. */
-+ int connected_number_in_message;
-+ /*! TRUE if the redirecting number ie was in the current received message. */
-+ int redirecting_number_in_message;
-+
- int useruserprotocoldisc;
- char useruserinfo[256];
-- char callingsubaddr[256]; /* Calling parties sub address */
-
- long aoc_units; /* Advice of Charge Units */
-
- struct apdu_event *apdus; /* APDU queue for call */
-
-- int transferable;
-+ int transferable; /* RLT call is transferable */
- unsigned int rlt_call_id; /* RLT call id */
-
- /* Bridged call info */
-- q931_call *bridged_call; /* Pointer to other leg of bridged call */
-+ q931_call *bridged_call; /* Pointer to other leg of bridged call (Used by Q.SIG when eliminating tromboned calls) */
-+
-+ int changestatus; /* SERVICE message changestatus */
-+ int reversecharge; /* Reverse charging indication:
-+ -1 - No reverse charging
-+ 1 - Reverse charging
-+ 0,2-7 - Reserved for future use */
-+ int t303_timer;
-+ int t303_expirycnt;
-+
-+ int hangupinitiated;
-+ /*! \brief TRUE if we broadcast this call's SETUP message. */
-+ int outboundbroadcast;
-+ int performing_fake_clearing;
-+ /*!
-+ * \brief Master call controlling this call.
-+ * \note Always valid. Master and normal calls point to self.
-+ */
-+ struct q931_call *master_call;
-+
-+ /* These valid in master call only */
-+ struct q931_call *subcalls[Q931_MAX_TEI];
-+ int pri_winner;
- };
-
-+/*! D channel control structure with associated dummy call reference record. */
-+struct d_ctrl_dummy {
-+ /*! D channel control structure. Must be first in the structure. */
-+ struct pri ctrl;
-+ /*! Dummy call reference call record. */
-+ struct q931_call dummy_call;
-+};
-+
- extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
-
- extern pri_event *pri_schedule_run(struct pri *pri);
-@@ -274,14 +549,104 @@
-
- extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
-
--extern void pri_message(struct pri *pri, char *fmt, ...);
-+void pri_message(struct pri *ctrl, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
-+void pri_error(struct pri *ctrl, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
-
--extern void pri_error(struct pri *pri, char *fmt, ...);
--
- void libpri_copy_string(char *dst, const char *src, size_t size);
-
- struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri);
-
- void __pri_free_tei(struct pri *p);
-
-+void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr);
-+
-+void q931_party_name_init(struct q931_party_name *name);
-+void q931_party_number_init(struct q931_party_number *number);
-+void q931_party_subaddress_init(struct q931_party_subaddress *subaddr);
-+void q931_party_address_init(struct q931_party_address *address);
-+void q931_party_id_init(struct q931_party_id *id);
-+void q931_party_redirecting_init(struct q931_party_redirecting *redirecting);
-+
-+static inline void q931_party_address_to_id(struct q931_party_id *id, struct q931_party_address *address)
-+{
-+ id->number = address->number;
-+ id->subaddress = address->subaddress;
-+}
-+
-+int q931_party_name_cmp(const struct q931_party_name *left, const struct q931_party_name *right);
-+int q931_party_number_cmp(const struct q931_party_number *left, const struct q931_party_number *right);
-+int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right);
-+int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_id *right);
-+
-+void q931_party_name_copy_to_pri(struct pri_party_name *pri_name, const struct q931_party_name *q931_name);
-+void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const struct q931_party_number *q931_number);
-+void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress);
-+void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_party_id *q931_id);
-+void q931_party_redirecting_copy_to_pri(struct pri_party_redirecting *pri_redirecting, const struct q931_party_redirecting *q931_redirecting);
-+
-+void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id);
-+int q931_party_id_presentation(const struct q931_party_id *id);
-+
-+const char *q931_call_state_str(enum Q931_CALL_STATE callstate);
-+const char *msg2str(int msg);
-+
-+int q931_is_ptmp(const struct pri *ctrl);
-+int q931_master_pass_event(struct pri *ctrl, struct q931_call *subcall, int msg_type);
-+struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl);
-+
-+int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number);
-+
-+static inline struct pri * PRI_MASTER(struct pri *mypri)
-+{
-+ struct pri *pri = mypri;
-+
-+ if (!pri)
-+ return NULL;
-+
-+ while (pri->master)
-+ pri = pri->master;
-+
-+ return pri;
-+}
-+
-+static inline int BRI_NT_PTMP(struct pri *mypri)
-+{
-+ struct pri *pri;
-+
-+ pri = PRI_MASTER(mypri);
-+
-+ return pri->bri && (((pri)->localtype == PRI_NETWORK) && ((pri)->tei == Q921_TEI_GROUP));
-+}
-+
-+static inline int BRI_TE_PTMP(struct pri *mypri)
-+{
-+ struct pri *pri;
-+
-+ pri = PRI_MASTER(mypri);
-+
-+ return pri->bri && (((pri)->localtype == PRI_CPE) && ((pri)->tei == Q921_TEI_GROUP));
-+}
-+
-+static inline int PRI_PTP(struct pri *mypri)
-+{
-+ struct pri *pri;
-+
-+ pri = PRI_MASTER(mypri);
-+
-+ return !pri->bri;
-+}
-+
-+#define Q931_DUMMY_CALL_REFERENCE -1
-+
-+/*!
-+ * \brief Deterimine if the given call control pointer is a dummy call.
-+ *
-+ * \retval TRUE if given call is a dummy call.
-+ * \retval FALSE otherwise.
-+ */
-+static inline int q931_is_dummy_call(const q931_call *call)
-+{
-+ return (call->cr == Q931_DUMMY_CALL_REFERENCE) ? 1 : 0;
-+}
-+
- #endif
-Index: rose_qsig_name.c
-===================================================================
---- a/rose_qsig_name.c (.../tags/1.4.10.2) (revision 0)
-+++ b/rose_qsig_name.c (.../branches/1.4) (revision 1357)
-@@ -0,0 +1,474 @@
-+/*
-+ * libpri: An implementation of Primary Rate ISDN
-+ *
-+ * Copyright (C) 2009 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ *
-+ * In addition, when this program is distributed with Asterisk in
-+ * any form that would qualify as a 'combined work' or as a
-+ * 'derivative work' (but not mere aggregation), you can redistribute
-+ * and/or modify the combination under the terms of the license
-+ * provided with that copy of Asterisk, instead of the license
-+ * terms granted here.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Q.SIG ROSE Name operations and elements
-+ *
-+ * Name-Operations ECMA-164 Annex C
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ */
-+
-+
-+#include "compat.h"
-+#include "libpri.h"
-+#include "pri_internal.h"
-+#include "rose.h"
-+#include "rose_internal.h"
-+#include "asn1.h"
-+
-+
-+/* ------------------------------------------------------------------- */
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG NameSet type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param tag Component tag to identify the encoded component.
-+ * The tag should be ASN1_TAG_SEQUENCE unless the caller
-+ * implicitly tags it otherwise.
-+ * \param name
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_NameSet(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, unsigned tag, const struct roseQsigName *name)
-+{
-+ unsigned char *seq_len;
-+
-+ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
-+
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_OCTET_STRING, name->data,
-+ name->length));
-+ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, name->char_set));
-+
-+ ASN1_CONSTRUCTED_END(seq_len, pos, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG Name type.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param name
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const struct roseQsigName *name)
-+{
-+ switch (name->presentation) {
-+ case 0: /* optional_name_not_present */
-+ /* Do not encode anything */
-+ break;
-+ case 1: /* presentation_allowed */
-+ if (name->char_set == 1) {
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
-+ name->data, name->length));
-+ } else {
-+ ASN1_CALL(pos, rose_enc_qsig_NameSet(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 1, name));
-+ }
-+ break;
-+ case 2: /* presentation_restricted */
-+ if (name->char_set == 1) {
-+ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
-+ name->data, name->length));
-+ } else {
-+ ASN1_CALL(pos, rose_enc_qsig_NameSet(ctrl, pos, end,
-+ ASN1_CLASS_CONTEXT_SPECIFIC | 3, name));
-+ }
-+ break;
-+ case 3: /* presentation_restricted_null */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 7));
-+ break;
-+ case 4: /* name_not_available */
-+ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4));
-+ break;
-+ default:
-+ ASN1_ENC_ERROR(ctrl, "Unknown name presentation");
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Encode the Q.SIG party-Name invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param party Information to encode.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+static unsigned char *rose_enc_qsig_PartyName_ARG_Backend(struct pri *ctrl,
-+ unsigned char *pos, unsigned char *end, const struct roseQsigPartyName_ARG *party)
-+{
-+ return rose_enc_qsig_Name(ctrl, pos, end, &party->name);
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG CallingName invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CallingName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end, &args->qsig.CallingName);
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG CalledName invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_CalledName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end, &args->qsig.CalledName);
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG ConnectedName invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end,
-+ &args->qsig.ConnectedName);
-+}
-+
-+/*!
-+ * \brief Encode the Q.SIG BusyName invoke facility ie arguments.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param pos Starting position to encode ASN.1 component.
-+ * \param end End of ASN.1 encoding data buffer.
-+ * \param args Arguments to encode in the buffer.
-+ *
-+ * \retval Start of the next ASN.1 component to encode on success.
-+ * \retval NULL on error.
-+ */
-+unsigned char *rose_enc_qsig_BusyName_ARG(struct pri *ctrl, unsigned char *pos,
-+ unsigned char *end, const union rose_msg_invoke_args *args)
-+{
-+ return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end, &args->qsig.BusyName);
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the Q.SIG NameData Name argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param fname Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param name Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_NameData(struct pri *ctrl, const char *fname,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigName *name)
-+{
-+ size_t str_len;
-+
-+ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, fname, tag, pos, end, sizeof(name->data),
-+ name->data, &str_len));
-+ name->length = str_len;
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the Q.SIG NameSet Name argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param fname Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param name Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_NameSet(struct pri *ctrl, const char *fname,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigName *name)
-+{
-+ int32_t value;
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s NameSet %s\n", fname, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_OCTET_STRING);
-+ ASN1_CALL(pos, rose_dec_qsig_NameData(ctrl, "nameData", tag, pos, seq_end, name));
-+
-+ if (pos < end && *pos != ASN1_INDEF_TERM) {
-+ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
-+ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
-+ ASN1_CALL(pos, asn1_dec_int(ctrl, "characterSet", tag, pos, seq_end, &value));
-+ name->char_set = value;
-+ } else {
-+ name->char_set = 1; /* default to iso8859-1 */
-+ }
-+
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG Name argument parameters.
-+ *
-+ * \param ctrl D channel controller for any diagnostic messages.
-+ * \param fname Field name
-+ * \param tag Component tag that identified this production.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param name Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_Name(struct pri *ctrl, const char *fname,
-+ unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigName *name)
-+{
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s Name\n", fname);
-+ }
-+ name->char_set = 1; /* default to iso8859-1 */
-+ switch (tag & ~ASN1_PC_MASK) {
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
-+ name->presentation = 1; /* presentation_allowed */
-+ ASN1_CALL(pos, rose_dec_qsig_NameData(ctrl, "namePresentationAllowedSimple", tag,
-+ pos, end, name));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
-+ /* Must be constructed but we will not check for it for simplicity. */
-+ name->presentation = 1; /* presentation_allowed */
-+ ASN1_CALL(pos, rose_dec_qsig_NameSet(ctrl, "namePresentationAllowedExtended",
-+ tag, pos, end, name));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
-+ name->presentation = 2; /* presentation_restricted */
-+ ASN1_CALL(pos, rose_dec_qsig_NameData(ctrl, "namePresentationRestrictedSimple",
-+ tag, pos, end, name));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
-+ /* Must be constructed but we will not check for it for simplicity. */
-+ name->presentation = 2; /* presentation_restricted */
-+ ASN1_CALL(pos, rose_dec_qsig_NameSet(ctrl, "namePresentationRestrictedExtended",
-+ tag, pos, end, name));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
-+ /* Must not be constructed but we will not check for it for simplicity. */
-+ name->presentation = 4; /* name_not_available */
-+ name->length = 0;
-+ name->data[0] = 0;
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "nameNotAvailable", tag, pos, end));
-+ break;
-+ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
-+ /* Must not be constructed but we will not check for it for simplicity. */
-+ name->presentation = 3; /* presentation_restricted_null */
-+ name->length = 0;
-+ name->data[0] = 0;
-+ ASN1_CALL(pos, asn1_dec_null(ctrl, "namePresentationRestrictedNull", tag, pos,
-+ end));
-+ break;
-+ default:
-+ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
-+ return NULL;
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Decode the Q.SIG party-Name invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param name Field name
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param party Parameter storage to fill.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+static const unsigned char *rose_dec_qsig_PartyName_ARG_Backend(struct pri *ctrl,
-+ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
-+ struct roseQsigPartyName_ARG *party)
-+{
-+ int length;
-+ int seq_offset;
-+ const unsigned char *seq_end;
-+
-+ if (tag == ASN1_TAG_SEQUENCE) {
-+ if (ctrl->debug & PRI_DEBUG_APDU) {
-+ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
-+ }
-+ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
-+ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
-+
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "name", tag, pos, seq_end,
-+ &party->name));
-+
-+ /* Fixup will skip over any OPTIONAL manufacturer extension information */
-+ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
-+ } else {
-+ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, name, tag, pos, end, &party->name));
-+ }
-+
-+ return pos;
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CallingName invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CallingName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "callingName", tag, pos, end,
-+ &args->qsig.CallingName);
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG CalledName invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_CalledName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "calledName", tag, pos, end,
-+ &args->qsig.CalledName);
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG ConnectedName invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "connectedName", tag, pos, end,
-+ &args->qsig.ConnectedName);
-+}
-+
-+/*!
-+ * \brief Decode the Q.SIG BusyName invoke argument parameters.
-+ *
-+ * \param ctrl D channel controller for diagnostic messages or global options.
-+ * \param tag Component tag that identified this structure.
-+ * \param pos Starting position of the ASN.1 component length.
-+ * \param end End of ASN.1 decoding data buffer.
-+ * \param args Arguments to fill in from the decoded buffer.
-+ *
-+ * \retval Start of the next ASN.1 component on success.
-+ * \retval NULL on error.
-+ */
-+const unsigned char *rose_dec_qsig_BusyName_ARG(struct pri *ctrl, unsigned tag,
-+ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
-+{
-+ return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "busyName", tag, pos, end,
-+ &args->qsig.BusyName);
-+}
-+
-+/* ------------------------------------------------------------------- */
-+/* end rose_qsig_name.c */
-
-Property changes on: rose_qsig_name.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + 'Author Date Id Revision'
-
-Index: q921.c
-===================================================================
---- a/q921.c (.../tags/1.4.10.2) (revision 1357)
-+++ b/q921.c (.../branches/1.4) (revision 1357)
-@@ -27,6 +27,7 @@
- * terms granted here.
- */
-
-+#include <stdint.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
-@@ -139,8 +140,7 @@
- #endif
- pri->ri = random() % 65535;
- q921_send_tei(pri, Q921_TEI_IDENTITY_REQUEST, pri->ri, Q921_TEI_GROUP, 1);
-- if (pri->t202_timer)
-- pri_schedule_del(pri, pri->t202_timer);
-+ pri_schedule_del(pri, pri->t202_timer);
- pri->t202_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202], q921_tei_request, pri);
- }
-
-@@ -174,8 +174,8 @@
- {
- struct pri *pri = vpri;
- q921_h h;
-+
- pri_schedule_del(pri, pri->sabme_timer);
-- pri->sabme_timer = 0;
- pri->sabme_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], q921_send_sabme_now, pri);
- if (!now)
- return;
-@@ -248,14 +248,12 @@
-
- static void t203_expire(void *);
- static void t200_expire(void *);
--static pri_event *q921_dchannel_down(struct pri *pri);
-
- static void reschedule_t200(struct pri *pri)
- {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Restarting T200 timer\n");
-- if (pri->t200_timer)
-- pri_schedule_del(pri, pri->t200_timer);
-+ pri_schedule_del(pri, pri->t200_timer);
- pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
- }
-
-@@ -263,8 +261,7 @@
- {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Restarting T203 timer\n");
-- if (pri->t203_timer)
-- pri_schedule_del(pri, pri->t203_timer);
-+ pri_schedule_del(pri, pri->t203_timer);
- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
- }
-
-@@ -312,10 +309,8 @@
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Since there was nothing left, stopping T200 counter\n");
- /* Something was ACK'd. Stop T200 counter */
-- if (pri->t200_timer) {
-- pri_schedule_del(pri, pri->t200_timer);
-- pri->t200_timer = 0;
-- }
-+ pri_schedule_del(pri, pri->t200_timer);
-+ pri->t200_timer = 0;
- }
- if (pri->t203_timer) {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
-@@ -483,6 +478,45 @@
- }
- }
-
-+int q921_transmit_uiframe(struct pri *pri, void *buf, int len)
-+{
-+ uint8_t ubuf[512];
-+ q921_h *h = (void *)&ubuf[0];
-+
-+ if (len >= 512) {
-+ pri_error(pri, "Requested to send UI frame larger than 512 bytes!\n");
-+ return -1;
-+ }
-+
-+ memset(ubuf, 0, sizeof(ubuf));
-+ h->h.sapi = 0;
-+ h->h.ea1 = 0;
-+ h->h.ea2 = 1;
-+ h->h.tei = pri->tei;
-+ h->u.m3 = 0;
-+ h->u.m2 = 0;
-+ h->u.p_f = 0; /* Poll bit set */
-+ h->u.ft = Q921_FRAMETYPE_U;
-+
-+ switch(pri->localtype) {
-+ case PRI_NETWORK:
-+ h->h.c_r = 1;
-+ break;
-+ case PRI_CPE:
-+ h->h.c_r = 0;
-+ break;
-+ default:
-+ pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
-+ return -1;
-+ }
-+
-+ memcpy(h->u.data, buf, len);
-+
-+ q921_transmit(pri, h, len + 3);
-+
-+ return 0;
-+}
-+
- int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
- {
- q921_frame *f, *prev=NULL;
-@@ -521,6 +555,10 @@
- pri->txqueue = f;
- /* Immediately transmit unless we're in a recovery state, or the window
- size is too big */
-+ if (pri->debug & PRI_DEBUG_Q921_DUMP) {
-+ pri_message(pri, "TEI/SAPI: %d/%d state %d retran %d busy %d\n",
-+ pri->tei, pri->sapi, pri->q921_state, pri->retrans, pri->busy);
-+ }
- if ((pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) && (!pri->retrans && !pri->busy)) {
- if (pri->windowlen < pri->window) {
- q921_send_queued_iframes(pri);
-@@ -564,11 +602,15 @@
- /* Start timer T200 to resend our RR if we don't get it */
- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
- } else {
-- if (pri->debug & PRI_DEBUG_Q921_DUMP)
-- pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state);
-+ if (pri->debug & PRI_DEBUG_Q921_DUMP) {
-+ pri_message(pri,
-+ "T203 counter expired in weird state %d on pri with SAPI/TEI of %d/%d\n",
-+ pri->q921_state, pri->sapi, pri->tei);
-+ }
- pri->t203_timer = 0;
- }
- }
-+
- static pri_event *q921_handle_iframe(struct pri *pri, q921_i *i, int len)
- {
- int res;
-@@ -622,33 +664,34 @@
- char *buf = malloc(len * 3 + 1);
- int buflen = 0;
- if (buf) {
-+ pri_message(pri, "\n");
- for (x=0;x<len;x++)
- buflen += sprintf(buf + buflen, "%02x ", h->raw[x]);
-- pri_message(pri, "\n%c [ %s]\n", direction_tag, buf);
-+ pri_message(pri, "%c [ %s]\n", direction_tag, buf);
- free(buf);
- }
- }
-
-+ pri_message(pri, "\n");
- switch (h->h.data[0] & Q921_FRAMETYPE_MASK) {
- case 0:
- case 2:
-- pri_message(pri, "\n%c Informational frame:\n", direction_tag);
-+ pri_message(pri, "%c Informational frame:\n", direction_tag);
- break;
- case 1:
-- pri_message(pri, "\n%c Supervisory frame:\n", direction_tag);
-+ pri_message(pri, "%c Supervisory frame:\n", direction_tag);
- break;
- case 3:
-- pri_message(pri, "\n%c Unnumbered frame:\n", direction_tag);
-+ pri_message(pri, "%c Unnumbered frame:\n", direction_tag);
- break;
- }
-
-- pri_message(pri,
--"%c SAPI: %02d C/R: %d EA: %d\n"
--"%c TEI: %03d EA: %d\n",
-+ pri_message(pri, "%c SAPI: %02d C/R: %d EA: %d\n",
- direction_tag,
- h->h.sapi,
- h->h.c_r,
-- h->h.ea1,
-+ h->h.ea1);
-+ pri_message(pri, "%c TEI: %03d EA: %d\n",
- direction_tag,
- h->h.tei,
- h->h.ea2);
-@@ -658,15 +701,17 @@
- case 2:
- /* Informational frame */
- pri_message(pri,
--"%c N(S): %03d 0: %d\n"
--"%c N(R): %03d P: %d\n"
--"%c %d bytes of data\n",
-+"%c N(S): %03d 0: %d\n",
- direction_tag,
- h->i.n_s,
-- h->i.ft,
-+ h->i.ft);
-+ pri_message(pri,
-+"%c N(R): %03d P: %d\n",
- direction_tag,
- h->i.n_r,
-- h->i.p_f,
-+ h->i.p_f);
-+ pri_message(pri,
-+"%c %d bytes of data\n",
- direction_tag,
- len - 4);
- break;
-@@ -685,17 +730,19 @@
- break;
- }
- pri_message(pri,
--"%c Zero: %d S: %d 01: %d [ %s ]\n"
--"%c N(R): %03d P/F: %d\n"
--"%c %d bytes of data\n",
-+"%c Zero: %d S: %d 01: %d [ %s ]\n",
- direction_tag,
- h->s.x0,
- h->s.ss,
- h->s.ft,
-- type,
-+ type);
-+ pri_message(pri,
-+"%c N(R): %03d P/F: %d\n",
- direction_tag,
- h->s.n_r,
-- h->s.p_f,
-+ h->s.p_f);
-+ pri_message(pri,
-+"%c %d bytes of data\n",
- direction_tag,
- len - 4);
- break;
-@@ -731,14 +778,15 @@
- }
- }
- pri_message(pri,
--"%c M3: %d P/F: %d M2: %d 11: %d [ %s ]\n"
--"%c %d bytes of data\n",
-+"%c M3: %d P/F: %d M2: %d 11: %d [ %s ]\n",
- direction_tag,
- h->u.m3,
- h->u.p_f,
- h->u.m2,
- h->u.ft,
-- type,
-+ type);
-+ pri_message(pri,
-+"%c %d bytes of data\n",
- direction_tag,
- len - 3);
- break;
-@@ -783,7 +831,7 @@
- }
- }
-
--static pri_event *q921_dchannel_up(struct pri *pri)
-+pri_event *q921_dchannel_up(struct pri *pri)
- {
- if (pri->tei == Q921_TEI_PRI) {
- q921_reset(pri, 1);
-@@ -792,10 +840,8 @@
- }
-
- /* Stop any SABME retransmissions */
-- if (pri->sabme_timer) {
-- pri_schedule_del(pri, pri->sabme_timer);
-- pri->sabme_timer = 0;
-- }
-+ pri_schedule_del(pri, pri->sabme_timer);
-+ pri->sabme_timer = 0;
-
- /* Reset any rejects */
- pri->sentrej = 0;
-@@ -805,7 +851,12 @@
- pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_ESTABLISHED\n", DBGINFO);
- pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
-
-+ /* Ensure that we do not have T200 or T203 running when the link comes up */
-+ pri_schedule_del(pri, pri->t200_timer);
-+ pri->t200_timer = 0;
-+
- /* Start the T203 timer */
-+ pri_schedule_del(pri, pri->t203_timer);
- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
-
- /* Notify Layer 3 */
-@@ -818,7 +869,7 @@
- return &pri->ev;
- }
-
--static pri_event *q921_dchannel_down(struct pri *pri)
-+pri_event *q921_dchannel_down(struct pri *pri)
- {
- /* Reset counters, reset sabme timer etc */
- q921_reset(pri, 1);
-@@ -826,7 +877,7 @@
- /* Notify Layer 3 */
- q931_dl_indication(pri, PRI_EVENT_DCHAN_DOWN);
-
-- /* Report event that D-Channel is now up */
-+ /* Report event that D-Channel is now down */
- pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
- return &pri->ev;
- }
-@@ -842,12 +893,9 @@
- pri->v_na = 0;
- pri->window = pri->timers[PRI_TIMER_K];
- pri->windowlen = 0;
-- if (pri->sabme_timer)
-- pri_schedule_del(pri, pri->sabme_timer);
-- if (pri->t203_timer)
-- pri_schedule_del(pri, pri->t203_timer);
-- if (pri->t200_timer)
-- pri_schedule_del(pri, pri->t200_timer);
-+ pri_schedule_del(pri, pri->sabme_timer);
-+ pri_schedule_del(pri, pri->t203_timer);
-+ pri_schedule_del(pri, pri->t200_timer);
- pri->sabme_timer = 0;
- pri->sabme_count = 0;
- pri->t203_timer = 0;
-@@ -879,8 +927,14 @@
- static pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len)
- {
- int ri;
-- struct pri *sub;
-+ struct pri *sub = pri;
- int tei;
-+
-+ if (!BRI_NT_PTMP(pri) && !BRI_TE_PTMP(pri)) {
-+ pri_error(pri, "Received MDL/TEI managemement message, but configured for mode other than PTMP!\n");
-+ return NULL;
-+ }
-+
- if (pri->debug & PRI_DEBUG_Q921_STATE)
- pri_message(pri, "Received MDL message\n");
- if (h->data[0] != 0x0f) {
-@@ -895,16 +949,19 @@
- tei = (h->data[4] >> 1);
- switch(h->data[3]) {
- case Q921_TEI_IDENTITY_REQUEST:
-+ if (!BRI_NT_PTMP(pri)) {
-+ return NULL;
-+ }
-+
- if (tei != 127) {
- pri_error(pri, "Received TEI identity request with invalid TEI %d\n", tei);
- q921_send_tei(pri, Q921_TEI_IDENTITY_DENIED, ri, tei, 1);
- }
-- /* Go to master */
-- for (sub = pri; sub->master; sub = sub->master);
- tei = 64;
-- while(sub->subchannel) {
-- if(sub->subchannel->tei == tei)
-+ while (sub->subchannel) {
-+ if (sub->subchannel->tei == tei)
- ++tei;
-+ sub = sub->subchannel;
- }
- sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
- if (!sub->subchannel) {
-@@ -914,14 +971,15 @@
- q921_send_tei(pri, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 1);
- break;
- case Q921_TEI_IDENTITY_ASSIGNED:
-+ if (!BRI_TE_PTMP(pri))
-+ return NULL;
-+
- if (ri != pri->ri) {
- pri_message(pri, "TEI assignment received for invalid Ri %02x (our is %02x)\n", ri, pri->ri);
- return NULL;
- }
-- if (pri->t202_timer) {
-- pri_schedule_del(pri, pri->t202_timer);
-- pri->t202_timer = 0;
-- }
-+ pri_schedule_del(pri, pri->t202_timer);
-+ pri->t202_timer = 0;
- if (pri->subchannel && (pri->subchannel->tei == tei)) {
- pri_error(pri, "TEI already assigned (new is %d, current is %d)\n", tei, pri->subchannel->tei);
- q921_tei_release_and_reacquire(pri);
-@@ -937,6 +995,8 @@
- pri->q921_state = Q921_TEI_ASSIGNED;
- break;
- case Q921_TEI_IDENTITY_CHECK_REQUEST:
-+ if (!BRI_TE_PTMP(pri))
-+ return NULL;
- /* We're assuming one TEI per PRI in TE PTMP mode */
-
- /* If no subchannel (TEI) ignore */
-@@ -949,6 +1009,8 @@
-
- break;
- case Q921_TEI_IDENTITY_REMOVE:
-+ if (!BRI_TE_PTMP(pri))
-+ return NULL;
- /* XXX: Assuming multiframe mode has been disconnected already */
- if (!pri->subchannel)
- return NULL;
-@@ -990,6 +1052,10 @@
- pri_error(pri, "!! Received short I-frame (expected 4, got %d)\n", len);
- break;
- }
-+
-+ /* T203 is rescheduled only on reception of I frames or S frames */
-+ reschedule_t203(pri);
-+
- return q921_handle_iframe(pri, &h->i, len);
- break;
- case 1:
-@@ -1001,6 +1067,10 @@
- pri_error(pri, "!! Received short S-frame (expected 4, got %d)\n", len);
- break;
- }
-+
-+ /* T203 is rescheduled only on reception of I frames or S frames */
-+ reschedule_t203(pri);
-+
- switch(h->s.ss) {
- case 0:
- /* Receiver Ready */
-@@ -1091,10 +1161,8 @@
- }
- }
- /* Reset t200 timer if it was somehow going */
-- if (pri->t200_timer) {
-- pri_schedule_del(pri, pri->t200_timer);
-- pri->t200_timer = 0;
-- }
-+ pri_schedule_del(pri, pri->t200_timer);
-+ pri->t200_timer = 0;
- /* Reset and restart t203 timer */
- reschedule_t203(pri);
- }
-@@ -1152,7 +1220,9 @@
- /* Acknowledge */
- q921_send_ua(pri, h->u.p_f);
- ev = q921_dchannel_down(pri);
-- q921_restart(pri, 0);
-+ if (BRI_TE_PTMP(pri) || PRI_PTP(pri)) {
-+ q921_restart(pri, PRI_PTP(pri) ? 1 : 0);
-+ }
- return ev;
- case 3:
- if (h->u.m2 == 3) {
-@@ -1212,6 +1282,34 @@
- return NULL;
- }
-
-+static pri_event *q921_handle_unmatched_frame(struct pri *pri, q921_h *h, int len)
-+{
-+ pri = PRI_MASTER(pri);
-+
-+ if (h->h.tei < 64) {
-+ pri_error(pri, "Do not support manual TEI range. Discarding\n");
-+ return NULL;
-+ }
-+
-+ if (h->h.sapi != Q921_SAPI_CALL_CTRL) {
-+ pri_error(pri, "Message with SAPI other than CALL CTRL is discarded\n");
-+ return NULL;
-+ }
-+
-+ if (pri->debug & PRI_DEBUG_Q921_DUMP) {
-+ pri_message(pri,
-+ "Could not find candidate subchannel for received frame with SAPI/TEI of %d/%d.\n",
-+ h->h.sapi, h->h.tei);
-+ pri_message(pri, "Sending TEI release, in order to re-establish TEI state\n");
-+ }
-+
-+ /* Q.921 says we should send the remove message twice, in case of link corruption */
-+ q921_send_tei(pri, Q921_TEI_IDENTITY_REMOVE, 0, h->h.tei, 1);
-+ q921_send_tei(pri, Q921_TEI_IDENTITY_REMOVE, 0, h->h.tei, 1);
-+
-+ return NULL;
-+}
-+
- static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len)
- {
- pri_event *ev;
-@@ -1225,26 +1323,22 @@
- if (h->h.ea1 || !(h->h.ea2))
- return NULL;
-
--#if 0 /* Will be rejected by subchannel analyzis */
-- /* Check for broadcasts - not yet handled */
-- if (h->h.tei == Q921_TEI_GROUP)
-- return NULL;
--#endif
--
- if (!((h->h.sapi == pri->sapi) && ((h->h.tei == pri->tei) || (h->h.tei == Q921_TEI_GROUP)))) {
- /* Check for SAPIs we don't yet handle */
- /* If it's not us, try any subchannels we have */
- if (pri->subchannel)
- return q921_receive(pri->subchannel, h, len + 2);
- else {
-- return NULL;
-+ /* This means we couldn't find a candidate subchannel for it...
-+ * Time for some corrective action */
-+
-+ return q921_handle_unmatched_frame(pri, h, len);
- }
-
- }
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "Handling message for SAPI/TEI=%d/%d\n", h->h.sapi, h->h.tei);
- ev = __q921_receive_qualified(pri, h, len);
-- reschedule_t203(pri);
- return ev;
- }
-
-
-Property changes on: .
-___________________________________________________________________
-Added: reviewboard:url
- + https://reviewboard.asterisk.org
-
diff --git a/main/libpri/libpri-cflags.patch b/main/libpri/libpri-cflags.patch
deleted file mode 100644
index 7bf31c7ac1..0000000000
--- a/main/libpri/libpri-cflags.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-Index: Makefile
-===================================================================
---- a/Makefile (revision 650)
-+++ b/Makefile (working copy)
-@@ -43,7 +43,7 @@
- DYNAMIC_LIBRARY:=libpri.so.$(SONAME)
- STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o version.o
- DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo version.lo
--CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
-+CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
- INSTALL_PREFIX=$(DESTDIR)
- INSTALL_BASE=/usr
- libdir?=$(INSTALL_BASE)/lib
-@@ -102,7 +102,6 @@
- ifneq (${OSARCH},SunOS)
- install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include
- install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
-- if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY); fi
- ( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf libpri.so.$(SONAME) libpri.so)
- install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
- if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(libdir); fi