libisdn
|
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 */