Add files for 5ess Dialect, numerous formatting and typo fixes. MODENDP-43 and MODENDP-44.

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@346 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
Michael Jerris 2007-11-22 09:28:40 +00:00
parent 027e0d1438
commit 3f2097c49b
10 changed files with 1206 additions and 304 deletions

View File

@ -61,6 +61,9 @@ $(SRC)/isdn/nationalStateTE.o \
$(SRC)/isdn/DMSmes.o \
$(SRC)/isdn/DMSStateNT.o \
$(SRC)/isdn/DMSStateTE.o \
$(SRC)/isdn/5ESSmes.o \
$(SRC)/isdn/5ESSStateNT.o \
$(SRC)/isdn/5ESSStateTE.o \
$(SRC)/isdn/Q932mes.o \
$(SRC)/zap_zt.o \
$(SRC)/zap_wanpipe.o
@ -90,6 +93,8 @@ $(SRC)/include/zap_wanpipe.h \
$(SRC)/include/zap_zt.h \
$(SRC)/isdn/include/mfifo.h \
$(SRC)/isdn/include/national.h \
$(SRC)/isdn/include/DMS.h \
$(SRC)/isdn/include/5ESS.h \
$(SRC)/isdn/include/Q921.h \
$(SRC)/isdn/include/Q931.h \
$(SRC)/isdn/include/Q931ie.h \
@ -180,3 +185,4 @@ clean: mod_openzap-clean
rm -f $(SRC)/*.o $(SRC)/isdn/*.o $(MYLIB) *~ \#* testapp testcid testtones detect_tones detect_dtmf priserver testisdn testanalog
@if [ -f $(LIBPRI)/$(LIBPRIA) ] ; then cd $(LIBPRI) && make clean ; fi

View File

@ -162,6 +162,10 @@
<Filter
Name="Header Files"
>
<File
RelativePath="..\src\isdn\include\5ESS.h"
>
</File>
<File
RelativePath="..\src\isdn\include\DMS.h"
>
@ -194,6 +198,18 @@
<Filter
Name="Source Files"
>
<File
RelativePath="..\src\isdn\5ESSmes.c"
>
</File>
<File
RelativePath="..\src\isdn\5ESSStateNT.c"
>
</File>
<File
RelativePath="..\src\isdn\5ESSStateTE.c"
>
</File>
<File
RelativePath="..\src\isdn\DMSmes.c"
>

View File

@ -0,0 +1,129 @@
/*****************************************************************************
FileName: 5ESSStateNT.c
Contents: AT&T 5ESS 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
Copyright (c) 2007, Michael S. Collins, All rights reserved.
email:mcollins@fcnetwork.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 "5ESS.h"
/*****************************************************************************
Function: ATT5ESSCreateNT
Description: Will create the AT&T 5ESS 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 ATT5ESSCreateNT(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, Q931Umes_Setup, Q931Pmes_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,Q931Pie_CallingNum, Q931Uie_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(Q931ie_GENERIC_DIGITS, i,Q931Pie_GenericDigits, Q931Uie_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 */
}

View File

@ -0,0 +1,295 @@
/*****************************************************************************
FileName: 5ESSStateTE.c
Contents: AT&T 5ESS 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
Copyright (c) 2007, Michael S. Collins, All rights reserved.
email:mcollins@fcnetwork.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 "5ESS.h"
extern L3INT Q931L4HeaderSpace;
/*****************************************************************************
Function: ATT5ESSCreateTE
Description: Will create the AT&T 5ESS 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 ATT5ESSCreateTE(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,ATT5ESSProc0x07TE, ATT5ESSUmes_0x07, ATT5ESSPmes_0x07);
Q931SetMesProc(Q931mes_CONNECT_ACKNOWLEDGE, i,ATT5ESSProc0x0fTE, ATT5ESSUmes_0x0f, ATT5ESSPmes_0x0f);
Q931SetMesProc(Q931mes_PROGRESS, i,Q931ProcProgressTE, Q931Umes_Progress, Q931Pmes_Progress);
Q931SetMesProc(Q931mes_SETUP, i,Q931ProcSetupTE, Q931Umes_Setup, Q931Pmes_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_CHANGE_STATUS, i,Q931Pie_ChangeStatus, Q931Uie_ChangeStatus);
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,Q931Pie_CallingNum, Q931Uie_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(Q931ie_GENERIC_DIGITS, i,Q931Pie_GenericDigits, Q931Uie_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,
*/
}
/*****************************************************************************
Function: ATT5ESSProc0x0fTE
*****************************************************************************/
L3INT ATT5ESSProc0x0fTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
{
L3INT callIndex;
L3INT ret=Q931E_NO_ERROR;
Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace];
if (pMes->ProtDisc == 8) {
/* Find the call using CRV */
ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex);
if(ret != Q931E_NO_ERROR)
return ret;
/* TODO chack against state table for illegal or unexpected message here*/
/* TODO - Set correct timer here */
Q931StartTimer(pTrunk, callIndex, 303);
}
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
}
else if (iFrom ==2)
{
/* TODO Add proc here*/
ret = Q931Tx34(pTrunk,buf,pMes->Size);
if (pMes->ProtDisc == 3 && pTrunk->autoServiceAck) {
printf("autoServiceAck is on, responding to Service Req from network...\n");
Q931AckService(pTrunk, buf);
}
}
return ret;
}
/*****************************************************************************
Function: ATT5ESSProc0x07TE
*****************************************************************************/
L3INT ATT5ESSProc0x07TE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
{
L3INT callIndex;
L3INT ret=Q931E_NO_ERROR;
Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace];
if (pMes->ProtDisc == 8) {
/* Find the call using CRV */
ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex);
if(ret != Q931E_NO_ERROR)
return ret;
/* TODO chack against state table for illegal or unexpected message here*/
/* TODO - Set correct timer here */
Q931StartTimer(pTrunk, callIndex, 303);
}
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
}
else if (iFrom ==2)
{
/* TODO Add proc here*/
ret = Q931Tx34(pTrunk,buf,pMes->Size);
}
return ret;
}

View File

@ -0,0 +1,341 @@
/*****************************************************************************
FileName: 5ESSmes.c
Contents: Pack/Unpack functions. These functions will unpack a 5ESS 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 5ESS.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
Copyright (c) 2007, Michael S. Collins, All rights reserved.
email:mcollins@fcnetwork.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 "5ESS.h"
/*****************************************************************************
Function: ATT5ESSUmes_Setup
*****************************************************************************/
L3INT ATT5ESSUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
{
L3INT ir=0;
L3INT OOff=0;
L3INT rc=Q931E_NO_ERROR;
L3UCHAR last_codeset = 0, codeset = 0;
L3UCHAR shift_lock = 1;
while(IOff < Size)
{
if (!shift_lock) {
codeset = last_codeset;
}
if ((IBuf[IOff] & 0xF0) == Q931ie_SHIFT ) {
shift_lock = (IBuf[IOff] & 0x08);
if (shift_lock) {
last_codeset = codeset;
}
codeset = ((IBuf[IOff] & 0x07));
IOff++;
}
if (codeset == 0) {
switch(IBuf[IOff])
{
case Q931ie_SENDING_COMPLETE:
case Q931ie_BEARER_CAPABILITY:
case Q931ie_CHANNEL_IDENTIFICATION:
case Q931ie_PROGRESS_INDICATOR:
case Q931ie_NETWORK_SPECIFIC_FACILITIES:
case Q931ie_DISPLAY:
case Q931ie_DATETIME:
case Q931ie_KEYPAD_FACILITY:
case Q931ie_SIGNAL:
case Q931ie_CALLING_PARTY_NUMBER:
case Q931ie_CALLING_PARTY_SUBADDRESS:
case Q931ie_CALLED_PARTY_NUMBER:
case Q931ie_CALLED_PARTY_SUBADDRESS:
case Q931ie_TRANSIT_NETWORK_SELECTION:
case Q931ie_LOW_LAYER_COMPATIBILITY:
case Q931ie_HIGH_LAYER_COMPATIBILITY:
rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
if(rc != Q931E_NO_ERROR)
return rc;
break;
case Q931ie_REPEAT_INDICATOR:
if(ir < 2) {
rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
ir++;
} else {
return Q931E_ILLEGAL_IE;
}
break;
default:
return Q931E_ILLEGAL_IE;
break;
}
} else if (codeset == 6) {
switch(IBuf[IOff])
{
case Q931ie_GENERIC_DIGITS:
rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
if(rc != Q931E_NO_ERROR)
return rc;
break;
default:
return Q931E_ILLEGAL_IE;
break;
}
} else {
return Q931E_ILLEGAL_IE;
}
}
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
}
/*****************************************************************************
Function: ATT5ESSPmes_Setup
Decription: Pack a Q931mes_Generic 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 ATT5ESSPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
{
L3INT rc = Q931E_NO_ERROR;
Q931mes_Generic *pMes = (Q931mes_Generic *)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) | (pMes->CRVFlag << 7); /* 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 specific 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;
}
/*****************************************************************************
Function: ATT5ESSUmes_0x0f
*****************************************************************************/
L3INT ATT5ESSUmes_0x0f(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
{
if (mes->ProtDisc == 8) {
return Q931Umes_ConnectAck(pTrunk, IBuf, mes, IOff, Size);
}
if (mes->ProtDisc == 3) {
return Q931Umes_Service(pTrunk, IBuf, mes, IOff, Size);
}
return Q931E_UNKNOWN_MESSAGE;
}
/*****************************************************************************
Function: ATT5ESSPmes_0x0f
*****************************************************************************/
L3INT ATT5ESSPmes_0x0f(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
{
Q931mes_Generic *mes = (Q931mes_Generic *)IBuf;
if (mes->ProtDisc == 8) {
return Q931Pmes_ConnectAck(pTrunk, IBuf, ISize, OBuf, OSize);
}
if (mes->ProtDisc == 3) {
return Q931Pmes_Service(pTrunk, IBuf, ISize, OBuf, OSize);
}
return Q931E_UNKNOWN_MESSAGE;
}
/*****************************************************************************
Function: ATT5ESSUmes_0x07
*****************************************************************************/
L3INT ATT5ESSUmes_0x07(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
{
if (mes->ProtDisc == 8) {
return Q931Umes_Connect(pTrunk, IBuf, mes, IOff, Size);
}
if (mes->ProtDisc == 3) {
return Q931Umes_ServiceAck(pTrunk, IBuf, mes, IOff, Size);
}
return Q931E_UNKNOWN_MESSAGE;
}
/*****************************************************************************
Function: ATT5ESSPmes_0x07
*****************************************************************************/
L3INT ATT5ESSPmes_0x07(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
{
Q931mes_Generic *mes = (Q931mes_Generic *)IBuf;
if (mes->ProtDisc == 8) {
return Q931Pmes_Connect(pTrunk, IBuf, ISize, OBuf, OSize);
}
if (mes->ProtDisc == 3) {
return Q931Pmes_ServiceAck(pTrunk, IBuf, ISize, OBuf, OSize);
}
return Q931E_UNKNOWN_MESSAGE;
}

View File

@ -1,8 +1,8 @@
/*****************************************************************************
FileName: nationalStateTE.c
FileName: DMSStateTE.c
Contents: National ISDN State Engine for TE (User Mode).
Contents: DMS-100 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

View File

@ -3,7 +3,7 @@
FileName: Q931.c
Contents: Implementation of Q.931 stack main interface functions.
See q931.h for description.
See q931.h for description.
License/Copyright:
@ -15,13 +15,13 @@
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
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.
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.
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
@ -39,6 +39,8 @@
#include "Q931.h"
#include "national.h"
#include "DMS.h"
#include "5ESS.h"
/*****************************************************************************
@ -50,7 +52,7 @@
The arrays are initialized with pointers to dummy functions and later
overrided with pointers to actual functions as new dialects are added.
The initial Q.931 will as an example define 2 dielects as it treats User
The initial Q.931 will as an example define 2 dialects as it treats User
and Network mode as separate ISDN dialects.
The API messages Q931AddProc, Q931AddMes, Q931AddIE are used to initialize
@ -68,8 +70,8 @@ q931pie_func_t *Q931Pie[Q931MAXDLCT][Q931MAXIE];
void (*Q931CreateDialectCB[Q931MAXDLCT]) (L3UCHAR iDialect)=
{
NULL,
NULL
NULL,
NULL
};
Q931State Q931st[Q931MAXSTATE];
@ -80,7 +82,7 @@ Q931State Q931st[Q931MAXSTATE];
*****************************************************************************/
L3INT Q931L4HeaderSpace={0}; /* header space to be ignoder/inserted */
L3INT Q931L4HeaderSpace = {0}; /* header space to be ignoder/inserted */
/* at head of each message. */
L3INT Q931L2HeaderSpace = {4}; /* Q921 header space, sapi, tei etc */
@ -92,7 +94,7 @@ L3INT Q931L2HeaderSpace = {4}; /* Q921 header space, sapi, tei etc */
*****************************************************************************/
Q931ErrorCB_t Q931ErrorProc;
/* callback for error messages. */
/* callback for error messages. */
L3ULONG (*Q931GetTimeProc) ()=NULL; /* callback for func reading time in ms */
@ -128,7 +130,7 @@ void Q931SetL2HeaderSpace(L3INT space)
/*****************************************************************************
Function: Q931
Function: Q931ProcDummy
Description: Dummy function for message processing.
@ -140,7 +142,7 @@ L3INT Q931ProcDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b,L3INT c)
/*****************************************************************************
Function: Q931
Function: Q931UmesDummy
Description: Dummy function for message processing
@ -152,7 +154,7 @@ L3INT Q931UmesDummy(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *OBu
/*****************************************************************************
Function: Q931
Function: Q931UieDummy
Description: Dummy function for message processing
@ -164,7 +166,7 @@ L3INT Q931UieDummy(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IB
/*****************************************************************************
Function: Q931
Function: Q931PmesDummy
Description: Dummy function for message processing
@ -207,7 +209,7 @@ L3INT Q931TxDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT n)
*****************************************************************************/
L3INT Q931ErrorDummy(void *priv, L3INT a, L3INT b, L3INT c)
{
return 0;
return 0;
}
/*****************************************************************************
@ -218,7 +220,7 @@ L3INT Q931ErrorDummy(void *priv, L3INT a, L3INT b, L3INT c)
Will set up the trunk array, channel
arrays and initialize Q931 function arrays before it finally
set up EuroISDN processing with User as diealect 0 and
set up EuroISDN processing with User as dialect 0 and
Network as dialect 1.
Note: Initialization of other stacks should be inserted after
@ -229,53 +231,59 @@ void Q931Initialize()
{
L3INT x,y;
/* Secure the callbacks to default procs */
/* Secure the callbacks to default procs */
Q931ErrorProc = Q931ErrorDummy;
/* The user will only add the message handlers and IE handlers he need, */
/* so we need to initialize every single entry to a default function */
/* that will throw an appropriate error if they are ever called. */
for(x=0;x< Q931MAXDLCT;x++)
/* The user will only add the message handlers and IE handlers he need, */
/* so we need to initialize every single entry to a default function */
/* that will throw an appropriate error if they are ever called. */
for(x=0; x < Q931MAXDLCT; x++)
{
for(y=0;y<Q931MAXMES;y++)
for(y=0; y < Q931MAXMES; y++)
{
Q931Proc[x][y] = Q931ProcDummy;
Q931Umes[x][y] = Q931UmesDummy;
Q931Pmes[x][y] = Q931PmesDummy;
}
for(y=0;y<Q931MAXIE;y++)
for(y=0; y < Q931MAXIE; y++)
{
Q931Pie[x][y] = Q931PieDummy;
Q931Uie[x][y] = Q931UieDummy;
}
}
if(Q931CreateDialectCB[Q931_Dialect_Q931 + Q931_TE] == NULL)
Q931AddDialect(Q931_Dialect_Q931 + Q931_TE, Q931CreateTE);
if(Q931CreateDialectCB[Q931_Dialect_Q931 + Q931_TE] == NULL)
Q931AddDialect(Q931_Dialect_Q931 + Q931_TE, Q931CreateTE);
if(Q931CreateDialectCB[Q931_Dialect_Q931 + Q931_NT] == NULL)
Q931AddDialect(Q931_Dialect_Q931 + Q931_NT, Q931CreateNT);
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_TE] == NULL)
Q931AddDialect(Q931_Dialect_National + Q931_TE, nationalCreateTE);
if(Q931CreateDialectCB[Q931_Dialect_National + Q931_NT] == NULL)
Q931AddDialect(Q931_Dialect_National + Q931_NT, nationalCreateNT);
if(Q931CreateDialectCB[Q931_Dialect_National + Q931_NT] == NULL)
Q931AddDialect(Q931_Dialect_National + Q931_NT, nationalCreateNT);
if(Q931CreateDialectCB[Q931_Dialect_DMS + Q931_TE] == NULL)
Q931AddDialect(Q931_Dialect_DMS + Q931_TE, DMSCreateTE);
if(Q931CreateDialectCB[Q931_Dialect_DMS + Q931_TE] == NULL)
Q931AddDialect(Q931_Dialect_DMS + Q931_TE, DMSCreateTE);
if(Q931CreateDialectCB[Q931_Dialect_DMS + Q931_NT] == NULL)
Q931AddDialect(Q931_Dialect_DMS + Q931_NT, DMSCreateNT);
if(Q931CreateDialectCB[Q931_Dialect_DMS + Q931_NT] == NULL)
Q931AddDialect(Q931_Dialect_DMS + Q931_NT, DMSCreateNT);
/* The last step we do is to call the callbacks to create the dialects */
for(x=0; x< Q931MAXDLCT; x++)
{
if(Q931CreateDialectCB[x] != NULL)
{
Q931CreateDialectCB[x]((L3UCHAR)x);
}
}
if(Q931CreateDialectCB[Q931_Dialect_5ESS + Q931_TE] == NULL)
Q931AddDialect(Q931_Dialect_5ESS + Q931_TE, ATT5ESSCreateTE);
if(Q931CreateDialectCB[Q931_Dialect_5ESS + Q931_NT] == NULL)
Q931AddDialect(Q931_Dialect_5ESS + Q931_NT, ATT5ESSCreateNT);
/* The last step we do is to call the callbacks to create the dialects */
for(x=0; x < Q931MAXDLCT; x++)
{
if(Q931CreateDialectCB[x] != NULL)
{
Q931CreateDialectCB[x]((L3UCHAR)x);
}
}
}
/*****************************************************************************
@ -292,14 +300,14 @@ void Q931Initialize()
*****************************************************************************/
void Q931TimeTick(Q931_TrunkInfo_t *pTrunk, L3ULONG ms)
{
(void)pTrunk;
(void)pTrunk;
ms=ms; /* avoid warning for now. */
/* TODO: Loop through all active calls, check timers and call timour procs
* if timers are expired.
* Implement an function array so each dialect can deal with their own
* timeouts.
*/
/* TODO: Loop through all active calls, check timers and call timout procs
* if timers are expired.
* Implement a function array so each dialect can deal with their own
* timeouts.
*/
}
/*****************************************************************************
@ -311,22 +319,22 @@ void Q931TimeTick(Q931_TrunkInfo_t *pTrunk, L3ULONG ms)
interpreted and translated to a static struct. Secondly
the message is processed and responded to.
The Q.931 message contains a static header that is
interpreated in his function. The rest is interpreted
in a sub function according to mestype.
The Q.931 message contains a static header that is
interpreted in this function. The rest is interpreted
in a sub function according to mestype.
Parameters: pTrunk [IN] Ptr to trunk info.
buf [IN] Ptr to buffer containing message.
Size [IN] Size of message.
Parameters: pTrunk [IN] Ptr to trunk info.
buf [IN] Ptr to buffer containing message.
Size [IN] Size of message.
Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
see q931errors.h for details.
see q931errors.h for details.
*****************************************************************************/
L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT Size)
{
L3UCHAR *Mes = &buf[Q931L2HeaderSpace];
L3INT RetCode = Q931E_NO_ERROR;
L3INT RetCode = Q931E_NO_ERROR;
Q931mes_Generic *m = (Q931mes_Generic *) pTrunk->L3Buf;
L3INT ISize;
@ -336,42 +344,44 @@ L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT Size)
m->ProtDisc = Mes[IOff++];
/* CRV */
m->CRVFlag = Mes[IOff + 1] & 0x80;
m->CRVFlag = Mes[IOff + 1] & 0x80;
m->CRV = Q931Uie_CRV(pTrunk, Mes, m->buf, &IOff, &ISize);
/* Message Type */
m->MesType = Mes[IOff++];
/* Call table proc to unpack codec message */
RetCode = Q931Umes[pTrunk->Dialect][m->MesType](pTrunk, Mes, (Q931mes_Generic *)pTrunk->L3Buf, Q931L4HeaderSpace + IOff , Size - Q931L4HeaderSpace - IOff + 1);
/*debug */
/* printf("\n\nQ931Rx23- Dialect: %d, MsgType: %d\n",pTrunk->Dialect,m->MesType); */
RetCode = Q931Umes[pTrunk->Dialect][m->MesType](pTrunk, Mes, (Q931mes_Generic *)pTrunk->L3Buf, Q931L4HeaderSpace + IOff , Size - Q931L4HeaderSpace - IOff + 1);
if(RetCode >= Q931E_NO_ERROR)
{
RetCode = Q931Proc[pTrunk->Dialect][m->MesType](pTrunk, pTrunk->L3Buf, 2);
}
if(RetCode >= Q931E_NO_ERROR)
{
RetCode = Q931Proc[pTrunk->Dialect][m->MesType](pTrunk, pTrunk->L3Buf, 2);
}
return RetCode;
}
/*****************************************************************************
Function: Q931Tx34
Function: Q931Tx34
Description: Called from the stac to send a message to layer 4.
Description: Called from the stack to send a message to layer 4.
Parameters: Mes[IN] Ptr to message buffer.
Size[IN] Message size in bytes.
Parameters: Mes[IN] Ptr to message buffer.
Size[IN] Message size in bytes.
Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
see q931errors.h for details.
see q931errors.h for details.
*****************************************************************************/
L3INT Q931Tx34(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size)
{
if (pTrunk->Q931Tx34CBProc) {
return pTrunk->Q931Tx34CBProc(pTrunk->PrivateData34, Mes, Size);
}
return Q931E_MISSING_CB;
if (pTrunk->Q931Tx34CBProc) {
return pTrunk->Q931Tx34CBProc(pTrunk->PrivateData34, Mes, Size);
}
return Q931E_MISSING_CB;
}
/*****************************************************************************
@ -385,52 +395,52 @@ L3INT Q931Tx34(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size)
Size[IN] Message size in bytes.
Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
see q931errors.h for details.
see q931errors.h for details.
*****************************************************************************/
L3INT Q931Rx43(Q931_TrunkInfo_t *pTrunk,L3UCHAR * buf, L3INT Size)
{
Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace];
L3INT RetCode = Q931E_NO_ERROR;
L3INT RetCode = Q931E_NO_ERROR;
RetCode=Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk,buf,4);
RetCode=Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk,buf,4);
return RetCode;
}
/*****************************************************************************
Function: Q931Tx32
Function: Q931Tx32
Description: Called from the stack to send a message to L2. The input is
Description: Called from the stack to send a message to L2. The input is
always a non-packed message so it will first make a proper
call to create a packed message before it transmits that
message to layer 2.
Parameters: pTrunk[IN] Trunk #
buf[IN] Ptr to message buffer.
Size[IN] Message size in bytes.
Parameters: pTrunk[IN] Trunk #
buf[IN] Ptr to message buffer.
Size[IN] Message size in bytes.
Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
see q931errors.h for details.
see q931errors.h for details.
*****************************************************************************/
L3INT Q931Tx32(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size)
{
L3INT OSize;
Q931mes_Generic *ptr = (Q931mes_Generic*)Mes;
L3INT RetCode = Q931E_NO_ERROR;
L3INT RetCode = Q931E_NO_ERROR;
L3INT iDialect = pTrunk->Dialect;
/* Call pack function through table. */
RetCode = Q931Pmes[iDialect][ptr->MesType](pTrunk, (Q931mes_Generic *)Mes, Size, &pTrunk->L2Buf[Q931L2HeaderSpace], &OSize);
if(RetCode >= Q931E_NO_ERROR)
{
if (pTrunk->Q931Tx32CBProc) {
RetCode = pTrunk->Q931Tx32CBProc(pTrunk->PrivateData32, pTrunk->L2Buf, OSize + Q931L2HeaderSpace);
} else {
RetCode = Q931E_MISSING_CB;
}
if(RetCode >= Q931E_NO_ERROR)
{
if (pTrunk->Q931Tx32CBProc) {
RetCode = pTrunk->Q931Tx32CBProc(pTrunk->PrivateData32, pTrunk->L2Buf, OSize + Q931L2HeaderSpace);
} else {
RetCode = Q931E_MISSING_CB;
}
}
return RetCode;
@ -439,23 +449,23 @@ L3INT Q931Tx32(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size)
/*****************************************************************************
Function: Q931SetError
Function: Q931SetError
Description: Called from the stack to indicate an error.
Description: Called from the stack to indicate an error.
Parameters: ErrID ID of ie or message causing error.
ErrPar1 Error parameter 1
Parameters: ErrID ID of ie or message causing error.
ErrPar1 Error parameter 1
ErrPar2 Error parameter 2.
*****************************************************************************/
void Q931SetError(Q931_TrunkInfo_t *pTrunk,L3INT ErrID, L3INT ErrPar1, L3INT ErrPar2)
{
if (pTrunk->Q931ErrorCBProc) {
pTrunk->Q931ErrorCBProc(pTrunk->PrivateData34, ErrID, ErrPar1, ErrPar2);
} else {
Q931ErrorProc(pTrunk->PrivateData34, ErrID, ErrPar1, ErrPar2);
}
if (pTrunk->Q931ErrorCBProc) {
pTrunk->Q931ErrorCBProc(pTrunk->PrivateData34, ErrID, ErrPar1, ErrPar2);
} else {
Q931ErrorProc(pTrunk->PrivateData34, ErrID, ErrPar1, ErrPar2);
}
}
void Q931SetDefaultErrorCB(Q931ErrorCB_t Q931ErrorPar)
@ -465,58 +475,58 @@ void Q931SetDefaultErrorCB(Q931ErrorCB_t Q931ErrorPar)
/*****************************************************************************
Function: Q931CreateCRV
Function: Q931CreateCRV
Description: Create a CRV entry and return it's index. The function will
locate a free entry in the call tables allocate it and
allocate a unique CRV value attached to it.
Description: Create a CRV entry and return it's index. The function will
locate a free entry in the call tables allocate it and
allocate a unique CRV value attached to it.
Parameters: pTrunk [IN] Trunk number
callindex [OUT] return call table index.
Parameters: pTrunk [IN] Trunk number
callindex [OUT] return call table index.
Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
see q931errors.h for details.
see q931errors.h for details.
*****************************************************************************/
L3INT Q931CreateCRV(Q931_TrunkInfo_t *pTrunk, L3INT * callIndex)
L3INT Q931CreateCRV(Q931_TrunkInfo_t *pTrunk, L3INT * callIndex)
{
L3INT CRV = Q931GetUniqueCRV(pTrunk);
L3INT CRV = Q931GetUniqueCRV(pTrunk);
return Q931AllocateCRV(pTrunk, CRV, callIndex);
return Q931AllocateCRV(pTrunk, CRV, callIndex);
}
/*****************************************************************************
Function: Q931AllocateCRV
Function: Q931AllocateCRV
Description: Allocate a call table entry and assigns the given CRV value
to it.
Description: Allocate a call table entry and assigns the given CRV value
to it.
Parameters: pTrunk [IN] Trunk number
iCRV [IN] Call Reference Value.
callindex [OUT] return call table index.
Parameters: pTrunk [IN] Trunk number
iCRV [IN] Call Reference Value.
callindex [OUT] return call table index.
Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
see q931errors.h for details.
see q931errors.h for details.
*****************************************************************************/
L3INT Q931AllocateCRV(Q931_TrunkInfo_t *pTrunk, L3INT iCRV, L3INT * callIndex)
L3INT Q931AllocateCRV(Q931_TrunkInfo_t *pTrunk, L3INT iCRV, L3INT * callIndex)
{
L3INT x;
for(x=0; x < Q931MAXCALLPERTRUNK; x++)
{
if(!pTrunk->call[x].InUse)
{
pTrunk->call[x].CRV = iCRV;
pTrunk->call[x].BChan = 255;
pTrunk->call[x].State = 0; /* null state - idle */
pTrunk->call[x].TimerID = 0; /* no timer running */
pTrunk->call[x].Timer = 0;
pTrunk->call[x].InUse = 1; /* mark as used */
for(x=0; x < Q931MAXCALLPERTRUNK; x++)
{
if(!pTrunk->call[x].InUse)
{
pTrunk->call[x].CRV = iCRV;
pTrunk->call[x].BChan = 255;
pTrunk->call[x].State = 0; /* null state - idle */
pTrunk->call[x].TimerID = 0; /* no timer running */
pTrunk->call[x].Timer = 0;
pTrunk->call[x].InUse = 1; /* mark as used */
*callIndex = x;
return Q931E_NO_ERROR;
}
}
}
}
return Q931E_TOMANYCALLS;
}
@ -527,19 +537,19 @@ L3INT Q931AllocateCRV(Q931_TrunkInfo_t *pTrunk, L3INT iCRV, L3INT * callIndex)
Description: Look up CRV and return current call state. A non existing
CRV is the same as state zero (0).
Parameters: pTrunk [IN] Trunk number.
iCRV [IN] CRV
Parameters: pTrunk [IN] Trunk number.
iCRV [IN] CRV
Return Value: Call State.
*****************************************************************************/
L3INT Q931GetCallState(Q931_TrunkInfo_t *pTrunk, L3INT iCRV)
L3INT Q931GetCallState(Q931_TrunkInfo_t *pTrunk, L3INT iCRV)
{
L3INT x;
for(x=0; x < Q931MAXCALLPERTRUNK; x++)
{
if(pTrunk->call[x].InUse)
{
for(x=0; x < Q931MAXCALLPERTRUNK; x++)
{
if(pTrunk->call[x].InUse)
{
if(pTrunk->call[x].CRV == iCRV)
{
return pTrunk->call[x].State;
@ -589,9 +599,9 @@ L3ULONG Q931GetTime()
tNow = Q931GetTimeProc();
if(tNow < tLast) /* wrapped */
{
/* TODO */
/* TODO */
}
tLast = tNow;
tLast = tNow;
}
return tNow;
}
@ -604,10 +614,10 @@ void Q931SetGetTimeCB(L3ULONG (*callback)())
L3INT Q931FindCRV(Q931_TrunkInfo_t *pTrunk, L3INT crv, L3INT *callindex)
{
L3INT x;
for(x=0; x < Q931MAXCALLPERTRUNK; x++)
{
if(pTrunk->call[x].InUse)
{
for(x=0; x < Q931MAXCALLPERTRUNK; x++)
{
if(pTrunk->call[x].InUse)
{
if(pTrunk->call[x].CRV == crv)
{
*callindex = x;
@ -621,101 +631,101 @@ L3INT Q931FindCRV(Q931_TrunkInfo_t *pTrunk, L3INT crv, L3INT *callindex)
void Q931AddDialect(L3UCHAR i, void (*callback)(L3UCHAR iD ))
{
if(i < Q931MAXDLCT)
{
Q931CreateDialectCB[i] = callback;
}
if(i < Q931MAXDLCT)
{
Q931CreateDialectCB[i] = callback;
}
}
/*****************************************************************************
Function: Q931AddStateEntry
Function: Q931AddStateEntry
Description: Find an empty entry in the dialects state table and add this
entry.
Description: Find an empty entry in the dialects state table and add this
entry.
*****************************************************************************/
void Q931AddStateEntry(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir)
void Q931AddStateEntry(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir)
{
int x;
for(x=0; x < Q931MAXSTATE; x++)
{
if(Q931st[x].Message == 0)
{
Q931st[x].State = iState;
Q931st[x].Message = iMes;
Q931st[x].Direction = cDir;
/* TODO Sort table and use bsearch */
return;
}
}
int x;
for(x=0; x < Q931MAXSTATE; x++)
{
if(Q931st[x].Message == 0)
{
Q931st[x].State = iState;
Q931st[x].Message = iMes;
Q931st[x].Direction = cDir;
/* TODO Sort table and use bsearch */
return;
}
}
}
/*****************************************************************************
Function: Q931IsEventLegal
Function: Q931IsEventLegal
Description: Check state table for matching criteria to indicate if this
Message is legal in this state or not.
Description: Check state table for matching criteria to indicate if this
Message is legal in this state or not.
Note: Someone write a bsearch or invent something smart here
please - sequensial is ok for now.
Note: Someone write a bsearch or invent something smart here
please - sequential is ok for now.
*****************************************************************************/
L3BOOL Q931IsEventLegal(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir)
{
int x;
/* TODO Sort table and use bsearch */
for(x=0; x < Q931MAXSTATE; x++)
{
if( Q931st[x].State == iState
&& Q931st[x].Message == iMes
&& Q931st[x].Direction == cDir)
{
return L3TRUE;
}
}
return L3FALSE;
int x;
/* TODO Sort table and use bsearch */
for(x=0; x < Q931MAXSTATE; x++)
{
if( Q931st[x].State == iState
&& Q931st[x].Message == iMes
&& Q931st[x].Direction == cDir)
{
return L3TRUE;
}
}
return L3FALSE;
}
/*****************************************************************************
Function: q931_error_to_name()
Function: q931_error_to_name()
Description: Check state table for matching criteria to indicate if this
Message is legal in this state or not.
Description: Check state table for matching criteria to indicate if this
Message is legal in this state or not.
Note: Someone write a bsearch or invent something smart here
please - sequensial is ok for now.
Note: Someone write a bsearch or invent something smart here
please - sequential is ok for now.
*****************************************************************************/
static const char *q931_error_names[] = {
"Q931E_NO_ERROR", /* 0 */
"Q931E_NO_ERROR", /* 0 */
"Q931E_UNKNOWN_MESSAGE", /* -3001 */
"Q931E_ILLEGAL_IE", /* -3002 */
"Q931E_UNKNOWN_IE", /* -3003 */
"Q931E_BEARERCAP", /* -3004 */
"Q931E_HLCOMP", /* -3005 */
"Q931E_LLCOMP", /* -3006 */
"Q931E_INTERNAL", /* -3007 */
"Q931E_MISSING_CB", /* -3008 */
"Q931E_UNEXPECTED_MESSAGE", /* -3009 */
"Q931E_ILLEGAL_MESSAGE", /* -3010 */
"Q931E_TOMANYCALLS", /* -3011 */
"Q931E_INVALID_CRV", /* -3012 */
"Q931E_CALLID", /* -3013 */
"Q931E_CALLSTATE", /* -3014 */
"Q931E_CALLEDSUB", /* -3015 */
"Q931E_CALLEDNUM", /* -3016 */
"Q931E_CALLINGNUM", /* -3017 */
"Q931E_CALLINGSUB", /* -3018 */
"Q931E_CAUSE", /* -3019 */
"Q931E_CHANID", /* -3020 */
"Q931E_DATETIME", /* -3021 */
"Q931E_DISPLAY", /* -3022 */
"Q931E_KEYPADFAC", /* -3023 */
"Q931E_NETFAC", /* -3024 */
"Q931E_NOTIFIND", /* -3025 */
"Q931E_PROGIND", /* -3026 */
"Q931E_RESTARTIND", /* -3027 */
"Q931E_SEGMENT", /* -3028 */
"Q931E_SIGNAL", /* -3029 */
"Q931E_GENERIC_DIGITS" /* -3030 */
"Q931E_UNKNOWN_MESSAGE", /* -3001 */
"Q931E_ILLEGAL_IE", /* -3002 */
"Q931E_UNKNOWN_IE", /* -3003 */
"Q931E_BEARERCAP", /* -3004 */
"Q931E_HLCOMP", /* -3005 */
"Q931E_LLCOMP", /* -3006 */
"Q931E_INTERNAL", /* -3007 */
"Q931E_MISSING_CB", /* -3008 */
"Q931E_UNEXPECTED_MESSAGE", /* -3009 */
"Q931E_ILLEGAL_MESSAGE", /* -3010 */
"Q931E_TOMANYCALLS", /* -3011 */
"Q931E_INVALID_CRV", /* -3012 */
"Q931E_CALLID", /* -3013 */
"Q931E_CALLSTATE", /* -3014 */
"Q931E_CALLEDSUB", /* -3015 */
"Q931E_CALLEDNUM", /* -3016 */
"Q931E_CALLINGNUM", /* -3017 */
"Q931E_CALLINGSUB", /* -3018 */
"Q931E_CAUSE", /* -3019 */
"Q931E_CHANID", /* -3020 */
"Q931E_DATETIME", /* -3021 */
"Q931E_DISPLAY", /* -3022 */
"Q931E_KEYPADFAC", /* -3023 */
"Q931E_NETFAC", /* -3024 */
"Q931E_NOTIFIND", /* -3025 */
"Q931E_PROGIND", /* -3026 */
"Q931E_RESTARTIND", /* -3027 */
"Q931E_SEGMENT", /* -3028 */
"Q931E_SIGNAL", /* -3029 */
"Q931E_GENERIC_DIGITS" /* -3030 */
};
@ -723,13 +733,14 @@ static const char *q931_error_names[] = {
const char *q931_error_to_name(q931_error_t error)
{
int index = 0;
if ((int)error < 0) {
index = (((int)error * -1) -3000);
}
if (index < 0 || index > Q931_MAX_ERROR) {
return "";
}
return q931_error_names[index];
int index = 0;
if ((int)error < 0) {
index = (((int)error * -1) -3000);
}
if (index < 0 || index > Q931_MAX_ERROR) {
return "";
}
return q931_error_names[index];
}

View File

@ -578,4 +578,4 @@ L3INT Q931AckService(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf)
}
Q931_ENUM_NAMES(DIALECT_TYPE_NAMES, DIALECT_STRINGS)
Q931_STR2ENUM(q931_str2Q931Diaelct_type, q931_Q931Diaelct_type2str, Q931Dialect_t, DIALECT_TYPE_NAMES, Q931_Dialect_Count)
Q931_STR2ENUM(q931_str2Q931Dialect_type, q931_Q931Dialect_type2str, Q931Dialect_t, DIALECT_TYPE_NAMES, Q931_Dialect_Count)

View File

@ -0,0 +1,103 @@
/******************************************************************************
FileName: 5ESS.h
Contents: Header and definition for the AT&T 5ESS ISDN dialect. The
header contains the following parts:
- Definition of codes
- Definition of information elements (5ESSie_).
- Definition of messages (5ESSmes_).
- Function prototypes.
Description: The AT&T 5ESS ISDN dialect here covers ????
Related Files: 5ESS.h AT&T 5ESS ISDN Definitions
5ESSie.c AT&T 5ESS ISDN IE encoders/coders (not extant yet)
See Q931ie.c for IE encoders/coders
5ESSStateTE.c AT&T 5ESS ISDN TE State Engine
5ESSStateNT.c AT&T 5ESS ISDN NT State Engine
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
Copyright (c) 2007, Michael S. Collins, All rights reserved.
email:mcollins@fcnetwork.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.
******************************************************************************/
#ifndef _5ESS_NL
#define _5ESS_NL
#include "Q931.h"
/*****************************************************************************
Q.931 Message codes
Only 5ESS specific message and ie types
here the rest are inherited from Q931.h
*****************************************************************************/
/*****************************************************************************
Q.931 Message Pack/Unpack functions. Implemented in 5ESSmes.c
Note: Because C variables may not begin with numeric digit, all identifiers
are prefixed with "ATT5ESS" instead of a bare "5ESS"
*****************************************************************************/
L3INT ATT5ESSUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size);
L3INT ATT5ESSPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize);
L3INT ATT5ESSUmes_SetupAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size);
L3INT ATT5ESSPmes_SetupAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize);
L3INT ATT5ESSUmes_0x07(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size);
L3INT ATT5ESSPmes_0x07(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize);
L3INT ATT5ESSUmes_0x0f(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size);
L3INT ATT5ESSPmes_0x0f(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize);
/*****************************************************************************
Q.931 Process Function Prototyping. Implemented in 5ESSStateTE.c
*****************************************************************************/
L3INT ATT5ESSProc0x0fTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom);
L3INT ATT5ESSProc0x07TE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom);
void ATT5ESSCreateTE(L3UCHAR i);
void ATT5ESSCreateNT(L3UCHAR i);
#endif /* _5ESS_NL */

View File

@ -3,75 +3,75 @@
FileName: Q931.h
Contents: Header and definition for the ITU-T Q.931 stack. The
header contents the following parts:
header contents the following parts:
- Definition of codes
- Definition of codes
- Definition of information elements (Q931ie_).
- Definition of messages (Q931mes_).
- Definitian of variables (var_).
- Function prototypes.
- Function prototypes.
Description: The Q.931 stack provided here covers ITU-T Q.931 w/Q.932
supplementary services for both PRI, BRI and variants.
The stack is generic and designed to deal with variants as
needed.
supplementary services for both PRI, BRI and variants.
The stack is generic and designed to deal with variants as
needed.
The stack uses the following interface functions:
The stack uses the following interface functions:
- Q931Initialize Initialize the Q.931 stack.
- Q931Rx23 Receive a message from layer 2
- Q931Tx32 Send a message to layer 2
- Q931Rx43 Receive a message from layer 4 or above.
- Q931Tx34 Send a message to layer 4 or above.
- Q931TimeTick Periodical timer processing.
- Q931ErrorProc Callback for stack error message.
- Q931Initialize Initialize the Q.931 stack.
- Q931Rx23 Receive a message from layer 2
- Q931Tx32 Send a message to layer 2
- Q931Rx43 Receive a message from layer 4 or above.
- Q931Tx34 Send a message to layer 4 or above.
- Q931TimeTick Periodical timer processing.
- Q931ErrorProc Callback for stack error message.
The protocol is a module with no external dependencies and
can easely be ported to any operating system like Windows,
Linux, rtos and others.
The protocol is a module with no external dependencies and
can easely be ported to any operating system like Windows,
Linux, rtos and others.
Related Files: Q931.h Q.931 Definitions
Q931.c Q.931 Interface Functions.
Q931api.c Low level L4 API functions.
Q931.c Q.931 Interface Functions.
Q931api.c Low level L4 API functions.
Q932.h Q.932 Suplementary Services
Q932mes.c Q.932 encoders/coders
Q932.h Q.932 Suplementary Services
Q932mes.c Q.932 encoders/coders
Q931mes.c Q.931 Message encoders/coders
Q931ie.c Q.931 IE encoders/coders
Q931StateTE.c Generic Q.931 TE State Engine
Q931StateNT.c Generic Q.931 NT State Engine
Q931mes.c Q.931 Message encoders/coders
Q931ie.c Q.931 IE encoders/coders
Q931StateTE.c Generic Q.931 TE State Engine
Q931StateNT.c Generic Q.931 NT State Engine
Design Note 1: For each variant please add separate files starting with
the variant short-name as follows:
the variant short-name as follows:
<variant>.h Spesific headers needed.
<variant>mes.c Message encoders/decores.
<variant>ie.c IE encoders/decoders.
<variant>StateTE.c TE side state engine.
<variant>StateNT.c NT side state engine.
<variant>.h Spesific headers needed.
<variant>mes.c Message encoders/decores.
<variant>ie.c IE encoders/decoders.
<variant>StateTE.c TE side state engine.
<variant>StateNT.c NT side state engine.
Design Note 2: The stack is deliberatly made non-threading. Use 1
thread per Trunk, but lock access from the timertick
and rx, tx functions. And make sure the callbacks only
dump messages to a queue, no time-consuming processing
inside stack processing.
thread per Trunk, but lock access from the timertick
and rx, tx functions. And make sure the callbacks only
dump messages to a queue, no time-consuming processing
inside stack processing.
All stack processing is async 'fire and forget', meaning
that there are not, and should not be any time-consuming
processing within the stack-time. The best way to thread
a stack is to use one single thread that signal 5 queues.
- Incoming L2 queue.
- Incoming L4 queue.
- Outgoing L2 queue.
- Outgoing L4 queue.
- Error/Trace queue.
All stack processing is async 'fire and forget', meaning
that there are not, and should not be any time-consuming
processing within the stack-time. The best way to thread
a stack is to use one single thread that signal 5 queues.
- Incoming L2 queue.
- Incoming L4 queue.
- Outgoing L2 queue.
- Outgoing L4 queue.
- Error/Trace queue.
Design Note 3: DSP optimization. The L3 (Rx23) can be called directly
from a hdlc receiver without usage of queues for optimized
processing. But keep in mind that Q.931 calls Tx34 or Tx32
as part of receiving a message from Layer 2.
from a HDLC receiver without usage of queues for optimized
processing. But keep in mind that Q.931 calls Tx34 or Tx32
as part of receiving a message from Layer 2.
License/Copyright:
@ -123,7 +123,7 @@
/*****************************************************************************
Enum helper macros
Enum helper macros <Need description of these macros>
*****************************************************************************/
#define Q931_ENUM_NAMES(_NAME, _STRINGS) static char * _NAME [] = { _STRINGS , NULL };
@ -200,11 +200,11 @@ const char *q931_error_to_name(q931_error_t error);
/*****************************************************************************
Some speed optimization can be achieved by changing all variables to the
word size of your processor. A 32 bit processor have to do a lot of extra
word size of your processor. A 32 bit processor has to do a lot of extra
work to read a packed 8 bit integer. Changing all fields to 32 bit integer
will ressult in usage of some extra space, but speed up the stack.
will result in usage of some extra space, but will speed up the stack.
The stack have been designed to allow L3UCHAR etc. to be any size of 8 bit
The stack has been designed to allow L3UCHAR etc. to be any size of 8 bit
or larger.
*****************************************************************************/
@ -233,7 +233,7 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
/* value for single octet ) to the */
/* struct holding the ie. Offset = 0 */
/* is buf[1] etc. */
/* ie == 0xffff indicate error */
/* ie == 0xffff indicates error */
/*****************************************************************************
@ -268,8 +268,8 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
changed when a new dialect needs to be inserted into the stack.
This stack uses an array of functions to know which function to call as
it receives a SETUP message etc. A new dialect can when schoose to use
the proc etc for standard Q.931 or insert a modified proc.
it receives a SETUP message etc. A new dialect can when choose to use
the proc etc. for standard Q.931 or insert a modified proc.
This technique has also been used to distinguish between user and network
mode to make the code as easy to read and maintainable as possible.
@ -283,7 +283,7 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
/* WARNING! Initialize Q931CreateDialectCB[] will NULL when increasing the */
/* Q931MAXDLCT value to avoid Q931Initialize from crashing if one entry is */
/* not used. */
#define Q931MAXDLCT 6 /* Max dialects included in this */
#define Q931MAXDLCT 8 /* Max dialects included in this */
/* compile. User and Network count as */
/* one dialect each. */
@ -294,9 +294,9 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
#define Q931MAXUSEDIE 50 /* Maximum number of ie types per Dialect */
#define Q931MAXCODESETS 7 /* Maximum number of codests (by spec, 0-7 */
#define Q931MAXCODESETS 7 /* Maximum number of codests (by spec, 0-7) */
#define Q931MAXSTATE 100 /* Size of state tables */
#define Q931MAXSTATE 100 /* Size of state tables */
/*****************************************************************************
@ -336,14 +336,14 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
#define Q931_N7 (0x0100 | 7)
#define Q931_N8 (0x0100 | 8)
#define Q931_N9 (0x0100 | 9)
#define Q931_N10 (0x0100 | 11)
#define Q931_N11 (0x0100 | 11)
#define Q931_N12 (0x0100 | 12)
#define Q931_N15 (0x0100 | 15)
#define Q931_N17 (0x0100 | 17)
#define Q931_N19 (0x0100 | 19)
#define Q931_N22 (0x0100 | 22)
#define Q931_N25 (0x0100 | 25)
#define Q931_N10 (0x0100 | 11)
#define Q931_N11 (0x0100 | 11)
#define Q931_N12 (0x0100 | 12)
#define Q931_N15 (0x0100 | 15)
#define Q931_N17 (0x0100 | 17)
#define Q931_N19 (0x0100 | 19)
#define Q931_N22 (0x0100 | 22)
#define Q931_N25 (0x0100 | 25)
/*****************************************************************************
@ -469,12 +469,12 @@ typedef struct
Struct: Q931_TrunkInfo
Description: TrunkInfo is the struct entry used to store Q.931 related
information and state for E1/T1/J1 trunks and assosiated
information and state for E1/T1/J1 trunks and associated
channels in the system.
The user should store this information outside this stack
and need to feed the interface functions with a pointer to
the trunk Info entry.
and needs to feed the interface functions with a pointer to
the TrunkInfo entry.
*****************************************************************************/
typedef struct Q931_TrunkInfo Q931_TrunkInfo_t;
@ -490,14 +490,15 @@ typedef enum /* Network/User Mode. */
typedef enum /* Dialect enum */
{
Q931_Dialect_Q931 = 0,
Q931_Dialect_Q931 = 0,
Q931_Dialect_National = 2,
Q931_Dialect_DMS = 4,
Q931_Dialect_DMS = 4,
Q931_Dialect_5ESS = 6, /* Coming soon to a PRI stack near you! */
Q931_Dialect_Count
} Q931Dialect_t;
#define DIALECT_STRINGS "q931", "", "national", "", "dms"
Q931_STR2ENUM_P(q931_str2Q931Diaelct_type, q931_Q931Diaelct_type2str, Q931Dialect_t)
#define DIALECT_STRINGS "q931", "", "national", "", "dms","","5ess",""
Q931_STR2ENUM_P(q931_str2Q931Dialect_type, q931_Q931Dialect_type2str, Q931Dialect_t)
typedef enum /* Trunk Line Type. */
{
@ -516,7 +517,7 @@ typedef enum /* Trunk State */
typedef enum {
Q931_ChType_NotUsed=0, /* Unused Channel */
Q931_ChType_B=1, /* B Channel (Voice) */
Q931_ChType_B=1, /* B Channel (Voice) */
Q931_ChType_D=2, /* D Channel (Signalling) */
Q931_ChType_Sync=3 /* Sync Channel */
} Q931_ChanType_t;
@ -525,7 +526,7 @@ struct Q931_TrunkInfo
{
Q931NetUser_t NetUser; /* Network/User Mode. */
Q931Dialect_t Dialect; /* Q.931 Based dielact index. */
Q931Dialect_t Dialect; /* Q.931 Based dialect index. */
Q931_TrunkType_t TrunkType; /* Trunk Line Type. */
@ -549,7 +550,7 @@ struct Q931_TrunkInfo
L3UCHAR L2Buf[Q931L2BUF]; /* buffer for messages send to L2. */
/* The auto flags below switch on/off automatic Ack messages. SETUP ACK */
/* as an example can be send by the stack in response to SETUP to buy */
/* as an example can be sent by the stack in response to SETUP to buy */
/* time in processing on L4. Setting this to true will cause the stack */
/* to automatically send this. */
@ -618,8 +619,8 @@ struct Q931_TrunkInfo
Description: Define a Q931 State, legal events and next state for each
event. Used to simplify the state engine logic. Each state
engine define it's own state table and the logic only need
to call a helper function to check if the message is legal
engine defines its own state table and the logic need only
call a helper function to check if the message is legal
at this stage.
*****************************************************************************/