]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add initial National ISDN Dialect.
authorMichael Jerris <mike@jerris.com>
Thu, 24 May 2007 04:12:15 +0000 (04:12 +0000)
committerMichael Jerris <mike@jerris.com>
Thu, 24 May 2007 04:12:15 +0000 (04:12 +0000)
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@132 a93c3328-9c30-0410-af19-c9cd2b2d52af

libs/freetdm/openzap.vcproj
libs/freetdm/src/isdn/Q931.c
libs/freetdm/src/isdn/Q931ie.c
libs/freetdm/src/isdn/include/Q931.h
libs/freetdm/src/isdn/nationalStateNT.c [new file with mode: 0644]
libs/freetdm/src/isdn/nationalStateTE.c [new file with mode: 0644]
libs/freetdm/src/isdn/nationalie.c [new file with mode: 0644]
libs/freetdm/src/isdn/nationalmes.c [new file with mode: 0644]

index af00754f666e600b1626cbf0a6f424e59004de18..aaacf7578bfb1ed0499198b4c907cd99103915b5 100644 (file)
                                RelativePath=".\src\isdn\mfifo.c"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\src\isdn\nationalie.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\isdn\nationalmes.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\isdn\nationalStateNT.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\isdn\nationalStateTE.c"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath=".\src\isdn\Q921.c"\r
                                >\r
                                        RelativePath=".\src\isdn\include\mfifo.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\src\isdn\include\national.h"\r
+                                       >\r
+                               </File>\r
                                <File\r
                                        RelativePath=".\src\isdn\include\Q921.h"\r
                                        >\r
index f230b5973a2e2f22cef73ebac41b60ddc1fb564c..0e130a3668bf46891961a56e5e675c416f974621 100644 (file)
@@ -37,6 +37,7 @@
 *****************************************************************************/
 
 #include "Q931.h"
+#include "national.h"
 
 /*****************************************************************************
 
@@ -253,6 +254,12 @@ void Q931Initialize()
        if(Q931CreateDialectCB[Q931_Dialect_Q931 + Q931_NT] == NULL)
                Q931AddDialect(Q931_Dialect_Q931 + Q931_NT, Q931CreateNT);
 
+       if(Q931CreateDialectCB[Q931_Dialect_National + Q931_TE] == NULL)
+               Q931AddDialect(Q931_Dialect_National + Q931_TE, nationalCreateTE);
+
+       if(Q931CreateDialectCB[Q931_Dialect_National + Q931_NT] == NULL)
+               Q931AddDialect(Q931_Dialect_National + Q931_NT, nationalCreateNT);
+
        /* The last step we do is to call the callbacks to create the dialects  */
        for(x=0; x< Q931MAXDLCT; x++)
        {
index f6d29610d94198d8add7c48b2ef9ab99aeb4d806..1435e3abc77bd7f57ef68fede6853c1940a1a4e1 100644 (file)
@@ -819,8 +819,7 @@ L3INT Q931Uie_CallingNum(Q931_TrunkInfo_t *pTrunk, ie *pIE, L3UCHAR * IBuf, L3UC
         pie->Digit[x] = IBuf[Octet+Off] & 0x7f;
         Off++;
         x++;
-/*    }while((IBuf[Octet+Off]&0x80) != 0 && x < 20); Temporary dirty hack. */
-       }while(Q931MoreIE());
+    }while((IBuf[Octet+Off]&0x80) != 0 && x < 20);
 
     Q931IESizeTest(Q931E_CALLINGNUM);
 
index b5251e2d7a795c00e2436ddb487ef347728e75b8..00e4f3738fd75b06f66d0d235ad86c1f336a819d 100644 (file)
 /* WARNING! Initialize Q931CreateDialectCB[] will NULL when increasing the  */
 /* Q931MAXDLCT value to avoid Q931Initialize from crashing if one entry is  */
 /* not used.                                                                                                                           */
-#define Q931MAXDLCT 2               /* Max dialects included in this        */
+#define Q931MAXDLCT 4               /* Max dialects included in this        */
                                     /* compile. User and Network count as   */
                                     /* one dialect each.                    */
 
@@ -1932,6 +1932,7 @@ typedef enum                                              /* Network/User Mode.                   */
 typedef enum                                           /* Dialect enum                         */
 {
        Q931_Dialect_Q931 = 0,
+       Q931_Dialect_National = 1,
 
        Q931_Dialect_Count
 } Q931Dialect_t;
diff --git a/libs/freetdm/src/isdn/nationalStateNT.c b/libs/freetdm/src/isdn/nationalStateNT.c
new file mode 100644 (file)
index 0000000..c18e185
--- /dev/null
@@ -0,0 +1,126 @@
+/*****************************************************************************
+
+  FileName:            nationalStateNT.c
+
+  Contents:            National ISDN State Engine for NT (Network Mode).
+
+                               The controlling state engine for Q.931 is the state engine
+                               on the NT side. The state engine on the TE side is a slave 
+                               of this. The TE side maintain it's own states as described in
+                               ITU-T Q931, but will in raise conditions be overridden by 
+                               the NT side.
+
+  License/Copyright:
+
+  Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
+  email:janvb@caselaboratories.com  
+
+  Copyright (c) 2007, Michael Jerris. All rights reserved.
+  email:mike@jerris.com  
+
+  Redistribution and use in source and binary forms, with or without 
+  modification, are permitted provided that the following conditions are 
+  met:
+
+    * Redistributions of source code must retain the above copyright notice, 
+         this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, 
+         this list of conditions and the following disclaimer in the documentation 
+         and/or other materials provided with the distribution.
+    * Neither the name of the Case Labs, Ltd nor the names of its contributors 
+         may be used to endorse or promote products derived from this software 
+         without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+  POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+#include "national.h"
+
+/*****************************************************************************
+  Function:            nationalCreateNT
+
+  Description: Will create the National ISDN NT as a Dialect in the stack. The first
+                               bulk set up the message handlers, the second bulk the IE
+                               encoders/coders, and the last bulk set up the state table.
+
+  Parameters:  i               Dialect index
+*****************************************************************************/
+void nationalCreateNT(L3UCHAR i)
+{
+    Q931SetMesProc(Q931mes_ALERTING,            i,Q931ProcAlertingNT,          Q931Umes_Alerting,          Q931Pmes_Alerting);
+    Q931SetMesProc(Q931mes_CALL_PROCEEDING,     i,Q931ProcCallProceedingNT,    Q931Umes_CallProceeding,    Q931Pmes_CallProceeding);
+    Q931SetMesProc(Q931mes_CONNECT,             i,Q931ProcConnectNT,           Q931Umes_Connect,           Q931Pmes_Connect);
+    Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i,Q931ProcConnectAckNT,        Q931Umes_ConnectAck,        Q931Pmes_ConnectAck);
+    Q931SetMesProc(Q931mes_PROGRESS,            i,Q931ProcProgressNT,          Q931Umes_Progress,          Q931Pmes_Progress);
+    Q931SetMesProc(Q931mes_SETUP,               i,Q931ProcSetupNT,             nationalUmes_Setup,         nationalPmes_Setup);
+    Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE,   i,Q931ProcSetupAckNT,          Q931Umes_SetupAck,          Q931Pmes_SetupAck);
+    Q931SetMesProc(Q931mes_RESUME,              i,Q931ProcResumeNT,            Q931Umes_Resume,            Q931Pmes_Resume);
+    Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE,  i,Q931ProcResumeAckNT,         Q931Umes_ResumeAck,         Q931Pmes_ResumeAck);
+    Q931SetMesProc(Q931mes_RESUME_REJECT,       i,Q931ProcResumeRejectNT,      Q931Umes_ResumeReject,      Q931Pmes_ResumeReject);
+    Q931SetMesProc(Q931mes_SUSPEND,             i,Q931ProcSuspendNT,           Q931Umes_Suspend,           Q931Pmes_Suspend);
+    Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i,Q931ProcSuspendAckNT,        Q931Umes_SuspendAck,        Q931Pmes_SuspendAck);
+    Q931SetMesProc(Q931mes_SUSPEND_REJECT,      i,Q931ProcSuspendRejectNT,     Q931Umes_SuspendReject,     Q931Pmes_SuspendReject);
+    Q931SetMesProc(Q931mes_USER_INFORMATION,    i,Q931ProcUserInformationNT,   Q931Umes_UserInformation,   Q931Pmes_UserInformation);
+    Q931SetMesProc(Q931mes_DISCONNECT,          i,Q931ProcDisconnectNT,        Q931Umes_Disconnect,        Q931Pmes_Disconnect);
+    Q931SetMesProc(Q931mes_RELEASE,             i,Q931ProcReleaseNT,           Q931Umes_Release,           Q931Pmes_Release);
+    Q931SetMesProc(Q931mes_RELEASE_COMPLETE,    i,Q931ProcReleaseCompleteNT,   Q931Umes_ReleaseComplete,   Q931Pmes_ReleaseComplete);
+    Q931SetMesProc(Q931mes_RESTART,             i,Q931ProcRestartNT,           Q931Umes_Restart,           Q931Pmes_Restart);
+    Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i,Q931ProcRestartAckNT,        Q931Umes_RestartAck,        Q931Pmes_RestartAck);
+    Q931SetMesProc(Q931mes_CONGESTION_CONTROL,  i,Q931ProcCongestionControlNT, Q931Umes_CongestionControl, Q931Pmes_CongestionControl);
+    Q931SetMesProc(Q931mes_INFORMATION,         i,Q931ProcInformationNT,       Q931Umes_Information,       Q931Pmes_Information);
+    Q931SetMesProc(Q931mes_NOTIFY,              i,Q931ProcNotifyNT,            Q931Umes_Notify,            Q931Pmes_Notify);
+    Q931SetMesProc(Q931mes_STATUS,              i,Q931ProcStatusNT,            Q931Umes_Status,            Q931Pmes_Status);
+    Q931SetMesProc(Q931mes_STATUS_ENQUIRY,      i,Q931ProcStatusEnquiryNT,     Q931Umes_StatusEnquiry,     Q931Pmes_StatusEnquiry);
+    Q931SetMesProc(Q931mes_SEGMENT,             i,Q931ProcSegmentNT,           Q931Umes_Segment,           Q931Pmes_Segment);
+
+    Q931SetMesProc(Q932mes_FACILITY,            i,Q932ProcFacilityNT,          Q932Umes_Facility,          Q932Pmes_Facility);
+    Q931SetMesProc(Q932mes_HOLD,                i,Q932ProcHoldNT,                     Q932Umes_Hold,              Q932Pmes_Hold);
+    Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE,    i,Q932ProcHoldAckNT,           Q932Umes_HoldAck,           Q932Pmes_HoldAck);
+    Q931SetMesProc(Q932mes_HOLD_REJECT,         i,Q932ProcHoldRejectNT,        Q932Umes_HoldReject,        Q932Pmes_HoldReject);
+    Q931SetMesProc(Q932mes_REGISTER,            i,Q932ProcRegisterNT,          Q932Umes_Register,          Q932Pmes_Register);
+    Q931SetMesProc(Q932mes_RETRIEVE,            i,Q932ProcRetrieveNT,          Q932Umes_Retrieve,          Q932Pmes_Retrieve);
+    Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE,i,Q932ProcRetrieveAckNT,       Q932Umes_RetrieveAck,       Q932Pmes_RetrieveAck);
+    Q931SetMesProc(Q932mes_RETRIEVE_REJECT,     i,Q932ProcRetrieveRejectNT,    Q932Umes_RetrieveReject,    Q932Pmes_RetrieveReject);
+
+       /* Set up the IE encoder/decoder handle table.*/ 
+    Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE,                i,Q931Pie_Segment,                  Q931Uie_Segment);
+    Q931SetIEProc(Q931ie_BEARER_CAPABILITY,                i,Q931Pie_BearerCap,                        Q931Uie_BearerCap);
+    Q931SetIEProc(Q931ie_CAUSE,                            i,Q931Pie_Cause,                            Q931Uie_Cause);
+    Q931SetIEProc(Q931ie_CALL_IDENTITY,                    i,Q931Pie_CallID,                   Q931Uie_CallID);
+    Q931SetIEProc(Q931ie_CALL_STATE,                       i,Q931Pie_CallState,                        Q931Uie_CallState);
+    Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION,           i,Q931Pie_ChanID,                   Q931Uie_ChanID);
+    Q931SetIEProc(Q931ie_PROGRESS_INDICATOR,               i,Q931Pie_ProgInd,                  Q931Uie_ProgInd);
+    Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES,      i,Q931Pie_NetFac,                   Q931Uie_NetFac);
+    Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR,           i,Q931Pie_NotifInd,                 Q931Uie_NotifInd);
+    Q931SetIEProc(Q931ie_DISPLAY,                          i,Q931Pie_Display,                  Q931Uie_Display);
+    Q931SetIEProc(Q931ie_DATETIME,                         i,Q931Pie_DateTime,                 Q931Uie_DateTime);
+    Q931SetIEProc(Q931ie_KEYPAD_FACILITY,                  i,Q931Pie_KeypadFac,                        Q931Uie_KeypadFac);
+    Q931SetIEProc(Q931ie_SIGNAL,                           i,Q931Pie_Signal,                   Q931Uie_Signal);
+    Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND,  i,Q931Pie_TransNetSel,              Q931Uie_TransNetSel);
+    Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER,             i,nationalPie_CallingNum,   nationalUie_CallingNum);
+    Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS,         i,Q931Pie_CallingSub,               Q931Uie_CallingSub);
+    Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER,              i,Q931Pie_CalledNum,                        Q931Uie_CalledNum);
+    Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS,          i,Q931Pie_CalledSub,                        Q931Uie_CalledSub);
+    Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION,        i,Q931Pie_TransNetSel,              Q931Uie_TransNetSel);
+    Q931SetIEProc(Q931ie_RESTART_INDICATOR,                i,Q931Pie_RestartInd,               Q931Uie_RestartInd);
+    Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY,          i,Q931Pie_LLComp,                   Q931Uie_LLComp);
+    Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY,         i,Q931Pie_HLComp,                   Q931Uie_HLComp);
+    Q931SetIEProc(Q931ie_USER_USER,                        i,Q931Pie_UserUser,                 Q931Uie_UserUser);
+    Q931SetIEProc(nationalie_GENERIC_DIGITS,               i,nationalPie_GenericDigits,        nationalUie_GenericDigits);
+
+       /* The following define a state machine. The point is that the Message  */
+       /* procs can when search this to find out if the message/state                  */
+       /* combination is legale. If not, the proc for unexpected message apply.*/
+
+       /* TODO define state table here */
+}
diff --git a/libs/freetdm/src/isdn/nationalStateTE.c b/libs/freetdm/src/isdn/nationalStateTE.c
new file mode 100644 (file)
index 0000000..f8b8a9f
--- /dev/null
@@ -0,0 +1,210 @@
+/*****************************************************************************
+
+  FileName:            nationalStateTE.c
+
+  Contents:            National ISDN State Engine for TE (User Mode).
+
+                               The controlling state engine for Q.931 is the state engine
+                               on the NT side. The state engine on the TE side is a slave 
+                               of this. The TE side maintain it's own states as described in
+                               ITU-T Q931, but will in raise conditions be overridden by 
+                               the NT side.
+
+                               This reference implementation uses a process per message,
+                               meaning that each message must check call states. This
+                               is easier for dialect maintenance as each message proc
+                               can be replaced individually. A new TE variant only
+                               need to copy the Q931CreateTE and replace those procs or
+                               need to override.
+
+  License/Copyright:
+
+  Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
+  email:janvb@caselaboratories.com  
+
+  Copyright (c) 2007, Michael Jerris. All rights reserved.
+  email:mike@jerris.com  
+
+  Redistribution and use in source and binary forms, with or without 
+  modification, are permitted provided that the following conditions are 
+  met:
+
+    * Redistributions of source code must retain the above copyright notice, 
+         this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, 
+         this list of conditions and the following disclaimer in the documentation 
+         and/or other materials provided with the distribution.
+    * Neither the name of the Case Labs, Ltd nor the names of its contributors 
+         may be used to endorse or promote products derived from this software 
+         without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+  POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+#include "national.h"
+
+/*****************************************************************************
+  Function:            nationalCreateTE
+
+  Description: Will create the National TE as a Dialect in the stack. The first
+                               bulk set up the message handlers, the second bulk the IE
+                               encoders/coders, and the last bulk set up the state table.
+
+  Parameters:  i               Dialect index
+*****************************************************************************/
+void nationalCreateTE(L3UCHAR i)
+{
+    Q931SetMesProc(Q931mes_ALERTING,            i,Q931ProcAlertingTE,          Q931Umes_Alerting,          Q931Pmes_Alerting);
+    Q931SetMesProc(Q931mes_CALL_PROCEEDING,     i,Q931ProcCallProceedingTE,    Q931Umes_CallProceeding,    Q931Pmes_CallProceeding);
+    Q931SetMesProc(Q931mes_CONNECT,             i,Q931ProcConnectTE,           Q931Umes_Connect,           Q931Pmes_Connect);
+    Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i,Q931ProcConnectAckTE,        Q931Umes_ConnectAck,        Q931Pmes_ConnectAck);
+    Q931SetMesProc(Q931mes_PROGRESS,            i,Q931ProcProgressTE,          Q931Umes_Progress,          Q931Pmes_Progress);
+    Q931SetMesProc(Q931mes_SETUP,               i,Q931ProcSetupTE,             nationalUmes_Setup,         nationalPmes_Setup);
+    Q931SetMesProc(Q931mes_SETUP_ACKNOWLEDGE,   i,Q931ProcSetupAckTE,          Q931Umes_SetupAck,          Q931Pmes_SetupAck);
+    Q931SetMesProc(Q931mes_RESUME,              i,Q931ProcResumeTE,            Q931Umes_Resume,            Q931Pmes_Resume);
+    Q931SetMesProc(Q931mes_RESUME_ACKNOWLEDGE,  i,Q931ProcResumeAckTE,         Q931Umes_ResumeAck,         Q931Pmes_ResumeAck);
+    Q931SetMesProc(Q931mes_RESUME_REJECT,       i,Q931ProcResumeRejectTE,      Q931Umes_ResumeReject,      Q931Pmes_ResumeReject);
+    Q931SetMesProc(Q931mes_SUSPEND,             i,Q931ProcSuspendTE,           Q931Umes_Suspend,           Q931Pmes_Suspend);
+    Q931SetMesProc(Q931mes_SUSPEND_ACKNOWLEDGE, i,Q931ProcSuspendAckTE,        Q931Umes_SuspendAck,        Q931Pmes_SuspendAck);
+    Q931SetMesProc(Q931mes_SUSPEND_REJECT,      i,Q931ProcSuspendRejectTE,     Q931Umes_SuspendReject,     Q931Pmes_SuspendReject);
+    Q931SetMesProc(Q931mes_USER_INFORMATION,    i,Q931ProcUserInformationTE,   Q931Umes_UserInformation,   Q931Pmes_UserInformation);
+    Q931SetMesProc(Q931mes_DISCONNECT,          i,Q931ProcDisconnectTE,        Q931Umes_Disconnect,        Q931Pmes_Disconnect);
+    Q931SetMesProc(Q931mes_RELEASE,             i,Q931ProcReleaseTE,           Q931Umes_Release,           Q931Pmes_Release);
+    Q931SetMesProc(Q931mes_RELEASE_COMPLETE,    i,Q931ProcReleaseCompleteTE,   Q931Umes_ReleaseComplete,   Q931Pmes_ReleaseComplete);
+    Q931SetMesProc(Q931mes_RESTART,             i,Q931ProcRestartTE,           Q931Umes_Restart,           Q931Pmes_Restart);
+    Q931SetMesProc(Q931mes_RESTART_ACKNOWLEDGE, i,Q931ProcRestartAckTE,        Q931Umes_RestartAck,        Q931Pmes_RestartAck);
+    Q931SetMesProc(Q931mes_CONGESTION_CONTROL,  i,Q931ProcCongestionControlTE, Q931Umes_CongestionControl, Q931Pmes_CongestionControl);
+    Q931SetMesProc(Q931mes_INFORMATION,         i,Q931ProcInformationTE,       Q931Umes_Information,       Q931Pmes_Information);
+    Q931SetMesProc(Q931mes_NOTIFY,              i,Q931ProcNotifyTE,            Q931Umes_Notify,            Q931Pmes_Notify);
+    Q931SetMesProc(Q931mes_STATUS,              i,Q931ProcStatusTE,            Q931Umes_Status,            Q931Pmes_Status);
+    Q931SetMesProc(Q931mes_STATUS_ENQUIRY,      i,Q931ProcStatusEnquiryTE,     Q931Umes_StatusEnquiry,     Q931Pmes_StatusEnquiry);
+    Q931SetMesProc(Q931mes_SEGMENT,             i,Q931ProcSegmentTE,           Q931Umes_Segment,           Q931Pmes_Segment);
+
+    Q931SetMesProc(Q932mes_FACILITY,            i,Q932ProcFacilityTE,          Q932Umes_Facility,          Q932Pmes_Facility);
+    Q931SetMesProc(Q932mes_HOLD,                i,Q932ProcHoldTE,                     Q932Umes_Hold,              Q932Pmes_Hold);
+    Q931SetMesProc(Q932mes_HOLD_ACKNOWLEDGE,    i,Q932ProcHoldAckTE,           Q932Umes_HoldAck,           Q932Pmes_HoldAck);
+    Q931SetMesProc(Q932mes_HOLD_REJECT,         i,Q932ProcHoldRejectTE,        Q932Umes_HoldReject,        Q932Pmes_HoldReject);
+    Q931SetMesProc(Q932mes_REGISTER,            i,Q932ProcRegisterTE,          Q932Umes_Register,          Q932Pmes_Register);
+    Q931SetMesProc(Q932mes_RETRIEVE,            i,Q932ProcRetrieveTE,          Q932Umes_Retrieve,          Q932Pmes_Retrieve);
+    Q931SetMesProc(Q932mes_RETRIEVE_ACKNOWLEDGE,i,Q932ProcRetrieveAckTE,       Q932Umes_RetrieveAck,       Q932Pmes_RetrieveAck);
+    Q931SetMesProc(Q932mes_RETRIEVE_REJECT,     i,Q932ProcRetrieveRejectTE,    Q932Umes_RetrieveReject,    Q932Pmes_RetrieveReject);
+
+       /* Set up the IE encoder/decoder handle table.*/ 
+    Q931SetIEProc(Q931ie_SEGMENTED_MESSAGE,                i,Q931Pie_Segment,                  Q931Uie_Segment);
+    Q931SetIEProc(Q931ie_BEARER_CAPABILITY,                i,Q931Pie_BearerCap,                        Q931Uie_BearerCap);
+    Q931SetIEProc(Q931ie_CAUSE,                            i,Q931Pie_Cause,                            Q931Uie_Cause);
+    Q931SetIEProc(Q931ie_CALL_IDENTITY,                    i,Q931Pie_CallID,                   Q931Uie_CallID);
+    Q931SetIEProc(Q931ie_CALL_STATE,                       i,Q931Pie_CallState,                        Q931Uie_CallState);
+    Q931SetIEProc(Q931ie_CHANNEL_IDENTIFICATION,           i,Q931Pie_ChanID,                   Q931Uie_ChanID);
+    Q931SetIEProc(Q931ie_PROGRESS_INDICATOR,               i,Q931Pie_ProgInd,                  Q931Uie_ProgInd);
+    Q931SetIEProc(Q931ie_NETWORK_SPECIFIC_FACILITIES,      i,Q931Pie_NetFac,                   Q931Uie_NetFac);
+    Q931SetIEProc(Q931ie_NOTIFICATION_INDICATOR,           i,Q931Pie_NotifInd,                 Q931Uie_NotifInd);
+    Q931SetIEProc(Q931ie_DISPLAY,                          i,Q931Pie_Display,                  Q931Uie_Display);
+    Q931SetIEProc(Q931ie_DATETIME,                         i,Q931Pie_DateTime,                 Q931Uie_DateTime);
+    Q931SetIEProc(Q931ie_KEYPAD_FACILITY,                  i,Q931Pie_KeypadFac,                        Q931Uie_KeypadFac);
+    Q931SetIEProc(Q931ie_SIGNAL,                           i,Q931Pie_Signal,                   Q931Uie_Signal);
+    Q931SetIEProc(Q931ie_TRANSIT_DELAY_SELECTION_AND_IND,  i,Q931Pie_TransNetSel,              Q931Uie_TransNetSel);
+    Q931SetIEProc(Q931ie_CALLING_PARTY_NUMBER,             i,nationalPie_CallingNum,   nationalUie_CallingNum);
+    Q931SetIEProc(Q931ie_CALLING_PARTY_SUBADDRESS,         i,Q931Pie_CallingSub,               Q931Uie_CallingSub);
+    Q931SetIEProc(Q931ie_CALLED_PARTY_NUMBER,              i,Q931Pie_CalledNum,                        Q931Uie_CalledNum);
+    Q931SetIEProc(Q931ie_CALLED_PARTY_SUBADDRESS,          i,Q931Pie_CalledSub,                        Q931Uie_CalledSub);
+    Q931SetIEProc(Q931ie_TRANSIT_NETWORK_SELECTION,        i,Q931Pie_TransNetSel,              Q931Uie_TransNetSel);
+    Q931SetIEProc(Q931ie_RESTART_INDICATOR,                i,Q931Pie_RestartInd,               Q931Uie_RestartInd);
+    Q931SetIEProc(Q931ie_LOW_LAYER_COMPATIBILITY,          i,Q931Pie_LLComp,                   Q931Uie_LLComp);
+    Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY,         i,Q931Pie_HLComp,                   Q931Uie_HLComp);
+    Q931SetIEProc(Q931ie_USER_USER,                        i,Q931Pie_UserUser,                 Q931Uie_UserUser);
+    Q931SetIEProc(nationalie_GENERIC_DIGITS,               i,nationalPie_GenericDigits,        nationalUie_GenericDigits);
+
+       /* The following define a state machine. The point is that the Message  */
+       /* procs can when search this to find out if the message/state                  */
+       /* combination is legale. If not, the proc for unexpected message apply.*/
+
+       /* State 0 Idle */
+       Q931AddStateEntry(i,Q931_U0,    Q931mes_RESUME,                 2);
+       Q931AddStateEntry(i,Q931_U0,    Q931mes_SETUP,                  4);
+       Q931AddStateEntry(i,Q931_U0,    Q931mes_SETUP,                  2);
+       Q931AddStateEntry(i,Q931_U0,    Q931mes_STATUS,                 4);
+       Q931AddStateEntry(i,Q931_U0,    Q931mes_RELEASE,                4);
+       Q931AddStateEntry(i,Q931_U0,    Q931mes_RELEASE_COMPLETE,4);
+
+       /* State 1 Call Initiating */
+       Q931AddStateEntry(i,Q931_U1,    Q931mes_DISCONNECT,             2);
+       Q931AddStateEntry(i,Q931_U1,    Q931mes_SETUP_ACKNOWLEDGE,              4);
+       Q931AddStateEntry(i,Q931_U1,    Q931mes_RELEASE_COMPLETE,4);
+       Q931AddStateEntry(i,Q931_U1,    Q931mes_CALL_PROCEEDING,        4);
+       Q931AddStateEntry(i,Q931_U1,    Q931mes_ALERTING,               4);
+       Q931AddStateEntry(i,Q931_U1,    Q931mes_CONNECT,                4);
+
+       /* State 2 Overlap Sending */
+       Q931AddStateEntry(i,Q931_U2,    Q931mes_INFORMATION,    2);
+       Q931AddStateEntry(i,Q931_U2,    Q931mes_CALL_PROCEEDING,        4);
+       Q931AddStateEntry(i,Q931_U2,    Q931mes_ALERTING,               4);
+       Q931AddStateEntry(i,Q931_U2,    Q931mes_PROGRESS,               4);
+       Q931AddStateEntry(i,Q931_U2,    Q931mes_CONNECT,                4);
+       Q931AddStateEntry(i,Q931_U2,    Q931mes_RELEASE,                2);
+
+       /* State 3 Outgoing Call Proceeding */
+       Q931AddStateEntry(i,Q931_U3,    Q931mes_PROGRESS,               4);
+       Q931AddStateEntry(i,Q931_U3,    Q931mes_ALERTING,               4);
+       Q931AddStateEntry(i,Q931_U3,    Q931mes_CONNECT,                4);
+       Q931AddStateEntry(i,Q931_U3,    Q931mes_RELEASE,                2);
+
+       /* State 4 Call Delivered */
+       Q931AddStateEntry(i,Q931_U4,    Q931mes_CONNECT,                4);
+
+       /* State 6 Call Precent */
+       Q931AddStateEntry(i,Q931_U6,    Q931mes_INFORMATION,    2);     
+       Q931AddStateEntry(i,Q931_U6,    Q931mes_ALERTING,               2);     
+       Q931AddStateEntry(i,Q931_U6,    Q931mes_CALL_PROCEEDING,2);     
+       Q931AddStateEntry(i,Q931_U6,    Q931mes_CONNECT,                2);     
+       Q931AddStateEntry(i,Q931_U6,    Q931mes_RELEASE_COMPLETE,2);    
+       Q931AddStateEntry(i,Q931_U6,    Q931mes_RELEASE,                4);     
+       Q931AddStateEntry(i,Q931_U6,    Q931mes_DISCONNECT,             4);     
+
+       /* State 7 Call Received */
+       Q931AddStateEntry(i,Q931_U7,    Q931mes_CONNECT,                2);
+
+       /* State 8 Connect request */
+       Q931AddStateEntry(i,Q931_U8,    Q931mes_CONNECT_ACKNOWLEDGE,            4);
+
+       /* State 9 Incoming Call Proceeding */
+       Q931AddStateEntry(i,Q931_U9,    Q931mes_CONNECT,                2);
+       Q931AddStateEntry(i,Q931_U9,    Q931mes_ALERTING,               2);
+       Q931AddStateEntry(i,Q931_U9,    Q931mes_PROGRESS,               2);
+
+       /* State 10 Active */
+       Q931AddStateEntry(i,Q931_U10,   Q931mes_SUSPEND,                2);
+       Q931AddStateEntry(i,Q931_U10, Q931mes_NOTIFY,                   4);
+       Q931AddStateEntry(i,Q931_U10, Q931mes_NOTIFY,                   2);
+
+       /* State 11 Disconnect Request */
+       Q931AddStateEntry(i,Q931_U11,   Q931mes_RELEASE,                4);
+       Q931AddStateEntry(i,Q931_U11,   Q931mes_DISCONNECT,             4);
+       Q931AddStateEntry(i,Q931_U11,   Q931mes_NOTIFY,                 4);
+
+       /* State 12 Disconnect Ind */
+       Q931AddStateEntry(i,Q931_U12,   Q931mes_RELEASE,                4);
+       Q931AddStateEntry(i,Q931_U12, Q931mes_RELEASE,          2);
+
+       /* State 15 Suspend Request */
+       Q931AddStateEntry(i,Q931_U15,   Q931mes_SUSPEND_ACKNOWLEDGE,            4);
+       Q931AddStateEntry(i,Q931_U15,   Q931mes_SUSPEND_REJECT, 4);
+       Q931AddStateEntry(i,Q931_U15,   Q931mes_DISCONNECT,             4);
+       Q931AddStateEntry(i,Q931_U15,   Q931mes_RELEASE,                4);
+
+/* TODO
+       Q931AddStateEntry(i,Q931_U17,
+       Q931AddStateEntry(i,Q931_U19,
+       Q931AddStateEntry(i,Q931_U25,
+*/
+}
diff --git a/libs/freetdm/src/isdn/nationalie.c b/libs/freetdm/src/isdn/nationalie.c
new file mode 100644 (file)
index 0000000..b6e2446
--- /dev/null
@@ -0,0 +1,254 @@
+/*****************************************************************************
+
+  FileName:     nationalie.c
+
+  Contents:     Information Element Pack/Unpack functions. 
+  
+                These functions will pack out a National ISDN message from the bit 
+                packed original format into structs that are easier to process 
+                and pack the same structs back into bit fields when sending
+                messages out.
+
+                The messages contains a short for each possible IE. The MSB 
+                bit flags the precense of an IE, while the remaining bits 
+                are the offset into a buffer to find the actual IE.
+
+                Each IE are supported by 3 functions:
+
+                nationalPie_XXX     Pack struct into Q.931 IE
+                nationalUie_XXX     Unpack Q.931 IE into struct
+                nationalInitIEXXX   Initialize IE (see nationalapi.c).
+
+  License/Copyright:
+
+  Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
+  email:janvb@caselaboratories.com  
+
+  Copyright (c) 2007, Michael Jerris. All rights reserved.
+  email:mike@jerris.com  
+
+  Redistribution and use in source and binary forms, with or without 
+  modification, are permitted provided that the following conditions are 
+  met:
+
+    * Redistributions of source code must retain the above copyright notice, 
+         this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, 
+         this list of conditions and the following disclaimer in the documentation 
+         and/or other materials provided with the distribution.
+    * Neither the name of the Case Labs, Ltd nor the names of its contributors 
+         may be used to endorse or promote products derived from this software 
+         without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+  POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+#include "national.h"
+
+/*****************************************************************************
+
+  Macro:        Q931MoreIE
+
+  Description:  Local helper macro detecting if there is more IE space left
+                based on the 3 standard parameters Octet, Off and IESpace.
+                This can be used to test if the IE is completed to avoid
+                that the header of the next IE is interpreted as a part of
+                the current IE.
+
+*****************************************************************************/
+#define Q931MoreIE() (Octet+Off - 2 < IESize)
+
+#define Q931IESizeTest(x)   {\
+                            if(Octet+Off-2 != IESize)\
+                            {\
+                                Q931SetError(pTrunk,x, Octet, Off);\
+                                return x;\
+                            }\
+                            }
+
+/*****************************************************************************
+
+  Function:     nationalUie_GenericDigits
+
+  Parameters:   pIE[OUT]        ptr to Information Element id.
+                IBuf[IN]        ptr to a packed ie.
+                OBuf[OUT]       ptr to buffer for Unpacked ie.
+                IOff[IN\OUT]    Input buffer offset
+                OOff[IN\OUT]    Output buffer offset
+
+
+                Ibuf and OBuf points directly to buffers. The IOff and OOff
+                must be updated, but are otherwise not used in the ie unpack.
+
+  Return Value: Error Message
+
+*****************************************************************************/
+L3INT nationalUie_GenericDigits(Q931_TrunkInfo_t *pTrunk, ie *pIE, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
+{
+    nationalie_GenericDigits * pie = (nationalie_GenericDigits*)OBuf;
+    L3INT Off = 0;
+    L3INT Octet = 0;
+    L3INT x=0;
+    L3INT IESize;
+
+    *pIE=0;
+
+    /* Octet 1 */
+    pie->IEId        = IBuf[Octet++];
+
+    /* Octet 2 */
+    IESize = IBuf[Octet++]; 
+
+    Q931SetIE(*pIE, *OOff);
+
+       *IOff = (*IOff) + Octet + Off;
+    *OOff = (*OOff) + sizeof(nationalie_GenericDigits) + x -1;
+    
+       pie->Size = (L3UCHAR)(sizeof(nationalie_GenericDigits) + x -1);
+
+    return Q931E_NO_ERROR;
+}
+
+/*****************************************************************************
+
+  Function:     nationalPie_GenericDigits
+
+  Parameters:   IBuf[IN]        Ptr to struct.
+                OBuf[OUT]        Ptr tp packed output buffer.
+                Octet[IN/OUT]    Offset into OBuf.
+
+  Return Value:    Error code, 0 = OK
+
+*****************************************************************************/
+
+L3INT nationalPie_GenericDigits(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
+{
+       OBuf[(*Octet)++] = nationalie_GENERIC_DIGITS ;
+    OBuf[(*Octet)++] = 2;
+
+    return Q931E_NO_ERROR;
+}
+
+/*****************************************************************************
+
+  Function:     nationalUie_CallingNum
+
+  Parameters:   pIE[OUT]        ptr to Information Element id.
+                IBuf[IN]        ptr to a packed ie.
+                OBuf[OUT]       ptr to buffer for Unpacked ie.
+                IOff[IN\OUT]    Input buffer offset
+                OOff[IN\OUT]    Output buffer offset
+
+                Ibuf and OBuf points directly to buffers. The IOff and OOff
+                must be updated, but are otherwise not used in the ie unpack.
+
+  Return Value: Error Message
+
+*****************************************************************************/
+L3INT nationalUie_CallingNum(Q931_TrunkInfo_t *pTrunk, ie *pIE, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
+{
+     Q931ie_CallingNum * pie = (Q931ie_CallingNum*)OBuf;
+    L3INT Off = 0;
+    L3INT Octet = 0;
+    L3INT x;
+    L3INT IESize;
+
+    *pIE=0;
+
+    /* Octet 1 */
+    pie->IEId  = IBuf[Octet];
+    Octet ++;
+
+    /* Octet 2 */
+    IESize = IBuf[Octet ++]; 
+
+    /* Octet 3 */
+    pie->TypNum = (IBuf[Octet+Off] >> 4) & 0x07;
+    pie->NumPlanID = IBuf[Octet+Off] & 0x0f;
+    
+    /* Octet 3a */
+    if((IBuf[Octet+Off] & 0x80) != 0)
+    {
+        Off++;
+        pie->PresInd = (IBuf[Octet+Off] >> 5) & 0x03;
+        pie->ScreenInd = IBuf[Octet+Off] & 0x03;
+    }
+    Octet++;
+
+    /* Octet 4a*/
+    x=0;
+    do{
+        pie->Digit[x] = IBuf[Octet+Off] & 0x7f;
+        Off++;
+        x++;
+       }while(Q931MoreIE());
+
+    Q931IESizeTest(Q931E_CALLINGNUM);
+
+    Q931SetIE(*pIE, *OOff);
+
+    *IOff = (*IOff) + Octet + Off;
+    *OOff = (*OOff) + sizeof(Q931ie_CallingNum) + x - 1;
+    pie->Size = (L3UCHAR)(sizeof(Q931ie_CallingNum) + x - 1);
+
+    return Q931E_NO_ERROR;
+}
+
+/*****************************************************************************
+
+  Function:     nationalPie_CallingNum
+
+  Parameters:   IBuf[IN]        Ptr to struct.
+                OBuf[OUT]        Ptr tp packed output buffer.
+                Octet[IN/OUT]    Offset into OBuf.
+
+  Return Value:    Error code, 0 = OK
+
+*****************************************************************************/
+L3INT nationalPie_CallingNum(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
+{
+    Q931ie_CallingSub * pIE = (Q931ie_CallingSub*)IBuf;
+    L3INT rc=0;
+    L3INT Beg=*Octet;
+    L3INT li;
+    L3INT sN = pIE->Size - sizeof(Q931ie_CalledSub) + 1;
+    L3INT x;
+
+    /* Octet 1 */
+    OBuf[(*Octet)++] = Q931ie_CALLING_PARTY_SUBADDRESS;
+    li=(*Octet)++;
+
+    /* Octet 3 */
+    OBuf[(*Octet)++] = 0x80 | (pIE->TypNum << 4) | (pIE->OddEvenInd << 3);
+    
+    /* Octet 3a */
+    /*
+
+        Details about the use and how to detect if Octet 3a is used
+        are very weak. Temp left out.
+
+        Octet 3 msb is set to 1 to indicate that this is not present
+
+    */
+
+    /* Octet 4 */
+    for(x=0;x<sN;x++)
+    {
+        OBuf[(*Octet)++] = pIE->Digit[x];
+    }
+
+    OBuf[(*Octet)-1] |= 0x80; /* Terminate bit */
+
+    OBuf[li] = (L3UCHAR)((*Octet)-Beg) - 2;
+    return rc;
+}
diff --git a/libs/freetdm/src/isdn/nationalmes.c b/libs/freetdm/src/isdn/nationalmes.c
new file mode 100644 (file)
index 0000000..c32398d
--- /dev/null
@@ -0,0 +1,301 @@
+/*****************************************************************************
+
+  FileName:            nationalmes.c
+
+  Contents:            Pack/Unpack functions. These functions will unpack a National ISDN
+                               message from the bit packed original format into structs
+                               that contains variables sized by the user. It will also pack
+                               the struct back into a Q.931 message as required.
+
+                               See     national.h for description. 
+
+  License/Copyright:
+
+  Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
+  email:janvb@caselaboratories.com  
+
+  Copyright (c) 2007, Michael Jerris. All rights reserved.
+  email:mike@jerris.com  
+
+  Redistribution and use in source and binary forms, with or without 
+  modification, are permitted provided that the following conditions are 
+  met:
+
+    * Redistributions of source code must retain the above copyright notice, 
+         this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, 
+         this list of conditions and the following disclaimer in the documentation 
+         and/or other materials provided with the distribution.
+    * Neither the name of the Case Labs, Ltd nor the names of its contributors 
+         may be used to endorse or promote products derived from this software 
+         without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+  POSSIBILITY OF SUCH DAMAGE.
+
+*****************************************************************************/
+
+#include "national.h"
+
+/*****************************************************************************
+
+  Function:     nationalUmes_Setup
+
+*****************************************************************************/
+L3INT nationalUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT IOff, L3INT Size)
+{
+       /* L3INT i = IOff; */
+       L3INT ir=0;
+       L3INT OOff=0;
+    Q931mes_Setup *mes = (Q931mes_Setup*)OBuf;
+       L3INT rc=Q931E_NO_ERROR;
+       while(IOff < Size)
+       {
+               switch(IBuf[IOff])
+               {
+               case Q931ie_SENDING_COMPLETE:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->SendComplete,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_REPEAT_INDICATOR:
+                       if(ir==0)
+                       {
+                               rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->RepeatInd,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                               ir++;
+                       }
+                       else if(ir==1)
+                       {
+                               rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->LLRepeatInd,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                               ir++;
+                       }
+                       else
+                       {
+                               return Q931E_ILLEGAL_IE;
+                       }
+                       break;
+               case Q931ie_BEARER_CAPABILITY:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->BearerCap,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_CHANNEL_IDENTIFICATION:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->ChanID,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_PROGRESS_INDICATOR:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->ProgInd,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_NETWORK_SPECIFIC_FACILITIES:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->NetFac,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_DISPLAY:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->Display,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_DATETIME:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->DateTime,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_KEYPAD_FACILITY:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->KeypadFac,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_SIGNAL:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->Signal,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_CALLING_PARTY_NUMBER:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->CallingNum,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_CALLING_PARTY_SUBADDRESS:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->CallingSub,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_CALLED_PARTY_NUMBER:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->CalledSub,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_CALLED_PARTY_SUBADDRESS:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->CalledSub,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_TRANSIT_NETWORK_SELECTION:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->TransNetSel,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_LOW_LAYER_COMPATIBILITY:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->LLComp,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case Q931ie_HIGH_LAYER_COMPATIBILITY:
+                       rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, &mes->HLComp,&IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
+                       if(rc != Q931E_NO_ERROR) 
+                               return rc;
+                       break;
+               case nationalie_GENERIC_DIGITS:
+                       /* TODO: Implement this ie */
+                       break;
+               default:
+                       return Q931E_ILLEGAL_IE;
+                       break;
+               }
+       }
+    mes->Size = sizeof(Q931mes_Setup) - 1 + OOff;
+    return Q931E_NO_ERROR;
+}
+
+/*****************************************************************************
+
+  Function:     nationalPmes_Setup
+
+  Decription:  Pack a Q931mes_Setup into a real Q.931 message. The user will
+                               set up a SETUP message and issue this to the stack where it
+                               is processed by Q931ProcSetup that processes and validates
+                               it before it actually sends it out. This function is called
+                               to compute the real Q.931 message.
+
+  Parameters:  IBuf[IN]        Ptr to un-packed struct
+                               ISize[IN]       Size of input buffer (unpacked message).
+                               OBuf[OUT]       Ptr to packed 'octet' wise message.
+                               OSize[OUT]      Size of packed message.
+
+  Called By:   Q931ProcSetup
+
+*****************************************************************************/
+L3INT nationalPmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
+{
+    L3INT rc = Q931E_NO_ERROR;
+       Q931mes_Setup *pMes = (Q931mes_Setup *)IBuf;
+       L3INT Octet = 0;
+
+       /* Q931 Message Header */
+
+       OBuf[Octet++]   = pMes->ProtDisc;               /* Protocol discriminator               */
+       OBuf[Octet++]   = 2;                                    /* length is 2 octets                   */
+       OBuf[Octet++]   = (L3UCHAR)(pMes->CRV>>8);      /* msb                                          */
+       OBuf[Octet++]   = (L3UCHAR)(pMes->CRV); /* lsb                                                  */
+       OBuf[Octet++]   = pMes->MesType;                /* message header                               */
+       
+       /* Sending Complete                             */
+       if(Q931IsIEPresent(pMes->SendComplete))
+               OBuf[Octet++]   = (L3UCHAR)(pMes->SendComplete & 0x00ff);
+
+       /* Repeat Indicator */
+       if(Q931IsIEPresent(pMes->RepeatInd))
+               OBuf[Octet++]   = (L3UCHAR)(pMes->RepeatInd & 0x00ff);          
+
+       /* Bearer capability */
+       if(Q931IsIEPresent(pMes->BearerCap))
+       {
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+       }
+       else
+       {
+               rc=Q931E_BEARERCAP;
+       }
+
+       /* Channel Identification */
+       if(Q931IsIEPresent(pMes->ChanID))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Progress indicator */
+       if(Q931IsIEPresent(pMes->ProgInd))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Network spesific facilities */
+       if(Q931IsIEPresent(pMes->NetFac))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_NETWORK_SPECIFIC_FACILITIES](pTrunk, Q931GetIEPtr(pMes->NetFac,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Display */
+       if(Q931IsIEPresent(pMes->Display))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Date/Time */
+       if(Q931IsIEPresent(pMes->DateTime))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_DATETIME](pTrunk, Q931GetIEPtr(pMes->DateTime,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Keypad Facility */
+       if(Q931IsIEPresent(pMes->KeypadFac))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_KEYPAD_FACILITY](pTrunk, Q931GetIEPtr(pMes->KeypadFac,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Signal */
+       if(Q931IsIEPresent(pMes->Signal))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Calling Party Number */
+       if(Q931IsIEPresent(pMes->CallingNum))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CallingNum,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Calling Party Subaddress */
+       if(Q931IsIEPresent(pMes->CallingSub))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CallingSub,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Called Party number */
+       if(Q931IsIEPresent(pMes->CalledNum))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CalledNum,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Called party subaddress */
+       if(Q931IsIEPresent(pMes->CalledSub))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CalledSub,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Transit network selection */
+       if(Q931IsIEPresent(pMes->TransNetSel))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_TRANSIT_NETWORK_SELECTION](pTrunk, Q931GetIEPtr(pMes->TransNetSel,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* Repeat Indicator */
+       if(Q931IsIEPresent(pMes->LLRepeatInd))
+               rc = Q931E_UNKNOWN_IE;/* TODO */
+
+       /* Low Layer Compatibility */
+       if(Q931IsIEPresent(pMes->LLComp))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_LOW_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->LLComp,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       /* High Layer Compatibility */
+       if(Q931IsIEPresent(pMes->HLComp))
+               if((rc=Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet))!=0)
+                       return rc;
+
+       *OSize = Octet; 
+
+    return rc;
+}