Add initial Basic Rate Interface (BRI) support...

Short summary of changes:
    (Massive) rework of the Q.921 layer
    Q.931 changes to get BRI PTMP working and cleanups (more to come...)
    Add Hi-Layer compat and Progress IE to outgoing SETUP messages
    Improve handling of call tear-down in zap_isdn.c
    Open ZAP I/O channels after processing the dialplan for incoming calls
    Bearer Capability and Channel ID IE handling improved for BRI/PRI and A-law/u-law

    ...and a lot of other small changes



git-svn-id: http://svn.openzap.org/svn/openzap/trunk@512 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
Stefan Knoblich committed 2008-08-22 16:55:01 +00:00
1 parent 9e4558ab13
commit ff19726bd0
25 files changed
+5148 -1059

No files matched your search

+117 -52
View File
@@ -31,7 +31,7 @@
NOTE: The following are not yet implemented
OnQ921Error Function called every if an error is
deteceted.
detected.
OnQ921Log Function called if logging is active.
@@ -76,84 +76,149 @@
*****************************************************************************/
/****************************************************************************
* Changes:
*
* - June,July 2008: Stefan Knoblich <s.knoblich@axsentis.de>:
* Add PTMP TEI management
* Add timers
* Add retransmit counters
* Add logging
* Various cleanups
*
****************************************************************************/
#ifndef _Q921
#define _Q921
#define Q921MAXHDLCSPACE 3000
#define L2UCHAR unsigned char /* Min 8 bit */
#define L2INT int /* Min 16 bit signed */
#define L2ULONG unsigned long /* Min 32 bit */
#define L2UCHAR unsigned char /* Min 8 bit */
#define L2USHORT unsigned short /* 16 bit */
#define L2INT int /* Min 16 bit signed */
#define L2ULONG unsigned long /* Min 32 bit */
#define L2TRUNK Q921Data_t *
typedef enum /* Network/User Mode. */
#define Q921_TEI_BCAST 127
#define Q921_TEI_MAX Q921_TEI_BCAST
#define Q921_TEI_DYN_MIN 64
#define Q921_TEI_DYN_MAX 126
typedef enum /* Network/User Mode */
{
Q921_TE=0, /* 0 : User Mode */
Q921_NT=1 /* 1 : Network Mode */
Q921_TE=0, /* 0 : User Mode */
Q921_NT=1 /* 1 : Network Mode */
} Q921NetUser_t;
typedef struct Q921Data Q921Data_t;
typedef int (*Q921TxCB_t) (void *, L2UCHAR *, L2INT);
typedef enum /* Type of connection */
{
Q921_PTP=0, /* 0 : Point-To-Point */
Q921_PTMP=1 /* 1 : Point-To-Multipoint */
} Q921NetType_t;
#define INITIALIZED_MAGIC 42
struct Q921Data
typedef enum
{
Q921_LOG_NONE = 0,
Q921_LOG_ERROR,
Q921_LOG_WARNING,
Q921_LOG_NOTICE,
Q921_LOG_INFO,
Q921_LOG_DEBUG
} Q921LogLevel_t;
/*
* Messages for L2 <-> L3 communication
*/
typedef enum {
Q921_DL_ESTABLISH = 0,
Q921_DL_ESTABLISH_CONFIRM,
Q921_DL_RELEASE,
Q921_DL_RELEASE_CONFIRM,
Q921_DL_DATA,
Q921_DL_UNIT_DATA
} Q921DLMsg_t;
typedef int (*Q921Tx21CB_t) (void *, L2UCHAR *, L2INT);
typedef int (*Q921Tx23CB_t) (void *, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *, L2INT);
typedef int (*Q921LogCB_t) (void *, Q921LogLevel_t, char *, L2INT);
struct Q921_Link;
typedef struct Q921Data
{
L2UCHAR HDLCInQueue[Q921MAXHDLCSPACE];
L2INT initialized;
L2UCHAR va;
L2UCHAR vs;
L2UCHAR vr;
L2INT state;
L2UCHAR sapi;
L2UCHAR tei;
L2UCHAR sapi; /*!< User assigned SAPI */
L2UCHAR tei; /*!< User assigned TEI value */
L2INT Q921HeaderSpace;
Q921NetUser_t NetUser;
L2ULONG T200;
L2ULONG T203;
Q921NetType_t NetType;
struct Q921_Link *context; /*!< per-TEI / link context space */
/* timers */
L2ULONG T202; /*!< PTMP TE mode TEI retransmit timer */
L2ULONG T200Timeout;
L2ULONG T201Timeout;
L2ULONG T202Timeout;
L2ULONG T203Timeout;
Q921TxCB_t Q921Tx21Proc;
Q921TxCB_t Q921Tx23Proc;
L2ULONG TM01Timeout;
/* counters */
L2ULONG N200Limit; /*!< max retransmit */
L2ULONG N202; /*!< PTMP TE mode retransmit counter */
L2ULONG N202Limit; /*!< PTMP TE mode max retransmit */
L2ULONG N201Limit; /*!< max number of octets */
L2ULONG k; /*!< max number of unacknowledged I frames */
/* callbacks and callback data pointers */
Q921Tx21CB_t Q921Tx21Proc;
Q921Tx23CB_t Q921Tx23Proc;
void *PrivateData21;
void *PrivateData23;
L2INT Q921HeaderSpace;
};
/* logging */
Q921LogLevel_t loglevel; /*!< trunk loglevel */
Q921LogCB_t Q921LogProc; /*!< log callback procedure */
void *PrivateDataLog; /*!< private data pointer for log proc */
void Q921_InitTrunk(L2TRUNK trunk,
/* tei mgmt */
L2UCHAR tei_map[Q921_TEI_MAX]; /*!< */
L2UCHAR HDLCInQueue[Q921MAXHDLCSPACE]; /*!< HDLC input queue */
} Q921Data_t;
/*
* Public functions
*/
int Q921_InitTrunk(L2TRUNK trunk,
L2UCHAR sapi,
L2UCHAR tei,
Q921NetUser_t NetUser,
Q921NetType_t NetType,
L2INT hsize,
Q921TxCB_t cb21,
Q921TxCB_t cb23,
Q921Tx21CB_t cb21,
Q921Tx23CB_t cb23,
void *priv21,
void *priv23);
int Q921QueueHDLCFrame(L2TRUNK trunk, L2UCHAR *b, L2INT size);
int Q921Rx12(L2TRUNK trunk);
int Q921Rx32(L2TRUNK trunk, L2UCHAR * Mes, L2INT Size);
int Q921Start(L2TRUNK trunk);
int Q921Stop(L2TRUNK trunk);
void Q921SetLogCB(L2TRUNK trunk, Q921LogCB_t func, void *priv);
void Q921SetLogLevel(L2TRUNK trunk, Q921LogLevel_t level);
int Q921Rx12(L2TRUNK trunk);
int Q921Rx32(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR * Mes, L2INT Size);
int Q921QueueHDLCFrame(L2TRUNK trunk, L2UCHAR *b, L2INT size);
void Q921SetGetTimeCB(L2ULONG (*callback)(void));
void Q921TimerTick(L2TRUNK trunk);
int Q921Tx21Proc(L2TRUNK trunk, L2UCHAR *Msg, L2INT size);
int Q921Tx23Proc(L2TRUNK trunk, L2UCHAR *Msg, L2INT size);
extern L2ULONG tLast;
L2ULONG Q921GetTime(void);
void Q921T200TimerStart(L2TRUNK trunk);
void Q921T200TimerStop(L2TRUNK trunk);
void Q921T200TimerReset(L2TRUNK trunk);
void Q921T203TimerStart(L2TRUNK trunk);
void Q921T203TimerStop(L2TRUNK trunk);
void Q921T203TimerReset(L2TRUNK trunk);
void Q921T200TimerExpire(L2TRUNK trunk);
void Q921T203TimerExpire(L2TRUNK trunk);
int Q921SendI(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR *mes, L2INT size);
int Q921SendRNR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendREJ(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendSABME(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendDM(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendDISC(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendUA(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921ProcSABME(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
#endif
+298
View File
@@ -0,0 +1,298 @@
/*****************************************************************************
FileName: Q921priv.h
Description: Private declarations
Created: 08.Aug.2008/STKN
License/Copyright:
Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
email:janvb@caselaboratories.com
Copyright (c) 2008, Stefan Knoblich, axsentis GmbH. All rights reserved.
email:s.knoblich@axsentis.de
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 _Q921_PRIV_H_
#define _Q921_PRIV_H_
typedef enum /* Q.921 States */
{
Q921_STATE_STOPPED = 0, /* Trunk stopped */
Q921_STATE_TEI_UNASSIGNED = 1, /* TEI unassigned */
Q921_STATE_TEI_AWAITING, /* Assign awaiting TEI */
Q921_STATE_TEI_ESTABLISH, /* Establish awaiting TEI */
Q921_STATE_TEI_ASSIGNED, /* TEI assigned */
Q921_STATE_AWAITING_ESTABLISHMENT, /* Awaiting establishment */
Q921_STATE_AWAITING_RELEASE, /* Awaiting release */
Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, /* Multiple frame established */
Q921_STATE_TIMER_RECOVERY /* Timer recovery */
} Q921State_t;
/*
* Flags
*/
enum Q921_Flags {
Q921_FLAG_L3_INITIATED = (1 << 0),
Q921_FLAG_UI_FRAME_QUEUED = (1 << 1),
Q921_FLAG_I_FRAME_QUEUED = (1 << 2),
Q921_FLAG_ACK_PENDING = (1 << 3),
Q921_FLAG_REJECT = (1 << 4),
Q921_FLAG_RECV_BUSY = (1 << 5),
Q921_FLAG_PEER_RECV_BUSY = (1 << 6)
};
#define Q921_SET_FLAG(x, f) ((x)->flags |= f)
#define Q921_CHECK_FLAG(x, f) ((x)->flags & f)
#define Q921_CLEAR_FLAG(x, f) ((x)->flags &= ~f)
/*
* dynamic TEI handling
*/
#define Q921_SAPI_TEI 63 /* SAPI for all TEI Messages */
#define Q921_LAYER_ENT_ID_TEI 0x0f /* UN Layer Management Entity ID for TEI Mgmt */
#define Q921_LAYER_ENT_ID_Q931 0x08 /* Q.931 Layer Management Entity ID */
typedef enum {
Q921_TEI_ID_REQUEST = 1,
Q921_TEI_ID_ASSIGNED,
Q921_TEI_ID_DENIED,
Q921_TEI_ID_CHECKREQ,
Q921_TEI_ID_CHECKRESP,
Q921_TEI_ID_REMOVE,
Q921_TEI_ID_VERIFY
} Q921TeiMessageType_t;
/**
* Per-Datalink context
*/
struct Q921_Link {
L2UCHAR tei; /*!< This endpoint's TEI */
L2UCHAR va;
L2UCHAR vs;
L2UCHAR vr;
L2INT flags;
Q921State_t state;
L2ULONG N202; /*!< PTMP TE mode retransmit counter */
L2ULONG N200; /*!< retransmit counter (per-TEI in PTMP NT mode) */
L2ULONG TM01; /*!< Datalink inactivity disconnect timer */
L2ULONG T200;
L2ULONG T201; /*!< PTMP NT mode timer */
L2ULONG T203;
L2USHORT ri; /*!< random id for TEI request mgmt */
/* I + UI Frame queue */
L2UCHAR UIFrameQueue[Q921MAXHDLCSPACE];
L2UCHAR IFrameQueue[Q921MAXHDLCSPACE];
L2UCHAR IFrameResendQueue[Q921MAXHDLCSPACE];
};
#define Q921_LINK_CONTEXT(tr, tei) \
(Q921_IS_PTMP_NT(tr) && tei != Q921_TEI_BCAST) ? ((struct Q921_Link *)&(tr)->context[tei]) : (tr)->context
#define Q921_TRUNK_CONTEXT(tr) \
(tr)->context
#define Q921_LOGBUFSIZE 2000
#define INITIALIZED_MAGIC 42
/*
* Helper macros
*/
#define Q921_INC_COUNTER(x) (x = (x + 1) % 128)
#define Q921_DEC_COUNTER(x) (x = (x) ? (x - 1) : 127)
#define Q921_UFRAME_HEADER_SIZE 3
#define Q921_UFRAME_DATA_OFFSET(tr) ((tr)->Q921HeaderSpace + Q921_UFRAME_HEADER_SIZE)
#define Q921_SFRAME_HEADER_SIZE 4
#define Q921_SFRAME_DATA_OFFSET(tr) ((tr)->Q921HeaderSpace + Q921_SFRAME_HEADER_SIZE)
#define Q921_IFRAME_HEADER_SIZE 4
#define Q921_IFRAME_DATA_OFFSET(tr) ((tr)->Q921HeaderSpace + Q921_IFRAME_HEADER_SIZE)
#define Q921_IS_TE(x) ((x)->NetUser == Q921_TE)
#define Q921_IS_NT(x) ((x)->NetUser == Q921_NT)
#define Q921_IS_STOPPED(tr) ((tr)->state == Q921_STATE_STOPPED)
/* TODO: rework this one */
#define Q921_IS_READY(tr) ((tr)->state >= Q921_STATE_TEI_ASSIGNED)
#define Q921_IS_PTMP(x) ((x)->NetType == Q921_PTMP)
#define Q921_IS_PTMP_TE(x) ((x)->NetType == Q921_PTMP && (x)->NetUser == Q921_TE)
#define Q921_IS_PTMP_NT(x) ((x)->NetType == Q921_PTMP && (x)->NetUser == Q921_NT)
#define Q921_IS_PTP(x) ((x)->NetType == Q921_PTP)
#define Q921_IS_PTP_TE(x) ((x)->NetType == Q921_PTP && (x)->NetUser == Q921_TE)
#define Q921_IS_PTP_NT(x) ((x)->NetType == Q921_PTP && (x)->NetUser == Q921_NT)
/* Make life a little easier */
#define Q921_COMMAND(x) ((x)->NetUser == Q921_TE ? 0 : 1)
#define Q921_RESPONSE(x) ((x)->NetUser == Q921_TE ? 1 : 0)
#define Q921_IS_COMMAND(tr, x) ((x) == (Q921_IS_TE(tr) ? 1 : 0))
#define Q921_IS_RESPONSE(tr, x) ((x) == (Q921_IS_TE(tr) ? 0 : 1))
/*******************************************************************************
* Private functions
*******************************************************************************/
/*
* L1 / L2 Interface
*/
static int Q921Tx21Proc(L2TRUNK trunk, L2UCHAR *Msg, L2INT size);
static int Q921Tx23Proc(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *Msg, L2INT size);
/*
* Timers
*/
static L2ULONG Q921GetTime(void);
static void Q921T200TimerStart(L2TRUNK trunk, L2UCHAR tei);
static void Q921T200TimerStop(L2TRUNK trunk, L2UCHAR tei);
static void Q921T200TimerReset(L2TRUNK trunk, L2UCHAR tei);
static void Q921T200TimerExpire(L2TRUNK trunk, L2UCHAR tei);
static void Q921T201TimerStart(L2TRUNK trunk, L2UCHAR tei);
static void Q921T201TimerStop(L2TRUNK trunk, L2UCHAR tei);
/* static void Q921T201TimerReset(L2TRUNK trunk, L2UCHAR tei); - Unused for now */
static void Q921T201TimerExpire(L2TRUNK trunk, L2UCHAR tei);
static void Q921T202TimerStart(L2TRUNK trunk);
static void Q921T202TimerStop(L2TRUNK trunk);
static void Q921T202TimerReset(L2TRUNK trunk);
static void Q921T202TimerExpire(L2TRUNK trunk);
static void Q921T203TimerStart(L2TRUNK trunk, L2UCHAR tei);
static void Q921T203TimerStop(L2TRUNK trunk, L2UCHAR tei);
static void Q921T203TimerReset(L2TRUNK trunk, L2UCHAR tei);
static void Q921T203TimerExpire(L2TRUNK trunk, L2UCHAR tei);
static void Q921TM01TimerStart(L2TRUNK trunk, L2UCHAR tei);
/* static void Q921TM01TimerStop(L2TRUNK trunk, L2UCHAR tei); - Unused for now */
static void Q921TM01TimerReset(L2TRUNK trunk, L2UCHAR tei);
/* static void Q921TM01TimerExpire(L2TRUNK trunk, L2UCHAR tei); - Unused for now */
/*
* Frame encoding
*/
static int Q921SendS(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR sv, L2UCHAR *mes, L2INT size);
static int Q921SendU(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR m, L2UCHAR *mes, L2INT size);
static int Q921SendRNR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendREJ(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendSABME(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendDM(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendDISC(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendUA(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendUN(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf, L2UCHAR *mes, L2INT size);
static int Q921SendRR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
/*
* Frame decoding
*/
static int Q921ProcIFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcSFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcUFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcSABME(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcDM(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcUA(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcDISC(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcRR(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcRNR(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcREJ(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
/*
* (Common) procedures defined in the Q.921 SDL
*/
static int Q921SendEnquiry(L2TRUNK trunk, L2UCHAR tei);
static int Q921SendEnquiryResponse(L2TRUNK trunk, L2UCHAR tei);
static void Q921ResetExceptionConditions(L2TRUNK trunk, L2UCHAR tei);
static int Q921EstablishDataLink(L2TRUNK trunk, L2UCHAR tei);
static int Q921NrErrorRecovery(L2TRUNK trunk, L2UCHAR tei);
static int Q921InvokeRetransmission(L2TRUNK trunk, L2UCHAR tei, L2UCHAR nr);
static int Q921AcknowledgePending(L2TRUNK trunk, L2UCHAR tei);
/*
static int Q921SetReceiverBusy(L2TRUNK trunk);
static int Q921ClearReceiverBusy(L2TRUNK trunk);
*/
/*
* Queueing
*/
static int Q921SendQueuedIFrame(L2TRUNK trunk, L2UCHAR tei);
static int Q921EnqueueI(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR *mes, L2INT size);
/*
* TEI management
*/
static int Q921TeiSendAssignRequest(L2TRUNK trunk);
static int Q921TeiProcAssignResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiSendVerifyRequest(L2TRUNK trunk);
static int Q921TeiProcCheckRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiProcRemoveRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiProcAssignRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiProcCheckResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiProcVerifyRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiSendRemoveRequest(L2TRUNK trunk, L2UCHAR tei);
static int Q921TeiSendDenyResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri);
static int Q921TeiSendAssignedResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri);
static int Q921TeiSendCheckRequest(L2TRUNK trunk, L2UCHAR tei);
/*
* Logging
*/
static int Q921Log(L2TRUNK trunk, Q921LogLevel_t level, const char *fmt, ...);
static int Q921LogMesg(L2TRUNK trunk, Q921LogLevel_t level, L2UCHAR received, L2UCHAR *mes, L2INT size, const char *fmt, ...);
/*
* State handling
*/
static int Q921ChangeState(L2TRUNK trunk, Q921State_t state, L2UCHAR tei);
#endif
+273 -88
View File
@@ -244,23 +244,35 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
*****************************************************************************/
#define Q931L4BUF 1000 /* size of message buffer */
#define Q931_LOGBUFSIZE 1024 /* size of logging buffer */
#define Q931L2BUF 300 /* size of message buffer */
#define Q931L4BUF 1000 /* size of message buffer */
#define Q931MAXTRUNKS 4 /* Total number of trunks that will be */
/* processed by this instance of the */
/* stack */
#define Q931L2BUF 300 /* size of message buffer */
#define Q931MAXCHPERTRUNK 32 /* Number of channels per trunk. The */
/* stack uses a static set of 32 */
/* channels regardless if it is E1, T1 */
/* or BRI that actually is used. */
#define Q931MAXTRUNKS 4 /* Total number of trunks that will be */
/* processed by this instance of the */
/* stack */
#define Q931MAXCALLPERTRUNK (Q931MAXCHPERTRUNK * 2)
/* Number of max active CRV per trunk. */
/* Q.931 can have more calls than there */
/* are channels. */
#define Q931MAXCHPERTRUNK 32 /* Number of channels per trunk. The */
/* stack uses a static set of 32 */
/* channels regardless if it is E1, T1 */
/* or BRI that actually is used. */
#define Q931MAXCALLPERTRUNK (Q931MAXCHPERTRUNK * 2)
/* Number of max active CRV per trunk. */
/* Q.931 can have more calls than there */
/* are channels. */
#define Q931_IS_BRI(x) ((x)->TrunkType == Q931_TrType_BRI || (x)->TrunkType == Q931_TrType_BRI_PTMP)
#define Q931_IS_PRI(x) (!Q931_IS_BRI(x))
#define Q931_IS_PTP(x) ((x)->TrunkType != Q931_TrType_BRI_PTMP)
#define Q931_IS_PTMP(X) ((x)->TrunkType == Q931_TrType_BRI_PTMP)
#define Q931_BRI_MAX_CRV 127
#define Q931_PRI_MAX_CRV 32767
/*****************************************************************************
@@ -280,24 +292,19 @@ 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 8 /* Max dialects included in this */
/* compile. User and Network count as */
/* one dialect each. */
#define Q931MAXMES 128 /* Number of messages */
#define Q931MAXIE 255 /* Number of IE */
#define Q931MAXUSEDIE 50 /* Maximum number of ie types per Dialect */
#define Q931MAXCODESETS 7 /* Maximum number of codests (by spec, 0-7) */
#define Q931MAXSTATE 100 /* Size of state tables */
/* WARNING! Initialize Q931CreateDialectCB[] will NULL when increasing the */
/* Q931MAXDLCT value to avoid Q931Initialize from crashing if one entry is */
/* not used. */
#define Q931MAXDLCT 8 /* Max dialects included in this */
/* compile. User and Network count as */
/* one dialect each. */
#define Q931MAXMES 128 /* Number of messages */
#define Q931MAXIE 255 /* Number of IE */
#define Q931MAXUSEDIE 50 /* Maximum number of ie types per Dialect */
#define Q931MAXCODESETS 7 /* Maximum number of codests (by spec, 0-7) */
#define Q931MAXSTATE 100 /* Size of state tables */
#define Q931MAXTIMER 25 /* Maximum number of timers */
/*****************************************************************************
@@ -381,6 +388,155 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
#define Q931mes_SERVICE_ACKNOWLEDGE 0x07 /* 0000 0111 */
/**
* Generic Q.931 Timers
*/
enum {
Q931_TIMER_T300 = 1, /* */
Q931_TIMER_T301,
Q931_TIMER_T302,
Q931_TIMER_T303,
Q931_TIMER_T304,
Q931_TIMER_T305,
Q931_TIMER_T306,
Q931_TIMER_T307,
Q931_TIMER_T308,
Q931_TIMER_T309,
Q931_TIMER_T310,
Q931_TIMER_T311,
Q931_TIMER_T312,
Q931_TIMER_T313,
Q931_TIMER_T314,
Q931_TIMER_T315,
Q931_TIMER_T316,
Q931_TIMER_T317,
Q931_TIMER_T318,
Q931_TIMER_T319,
Q931_TIMER_T320,
Q931_TIMER_T321,
Q931_TIMER_T322,
};
/**
* Q.931 ToN
*/
enum {
Q931_TON_UNKNOWN = 0x00,
Q931_TON_INTERNATIONAL = 0x01,
Q931_TON_NATIONAL = 0x02,
Q931_TON_NETWORK_SPECIFIC = 0x03,
Q931_TON_SUBSCRIBER_NUMBER = 0x04,
Q931_TON_ABBREVIATED_NUMBER = 0x06,
Q931_TON_RESERVED = 0x07
};
/**
* Q.931 Numbering Plan
*/
enum {
Q931_NUMPLAN_UNKNOWN = 0x00,
Q931_NUMPLAN_E164 = 0x01,
Q931_NUMPLAN_X121 = 0x03,
Q931_NUMPLAN_F69 = 0x04,
Q931_NUMPLAN_NATIONAL = 0x08,
Q931_NUMPLAN_PRIVATE = 0x09,
Q931_NUMPLAN_RESERVED = 0x0e
};
/**
* Q.931 Presentation Indicator
*/
enum {
Q931_PRES_ALLOWED = 0x00,
Q931_PRES_RESTRICTED = 0x01,
Q931_PRES_NOT_AVAILABLE = 0x02,
Q931_PRES_RESERVED = 0x03
};
/**
* Q.931 Screening Indicator
*/
enum {
Q931_SCREEN_USER_NOT_SCREENED = 0x00,
Q931_SCREEN_USER_VERIFIED_PASSED = 0x01,
Q931_SCREEN_USER_VERIFIED_FAILED = 0x02,
Q931_SCREEN_NETWORK = 0x03
};
/**
* Q.931 Coding Standard
*/
enum {
Q931_CODING_ITU = 0x00,
Q931_CODING_ISO = 0x01,
Q931_CODING_NATIONAL = 0x02,
Q931_CODING_NETWORK = 0x03
};
/**
* Q.931 High layer characteristik id
*/
enum {
Q931_HLCHAR_TELEPHONY = 0x01,
Q931_HLCHAR_FAX_G23 = 0x04,
Q931_HLCHAR_FAX_G4 = 0x21,
Q931_HLCHAR_FAX_G4II = 0x24,
Q931_HLCHAR_T102 = 0x32,
Q931_HLCHAR_T101 = 0x33,
Q931_HLCHAR_F60 = 0x35,
Q931_HLCHAR_X400 = 0x38,
Q931_HLCHAR_X200 = 0x41
};
/**
* Q.931 User information layer 1 protocol
*/
enum {
Q931_UIL1P_V110 = 0x01,
Q931_UIL1P_I460 = 0x01,
Q931_UIL1P_X30 = 0x01,
Q931_UIL1P_G711U = 0x02,
Q931_UIL1P_G711A = 0x03,
Q931_UIL1P_G721 = 0x04,
Q931_UIL1P_H221 = 0x05,
Q931_UIL1P_H242 = 0x05,
Q931_UIL1P_H223 = 0x06,
Q931_UIL1P_H245 = 0x06,
Q931_UIL1P_RATE_ADAP = 0x07,
Q931_UIL1P_V120 = 0x08,
Q931_UIL1P_X31 = 0x09
};
/**
* Q.931 Information Transfer Capability
*/
enum {
Q931_ITC_SPEECH = 0x00,
Q931_ITC_UNRESTRICTED = 0x08,
Q931_ITC_RESTRICTED = 0x09,
Q931_ITC_3K1_AUDIO = 0x10,
Q931_ITC_UNRESTRICTED_TONES = 0x11,
Q931_ITC_VIDEO = 0x18
};
/**
* Q.931 Information transfer rate
*/
enum {
Q931_ITR_PACKET = 0x00,
Q931_ITR_64K = 0x10,
Q931_ITR_128K = 0x11,
Q931_ITR_384K = 0x13,
Q931_ITR_1536K = 0x15,
Q931_ITR_1920K = 0x17,
Q931_ITR_MULTI = 0x18
};
/*****************************************************************************
Struct: Q931mes_Header
@@ -479,33 +635,46 @@ typedef struct
*****************************************************************************/
typedef struct Q931_TrunkInfo Q931_TrunkInfo_t;
typedef L3INT (*Q931TxCB_t) (void *,L3UCHAR *, L3INT);
typedef L3INT (*Q931ErrorCB_t) (void *,L3INT,L3INT,L3INT);
typedef enum /* Network/User Mode. */
typedef enum
{
Q931_TE=0, /* 0 : User Mode */
Q931_NT=1 /* 1 : Network Mode */
Q931_LOG_NONE = 0,
Q931_LOG_ERROR,
Q931_LOG_WARNING,
Q931_LOG_NOTICE,
Q931_LOG_INFO,
Q931_LOG_DEBUG
} Q931LogLevel_t;
typedef L3INT (*Q931Tx34CB_t) (void *,L3UCHAR *, L3INT);
typedef L3INT (*Q931Tx32CB_t) (void *, L3INT, L3UCHAR, L3UCHAR *, L3INT);
typedef L3INT (*Q931ErrorCB_t) (void *,L3INT,L3INT,L3INT);
typedef L3INT (*Q931LogCB_t) (void *, Q931LogLevel_t, char *, L3INT);
typedef enum /* Network/User Mode. */
{
Q931_TE=0, /* 0 : User Mode */
Q931_NT=1 /* 1 : Network Mode */
} Q931NetUser_t;
typedef enum /* Dialect enum */
typedef enum /* Dialect enum */
{
Q931_Dialect_Q931 = 0,
Q931_Dialect_National = 2,
Q931_Dialect_DMS = 4,
Q931_Dialect_5ESS = 6, /* Coming soon to a PRI stack near you! */
Q931_Dialect_5ESS = 6, /* Coming soon to a PRI stack near you! */
Q931_Dialect_Count
} Q931Dialect_t;
#define DIALECT_STRINGS "q931", "", "national", "", "dms","","5ess",""
#define DIALECT_STRINGS "q931", "", "national", "", "dms", "", "5ess", ""
Q931_STR2ENUM_P(q931_str2Q931Dialect_type, q931_Q931Dialect_type2str, Q931Dialect_t)
typedef enum /* Trunk Line Type. */
typedef enum /* Trunk Line Type. */
{
Q931_TrType_E1=0, /* 0 : E1 Trunk */
Q931_TrType_T1=1, /* 1 : T1 Trunk */
Q931_TrType_J1=2, /* 2 : J1 Trunk */
Q931_TrType_BRI=3 /* 3 : BRI Trunk */
Q931_TrType_E1 = 0, /* 0 : E1 Trunk */
Q931_TrType_T1 = 1, /* 1 : T1 Trunk */
Q931_TrType_J1 = 2, /* 2 : J1 Trunk */
Q931_TrType_BRI = 3, /* 3 : BRI Trunk */
Q931_TrType_BRI_PTMP = 4 /* 4 : BRI PTMP Trunk */
} Q931_TrunkType_t;
typedef enum /* Trunk State */
@@ -522,19 +691,51 @@ typedef enum {
Q931_ChType_Sync=3 /* Sync Channel */
} Q931_ChanType_t;
struct Q931_Call
{
L3UCHAR InUse; /* Indicate if entry is in use. */
/* 0 = Not in Use */
/* 1 = Active Call. */
L3UCHAR Tei; /* Associated TEI */
L3UCHAR BChan; /* Associated B Channel. */
/* 0 - 31 valid B chan */
/* 255 = Not allocated */
L3INT CRV; /* Associated CRV. */
L3UINT State; /* Call State. */
/* 0 is Idle, but other values are */
/* defined per dialect. */
/* Default usage is 1-99 for TE and */
/* 101 - 199 for NT. */
L3ULONG Timer; /* Timer in ms. The TimeTick will check */
/* if this has exceeded the timeout, and */
/* if so call the timers timeout proc. */
L3USHORT TimerID; /* Timer Identification/State */
/* actual values defined by dialect */
/* 0 : No timer running */
/* ITU-T Q.931:301 - 322 Timer running */
};
struct Q931_TrunkInfo
{
Q931NetUser_t NetUser; /* Network/User Mode. */
Q931Dialect_t Dialect; /* Q.931 Based dialect index. */
Q931_TrunkType_t TrunkType; /* Trunk Line Type. */
Q931Dialect_t Dialect; /* Q.931 Based dialect index. */
Q931TxCB_t Q931Tx34CBProc;
Q931TxCB_t Q931Tx32CBProc;
Q931Tx34CB_t Q931Tx34CBProc;
Q931Tx32CB_t Q931Tx32CBProc;
Q931ErrorCB_t Q931ErrorCBProc;
Q931LogCB_t Q931LogCBProc;
void *PrivateData32;
void *PrivateData34;
void *PrivateDataLog;
Q931LogLevel_t loglevel;
L3UCHAR Enabled; /* Enabled/Disabled */
/* 0 = Disabled */
@@ -580,37 +781,9 @@ struct Q931_TrunkInfo
}ch[Q931MAXCHPERTRUNK];
/* Active Call information indentified by CRV. See Q931AllocateCRV for */
/* initialization of call table. */
struct _ccarray
{
L3UCHAR InUse; /* Indicate if entry is in use. */
/* 0 = Not in Use */
/* 1 = Active Call. */
L3UCHAR BChan; /* Associated B Channel. */
/* 0 - 31 valid B chan */
/* 255 = Not allocated */
L3INT CRV; /* Associated CRV. */
L3UINT State; /* Call State. */
/* 0 is Idle, but other values are */
/* defined per dialect. */
/* Default usage is 1-99 for TE and */
/* 101 - 199 for NT. */
L3ULONG Timer; /* Timer in ms. The TimeTick will check */
/* if this has exceeded the timeout, and*/
/* if so call the timers timeout proc. */
L3USHORT TimerID; /* Timer Identification/State */
/* actual values defined by dialect */
/* 0 : No timer running */
/* ITU-T Q.931:301 - 322 Timer running */
}call[Q931MAXCALLPERTRUNK];
/* Active Call information indentified by CRV. See Q931AllocateCRV for */
/* initialization of call table. */
struct Q931_Call call[Q931MAXCALLPERTRUNK];
};
/*****************************************************************************
@@ -646,6 +819,9 @@ typedef L3INT (q931pmes_func_t) (Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf
typedef L3INT (q931uie_func_t) (Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff);
typedef L3INT (q931pie_func_t) (Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet);
typedef L3INT (q931timeout_func_t) (Q931_TrunkInfo_t *pTrunk, L3INT callIndex);
typedef L3ULONG q931timer_t;
extern q931proc_func_t *Q931Proc[Q931MAXDLCT][Q931MAXMES];
extern q931umes_func_t *Q931Umes[Q931MAXDLCT][Q931MAXMES];
@@ -654,6 +830,10 @@ extern q931pmes_func_t *Q931Pmes[Q931MAXDLCT][Q931MAXMES];
extern q931uie_func_t *Q931Uie[Q931MAXDLCT][Q931MAXIE];
extern q931pie_func_t *Q931Pie[Q931MAXDLCT][Q931MAXIE];
extern q931timeout_func_t *Q931Timeout[Q931MAXDLCT][Q931MAXTIMER];
extern q931timer_t Q931Timer[Q931MAXDLCT][Q931MAXTIMER];
/*****************************************************************************
Macro: GetIETotoSize
@@ -893,9 +1073,9 @@ L3INT Q931ProcUnexpectedMessage(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFro
Interface Function Prototypes. Implemented in Q931.c
*****************************************************************************/
void Q931TimeTick(Q931_TrunkInfo_t *pTrunk, L3ULONG ms);
L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size);
L3INT Q931Tx32(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size);
void Q931TimerTick(Q931_TrunkInfo_t *pTrunk);
L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3INT ind, L3UCHAR tei, L3UCHAR * Mes, L3INT Size);
L3INT Q931Tx32Data(Q931_TrunkInfo_t *pTrunk, L3UCHAR bcast, L3UCHAR * Mes, L3INT Size);
L3INT Q931Rx43(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size);
L3INT Q931Tx34(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size);
void Q931SetError(Q931_TrunkInfo_t *pTrunk,L3INT ErrID, L3INT ErrPar1, L3INT ErrPar2);
@@ -910,6 +1090,8 @@ void Q931SetHeaderSpace(L3INT space);
void Q931SetMesProc(L3UCHAR mes, L3UCHAR dialect, q931proc_func_t *Q931ProcFunc, q931umes_func_t *Q931UmesFunc, q931pmes_func_t *Q931PmesFunc);
void Q931SetIEProc(L3UCHAR iec, L3UCHAR dialect, q931pie_func_t *Q931PieProc, q931uie_func_t *Q931UieProc);
void Q931SetTimeoutProc(L3UCHAR timer, L3UCHAR dialect, q931timeout_func_t *Q931TimeoutProc);
void Q931SetTimerDefault(L3UCHAR timer, L3UCHAR dialect, q931timer_t timeout);
void Q931Initialize(void);
void Q931AddDialect(L3UCHAR iDialect, void (*Q931CreateDialectCB)(L3UCHAR iDialect));
@@ -926,7 +1108,7 @@ L3INT Q931StartTimer(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3USHORT iTimer)
L3INT Q931StopTimer(Q931_TrunkInfo_t *pTrunk, L3INT callindex, L3USHORT iTimer);
L3INT Q931SetState(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3INT iState);
L3ULONG Q931GetTime(void);
void Q931SetGetTimeCB(L3ULONG (*callback)(void));
void Q931SetGetTimeCB(L3ULONG (*callback)(void));
void Q931AddStateEntry(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir);
L3BOOL Q931IsEventLegal(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir);
@@ -965,8 +1147,8 @@ L3INT Q931Api_InitTrunk(Q931_TrunkInfo_t *pTrunk,
Q931Dialect_t Dialect,
Q931NetUser_t NetUser,
Q931_TrunkType_t TrunkType,
Q931TxCB_t Q931Tx34CBProc,
Q931TxCB_t Q931Tx32CBProc,
Q931Tx34CB_t Q931Tx34CBProc,
Q931Tx32CB_t Q931Tx32CBProc,
Q931ErrorCB_t Q931ErrorCBProc,
void *PrivateData32,
void *PrivateData34);
@@ -974,7 +1156,9 @@ L3INT Q931Api_InitTrunk(Q931_TrunkInfo_t *pTrunk,
L3INT Q931GetMesSize(Q931mes_Generic *pMes);
L3INT Q931InitMesResume(Q931mes_Generic * pMes);
L3INT Q931Log(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level, const char *fmt, ...);
void Q931SetLogCB(Q931_TrunkInfo_t *trunk, Q931LogCB_t func, void *priv);
void Q931SetLogLevel(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level);
void Q931SetL4HeaderSpace(L3INT space);
void Q931SetL2HeaderSpace(L3INT space);
@@ -985,7 +1169,8 @@ L3INT Q931PmesDummy(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize
L3INT Q931PieDummy(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet);
L3INT Q931TxDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT n);
L3INT Q931ErrorDummy(void *priv, L3INT a, L3INT b, L3INT c);
L3INT Q931TimeoutDummy(Q931_TrunkInfo_t *pTrunk, L3INT callIndex);
L3INT Q931MesgHeader(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *mes, L3UCHAR *OBuf, L3INT Size, L3INT *IOff);
#endif /* _Q931_NL */
+6 -1
View File
@@ -57,7 +57,7 @@ typedef enum {
/* Single octet information elements */
#define Q931ie_SHIFT 0x90 /* 1001 ---- */
#define Q931ie_MORE_DATA 0xa0 /* 1010 ---- */
#define Q931ie_SENDING_COMPLETE 0xa1 /* 1010 0000 */
#define Q931ie_SENDING_COMPLETE 0xa1 /* 1010 0001 */
#define Q931ie_CONGESTION_LEVEL 0xb0 /* 1011 ---- */
#define Q931ie_REPEAT_INDICATOR 0xd0 /* 1101 ---- */
@@ -101,6 +101,9 @@ typedef enum {
#define Q931ie_GENERIC_DIGITS 0x37 /* 0011 0111 */
/* Variable Length Information Element to shut up BRI testing */
#define Q931ie_CONNECTED_NUMBER 0x4c /* 0100 1101 */
#define Q931ie_FACILITY 0x1c /* 0001 1101 */
/*****************************************************************************
@@ -1168,5 +1171,7 @@ L3INT Q931Pie_CongLevel(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf,
L3INT Q931Uie_RevChargeInd(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff);
L3INT Q931Pie_RevChargeInd(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet);
L3INT Q931Uie_Generic(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff);
L3INT Q931Pie_Generic(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet);
#endif /* _Q931IE_NL */
+9 -5
View File
@@ -58,15 +58,15 @@ typedef struct _mindex
queue.
*****************************************************************************/
typedef struct _mfifo
typedef struct
{
int first; /* first out */
int last; /* last in + 1 */
int bsize; /* buffer size */
unsigned char *buf; /* ptr to start of buffer */
int ixsize; /* index size */
MINDEX ix[1]; /* message index */
}MFIFO;
unsigned char *buf; /* ptr to start of buffer */
int ixsize; /* index size */
MINDEX ix[1]; /* message index */
} MFIFO;
/*****************************************************************************
Function prototypes.
@@ -80,4 +80,8 @@ int MFIFOWriteMes(unsigned char *buf, unsigned char *mes, int size);
unsigned char * MFIFOGetMesPtr(unsigned char *buf, int *size);
void MFIFOKillNext(unsigned char *buf);
unsigned char * MFIFOGetMesPtrOffset(unsigned char *buf, int *size, const int pos);
int MFIFOGetMesCount(unsigned char *buf);
int MFIFOWriteMesOverwrite(unsigned char *buf, unsigned char *mes, int size);
#endif