[libpri-commits] rmudgett: branch rmudgett/mwi r1568 - /team/rmudgett/mwi/

SVN commits to the libpri project libpri-commits at lists.digium.com
Tue Mar 23 13:50:00 CDT 2010


Author: rmudgett
Date: Tue Mar 23 13:49:56 2010
New Revision: 1568

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1568
Log:
Implement ETSI MWI encode/decode routines with unit test.

Added:
    team/rmudgett/mwi/rose_etsi_mwi.c   (with props)
Modified:
    team/rmudgett/mwi/Makefile
    team/rmudgett/mwi/rose.c
    team/rmudgett/mwi/rose.h
    team/rmudgett/mwi/rose_internal.h
    team/rmudgett/mwi/rose_qsig_mwi.c
    team/rmudgett/mwi/rosetest.c

Modified: team/rmudgett/mwi/Makefile
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/mwi/Makefile?view=diff&rev=1568&r1=1567&r2=1568
==============================================================================
--- team/rmudgett/mwi/Makefile (original)
+++ team/rmudgett/mwi/Makefile Tue Mar 23 13:49:56 2010
@@ -57,6 +57,7 @@
 	rose_etsi_cc.o \
 	rose_etsi_diversion.o \
 	rose_etsi_ect.o \
+	rose_etsi_mwi.o \
 	rose_other.o \
 	rose_q931.o \
 	rose_qsig_aoc.o \
@@ -82,6 +83,7 @@
 	rose_etsi_cc.lo \
 	rose_etsi_diversion.lo \
 	rose_etsi_ect.lo \
+	rose_etsi_mwi.lo \
 	rose_other.lo \
 	rose_q931.lo \
 	rose_qsig_aoc.lo \

Modified: team/rmudgett/mwi/rose.c
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/mwi/rose.c?view=diff&rev=1568&r1=1567&r2=1568
==============================================================================
--- team/rmudgett/mwi/rose.c (original)
+++ team/rmudgett/mwi/rose.c Tue Mar 23 13:49:56 2010
@@ -240,6 +240,14 @@
 /* *INDENT-ON* */
 };
 
+/*! \brief ETSI Message Waiting Indication OID prefix. */
+static const struct asn1_oid rose_etsi_mwi = {
+/* *INDENT-OFF* */
+	/* {ccitt(0) identified-organization(4) etsi(0) 745 operations-and-errors(1)} */
+	4, { 4, 0, 745, 1 }
+/* *INDENT-ON* */
+};
+
 /*! \brief ETSI specific invoke/result encode/decode message table */
 static const struct rose_convert_msg rose_etsi_msgs[] = {
 /* *INDENT-OFF* */
@@ -541,6 +549,26 @@
 			NULL,									NULL,
 			NULL,									NULL
 	},
+
+	/*
+	 * globalValue's (OIDs) from MWI-Operations-and-Errors
+	 * {ccitt identified-organization etsi(0) 745 operations-and-errors(1)}
+	 */
+	{
+		ROSE_ETSI_MWIActivate,						&rose_etsi_mwi, 1,
+			rose_enc_etsi_MWIActivate_ARG,			NULL,
+			rose_dec_etsi_MWIActivate_ARG,			NULL
+	},
+	{
+		ROSE_ETSI_MWIDeactivate,					&rose_etsi_mwi, 2,
+			rose_enc_etsi_MWIDeactivate_ARG,		NULL,
+			rose_dec_etsi_MWIDeactivate_ARG,		NULL
+	},
+	{
+		ROSE_ETSI_MWIIndicate,						&rose_etsi_mwi, 3,
+			rose_enc_etsi_MWIIndicate_ARG,			NULL,
+			rose_dec_etsi_MWIIndicate_ARG,			NULL
+	},
 /* *INDENT-ON* */
 };
 
@@ -695,6 +723,35 @@
 	},
 	{
 		ROSE_ERROR_CCBS_T_ShortTermDenial,			&rose_etsi_ccbs_t, 21,
+			NULL,									NULL
+	},
+
+	/*
+	 * globalValue's (OIDs) from MWI-Operations-and-Errors
+	 * {ccitt identified-organization etsi(0) 745 operations-and-errors(1)}
+	 */
+	{
+		ROSE_ERROR_MWI_InvalidReceivingUserNr,		&rose_etsi_mwi, 10,
+			NULL,									NULL
+	},
+	{
+		ROSE_ERROR_MWI_ReceivingUserNotSubscribed,	&rose_etsi_mwi, 11,
+			NULL,									NULL
+	},
+	{
+		ROSE_ERROR_MWI_ControllingUserNotRegistered,&rose_etsi_mwi, 12,
+			NULL,									NULL
+	},
+	{
+		ROSE_ERROR_MWI_IndicationNotDelivered,		&rose_etsi_mwi, 13,
+			NULL,									NULL
+	},
+	{
+		ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,&rose_etsi_mwi, 14,
+			NULL,									NULL
+	},
+	{
+		ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,&rose_etsi_mwi, 15,
 			NULL,									NULL
 	},
 /* *INDENT-ON* */
@@ -1403,6 +1460,10 @@
 
 		{ ROSE_ETSI_MCIDRequest,                    "ROSE_ETSI_MCIDRequest" },
 
+		{ ROSE_ETSI_MWIActivate,                    "ROSE_ETSI_MWIActivate" },
+		{ ROSE_ETSI_MWIDeactivate,                  "ROSE_ETSI_MWIDeactivate" },
+		{ ROSE_ETSI_MWIIndicate,                    "ROSE_ETSI_MWIIndicate" },
+
 		{ ROSE_QSIG_CallingName,                    "ROSE_QSIG_CallingName" },
 		{ ROSE_QSIG_CalledName,                     "ROSE_QSIG_CalledName" },
 		{ ROSE_QSIG_ConnectedName,                  "ROSE_QSIG_ConnectedName" },
@@ -1516,6 +1577,13 @@
 
 		{ ROSE_ERROR_CCBS_T_LongTermDenial,           "CCBS-T: Long Term Denial" },
 		{ ROSE_ERROR_CCBS_T_ShortTermDenial,          "CCBS-T: Short Term Denial" },
+
+		{ ROSE_ERROR_MWI_InvalidReceivingUserNr,      "MWI: Invalid Receiving User Number" },
+		{ ROSE_ERROR_MWI_ReceivingUserNotSubscribed,  "MWI: Receiving User Not Subscribed" },
+		{ ROSE_ERROR_MWI_ControllingUserNotRegistered,"MWI: Controlling User Not Registered" },
+		{ ROSE_ERROR_MWI_IndicationNotDelivered,      "MWI: Indication Not Delivered" },
+		{ ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,"MWI: Max Num Of Controlling Users Reached" },
+		{ ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,"MWI: Max Num Of Active Instances Reached" },
 
 		/* Q.SIG specific errors */
 		{ ROSE_ERROR_QSIG_Unspecified,                "Unspecified" },

Modified: team/rmudgett/mwi/rose.h
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/mwi/rose.h?view=diff&rev=1568&r1=1567&r2=1568
==============================================================================
--- team/rmudgett/mwi/rose.h (original)
+++ team/rmudgett/mwi/rose.h Tue Mar 23 13:49:56 2010
@@ -137,6 +137,11 @@
 	/* ETSI MCID-Operations */
 	ROSE_ETSI_MCIDRequest,                  /*!< Invoke/Result */
 
+	/* ETSI MWI-Operations-and-Errors */
+	ROSE_ETSI_MWIActivate,                  /*!< Invoke/Result */
+	ROSE_ETSI_MWIDeactivate,                /*!< Invoke/Result */
+	ROSE_ETSI_MWIIndicate,                  /*!< Invoke only */
+
 	/* Q.SIG Name-Operations */
 	ROSE_QSIG_CallingName,                  /*!< Invoke only */
 	ROSE_QSIG_CalledName,                   /*!< Invoke only */
@@ -257,6 +262,14 @@
 	ROSE_ERROR_CCBS_T_LongTermDenial,
 	ROSE_ERROR_CCBS_T_ShortTermDenial,
 
+	/* ETSI MWI-Operations-and-Errors */
+	ROSE_ERROR_MWI_InvalidReceivingUserNr,
+	ROSE_ERROR_MWI_ReceivingUserNotSubscribed,
+	ROSE_ERROR_MWI_ControllingUserNotRegistered,
+	ROSE_ERROR_MWI_IndicationNotDelivered,
+	ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,
+	ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,
+
 	/* Q.SIG from various specifications */
 	ROSE_ERROR_QSIG_Unspecified,
 
@@ -384,6 +397,31 @@
 	 * ITU-T allows up to 2.
 	 */
 	ROSE_Q931_MAX_PROGRESS = 3 * 4,
+};
+
+
+/* ------------------------------------------------------------------- */
+
+
+/*
+ * Comment obtained from ECMA-242 ASN.1 source.
+ * a VisibleString containing:
+ *   - the (local) date in 8 digits (YYYYMMDD),
+ *   - followed by (local) time of day in 4 or 6 digits (HHMM[SS]),
+ *   - optionally followed by the letter "Z" or
+ *     by a local time differential in 5 digits ("+"HHMM or "-"HHMM);
+ *     this date and time representation follows ISO 8601
+ * Examples:
+ * 1) 19970621194530, meaning 21 June 1997, 19:45:30;
+ * 2) 19970621194530Z, meaning the same as 1);
+ * 3) 19970621194530-0500, meaning the same as 1),
+ *      5 hours retarded in relation to UTC time
+ *
+ * GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT VisibleString
+ */
+struct roseGeneralizedTime {
+	/*! GeneralizedTime (SIZE (12..19)) */
+	unsigned char str[19 + 1];
 };
 
 
@@ -2083,6 +2121,206 @@
 
 
 /*
+ * MessageID ::= SEQUENCE {
+ *     messageRef  MessageRef,
+ *     status      MessageStatus
+ * }
+ */
+struct roseEtsiMessageID {
+	/*! \brief Message reference number. (INTEGER (0..65535)) */
+	u_int16_t reference_number;
+	/*!
+	 * \brief Message status
+	 * \details
+	 * added_message(0),
+	 * removed_message(1)
+	 */
+	u_int8_t status;
+};
+
+/*
+ * ARGUMENT SEQUENCE {
+ *     receivingUserNr             PartyNumber,
+ *     basicService                BasicService,
+ *     controllingUserNr           [1] EXPLICIT PartyNumber     OPTIONAL,
+ *     numberOfMessages            [2] EXPLICIT MessageCounter  OPTIONAL,
+ *     controllingUserProvidedNr   [3] EXPLICIT PartyNumber     OPTIONAL,
+ *     time                        [4] EXPLICIT GeneralizedTime OPTIONAL,
+ *     messageId                   [5] EXPLICIT MessageID       OPTIONAL,
+ *     mode                        [6] EXPLICIT InvocationMode  OPTIONAL
+ * }
+ */
+struct roseEtsiMWIActivate_ARG {
+	/*! \brief Number of messages in mailbox. (INTEGER (0..65535)) (Optional) */
+	u_int16_t number_of_messages;
+
+	/*! \brief Message ID (Status of this message) (Optional)*/
+	struct roseEtsiMessageID message_id;
+
+	/*! \brief Receiving user number (Who the message is for.) */
+	struct rosePartyNumber receiving_user_number;
+	/*! \brief Controlling user number (Mailbox number) (Optional) */
+	struct rosePartyNumber controlling_user_number;
+	/*! \brief Controlling user provided number (Caller-ID of party leaving message) (Optional) */
+	struct rosePartyNumber controlling_user_provided_number;
+
+	/*! \brief When message left. (optional) */
+	struct roseGeneralizedTime time;
+
+	/*!
+	 * \brief Type of call leaving message.
+	 * \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;
+	/*!
+	 * \brief Invocation mode (When it should be delivered.) (Optional)
+	 * \details
+	 * deferred(0),
+	 * immediate(1),
+	 * combined(2)
+	 */
+	u_int8_t mode;
+
+	/*! \brief TRUE if NumberOfMessages present */
+	u_int8_t number_of_messages_present;
+	/*! \brief TRUE if time present */
+	u_int8_t time_present;
+	/*! \brief TRUE if MessageId present */
+	u_int8_t message_id_present;
+	/*! \brief TRUE if invocation mode present */
+	u_int8_t mode_present;
+};
+
+/*
+ * ARGUMENT SEQUENCE {
+ *     receivingUserNr     PartyNumber,
+ *     basicService        BasicService,
+ *     controllingUserNr   PartyNumber    OPTIONAL,
+ *     mode                InvocationMode OPTIONAL
+ * }
+ */
+struct roseEtsiMWIDeactivate_ARG {
+	/*! \brief Receiving user number (Who the message is for.) */
+	struct rosePartyNumber receiving_user_number;
+	/*! \brief Controlling user number (Mailbox number) (Optional) */
+	struct rosePartyNumber controlling_user_number;
+
+	/*!
+	 * \brief Type of call leaving message.
+	 * \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;
+
+	/*!
+	 * \brief Invocation mode (When it should be delivered.) (Optional)
+	 * \details
+	 * deferred(0),
+	 * immediate(1),
+	 * combined(2)
+	 */
+	u_int8_t mode;
+
+	/*! \brief TRUE if invocation mode present */
+	u_int8_t mode_present;
+};
+
+/*
+ * ARGUMENT SEQUENCE {
+ *     controllingUserNr           [1] EXPLICIT PartyNumber     OPTIONAL,
+ *     basicService                [2] EXPLICIT BasicService    OPTIONAL,
+ *     numberOfMessages            [3] EXPLICIT MessageCounter  OPTIONAL,
+ *     controllingUserProvidedNr   [4] EXPLICIT PartyNumber     OPTIONAL,
+ *     time                        [5] EXPLICIT GeneralizedTime OPTIONAL,
+ *     messageId                   [6] EXPLICIT MessageID       OPTIONAL
+ * }
+ */
+struct roseEtsiMWIIndicate_ARG {
+	/*! \brief Number of messages in mailbox. (INTEGER (0..65535)) (Optional) */
+	u_int16_t number_of_messages;
+
+	/*! \brief Message ID (Status of this message) (Optional)*/
+	struct roseEtsiMessageID message_id;
+
+	/*! \brief Controlling user number (Mailbox number) (Optional) */
+	struct rosePartyNumber controlling_user_number;
+	/*! \brief Controlling user provided number (Caller-ID of party leaving message) (Optional) */
+	struct rosePartyNumber controlling_user_provided_number;
+
+	/*! \brief When message left. (optional) */
+	struct roseGeneralizedTime time;
+
+	/*!
+	 * \brief Type of call leaving message.
+	 * \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;
+
+	/*! \brief TRUE if basic_service present */
+	u_int8_t basic_service_present;
+	/*! \brief TRUE if NumberOfMessages present */
+	u_int8_t number_of_messages_present;
+	/*! \brief TRUE if time present */
+	u_int8_t time_present;
+	/*! \brief TRUE if MessageId present */
+	u_int8_t message_id_present;
+};
+
+
+/* ------------------------------------------------------------------- */
+
+
+/*
  * Name ::= CHOICE {
  *     -- iso8859-1 is implied in namePresentationAllowedSimple.
  *     namePresentationAllowedSimple   [0] IMPLICIT NameData,
@@ -3450,7 +3688,7 @@
 	struct rosePartyNumber originating_number;
 
 	/*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
-	unsigned char timestamp[19 + 1];
+	struct roseGeneralizedTime timestamp;
 
 	/*!
 	 * \details
@@ -3675,7 +3913,7 @@
 	struct rosePartyNumber originating_number;
 
 	/*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
-	unsigned char timestamp[19 + 1];
+	struct roseGeneralizedTime timestamp;
 
 	/*!
 	 * \details
@@ -3862,6 +4100,11 @@
 
 	/* ETSI CCNR-T */
 	struct roseEtsiCCBS_T_Request_ARG CCNR_T_Request;
+
+	/* ETSI Message Waiting Indication (MWI) */
+	struct roseEtsiMWIActivate_ARG MWIActivate;
+	struct roseEtsiMWIDeactivate_ARG MWIDeactivate;
+	struct roseEtsiMWIIndicate_ARG MWIIndicate;
 };
 
 /*! \brief Facility ie result etsi messages with arguments. */

Added: team/rmudgett/mwi/rose_etsi_mwi.c
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/mwi/rose_etsi_mwi.c?view=auto&rev=1568
==============================================================================
--- team/rmudgett/mwi/rose_etsi_mwi.c (added)
+++ team/rmudgett/mwi/rose_etsi_mwi.c Tue Mar 23 13:49:56 2010
@@ -1,0 +1,686 @@
+/*
+ * libpri: An implementation of Primary Rate ISDN
+ *
+ * Copyright (C) 2010 Digium, Inc.
+ *
+ * Richard Mudgett <rmudgett at 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 Message Waiting Indication (MWI) operations
+ *
+ * Message Waiting Indication (MWI) supplementary service EN 300 745-1
+ *
+ * \author Richard Mudgett <rmudgett at 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 MessageID 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_id
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *rose_enc_etsi_message_id(struct pri *ctrl, unsigned char *pos,
+	unsigned char *end, const struct roseEtsiMessageID *msg_id)
+{
+	unsigned char *seq_len;
+
+	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
+
+	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg_id->reference_number));
+	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, msg_id->status));
+
+	ASN1_CONSTRUCTED_END(seq_len, pos, end);
+
+	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_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
+	unsigned char *end, const union rose_msg_invoke_args *args)
+{
+	const struct roseEtsiMWIActivate_ARG *mwi_activate;
+	unsigned char *seq_len;
+	unsigned char *explicit_len;
+
+	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
+
+	mwi_activate = &args->etsi.MWIActivate;
+	ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
+		&mwi_activate->receiving_user_number));
+	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
+		mwi_activate->basic_service));
+	if (mwi_activate->controlling_user_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,
+			&mwi_activate->controlling_user_number));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_activate->number_of_messages_present) {
+		/* EXPLICIT tag */
+		ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
+		ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
+			mwi_activate->number_of_messages));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_activate->controlling_user_provided_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,
+			&mwi_activate->controlling_user_provided_number));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_activate->time_present) {
+		/* EXPLICIT tag */
+		ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
+		ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
+			mwi_activate->time.str, sizeof(mwi_activate->time.str) - 1));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_activate->message_id_present) {
+		/* EXPLICIT tag */
+		ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
+		ASN1_CALL(pos, rose_enc_etsi_message_id(ctrl, pos, end,
+			&mwi_activate->message_id));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_activate->mode_present) {
+		/* EXPLICIT tag */
+		ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
+		ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
+			mwi_activate->mode));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+
+	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_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
+	unsigned char *end, const union rose_msg_invoke_args *args)
+{
+	const struct roseEtsiMWIDeactivate_ARG *mwi_deactivate;
+	unsigned char *seq_len;
+
+	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
+
+	mwi_deactivate = &args->etsi.MWIDeactivate;
+	ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
+		&mwi_deactivate->receiving_user_number));
+	ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
+		mwi_deactivate->basic_service));
+	if (mwi_deactivate->controlling_user_number.length) {
+		ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
+			&mwi_deactivate->controlling_user_number));
+	}
+	if (mwi_deactivate->mode_present) {
+		ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
+			mwi_deactivate->mode));
+	}
+
+	ASN1_CONSTRUCTED_END(seq_len, pos, end);
+
+	return pos;
+}
+
+/*!
+ * \brief Encode the MWIIndicate 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_MWIIndicate_ARG(struct pri *ctrl, unsigned char *pos,
+	unsigned char *end, const union rose_msg_invoke_args *args)
+{
+	const struct roseEtsiMWIIndicate_ARG *mwi_indicate;
+	unsigned char *seq_len;
+	unsigned char *explicit_len;
+
+	ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
+
+	mwi_indicate = &args->etsi.MWIIndicate;
+	if (mwi_indicate->controlling_user_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,
+			&mwi_indicate->controlling_user_number));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_indicate->basic_service_present) {
+		/* 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,
+			mwi_indicate->basic_service));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_indicate->number_of_messages_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_INTEGER,
+			mwi_indicate->number_of_messages));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_indicate->controlling_user_provided_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_indicate->controlling_user_provided_number));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_indicate->time_present) {
+		/* EXPLICIT tag */
+		ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
+		ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
+			mwi_indicate->time.str, sizeof(mwi_indicate->time.str) - 1));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+	if (mwi_indicate->message_id_present) {
+		/* EXPLICIT tag */
+		ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
+		ASN1_CALL(pos, rose_enc_etsi_message_id(ctrl, pos, end,
+			&mwi_indicate->message_id));
+		ASN1_CONSTRUCTED_END(explicit_len, pos, end);
+	}
+
+	ASN1_CONSTRUCTED_END(seq_len, pos, end);
+
+	return pos;
+}
+
+/*!
+ * \internal
+ * \brief Decode the MessageID 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_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_etsi_message_id(struct pri *ctrl, const char *name,
+	unsigned tag, const unsigned char *pos, const unsigned char *end,
+	struct roseEtsiMessageID *msg_id)
+{
+	int32_t value;
+	int length;
+	int seq_offset;
+	const unsigned char *seq_end;
+
+	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
+	if (ctrl->debug & PRI_DEBUG_APDU) {
+		pri_message(ctrl, "  %s MessageID %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_INTEGER);
+	ASN1_CALL(pos, asn1_dec_int(ctrl, "messageRef", tag, pos, seq_end, &value));
+	msg_id->reference_number = 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, "status", tag, pos, seq_end, &value));
+	msg_id->status = value;
+
+	ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
+
+	return pos;
+}
+
+/*!
+ * \brief Decode the 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_etsi_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 roseEtsiMWIActivate_ARG *mwi_activate;
+
+	mwi_activate = &args->etsi.MWIActivate;
+
+	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
+	if (ctrl->debug & PRI_DEBUG_APDU) {
+		pri_message(ctrl, "  MWIActivate %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, "receivingUserNr", tag, pos, seq_end,
+		&mwi_activate->receiving_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->controlling_user_number.length = 0;
+	mwi_activate->number_of_messages_present = 0;
+	mwi_activate->controlling_user_provided_number.length = 0;
+	mwi_activate->time_present = 0;
+	mwi_activate->message_id_present = 0;
+	mwi_activate->mode_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_PartyNumber(ctrl, "controllingUserNr", tag, pos,
+				explicit_end, &mwi_activate->controlling_user_number));
+
+			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_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
+			ASN1_CALL(pos, asn1_dec_int(ctrl, "numberOfMessages", tag, pos, explicit_end,
+				&value));
+			mwi_activate->number_of_messages = value;
+			mwi_activate->number_of_messages_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_PartyNumber(ctrl, "controllingUserProvidedNr", tag,
+				pos, explicit_end, &mwi_activate->controlling_user_provided_number));
+
+			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_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_GENERALIZED_TIME);
+			ASN1_CALL(pos, asn1_dec_string_max(ctrl, "time", tag, pos, explicit_end,
+				sizeof(mwi_activate->time.str), mwi_activate->time.str, &str_len));
+			mwi_activate->time_present = 1;
+
+			ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
+			break;
+		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_etsi_message_id(ctrl, "messageId", tag, pos,
+				explicit_end, &mwi_activate->message_id));
+			mwi_activate->message_id_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_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
+			ASN1_CALL(pos, asn1_dec_int(ctrl, "mode", tag, pos, explicit_end, &value));
+			mwi_activate->mode = value;
+			mwi_activate->mode_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 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_etsi_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;
+	struct roseEtsiMWIDeactivate_ARG *mwi_deactivate;
+
+	mwi_deactivate = &args->etsi.MWIDeactivate;
+
+	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
+	if (ctrl->debug & PRI_DEBUG_APDU) {
+		pri_message(ctrl, "  MWIDeactivate %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, "receivingUserNr", tag, pos, seq_end,
+		&mwi_deactivate->receiving_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->controlling_user_number.length = 0;
+	mwi_deactivate->mode_present = 0;
+	while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
+		ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
+		switch (tag) {
+		default:
+			ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
+				seq_end, &mwi_deactivate->controlling_user_number));
+			break;
+		case ASN1_TYPE_ENUMERATED:
+			ASN1_CALL(pos, asn1_dec_int(ctrl, "mode", tag, pos, seq_end, &value));
+			mwi_deactivate->mode = value;
+			mwi_deactivate->mode_present = 1;
+			break;
+		}
+	}
+
+	ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
+
+	return pos;
+}
+
+/*!
+ * \brief Decode the MWIIndicate 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_MWIIndicate_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 roseEtsiMWIIndicate_ARG *mwi_indicate;
+
+	mwi_indicate = &args->etsi.MWIIndicate;
+
+	ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
+	if (ctrl->debug & PRI_DEBUG_APDU) {
+		pri_message(ctrl, "  MWIIndicate %s\n", asn1_tag2str(tag));
+	}
+	ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
+	ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
+
+	/*
+	 * A sequence specifies an ordered list of component types.
+	 * However, for simplicity we are not checking the order of
+	 * the remaining optional components.
+	 */
+	mwi_indicate->controlling_user_number.length = 0;
+	mwi_indicate->basic_service_present = 0;
+	mwi_indicate->number_of_messages_present = 0;
+	mwi_indicate->controlling_user_provided_number.length = 0;
+	mwi_indicate->time_present = 0;
+	mwi_indicate->message_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) {
+		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_PartyNumber(ctrl, "controllingUserNr", tag, pos,
+				explicit_end, &mwi_indicate->controlling_user_number));
+
+			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_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
+			ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, explicit_end,
+				&value));
+			mwi_indicate->basic_service = value;
+			mwi_indicate->basic_service_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_INTEGER);
+			ASN1_CALL(pos, asn1_dec_int(ctrl, "numberOfMessages", tag, pos, explicit_end,
+				&value));
+			mwi_indicate->number_of_messages = value;
+			mwi_indicate->number_of_messages_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_PartyNumber(ctrl, "controllingUserProvidedNr", tag,
+				pos, explicit_end, &mwi_indicate->controlling_user_provided_number));
+
+			ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
+			break;
+		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_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_GENERALIZED_TIME);
+			ASN1_CALL(pos, asn1_dec_string_max(ctrl, "time", tag, pos, explicit_end,
+				sizeof(mwi_indicate->time.str), mwi_indicate->time.str, &str_len));
+			mwi_indicate->time_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_etsi_message_id(ctrl, "messageId", tag, pos,
+				explicit_end, &mwi_indicate->message_id));
+			mwi_indicate->message_id_present = 1;
+
+			ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
+			break;
+		default:

[... 217 lines stripped ...]



More information about the libpri-commits mailing list