add functions to initialize a trunk, and a public function to receive from layer 3 that sends an I frame.

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@86 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
Michael Jerris 2007-05-22 01:25:35 +00:00
parent f969341e86
commit ca278fa2f1
2 changed files with 586 additions and 541 deletions

View File

@ -1,424 +1,458 @@
/***************************************************************************** /*****************************************************************************
FileName: q921.c FileName: q921.c
Description: Contains the implementation of a Q.921 protocol on top of the Description: Contains the implementation of a Q.921 protocol on top of the
Comet Driver. Comet Driver.
Most of the work required to execute a Q.921 protocol is Most of the work required to execute a Q.921 protocol is
taken care of by the Comet ship and it's driver. This layer taken care of by the Comet ship and it's driver. This layer
will simply configure and make use of these features to will simply configure and make use of these features to
complete a Q.921 implementation. complete a Q.921 implementation.
Created: 27.dec.2000/JVB Created: 27.dec.2000/JVB
License/Copyright: License/Copyright:
Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
email:janvb@caselaboratories.com email:janvb@caselaboratories.com
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are
met: met:
* Redistributions of source code must retain the above copyright notice, * 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, * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
* Neither the name of the Case Labs, Ltd nor the names of its contributors * 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 may be used to endorse or promote products derived from this software
without specific prior written permission. without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include "Q921.h" #include "Q921.h"
#include <stdlib.h> #include <stdlib.h>
#include "mfifo.h" #include "mfifo.h"
/***************************************************************************** /*****************************************************************************
Global Tables & Variables. Global Tables & Variables.
*****************************************************************************/ *****************************************************************************/
Q921Data Q921DevSpace[Q921MAXTRUNK]; Q921Data Q921DevSpace[Q921MAXTRUNK];
int Q921HeaderSpace={0}; int Q921HeaderSpace={0};
int (*Q921Tx21Proc)(int dev, L2UCHAR *, int)={NULL}; int (*Q921Tx21Proc)(int dev, L2UCHAR *, int)={NULL};
int (*Q921Tx23Proc)(int dev, L2UCHAR *, int)={NULL}; int (*Q921Tx23Proc)(int dev, L2UCHAR *, int)={NULL};
/***************************************************************************** /*****************************************************************************
Function: Q921Init Function: Q921Init
Decription: Initialize the Q.921 stack so it is ready for use. This Decription: Initialize the Q.921 stack so it is ready for use. This
function MUST be called as part of initializing the function MUST be called as part of initializing the
application. application.
*****************************************************************************/ *****************************************************************************/
void Q921Init() void Q921Init()
{ {
int x; int x;
for(x=0; x<Q921MAXTRUNK;x++) for(x=0; x<Q921MAXTRUNK;x++)
{ {
MFIFOCreate(Q921DevSpace[x].HDLCInQueue, Q921MAXHDLCSPACE, 10); MFIFOCreate(Q921DevSpace[x].HDLCInQueue, Q921MAXHDLCSPACE, 10);
Q921DevSpace[x].vr=0; Q921DevSpace[x].vr = 0;
Q921DevSpace[x].vs=0; Q921DevSpace[x].vs = 0;
Q921DevSpace[x].state=0;; Q921DevSpace[x].state = 0;
} Q921DevSpace[x].sapi = 0;
} Q921DevSpace[x].tei = 0;
Q921DevSpace[x].NetUser = Q921_TE;
void Q921SetHeaderSpace(int hspace) }
{ }
Q921HeaderSpace=hspace;
} /*****************************************************************************
void Q921SetTx21CB(int (*callback)(int dev, L2UCHAR *, int)) Function: Q921_InitTrunk
{
Q921Tx21Proc = callback; Decription: Initialize a Q.921 trunk so it is ready for use. This
} function should be called before you call the rx functions
if your trunk will not use hardcoded tei and sapi of 0 or
void Q921SetTx23CB(int (*callback)(int dev, L2UCHAR *, int)) if your trunk is not TE (user) mode (i.e. NET).
{
Q921Tx23Proc = callback; *****************************************************************************/
} int Q921_InitTrunk(long trunk, int sapi, int tei, Q921NetUser_t NetUser)
{
/***************************************************************************** if (trunk > Q921MAXTRUNK)
return 0;
Function: Q921QueueHDLCFrame
Q921DevSpace[trunk].sapi = sapi;
Description: Called to receive and queue an incoming HDLC frame. Will Q921DevSpace[trunk].tei = tei;
queue this in Q921HDLCInQueue. The called must either call Q921DevSpace[trunk].NetUser = NetUser;
Q921Rx12 directly afterwards or signal Q921Rx12 to be called return 1;
later. Q921Rx12 will read from the same queue and process }
the frame.
void Q921SetHeaderSpace(int hspace)
This function assumes that the message contains header {
space. This is removed for internal Q921 processing, but Q921HeaderSpace=hspace;
must be keept for I frames. }
Parameters: trunk trunk # void Q921SetTx21CB(int (*callback)(int dev, L2UCHAR *, int))
b ptr to frame; {
size size of frame in bytes Q921Tx21Proc = callback;
}
*****************************************************************************/
int Q921QueueHDLCFrame(int trunk, L2UCHAR *b, int size) void Q921SetTx23CB(int (*callback)(int dev, L2UCHAR *, int))
{ {
return MFIFOWriteMes(Q921DevSpace[trunk].HDLCInQueue, b, size); Q921Tx23Proc = callback;
} }
/***************************************************************************** /*****************************************************************************
Function: Q921SendI Function: Q921QueueHDLCFrame
Description: Compose and Send I Frame to layer. Will receive an I frame Description: Called to receive and queue an incoming HDLC frame. Will
with space for L2 header and fill out that header before queue this in Q921HDLCInQueue. The called must either call
it call Q921Tx21Proc. Q921Rx12 directly afterwards or signal Q921Rx12 to be called
later. Q921Rx12 will read from the same queue and process
Parameters: trunk trunk # the frame.
Sapi Sapi
cr C/R field. This function assumes that the message contains header
Tei Tei. space. This is removed for internal Q921 processing, but
pf P fiels octet 5 must be keept for I frames.
mes ptr to I frame message.
size size of message in bytes. Parameters: trunk trunk #
b ptr to frame;
Return Value: 0 if failed, 1 if Send. size size of frame in bytes
*****************************************************************************/ *****************************************************************************/
int Q921SendI(int trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR *mes, int size) int Q921QueueHDLCFrame(int trunk, L2UCHAR *b, int size)
{ {
mes[Q921HeaderSpace+0] = (Sapi&0xfc) | ((cr<<1)&0x02); return MFIFOWriteMes(Q921DevSpace[trunk].HDLCInQueue, b, size);
mes[Q921HeaderSpace+1] = (Tei<<1) | 0x01; }
mes[Q921HeaderSpace+2] = Q921DevSpace[trunk].vs<<1;
mes[Q921HeaderSpace+3] = (Q921DevSpace[trunk].vr<<1) | (pf & 0x01); /*****************************************************************************
Q921DevSpace[trunk].vs++;
Function: Q921SendI
return Q921Tx21Proc(trunk, mes, size);
} Description: Compose and Send I Frame to layer. Will receive an I frame
with space for L2 header and fill out that header before
/***************************************************************************** it call Q921Tx21Proc.
Function: Q921SendRR Parameters: trunk trunk #
Sapi Sapi
Description: Compose and send Receive Ready. cr C/R field.
Tei Tei.
Parameters: trunk trunk # pf P fiels octet 5
Sapi Sapi mes ptr to I frame message.
cr C/R field. size size of message in bytes.
Tei Tei.
pf P/F fiels octet 5 Return Value: 0 if failed, 1 if Send.
Return Value: 0 if failed, 1 if Send. *****************************************************************************/
int Q921SendI(int trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR *mes, int size)
*****************************************************************************/ {
mes[Q921HeaderSpace+0] = (Sapi&0xfc) | ((cr<<1)&0x02);
int Q921SendRR(int trunk, int Sapi, int cr, int Tei, int pf) mes[Q921HeaderSpace+1] = (Tei<<1) | 0x01;
{ mes[Q921HeaderSpace+2] = Q921DevSpace[trunk].vs<<1;
L2UCHAR mes[400]; mes[Q921HeaderSpace+3] = (Q921DevSpace[trunk].vr<<1) | (pf & 0x01);
Q921DevSpace[trunk].vs++;
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01); return Q921Tx21Proc(trunk, mes, size);
mes[Q921HeaderSpace+2] = (L2UCHAR)0x01; }
mes[Q921HeaderSpace+3] = (L2UCHAR)((Q921DevSpace[trunk].vr<<1) | (pf & 0x01));
int Q921Rx32(long trunk, L2UCHAR * Mes, L2INT Size)
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+4); {
} return Q921SendI(trunk,
Q921DevSpace[x].sapi,
/***************************************************************************** Q921DevSpace[x].NetUser == Q921_TE ? 0 : 1;
Q921DevSpace[x].tei,
Function: Q921SendRNR 0,
Mes,
Description: Compose and send Receive Nor Ready Size);
}
Parameters: trunk trunk # /*****************************************************************************
Sapi Sapi
cr C/R field. Function: Q921SendRR
Tei Tei.
pf P/F fiels octet 5 Description: Compose and send Receive Ready.
Return Value: 0 if failed, 1 if Send. Parameters: trunk trunk #
Sapi Sapi
*****************************************************************************/ cr C/R field.
int Q921SendRNR(int trunk, int Sapi, int cr, int Tei, int pf) Tei Tei.
{ pf P/F fiels octet 5
L2UCHAR mes[400];
Return Value: 0 if failed, 1 if Send.
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01); *****************************************************************************/
mes[Q921HeaderSpace+2] = (L2UCHAR)0x05;
mes[Q921HeaderSpace+3] = (L2UCHAR)((Q921DevSpace[trunk].vr<<1) | (pf & 0x01)); int Q921SendRR(int trunk, int Sapi, int cr, int Tei, int pf)
{
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+4); L2UCHAR mes[400];
}
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
/***************************************************************************** mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01);
mes[Q921HeaderSpace+2] = (L2UCHAR)0x01;
Function: Q921SendREJ mes[Q921HeaderSpace+3] = (L2UCHAR)((Q921DevSpace[trunk].vr<<1) | (pf & 0x01));
Description: Compose and Send Reject. return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+4);
}
Parameters: trunk trunk #
Sapi Sapi /*****************************************************************************
cr C/R field.
Tei Tei. Function: Q921SendRNR
pf P/F fiels octet 5
Description: Compose and send Receive Nor Ready
Return Value: 0 if failed, 1 if Send.
Parameters: trunk trunk #
*****************************************************************************/ Sapi Sapi
int Q921SendREJ(int trunk, int Sapi, int cr, int Tei, int pf) cr C/R field.
{ Tei Tei.
L2UCHAR mes[400]; pf P/F fiels octet 5
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02)); Return Value: 0 if failed, 1 if Send.
mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01);
mes[Q921HeaderSpace+2] = (L2UCHAR)0x09; *****************************************************************************/
mes[Q921HeaderSpace+3] = (L2UCHAR)((Q921DevSpace[trunk].vr<<1) | (pf & 0x01)); int Q921SendRNR(int trunk, int Sapi, int cr, int Tei, int pf)
{
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+4); L2UCHAR mes[400];
}
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
/***************************************************************************** mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01);
mes[Q921HeaderSpace+2] = (L2UCHAR)0x05;
Function: Q921SendSABME mes[Q921HeaderSpace+3] = (L2UCHAR)((Q921DevSpace[trunk].vr<<1) | (pf & 0x01));
Description: Compose and send SABME return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+4);
}
Parameters: trunk trunk #
Sapi Sapi /*****************************************************************************
cr C/R field.
Tei Tei. Function: Q921SendREJ
pf P fiels octet 4
Description: Compose and Send Reject.
Return Value: 0 if failed, 1 if Send.
Parameters: trunk trunk #
*****************************************************************************/ Sapi Sapi
int Q921SendSABME(int trunk, int Sapi, int cr, int Tei, int pf) cr C/R field.
{ Tei Tei.
L2UCHAR mes[400]; pf P/F fiels octet 5
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02)); Return Value: 0 if failed, 1 if Send.
mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01);
mes[Q921HeaderSpace+2] = (L2UCHAR)(0x6f | ((pf<<4)&0x10)); *****************************************************************************/
int Q921SendREJ(int trunk, int Sapi, int cr, int Tei, int pf)
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+3); {
} L2UCHAR mes[400];
/***************************************************************************** mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01);
Function: Q921SendDM mes[Q921HeaderSpace+2] = (L2UCHAR)0x09;
mes[Q921HeaderSpace+3] = (L2UCHAR)((Q921DevSpace[trunk].vr<<1) | (pf & 0x01));
Description: Comose and Send DM (Disconnected Mode)
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+4);
Parameters: trunk trunk # }
Sapi Sapi
cr C/R field. /*****************************************************************************
Tei Tei.
pf F fiels octet 4 Function: Q921SendSABME
Return Value: 0 if failed, 1 if Send. Description: Compose and send SABME
*****************************************************************************/ Parameters: trunk trunk #
int Q921SendDM(int trunk, int Sapi, int cr, int Tei, int pf) Sapi Sapi
{ cr C/R field.
L2UCHAR mes[400]; Tei Tei.
pf P fiels octet 4
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01); Return Value: 0 if failed, 1 if Send.
mes[Q921HeaderSpace+2] = (L2UCHAR)(0x0f | ((pf<<4)&0x10));
*****************************************************************************/
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+3); int Q921SendSABME(int trunk, int Sapi, int cr, int Tei, int pf)
} {
L2UCHAR mes[400];
/*****************************************************************************
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
Function: Q921SendDISC mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01);
mes[Q921HeaderSpace+2] = (L2UCHAR)(0x6f | ((pf<<4)&0x10));
Description: Compose and Send Disconnect
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+3);
Parameters: trunk trunk # }
Sapi Sapi
cr C/R field. /*****************************************************************************
Tei Tei.
pf P fiels octet 4 Function: Q921SendDM
Return Value: 0 if failed, 1 if Send. Description: Comose and Send DM (Disconnected Mode)
*****************************************************************************/ Parameters: trunk trunk #
int Q921SendDISC(int trunk, int Sapi, int cr, int Tei, int pf) Sapi Sapi
{ cr C/R field.
L2UCHAR mes[400]; Tei Tei.
pf F fiels octet 4
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01); Return Value: 0 if failed, 1 if Send.
mes[Q921HeaderSpace+2] = (L2UCHAR)(0x43 | ((pf<<4)&0x10));
*****************************************************************************/
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+3); int Q921SendDM(int trunk, int Sapi, int cr, int Tei, int pf)
} {
L2UCHAR mes[400];
/*****************************************************************************
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
Function: Q921SendUA mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01);
mes[Q921HeaderSpace+2] = (L2UCHAR)(0x0f | ((pf<<4)&0x10));
Description: Compose and Send UA
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+3);
Parameters: trunk trunk # }
Sapi Sapi
cr C/R field. /*****************************************************************************
Tei Tei.
pf F fiels octet 4 Function: Q921SendDISC
Return Value: 0 if failed, 1 if Send. Description: Compose and Send Disconnect
*****************************************************************************/ Parameters: trunk trunk #
int Q921SendUA(int trunk, int Sapi, int cr, int Tei, int pf) Sapi Sapi
{ cr C/R field.
L2UCHAR mes[400]; Tei Tei.
pf P fiels octet 4
mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01); Return Value: 0 if failed, 1 if Send.
mes[Q921HeaderSpace+2] = (L2UCHAR)(0x63 | ((pf<<4)&0x10));
*****************************************************************************/
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+3); int Q921SendDISC(int trunk, int Sapi, int cr, int Tei, int pf)
} {
L2UCHAR mes[400];
int Q921ProcSABME(int trunk, L2UCHAR *mes, int size)
{ mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
/* TODO: Do we need these paramaters? */ mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01);
(void)mes; mes[Q921HeaderSpace+2] = (L2UCHAR)(0x43 | ((pf<<4)&0x10));
(void)size;
return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+3);
Q921DevSpace[trunk].vr=0; }
Q921DevSpace[trunk].vs=0;
/*****************************************************************************
return 1;
} Function: Q921SendUA
/***************************************************************************** Description: Compose and Send UA
Function: Q921Rx12 Parameters: trunk trunk #
Sapi Sapi
Description: Called to process a message frame from layer 1. Will cr C/R field.
identify the message and call the proper 'processor' for Tei Tei.
layer 2 messages and forward I frames to the layer 3 entity. pf F fiels octet 4
Q921Rx12 will check the input fifo for a message, and if a Return Value: 0 if failed, 1 if Send.
message exist process one message before it exits. The caller
must either call Q921Rx12 polling or keep track on # *****************************************************************************/
messages in the queue. int Q921SendUA(int trunk, int Sapi, int cr, int Tei, int pf)
{
Parameters: trunk trunk #. L2UCHAR mes[400];
Return Value: # messages processed (always 1 or 0). mes[Q921HeaderSpace+0] = (L2UCHAR)((Sapi&0xfc) | ((cr<<1)&0x02));
mes[Q921HeaderSpace+1] = (L2UCHAR)((Tei<<1) | 0x01);
*****************************************************************************/ mes[Q921HeaderSpace+2] = (L2UCHAR)(0x63 | ((pf<<4)&0x10));
int Q921Rx12(long trunk)
{ return Q921Tx21Proc(trunk, mes, Q921HeaderSpace+3);
L2UCHAR *mes; }
int rs,size; /* receive size & Q921 frame size*/
L2UCHAR *smes = MFIFOGetMesPtr(Q921DevSpace[trunk].HDLCInQueue, &size); int Q921ProcSABME(int trunk, L2UCHAR *mes, int size)
if(smes != NULL) {
{ /* TODO: Do we need these paramaters? */
rs = size - Q921HeaderSpace; (void)mes;
mes = &smes[Q921HeaderSpace]; (void)size;
/* check for I frame */
if((mes[2] & 0x01) == 0) Q921DevSpace[trunk].vr=0;
{ Q921DevSpace[trunk].vs=0;
if(Q921Tx23Proc(trunk, smes, size-2)) /* -2 to clip away CRC */
{ return 1;
Q921DevSpace[trunk].vr++; }
Q921SendRR(trunk, (mes[0]&0xfc)>>2, (mes[0]>>1)&0x01,mes[1]>>1, mes[3]&0x01);
} /*****************************************************************************
else
{ Function: Q921Rx12
/* todo: whatever*/
} Description: Called to process a message frame from layer 1. Will
} identify the message and call the proper 'processor' for
layer 2 messages and forward I frames to the layer 3 entity.
/* check for RR */
else if(mes[2] ==0x01) Q921Rx12 will check the input fifo for a message, and if a
{ message exist process one message before it exits. The caller
/* todo: check if RR is responce to I */ must either call Q921Rx12 polling or keep track on #
Q921SendRR(trunk, (mes[0]&0xfc)>>2, (mes[0]>>1)&0x01,mes[1]>>1, mes[2]&0x01); messages in the queue.
}
Parameters: trunk trunk #.
/* check for RNR */
/* check for REJ */ Return Value: # messages processed (always 1 or 0).
/* check for SABME */
else if((mes[2] & 0xef) == 0x6f) *****************************************************************************/
{ int Q921Rx12(long trunk)
Q921ProcSABME(trunk, mes, rs); {
Q921SendUA(trunk, (mes[0]&0xfc)>>2, (mes[0]>>1)&0x01,mes[1]>>1, (mes[2]&0x10)>>4); L2UCHAR *mes;
} int rs,size; /* receive size & Q921 frame size*/
L2UCHAR *smes = MFIFOGetMesPtr(Q921DevSpace[trunk].HDLCInQueue, &size);
/* check for DM */ if(smes != NULL)
/* check for UI */ {
/* check for DISC */ rs = size - Q921HeaderSpace;
/* check for UA */ mes = &smes[Q921HeaderSpace];
/* check for FRMR */ /* check for I frame */
/* check for XID */ if((mes[2] & 0x01) == 0)
{
else if(Q921Tx23Proc(trunk, smes, size-2)) /* -2 to clip away CRC */
{ {
/* what the ? Issue an error */ Q921DevSpace[trunk].vr++;
/* Q921ErrorProc(trunk, Q921_UNKNOWNFRAME, mes, rs); */ Q921SendRR(trunk, (mes[0]&0xfc)>>2, (mes[0]>>1)&0x01,mes[1]>>1, mes[3]&0x01);
/* todo: REJ or FRMR */ }
} else
{
MFIFOKillNext(Q921DevSpace[trunk].HDLCInQueue); /* todo: whatever*/
}
return 1; }
}
return 0; /* check for RR */
} else if(mes[2] ==0x01)
{
/* todo: check if RR is responce to I */
Q921SendRR(trunk, (mes[0]&0xfc)>>2, (mes[0]>>1)&0x01,mes[1]>>1, mes[2]&0x01);
}
/* check for RNR */
/* check for REJ */
/* check for SABME */
else if((mes[2] & 0xef) == 0x6f)
{
Q921ProcSABME(trunk, mes, rs);
Q921SendUA(trunk, (mes[0]&0xfc)>>2, (mes[0]>>1)&0x01,mes[1]>>1, (mes[2]&0x10)>>4);
}
/* check for DM */
/* check for UI */
/* check for DISC */
/* check for UA */
/* check for FRMR */
/* check for XID */
else
{
/* what the ? Issue an error */
/* Q921ErrorProc(trunk, Q921_UNKNOWNFRAME, mes, rs); */
/* todo: REJ or FRMR */
}
MFIFOKillNext(Q921DevSpace[trunk].HDLCInQueue);
return 1;
}
return 0;
}

View File

@ -1,117 +1,128 @@
/***************************************************************************** /*****************************************************************************
FileName: q921.h FileName: q921.h
Description: Contains headers of a Q.921 protocol on top of the Comet Description: Contains headers of a Q.921 protocol on top of the Comet
Driver. Driver.
Most of the work required to execute a Q.921 protocol is Most of the work required to execute a Q.921 protocol is
taken care of by the Comet ship and it's driver. This layer taken care of by the Comet ship and it's driver. This layer
will simply configure and make use of these features to will simply configure and make use of these features to
complete a Q.921 implementation. complete a Q.921 implementation.
Note: This header file is the only include file that should be Note: This header file is the only include file that should be
acessed by users of the Q.921 stack. acessed by users of the Q.921 stack.
Interface: The Q.921 stack contains 2 layers. Interface: The Q.921 stack contains 2 layers.
- One interface layer. - One interface layer.
- One driver layer. - One driver layer.
The interface layer contains the interface functions required The interface layer contains the interface functions required
for a layer 3 stack to be able to send and receive messages. for a layer 3 stack to be able to send and receive messages.
The driver layer will simply feed bytes into the ship as The driver layer will simply feed bytes into the ship as
required and queue messages received out from the ship. required and queue messages received out from the ship.
Q921TimeTick The Q.921 like any other blackbox Q921TimeTick The Q.921 like any other blackbox
modules contains no thread by it's own modules contains no thread by it's own
and must therefore be called regularly and must therefore be called regularly
by an external 'thread' to do maintenance by an external 'thread' to do maintenance
etc. etc.
Q921Rx32 Receive message from layer 3. Called by Q921Rx32 Receive message from layer 3. Called by
the layer 3 stack to send a message. the layer 3 stack to send a message.
Q921Tx23 Send a message to layer 3. Q921Tx23 Send a message to layer 3.
OnQ921Error Function called every if an error is OnQ921Error Function called every if an error is
deteceted. deteceted.
OnQ921Log Function called if logging is active. OnQ921Log Function called if logging is active.
<TODO> Maintenance/Configuration interface <TODO> Maintenance/Configuration interface
Created: 27.dec.2000/JVB Created: 27.dec.2000/JVB
License/Copyright: License/Copyright:
Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
email:janvb@caselaboratories.com email:janvb@caselaboratories.com
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are
met: met:
* Redistributions of source code must retain the above copyright notice, * 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, * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
* Neither the name of the Case Labs, Ltd nor the names of its contributors * 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 may be used to endorse or promote products derived from this software
without specific prior written permission. without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef _Q921 #ifndef _Q921
#define _Q921 #define _Q921
#define Q921MAXTRUNK 4 #define Q921MAXTRUNK 4
#define Q921MAXHDLCSPACE 3000 #define Q921MAXHDLCSPACE 3000
/***************************************************************************** /*****************************************************************************
Some speed optimization can be achieved by changing all variables to the 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 have to do a lot of extra
work to read a packed 8 bit integer. Changing all fields to 32 bit integer 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 ressult in usage of some extra space, but speed up the stack.
The stack have been designed to allow L3UCHAR etc. to be any size of 8 bit The stack have been designed to allow L3UCHAR etc. to be any size of 8 bit
or larger. or larger.
*****************************************************************************/ *****************************************************************************/
#define L2UCHAR unsigned char /* Min 8 bit */ #define L2UCHAR unsigned char /* Min 8 bit */
#define L2INT int /* Min 16 bit signed */ #define L2INT int /* Min 16 bit signed */
typedef struct typedef enum /* Network/User Mode. */
{ {
L2UCHAR HDLCInQueue[Q921MAXHDLCSPACE]; Q921_TE=0, /* 0 : User Mode */
L2UCHAR vs; Q921_NT=1 /* 1 : Network Mode */
L2UCHAR vr; } Q921NetUser_t;
int state;
}Q921Data; typedef struct
{
void Q921Init(); L2UCHAR HDLCInQueue[Q921MAXHDLCSPACE];
void Q921SetHeaderSpace(int hspace); L2UCHAR vs;
void Q921SetTx21CB(int (*callback)(int dev, L2UCHAR *, int)); L2UCHAR vr;
void Q921SetTx23CB(int (*callback)(int dev, L2UCHAR *, int)); L2INT state;
int Q921QueueHDLCFrame(int trunk, L2UCHAR *b, int size); L2INT sapi;
int Q921Rx12(long trunk); L2INT tei;
Q921NetUser_t NetUser;
#endif
}Q921Data;
void Q921Init();
int Q921_InitTrunk(long trunk, int sapi, int tei, Q921NetUser_t NetUser);
void Q921SetHeaderSpace(int hspace);
void Q921SetTx21CB(int (*callback)(int dev, L2UCHAR *, int));
void Q921SetTx23CB(int (*callback)(int dev, L2UCHAR *, int));
int Q921QueueHDLCFrame(int trunk, L2UCHAR *b, int size);
int Q921Rx12(long trunk);
#endif