libisdn
Q931api.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   FileName:             Q931api.c
00004 
00005   Contents:             api (Application Programming Interface) functions.
00006                                 See     q931.h for description.
00007 
00008   License/Copyright:
00009 
00010   Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
00011   email:janvb@caselaboratories.com
00012 
00013   Redistribution and use in source and binary forms, with or without
00014   modification, are permitted provided that the following conditions are
00015   met:
00016 
00017     * Redistributions of source code must retain the above copyright notice,
00018           this list of conditions and the following disclaimer.
00019     * Redistributions in binary form must reproduce the above copyright notice,
00020           this list of conditions and the following disclaimer in the documentation
00021           and/or other materials provided with the distribution.
00022     * Neither the name of the Case Labs, Ltd nor the names of its contributors
00023           may be used to endorse or promote products derived from this software
00024           without specific prior written permission.
00025 
00026   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036   POSSIBILITY OF SUCH DAMAGE.
00037 *****************************************************************************/
00038 #include <stdlib.h>
00039 #include <string.h>
00040 
00041 #include "Q931.h"
00042 #include "Q931priv.h"
00043 
00044 extern L3INT Q931L4HeaderSpace;
00045 
00046 Q931_API L3INT Q931InitTrunk(Q931_TrunkInfo_t *trunk,
00047                                                 Q931Dialect_t Dialect,
00048                                                 Q931NetUser_t NetUser,
00049                                                 Q931_TrunkType_t TrunkType,
00050                                                 Q931Tx34CB_t Q931Tx34CBProc,
00051                                                 Q931Tx32CB_t Q931Tx32CBProc,
00052                                                 Q931ErrorCB_t Q931ErrorCBProc,
00053                                                 void *PrivateData32,
00054                                                 void *PrivateData34)
00055 {
00056         int y, dchannel, maxchans, has_sync = 0;
00057 
00058         memset(trunk, 0, sizeof(Q931_TrunkInfo_t));
00059 
00060         switch(TrunkType) {
00061         case Q931_TrType_E1:
00062                 dchannel = 16;
00063                 maxchans = 31;
00064                 has_sync = 1;
00065                 break;
00066 
00067         case Q931_TrType_T1:
00068         case Q931_TrType_J1:
00069                 dchannel = 24;
00070                 maxchans = 24;
00071                 break;
00072 
00073         case Q931_TrType_BRI:
00074         case Q931_TrType_BRI_PTMP:
00075                 dchannel = 3;
00076                 maxchans = 3;
00077                 break;
00078 
00079         default:
00080                 return -1;
00081         }
00082 
00083         trunk->Q931Tx34CBProc  = Q931Tx34CBProc;
00084         trunk->Q931Tx32CBProc  = Q931Tx32CBProc;
00085         trunk->Q931ErrorCBProc = Q931ErrorCBProc;
00086         trunk->PrivateData32   = PrivateData32;
00087         trunk->PrivateData34   = PrivateData34;
00088 
00089         trunk->LastCRV        = 0;
00090         trunk->Enabled        = 0;
00091         trunk->TrunkState     = 0;
00092 #if 0
00093         trunk->autoRestartAck = 0;
00094 #endif
00095 
00096         /* Set dialect */
00097         trunk->Dialect = Q931DialectGet(Dialect, NetUser);
00098         if (!trunk->Dialect) {
00099                 return -1;
00100         }
00101         trunk->TrunkType = TrunkType;
00102         trunk->NetUser   = NetUser;
00103 
00104         /* Init channel list */
00105         for (y = 0; y < Q931MAXCHPERTRUNK; y++) {
00106                 trunk->ch[y].Available = 1;
00107 
00108                 if (has_sync && y == 0) {
00109                         trunk->ch[y].ChanType = Q931_ChType_Sync;
00110                 }
00111                 else if (y == dchannel) {
00112                         trunk->ch[y].ChanType = Q931_ChType_D;
00113                 }
00114                 else if(y > maxchans) {
00115                         trunk->ch[y].ChanType = Q931_ChType_NotUsed;
00116                 }
00117                 else {
00118                         trunk->ch[y].ChanType = Q931_ChType_B;
00119                 }
00120         }
00121 
00122         /* Init global call */
00123         trunk->call[0].Trunk = trunk;
00124         trunk->call[0].InUse = 1;
00125 
00126         return 0;
00127 }
00128 
00132 Q931_API L3INT Q931Start(Q931_TrunkInfo_t *trunk)
00133 {
00134         L3UCHAR buf[Q931L4BUF];
00135         Q931mes_Generic *msg = (Q931mes_Generic *)buf;
00136         Q931ie_RestartInd resind;
00137         Q931ie_ChanID chanID;
00138 
00139         /*
00140          * TODO: Only restart Interface on
00141          * Init -> Up trunk state change (after receiving a L2_ESTABLISH indication)
00142          */
00143         Q931InitMesGeneric(msg);
00144         msg->MesType = Q931mes_RESTART;
00145         msg->CRV     = 0;
00146 
00147         /* Restart Indicator IE */
00148         resind.IEId  = Q931ie_RESTART_INDICATOR;
00149         resind.Class = 0x06;    /* Restart this interfaces (?) */
00150         resind.Size  = sizeof(Q931ie_RestartInd);
00151 
00152         msg->RestartInd = Q931AppendIE(msg, (L3UCHAR *)&resind);
00153 
00154         /* Channel ID IE */
00155         Q931InitIEChanID(&chanID);
00156         chanID.CodStand = 0;
00157         chanID.IntType = Q931_IS_PRI(trunk) ? 1 : 0;
00158 
00159         msg->ChanID = Q931AppendIE(msg, (L3UCHAR *)&chanID);
00160 
00161         return Q931Proc(trunk, Q931GetGlobalCall(trunk), msg, Q931_MSG_FROM_L4);
00162 }
00163 
00164 L3INT Q931GetMesSize(Q931mes_Generic *msg)
00165 {
00166         return ((L3INT)(&msg->buf[0] - (L3UCHAR *)msg));
00167 }
00168 
00169 /*****************************************************************************
00170 
00171   Function:     q931AppendIE
00172 
00173   Description:  Append IE to the message.
00174 
00175   Parameters:   pm      Ptr to message.
00176                 pi      Ptr to information element
00177 
00178   Return Value  ie setting
00179 
00180 *****************************************************************************/
00181 Q931_API ie Q931AppendIE(Q931mes_Generic *msg, L3UCHAR *pi)
00182 {
00183         L3UCHAR *ptr = (L3UCHAR *)msg;
00184         L3INT iISize = ((Q931ie_BearerCap *)pi)->Size;
00185         L3INT Off    = msg->Size - (&msg->buf[0] - ptr);
00186 
00187         memcpy(ptr + msg->Size, pi, iISize);
00188         msg->Size += iISize;
00189 
00190         return (ie)(Off | 0x8000);
00191 }
00192 
00193 /*****************************************************************************
00194 *****************************************************************************/
00195 
00196 L3INT Q931GetUniqueCRV(Q931_TrunkInfo_t *trunk)
00197 {
00198         L3INT max = (Q931_IS_BRI(trunk)) ? Q931_BRI_MAX_CRV : Q931_PRI_MAX_CRV;
00199         L3INT attempts = 50;
00200 
00201         do {
00202                 trunk->LastCRV++;
00203                 trunk->LastCRV = (trunk->LastCRV <= max) ? trunk->LastCRV : 1;
00204 
00205         } while(Q931GetCallByCRV(trunk, trunk->LastCRV) && --attempts > 0);
00206 
00207         return trunk->LastCRV;
00208 }
00209 
00210 Q931_API L3INT Q931InitMesGeneric(Q931mes_Generic *msg)
00211 {
00212         memset(msg, 0, sizeof(*msg));
00213         msg->ProtDisc = 0x08;
00214         msg->Size     = Q931GetMesSize(msg);
00215         return 0;
00216 }
00217 
00218 Q931_API L3INT Q931InitMesResume(Q931mes_Generic *msg)
00219 {
00220         memset(msg, 0, sizeof(*msg));
00221         msg->ProtDisc = 0x08;
00222         msg->MesType  = Q931mes_RESUME;
00223         msg->Size     = Q931GetMesSize(msg);
00224         return 0;
00225 }
00226 
00227 Q931_API L3INT Q931InitMesRestartAck(Q931mes_Generic *msg)
00228 {
00229         memset(msg, 0, sizeof(*msg));
00230         msg->ProtDisc = 0x08;
00231         msg->MesType  = Q931mes_RESTART_ACKNOWLEDGE;
00232         msg->Size     = Q931GetMesSize(msg);
00233         return 0;
00234 }
00235 
00236 Q931_API L3INT Q931InitIEBearerCap(Q931ie_BearerCap *ie)
00237 {
00238         memset(ie, 0, sizeof(*ie));
00239         ie->IEId = Q931ie_BEARER_CAPABILITY;
00240         ie->Size = sizeof(Q931ie_BearerCap);
00241         ie->ITR  = 0x10;
00242         return 0;
00243 }
00244 
00245 Q931_API L3INT Q931InitIEChanID(Q931ie_ChanID *ie)
00246 {
00247         memset(ie, 0, sizeof(*ie));
00248         ie->IEId = Q931ie_CHANNEL_IDENTIFICATION;
00249         ie->Size = sizeof(Q931ie_ChanID);
00250         return 0;
00251 }
00252 
00253 Q931_API L3INT Q931InitIEProgInd(Q931ie_ProgInd *ie)
00254 {
00255         memset(ie, 0, sizeof(*ie));
00256         ie->IEId = Q931ie_PROGRESS_INDICATOR;
00257         ie->Size = sizeof(Q931ie_ProgInd);
00258         return 0;
00259 }
00260 
00261 Q931_API L3INT Q931InitIENetFac(Q931ie_NetFac *ie)
00262 {
00263         memset(ie, 0, sizeof(*ie));
00264         ie->IEId = Q931ie_NETWORK_SPECIFIC_FACILITIES;
00265         ie->Size = sizeof(Q931ie_NetFac);
00266         return 0;
00267 }
00268 
00269 Q931_API L3INT Q931InitIEDisplay(Q931ie_Display *ie)
00270 {
00271         memset(ie, 0, sizeof(*ie));
00272         ie->IEId = Q931ie_DISPLAY;
00273         ie->Size = sizeof(Q931ie_Display);
00274         return 0;
00275 }
00276 
00277 Q931_API L3INT Q931InitIEDateTime(Q931ie_DateTime *ie)
00278 {
00279         memset(ie, 0, sizeof(*ie));
00280         ie->IEId = Q931ie_DATETIME;
00281         ie->Size = sizeof(Q931ie_DateTime);
00282         return 0;
00283 }
00284 
00285 Q931_API L3INT Q931InitIEKeypadFac(Q931ie_KeypadFac *ie)
00286 {
00287         memset(ie, 0, sizeof(*ie));
00288         ie->IEId = Q931ie_KEYPAD_FACILITY;
00289         ie->Size = sizeof(Q931ie_KeypadFac);
00290         return 0;
00291 }
00292 
00293 Q931_API L3INT Q931InitIESignal(Q931ie_Signal *ie)
00294 {
00295         memset(ie, 0, sizeof(*ie));
00296         ie->IEId = Q931ie_SIGNAL;
00297         ie->Size = sizeof(Q931ie_Signal);
00298         return 0;
00299 }
00300 
00301 Q931_API L3INT Q931InitIECallingNum(Q931ie_CallingNum * ie)
00302 {
00303         memset(ie, 0, sizeof(*ie));
00304         ie->IEId = Q931ie_CALLING_PARTY_NUMBER;
00305         ie->Size = sizeof(Q931ie_CallingNum);
00306         return 0;
00307 }
00308 
00309 Q931_API L3INT Q931InitIECallingSub(Q931ie_CallingSub *ie)
00310 {
00311         memset(ie, 0, sizeof(*ie));
00312         ie->IEId = Q931ie_CALLING_PARTY_SUBADDRESS;
00313         ie->Size = sizeof(Q931ie_CallingSub);
00314         return 0;
00315 }
00316 
00317 Q931_API L3INT Q931InitIECalledNum(Q931ie_CalledNum *ie)
00318 {
00319         memset(ie, 0, sizeof(*ie));
00320         ie->IEId = Q931ie_CALLED_PARTY_NUMBER;
00321         ie->Size = sizeof(Q931ie_CalledNum);
00322         return 0;
00323 }
00324 
00325 Q931_API L3INT Q931InitIECalledSub(Q931ie_CalledSub *ie)
00326 {
00327         memset(ie, 0, sizeof(*ie));
00328         ie->IEId = Q931ie_CALLED_PARTY_SUBADDRESS;
00329         ie->Size = sizeof(Q931ie_CalledSub);
00330         return 0;
00331 }
00332 
00333 Q931_API L3INT Q931InitIETransNetSel(Q931ie_TransNetSel *ie)
00334 {
00335         memset(ie, 0, sizeof(*ie));
00336         ie->IEId = Q931ie_TRANSIT_NETWORK_SELECTION;
00337         ie->Size = sizeof(Q931ie_TransNetSel);
00338         return 0;
00339 }
00340 
00341 Q931_API L3INT Q931InitIELLComp(Q931ie_LLComp *ie)
00342 {
00343         memset(ie, 0, sizeof(*ie));
00344         ie->IEId = Q931ie_LOW_LAYER_COMPATIBILITY;
00345         ie->Size = sizeof(Q931ie_LLComp);
00346         return 0;
00347 }
00348 
00349 Q931_API L3INT Q931InitIEHLComp(Q931ie_HLComp *ie)
00350 {
00351         memset(ie, 0, sizeof(*ie));
00352         ie->IEId = Q931ie_HIGH_LAYER_COMPATIBILITY;
00353         ie->Size = sizeof(Q931ie_HLComp);
00354         return 0;
00355 }
00356 
00357 L3INT Q931Disconnect(Q931_TrunkInfo_t *trunk, L3INT iTo, L3INT iCRV, L3INT iCause)
00358 {
00359         /* TODO:  Unhandled paramaters */
00360         (void)trunk;
00361         (void)iTo;
00362         (void)iCRV;
00363         (void)iCause;
00364         return 0;
00365 }
00366 
00367 L3INT Q931Release(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, L3UCHAR causeval)
00368 {
00369         L3UCHAR buf[Q931L4BUF];
00370         Q931mes_Generic *msg = (Q931mes_Generic *)buf;
00371         Q931ie_Cause cause;
00372 
00373         Q931InitMesGeneric(msg);
00374         msg->MesType = Q931mes_RELEASE;
00375         msg->CRV     = Q931CallGetCRV(call);
00376         msg->CRVFlag = (Q931CallGetDirection(call) == Q931_DIRECTION_INBOUND) ? 1 : 0;
00377 
00378         if (causeval) {
00379                 /* Inititalize cause IE */
00380                 cause.IEId = Q931ie_CAUSE;
00381                 cause.Size = sizeof(Q931ie_Cause);
00382                 cause.CodStand = Q931_CODING_ITU;
00383                 cause.Location = 1;
00384                 cause.Recom    = 1;
00385                 cause.Value    = causeval;
00386                 *cause.Diag    = '\0';
00387 
00388                 msg->Cause = Q931AppendIE(msg, (L3UCHAR *)&cause);
00389         }
00390 
00391         return Q931Tx32(trunk, 0, msg, msg->Size);
00392 }
00393 
00394 L3INT Q931ReleaseComplete(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, L3UCHAR causeval)
00395 {
00396         L3UCHAR buf[Q931L4BUF];
00397         Q931mes_Generic *msg = (Q931mes_Generic *)buf;
00398         Q931ie_Cause cause;
00399 
00400         Q931InitMesGeneric(msg);
00401         msg->MesType = Q931mes_RELEASE_COMPLETE;
00402         msg->CRV     = Q931CallGetCRV(call);
00403         msg->CRVFlag = (Q931CallGetDirection(call) == Q931_DIRECTION_INBOUND) ? 1 : 0;
00404 
00405         if (causeval) {
00406                 /* Inititalize cause IE */
00407                 cause.IEId = Q931ie_CAUSE;
00408                 cause.Size = sizeof(Q931ie_Cause);
00409                 cause.CodStand = Q931_CODING_ITU;
00410                 cause.Location = 1;
00411                 cause.Recom    = 1;
00412                 cause.Value    = causeval;
00413                 *cause.Diag    = '\0';
00414 
00415                 msg->Cause = Q931AppendIE(msg, (L3UCHAR *)&cause);
00416         }
00417 
00418         return Q931Tx32(trunk, 0, msg, msg->Size);
00419 }
00420 
00421 L3INT Q931StatusEnquiryResponse(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, L3UCHAR causeval)
00422 {
00423         L3UCHAR buf[Q931L4BUF];
00424         Q931mes_Generic *msg = (Q931mes_Generic *)buf;
00425         Q931ie_CallState state;
00426         Q931ie_Cause cause;
00427 
00428         Q931InitMesGeneric(msg);
00429         msg->MesType = Q931mes_STATUS;
00430         msg->CRV     = Q931CallGetCRV(call);
00431         msg->CRVFlag = (Q931CallGetDirection(call) == Q931_DIRECTION_INBOUND) ? 1 : 0;
00432 
00433         /* Inititalize cause IE */
00434         cause.IEId = Q931ie_CAUSE;
00435         cause.Size = sizeof(Q931ie_Cause);
00436         cause.CodStand = Q931_CODING_ITU;
00437         cause.Location = 1;
00438         cause.Recom    = 1;
00439         cause.Value    = causeval;
00440         *cause.Diag    = '\0';
00441 
00442         msg->Cause = Q931AppendIE(msg, (L3UCHAR *)&cause);
00443 
00444         /* Initialize callstate IE */
00445         state.IEId = Q931ie_CALL_STATE;
00446         state.Size = sizeof(Q931ie_CallState);
00447         state.CodStand  = Q931_CODING_ITU;
00448         state.CallState = (L3UCHAR)(Q931CallGetState(call) & 0xff);
00449 
00450         msg->CallState = Q931AppendIE(msg, (L3UCHAR *)&state);
00451 
00452         return Q931Tx32(trunk, 0, msg, msg->Size);
00453 }
00454 
00464 L3INT Q931CallSendStatus(const struct Q931_Call *call, const L3UCHAR causeval)
00465 {
00466         L3UCHAR buf[Q931L4BUF];
00467         Q931mes_Generic *msg = (Q931mes_Generic *)buf;
00468         Q931_TrunkInfo_t *trunk;
00469         Q931ie_CallState state;
00470         Q931ie_Cause cause;
00471 
00472         trunk = Q931CallGetTrunk(call);
00473 
00474         Q931InitMesGeneric(msg);
00475         msg->MesType = Q931mes_STATUS;
00476         msg->CRVFlag = Q931CallIsOutgoing(call) ? 0 : 1;
00477 
00478         /* Inititalize cause IE */
00479         cause.IEId = Q931ie_CAUSE;
00480         cause.Size = sizeof(Q931ie_Cause);
00481         cause.CodStand = Q931_CODING_ITU;
00482         cause.Location = 1;
00483         cause.Recom    = 1;
00484         cause.Value    = causeval;
00485         *cause.Diag    = '\0';
00486 
00487         msg->Cause = Q931AppendIE(msg, (L3UCHAR *)&cause);
00488 
00489         /* Initialize callstate IE */
00490         state.IEId = Q931ie_CALL_STATE;
00491         state.Size = sizeof(Q931ie_CallState);
00492         state.CodStand  = Q931_CODING_ITU;
00493         state.CallState = (L3UCHAR)(Q931CallGetState(call) & 0xff);
00494 
00495         msg->CallState = Q931AppendIE(msg, (L3UCHAR *) &state);
00496 
00497         return Q931Tx32(trunk, 0, msg, msg->Size);
00498 }
00499 
00500 L3INT Q931AckRestart(Q931_TrunkInfo_t *trunk, Q931mes_Generic *msg)
00501 {
00502         L3INT RetCode;
00503 
00504         msg->MesType = Q931mes_RESTART_ACKNOWLEDGE;
00505         msg->CRVFlag = !(msg->CRVFlag);
00506 
00507         /* Restart Indicator */
00508         if (!msg->RestartInd) {
00509                 Q931ie_RestartInd resind;
00510 
00511                 resind.IEId  = Q931ie_RESTART_INDICATOR;
00512                 resind.Class = 0x06;    /* Restart this interface (?) */
00513 
00514                 msg->RestartInd = Q931AppendIE(msg, (L3UCHAR *)&resind);
00515         }
00516 
00517         RetCode = Q931Proc(trunk, Q931GetGlobalCall(trunk), msg, Q931_MSG_FROM_L4);
00518         return RetCode;
00519 }
00520 
00521 L3INT Q931AckSetup(Q931_TrunkInfo_t *trunk, Q931mes_Generic *msg)
00522 {
00523         msg->MesType = Q931mes_SETUP_ACKNOWLEDGE;
00524 
00525         return Q931Proc(trunk, Q931GetGlobalCall(trunk), msg, Q931_MSG_FROM_L4);
00526 }
00527 
00528 L3INT Q931Send(struct Q931_Call *call, Q931mes_Generic *msg, L3INT bcast)
00529 {
00530         Q931_TrunkInfo_t *trunk = Q931CallGetTrunk(call);
00531 
00532         return Q931Tx32(trunk, bcast, msg, msg->Size);
00533 }
00534 
00535 L3INT Q931AckConnect(struct Q931_Call *call)
00536 {
00537         L3UCHAR buf[Q931L4BUF];
00538         Q931mes_Generic *msg = (Q931mes_Generic *)buf;
00539         Q931_TrunkInfo_t *trunk = Q931CallGetTrunk(call);
00540 
00541         Q931InitMesGeneric(msg);
00542         msg->MesType = Q931mes_CONNECT_ACKNOWLEDGE;
00543         msg->CRVFlag = Q931CallIsOutgoing(call) ? 0 : 1;
00544         msg->CRV     = Q931CallGetCRV(call);
00545 
00546         return Q931Tx32(trunk, 0, msg, msg->Size);
00547 }
00548 
00549 L3INT Q931AckService(Q931_TrunkInfo_t *trunk, Q931mes_Generic *msg)
00550 {
00551         msg->MesType = Q931mes_SERVICE_ACKNOWLEDGE;
00552         if (msg->CRV)
00553                 msg->CRVFlag = !(msg->CRVFlag);
00554 
00555         return Q931Proc(trunk, Q931GetGlobalCall(trunk), msg, Q931_MSG_FROM_L4);
00556 }
00557 
00558 
00559 /***************************************************************************************************************************
00560  *
00561  * Q.931 Simple API
00562  *
00563  ***************************************************************************************************************************/
00564 #if 0
00565 #include <stdarg.h>
00566 
00567 /*
00568  * Tag definition
00569  */
00570 typedef enum {
00571         Q931_TAG_TYPE_END = 0,                  
00572         Q931_TAG_TYPE_SKIP,                     
00574         /* CID */
00575         Q931_TAG_TYPE_CALLED_NUMBER,
00576         Q931_TAG_TYPE_CALLING_NUMBER,
00577 
00578         /* Cause */
00579         Q931_TAG_TYPE_CAUSE_CODE,
00580 
00581         /* Always last */
00582         Q931_TAG_TYPE_MAX
00583 } q931_tag_type_t;
00584 
00585 #define Q931_TAG_IF(cond, x)            !(cond) ? Q931_TAG_TYPE_SKIP : (x)
00586 
00587 #define Q931_TAG_END                    Q931_TAG_TYPE_END
00588 
00589 #define Q931_TAG_CALLED_NUMBER(x)       Q931_TAG_TYPE_CALLED_NUMBER, (x)
00590 #define Q931_TAG_CALLING_NUMBER(x)      Q931_TAG_TYPE_CALLING_NUMBER, (x)
00591 
00592 #define Q931_TAG_CAUSE(x)               Q931_TAG_TYPE_CAUSE_CODE, (x)
00593 
00594 
00595 #define Q931_NUMBER_LEN         32
00596 #define Q931_NAME_LEN           32
00597 
00598 //struct Q931_CallData {
00599 //};
00600 
00601 struct Q931_CallProfile {
00602         L3CHAR  ton;
00603         L3CHAR  screen;
00604         L3CHAR  pres;
00605         L3CHAR  number_plan;
00606         L3CHAR  number[Q931_NUMBER_LEN];
00607         L3CHAR    name[Q931_NAME_LEN];
00608 };
00609 
00610 #define Q931_STRLEN_ZERO(x)     (!x || !x[0])
00611 
00612 enum {
00613         NUMBER_TAG_NUMBER = 0,  
00614         NUMBER_TAG_NAME,        
00615         NUMBER_TAG_TON,         
00616         NUMBER_TAG_NUMPLAN,     
00617         NUMBER_TAG_SCREEN,      
00618         NUMBER_TAG_PRES         
00619 };
00620 
00621 static L3INT Q931Tag_setup_number_params(struct Q931_CallProfile *profile, int opt, ap_list *ap)
00622 {
00623         const char *strval;
00624         const int   intval;
00625 
00626         if (!profile || !ap)
00627                 return -1;
00628 
00629         switch (opt) {
00630         case NUMBER_TAG_NUMBER:
00631                 strval = va_arg(*ap, char *);
00632                 if (!Q931_STRLEN_ZERO(strval))
00633                         strncpy(profile->number, strval, Q931_NUMBER_LEN);
00634                 break;
00635 
00636         case NUMBER_TAG_NAME:
00637                 strval = va_arg(*ap, char *);
00638                 if (!Q931_STRLEN_ZERO(strval))
00639                         strncpy(profile->name, strval, Q931_NAME_LEN);
00640                 break;
00641 
00642         case NUMBER_TAG_TON:
00643                 intval = va_arg(*ap, int);
00644                 if (intval < 0 || intval >= Q931_TON_RESERVED)
00645                         return -1;
00646 
00647                 profile->ton = intval;
00648                 break;
00649 
00650         case NUMBER_TAG_NUMPLAN:
00651                 intval = va_arg(*ap, int);
00652                 if (intval < 0 || intval >= Q931_NUMPLAN_RESERVED)
00653                         return -1;
00654 
00655                 profile->number_plan = intval;
00656                 break;
00657 
00658         case NUMBER_TAG_SCREEN:
00659                 intval = va_arg(*ap, int);
00660                 if (intval < 0 || intval > Q931_SCREEN_NETWORK)
00661                         return -1;
00662 
00663                 profile->screen = intval;
00664                 break;
00665 
00666         case NUMBER_TAG_PRES:
00667                 intval = va_arg(*ap, int);
00668                 if (intval < 0 || intval >= Q931_PRES_RESERVED)
00669                         return -1;
00670 
00671                 profile->pres = intval;
00672                 break;
00673 
00674         default:
00675                 return -1;
00676         }
00677 
00678         return 0;
00679 }
00680 
00681 L3INT Q931Simple_Setup(Q931_TrunkInfo_t *trunk, struct Q931_Call **call, ...)
00682 {
00683         struct Q931_Call *new_call = NULL;
00684         va_list ap;
00685         q931_tag_type_t tag;
00686         int ret = 0;
00687 
00688         if (!trunk || !call)
00689                 return -1;
00690 
00691         /*
00692          * Allocate + init new outgoing call
00693          */
00694         new_call = Q931CallNew(trunk);
00695         if (!new_call)
00696                 return -1;
00697 
00698 #if __TODO__
00699         /* Probably going to put all call parameters into a sub structure */
00700         memset(&call->called_number,  0, sizeof(struct Q931_CallProfile));
00701         memset(&call->calling_number, 0, sizeof(struct Q931_CallProfile));
00702 #endif
00703 
00704         /*
00705          * Parse tags
00706          */
00707         va_start(ap, call);
00708         while (!ret) {
00709                 tag = va_arg(ap, q931_tag_type_t);
00710                 if (tag == Q931_TAG_TYPE_END)
00711                         break;
00712 
00713                 switch (tag) {
00714                 case Q931_TAG_TYPE_SKIP:
00715                         continue;
00716 
00717                 case Q931_TAG_TYPE_CALLED_NUMBER:
00718 //                      ret = Q931Tag_setup_number_params(&new_call->called_number,  NUMBER_TAG_NUMBER, &ap);
00719                         break;
00720 
00721                 case Q931_TAG_TYPE_CALLING_NUMBER:
00722 //                      ret = Q931Tag_setup_number_params(&new_call->calling_number, NUMBER_TAG_NUMBER, &ap);
00723                         break;
00724 
00725                 default:
00726                         Q931Log(trunk, Q931_LOG_ERROR, "Unknown/invalid tag %d\n", tag);
00727                         ret = -1;
00728                 }
00729         }
00730         va_end(ap);
00731 
00732         if (ret < 0) {
00733                 Q931CallRelease(new_call);
00734                 return ret;
00735         }
00736 
00737         /*
00738          * Minimum requirements: Destination number
00739          * (unless we're going to support overlap dialing)
00740          */
00741 #if __TODO__
00742         if (Q931_STRLEN_ZERO(call->called_number.number)) {
00743                 Q931Log(trunk, Q931_LOG_ERROR, "Need a destination number\n");
00744                 goto error;
00745         }
00746 #endif
00747 
00748         *call = new_call;
00749         return ret;
00750 
00751 error:
00752         Q931Release(new_call);
00753         return -1;
00754 }
00755 
00756 L3INT Q931Simple_Hangup(struct Q931_Call *call, ...)
00757 {
00758         Q931_TrunkInfo_t *trunk = NULL;
00759         va_list ap;
00760         q931_tag_type_t tag;
00761         int ret = 0;
00762         int intval;
00763         int cause = Q850_CAUSE_NORMAL_CLEARING;
00764 
00765         if (!call)
00766                 return -1;
00767 
00768         if (!(trunk = Q931CallGetTrunk(call)))
00769                 return -1;
00770 
00771         /*
00772          * Parse tags
00773          */
00774         va_start(ap, call);
00775 
00776         while (!ret) {
00777                 tag = va_arg(ap, q931_tag_type_t);
00778                 if (tag == Q931_TAG_TYPE_END)
00779                         break;
00780 
00781                 switch (tag) {
00782                 case Q931_TAG_TYPE_SKIP:
00783                         continue;
00784 
00785                 case Q931_TAG_TYPE_CAUSE_CODE:
00786                         intval = va_arg(ap, int);
00787                         if (intval <= Q850_CAUSE_NONE || intval > Q850_CAUSE_INTERWORKING) {
00788                                 ret = -1;
00789                                 break;
00790                         }
00791 
00792                         cause = intval;
00793                         break;
00794 
00795                 default:
00796                         Q931Log(trunk, Q931_LOG_ERROR, "Unknown/invalid tag %d\n", tag);
00797                         ret = -1;
00798                 }
00799         }
00800         va_end(ap);
00801 
00802         if (ret < 0)
00803                 return ret;
00804 
00805         /*
00806          * Hangup
00807          * --- TODO ---
00808          */
00809 
00810         return ret;
00811 }
00812 #endif /* 0 */