00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "asterisk.h"
00050
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 313188 $")
00052
00053 #include <stdio.h>
00054 #include <string.h>
00055 #if defined(__NetBSD__) || defined(__FreeBSD__)
00056 #include <pthread.h>
00057 #include <signal.h>
00058 #else
00059 #include <sys/signal.h>
00060 #endif
00061 #include <errno.h>
00062 #include <stdlib.h>
00063 #if !defined(SOLARIS) && !defined(__FreeBSD__)
00064 #include <stdint.h>
00065 #endif
00066 #include <unistd.h>
00067 #include <sys/ioctl.h>
00068 #include <math.h>
00069 #include <ctype.h>
00070
00071 #ifdef HAVE_PRI
00072 #include <libpri.h>
00073 #endif
00074
00075 #ifdef HAVE_OPENR2
00076 #include <openr2.h>
00077 #endif
00078
00079 #include "asterisk/lock.h"
00080 #include "asterisk/channel.h"
00081 #include "asterisk/config.h"
00082 #include "asterisk/logger.h"
00083 #include "asterisk/module.h"
00084 #include "asterisk/pbx.h"
00085 #include "asterisk/options.h"
00086 #include "asterisk/file.h"
00087 #include "asterisk/ulaw.h"
00088 #include "asterisk/alaw.h"
00089 #include "asterisk/callerid.h"
00090 #include "asterisk/adsi.h"
00091 #include "asterisk/cli.h"
00092 #include "asterisk/cdr.h"
00093 #include "asterisk/features.h"
00094 #include "asterisk/musiconhold.h"
00095 #include "asterisk/say.h"
00096 #include "asterisk/tdd.h"
00097 #include "asterisk/app.h"
00098 #include "asterisk/dsp.h"
00099 #include "asterisk/astdb.h"
00100 #include "asterisk/manager.h"
00101 #include "asterisk/causes.h"
00102 #include "asterisk/term.h"
00103 #include "asterisk/utils.h"
00104 #include "asterisk/transcap.h"
00105 #include "asterisk/stringfields.h"
00106 #include "asterisk/abstract_jb.h"
00107 #include "asterisk/smdi.h"
00108 #include "asterisk/astobj.h"
00109 #define SMDI_MD_WAIT_TIMEOUT 1500
00110
00111 #include "asterisk/dahdi_compat.h"
00112 #include "asterisk/tonezone_compat.h"
00113
00114
00115 static struct ast_jb_conf default_jbconf =
00116 {
00117 .flags = 0,
00118 .max_size = -1,
00119 .resync_threshold = -1,
00120 .impl = ""
00121 };
00122 static struct ast_jb_conf global_jbconf;
00123
00124 #ifndef DAHDI_TONEDETECT
00125
00126 #define DAHDI_EVENT_DTMFDOWN 0
00127 #define DAHDI_EVENT_DTMFUP 0
00128 #endif
00129
00130
00131 #undef SUPPORT_USERUSER
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 #define FORCE_RESTART_UNAVAIL_CHANS 1
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 #define DEFAULT_CIDRINGS 1
00168
00169 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00170
00171
00172 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
00173
00174 static const char tdesc[] = "DAHDI Telephony Driver"
00175 #ifdef HAVE_PRI
00176 " w/PRI"
00177 #endif
00178
00179 #ifdef HAVE_OPENR2
00180 " w/OPENR2"
00181 #endif
00182 ;
00183
00184 #define SIG_EM DAHDI_SIG_EM
00185 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00186 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00187 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00188 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00189 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00190 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00191 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00192 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00193 #define SIG_FXSLS DAHDI_SIG_FXSLS
00194 #define SIG_FXSGS DAHDI_SIG_FXSGS
00195 #define SIG_FXSKS DAHDI_SIG_FXSKS
00196 #define SIG_FXOLS DAHDI_SIG_FXOLS
00197 #define SIG_FXOGS DAHDI_SIG_FXOGS
00198 #define SIG_FXOKS DAHDI_SIG_FXOKS
00199 #define SIG_PRI DAHDI_SIG_CLEAR
00200 #define SIG_MFCR2 DAHDI_SIG_CAS
00201 #define SIG_SF DAHDI_SIG_SF
00202 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00203 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00204 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00205 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00206 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00207 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00208 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00209
00210 #define NUM_SPANS 32
00211 #define NUM_DCHANS 4
00212 #define MAX_CHANNELS 672
00213
00214 #define CHAN_PSEUDO -2
00215
00216 #define DCHAN_PROVISIONED (1 << 0)
00217 #define DCHAN_NOTINALARM (1 << 1)
00218 #define DCHAN_UP (1 << 2)
00219
00220 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00221
00222
00223 #define DAHDI_OVERLAPDIAL_NONE 0
00224 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00225 #define DAHDI_OVERLAPDIAL_INCOMING 2
00226 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00227
00228 static char defaultcic[64] = "";
00229 static char defaultozz[64] = "";
00230
00231 static char progzone[10] = "";
00232
00233 static int distinctiveringaftercid = 0;
00234
00235 static int numbufs = 4;
00236 static int dtmfcid_level = 256;
00237
00238 #ifdef HAVE_PRI
00239 static struct ast_channel inuse;
00240 #ifdef PRI_GETSET_TIMERS
00241 static int pritimers[PRI_MAX_TIMERS];
00242 #endif
00243 static int pridebugfd = -1;
00244 static char pridebugfilename[1024] = "";
00245 #endif
00246
00247
00248 static int firstdigittimeout = 16000;
00249
00250
00251 static int gendigittimeout = 8000;
00252
00253
00254 static int matchdigittimeout = 3000;
00255
00256
00257 AST_MUTEX_DEFINE_STATIC(iflock);
00258
00259
00260 static int ifcount = 0;
00261
00262 #ifdef HAVE_PRI
00263 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00264 #endif
00265
00266
00267
00268 AST_MUTEX_DEFINE_STATIC(monlock);
00269
00270
00271
00272 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00273 static ast_cond_t ss_thread_complete;
00274 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00275 AST_MUTEX_DEFINE_STATIC(restart_lock);
00276 static int ss_thread_count = 0;
00277 static int num_restart_pending = 0;
00278
00279 static int restart_monitor(void);
00280
00281 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00282
00283 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00284
00285 #define SIG_PRI_LIB_HANDLE_CASES \
00286 SIG_PRI
00287
00288
00289 static inline int dahdi_get_event(int fd)
00290 {
00291 int j;
00292 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00293 return -1;
00294 return j;
00295 }
00296
00297
00298 static inline int dahdi_wait_event(int fd)
00299 {
00300 int i, j = 0;
00301 i = DAHDI_IOMUX_SIGEVENT;
00302 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00303 return -1;
00304 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00305 return -1;
00306 return j;
00307 }
00308
00309
00310 #define READ_SIZE 160
00311
00312 #define MASK_AVAIL (1 << 0)
00313 #define MASK_INUSE (1 << 1)
00314
00315 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00316 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00317 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00318 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00319 #define MIN_MS_SINCE_FLASH ((2000) )
00320 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00321
00322 struct dahdi_pvt;
00323
00324
00325
00326
00327
00328 static int ringt_base = DEFAULT_RINGT;
00329
00330 #ifdef HAVE_OPENR2
00331
00332 struct dahdi_mfcr2 {
00333 pthread_t master;
00334 openr2_context_t *protocol_context;
00335 struct dahdi_pvt *pvts[MAX_CHANNELS];
00336 int numchans;
00337 };
00338
00339 static struct dahdi_mfcr2 r2links[NUM_SPANS];
00340 static openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN;
00341 static int mfcr2_cur_mfback_timeout = -1;
00342 static int mfcr2_cur_metering_pulse_timeout = -1;
00343 static int mfcr2_cur_max_ani = 10;
00344 static int mfcr2_cur_max_dnis = 4;
00345 static int mfcr2_cur_get_ani_first = -1;
00346 static int mfcr2_cur_skip_category = -1;
00347 static int mfcr2_cur_context_index = 0;
00348 static int mfcr2_cur_call_files = 0;
00349 static int mfcr2_cur_allow_collect_calls = 0;
00350 static int mfcr2_cur_accept_on_offer = 1;
00351 static int mfcr2_cur_charge_calls = 1;
00352 static int mfcr2_cur_forced_release = 0;
00353 static int mfcr2_cur_double_answer = 0;
00354 static int mfcr2_cur_immediate_accept = -1;
00355
00356 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00357 static int mfcr2_cur_dtmf_dialing = -1;
00358 static int mfcr2_cur_dtmf_detection = -1;
00359 static int mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
00360 static int mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
00361 #endif
00362 static char mfcr2_cur_logdir[OR2_MAX_PATH];
00363 static char mfcr2_cur_r2proto_file[OR2_MAX_PATH];
00364 static openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
00365 static openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
00366
00367 #endif
00368
00369 #ifdef HAVE_PRI
00370
00371 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00372 #define PRI_CHANNEL(p) ((p) & 0xff)
00373 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00374 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00375
00376
00377 enum dahdi_call_level {
00378
00379 DAHDI_CALL_LEVEL_IDLE,
00380
00381 DAHDI_CALL_LEVEL_SETUP,
00382
00383 DAHDI_CALL_LEVEL_OVERLAP,
00384
00385 DAHDI_CALL_LEVEL_PROCEEDING,
00386
00387 DAHDI_CALL_LEVEL_ALERTING,
00388
00389 DAHDI_CALL_LEVEL_CONNECT,
00390 };
00391
00392 struct dahdi_pri {
00393 pthread_t master;
00394 ast_mutex_t lock;
00395 char idleext[AST_MAX_EXTENSION];
00396 char idlecontext[AST_MAX_CONTEXT];
00397 char idledial[AST_MAX_EXTENSION];
00398 int minunused;
00399 int minidle;
00400 int nodetype;
00401 int switchtype;
00402 int nsf;
00403 int dialplan;
00404 int localdialplan;
00405 char internationalprefix[10];
00406 char nationalprefix[10];
00407 char localprefix[20];
00408 char privateprefix[20];
00409 char unknownprefix[20];
00410 int dchannels[NUM_DCHANS];
00411 int trunkgroup;
00412 int mastertrunkgroup;
00413 int prilogicalspan;
00414 int numchans;
00415 int overlapdial;
00416 int facilityenable;
00417 struct pri *dchans[NUM_DCHANS];
00418 int dchanavail[NUM_DCHANS];
00419 struct pri *pri;
00420
00421 int debug;
00422 int fds[NUM_DCHANS];
00423
00424 int offset;
00425
00426 int span;
00427
00428 int resetting;
00429
00430 int resetpos;
00431 #ifdef HAVE_PRI_INBANDDISCONNECT
00432 unsigned int inbanddisconnect:1;
00433 #endif
00434
00435 unsigned int no_d_channels:1;
00436 time_t lastreset;
00437 long resetinterval;
00438 struct dahdi_pvt *pvts[MAX_CHANNELS];
00439 struct dahdi_pvt *crvs;
00440 struct dahdi_pvt *crvend;
00441 };
00442
00443
00444 static struct dahdi_pri pris[NUM_SPANS];
00445
00446 #if 0
00447 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00448 #else
00449 #define DEFAULT_PRI_DEBUG 0
00450 #endif
00451
00452 static inline void pri_rel(struct dahdi_pri *pri)
00453 {
00454 ast_mutex_unlock(&pri->lock);
00455 }
00456
00457 #else
00458
00459 struct dahdi_pri;
00460 #endif
00461
00462 #define SUB_REAL 0
00463 #define SUB_CALLWAIT 1
00464 #define SUB_THREEWAY 2
00465
00466
00467 #define POLARITY_IDLE 0
00468 #define POLARITY_REV 1
00469
00470
00471 static struct dahdi_distRings drings;
00472
00473 struct distRingData {
00474 int ring[3];
00475 };
00476 struct ringContextData {
00477 char contextData[AST_MAX_CONTEXT];
00478 };
00479 struct dahdi_distRings {
00480 struct distRingData ringnum[3];
00481 struct ringContextData ringContext[3];
00482 };
00483
00484 static char *subnames[] = {
00485 "Real",
00486 "Callwait",
00487 "Threeway"
00488 };
00489
00490 struct dahdi_subchannel {
00491 int dfd;
00492 struct ast_channel *owner;
00493 int chan;
00494 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00495 struct ast_frame f;
00496 unsigned int needringing:1;
00497 unsigned int needbusy:1;
00498 unsigned int needcongestion:1;
00499 unsigned int needcallerid:1;
00500 unsigned int needanswer:1;
00501 unsigned int needflash:1;
00502 unsigned int needhold:1;
00503 unsigned int needunhold:1;
00504 unsigned int linear:1;
00505 unsigned int inthreeway:1;
00506 struct dahdi_confinfo curconf;
00507 };
00508
00509 #define CONF_USER_REAL (1 << 0)
00510 #define CONF_USER_THIRDCALL (1 << 1)
00511
00512 #define MAX_SLAVES 4
00513
00514 static struct dahdi_pvt {
00515 ast_mutex_t lock;
00516 struct ast_channel *owner;
00517
00518
00519 struct dahdi_subchannel sub_unused;
00520 struct dahdi_subchannel subs[3];
00521 struct dahdi_confinfo saveconf;
00522
00523 struct dahdi_pvt *slaves[MAX_SLAVES];
00524 struct dahdi_pvt *master;
00525 int inconference;
00526
00527 int bufsize;
00528 int buf_no;
00529 int buf_policy;
00530 int sig;
00531
00532
00533
00534
00535 int radio;
00536 int outsigmod;
00537 int oprmode;
00538 struct dahdi_pvt *oprpeer;
00539
00540 float rxgain;
00541
00542 float txgain;
00543 int tonezone;
00544 struct dahdi_pvt *next;
00545 struct dahdi_pvt *prev;
00546
00547
00548
00549
00550
00551
00552
00553 unsigned int adsi:1;
00554
00555
00556
00557
00558
00559 unsigned int answeronpolarityswitch:1;
00560
00561
00562
00563
00564
00565 unsigned int busydetect:1;
00566
00567
00568
00569
00570
00571 unsigned int callreturn:1;
00572
00573
00574
00575
00576
00577
00578 unsigned int callwaiting:1;
00579
00580
00581
00582
00583 unsigned int callwaitingcallerid:1;
00584
00585
00586
00587
00588
00589
00590 unsigned int cancallforward:1;
00591
00592
00593
00594
00595 unsigned int canpark:1;
00596
00597 unsigned int confirmanswer:1;
00598
00599
00600
00601
00602 unsigned int destroy:1;
00603 unsigned int didtdd:1;
00604
00605 unsigned int dialednone:1;
00606
00607 unsigned int dialing:1;
00608
00609 unsigned int digital:1;
00610
00611 unsigned int dnd:1;
00612
00613 unsigned int echobreak:1;
00614
00615
00616
00617
00618
00619 unsigned int echocanbridged:1;
00620
00621 unsigned int echocanon:1;
00622
00623 unsigned int faxhandled:1;
00624
00625 unsigned int bufferoverrideinuse:1;
00626
00627 unsigned int firstradio:1;
00628
00629
00630
00631
00632 unsigned int hanguponpolarityswitch:1;
00633
00634 unsigned int hardwaredtmf:1;
00635
00636
00637
00638
00639
00640
00641 unsigned int hidecallerid:1;
00642
00643
00644
00645
00646
00647 unsigned int hidecalleridname:1;
00648
00649 unsigned int ignoredtmf:1;
00650
00651
00652
00653
00654
00655 unsigned int immediate:1;
00656
00657 unsigned int inalarm:1;
00658 unsigned int unknown_alarm:1;
00659
00660 unsigned int mate:1;
00661 #if defined(HAVE_PRI)
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 unsigned int allocated:1;
00673 #endif
00674
00675 unsigned int outgoing:1;
00676
00677
00678
00679
00680
00681
00682 unsigned int permcallwaiting:1;
00683
00684
00685
00686
00687 unsigned int permhidecallerid:1;
00688
00689
00690
00691
00692 unsigned int priindication_oob:1;
00693
00694
00695
00696
00697 unsigned int priexclusive:1;
00698
00699
00700
00701
00702 unsigned int pulse:1;
00703
00704 unsigned int pulsedial:1;
00705 unsigned int restartpending:1;
00706
00707
00708
00709
00710
00711 unsigned int restrictcid:1;
00712
00713
00714
00715
00716 unsigned int threewaycalling:1;
00717
00718
00719
00720
00721
00722
00723
00724
00725 unsigned int transfer:1;
00726
00727
00728
00729
00730
00731
00732
00733 unsigned int use_callerid:1;
00734
00735
00736
00737
00738
00739
00740 unsigned int use_callingpres:1;
00741
00742
00743
00744
00745
00746 unsigned int usedistinctiveringdetection:1;
00747
00748
00749
00750
00751 unsigned int dahditrcallerid:1;
00752
00753
00754
00755
00756 unsigned int transfertobusy:1;
00757
00758
00759
00760
00761 unsigned int use_smdi:1;
00762 #if defined(HAVE_PRI)
00763
00764 unsigned int alreadyhungup:1;
00765
00766
00767
00768
00769 unsigned int isidlecall:1;
00770
00771 unsigned int progress:1;
00772
00773
00774
00775
00776 unsigned int resetting:1;
00777
00778
00779 enum dahdi_call_level call_level;
00780 #endif
00781
00782 struct ast_smdi_interface *smdi_iface;
00783
00784
00785 struct dahdi_distRings drings;
00786
00787
00788
00789
00790
00791 char context[AST_MAX_CONTEXT];
00792
00793
00794
00795 char defcontext[AST_MAX_CONTEXT];
00796
00797 char exten[AST_MAX_EXTENSION];
00798
00799
00800
00801
00802 char language[MAX_LANGUAGE];
00803
00804
00805
00806
00807 char mohinterpret[MAX_MUSICCLASS];
00808
00809
00810
00811
00812 char mohsuggest[MAX_MUSICCLASS];
00813 #ifdef PRI_ANI
00814
00815 char cid_ani[AST_MAX_EXTENSION];
00816 #endif
00817
00818 char cid_num[AST_MAX_EXTENSION];
00819
00820 int cid_ton;
00821
00822 char cid_name[AST_MAX_EXTENSION];
00823
00824 char lastcid_num[AST_MAX_EXTENSION];
00825
00826 char lastcid_name[AST_MAX_EXTENSION];
00827 char *origcid_num;
00828 char *origcid_name;
00829
00830 char callwait_num[AST_MAX_EXTENSION];
00831
00832 char callwait_name[AST_MAX_EXTENSION];
00833
00834 char rdnis[AST_MAX_EXTENSION];
00835
00836 char dnid[AST_MAX_EXTENSION];
00837
00838
00839
00840
00841 ast_group_t group;
00842
00843 int law;
00844 int confno;
00845 int confusers;
00846 int propconfno;
00847
00848
00849
00850
00851 ast_group_t callgroup;
00852
00853
00854
00855
00856 ast_group_t pickupgroup;
00857 int channel;
00858 int span;
00859 time_t guardtime;
00860 int cid_signalling;
00861 int cid_start;
00862 int dtmfcid_holdoff_state;
00863 struct timeval dtmfcid_delay;
00864 int callingpres;
00865 int callwaitingrepeat;
00866 int cidcwexpire;
00867 int cid_suppress_expire;
00868
00869 unsigned char *cidspill;
00870
00871 int cidpos;
00872
00873 int cidlen;
00874
00875 int ringt;
00876
00877
00878
00879
00880 int ringt_base;
00881
00882
00883
00884
00885
00886
00887 int stripmsd;
00888
00889
00890
00891
00892
00893
00894 int callwaitcas;
00895
00896 int callwaitrings;
00897
00898 int echocancel;
00899
00900
00901
00902
00903 int echotraining;
00904
00905 char echorest[20];
00906
00907
00908
00909
00910 int busycount;
00911
00912
00913
00914
00915 int busycompare;
00916
00917
00918
00919
00920 int busytonelength;
00921
00922
00923
00924
00925 int busyquietlength;
00926
00927
00928
00929
00930 int busyfuzziness;
00931
00932
00933
00934
00935 int silencethreshold;
00936
00937
00938
00939
00940 int callprogress;
00941 struct timeval flashtime;
00942
00943 struct ast_dsp *dsp;
00944
00945
00946 struct dahdi_dialoperation dop;
00947 int whichwink;
00948
00949 char finaldial[64];
00950 char accountcode[AST_MAX_ACCOUNT_CODE];
00951 int amaflags;
00952 struct tdd_state *tdd;
00953
00954 char call_forward[AST_MAX_EXTENSION];
00955
00956
00957
00958
00959 char mailbox[AST_MAX_EXTENSION];
00960
00961 char dialdest[256];
00962
00963 int onhooktime;
00964
00965 int msgstate;
00966 int distinctivering;
00967 int cidrings;
00968 int dtmfrelax;
00969
00970 int fake_event;
00971
00972
00973
00974
00975 int polarityonanswerdelay;
00976
00977 struct timeval polaritydelaytv;
00978
00979
00980
00981
00982 int sendcalleridafter;
00983 #ifdef HAVE_PRI
00984
00985 struct dahdi_pri *pri;
00986
00987 struct dahdi_pvt *bearer;
00988
00989 struct dahdi_pvt *realcall;
00990
00991 q931_call *call;
00992
00993 int prioffset;
00994
00995 int logicalspan;
00996 #endif
00997
00998 #ifdef HAVE_OPENR2
00999 int mfcr2call;
01000 int mfcr2block;
01001 struct dahdi_mfcr2 *mfcr2;
01002 openr2_chan_t *r2chan;
01003 openr2_calling_party_category_t mfcr2_recvd_category;
01004 openr2_calling_party_category_t mfcr2_category;
01005 int mfcr2_accept_on_offer;
01006 int mfcr2_charge_calls;
01007 int mfcr2_allow_collect_calls;
01008 int mfcr2_forced_release;
01009 int mfcr2_dnis_index;
01010 int mfcr2_ani_index;
01011 int mfcr2_dnis_matched;
01012 int mfcr2_call_accepted;
01013 #endif
01014
01015
01016 int polarity;
01017
01018 int dsp_features;
01019
01020 char begindigit;
01021 } *iflist = NULL, *ifend = NULL;
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 struct dahdi_chan_conf {
01034 struct dahdi_pvt chan;
01035 #ifdef HAVE_PRI
01036 struct dahdi_pri pri;
01037 #endif
01038 struct dahdi_params timing;
01039
01040
01041
01042
01043
01044 char smdi_port[SMDI_MAX_FILENAME_LEN];
01045 };
01046
01047
01048 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01049
01050
01051
01052 struct dahdi_chan_conf conf = {
01053 #ifdef HAVE_PRI
01054 .pri = {
01055 .nsf = PRI_NSF_NONE,
01056 .switchtype = PRI_SWITCH_NI2,
01057 .dialplan = PRI_NATIONAL_ISDN + 1,
01058 .localdialplan = PRI_NATIONAL_ISDN + 1,
01059 .nodetype = PRI_CPE,
01060
01061 .minunused = 2,
01062 .idleext = "",
01063 .idledial = "",
01064 .internationalprefix = "",
01065 .nationalprefix = "",
01066 .localprefix = "",
01067 .privateprefix = "",
01068 .unknownprefix = "",
01069
01070 .resetinterval = 3600
01071 },
01072 #endif
01073 .chan = {
01074 .context = "default",
01075 .cid_num = "",
01076 .cid_name = "",
01077 .mohinterpret = "default",
01078 .mohsuggest = "",
01079 .transfertobusy = 1,
01080
01081 .cid_signalling = CID_SIG_BELL,
01082 .cid_start = CID_START_RING,
01083 .dahditrcallerid = 0,
01084 .use_callerid = 1,
01085 .sig = -1,
01086 .outsigmod = -1,
01087
01088 .tonezone = -1,
01089
01090 .echocancel = 1,
01091
01092 .busycount = 3,
01093 .busycompare = 0,
01094 .busytonelength = 0,
01095 .busyquietlength = 0,
01096 .busyfuzziness = 0,
01097 .silencethreshold = 0,
01098
01099 .accountcode = "",
01100
01101 .mailbox = "",
01102
01103
01104 .polarityonanswerdelay = 600,
01105
01106 .sendcalleridafter = DEFAULT_CIDRINGS,
01107
01108 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01109 .buf_no = numbufs,
01110 },
01111 .timing = {
01112 .prewinktime = -1,
01113 .preflashtime = -1,
01114 .winktime = -1,
01115 .flashtime = -1,
01116 .starttime = -1,
01117 .rxwinktime = -1,
01118 .rxflashtime = -1,
01119 .debouncetime = -1
01120 },
01121 .smdi_port = "/dev/ttyS0",
01122 };
01123
01124 return conf;
01125 }
01126
01127
01128 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01129 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01130 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01131 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01132 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01133 static int dahdi_hangup(struct ast_channel *ast);
01134 static int dahdi_answer(struct ast_channel *ast);
01135 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01136 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01137 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01138 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01139 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01140 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01141 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
01142 static int dahdi_func_write(struct ast_channel *chan, char *function, char *data, const char *value);
01143
01144 static const struct ast_channel_tech dahdi_tech = {
01145 .type = "DAHDI",
01146 .description = tdesc,
01147 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01148 .requester = dahdi_request,
01149 .send_digit_begin = dahdi_digit_begin,
01150 .send_digit_end = dahdi_digit_end,
01151 .send_text = dahdi_sendtext,
01152 .call = dahdi_call,
01153 .hangup = dahdi_hangup,
01154 .answer = dahdi_answer,
01155 .read = dahdi_read,
01156 .write = dahdi_write,
01157 .bridge = dahdi_bridge,
01158 .exception = dahdi_exception,
01159 .indicate = dahdi_indicate,
01160 .fixup = dahdi_fixup,
01161 .setoption = dahdi_setoption,
01162 .func_channel_read = dahdi_func_read,
01163 .func_channel_write = dahdi_func_write,
01164 };
01165
01166 static const struct ast_channel_tech zap_tech = {
01167 .type = "Zap",
01168 .description = tdesc,
01169 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01170 .requester = dahdi_request,
01171 .send_digit_begin = dahdi_digit_begin,
01172 .send_digit_end = dahdi_digit_end,
01173 .send_text = dahdi_sendtext,
01174 .call = dahdi_call,
01175 .hangup = dahdi_hangup,
01176 .answer = dahdi_answer,
01177 .read = dahdi_read,
01178 .write = dahdi_write,
01179 .bridge = dahdi_bridge,
01180 .exception = dahdi_exception,
01181 .indicate = dahdi_indicate,
01182 .fixup = dahdi_fixup,
01183 .setoption = dahdi_setoption,
01184 .func_channel_read = dahdi_func_read,
01185 .func_channel_write = dahdi_func_write,
01186 };
01187
01188 static const struct ast_channel_tech *chan_tech;
01189
01190 #ifdef HAVE_PRI
01191 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01192 #else
01193 #define GET_CHANNEL(p) ((p)->channel)
01194 #endif
01195
01196 struct dahdi_pvt *round_robin[32];
01197
01198 #ifdef HAVE_PRI
01199 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01200 {
01201 int res;
01202
01203 do {
01204 res = ast_mutex_trylock(&pri->lock);
01205 if (res) {
01206 DEADLOCK_AVOIDANCE(&pvt->lock);
01207 }
01208 } while (res);
01209
01210 if (pri->master != AST_PTHREADT_NULL)
01211 pthread_kill(pri->master, SIGURG);
01212 return 0;
01213 }
01214 #endif
01215
01216 #define NUM_CADENCE_MAX 25
01217 static int num_cadence = 4;
01218 static int user_has_defined_cadences = 0;
01219
01220 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01221 { { 125, 125, 2000, 4000 } },
01222 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01223 { { 125, 125, 125, 125, 125, 4000 } },
01224 { { 1000, 500, 2500, 5000 } },
01225 };
01226
01227
01228
01229
01230
01231 static int cidrings[NUM_CADENCE_MAX] = {
01232 2,
01233 4,
01234 3,
01235 2,
01236 };
01237
01238 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01239 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01240
01241 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01242 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01243
01244 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
01245 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
01246 {
01247 int res;
01248 if (p->subs[SUB_REAL].owner == ast)
01249 res = 0;
01250 else if (p->subs[SUB_CALLWAIT].owner == ast)
01251 res = 1;
01252 else if (p->subs[SUB_THREEWAY].owner == ast)
01253 res = 2;
01254 else {
01255 res = -1;
01256 if (!nullok)
01257 ast_log(LOG_WARNING,
01258 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
01259 ast ? ast->name : "", p->channel, fname, line);
01260 }
01261 return res;
01262 }
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
01280 {
01281 for (;;) {
01282 if (!pvt->subs[sub_idx].owner) {
01283
01284 break;
01285 }
01286 if (!ast_mutex_trylock(&pvt->subs[sub_idx].owner->lock)) {
01287
01288 break;
01289 }
01290
01291 DEADLOCK_AVOIDANCE(&pvt->lock);
01292 }
01293 }
01294
01295 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01296 {
01297 #ifdef HAVE_PRI
01298 if (pri)
01299 ast_mutex_unlock(&pri->lock);
01300 #endif
01301 dahdi_lock_sub_owner(p, a);
01302 if (p->subs[a].owner) {
01303 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01304 ast_mutex_unlock(&p->subs[a].owner->lock);
01305 }
01306 #ifdef HAVE_PRI
01307 if (pri)
01308 ast_mutex_lock(&pri->lock);
01309 #endif
01310 }
01311
01312 #ifdef HAVE_PRI
01313 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
01314 #else
01315 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
01316 #endif
01317 {
01318
01319 #ifdef HAVE_PRI
01320 if (pri)
01321 ast_mutex_unlock(&pri->lock);
01322 #endif
01323 for (;;) {
01324 if (p->owner) {
01325 if (ast_mutex_trylock(&p->owner->lock)) {
01326 DEADLOCK_AVOIDANCE(&p->lock);
01327 } else {
01328 ast_queue_frame(p->owner, f);
01329 ast_mutex_unlock(&p->owner->lock);
01330 break;
01331 }
01332 } else
01333 break;
01334 }
01335 #ifdef HAVE_PRI
01336 if (pri)
01337 ast_mutex_lock(&pri->lock);
01338 #endif
01339 }
01340
01341 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability);
01342 #ifdef HAVE_OPENR2
01343 static void init_mfcr2_globals(void)
01344 {
01345 int r;
01346 mfcr2_cur_context_index = 0;
01347 mfcr2_cur_variant = OR2_VAR_UNKNOWN;
01348 mfcr2_cur_mfback_timeout = -1;
01349 mfcr2_cur_metering_pulse_timeout = -1;
01350 mfcr2_cur_max_ani = 10;
01351 mfcr2_cur_max_dnis = 4;
01352 mfcr2_cur_get_ani_first = -1;
01353 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01354 mfcr2_cur_dtmf_dialing = -1;
01355 mfcr2_cur_dtmf_detection = -1;
01356 mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
01357 mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
01358 #endif
01359 mfcr2_cur_skip_category = -1;
01360 mfcr2_cur_call_files = 0;
01361 mfcr2_cur_allow_collect_calls = 0;
01362 mfcr2_cur_forced_release = 0;
01363 mfcr2_cur_double_answer = 0;
01364 mfcr2_cur_immediate_accept = -1;
01365 mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
01366 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
01367 memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir));
01368 memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file));
01369 memset(r2links, 0, sizeof(r2links));
01370 for (r = 0; r < NUM_SPANS; r++) {
01371 r2links[r].master = AST_PTHREADT_NULL;
01372 }
01373 }
01374
01375 static int dahdi_r2_answer(struct dahdi_pvt *p)
01376 {
01377 int res = 0;
01378
01379
01380
01381 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01382 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01383 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01384 if (!double_answer) {
01385
01386
01387 res = openr2_chan_answer_call(p->r2chan);
01388 } else if (wants_double_answer) {
01389 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01390 } else {
01391 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01392 }
01393 #else
01394 res = openr2_chan_answer_call(p->r2chan);
01395 #endif
01396 return res;
01397 }
01398
01399 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01400 {
01401 openr2_calling_party_category_t cat;
01402 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01403 struct dahdi_pvt *p = c->tech_pvt;
01404 if (ast_strlen_zero(catstr)) {
01405 ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n",
01406 c->name, openr2_proto_get_category_string(p->mfcr2_category));
01407 return p->mfcr2_category;
01408 }
01409 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01410 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01411 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01412 return p->mfcr2_category;
01413 }
01414 ast_log(LOG_DEBUG, "Using category %s\n", catstr);
01415 return cat;
01416 }
01417
01418 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01419 {
01420 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01421 ast_mutex_lock(&p->lock);
01422 if (p->mfcr2call) {
01423 ast_mutex_unlock(&p->lock);
01424
01425
01426
01427
01428
01429 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01430 return;
01431 }
01432 p->mfcr2call = 1;
01433
01434 p->cid_name[0] = 0;
01435 p->cid_num[0] = 0;
01436 p->rdnis[0] = 0;
01437 p->exten[0] = 0;
01438 p->mfcr2_ani_index = 0;
01439 p->mfcr2_dnis_index = 0;
01440 p->mfcr2_dnis_matched = 0;
01441 p->mfcr2_call_accepted = 0;
01442 ast_mutex_unlock(&p->lock);
01443 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01444 }
01445
01446 static void handle_alarms(struct dahdi_pvt *p, int alarms);
01447 static int get_alarms(struct dahdi_pvt *p);
01448 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01449 {
01450 int res;
01451 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01452 ast_mutex_lock(&p->lock);
01453 p->inalarm = alarm ? 1 : 0;
01454 if (p->inalarm) {
01455 res = get_alarms(p);
01456
01457 handle_alarms(p, res);
01458 } else {
01459 if (!p->unknown_alarm) {
01460 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01461 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01462 } else {
01463 p->unknown_alarm = 0;
01464 }
01465 }
01466 ast_mutex_unlock(&p->lock);
01467 ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan));
01468 }
01469
01470 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01471 {
01472 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01473 }
01474
01475 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01476 {
01477 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01478 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01479 if (p->owner) {
01480 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01481 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01482 }
01483 ast_mutex_lock(&p->lock);
01484 p->mfcr2call = 0;
01485 ast_mutex_unlock(&p->lock);
01486 }
01487
01488 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01489 {
01490 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01491 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01492 p->channel, openr2_proto_get_disconnect_string(cause));
01493
01494 openr2_chan_set_idle(p->r2chan);
01495 ast_mutex_lock(&p->lock);
01496 p->mfcr2call = 0;
01497 ast_mutex_unlock(&p->lock);
01498 }
01499 }
01500
01501 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01502 {
01503 struct dahdi_pvt *p;
01504 struct ast_channel *c;
01505 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01506 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category));
01507 p = openr2_chan_get_client_data(r2chan);
01508 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01509 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel);
01510 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01511 return;
01512 }
01513 ast_mutex_lock(&p->lock);
01514 p->mfcr2_recvd_category = category;
01515
01516 if (!p->use_callerid) {
01517 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01518 p->cid_num[0] = 0;
01519 p->cid_name[0] = 0;
01520 }
01521
01522 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01523 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01524 p->exten[0] = 's';
01525 p->exten[1] = 0;
01526 }
01527 ast_mutex_unlock(&p->lock);
01528 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01529 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01530 p->channel, p->exten, p->context);
01531 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01532 } else {
01533
01534 if (!p->mfcr2_accept_on_offer) {
01535 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01536 if (!c) {
01537 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01538 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01539 }
01540
01541
01542 } else if (p->mfcr2_charge_calls) {
01543 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel);
01544 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01545 } else {
01546 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel);
01547 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01548 }
01549 }
01550 }
01551
01552 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01553 {
01554 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01555 ast_verbose("MFC/R2 call end on chan %d\n", p->channel);
01556 ast_mutex_lock(&p->lock);
01557 p->mfcr2call = 0;
01558 ast_mutex_unlock(&p->lock);
01559 }
01560
01561 static void dahdi_enable_ec(struct dahdi_pvt *p);
01562 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01563 {
01564 struct dahdi_pvt *p = NULL;
01565 struct ast_channel *c = NULL;
01566 p = openr2_chan_get_client_data(r2chan);
01567 dahdi_enable_ec(p);
01568 p->mfcr2_call_accepted = 1;
01569 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01570 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01571
01572
01573
01574
01575 if (!p->mfcr2_accept_on_offer) {
01576 openr2_chan_disable_read(r2chan);
01577 ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01578 dahdi_r2_answer(p);
01579 return;
01580 }
01581 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01582 if (c) {
01583
01584 openr2_chan_disable_read(r2chan);
01585 } else {
01586 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01587 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01588 return;
01589 }
01590 } else {
01591 ast_verbose("Call accepted on forward channel %d\n", p->channel);
01592 p->subs[SUB_REAL].needringing = 1;
01593 p->dialing = 0;
01594
01595 openr2_chan_disable_read(r2chan);
01596 }
01597 }
01598
01599 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01600 {
01601 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01602 ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan));
01603 p->subs[SUB_REAL].needanswer = 1;
01604 }
01605
01606 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01607 {
01608
01609 }
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01633 {
01634 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01635 ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan));
01636 ast_mutex_lock(&p->lock);
01637 if (p->owner) {
01638
01639
01640 if (p->owner->_state == AST_STATE_UP) {
01641 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01642 ast_mutex_unlock(&p->lock);
01643 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01644
01645 switch (cause) {
01646 case OR2_CAUSE_BUSY_NUMBER:
01647 p->owner->hangupcause = AST_CAUSE_BUSY;
01648 p->subs[SUB_REAL].needbusy = 1;
01649 break;
01650 case OR2_CAUSE_NUMBER_CHANGED:
01651 p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED;
01652 p->subs[SUB_REAL].needcongestion = 1;
01653 break;
01654 case OR2_CAUSE_NETWORK_CONGESTION:
01655 p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
01656 p->subs[SUB_REAL].needcongestion = 1;
01657 break;
01658 case OR2_CAUSE_OUT_OF_ORDER:
01659 p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01660 p->subs[SUB_REAL].needcongestion = 1;
01661 break;
01662 case OR2_CAUSE_UNALLOCATED_NUMBER:
01663 p->owner->hangupcause = AST_CAUSE_UNALLOCATED;
01664 p->subs[SUB_REAL].needcongestion = 1;
01665 break;
01666 case OR2_CAUSE_NO_ANSWER:
01667 p->owner->hangupcause = AST_CAUSE_NO_ANSWER;
01668 p->subs[SUB_REAL].needcongestion = 1;
01669 break;
01670 case OR2_CAUSE_UNSPECIFIED:
01671 p->owner->hangupcause = AST_CAUSE_NOTDEFINED;
01672 p->subs[SUB_REAL].needcongestion = 1;
01673 break;
01674 case OR2_CAUSE_NORMAL_CLEARING:
01675 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01676 p->subs[SUB_REAL].needcongestion = 1;
01677 break;
01678 default:
01679 ast_log(LOG_WARNING, "Unhandled cause %d\n", cause);
01680 }
01681 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01682 ast_mutex_unlock(&p->lock);
01683 } else {
01684 ast_mutex_unlock(&p->lock);
01685
01686
01687 ast_queue_hangup(p->owner);
01688 }
01689 } else {
01690 ast_mutex_unlock(&p->lock);
01691
01692 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01693 }
01694 }
01695
01696 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01697 {
01698 switch (level) {
01699 case OR2_LOG_NOTICE:
01700 ast_verbose("%s", logmessage);
01701 break;
01702 case OR2_LOG_WARNING:
01703 ast_log(LOG_WARNING, "%s", logmessage);
01704 break;
01705 case OR2_LOG_ERROR:
01706 ast_log(LOG_ERROR, "%s", logmessage);
01707 break;
01708 case OR2_LOG_STACK_TRACE:
01709 case OR2_LOG_MF_TRACE:
01710 case OR2_LOG_CAS_TRACE:
01711 case OR2_LOG_DEBUG:
01712 case OR2_LOG_EX_DEBUG:
01713 ast_log(LOG_DEBUG, "%s", logmessage);
01714 break;
01715 default:
01716 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01717 ast_log(LOG_NOTICE, "%s", logmessage);
01718 break;
01719 }
01720 }
01721
01722 #define DAHDI_R2_REMOTE_BLOCK (1 << 0)
01723 #define DAHDI_R2_LOCAL_BLOCK (1 << 1)
01724 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01725 {
01726 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01727 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel);
01728 ast_mutex_lock(&p->lock);
01729 p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK;
01730 ast_mutex_unlock(&p->lock);
01731 }
01732
01733 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01734 {
01735 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01736 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01737 ast_mutex_lock(&p->lock);
01738 p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK;
01739 ast_mutex_unlock(&p->lock);
01740 }
01741
01742 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01743 __attribute__((format (printf, 3, 0)));
01744 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01745 {
01746 char logmsg[256];
01747 char completemsg[sizeof(logmsg)+50];
01748 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01749 snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg);
01750 dahdi_r2_write_log(level, completemsg);
01751 }
01752
01753 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01754 __attribute__((format (printf, 3, 0)));
01755 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01756 {
01757 char logmsg[256];
01758 char completemsg[sizeof(logmsg)+50];
01759 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01760 snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg);
01761 dahdi_r2_write_log(level, completemsg);
01762 }
01763
01764 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01765 {
01766 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01767
01768 if (p->immediate) {
01769 return 0;
01770 }
01771 p->exten[p->mfcr2_dnis_index] = digit;
01772 p->rdnis[p->mfcr2_dnis_index] = digit;
01773 p->mfcr2_dnis_index++;
01774 p->exten[p->mfcr2_dnis_index] = 0;
01775 p->rdnis[p->mfcr2_dnis_index] = 0;
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785 if ((p->mfcr2_dnis_matched ||
01786 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
01787 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01788 return 0;
01789 }
01790
01791 return 1;
01792 }
01793
01794 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
01795 {
01796 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01797 p->cid_num[p->mfcr2_ani_index] = digit;
01798 p->cid_name[p->mfcr2_ani_index] = digit;
01799 p->mfcr2_ani_index++;
01800 p->cid_num[p->mfcr2_ani_index] = 0;
01801 p->cid_name[p->mfcr2_ani_index] = 0;
01802 }
01803
01804 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
01805 {
01806 ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
01807 }
01808
01809 static openr2_event_interface_t dahdi_r2_event_iface = {
01810 .on_call_init = dahdi_r2_on_call_init,
01811 .on_call_offered = dahdi_r2_on_call_offered,
01812 .on_call_accepted = dahdi_r2_on_call_accepted,
01813 .on_call_answered = dahdi_r2_on_call_answered,
01814 .on_call_disconnect = dahdi_r2_on_call_disconnect,
01815 .on_call_end = dahdi_r2_on_call_end,
01816 .on_call_read = dahdi_r2_on_call_read,
01817 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
01818 .on_os_error = dahdi_r2_on_os_error,
01819 .on_protocol_error = dahdi_r2_on_protocol_error,
01820 .on_line_blocked = dahdi_r2_on_line_blocked,
01821 .on_line_idle = dahdi_r2_on_line_idle,
01822
01823 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
01824 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
01825 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
01826
01827 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
01828 };
01829
01830 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
01831 {
01832 return AST_ALAW(sample);
01833 }
01834
01835 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
01836 {
01837 return AST_LIN2A(sample);
01838 }
01839
01840 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
01841 dahdi_r2_alaw_to_linear,
01842 dahdi_r2_linear_to_alaw
01843 };
01844
01845 #endif
01846
01847 static int restore_gains(struct dahdi_pvt *p);
01848
01849 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01850 {
01851 int tchan;
01852 int tinthreeway;
01853 struct ast_channel *towner;
01854
01855 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01856
01857 tchan = p->subs[a].chan;
01858 towner = p->subs[a].owner;
01859 tinthreeway = p->subs[a].inthreeway;
01860
01861 p->subs[a].chan = p->subs[b].chan;
01862 p->subs[a].owner = p->subs[b].owner;
01863 p->subs[a].inthreeway = p->subs[b].inthreeway;
01864
01865 p->subs[b].chan = tchan;
01866 p->subs[b].owner = towner;
01867 p->subs[b].inthreeway = tinthreeway;
01868
01869 if (p->subs[a].owner)
01870 p->subs[a].owner->fds[0] = p->subs[a].dfd;
01871 if (p->subs[b].owner)
01872 p->subs[b].owner->fds[0] = p->subs[b].dfd;
01873 wakeup_sub(p, a, NULL);
01874 wakeup_sub(p, b, NULL);
01875 }
01876
01877 static int dahdi_open(char *fn)
01878 {
01879 int fd;
01880 int isnum;
01881 int chan = 0;
01882 int bs;
01883 int x;
01884 isnum = 1;
01885 for (x = 0; x < strlen(fn); x++) {
01886 if (!isdigit(fn[x])) {
01887 isnum = 0;
01888 break;
01889 }
01890 }
01891 if (isnum) {
01892 chan = atoi(fn);
01893 if (chan < 1) {
01894 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01895 return -1;
01896 }
01897 fn = DAHDI_FILE_CHANNEL;
01898 }
01899 fd = open(fn, O_RDWR | O_NONBLOCK);
01900 if (fd < 0) {
01901 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01902 return -1;
01903 }
01904 if (chan) {
01905 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01906 x = errno;
01907 close(fd);
01908 errno = x;
01909 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01910 return -1;
01911 }
01912 }
01913 bs = READ_SIZE;
01914 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01915 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01916 x = errno;
01917 close(fd);
01918 errno = x;
01919 return -1;
01920 }
01921 return fd;
01922 }
01923
01924 static void dahdi_close(int fd)
01925 {
01926 if (fd > 0)
01927 close(fd);
01928 }
01929
01930 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01931 {
01932 dahdi_close(chan_pvt->subs[sub_num].dfd);
01933 chan_pvt->subs[sub_num].dfd = -1;
01934 }
01935
01936 #ifdef HAVE_PRI
01937 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01938 {
01939 dahdi_close(pri->fds[fd_num]);
01940 pri->fds[fd_num] = -1;
01941 }
01942 #endif
01943
01944 static int dahdi_setlinear(int dfd, int linear)
01945 {
01946 int res;
01947 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01948 if (res)
01949 return res;
01950 return 0;
01951 }
01952
01953
01954 static int alloc_sub(struct dahdi_pvt *p, int x)
01955 {
01956 struct dahdi_bufferinfo bi;
01957 int res;
01958 if (p->subs[x].dfd < 0) {
01959 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01960 if (p->subs[x].dfd > -1) {
01961 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01962 if (!res) {
01963 bi.txbufpolicy = p->buf_policy;
01964 bi.rxbufpolicy = p->buf_policy;
01965 bi.numbufs = p->buf_no;
01966 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01967 if (res < 0) {
01968 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01969 }
01970 } else
01971 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01972 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01973 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01974 dahdi_close_sub(p, x);
01975 return -1;
01976 }
01977 if (option_debug)
01978 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01979 return 0;
01980 } else
01981 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01982 return -1;
01983 }
01984 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01985 return -1;
01986 }
01987
01988 static int unalloc_sub(struct dahdi_pvt *p, int x)
01989 {
01990 if (!x) {
01991 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01992 return -1;
01993 }
01994 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01995 dahdi_close_sub(p, x);
01996 p->subs[x].linear = 0;
01997 p->subs[x].chan = 0;
01998 p->subs[x].owner = NULL;
01999 p->subs[x].inthreeway = 0;
02000 p->polarity = POLARITY_IDLE;
02001 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02002 return 0;
02003 }
02004
02005 static int digit_to_dtmfindex(char digit)
02006 {
02007 if (isdigit(digit))
02008 return DAHDI_TONE_DTMF_BASE + (digit - '0');
02009 else if (digit >= 'A' && digit <= 'D')
02010 return DAHDI_TONE_DTMF_A + (digit - 'A');
02011 else if (digit >= 'a' && digit <= 'd')
02012 return DAHDI_TONE_DTMF_A + (digit - 'a');
02013 else if (digit == '*')
02014 return DAHDI_TONE_DTMF_s;
02015 else if (digit == '#')
02016 return DAHDI_TONE_DTMF_p;
02017 else
02018 return -1;
02019 }
02020
02021 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02022 {
02023 struct dahdi_pvt *pvt;
02024 int index;
02025 int dtmf = -1;
02026
02027 pvt = chan->tech_pvt;
02028
02029 ast_mutex_lock(&pvt->lock);
02030
02031 index = dahdi_get_index(chan, pvt, 0);
02032
02033 if ((index != SUB_REAL) || !pvt->owner)
02034 goto out;
02035
02036 #ifdef HAVE_PRI
02037 if (pvt->sig == SIG_PRI
02038 && chan->_state == AST_STATE_DIALING) {
02039 if (pvt->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
02040 unsigned int len;
02041
02042 len = strlen(pvt->dialdest);
02043 if (len < sizeof(pvt->dialdest) - 1) {
02044 ast_log(LOG_DEBUG,
02045 "Queueing digit '%c' since setup_ack not yet received\n", digit);
02046 pvt->dialdest[len++] = digit;
02047 pvt->dialdest[len] = '\0';
02048 } else {
02049 ast_log(LOG_WARNING,
02050 "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
02051 pvt->span, digit);
02052 }
02053 goto out;
02054 }
02055 if (pvt->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
02056 if (!pri_grab(pvt, pvt->pri)) {
02057 pri_information(pvt->pri->pri, pvt->call, digit);
02058 pri_rel(pvt->pri);
02059 } else {
02060 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02061 }
02062 goto out;
02063 }
02064 if (pvt->call_level < DAHDI_CALL_LEVEL_CONNECT) {
02065 ast_log(LOG_WARNING,
02066 "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n",
02067 pvt->span, digit, pvt->call_level);
02068 }
02069 }
02070 #endif
02071 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02072 goto out;
02073
02074 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02075 int res;
02076 struct dahdi_dialoperation zo = {
02077 .op = DAHDI_DIAL_OP_APPEND,
02078 .dialstr[0] = 'T',
02079 .dialstr[1] = digit,
02080 .dialstr[2] = 0,
02081 };
02082 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02083 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02084 else
02085 pvt->dialing = 1;
02086 } else {
02087 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
02088 pvt->dialing = 1;
02089 pvt->begindigit = digit;
02090 }
02091
02092 out:
02093 ast_mutex_unlock(&pvt->lock);
02094
02095 return 0;
02096 }
02097
02098 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02099 {
02100 struct dahdi_pvt *pvt;
02101 int res = 0;
02102 int index;
02103 int x;
02104
02105 pvt = chan->tech_pvt;
02106
02107 ast_mutex_lock(&pvt->lock);
02108
02109 index = dahdi_get_index(chan, pvt, 0);
02110
02111 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
02112 goto out;
02113
02114 #ifdef HAVE_PRI
02115
02116 if (pvt->sig == SIG_PRI && !pvt->begindigit)
02117 goto out;
02118 #endif
02119
02120 if (pvt->begindigit) {
02121 x = -1;
02122 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
02123 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02124 pvt->dialing = 0;
02125 pvt->begindigit = 0;
02126 }
02127
02128 out:
02129 ast_mutex_unlock(&pvt->lock);
02130
02131 return res;
02132 }
02133
02134 static char *events[] = {
02135 "No event",
02136 "On hook",
02137 "Ring/Answered",
02138 "Wink/Flash",
02139 "Alarm",
02140 "No more alarm",
02141 "HDLC Abort",
02142 "HDLC Overrun",
02143 "HDLC Bad FCS",
02144 "Dial Complete",
02145 "Ringer On",
02146 "Ringer Off",
02147 "Hook Transition Complete",
02148 "Bits Changed",
02149 "Pulse Start",
02150 "Timer Expired",
02151 "Timer Ping",
02152 "Polarity Reversal",
02153 "Ring Begin",
02154 };
02155
02156 static struct {
02157 int alarm;
02158 char *name;
02159 } alarms[] = {
02160 { DAHDI_ALARM_RED, "Red Alarm" },
02161 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02162 { DAHDI_ALARM_BLUE, "Blue Alarm" },
02163 { DAHDI_ALARM_RECOVER, "Recovering" },
02164 { DAHDI_ALARM_LOOPBACK, "Loopback" },
02165 { DAHDI_ALARM_NOTOPEN, "Not Open" },
02166 { DAHDI_ALARM_NONE, "None" },
02167 };
02168
02169 static char *alarm2str(int alarm)
02170 {
02171 int x;
02172 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
02173 if (alarms[x].alarm & alarm)
02174 return alarms[x].name;
02175 }
02176 return alarm ? "Unknown Alarm" : "No Alarm";
02177 }
02178
02179 static char *event2str(int event)
02180 {
02181 static char buf[256];
02182 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
02183 return events[event];
02184 sprintf(buf, "Event %d", event);
02185 return buf;
02186 }
02187
02188 #ifdef HAVE_PRI
02189 static char *dialplan2str(int dialplan)
02190 {
02191 if (dialplan == -1) {
02192 return("Dynamically set dialplan in ISDN");
02193 }
02194 return (pri_plan2str(dialplan));
02195 }
02196 #endif
02197
02198 static char *dahdi_sig2str(int sig)
02199 {
02200 static char buf[256];
02201 switch (sig) {
02202 case SIG_EM:
02203 return "E & M Immediate";
02204 case SIG_EMWINK:
02205 return "E & M Wink";
02206 case SIG_EM_E1:
02207 return "E & M E1";
02208 case SIG_FEATD:
02209 return "Feature Group D (DTMF)";
02210 case SIG_FEATDMF:
02211 return "Feature Group D (MF)";
02212 case SIG_FEATDMF_TA:
02213 return "Feature Groud D (MF) Tandem Access";
02214 case SIG_FEATB:
02215 return "Feature Group B (MF)";
02216 case SIG_E911:
02217 return "E911 (MF)";
02218 case SIG_FGC_CAMA:
02219 return "FGC/CAMA (Dialpulse)";
02220 case SIG_FGC_CAMAMF:
02221 return "FGC/CAMA (MF)";
02222 case SIG_FXSLS:
02223 return "FXS Loopstart";
02224 case SIG_FXSGS:
02225 return "FXS Groundstart";
02226 case SIG_FXSKS:
02227 return "FXS Kewlstart";
02228 case SIG_FXOLS:
02229 return "FXO Loopstart";
02230 case SIG_FXOGS:
02231 return "FXO Groundstart";
02232 case SIG_FXOKS:
02233 return "FXO Kewlstart";
02234 case SIG_PRI:
02235 return "ISDN PRI";
02236 case SIG_MFCR2:
02237 return "MFC/R2";
02238 case SIG_SF:
02239 return "SF (Tone) Immediate";
02240 case SIG_SFWINK:
02241 return "SF (Tone) Wink";
02242 case SIG_SF_FEATD:
02243 return "SF (Tone) with Feature Group D (DTMF)";
02244 case SIG_SF_FEATDMF:
02245 return "SF (Tone) with Feature Group D (MF)";
02246 case SIG_SF_FEATB:
02247 return "SF (Tone) with Feature Group B (MF)";
02248 case SIG_GR303FXOKS:
02249 return "GR-303 with FXOKS";
02250 case SIG_GR303FXSKS:
02251 return "GR-303 with FXSKS";
02252 case 0:
02253 return "Pseudo";
02254 default:
02255 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02256 return buf;
02257 }
02258 }
02259
02260 #define sig2str dahdi_sig2str
02261
02262 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
02263 {
02264
02265
02266 struct dahdi_confinfo zi;
02267
02268 memset(&zi, 0, sizeof(zi));
02269 zi.chan = 0;
02270
02271 if (slavechannel > 0) {
02272
02273 zi.confmode = DAHDI_CONF_DIGITALMON;
02274 zi.confno = slavechannel;
02275 } else {
02276 if (!index) {
02277
02278 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02279 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02280 } else
02281 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02282 zi.confno = p->confno;
02283 }
02284 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02285 return 0;
02286 if (c->dfd < 0)
02287 return 0;
02288 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02289 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02290 return -1;
02291 }
02292 if (slavechannel < 1) {
02293 p->confno = zi.confno;
02294 }
02295 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02296 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02297 return 0;
02298 }
02299
02300 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02301 {
02302
02303 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02304 return 1;
02305
02306 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02307 return 1;
02308 return 0;
02309 }
02310
02311 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
02312 {
02313 struct dahdi_confinfo zi;
02314 if (
02315 (c->dfd < 0) ||
02316
02317 !isourconf(p, c)
02318
02319 ) return 0;
02320 memset(&zi, 0, sizeof(zi));
02321 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02322 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02323 return -1;
02324 }
02325 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02326 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02327 return 0;
02328 }
02329
02330 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02331 {
02332 int x;
02333 int useslavenative;
02334 struct dahdi_pvt *slave = NULL;
02335
02336 useslavenative = 1;
02337
02338 for (x = 0; x < 3; x++) {
02339
02340
02341 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02342 useslavenative = 0;
02343 }
02344
02345
02346 if (useslavenative) {
02347 for (x = 0; x < MAX_SLAVES; x++) {
02348 if (p->slaves[x]) {
02349 if (slave) {
02350
02351
02352 slave = NULL;
02353 useslavenative = 0;
02354 break;
02355 } else {
02356
02357 slave = p->slaves[x];
02358 }
02359 }
02360 }
02361 }
02362
02363 if (!slave)
02364 useslavenative = 0;
02365 else if (slave->law != p->law) {
02366 useslavenative = 0;
02367 slave = NULL;
02368 }
02369 if (out)
02370 *out = slave;
02371 return useslavenative;
02372 }
02373
02374 static int reset_conf(struct dahdi_pvt *p)
02375 {
02376 p->confno = -1;
02377 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02378 if (p->subs[SUB_REAL].dfd > -1) {
02379 struct dahdi_confinfo zi;
02380
02381 memset(&zi, 0, sizeof(zi));
02382 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02383 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02384 }
02385 return 0;
02386 }
02387
02388 static int update_conf(struct dahdi_pvt *p)
02389 {
02390 int needconf = 0;
02391 int x;
02392 int useslavenative;
02393 struct dahdi_pvt *slave = NULL;
02394
02395 useslavenative = isslavenative(p, &slave);
02396
02397 for (x = 0; x < 3; x++) {
02398
02399 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02400 conf_add(p, &p->subs[x], x, 0);
02401 needconf++;
02402 } else {
02403 conf_del(p, &p->subs[x], x);
02404 }
02405 }
02406
02407
02408 for (x = 0; x < MAX_SLAVES; x++) {
02409 if (p->slaves[x]) {
02410 if (useslavenative)
02411 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02412 else {
02413 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02414 needconf++;
02415 }
02416 }
02417 }
02418
02419 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02420 if (useslavenative)
02421 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02422 else {
02423 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02424 needconf++;
02425 }
02426 }
02427
02428 if (p->master) {
02429 if (isslavenative(p->master, NULL)) {
02430 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02431 } else {
02432 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02433 }
02434 }
02435 if (!needconf) {
02436
02437
02438 p->confno = -1;
02439 }
02440 if (option_debug)
02441 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02442 return 0;
02443 }
02444
02445 static void dahdi_enable_ec(struct dahdi_pvt *p)
02446 {
02447 int x;
02448 int res;
02449 if (!p)
02450 return;
02451 if (p->echocanon) {
02452 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
02453 return;
02454 }
02455 if (p->digital) {
02456 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
02457 return;
02458 }
02459 if (p->echocancel) {
02460 if (p->sig == SIG_PRI) {
02461 x = 1;
02462 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02463 if (res)
02464 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02465 }
02466 x = p->echocancel;
02467 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02468 if (res)
02469 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02470 else {
02471 p->echocanon = 1;
02472 if (option_debug)
02473 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
02474 }
02475 } else if (option_debug)
02476 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
02477 }
02478
02479 static void dahdi_train_ec(struct dahdi_pvt *p)
02480 {
02481 int x;
02482 int res;
02483 if (p && p->echocancel && p->echotraining) {
02484 x = p->echotraining;
02485 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02486 if (res)
02487 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02488 else {
02489 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
02490 }
02491 } else
02492 ast_log(LOG_DEBUG, "No echo training requested\n");
02493 }
02494
02495 static void dahdi_disable_ec(struct dahdi_pvt *p)
02496 {
02497 int x;
02498 int res;
02499 if (p->echocancel) {
02500 x = 0;
02501 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02502 if (res)
02503 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02504 else if (option_debug)
02505 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
02506 }
02507 p->echocanon = 0;
02508 }
02509
02510 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02511 {
02512 int j;
02513 int k;
02514 float linear_gain = pow(10.0, gain / 20.0);
02515
02516 switch (law) {
02517 case DAHDI_LAW_ALAW:
02518 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02519 if (gain) {
02520 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02521 if (k > 32767) k = 32767;
02522 if (k < -32767) k = -32767;
02523 g->txgain[j] = AST_LIN2A(k);
02524 } else {
02525 g->txgain[j] = j;
02526 }
02527 }
02528 break;
02529 case DAHDI_LAW_MULAW:
02530 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02531 if (gain) {
02532 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02533 if (k > 32767) k = 32767;
02534 if (k < -32767) k = -32767;
02535 g->txgain[j] = AST_LIN2MU(k);
02536 } else {
02537 g->txgain[j] = j;
02538 }
02539 }
02540 break;
02541 }
02542 }
02543
02544 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02545 {
02546 int j;
02547 int k;
02548 float linear_gain = pow(10.0, gain / 20.0);
02549
02550 switch (law) {
02551 case DAHDI_LAW_ALAW:
02552 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02553 if (gain) {
02554 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02555 if (k > 32767) k = 32767;
02556 if (k < -32767) k = -32767;
02557 g->rxgain[j] = AST_LIN2A(k);
02558 } else {
02559 g->rxgain[j] = j;
02560 }
02561 }
02562 break;
02563 case DAHDI_LAW_MULAW:
02564 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02565 if (gain) {
02566 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02567 if (k > 32767) k = 32767;
02568 if (k < -32767) k = -32767;
02569 g->rxgain[j] = AST_LIN2MU(k);
02570 } else {
02571 g->rxgain[j] = j;
02572 }
02573 }
02574 break;
02575 }
02576 }
02577
02578 static int set_actual_txgain(int fd, int chan, float gain, int law)
02579 {
02580 struct dahdi_gains g;
02581 int res;
02582
02583 memset(&g, 0, sizeof(g));
02584 g.chan = chan;
02585 res = ioctl(fd, DAHDI_GETGAINS, &g);
02586 if (res) {
02587 if (option_debug)
02588 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02589 return res;
02590 }
02591
02592 fill_txgain(&g, gain, law);
02593
02594 return ioctl(fd, DAHDI_SETGAINS, &g);
02595 }
02596
02597 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02598 {
02599 struct dahdi_gains g;
02600 int res;
02601
02602 memset(&g, 0, sizeof(g));
02603 g.chan = chan;
02604 res = ioctl(fd, DAHDI_GETGAINS, &g);
02605 if (res) {
02606 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02607 return res;
02608 }
02609
02610 fill_rxgain(&g, gain, law);
02611
02612 return ioctl(fd, DAHDI_SETGAINS, &g);
02613 }
02614
02615 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02616 {
02617 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02618 }
02619
02620 static int bump_gains(struct dahdi_pvt *p)
02621 {
02622 int res;
02623
02624
02625 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
02626 if (res) {
02627 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02628 return -1;
02629 }
02630
02631 return 0;
02632 }
02633
02634 static int restore_gains(struct dahdi_pvt *p)
02635 {
02636 int res;
02637
02638 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02639 if (res) {
02640 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02641 return -1;
02642 }
02643
02644 return 0;
02645 }
02646
02647 static inline int dahdi_set_hook(int fd, int hs)
02648 {
02649 int x, res;
02650
02651 x = hs;
02652 res = ioctl(fd, DAHDI_HOOK, &x);
02653
02654 if (res < 0) {
02655 if (errno == EINPROGRESS)
02656 return 0;
02657 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02658
02659 }
02660
02661 return res;
02662 }
02663
02664 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02665 {
02666 int x, y, res;
02667 x = muted;
02668 if (p->sig == SIG_PRI) {
02669 y = 1;
02670 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02671 if (res)
02672 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02673 }
02674 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02675 if (res < 0)
02676 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02677 return res;
02678 }
02679
02680 static int save_conference(struct dahdi_pvt *p)
02681 {
02682 struct dahdi_confinfo c;
02683 int res;
02684 if (p->saveconf.confmode) {
02685 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02686 return -1;
02687 }
02688 p->saveconf.chan = 0;
02689 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02690 if (res) {
02691 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02692 p->saveconf.confmode = 0;
02693 return -1;
02694 }
02695 memset(&c, 0, sizeof(c));
02696 c.confmode = DAHDI_CONF_NORMAL;
02697 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02698 if (res) {
02699 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02700 return -1;
02701 }
02702 if (option_debug)
02703 ast_log(LOG_DEBUG, "Disabled conferencing\n");
02704 return 0;
02705 }
02706
02707 static int restore_conference(struct dahdi_pvt *p)
02708 {
02709 int res;
02710 if (p->saveconf.confmode) {
02711 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02712 p->saveconf.confmode = 0;
02713 if (res) {
02714 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02715 return -1;
02716 }
02717 if (option_debug)
02718 ast_log(LOG_DEBUG, "Restored conferencing\n");
02719 }
02720 return 0;
02721 }
02722
02723 static int send_callerid(struct dahdi_pvt *p);
02724
02725 static int send_cwcidspill(struct dahdi_pvt *p)
02726 {
02727 p->callwaitcas = 0;
02728 p->cidcwexpire = 0;
02729 p->cid_suppress_expire = 0;
02730 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02731 return -1;
02732 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02733
02734 p->cidlen += READ_SIZE * 4;
02735 p->cidpos = 0;
02736 send_callerid(p);
02737 if (option_verbose > 2)
02738 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02739 return 0;
02740 }
02741
02742 static int has_voicemail(struct dahdi_pvt *p)
02743 {
02744
02745 return ast_app_has_voicemail(p->mailbox, NULL);
02746 }
02747
02748 static int send_callerid(struct dahdi_pvt *p)
02749 {
02750
02751 int res;
02752
02753 if (p->subs[SUB_REAL].linear) {
02754 p->subs[SUB_REAL].linear = 0;
02755 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02756 }
02757 while (p->cidpos < p->cidlen) {
02758 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02759 if (res < 0) {
02760 if (errno == EAGAIN)
02761 return 0;
02762 else {
02763 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02764 return -1;
02765 }
02766 }
02767 if (!res)
02768 return 0;
02769 p->cidpos += res;
02770 }
02771 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
02772 free(p->cidspill);
02773 p->cidspill = NULL;
02774 if (p->callwaitcas) {
02775
02776 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02777 p->cid_suppress_expire = p->cidcwexpire;
02778 } else
02779 restore_conference(p);
02780 return 0;
02781 }
02782
02783 static int dahdi_callwait(struct ast_channel *ast)
02784 {
02785 struct dahdi_pvt *p = ast->tech_pvt;
02786 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02787 if (p->cidspill) {
02788 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02789 free(p->cidspill);
02790 }
02791
02792
02793
02794
02795
02796 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02797 return -1;
02798 save_conference(p);
02799
02800 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02801 if (!p->callwaitrings && p->callwaitingcallerid) {
02802 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02803 p->callwaitcas = 1;
02804 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02805 } else {
02806 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02807 p->callwaitcas = 0;
02808 p->cidlen = 2400 + READ_SIZE * 4;
02809 }
02810 p->cidpos = 0;
02811 send_callerid(p);
02812
02813 return 0;
02814 }
02815
02816 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02817 {
02818 struct dahdi_pvt *p = ast->tech_pvt;
02819 int x, res, index,mysig;
02820 char *c, *n, *l;
02821 #ifdef HAVE_PRI
02822 char *s = NULL;
02823 #endif
02824 char dest[256];
02825 ast_mutex_lock(&p->lock);
02826 ast_copy_string(dest, rdest, sizeof(dest));
02827 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02828 if ((ast->_state == AST_STATE_BUSY)) {
02829 p->subs[SUB_REAL].needbusy = 1;
02830 ast_mutex_unlock(&p->lock);
02831 return 0;
02832 }
02833 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02834 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02835 ast_mutex_unlock(&p->lock);
02836 return -1;
02837 }
02838 p->dialednone = 0;
02839 if ((p->radio || (p->oprmode < 0)))
02840 {
02841
02842 ast_setstate(ast, AST_STATE_UP);
02843 ast_mutex_unlock(&p->lock);
02844 return 0;
02845 }
02846 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02847 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02848 if (res)
02849 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02850 p->outgoing = 1;
02851
02852 if (IS_DIGITAL(ast->transfercapability)) {
02853 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02854 } else {
02855 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02856 }
02857
02858 mysig = p->sig;
02859 if (p->outsigmod > -1)
02860 mysig = p->outsigmod;
02861
02862 switch (mysig) {
02863 case SIG_FXOLS:
02864 case SIG_FXOGS:
02865 case SIG_FXOKS:
02866 if (p->owner == ast) {
02867
02868
02869
02870 p->dialing = 1;
02871 if (p->use_callerid) {
02872
02873 if (p->cidspill) {
02874 ast_log(LOG_WARNING, "cidspill already exists??\n");
02875 free(p->cidspill);
02876 }
02877 p->callwaitcas = 0;
02878 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02879 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02880 p->cidpos = 0;
02881 send_callerid(p);
02882 }
02883 }
02884
02885 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02886 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02887 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02888 p->cidrings = cidrings[p->distinctivering - 1];
02889 } else {
02890 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02891 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02892 p->cidrings = p->sendcalleridafter;
02893 }
02894
02895
02896 c = strchr(dest, '/');
02897 if (c)
02898 c++;
02899 if (c && (strlen(c) < p->stripmsd)) {
02900 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02901 c = NULL;
02902 }
02903 if (c) {
02904 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02905 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02906 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02907 } else {
02908 p->dop.dialstr[0] = '\0';
02909 }
02910 x = DAHDI_RING;
02911 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02912 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02913 ast_mutex_unlock(&p->lock);
02914 return -1;
02915 }
02916 p->dialing = 1;
02917 } else {
02918
02919 p->callwaitrings = 0;
02920 if (ast->cid.cid_num)
02921 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02922 else
02923 p->callwait_num[0] = '\0';
02924 if (ast->cid.cid_name)
02925 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02926 else
02927 p->callwait_name[0] = '\0';
02928
02929 if (dahdi_callwait(ast)) {
02930 ast_mutex_unlock(&p->lock);
02931 return -1;
02932 }
02933
02934 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02935 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02936
02937 }
02938 n = ast->cid.cid_name;
02939 l = ast->cid.cid_num;
02940 if (l)
02941 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02942 else
02943 p->lastcid_num[0] = '\0';
02944 if (n)
02945 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02946 else
02947 p->lastcid_name[0] = '\0';
02948 ast_setstate(ast, AST_STATE_RINGING);
02949 index = dahdi_get_index(ast, p, 0);
02950 if (index > -1) {
02951 p->subs[index].needringing = 1;
02952 }
02953 break;
02954 case SIG_FXSLS:
02955 case SIG_FXSGS:
02956 case SIG_FXSKS:
02957 case SIG_EMWINK:
02958 case SIG_EM:
02959 case SIG_EM_E1:
02960 case SIG_FEATD:
02961 case SIG_FEATDMF:
02962 case SIG_E911:
02963 case SIG_FGC_CAMA:
02964 case SIG_FGC_CAMAMF:
02965 case SIG_FEATB:
02966 case SIG_SFWINK:
02967 case SIG_SF:
02968 case SIG_SF_FEATD:
02969 case SIG_SF_FEATDMF:
02970 case SIG_FEATDMF_TA:
02971 case SIG_SF_FEATB:
02972 c = strchr(dest, '/');
02973 if (c)
02974 c++;
02975 else
02976 c = "";
02977 if (strlen(c) < p->stripmsd) {
02978 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02979 ast_mutex_unlock(&p->lock);
02980 return -1;
02981 }
02982 #ifdef HAVE_PRI
02983
02984 if (!p->pri) {
02985 #endif
02986 x = DAHDI_START;
02987 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02988 if (res < 0) {
02989 if (errno != EINPROGRESS) {
02990 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02991 ast_mutex_unlock(&p->lock);
02992 return -1;
02993 }
02994 }
02995 #ifdef HAVE_PRI
02996 }
02997 #endif
02998 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02999 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03000
03001 c += p->stripmsd;
03002
03003 switch (mysig) {
03004 case SIG_FEATD:
03005 l = ast->cid.cid_num;
03006 if (l)
03007 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03008 else
03009 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03010 break;
03011 case SIG_FEATDMF:
03012 l = ast->cid.cid_num;
03013 if (l)
03014 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03015 else
03016 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03017 break;
03018 case SIG_FEATDMF_TA:
03019 {
03020 const char *cic, *ozz;
03021
03022
03023 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03024 if (!ozz)
03025 ozz = defaultozz;
03026 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03027 if (!cic)
03028 cic = defaultcic;
03029 if (!ozz || !cic) {
03030 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03031 ast_mutex_unlock(&p->lock);
03032 return -1;
03033 }
03034 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03035 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03036 p->whichwink = 0;
03037 }
03038 break;
03039 case SIG_E911:
03040 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03041 break;
03042 case SIG_FGC_CAMA:
03043 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03044 break;
03045 case SIG_FGC_CAMAMF:
03046 case SIG_FEATB:
03047 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03048 break;
03049 default:
03050 if (p->pulse)
03051 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03052 else
03053 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03054 break;
03055 }
03056
03057 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03058 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03059 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03060 p->echorest[sizeof(p->echorest) - 1] = '\0';
03061 p->echobreak = 1;
03062 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03063 } else
03064 p->echobreak = 0;
03065 if (!res) {
03066 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03067 int saveerr = errno;
03068
03069 x = DAHDI_ONHOOK;
03070 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03071 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03072 ast_mutex_unlock(&p->lock);
03073 return -1;
03074 }
03075 } else
03076 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res);
03077 p->dialing = 1;
03078 if (ast_strlen_zero(c))
03079 p->dialednone = 1;
03080 ast_setstate(ast, AST_STATE_DIALING);
03081 break;
03082 case 0:
03083
03084 ast_setstate(ast, AST_STATE_UP);
03085 break;
03086 case SIG_PRI:
03087 case SIG_MFCR2:
03088
03089 p->dialdest[0] = '\0';
03090 p->dialing = 1;
03091 break;
03092 default:
03093 ast_log(LOG_DEBUG, "not yet implemented\n");
03094 ast_mutex_unlock(&p->lock);
03095 return -1;
03096 }
03097
03098 #ifdef HAVE_OPENR2
03099 if (p->mfcr2) {
03100 int strip = p->stripmsd;
03101 int callres = 0;
03102 c = strchr(dest, '/');
03103 if (c) {
03104 c++;
03105 } else {
03106 c = dest;
03107 }
03108 if (!p->hidecallerid) {
03109 l = ast->cid.cid_num;
03110 } else {
03111 l = NULL;
03112 }
03113 if (strlen(c) < strip) {
03114 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
03115 strip = 0;
03116 }
03117 p->dialing = 1;
03118 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast));
03119 if (-1 == callres) {
03120 ast_mutex_unlock(&p->lock);
03121 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03122 return -1;
03123 }
03124 ast_setstate(ast, AST_STATE_DIALING);
03125 }
03126 #endif
03127
03128 #ifdef HAVE_PRI
03129 if (p->pri) {
03130 struct pri_sr *sr;
03131 #ifdef SUPPORT_USERUSER
03132 const char *useruser;
03133 #endif
03134 int pridialplan;
03135 int dp_strip;
03136 int prilocaldialplan;
03137 int ldp_strip;
03138 int exclusive;
03139 const char *rr_str;
03140 int redirect_reason;
03141
03142 c = strchr(dest, '/');
03143 if (c) {
03144 c++;
03145 } else {
03146 c = "";
03147 }
03148
03149 l = NULL;
03150 n = NULL;
03151 if (!p->hidecallerid) {
03152 l = ast->cid.cid_num;
03153 if (!p->hidecalleridname) {
03154 n = ast->cid.cid_name;
03155 }
03156 }
03157
03158
03159 if (strlen(c) < p->stripmsd) {
03160 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03161 ast_mutex_unlock(&p->lock);
03162 return -1;
03163 }
03164 if (mysig != SIG_FXSKS) {
03165 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03166 s = strchr(c + p->stripmsd, 'w');
03167 if (s) {
03168 if (strlen(s) > 1)
03169 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03170 else
03171 p->dop.dialstr[0] = '\0';
03172 *s = '\0';
03173 } else {
03174 p->dop.dialstr[0] = '\0';
03175 }
03176 }
03177 if (pri_grab(p, p->pri)) {
03178 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03179 ast_mutex_unlock(&p->lock);
03180 return -1;
03181 }
03182 if (!(p->call = pri_new_call(p->pri->pri))) {
03183 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03184 pri_rel(p->pri);
03185 ast_mutex_unlock(&p->lock);
03186 return -1;
03187 }
03188 if (!(sr = pri_sr_new())) {
03189 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03190 pri_destroycall(p->pri->pri, p->call);
03191 p->call = NULL;
03192 pri_rel(p->pri);
03193 ast_mutex_unlock(&p->lock);
03194 return -1;
03195 }
03196 if (p->bearer || (mysig == SIG_FXSKS)) {
03197 if (p->bearer) {
03198 ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03199 p->bearer->call = p->call;
03200 } else
03201 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
03202 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03203 }
03204 p->digital = IS_DIGITAL(ast->transfercapability);
03205
03206
03207 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03208 exclusive = 1;
03209 } else {
03210 exclusive = 0;
03211 }
03212
03213 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03214 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03215 (p->digital ? -1 :
03216 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03217 if (p->pri->facilityenable)
03218 pri_facility_enable(p->pri->pri);
03219
03220 if (option_verbose > 2)
03221 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03222 dp_strip = 0;
03223 pridialplan = p->pri->dialplan - 1;
03224 if (pridialplan == -2) {
03225 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03226 dp_strip = strlen(p->pri->internationalprefix);
03227 pridialplan = PRI_INTERNATIONAL_ISDN;
03228 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03229 dp_strip = strlen(p->pri->nationalprefix);
03230 pridialplan = PRI_NATIONAL_ISDN;
03231 } else {
03232 pridialplan = PRI_LOCAL_ISDN;
03233 }
03234 }
03235 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03236
03237 ldp_strip = 0;
03238 prilocaldialplan = p->pri->localdialplan - 1;
03239 if ((l != NULL) && (prilocaldialplan == -2)) {
03240 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03241 ldp_strip = strlen(p->pri->internationalprefix);
03242 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03243 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03244 ldp_strip = strlen(p->pri->nationalprefix);
03245 prilocaldialplan = PRI_NATIONAL_ISDN;
03246 } else {
03247 prilocaldialplan = PRI_LOCAL_ISDN;
03248 }
03249 }
03250 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03251 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03252 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03253 if (!strcasecmp(rr_str, "UNKNOWN"))
03254 redirect_reason = 0;
03255 else if (!strcasecmp(rr_str, "BUSY"))
03256 redirect_reason = 1;
03257 else if (!strcasecmp(rr_str, "NO_REPLY"))
03258 redirect_reason = 2;
03259 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03260 redirect_reason = 15;
03261 else
03262 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03263 } else
03264 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03265 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03266
03267 #ifdef SUPPORT_USERUSER
03268
03269 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03270
03271 if (useruser)
03272 pri_sr_set_useruser(sr, useruser);
03273 #endif
03274
03275 if (pri_setup(p->pri->pri, p->call, sr)) {
03276 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03277 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03278 pri_destroycall(p->pri->pri, p->call);
03279 p->call = NULL;
03280 pri_rel(p->pri);
03281 ast_mutex_unlock(&p->lock);
03282 pri_sr_free(sr);
03283 return -1;
03284 }
03285 p->call_level = DAHDI_CALL_LEVEL_SETUP;
03286 pri_sr_free(sr);
03287 ast_setstate(ast, AST_STATE_DIALING);
03288 pri_rel(p->pri);
03289 }
03290 #endif
03291 ast_mutex_unlock(&p->lock);
03292 return 0;
03293 }
03294
03295 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03296 {
03297 struct dahdi_pvt *p = *pvt;
03298
03299 if (p->prev)
03300 p->prev->next = p->next;
03301 if (p->next)
03302 p->next->prev = p->prev;
03303
03304 free(p->cidspill);
03305 if (p->use_smdi)
03306 ast_smdi_interface_unref(p->smdi_iface);
03307 ast_mutex_destroy(&p->lock);
03308 dahdi_close_sub(p, SUB_REAL);
03309 if (p->owner)
03310 p->owner->tech_pvt = NULL;
03311 free(p);
03312 *pvt = NULL;
03313 }
03314
03315 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03316 {
03317 int owned = 0;
03318 int i = 0;
03319
03320 if (!now) {
03321 if (cur->owner) {
03322 owned = 1;
03323 }
03324
03325 for (i = 0; i < 3; i++) {
03326 if (cur->subs[i].owner) {
03327 owned = 1;
03328 }
03329 }
03330 if (!owned) {
03331 if (prev) {
03332 prev->next = cur->next;
03333 if (prev->next)
03334 prev->next->prev = prev;
03335 else
03336 ifend = prev;
03337 } else {
03338 iflist = cur->next;
03339 if (iflist)
03340 iflist->prev = NULL;
03341 else
03342 ifend = NULL;
03343 }
03344 destroy_dahdi_pvt(&cur);
03345 }
03346 } else {
03347 if (prev) {
03348 prev->next = cur->next;
03349 if (prev->next)
03350 prev->next->prev = prev;
03351 else
03352 ifend = prev;
03353 } else {
03354 iflist = cur->next;
03355 if (iflist)
03356 iflist->prev = NULL;
03357 else
03358 ifend = NULL;
03359 }
03360 destroy_dahdi_pvt(&cur);
03361 }
03362 return 0;
03363 }
03364
03365 static void destroy_all_channels(void)
03366 {
03367 int x;
03368 struct dahdi_pvt *p, *pl;
03369
03370 while (num_restart_pending) {
03371 usleep(1);
03372 }
03373
03374 ast_mutex_lock(&iflock);
03375
03376 p = iflist;
03377 while (p) {
03378 pl = p;
03379 p = p->next;
03380 x = pl->channel;
03381
03382 destroy_dahdi_pvt(&pl);
03383 if (option_verbose > 2)
03384 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03385 }
03386 iflist = NULL;
03387 ifcount = 0;
03388 ast_mutex_unlock(&iflock);
03389 }
03390
03391 #ifdef HAVE_PRI
03392 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03393 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
03394
03395 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03396 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03397
03398 static char *dahdi_send_keypad_facility_descrip =
03399 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03400 " IE over the current channel.\n";
03401 static char *zap_send_keypad_facility_descrip =
03402 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03403 " IE over the current channel.\n";
03404
03405 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
03406 {
03407
03408 struct dahdi_pvt *p;
03409 char *digits = (char *) data;
03410
03411 if (ast_strlen_zero(digits)) {
03412 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
03413 return -1;
03414 }
03415
03416 p = (struct dahdi_pvt *)chan->tech_pvt;
03417
03418 if (!p) {
03419 ast_log(LOG_DEBUG, "Unable to find technology private\n");
03420 return -1;
03421 }
03422
03423 ast_mutex_lock(&p->lock);
03424
03425 if (!p->pri || !p->call) {
03426 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
03427 ast_mutex_unlock(&p->lock);
03428 return -1;
03429 }
03430
03431 if (!pri_grab(p, p->pri)) {
03432 pri_keypad_facility(p->pri->pri, p->call, digits);
03433 pri_rel(p->pri);
03434 } else {
03435 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
03436 ast_mutex_unlock(&p->lock);
03437 return -1;
03438 }
03439
03440 ast_mutex_unlock(&p->lock);
03441
03442 return 0;
03443 }
03444
03445 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03446 {
03447 return send_keypad_facility_exec(chan, data);
03448 }
03449
03450 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03451 {
03452 ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app);
03453 return send_keypad_facility_exec(chan, data);
03454 }
03455
03456 static int pri_is_up(struct dahdi_pri *pri)
03457 {
03458 int x;
03459 for (x = 0; x < NUM_DCHANS; x++) {
03460 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03461 return 1;
03462 }
03463 return 0;
03464 }
03465
03466 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03467 {
03468 bearer->owner = &inuse;
03469 bearer->realcall = crv;
03470 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03471 if (crv->subs[SUB_REAL].owner)
03472 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03473 crv->bearer = bearer;
03474 crv->call = bearer->call;
03475 crv->pri = pri;
03476 return 0;
03477 }
03478
03479 static char *pri_order(int level)
03480 {
03481 switch (level) {
03482 case 0:
03483 return "Primary";
03484 case 1:
03485 return "Secondary";
03486 case 2:
03487 return "Tertiary";
03488 case 3:
03489 return "Quaternary";
03490 default:
03491 return "<Unknown>";
03492 }
03493 }
03494
03495
03496 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03497 {
03498 int x = -1;
03499
03500 for (x = 0; x < NUM_DCHANS; x++) {
03501 if ((pri->dchans[x] == pri->pri))
03502 break;
03503 }
03504
03505 return pri->fds[x];
03506 }
03507
03508 static int pri_find_dchan(struct dahdi_pri *pri)
03509 {
03510 int oldslot = -1;
03511 struct pri *old;
03512 int newslot = -1;
03513 int x;
03514 old = pri->pri;
03515 for (x = 0; x < NUM_DCHANS; x++) {
03516 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03517 newslot = x;
03518 if (pri->dchans[x] == old) {
03519 oldslot = x;
03520 }
03521 }
03522 if (newslot < 0) {
03523 newslot = 0;
03524 if (!pri->no_d_channels) {
03525 pri->no_d_channels = 1;
03526 ast_log(LOG_WARNING,
03527 "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03528 pri->dchannels[newslot]);
03529 }
03530 } else {
03531 pri->no_d_channels = 0;
03532 }
03533 if (old && (oldslot != newslot))
03534 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03535 pri->dchannels[oldslot], pri->dchannels[newslot]);
03536 pri->pri = pri->dchans[newslot];
03537 return 0;
03538 }
03539 #endif
03540
03541 #ifdef HAVE_OPENR2
03542 static char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
03543 static char *zap_accept_r2_call_app = "ZapAcceptR2Call";
03544
03545 static char *dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03546 static char *zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03547
03548 static char *dahdi_accept_r2_call_descrip =
03549 " DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03550 " You can specify yes or no as argument to accept with or without charge.\n";
03551
03552 static char *zap_accept_r2_call_descrip =
03553 " ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03554 " You can specify yes or no as argument to accept with or without charge.\n";
03555
03556 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
03557 {
03558
03559 openr2_call_mode_t accept_mode;
03560 int res, timeout, maxloops;
03561 struct ast_frame *f;
03562 struct dahdi_pvt *p;
03563 char *parse;
03564 AST_DECLARE_APP_ARGS(args,
03565 AST_APP_ARG(charge);
03566 );
03567
03568 if (ast_strlen_zero(data)) {
03569 ast_log(LOG_DEBUG, "No data sent to application!\n");
03570 return -1;
03571 }
03572
03573 if (chan->tech != &dahdi_tech) {
03574 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
03575 return -1;
03576 }
03577
03578 p = (struct dahdi_pvt *)chan->tech_pvt;
03579 if (!p) {
03580 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
03581 return -1;
03582 }
03583
03584 parse = ast_strdupa(data);
03585 AST_STANDARD_APP_ARGS(args, parse);
03586
03587 if (ast_strlen_zero(args.charge)) {
03588 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
03589 return -1;
03590 }
03591
03592 ast_mutex_lock(&p->lock);
03593 if (!p->mfcr2 || !p->mfcr2call) {
03594 ast_mutex_unlock(&p->lock);
03595 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
03596 return -1;
03597 }
03598
03599 if (p->mfcr2_call_accepted) {
03600 ast_mutex_unlock(&p->lock);
03601 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
03602 return 0;
03603 }
03604 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
03605 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
03606 ast_mutex_unlock(&p->lock);
03607 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03608 return -1;
03609 }
03610 ast_mutex_unlock(&p->lock);
03611
03612 res = 0;
03613 timeout = 100;
03614 maxloops = 50;
03615
03616 while (maxloops > 0) {
03617 maxloops--;
03618 if (ast_check_hangup(chan)) {
03619 break;
03620 }
03621 res = ast_waitfor(chan, timeout);
03622 if (res < 0) {
03623 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
03624 res = -1;
03625 break;
03626 }
03627 if (res == 0) {
03628 continue;
03629 }
03630 f = ast_read(chan);
03631 if (!f) {
03632 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
03633 res = -1;
03634 break;
03635 }
03636 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
03637 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
03638 ast_frfree(f);
03639 res = -1;
03640 break;
03641 }
03642 ast_frfree(f);
03643 ast_mutex_lock(&p->lock);
03644 if (p->mfcr2_call_accepted) {
03645 ast_mutex_unlock(&p->lock);
03646 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
03647 break;
03648 }
03649 ast_mutex_unlock(&p->lock);
03650 }
03651 if (res == -1) {
03652 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03653 }
03654 return res;
03655 }
03656
03657 static int zap_accept_r2_call_exec(struct ast_channel *chan, void *data)
03658 {
03659 return dahdi_accept_r2_call_exec(chan, data);
03660 }
03661
03662 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
03663 {
03664 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
03665 switch (cause) {
03666 case AST_CAUSE_USER_BUSY:
03667 case AST_CAUSE_CALL_REJECTED:
03668 case AST_CAUSE_INTERWORKING:
03669 r2cause = OR2_CAUSE_BUSY_NUMBER;
03670 break;
03671
03672 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
03673 case AST_CAUSE_SWITCH_CONGESTION:
03674 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
03675 break;
03676
03677 case AST_CAUSE_UNALLOCATED:
03678 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
03679 break;
03680
03681 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
03682 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03683 r2cause = OR2_CAUSE_OUT_OF_ORDER;
03684 break;
03685
03686 case AST_CAUSE_NO_ANSWER:
03687 case AST_CAUSE_NO_USER_RESPONSE:
03688 r2cause = OR2_CAUSE_NO_ANSWER;
03689 break;
03690
03691 default:
03692 r2cause = OR2_CAUSE_NORMAL_CLEARING;
03693 break;
03694 }
03695 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n",
03696 r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
03697 return r2cause;
03698 }
03699 #endif
03700
03701 static int dahdi_hangup(struct ast_channel *ast)
03702 {
03703 int res;
03704 int index,x, law;
03705
03706 struct dahdi_pvt *p = ast->tech_pvt;
03707 struct dahdi_pvt *tmp = NULL;
03708 struct dahdi_pvt *prev = NULL;
03709 struct dahdi_params par;
03710
03711 if (option_debug)
03712 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
03713 if (!ast->tech_pvt) {
03714 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03715 return 0;
03716 }
03717
03718 ast_mutex_lock(&p->lock);
03719
03720 index = dahdi_get_index(ast, p, 1);
03721
03722 if (p->sig == SIG_PRI) {
03723 x = 1;
03724 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03725 p->cid_num[0] = '\0';
03726 p->cid_name[0] = '\0';
03727 }
03728
03729 x = 0;
03730 dahdi_confmute(p, 0);
03731 restore_gains(p);
03732 if (p->origcid_num) {
03733 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03734 free(p->origcid_num);
03735 p->origcid_num = NULL;
03736 }
03737 if (p->origcid_name) {
03738 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03739 free(p->origcid_name);
03740 p->origcid_name = NULL;
03741 }
03742 if (p->dsp)
03743 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03744 p->exten[0] = '\0';
03745
03746 if (option_debug)
03747 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03748 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03749 p->ignoredtmf = 0;
03750
03751 if (index > -1) {
03752
03753 p->subs[index].owner = NULL;
03754 p->subs[index].needanswer = 0;
03755 p->subs[index].needflash = 0;
03756 p->subs[index].needringing = 0;
03757 p->subs[index].needbusy = 0;
03758 p->subs[index].needcongestion = 0;
03759 p->subs[index].linear = 0;
03760 p->subs[index].needcallerid = 0;
03761 p->polarity = POLARITY_IDLE;
03762 dahdi_setlinear(p->subs[index].dfd, 0);
03763 switch (index) {
03764 case SUB_REAL:
03765 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03766 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
03767 if (p->subs[SUB_CALLWAIT].inthreeway) {
03768
03769 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
03770
03771 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03772 unalloc_sub(p, SUB_CALLWAIT);
03773 p->owner = NULL;
03774 } else {
03775
03776 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03777 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03778 unalloc_sub(p, SUB_THREEWAY);
03779 if (p->subs[SUB_REAL].inthreeway) {
03780
03781
03782 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03783 p->subs[SUB_REAL].inthreeway = 0;
03784 p->owner = p->subs[SUB_REAL].owner;
03785 } else {
03786
03787 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03788 p->owner = NULL;
03789 }
03790 }
03791 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03792
03793 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
03794 if (!p->subs[SUB_CALLWAIT].owner) {
03795
03796 p->owner = NULL;
03797 break;
03798 }
03799
03800
03801 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03802 unalloc_sub(p, SUB_CALLWAIT);
03803 p->owner = p->subs[SUB_REAL].owner;
03804 if (p->owner->_state != AST_STATE_UP)
03805 p->subs[SUB_REAL].needanswer = 1;
03806 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03807 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03808
03809 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03810 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03811 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03812 unalloc_sub(p, SUB_THREEWAY);
03813 if (p->subs[SUB_REAL].inthreeway) {
03814
03815
03816 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03817 p->subs[SUB_REAL].inthreeway = 0;
03818 p->owner = p->subs[SUB_REAL].owner;
03819 } else {
03820
03821 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03822 p->owner = NULL;
03823 }
03824 }
03825 break;
03826 case SUB_CALLWAIT:
03827
03828 if (p->subs[SUB_CALLWAIT].inthreeway) {
03829
03830 dahdi_lock_sub_owner(p, SUB_THREEWAY);
03831
03832
03833
03834 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03835 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03836 S_OR(p->mohsuggest, NULL),
03837 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03838 }
03839 p->subs[SUB_THREEWAY].inthreeway = 0;
03840
03841 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03842 unalloc_sub(p, SUB_THREEWAY);
03843 if (p->subs[SUB_CALLWAIT].owner) {
03844
03845 ast_mutex_unlock(&p->subs[SUB_CALLWAIT].owner->lock);
03846 }
03847 } else
03848 unalloc_sub(p, SUB_CALLWAIT);
03849 break;
03850 case SUB_THREEWAY:
03851
03852 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
03853 if (p->subs[SUB_CALLWAIT].inthreeway) {
03854
03855
03856 p->subs[SUB_CALLWAIT].inthreeway = 0;
03857 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03858 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03859 S_OR(p->mohsuggest, NULL),
03860 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03861 }
03862 }
03863 if (p->subs[SUB_CALLWAIT].owner) {
03864 ast_mutex_unlock(&p->subs[SUB_CALLWAIT].owner->lock);
03865 }
03866 p->subs[SUB_REAL].inthreeway = 0;
03867
03868
03869 unalloc_sub(p, SUB_THREEWAY);
03870 break;
03871 default:
03872
03873
03874
03875
03876 ast_log(LOG_ERROR, "Index found but not any type of call?\n");
03877 break;
03878 }
03879 }
03880
03881 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03882 p->ringt = 0;
03883 p->distinctivering = 0;
03884 p->confirmanswer = 0;
03885 p->cidrings = 1;
03886 p->outgoing = 0;
03887 p->digital = 0;
03888 p->faxhandled = 0;
03889 p->pulsedial = 0;
03890 p->onhooktime = time(NULL);
03891 #ifdef HAVE_PRI
03892 p->dialing = 0;
03893 p->progress = 0;
03894 p->call_level = DAHDI_CALL_LEVEL_IDLE;
03895 #endif
03896 if (p->dsp) {
03897 ast_dsp_free(p->dsp);
03898 p->dsp = NULL;
03899 }
03900
03901 if (p->bufferoverrideinuse) {
03902
03903 struct dahdi_bufferinfo bi = {
03904 .txbufpolicy = p->buf_policy,
03905 .rxbufpolicy = p->buf_policy,
03906 .bufsize = p->bufsize,
03907 .numbufs = p->buf_no
03908 };
03909 int bpres;
03910
03911 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
03912 ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
03913 }
03914 p->bufferoverrideinuse = 0;
03915 }
03916
03917 law = DAHDI_LAW_DEFAULT;
03918 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03919 if (res < 0)
03920 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03921
03922
03923 #ifdef HAVE_OPENR2
03924 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
03925 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
03926 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
03927 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
03928 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
03929 } else {
03930 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
03931 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
03932 openr2_call_disconnect_cause_t r2cause = r2cause_user
03933 ? dahdi_ast_cause_to_r2_cause(r2cause_user)
03934 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
03935 dahdi_r2_disconnect_call(p, r2cause);
03936 }
03937 } else if (p->mfcr2call) {
03938 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
03939 p->mfcr2call = 0;
03940 }
03941 #endif
03942
03943 #if defined(HAVE_PRI)
03944 if (p->pri) {
03945 #ifdef SUPPORT_USERUSER
03946 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03947 #endif
03948
03949
03950 pri_grab(p, p->pri);
03951 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03952 if (p->alreadyhungup) {
03953 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
03954
03955 #ifdef SUPPORT_USERUSER
03956 pri_call_set_useruser(p->call, useruser);
03957 #endif
03958
03959 pri_hangup(p->pri->pri, p->call, -1);
03960 p->call = NULL;
03961 if (p->bearer)
03962 p->bearer->call = NULL;
03963 } else {
03964 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03965 int icause = ast->hangupcause ? ast->hangupcause : -1;
03966 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03967
03968 #ifdef SUPPORT_USERUSER
03969 pri_call_set_useruser(p->call, useruser);
03970 #endif
03971
03972 p->alreadyhungup = 1;
03973 if (p->bearer)
03974 p->bearer->alreadyhungup = 1;
03975 if (cause) {
03976 if (atoi(cause))
03977 icause = atoi(cause);
03978 }
03979 pri_hangup(p->pri->pri, p->call, icause);
03980 }
03981 } else {
03982 if (p->bearer)
03983 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03984 p->call = NULL;
03985 }
03986 p->allocated = 0;
03987 p->owner = NULL;
03988 pri_rel(p->pri);
03989 res = 0;
03990 } else
03991 #endif
03992 {
03993 p->owner = NULL;
03994 }
03995 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
03996 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03997 if (res < 0) {
03998 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03999 }
04000 switch (p->sig) {
04001 case SIG_FXOGS:
04002 case SIG_FXOLS:
04003 case SIG_FXOKS:
04004 memset(&par, 0, sizeof(par));
04005 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04006 if (!res) {
04007 #if 0
04008 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04009 #endif
04010
04011 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04012 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04013 else
04014 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04015 }
04016 break;
04017 case SIG_FXSGS:
04018 case SIG_FXSLS:
04019 case SIG_FXSKS:
04020
04021
04022 if (ast->_state != AST_STATE_RESERVED) {
04023 time(&p->guardtime);
04024 p->guardtime += 2;
04025 }
04026 break;
04027 default:
04028 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04029 }
04030 free(p->cidspill);
04031 p->cidspill = NULL;
04032 if (p->sig)
04033 dahdi_disable_ec(p);
04034 x = 0;
04035 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04036 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04037 p->didtdd = 0;
04038 p->callwaitcas = 0;
04039 p->callwaiting = p->permcallwaiting;
04040 p->hidecallerid = p->permhidecallerid;
04041 p->dialing = 0;
04042 p->rdnis[0] = '\0';
04043 update_conf(p);
04044 reset_conf(p);
04045
04046 if (p->sig == SIG_PRI) {
04047 x = 0;
04048 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04049 }
04050 #ifdef HAVE_PRI
04051 if (p->bearer) {
04052 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
04053
04054
04055 update_conf(p->bearer);
04056 reset_conf(p->bearer);
04057 p->bearer->owner = NULL;
04058 p->bearer->realcall = NULL;
04059 p->bearer = NULL;
04060 p->subs[SUB_REAL].dfd = -1;
04061 p->pri = NULL;
04062 }
04063 #endif
04064 if (num_restart_pending == 0)
04065 restart_monitor();
04066 }
04067
04068 p->callwaitingrepeat = 0;
04069 p->cidcwexpire = 0;
04070 p->cid_suppress_expire = 0;
04071 p->oprmode = 0;
04072 ast->tech_pvt = NULL;
04073 ast_mutex_unlock(&p->lock);
04074 if (option_verbose > 2)
04075 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
04076
04077 ast_mutex_lock(&iflock);
04078 if (p->restartpending) {
04079 num_restart_pending--;
04080 }
04081
04082 tmp = iflist;
04083 prev = NULL;
04084 if (p->destroy) {
04085 while (tmp) {
04086 if (tmp == p) {
04087 destroy_channel(prev, tmp, 0);
04088 break;
04089 } else {
04090 prev = tmp;
04091 tmp = tmp->next;
04092 }
04093 }
04094 }
04095 ast_mutex_unlock(&iflock);
04096
04097 ast_module_unref(ast_module_info->self);
04098 return 0;
04099 }
04100
04101 static int dahdi_answer(struct ast_channel *ast)
04102 {
04103 struct dahdi_pvt *p = ast->tech_pvt;
04104 int res = 0;
04105 int index;
04106 int oldstate = ast->_state;
04107 ast_setstate(ast, AST_STATE_UP);
04108 ast_mutex_lock(&p->lock);
04109 index = dahdi_get_index(ast, p, 0);
04110 if (index < 0)
04111 index = SUB_REAL;
04112
04113 if ((p->radio || (p->oprmode < 0))) {
04114 ast_mutex_unlock(&p->lock);
04115 return 0;
04116 }
04117 switch (p->sig) {
04118 case SIG_FXSLS:
04119 case SIG_FXSGS:
04120 case SIG_FXSKS:
04121 p->ringt = 0;
04122
04123 case SIG_EM:
04124 case SIG_EM_E1:
04125 case SIG_EMWINK:
04126 case SIG_FEATD:
04127 case SIG_FEATDMF:
04128 case SIG_FEATDMF_TA:
04129 case SIG_E911:
04130 case SIG_FGC_CAMA:
04131 case SIG_FGC_CAMAMF:
04132 case SIG_FEATB:
04133 case SIG_SF:
04134 case SIG_SFWINK:
04135 case SIG_SF_FEATD:
04136 case SIG_SF_FEATDMF:
04137 case SIG_SF_FEATB:
04138 case SIG_FXOLS:
04139 case SIG_FXOGS:
04140 case SIG_FXOKS:
04141
04142 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
04143 if (p->hanguponpolarityswitch) {
04144 gettimeofday(&p->polaritydelaytv, NULL);
04145 }
04146 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04147 tone_zone_play_tone(p->subs[index].dfd, -1);
04148 p->dialing = 0;
04149 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04150 if (oldstate == AST_STATE_RINGING) {
04151 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
04152 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04153 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04154 p->owner = p->subs[SUB_REAL].owner;
04155 }
04156 }
04157 if (p->sig & __DAHDI_SIG_FXS) {
04158 dahdi_enable_ec(p);
04159 dahdi_train_ec(p);
04160 }
04161 break;
04162 #ifdef HAVE_PRI
04163 case SIG_PRI:
04164
04165 if (!pri_grab(p, p->pri)) {
04166 if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04167 p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04168 }
04169 p->dialing = 0;
04170 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04171 pri_rel(p->pri);
04172 } else {
04173 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04174 res = -1;
04175 }
04176 break;
04177 #endif
04178
04179 #ifdef HAVE_OPENR2
04180 case SIG_MFCR2:
04181 if (!p->mfcr2_accept_on_offer) {
04182
04183
04184 if (p->mfcr2_charge_calls) {
04185 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
04186 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04187 } else {
04188 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
04189 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04190 }
04191 } else {
04192 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04193 res = dahdi_r2_answer(p);
04194 }
04195 break;
04196 #endif
04197
04198 case 0:
04199 ast_mutex_unlock(&p->lock);
04200 return 0;
04201 default:
04202 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04203 res = -1;
04204 }
04205 ast_mutex_unlock(&p->lock);
04206 return res;
04207 }
04208
04209 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04210 {
04211 char *cp;
04212 signed char *scp;
04213 int x;
04214 int index;
04215 struct dahdi_pvt *p = chan->tech_pvt, *pp;
04216 struct oprmode *oprmode;
04217
04218
04219
04220 if (!data || (datalen < 1)) {
04221 errno = EINVAL;
04222 return -1;
04223 }
04224
04225 switch (option) {
04226 case AST_OPTION_TXGAIN:
04227 scp = (signed char *) data;
04228 index = dahdi_get_index(chan, p, 0);
04229 if (index < 0) {
04230 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04231 return -1;
04232 }
04233 if (option_debug)
04234 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04235 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
04236 case AST_OPTION_RXGAIN:
04237 scp = (signed char *) data;
04238 index = dahdi_get_index(chan, p, 0);
04239 if (index < 0) {
04240 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04241 return -1;
04242 }
04243 if (option_debug)
04244 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04245 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
04246 case AST_OPTION_TONE_VERIFY:
04247 if (!p->dsp)
04248 break;
04249 cp = (char *) data;
04250 switch (*cp) {
04251 case 1:
04252 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04253 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
04254 break;
04255 case 2:
04256 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04257 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
04258 break;
04259 default:
04260 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04261 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
04262 break;
04263 }
04264 break;
04265 case AST_OPTION_TDD:
04266
04267 cp = (char *) data;
04268 p->mate = 0;
04269 if (!*cp) {
04270 if (option_debug)
04271 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04272 if (p->tdd)
04273 tdd_free(p->tdd);
04274 p->tdd = 0;
04275 break;
04276 }
04277 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
04278 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04279 dahdi_disable_ec(p);
04280
04281 if (!p->didtdd) {
04282 unsigned char mybuf[41000];
04283 unsigned char *buf;
04284 int size, res, fd, len;
04285 struct pollfd fds[1];
04286
04287 buf = mybuf;
04288 memset(buf, 0x7f, sizeof(mybuf));
04289 ast_tdd_gen_ecdisa(buf + 16000, 16000);
04290 len = 40000;
04291 index = dahdi_get_index(chan, p, 0);
04292 if (index < 0) {
04293 ast_log(LOG_WARNING, "No index in TDD?\n");
04294 return -1;
04295 }
04296 fd = p->subs[index].dfd;
04297 while (len) {
04298 if (ast_check_hangup(chan))
04299 return -1;
04300 size = len;
04301 if (size > READ_SIZE)
04302 size = READ_SIZE;
04303 fds[0].fd = fd;
04304 fds[0].events = POLLPRI | POLLOUT;
04305 fds[0].revents = 0;
04306 res = poll(fds, 1, -1);
04307 if (!res) {
04308 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
04309 continue;
04310 }
04311
04312 if (fds[0].revents & POLLPRI)
04313 return -1;
04314 if (!(fds[0].revents & POLLOUT)) {
04315 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
04316 continue;
04317 }
04318 res = write(fd, buf, size);
04319 if (res != size) {
04320 if (res == -1) return -1;
04321 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04322 break;
04323 }
04324 len -= size;
04325 buf += size;
04326 }
04327 p->didtdd = 1;
04328 }
04329 if (*cp == 2) {
04330 if (p->tdd)
04331 tdd_free(p->tdd);
04332 p->tdd = 0;
04333 p->mate = 1;
04334 break;
04335 }
04336 if (!p->tdd) {
04337 p->tdd = tdd_new();
04338 }
04339 break;
04340 case AST_OPTION_RELAXDTMF:
04341 if (!p->dsp)
04342 break;
04343 cp = (char *) data;
04344 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04345 *cp ? "ON" : "OFF", (int) *cp, chan->name);
04346 p->dtmfrelax = 0;
04347 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
04348 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04349 break;
04350 case AST_OPTION_AUDIO_MODE:
04351 cp = (char *) data;
04352 if (!*cp) {
04353 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04354 x = 0;
04355 dahdi_disable_ec(p);
04356 } else {
04357 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04358 x = 1;
04359 }
04360 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04361 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04362 break;
04363 case AST_OPTION_OPRMODE:
04364 oprmode = (struct oprmode *) data;
04365 pp = oprmode->peer->tech_pvt;
04366 p->oprmode = pp->oprmode = 0;
04367
04368 p->oprpeer = pp;
04369 pp->oprpeer = p;
04370
04371 if (oprmode->mode)
04372 {
04373 pp->oprmode = oprmode->mode;
04374 p->oprmode = -oprmode->mode;
04375 }
04376 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
04377 oprmode->mode, chan->name,oprmode->peer->name);;
04378 break;
04379 case AST_OPTION_ECHOCAN:
04380 cp = (char *) data;
04381 if (*cp) {
04382 ast_log(LOG_DEBUG, "Enabling echo cancellation on %s\n", chan->name);
04383 dahdi_enable_ec(p);
04384 } else {
04385 ast_log(LOG_DEBUG, "Disabling echo cancellation on %s\n", chan->name);
04386 dahdi_disable_ec(p);
04387 }
04388 break;
04389 }
04390 errno = 0;
04391
04392 return 0;
04393 }
04394
04395 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
04396 {
04397 struct dahdi_pvt *p = chan->tech_pvt;
04398 int res = 0;
04399
04400 if (!strcasecmp(data, "rxgain")) {
04401 ast_mutex_lock(&p->lock);
04402 snprintf(buf, len, "%f", p->rxgain);
04403 ast_mutex_unlock(&p->lock);
04404 } else if (!strcasecmp(data, "txgain")) {
04405 ast_mutex_lock(&p->lock);
04406 snprintf(buf, len, "%f", p->txgain);
04407 ast_mutex_unlock(&p->lock);
04408 } else {
04409 ast_copy_string(buf, "", len);
04410 res = -1;
04411 }
04412
04413 return res;
04414 }
04415
04416
04417 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
04418 {
04419 int res;
04420 char policy_str[21] = "";
04421
04422 if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
04423 ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
04424 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
04425 return 1;
04426 }
04427 if (*num_buffers < 0) {
04428 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
04429 return -1;
04430 }
04431 if (!strcasecmp(policy_str, "full")) {
04432 *policy = DAHDI_POLICY_WHEN_FULL;
04433 } else if (!strcasecmp(policy_str, "immediate")) {
04434 *policy = DAHDI_POLICY_IMMEDIATE;
04435 #ifdef DAHDI_POLICY_HALF_FULL
04436 } else if (!strcasecmp(policy_str, "half")) {
04437 *policy = DAHDI_POLICY_HALF_FULL;
04438 #endif
04439 } else {
04440 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
04441 return -1;
04442 }
04443
04444 return 0;
04445 }
04446
04447 static int dahdi_func_write(struct ast_channel *chan, char *function, char *data, const char *value)
04448 {
04449 struct dahdi_pvt *p = chan->tech_pvt;
04450 int res = 0;
04451
04452 if (!strcasecmp(data, "buffers")) {
04453 int num_bufs, policy;
04454
04455 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
04456 struct dahdi_bufferinfo bi = {
04457 .txbufpolicy = policy,
04458 .rxbufpolicy = policy,
04459 .bufsize = p->bufsize,
04460 .numbufs = num_bufs,
04461 };
04462 int bpres;
04463
04464 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04465 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
04466 } else {
04467 p->bufferoverrideinuse = 1;
04468 }
04469 } else {
04470 res = -1;
04471 }
04472 } else {
04473 res = -1;
04474 }
04475
04476 return res;
04477 }
04478
04479 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04480 {
04481
04482 int x;
04483 int hasslaves;
04484 if (!master)
04485 return;
04486 if (needlock) {
04487 ast_mutex_lock(&master->lock);
04488 if (slave) {
04489 while (ast_mutex_trylock(&slave->lock)) {
04490 DEADLOCK_AVOIDANCE(&master->lock);
04491 }
04492 }
04493 }
04494 hasslaves = 0;
04495 for (x = 0; x < MAX_SLAVES; x++) {
04496 if (master->slaves[x]) {
04497 if (!slave || (master->slaves[x] == slave)) {
04498
04499 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04500 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04501 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04502 master->slaves[x]->master = NULL;
04503 master->slaves[x] = NULL;
04504 } else
04505 hasslaves = 1;
04506 }
04507 if (!hasslaves)
04508 master->inconference = 0;
04509 }
04510 if (!slave) {
04511 if (master->master) {
04512
04513 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04514 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04515 hasslaves = 0;
04516 for (x = 0; x < MAX_SLAVES; x++) {
04517 if (master->master->slaves[x] == master)
04518 master->master->slaves[x] = NULL;
04519 else if (master->master->slaves[x])
04520 hasslaves = 1;
04521 }
04522 if (!hasslaves)
04523 master->master->inconference = 0;
04524 }
04525 master->master = NULL;
04526 }
04527 update_conf(master);
04528 if (needlock) {
04529 if (slave)
04530 ast_mutex_unlock(&slave->lock);
04531 ast_mutex_unlock(&master->lock);
04532 }
04533 }
04534
04535 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04536 int x;
04537 if (!slave || !master) {
04538 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04539 return;
04540 }
04541 for (x = 0; x < MAX_SLAVES; x++) {
04542 if (!master->slaves[x]) {
04543 master->slaves[x] = slave;
04544 break;
04545 }
04546 }
04547 if (x >= MAX_SLAVES) {
04548 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04549 master->slaves[MAX_SLAVES - 1] = slave;
04550 }
04551 if (slave->master)
04552 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04553 slave->master = master;
04554
04555 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04556 }
04557
04558 static void disable_dtmf_detect(struct dahdi_pvt *p)
04559 {
04560 #ifdef DAHDI_TONEDETECT
04561 int val;
04562 #endif
04563
04564 p->ignoredtmf = 1;
04565
04566 #ifdef DAHDI_TONEDETECT
04567 val = 0;
04568 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04569 #endif
04570 if (!p->hardwaredtmf && p->dsp) {
04571 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04572 ast_dsp_set_features(p->dsp, p->dsp_features);
04573 }
04574 }
04575
04576 static void enable_dtmf_detect(struct dahdi_pvt *p)
04577 {
04578 #ifdef DAHDI_TONEDETECT
04579 int val;
04580 #endif
04581
04582 if (p->channel == CHAN_PSEUDO)
04583 return;
04584
04585 p->ignoredtmf = 0;
04586
04587 #ifdef DAHDI_TONEDETECT
04588 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04589 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04590 #endif
04591 if (!p->hardwaredtmf && p->dsp) {
04592 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04593 ast_dsp_set_features(p->dsp, p->dsp_features);
04594 }
04595 }
04596
04597 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
04598 {
04599 struct ast_channel *who;
04600 struct dahdi_pvt *p0, *p1, *op0, *op1;
04601 struct dahdi_pvt *master = NULL, *slave = NULL;
04602 struct ast_frame *f;
04603 int inconf = 0;
04604 int nothingok = 1;
04605 int ofd0, ofd1;
04606 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04607 int os0 = -1, os1 = -1;
04608 int priority = 0;
04609 struct ast_channel *oc0, *oc1;
04610 enum ast_bridge_result res;
04611
04612 #ifdef PRI_2BCT
04613 int triedtopribridge = 0;
04614 #endif
04615
04616
04617
04618
04619
04620
04621 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04622 return AST_BRIDGE_FAILED_NOWARN;
04623
04624 ast_mutex_lock(&c0->lock);
04625 while (ast_mutex_trylock(&c1->lock)) {
04626 DEADLOCK_AVOIDANCE(&c0->lock);
04627 }
04628
04629 p0 = c0->tech_pvt;
04630 p1 = c1->tech_pvt;
04631
04632 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04633 ast_mutex_unlock(&c0->lock);
04634 ast_mutex_unlock(&c1->lock);
04635 return AST_BRIDGE_FAILED_NOWARN;
04636 }
04637
04638 oi0 = dahdi_get_index(c0, p0, 0);
04639 oi1 = dahdi_get_index(c1, p1, 0);
04640 if ((oi0 < 0) || (oi1 < 0)) {
04641 ast_mutex_unlock(&c0->lock);
04642 ast_mutex_unlock(&c1->lock);
04643 return AST_BRIDGE_FAILED;
04644 }
04645
04646 op0 = p0 = c0->tech_pvt;
04647 op1 = p1 = c1->tech_pvt;
04648 ofd0 = c0->fds[0];
04649 ofd1 = c1->fds[0];
04650 oc0 = p0->owner;
04651 oc1 = p1->owner;
04652
04653 if (ast_mutex_trylock(&p0->lock)) {
04654
04655 ast_mutex_unlock(&c0->lock);
04656 ast_mutex_unlock(&c1->lock);
04657 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04658 return AST_BRIDGE_RETRY;
04659 }
04660 if (ast_mutex_trylock(&p1->lock)) {
04661
04662 ast_mutex_unlock(&p0->lock);
04663 ast_mutex_unlock(&c0->lock);
04664 ast_mutex_unlock(&c1->lock);
04665 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04666 return AST_BRIDGE_RETRY;
04667 }
04668
04669 if ((p0->callwaiting && p0->callwaitingcallerid)
04670 || (p1->callwaiting && p1->callwaitingcallerid)) {
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680 ast_mutex_unlock(&p0->lock);
04681 ast_mutex_unlock(&p1->lock);
04682 ast_mutex_unlock(&c0->lock);
04683 ast_mutex_unlock(&c1->lock);
04684 return AST_BRIDGE_FAILED_NOWARN;
04685 }
04686
04687 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04688 if (p0->owner && p1->owner) {
04689
04690 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04691 master = p0;
04692 slave = p1;
04693 inconf = 1;
04694 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04695 master = p1;
04696 slave = p0;
04697 inconf = 1;
04698 } else {
04699 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04700 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04701 p0->channel,
04702 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04703 p0->subs[SUB_REAL].inthreeway, p0->channel,
04704 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04705 p1->subs[SUB_REAL].inthreeway);
04706 }
04707 nothingok = 0;
04708 }
04709 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04710 if (p1->subs[SUB_THREEWAY].inthreeway) {
04711 master = p1;
04712 slave = p0;
04713 nothingok = 0;
04714 }
04715 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04716 if (p0->subs[SUB_THREEWAY].inthreeway) {
04717 master = p0;
04718 slave = p1;
04719 nothingok = 0;
04720 }
04721 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04722
04723
04724 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04725 master = p1;
04726 slave = p0;
04727 nothingok = 0;
04728 }
04729 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04730
04731 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04732 master = p0;
04733 slave = p1;
04734 nothingok = 0;
04735 }
04736 }
04737 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
04738 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04739 if (master && slave) {
04740
04741
04742
04743 if ((oi1 == SUB_THREEWAY) &&
04744 p1->subs[SUB_THREEWAY].inthreeway &&
04745 p1->subs[SUB_REAL].owner &&
04746 p1->subs[SUB_REAL].inthreeway &&
04747 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04748 ast_log(LOG_DEBUG,
04749 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
04750 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
04751 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04752 os1 = p1->subs[SUB_REAL].owner->_state;
04753 } else {
04754 ast_log(LOG_DEBUG, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
04755 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
04756 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04757 }
04758 if ((oi0 == SUB_THREEWAY) &&
04759 p0->subs[SUB_THREEWAY].inthreeway &&
04760 p0->subs[SUB_REAL].owner &&
04761 p0->subs[SUB_REAL].inthreeway &&
04762 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04763 ast_log(LOG_DEBUG,
04764 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
04765 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
04766 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04767 os0 = p0->subs[SUB_REAL].owner->_state;
04768 } else {
04769 ast_log(LOG_DEBUG, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
04770 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
04771 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
04772 }
04773 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04774 if (!p0->echocanbridged || !p1->echocanbridged) {
04775
04776 dahdi_disable_ec(p0);
04777 dahdi_disable_ec(p1);
04778 }
04779 }
04780 dahdi_link(slave, master);
04781 master->inconference = inconf;
04782 } else if (!nothingok)
04783 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04784
04785 update_conf(p0);
04786 update_conf(p1);
04787 t0 = p0->subs[SUB_REAL].inthreeway;
04788 t1 = p1->subs[SUB_REAL].inthreeway;
04789
04790 ast_mutex_unlock(&p0->lock);
04791 ast_mutex_unlock(&p1->lock);
04792
04793 ast_mutex_unlock(&c0->lock);
04794 ast_mutex_unlock(&c1->lock);
04795
04796
04797 if ((!master || !slave) && !nothingok) {
04798 dahdi_enable_ec(p0);
04799 dahdi_enable_ec(p1);
04800 return AST_BRIDGE_FAILED;
04801 }
04802
04803 if (option_verbose > 2)
04804 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
04805
04806 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04807 disable_dtmf_detect(op0);
04808
04809 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04810 disable_dtmf_detect(op1);
04811
04812 for (;;) {
04813 struct ast_channel *c0_priority[2] = {c0, c1};
04814 struct ast_channel *c1_priority[2] = {c1, c0};
04815
04816
04817
04818 ast_mutex_lock(&c0->lock);
04819 while (ast_mutex_trylock(&c1->lock)) {
04820 DEADLOCK_AVOIDANCE(&c0->lock);
04821 }
04822
04823 p0 = c0->tech_pvt;
04824 p1 = c1->tech_pvt;
04825
04826 if (op0 == p0)
04827 i0 = dahdi_get_index(c0, p0, 1);
04828 if (op1 == p1)
04829 i1 = dahdi_get_index(c1, p1, 1);
04830 ast_mutex_unlock(&c0->lock);
04831 ast_mutex_unlock(&c1->lock);
04832
04833 if (!timeoutms ||
04834 (op0 != p0) ||
04835 (op1 != p1) ||
04836 (ofd0 != c0->fds[0]) ||
04837 (ofd1 != c1->fds[0]) ||
04838 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04839 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04840 (oc0 != p0->owner) ||
04841 (oc1 != p1->owner) ||
04842 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04843 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04844 (oi0 != i0) ||
04845 (oi1 != i1)) {
04846 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04847 op0->channel, oi0, op1->channel, oi1);
04848 res = AST_BRIDGE_RETRY;
04849 goto return_from_bridge;
04850 }
04851
04852 #ifdef PRI_2BCT
04853 if (!triedtopribridge) {
04854 triedtopribridge = 1;
04855 if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
04856 ast_mutex_lock(&p0->pri->lock);
04857 if (p0->call && p1->call) {
04858 pri_channel_bridge(p0->call, p1->call);
04859 }
04860 ast_mutex_unlock(&p0->pri->lock);
04861 }
04862 }
04863 #endif
04864
04865 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04866 if (!who) {
04867 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
04868 continue;
04869 }
04870 f = ast_read(who);
04871 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04872 *fo = f;
04873 *rc = who;
04874 res = AST_BRIDGE_COMPLETE;
04875 goto return_from_bridge;
04876 }
04877 if (f->frametype == AST_FRAME_DTMF) {
04878 if ((who == c0) && p0->pulsedial) {
04879 ast_write(c1, f);
04880 } else if ((who == c1) && p1->pulsedial) {
04881 ast_write(c0, f);
04882 } else {
04883 *fo = f;
04884 *rc = who;
04885 res = AST_BRIDGE_COMPLETE;
04886 goto return_from_bridge;
04887 }
04888 }
04889 ast_frfree(f);
04890
04891
04892 priority = !priority;
04893 }
04894
04895 return_from_bridge:
04896 if (op0 == p0)
04897 dahdi_enable_ec(p0);
04898
04899 if (op1 == p1)
04900 dahdi_enable_ec(p1);
04901
04902 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04903 enable_dtmf_detect(op0);
04904
04905 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04906 enable_dtmf_detect(op1);
04907
04908 dahdi_unlink(slave, master, 1);
04909
04910 return res;
04911 }
04912
04913 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04914 {
04915 struct dahdi_pvt *p = newchan->tech_pvt;
04916 int x;
04917 ast_mutex_lock(&p->lock);
04918 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
04919 if (p->owner == oldchan) {
04920 p->owner = newchan;
04921 }
04922 for (x = 0; x < 3; x++)
04923 if (p->subs[x].owner == oldchan) {
04924 if (!x)
04925 dahdi_unlink(NULL, p, 0);
04926 p->subs[x].owner = newchan;
04927 }
04928 update_conf(p);
04929 ast_mutex_unlock(&p->lock);
04930 if (newchan->_state == AST_STATE_RINGING)
04931 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04932 return 0;
04933 }
04934
04935 static int dahdi_ring_phone(struct dahdi_pvt *p)
04936 {
04937 int x;
04938 int res;
04939
04940 x = 0;
04941 x = DAHDI_ONHOOK;
04942 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04943 do {
04944 x = DAHDI_RING;
04945 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04946 if (res) {
04947 switch (errno) {
04948 case EBUSY:
04949 case EINTR:
04950
04951 usleep(10000);
04952 continue;
04953 case EINPROGRESS:
04954 res = 0;
04955 break;
04956 default:
04957 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04958 res = 0;
04959 }
04960 }
04961 } while (res);
04962 return res;
04963 }
04964
04965 static void *ss_thread(void *data);
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981 static int attempt_transfer(struct dahdi_pvt *p)
04982 {
04983
04984
04985
04986 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04987
04988
04989 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04990 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04991 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04992
04993
04994
04995
04996
04997
04998
04999 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05000 }
05001 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05002 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05003 }
05004 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05005 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05006 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05007 return -1;
05008 }
05009
05010 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05011 unalloc_sub(p, SUB_THREEWAY);
05012 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05013 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05014 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05015
05016
05017
05018
05019
05020
05021
05022 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05023 }
05024 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05025 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05026 }
05027 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05028 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05029 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05030 return -1;
05031 }
05032
05033 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05034 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05035 unalloc_sub(p, SUB_THREEWAY);
05036
05037 return 1;
05038 } else {
05039 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05040 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05041 return -1;
05042 }
05043 return 0;
05044 }
05045
05046 static int check_for_conference(struct dahdi_pvt *p)
05047 {
05048 struct dahdi_confinfo ci;
05049
05050 if (p->master || (p->confno > -1))
05051 return 0;
05052 memset(&ci, 0, sizeof(ci));
05053 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05054 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05055 return 0;
05056 }
05057
05058
05059
05060 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05061 if (option_verbose > 2)
05062 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
05063 return 1;
05064 }
05065 return 0;
05066 }
05067
05068 static int get_alarms(struct dahdi_pvt *p)
05069 {
05070 int res;
05071 struct dahdi_spaninfo zi;
05072 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
05073
05074
05075
05076
05077
05078 struct dahdi_params params;
05079 #endif
05080
05081 memset(&zi, 0, sizeof(zi));
05082 zi.spanno = p->span;
05083
05084
05085 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
05086 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05087 return 0;
05088 }
05089 if (zi.alarms != DAHDI_ALARM_NONE)
05090 return zi.alarms;
05091 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
05092
05093 memset(¶ms, 0, sizeof(params));
05094 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
05095 return params.chan_alarms;
05096
05097 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05098 #endif
05099 return DAHDI_ALARM_NONE;
05100 }
05101
05102 static void dahdi_handle_dtmf(struct ast_channel *ast, int index, struct ast_frame **dest)
05103 {
05104 struct dahdi_pvt *p = ast->tech_pvt;
05105 struct ast_frame *f = *dest;
05106
05107 if (option_debug)
05108 ast_log(LOG_DEBUG, "%s DTMF digit: 0x%02X '%c' on %s\n",
05109 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
05110 f->subclass, f->subclass, ast->name);
05111
05112 if (p->confirmanswer) {
05113 if (f->frametype == AST_FRAME_DTMF_END) {
05114 if (option_debug)
05115 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
05116
05117
05118 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05119 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05120
05121 p->confirmanswer = 0;
05122 } else {
05123 p->subs[index].f.frametype = AST_FRAME_NULL;
05124 p->subs[index].f.subclass = 0;
05125 }
05126 *dest = &p->subs[index].f;
05127 } else if (p->callwaitcas) {
05128 if (f->frametype == AST_FRAME_DTMF_END) {
05129 if ((f->subclass == 'A') || (f->subclass == 'D')) {
05130 if (option_debug)
05131 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
05132 free(p->cidspill);
05133 p->cidspill = NULL;
05134 send_cwcidspill(p);
05135 }
05136 if ((f->subclass != 'm') && (f->subclass != 'u'))
05137 p->callwaitcas = 0;
05138 }
05139 p->subs[index].f.frametype = AST_FRAME_NULL;
05140 p->subs[index].f.subclass = 0;
05141 *dest = &p->subs[index].f;
05142 } else if (f->subclass == 'f') {
05143 if (f->frametype == AST_FRAME_DTMF_END) {
05144
05145 if ((p->callprogress & 0x6) && !p->faxhandled) {
05146 p->faxhandled = 1;
05147 if (strcmp(ast->exten, "fax")) {
05148 const char *target_context = S_OR(ast->macrocontext, ast->context);
05149
05150
05151
05152
05153
05154 ast_mutex_unlock(&p->lock);
05155 ast_channel_unlock(ast);
05156 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05157 ast_channel_lock(ast);
05158 ast_mutex_lock(&p->lock);
05159 if (option_verbose > 2)
05160 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
05161
05162 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05163 if (ast_async_goto(ast, target_context, "fax", 1))
05164 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05165 } else {
05166 ast_channel_lock(ast);
05167 ast_mutex_lock(&p->lock);
05168 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05169 }
05170 } else if (option_debug)
05171 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
05172 } else if (option_debug)
05173 ast_log(LOG_DEBUG, "Fax already handled\n");
05174 dahdi_confmute(p, 0);
05175 }
05176 p->subs[index].f.frametype = AST_FRAME_NULL;
05177 p->subs[index].f.subclass = 0;
05178 *dest = &p->subs[index].f;
05179 } else if (f->subclass == 'm') {
05180 if (f->frametype == AST_FRAME_DTMF_END) {
05181
05182 dahdi_confmute(p, 1);
05183 }
05184 p->subs[index].f.frametype = AST_FRAME_NULL;
05185 p->subs[index].f.subclass = 0;
05186 *dest = &p->subs[index].f;
05187 } else if (f->subclass == 'u') {
05188 if (f->frametype == AST_FRAME_DTMF_END) {
05189
05190 dahdi_confmute(p, 0);
05191 }
05192 p->subs[index].f.frametype = AST_FRAME_NULL;
05193 p->subs[index].f.subclass = 0;
05194 *dest = &p->subs[index].f;
05195 } else {
05196 if (f->frametype == AST_FRAME_DTMF_END) {
05197 dahdi_confmute(p, 0);
05198 }
05199 }
05200 }
05201
05202 static void handle_alarms(struct dahdi_pvt *p, int alarms)
05203 {
05204 const char *alarm_str = alarm2str(alarms);
05205
05206
05207
05208 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
05209 p->unknown_alarm = 1;
05210 return;
05211 } else {
05212 p->unknown_alarm = 0;
05213 }
05214
05215 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05216 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05217 "Alarm: %s\r\n"
05218 "Channel: %d\r\n",
05219 alarm_str, p->channel);
05220 }
05221
05222 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05223 {
05224 int res, x;
05225 int index, mysig;
05226 char *c;
05227 struct dahdi_pvt *p = ast->tech_pvt;
05228 pthread_t threadid;
05229 pthread_attr_t attr;
05230 struct ast_channel *chan;
05231 struct ast_frame *f;
05232
05233 index = dahdi_get_index(ast, p, 0);
05234 if (index < 0) {
05235 return &ast_null_frame;
05236 }
05237 if (index != SUB_REAL) {
05238 ast_log(LOG_ERROR, "We got an event on a non real sub. Fix it!\n");
05239 }
05240
05241 mysig = p->sig;
05242 if (p->outsigmod > -1)
05243 mysig = p->outsigmod;
05244
05245 p->subs[index].f.frametype = AST_FRAME_NULL;
05246 p->subs[index].f.subclass = 0;
05247 p->subs[index].f.datalen = 0;
05248 p->subs[index].f.samples = 0;
05249 p->subs[index].f.mallocd = 0;
05250 p->subs[index].f.offset = 0;
05251 p->subs[index].f.src = "dahdi_handle_event";
05252 p->subs[index].f.data = NULL;
05253 f = &p->subs[index].f;
05254
05255 if (p->fake_event) {
05256 res = p->fake_event;
05257 p->fake_event = 0;
05258 } else
05259 res = dahdi_get_event(p->subs[index].dfd);
05260
05261 if (option_debug)
05262 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
05263
05264 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05265 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05266
05267 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05268 #ifdef HAVE_PRI
05269 if (p->sig == SIG_PRI
05270 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
05271 && p->pri
05272 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05273
05274 } else
05275 #endif
05276 {
05277 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
05278 p->subs[index].f.subclass = res & 0xff;
05279 dahdi_handle_dtmf(ast, index, &f);
05280 }
05281 return f;
05282 }
05283
05284 if (res & DAHDI_EVENT_DTMFDOWN) {
05285 if (option_debug)
05286 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
05287 #ifdef HAVE_PRI
05288 if (p->sig == SIG_PRI
05289 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
05290 && p->pri
05291 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05292
05293 } else
05294 #endif
05295 {
05296
05297 dahdi_confmute(p, 1);
05298 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
05299 p->subs[index].f.subclass = res & 0xff;
05300 dahdi_handle_dtmf(ast, index, &f);
05301 }
05302 return &p->subs[index].f;
05303 }
05304
05305 switch (res) {
05306 #ifdef DAHDI_EVENT_EC_DISABLED
05307 case DAHDI_EVENT_EC_DISABLED:
05308 if (option_verbose > 2)
05309 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
05310 p->echocanon = 0;
05311 break;
05312 #endif
05313 case DAHDI_EVENT_BITSCHANGED:
05314 #ifdef HAVE_OPENR2
05315 if (p->sig != SIG_MFCR2) {
05316 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05317 } else {
05318 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05319 openr2_chan_handle_cas(p->r2chan);
05320 }
05321 #else
05322 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05323 #endif
05324 case DAHDI_EVENT_PULSE_START:
05325
05326 if (!ast->pbx)
05327 tone_zone_play_tone(p->subs[index].dfd, -1);
05328 break;
05329 case DAHDI_EVENT_DIALCOMPLETE:
05330 #ifdef HAVE_OPENR2
05331 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05332
05333
05334 break;
05335 }
05336 #endif
05337 if (p->inalarm) break;
05338 if ((p->radio || (p->oprmode < 0))) break;
05339 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
05340 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05341 return NULL;
05342 }
05343 if (!x) {
05344 dahdi_enable_ec(p);
05345 if (p->echobreak) {
05346 dahdi_train_ec(p);
05347 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05348 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05349 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05350 p->echobreak = 0;
05351 } else {
05352 p->dialing = 0;
05353 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05354
05355 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05356 ast_setstate(ast, AST_STATE_UP);
05357 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05358 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05359 break;
05360 } else {
05361
05362 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05363 }
05364 }
05365 if (ast->_state == AST_STATE_DIALING) {
05366 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05367 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
05368 } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
05369 ast_setstate(ast, AST_STATE_RINGING);
05370 } else if (!p->answeronpolarityswitch) {
05371 ast_setstate(ast, AST_STATE_UP);
05372 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05373 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05374
05375 p->polarity = POLARITY_REV;
05376 } else {
05377
05378 p->polarity = POLARITY_IDLE;
05379 }
05380 }
05381 }
05382 }
05383 break;
05384 case DAHDI_EVENT_ALARM:
05385 #ifdef HAVE_PRI
05386 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05387
05388 if (p->call) {
05389 if (p->pri && p->pri->pri) {
05390 pri_grab(p, p->pri);
05391 pri_destroycall(p->pri->pri, p->call);
05392 p->call = NULL;
05393 pri_rel(p->pri);
05394 } else
05395 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05396 }
05397 if (p->owner)
05398 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05399 }
05400 if (p->bearer) {
05401 p->bearer->inalarm = 1;
05402 p->bearer->resetting = 0;
05403 } else
05404 #endif
05405 {
05406 p->inalarm = 1;
05407 #if defined(HAVE_PRI)
05408 p->resetting = 0;
05409 #endif
05410 }
05411 res = get_alarms(p);
05412 handle_alarms(p, res);
05413 #ifdef HAVE_PRI
05414 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05415
05416 } else {
05417 break;
05418 }
05419 #endif
05420
05421 #ifdef HAVE_OPENR2
05422 if (p->sig == SIG_MFCR2)
05423 break;
05424 #endif
05425
05426 case DAHDI_EVENT_ONHOOK:
05427 if (p->radio) {
05428 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05429 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05430 break;
05431 }
05432 if (p->oprmode < 0)
05433 {
05434 if (p->oprmode != -1) break;
05435 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05436 {
05437
05438 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05439 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05440 save_conference(p->oprpeer);
05441 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05442 }
05443 break;
05444 }
05445 switch (p->sig) {
05446 case SIG_FXOLS:
05447 case SIG_FXOGS:
05448 case SIG_FXOKS:
05449 p->onhooktime = time(NULL);
05450 p->msgstate = -1;
05451
05452 if (index == SUB_REAL) {
05453
05454 if (p->subs[SUB_CALLWAIT].owner) {
05455
05456 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
05457 if (!p->subs[SUB_CALLWAIT].owner) {
05458
05459
05460
05461
05462 dahdi_disable_ec(p);
05463 return NULL;
05464 }
05465
05466
05467 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05468 if (option_verbose > 2)
05469 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05470 unalloc_sub(p, SUB_CALLWAIT);
05471 #if 0
05472 p->subs[index].needanswer = 0;
05473 p->subs[index].needringing = 0;
05474 #endif
05475 p->callwaitingrepeat = 0;
05476 p->cidcwexpire = 0;
05477 p->cid_suppress_expire = 0;
05478 p->owner = NULL;
05479
05480 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05481 p->dialing = 1;
05482
05483 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05484 dahdi_ring_phone(p);
05485 } else if (p->subs[SUB_THREEWAY].owner) {
05486 unsigned int mssinceflash;
05487
05488
05489 dahdi_lock_sub_owner(p, SUB_THREEWAY);
05490 if (!p->subs[SUB_THREEWAY].owner) {
05491 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05492
05493 return NULL;
05494 }
05495 if (p->owner != ast) {
05496 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05497 ast_log(LOG_WARNING, "This isn't good...\n");
05498
05499 return NULL;
05500 }
05501
05502 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05503 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
05504 if (mssinceflash < MIN_MS_SINCE_FLASH) {
05505
05506
05507 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05508 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
05509 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05510 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05511 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05512 if (p->transfer) {
05513
05514 p->subs[SUB_REAL].inthreeway = 0;
05515 p->subs[SUB_THREEWAY].inthreeway = 0;
05516
05517 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05518
05519 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05520
05521 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05522 p->owner = NULL;
05523
05524 dahdi_ring_phone(p);
05525 } else {
05526 res = attempt_transfer(p);
05527 if (res < 0) {
05528
05529 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05530 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05531 } else if (res) {
05532
05533 break;
05534 }
05535 }
05536 } else {
05537 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05538 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05539 }
05540 } else {
05541
05542 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05543
05544 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05545 p->owner = NULL;
05546
05547 dahdi_ring_phone(p);
05548 }
05549 }
05550 } else {
05551 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
05552 }
05553
05554 default:
05555 dahdi_disable_ec(p);
05556 return NULL;
05557 }
05558 break;
05559 case DAHDI_EVENT_RINGOFFHOOK:
05560 if (p->inalarm) break;
05561 if (p->oprmode < 0)
05562 {
05563 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05564 {
05565
05566 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05567 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
05568 restore_conference(p->oprpeer);
05569 }
05570 break;
05571 }
05572 if (p->radio)
05573 {
05574 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05575 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05576 break;
05577 }
05578
05579
05580 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05581 c = strchr(p->dialdest, '/');
05582 if (c)
05583 c++;
05584 else
05585 c = p->dialdest;
05586 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05587 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05588 if (strlen(p->dop.dialstr) > 4) {
05589 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05590 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05591 p->echorest[sizeof(p->echorest) - 1] = '\0';
05592 p->echobreak = 1;
05593 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05594 } else
05595 p->echobreak = 0;
05596 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05597 int saveerr = errno;
05598
05599 x = DAHDI_ONHOOK;
05600 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05601 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05602 return NULL;
05603 }
05604 p->dialing = 1;
05605 return &p->subs[index].f;
05606 }
05607 switch (p->sig) {
05608 case SIG_FXOLS:
05609 case SIG_FXOGS:
05610 case SIG_FXOKS:
05611 switch (ast->_state) {
05612 case AST_STATE_RINGING:
05613 dahdi_enable_ec(p);
05614 dahdi_train_ec(p);
05615 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05616 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05617
05618 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05619 p->subs[SUB_REAL].needringing = 0;
05620 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
05621
05622
05623 free(p->cidspill);
05624 p->cidspill = NULL;
05625 restore_conference(p);
05626
05627 p->dialing = 0;
05628 p->callwaitcas = 0;
05629 if (p->confirmanswer) {
05630
05631 p->subs[index].f.frametype = AST_FRAME_NULL;
05632 p->subs[index].f.subclass = 0;
05633 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05634
05635 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05636 if (res < 0) {
05637 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05638 p->dop.dialstr[0] = '\0';
05639 return NULL;
05640 } else {
05641 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05642 p->subs[index].f.frametype = AST_FRAME_NULL;
05643 p->subs[index].f.subclass = 0;
05644 p->dialing = 1;
05645 }
05646 p->dop.dialstr[0] = '\0';
05647 ast_setstate(ast, AST_STATE_DIALING);
05648 } else
05649 ast_setstate(ast, AST_STATE_UP);
05650 return &p->subs[index].f;
05651 case AST_STATE_DOWN:
05652 ast_setstate(ast, AST_STATE_RING);
05653 ast->rings = 1;
05654 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05655 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05656 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
05657 return &p->subs[index].f;
05658 case AST_STATE_UP:
05659
05660 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05661
05662 if (ast_bridged_channel(p->owner))
05663 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05664 p->subs[index].needunhold = 1;
05665 break;
05666 case AST_STATE_RESERVED:
05667
05668 if (has_voicemail(p))
05669 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05670 else
05671 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05672 break;
05673 default:
05674 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05675 }
05676 break;
05677 case SIG_FXSLS:
05678 case SIG_FXSGS:
05679 case SIG_FXSKS:
05680 if (ast->_state == AST_STATE_RING) {
05681 p->ringt = p->ringt_base;
05682 }
05683
05684
05685 case SIG_EM:
05686 case SIG_EM_E1:
05687 case SIG_EMWINK:
05688 case SIG_FEATD:
05689 case SIG_FEATDMF:
05690 case SIG_FEATDMF_TA:
05691 case SIG_E911:
05692 case SIG_FGC_CAMA:
05693 case SIG_FGC_CAMAMF:
05694 case SIG_FEATB:
05695 case SIG_SF:
05696 case SIG_SFWINK:
05697 case SIG_SF_FEATD:
05698 case SIG_SF_FEATDMF:
05699 case SIG_SF_FEATB:
05700 if (ast->_state == AST_STATE_PRERING)
05701 ast_setstate(ast, AST_STATE_RING);
05702 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05703 if (option_debug)
05704 ast_log(LOG_DEBUG, "Ring detected\n");
05705 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05706 p->subs[index].f.subclass = AST_CONTROL_RING;
05707 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05708 if (option_debug)
05709 ast_log(LOG_DEBUG, "Line answered\n");
05710 if (p->confirmanswer) {
05711 p->subs[index].f.frametype = AST_FRAME_NULL;
05712 p->subs[index].f.subclass = 0;
05713 } else {
05714 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05715 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05716 ast_setstate(ast, AST_STATE_UP);
05717 }
05718 } else if (ast->_state != AST_STATE_RING)
05719 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05720 break;
05721 default:
05722 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05723 }
05724 break;
05725 #ifdef DAHDI_EVENT_RINGBEGIN
05726 case DAHDI_EVENT_RINGBEGIN:
05727 switch (p->sig) {
05728 case SIG_FXSLS:
05729 case SIG_FXSGS:
05730 case SIG_FXSKS:
05731 if (ast->_state == AST_STATE_RING) {
05732 p->ringt = p->ringt_base;
05733 }
05734 break;
05735 }
05736 break;
05737 #endif
05738 case DAHDI_EVENT_RINGEROFF:
05739 if (p->inalarm) break;
05740 if ((p->radio || (p->oprmode < 0))) break;
05741 ast->rings++;
05742 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05743 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05744 free(p->cidspill);
05745 p->cidspill = NULL;
05746 p->callwaitcas = 0;
05747 }
05748 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05749 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05750 break;
05751 case DAHDI_EVENT_RINGERON:
05752 break;
05753 case DAHDI_EVENT_NOALARM:
05754 p->inalarm = 0;
05755 #ifdef HAVE_PRI
05756 p->resetting = 0;
05757
05758 if (p->bearer) {
05759 p->bearer->inalarm = 0;
05760 p->bearer->resetting = 0;
05761 }
05762 #endif
05763 if (!p->unknown_alarm) {
05764 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05765 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05766 "Channel: %d\r\n", p->channel);
05767 } else {
05768 p->unknown_alarm = 0;
05769 }
05770 break;
05771 case DAHDI_EVENT_WINKFLASH:
05772 if (p->inalarm) break;
05773 if (p->radio) break;
05774 if (p->oprmode < 0) break;
05775 if (p->oprmode > 1)
05776 {
05777 struct dahdi_params par;
05778
05779 memset(&par, 0, sizeof(par));
05780 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05781 {
05782 if (!par.rxisoffhook)
05783 {
05784
05785 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05786 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05787 save_conference(p);
05788 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05789 }
05790 }
05791 break;
05792 }
05793
05794 gettimeofday(&p->flashtime, NULL);
05795 switch (mysig) {
05796 case SIG_FXOLS:
05797 case SIG_FXOGS:
05798 case SIG_FXOKS:
05799 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05800 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05801
05802
05803 free(p->cidspill);
05804 p->cidspill = NULL;
05805 restore_conference(p);
05806 p->callwaitcas = 0;
05807
05808 if (index != SUB_REAL) {
05809 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05810 goto winkflashdone;
05811 }
05812
05813 if (p->subs[SUB_CALLWAIT].owner) {
05814
05815 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
05816 if (!p->subs[SUB_CALLWAIT].owner) {
05817
05818
05819
05820
05821 ast_log(LOG_NOTICE, "Whoa, the call-waiting call disappeared.\n");
05822 goto winkflashdone;
05823 }
05824
05825
05826 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05827 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05828 p->owner = p->subs[SUB_REAL].owner;
05829 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
05830 if (p->owner->_state == AST_STATE_RINGING) {
05831 ast_setstate(p->owner, AST_STATE_UP);
05832 p->subs[SUB_REAL].needanswer = 1;
05833 }
05834 p->callwaitingrepeat = 0;
05835 p->cidcwexpire = 0;
05836 p->cid_suppress_expire = 0;
05837
05838
05839 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05840 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05841 S_OR(p->mohsuggest, NULL),
05842 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05843 }
05844 p->subs[SUB_CALLWAIT].needhold = 1;
05845 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05846 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05847 S_OR(p->mohsuggest, NULL),
05848 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05849 }
05850 p->subs[SUB_REAL].needunhold = 1;
05851
05852
05853 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05854 } else if (!p->subs[SUB_THREEWAY].owner) {
05855 if (!p->threewaycalling) {
05856
05857 p->subs[SUB_REAL].needflash = 1;
05858 goto winkflashdone;
05859 } else if (!check_for_conference(p)) {
05860 char cid_num[256];
05861 char cid_name[256];
05862
05863 cid_num[0] = 0;
05864 cid_name[0] = 0;
05865 if (p->dahditrcallerid && p->owner) {
05866 if (p->owner->cid.cid_num)
05867 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05868 if (p->owner->cid.cid_name)
05869 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05870 }
05871
05872
05873 if (!((ast->pbx) ||
05874 (ast->_state == AST_STATE_UP) ||
05875 (ast->_state == AST_STATE_RING))) {
05876 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
05877 goto winkflashdone;
05878 }
05879 if (alloc_sub(p, SUB_THREEWAY)) {
05880 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05881 goto winkflashdone;
05882 }
05883
05884 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05885 if (!chan) {
05886 ast_log(LOG_WARNING,
05887 "Cannot allocate new call structure on channel %d\n",
05888 p->channel);
05889 unalloc_sub(p, SUB_THREEWAY);
05890 goto winkflashdone;
05891 }
05892 if (p->dahditrcallerid) {
05893 if (!p->origcid_num)
05894 p->origcid_num = ast_strdup(p->cid_num);
05895 if (!p->origcid_name)
05896 p->origcid_name = ast_strdup(p->cid_name);
05897 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05898 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05899 }
05900
05901 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05902
05903 dahdi_disable_ec(p);
05904 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05905 if (res)
05906 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05907 p->owner = chan;
05908 pthread_attr_init(&attr);
05909 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05910 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
05911 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05912 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05913 dahdi_enable_ec(p);
05914 ast_hangup(chan);
05915 } else {
05916 if (option_verbose > 2)
05917 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
05918
05919 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05920 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05921 S_OR(p->mohsuggest, NULL),
05922 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05923 }
05924 p->subs[SUB_THREEWAY].needhold = 1;
05925 }
05926 pthread_attr_destroy(&attr);
05927 }
05928 } else {
05929
05930 int orig_3way_sub;
05931
05932
05933 dahdi_lock_sub_owner(p, SUB_THREEWAY);
05934 if (!p->subs[SUB_THREEWAY].owner) {
05935
05936
05937
05938
05939 ast_log(LOG_NOTICE, "Whoa, the 3-way call disappeared.\n");
05940 goto winkflashdone;
05941 }
05942 orig_3way_sub = SUB_THREEWAY;
05943
05944 if (p->subs[SUB_THREEWAY].inthreeway) {
05945
05946 if (option_debug)
05947 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05948
05949 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05950
05951 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05952 orig_3way_sub = SUB_REAL;
05953 p->owner = p->subs[SUB_REAL].owner;
05954 }
05955
05956 if (option_verbose > 2)
05957 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05958 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05959 p->subs[SUB_REAL].inthreeway = 0;
05960 p->subs[SUB_THREEWAY].inthreeway = 0;
05961 } else {
05962
05963 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05964 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05965 if (option_verbose > 2) {
05966 ast_verbose(VERBOSE_PREFIX_3 "Building conference call with %s and %s\n",
05967 p->subs[SUB_THREEWAY].owner->name,
05968 p->subs[SUB_REAL].owner->name);
05969 }
05970
05971 p->subs[SUB_THREEWAY].inthreeway = 1;
05972 p->subs[SUB_REAL].inthreeway = 1;
05973 if (ast->_state == AST_STATE_UP) {
05974 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05975 orig_3way_sub = SUB_REAL;
05976 }
05977 if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) {
05978 ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD);
05979 }
05980 p->subs[orig_3way_sub].needunhold = 1;
05981 p->owner = p->subs[SUB_REAL].owner;
05982 } else {
05983 if (option_verbose > 2)
05984 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05985 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05986 orig_3way_sub = SUB_REAL;
05987 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05988 p->owner = p->subs[SUB_REAL].owner;
05989 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05990 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05991 }
05992 p->subs[SUB_REAL].needunhold = 1;
05993 dahdi_enable_ec(p);
05994 }
05995
05996 }
05997 ast_mutex_unlock(&p->subs[orig_3way_sub].owner->lock);
05998 }
05999 winkflashdone:
06000 update_conf(p);
06001 break;
06002 case SIG_EM:
06003 case SIG_EM_E1:
06004 case SIG_FEATD:
06005 case SIG_SF:
06006 case SIG_SFWINK:
06007 case SIG_SF_FEATD:
06008 case SIG_FXSLS:
06009 case SIG_FXSGS:
06010 if (p->dialing)
06011 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
06012 else
06013 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06014 break;
06015 case SIG_FEATDMF_TA:
06016 switch (p->whichwink) {
06017 case 0:
06018 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06019 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06020 break;
06021 case 1:
06022 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06023 break;
06024 case 2:
06025 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06026 return NULL;
06027 }
06028 p->whichwink++;
06029
06030 case SIG_FEATDMF:
06031 case SIG_E911:
06032 case SIG_FGC_CAMAMF:
06033 case SIG_FGC_CAMA:
06034 case SIG_FEATB:
06035 case SIG_SF_FEATDMF:
06036 case SIG_SF_FEATB:
06037 case SIG_EMWINK:
06038
06039 if (!ast_strlen_zero(p->dop.dialstr)) {
06040 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06041 if (res < 0) {
06042 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06043 p->dop.dialstr[0] = '\0';
06044 return NULL;
06045 } else
06046 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
06047 }
06048 p->dop.dialstr[0] = '\0';
06049 break;
06050 default:
06051 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
06052 }
06053 break;
06054 case DAHDI_EVENT_HOOKCOMPLETE:
06055 if (p->inalarm) break;
06056 if ((p->radio || (p->oprmode < 0))) break;
06057 switch (mysig) {
06058 case SIG_FXSLS:
06059 case SIG_FXSGS:
06060 case SIG_FXSKS:
06061 case SIG_EM:
06062 case SIG_EM_E1:
06063 case SIG_EMWINK:
06064 case SIG_FEATD:
06065 case SIG_SF:
06066 case SIG_SFWINK:
06067 case SIG_SF_FEATD:
06068 if (!ast_strlen_zero(p->dop.dialstr)) {
06069 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06070 if (res < 0) {
06071 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06072 p->dop.dialstr[0] = '\0';
06073 return NULL;
06074 } else
06075 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
06076 }
06077 p->dop.dialstr[0] = '\0';
06078 p->dop.op = DAHDI_DIAL_OP_REPLACE;
06079 break;
06080 case SIG_FEATDMF:
06081 case SIG_FEATDMF_TA:
06082 case SIG_E911:
06083 case SIG_FGC_CAMA:
06084 case SIG_FGC_CAMAMF:
06085 case SIG_FEATB:
06086 case SIG_SF_FEATDMF:
06087 case SIG_SF_FEATB:
06088 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06089 break;
06090 default:
06091 break;
06092 }
06093 break;
06094 case DAHDI_EVENT_POLARITY:
06095
06096
06097
06098
06099
06100
06101 if (p->polarity == POLARITY_IDLE) {
06102 p->polarity = POLARITY_REV;
06103 if (p->answeronpolarityswitch &&
06104 ((ast->_state == AST_STATE_DIALING) ||
06105 (ast->_state == AST_STATE_RINGING))) {
06106 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
06107 ast_setstate(p->owner, AST_STATE_UP);
06108 if (p->hanguponpolarityswitch) {
06109 gettimeofday(&p->polaritydelaytv, NULL);
06110 }
06111 } else
06112 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
06113 }
06114
06115
06116 if (p->hanguponpolarityswitch &&
06117 (p->polarityonanswerdelay > 0) &&
06118 (p->polarity == POLARITY_REV) &&
06119 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
06120
06121 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
06122
06123 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06124 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
06125 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06126 p->polarity = POLARITY_IDLE;
06127 } else {
06128 ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
06129 }
06130 } else {
06131 p->polarity = POLARITY_IDLE;
06132 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
06133 }
06134
06135 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
06136 break;
06137 default:
06138 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06139 }
06140 return &p->subs[index].f;
06141 }
06142
06143 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06144 {
06145 struct dahdi_pvt *p = ast->tech_pvt;
06146 int res;
06147 int index;
06148 struct ast_frame *f;
06149
06150
06151 index = dahdi_get_index(ast, p, 1);
06152 if (index < 0) {
06153 index = SUB_REAL;
06154 }
06155
06156 p->subs[index].f.frametype = AST_FRAME_NULL;
06157 p->subs[index].f.datalen = 0;
06158 p->subs[index].f.samples = 0;
06159 p->subs[index].f.mallocd = 0;
06160 p->subs[index].f.offset = 0;
06161 p->subs[index].f.subclass = 0;
06162 p->subs[index].f.delivery = ast_tv(0,0);
06163 p->subs[index].f.src = "dahdi_exception";
06164 p->subs[index].f.data = NULL;
06165
06166 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06167
06168
06169
06170
06171
06172 if (p->fake_event) {
06173 res = p->fake_event;
06174 p->fake_event = 0;
06175 } else
06176 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06177
06178 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06179 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06180 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
06181 p->owner = p->subs[SUB_REAL].owner;
06182 if (p->owner && ast != p->owner) {
06183
06184
06185
06186
06187 ast_log(LOG_WARNING, "Event %s on %s is not restored owner %s\n",
06188 event2str(res), ast->name, p->owner->name);
06189 }
06190 if (p->owner && ast_bridged_channel(p->owner))
06191 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06192 p->subs[SUB_REAL].needunhold = 1;
06193 }
06194 switch (res) {
06195 case DAHDI_EVENT_ONHOOK:
06196 dahdi_disable_ec(p);
06197 if (p->owner) {
06198 if (option_verbose > 2)
06199 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
06200 dahdi_ring_phone(p);
06201 p->callwaitingrepeat = 0;
06202 p->cidcwexpire = 0;
06203 p->cid_suppress_expire = 0;
06204 } else {
06205 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
06206 event2str(res));
06207 }
06208 update_conf(p);
06209 break;
06210 case DAHDI_EVENT_RINGOFFHOOK:
06211 dahdi_enable_ec(p);
06212 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06213 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06214 p->subs[SUB_REAL].needanswer = 1;
06215 p->dialing = 0;
06216 }
06217 break;
06218 case DAHDI_EVENT_HOOKCOMPLETE:
06219 case DAHDI_EVENT_RINGERON:
06220 case DAHDI_EVENT_RINGEROFF:
06221
06222 break;
06223 case DAHDI_EVENT_WINKFLASH:
06224 gettimeofday(&p->flashtime, NULL);
06225 if (p->owner) {
06226 if (option_verbose > 2)
06227 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06228 if (p->owner->_state != AST_STATE_UP) {
06229
06230 p->subs[SUB_REAL].needanswer = 1;
06231 ast_setstate(p->owner, AST_STATE_UP);
06232 }
06233 p->callwaitingrepeat = 0;
06234 p->cidcwexpire = 0;
06235 p->cid_suppress_expire = 0;
06236 if (ast_bridged_channel(p->owner))
06237 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06238 p->subs[SUB_REAL].needunhold = 1;
06239 } else {
06240 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
06241 event2str(res));
06242 }
06243 update_conf(p);
06244 break;
06245 default:
06246 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
06247 break;
06248 }
06249 f = &p->subs[index].f;
06250 return f;
06251 }
06252 if (!(p->radio || (p->oprmode < 0)) && option_debug)
06253 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
06254
06255 if (ast != p->owner) {
06256 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
06257 f = &p->subs[index].f;
06258 return f;
06259 }
06260 f = dahdi_handle_event(ast);
06261 return f;
06262 }
06263
06264 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
06265 {
06266 struct dahdi_pvt *p = ast->tech_pvt;
06267 struct ast_frame *f;
06268 ast_mutex_lock(&p->lock);
06269 f = __dahdi_exception(ast);
06270 ast_mutex_unlock(&p->lock);
06271 return f;
06272 }
06273
06274 static struct ast_frame *dahdi_read(struct ast_channel *ast)
06275 {
06276 struct dahdi_pvt *p;
06277 int res;
06278 int index;
06279 void *readbuf;
06280 struct ast_frame *f;
06281
06282
06283
06284
06285
06286
06287 p = ast->tech_pvt;
06288 while (ast_mutex_trylock(&p->lock)) {
06289 DEADLOCK_AVOIDANCE(&ast->lock);
06290
06291
06292
06293
06294
06295
06296 p = ast->tech_pvt;
06297 }
06298
06299 index = dahdi_get_index(ast, p, 0);
06300
06301
06302 if (index < 0) {
06303 ast_log(LOG_WARNING, "We don't exist?\n");
06304 ast_mutex_unlock(&p->lock);
06305 return NULL;
06306 }
06307
06308 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
06309 ast_mutex_unlock(&p->lock);
06310 return NULL;
06311 }
06312
06313 p->subs[index].f.frametype = AST_FRAME_NULL;
06314 p->subs[index].f.datalen = 0;
06315 p->subs[index].f.samples = 0;
06316 p->subs[index].f.mallocd = 0;
06317 p->subs[index].f.offset = 0;
06318 p->subs[index].f.subclass = 0;
06319 p->subs[index].f.delivery = ast_tv(0,0);
06320 p->subs[index].f.src = "dahdi_read";
06321 p->subs[index].f.data = NULL;
06322
06323
06324 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
06325 {
06326 struct dahdi_params ps;
06327
06328 memset(&ps, 0, sizeof(ps));
06329 ps.channo = p->channel;
06330 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
06331 ast_mutex_unlock(&p->lock);
06332 return NULL;
06333 }
06334 p->firstradio = 1;
06335 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06336 if (ps.rxisoffhook)
06337 {
06338 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
06339 }
06340 else
06341 {
06342 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
06343 }
06344 ast_mutex_unlock(&p->lock);
06345 return &p->subs[index].f;
06346 }
06347 if (p->ringt == 1) {
06348 ast_mutex_unlock(&p->lock);
06349 return NULL;
06350 }
06351 else if (p->ringt > 0)
06352 p->ringt--;
06353
06354 #ifdef HAVE_OPENR2
06355 if (p->mfcr2) {
06356 openr2_chan_process_event(p->r2chan);
06357 }
06358 #endif
06359
06360 if (p->subs[index].needringing) {
06361
06362 p->subs[index].needringing = 0;
06363 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06364 p->subs[index].f.subclass = AST_CONTROL_RINGING;
06365 ast_setstate(ast, AST_STATE_RINGING);
06366 ast_mutex_unlock(&p->lock);
06367 return &p->subs[index].f;
06368 }
06369
06370 if (p->subs[index].needbusy) {
06371
06372 p->subs[index].needbusy = 0;
06373 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06374 p->subs[index].f.subclass = AST_CONTROL_BUSY;
06375 ast_mutex_unlock(&p->lock);
06376 return &p->subs[index].f;
06377 }
06378
06379 if (p->subs[index].needcongestion) {
06380
06381 p->subs[index].needcongestion = 0;
06382 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06383 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
06384 ast_mutex_unlock(&p->lock);
06385 return &p->subs[index].f;
06386 }
06387
06388 if (p->subs[index].needcallerid && !ast->cid.cid_tns) {
06389 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06390 S_OR(p->lastcid_name, NULL),
06391 S_OR(p->lastcid_num, NULL)
06392 );
06393 p->subs[index].needcallerid = 0;
06394 }
06395
06396 if (p->subs[index].needanswer) {
06397
06398 p->subs[index].needanswer = 0;
06399 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06400 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
06401 ast_mutex_unlock(&p->lock);
06402 return &p->subs[index].f;
06403 }
06404
06405 #ifdef HAVE_OPENR2
06406 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06407
06408
06409
06410
06411 p->subs[index].f.frametype = AST_FRAME_NULL;
06412 p->subs[index].f.subclass = 0;
06413 p->subs[index].f.samples = 0;
06414 p->subs[index].f.mallocd = 0;
06415 p->subs[index].f.offset = 0;
06416 p->subs[index].f.data = NULL;
06417 p->subs[index].f.datalen= 0;
06418 ast_mutex_unlock(&p->lock);
06419 return &p->subs[index].f;
06420 }
06421 #endif
06422
06423 if (p->subs[index].needflash) {
06424
06425 p->subs[index].needflash = 0;
06426 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06427 p->subs[index].f.subclass = AST_CONTROL_FLASH;
06428 ast_mutex_unlock(&p->lock);
06429 return &p->subs[index].f;
06430 }
06431
06432 if (p->subs[index].needhold) {
06433
06434 p->subs[index].needhold = 0;
06435 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06436 p->subs[index].f.subclass = AST_CONTROL_HOLD;
06437 ast_mutex_unlock(&p->lock);
06438 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
06439 return &p->subs[index].f;
06440 }
06441
06442 if (p->subs[index].needunhold) {
06443
06444 p->subs[index].needunhold = 0;
06445 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06446 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
06447 ast_mutex_unlock(&p->lock);
06448 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
06449 return &p->subs[index].f;
06450 }
06451
06452 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06453 if (!p->subs[index].linear) {
06454 p->subs[index].linear = 1;
06455 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06456 if (res)
06457 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
06458 }
06459 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06460 (ast->rawreadformat == AST_FORMAT_ALAW)) {
06461 if (p->subs[index].linear) {
06462 p->subs[index].linear = 0;
06463 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06464 if (res)
06465 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
06466 }
06467 } else {
06468 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06469 ast_mutex_unlock(&p->lock);
06470 return NULL;
06471 }
06472 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
06473 CHECK_BLOCKING(ast);
06474 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06475 ast_clear_flag(ast, AST_FLAG_BLOCKING);
06476
06477 if (p->use_callerid && (ast->_state == AST_STATE_PRERING &&
06478 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
06479
06480 if (!p->subs[index].linear) {
06481 int x, samplin;
06482 int mean, ssum;
06483
06484
06485 for (x = 0, ssum = 0; x < READ_SIZE; x++) {
06486
06487 ssum += AST_MULAW(((u_char *)readbuf)[x]);
06488 if (option_verbose > 5 && (x % 10 == 0))
06489 ast_log(LOG_NOTICE, "dahdi_read ssum %i, mean %i \n", ssum, ssum / READ_SIZE);
06490 }
06491 mean = ssum / READ_SIZE;
06492
06493 if (option_verbose > 5)
06494 ast_log(LOG_WARNING, "dahdi_read channel %s, mean %i \n", ast->name, mean);
06495 if (ast->rawreadformat == AST_FORMAT_ULAW) {
06496 for (x = 0; x < READ_SIZE; x++) {
06497 samplin = AST_MULAW(((u_char *)readbuf)[x]);
06498 if (option_verbose > 6 && (x % 10 == 0))
06499 ast_log(LOG_NOTICE, "dahdi_read,x %i, samporig %i samplin %i, samplinconv %i, xconv %i\n", x, ((u_char *)readbuf)[x], samplin, samplin - mean, AST_LIN2MU(samplin - mean));
06500 ((u_char *)readbuf)[x] = AST_LIN2MU(samplin - mean);
06501 }
06502 }
06503 }
06504 }
06505
06506
06507 if (res < 0) {
06508 f = NULL;
06509 if (res == -1) {
06510 if (errno == EAGAIN) {
06511
06512 ast_mutex_unlock(&p->lock);
06513 return &p->subs[index].f;
06514 } else if (errno == ELAST) {
06515 f = __dahdi_exception(ast);
06516 } else
06517 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06518 }
06519 ast_mutex_unlock(&p->lock);
06520 return f;
06521 }
06522 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06523 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06524 f = __dahdi_exception(ast);
06525 ast_mutex_unlock(&p->lock);
06526 return f;
06527 }
06528 if (p->tdd) {
06529 int c;
06530
06531 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06532 if (c < 0) {
06533 ast_log(LOG_DEBUG,"tdd_feed failed\n");
06534 ast_mutex_unlock(&p->lock);
06535 return NULL;
06536 }
06537 if (c) {
06538 p->subs[index].f.subclass = 0;
06539 p->subs[index].f.frametype = AST_FRAME_TEXT;
06540 p->subs[index].f.mallocd = 0;
06541 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06542 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06543 p->subs[index].f.datalen = 1;
06544 *((char *) p->subs[index].f.data) = c;
06545 ast_mutex_unlock(&p->lock);
06546 return &p->subs[index].f;
06547 }
06548 }
06549 if (index == SUB_REAL) {
06550
06551 if (p->cidcwexpire) {
06552 if (!--p->cidcwexpire) {
06553
06554 if (option_verbose > 2)
06555 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06556 restore_conference(p);
06557 }
06558 }
06559 if (p->cid_suppress_expire) {
06560 --p->cid_suppress_expire;
06561 }
06562 if (p->callwaitingrepeat) {
06563 if (!--p->callwaitingrepeat) {
06564
06565 ++p->callwaitrings;
06566 dahdi_callwait(ast);
06567 }
06568 }
06569 }
06570 if (p->subs[index].linear) {
06571 p->subs[index].f.datalen = READ_SIZE * 2;
06572 } else
06573 p->subs[index].f.datalen = READ_SIZE;
06574
06575
06576 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06577 send_callerid(p);
06578 }
06579
06580 p->subs[index].f.frametype = AST_FRAME_VOICE;
06581 p->subs[index].f.subclass = ast->rawreadformat;
06582 p->subs[index].f.samples = READ_SIZE;
06583 p->subs[index].f.mallocd = 0;
06584 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06585 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06586 #if 0
06587 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06588 #endif
06589 if (p->dialing ||
06590 (index && (ast->_state != AST_STATE_UP)) ||
06591 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
06592 ) {
06593
06594
06595 p->subs[index].f.frametype = AST_FRAME_NULL;
06596 p->subs[index].f.subclass = 0;
06597 p->subs[index].f.samples = 0;
06598 p->subs[index].f.mallocd = 0;
06599 p->subs[index].f.offset = 0;
06600 p->subs[index].f.data = NULL;
06601 p->subs[index].f.datalen= 0;
06602 }
06603 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
06604
06605 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06606 if (f) {
06607 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06608 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06609
06610
06611 f = NULL;
06612 }
06613 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
06614 || f->frametype == AST_FRAME_DTMF_END) {
06615 #ifdef HAVE_PRI
06616 if (p->sig == SIG_PRI
06617 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06618 && p->pri
06619 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
06620 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06621
06622 ast_log(LOG_DEBUG,
06623 "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
06624 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
06625 f->subclass, f->subclass, ast->name);
06626
06627 f->frametype = AST_FRAME_NULL;
06628 f->subclass = 0;
06629 }
06630 #endif
06631
06632 p->pulsedial = 0;
06633 }
06634 }
06635 } else
06636 f = &p->subs[index].f;
06637
06638 if (f) {
06639 switch (f->frametype) {
06640 case AST_FRAME_DTMF_BEGIN:
06641 case AST_FRAME_DTMF_END:
06642 dahdi_handle_dtmf(ast, index, &f);
06643 break;
06644 case AST_FRAME_VOICE:
06645 if (p->cidspill || p->cid_suppress_expire) {
06646
06647 p->subs[index].f.frametype = AST_FRAME_NULL;
06648 p->subs[index].f.subclass = 0;
06649 p->subs[index].f.samples = 0;
06650 p->subs[index].f.mallocd = 0;
06651 p->subs[index].f.offset = 0;
06652 p->subs[index].f.data = NULL;
06653 p->subs[index].f.datalen= 0;
06654 }
06655 break;
06656 default:
06657 break;
06658 }
06659 }
06660
06661
06662 if (p->fake_event)
06663 ast_set_flag(ast, AST_FLAG_EXCEPTION);
06664
06665 ast_mutex_unlock(&p->lock);
06666 return f;
06667 }
06668
06669 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
06670 {
06671 int sent=0;
06672 int size;
06673 int res;
06674 int fd;
06675 fd = p->subs[index].dfd;
06676 while (len) {
06677 size = len;
06678 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06679 size = (linear ? READ_SIZE * 2 : READ_SIZE);
06680 res = write(fd, buf, size);
06681 if (res != size) {
06682 if (option_debug)
06683 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06684 return sent;
06685 }
06686 len -= size;
06687 buf += size;
06688 }
06689 return sent;
06690 }
06691
06692 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06693 {
06694 struct dahdi_pvt *p = ast->tech_pvt;
06695 int res;
06696 int index;
06697 index = dahdi_get_index(ast, p, 0);
06698 if (index < 0) {
06699 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06700 return -1;
06701 }
06702
06703
06704 if (frame->frametype != AST_FRAME_VOICE) {
06705 if (frame->frametype != AST_FRAME_IMAGE)
06706 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06707 return 0;
06708 }
06709 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06710 (frame->subclass != AST_FORMAT_ULAW) &&
06711 (frame->subclass != AST_FORMAT_ALAW)) {
06712 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06713 return -1;
06714 }
06715 if (p->dialing) {
06716 if (option_debug)
06717 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06718 return 0;
06719 }
06720 if (!p->owner) {
06721 if (option_debug)
06722 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06723 return 0;
06724 }
06725 if (p->cidspill) {
06726 if (option_debug) {
06727 ast_log(LOG_DEBUG,
06728 "Dropping frame since I've still got a callerid spill on %s...\n",
06729 ast->name);
06730 }
06731 return 0;
06732 }
06733
06734 if (!frame->data || !frame->datalen)
06735 return 0;
06736
06737 if (frame->subclass == AST_FORMAT_SLINEAR) {
06738 if (!p->subs[index].linear) {
06739 p->subs[index].linear = 1;
06740 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06741 if (res)
06742 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06743 }
06744 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06745 } else {
06746
06747 if (p->subs[index].linear) {
06748 p->subs[index].linear = 0;
06749 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06750 if (res)
06751 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06752 }
06753 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06754 }
06755 if (res < 0) {
06756 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06757 return -1;
06758 }
06759 return 0;
06760 }
06761
06762 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06763 {
06764 struct dahdi_pvt *p = chan->tech_pvt;
06765 int res=-1;
06766 int index;
06767 int func = DAHDI_FLASH;
06768 ast_mutex_lock(&p->lock);
06769 index = dahdi_get_index(chan, p, 0);
06770 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06771 #ifdef HAVE_OPENR2
06772 if (p->mfcr2 && !p->mfcr2_call_accepted) {
06773 ast_mutex_unlock(&p->lock);
06774
06775
06776 return 0;
06777 }
06778 #endif
06779 if (index == SUB_REAL) {
06780 switch (condition) {
06781 case AST_CONTROL_BUSY:
06782 #ifdef HAVE_PRI
06783 if (p->sig == SIG_PRI) {
06784 if (p->priindication_oob) {
06785 chan->hangupcause = AST_CAUSE_USER_BUSY;
06786 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06787 res = 0;
06788 break;
06789 }
06790 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06791 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
06792 chan->hangupcause = AST_CAUSE_USER_BUSY;
06793 p->progress = 1;
06794 if (p->pri && p->pri->pri) {
06795 if (!pri_grab(p, p->pri)) {
06796 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06797 pri_rel(p->pri);
06798 } else {
06799 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06800 }
06801 }
06802 }
06803 break;
06804 }
06805 #endif
06806 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06807 break;
06808 case AST_CONTROL_RINGING:
06809 #ifdef HAVE_PRI
06810 if (p->sig == SIG_PRI
06811 && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
06812 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
06813 if (p->pri && p->pri->pri) {
06814 if (!pri_grab(p, p->pri)) {
06815 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06816 pri_rel(p->pri);
06817 } else {
06818 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06819 }
06820 }
06821 }
06822 #endif
06823 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06824 if (chan->_state != AST_STATE_UP) {
06825 if ((chan->_state != AST_STATE_RING) ||
06826 ((p->sig != SIG_FXSKS) &&
06827 (p->sig != SIG_FXSLS) &&
06828 (p->sig != SIG_FXSGS)))
06829 ast_setstate(chan, AST_STATE_RINGING);
06830 }
06831 break;
06832 case AST_CONTROL_PROCEEDING:
06833 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06834 #ifdef HAVE_PRI
06835 if (p->sig == SIG_PRI
06836 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
06837 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
06838 if (p->pri && p->pri->pri) {
06839 if (!pri_grab(p, p->pri)) {
06840 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06841 pri_rel(p->pri);
06842 } else {
06843 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06844 }
06845 }
06846 p->dialing = 0;
06847 }
06848 #endif
06849
06850 res = 0;
06851 break;
06852 case AST_CONTROL_PROGRESS:
06853 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06854 #ifdef HAVE_PRI
06855 p->digital = 0;
06856 if (p->sig == SIG_PRI
06857 && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
06858 && !p->outgoing) {
06859 p->progress = 1;
06860 if (p->pri && p->pri->pri) {
06861 if (!pri_grab(p, p->pri)) {
06862 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06863 pri_rel(p->pri);
06864 } else {
06865 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06866 }
06867 }
06868 }
06869 #endif
06870
06871 res = 0;
06872 break;
06873 case AST_CONTROL_CONGESTION:
06874 #ifdef HAVE_PRI
06875 if (p->sig == SIG_PRI) {
06876 if (p->priindication_oob) {
06877
06878 switch (chan->hangupcause) {
06879 case AST_CAUSE_USER_BUSY:
06880 case AST_CAUSE_NORMAL_CLEARING:
06881 case 0:
06882
06883 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06884 break;
06885 default:
06886 break;
06887 }
06888 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06889 res = 0;
06890 break;
06891 }
06892 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06893 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
06894
06895 switch (chan->hangupcause) {
06896 case AST_CAUSE_USER_BUSY:
06897 case AST_CAUSE_NORMAL_CLEARING:
06898 case 0:
06899
06900 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06901 break;
06902 default:
06903 break;
06904 }
06905 p->progress = 1;
06906 if (p->pri && p->pri->pri) {
06907 if (!pri_grab(p, p->pri)) {
06908 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06909 pri_rel(p->pri);
06910 } else {
06911 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06912 }
06913 }
06914 }
06915 break;
06916 }
06917 #endif
06918
06919 switch (chan->hangupcause) {
06920 case AST_CAUSE_USER_BUSY:
06921 case AST_CAUSE_NORMAL_CLEARING:
06922 case 0:
06923
06924 chan->hangupcause = AST_CAUSE_CONGESTION;
06925 break;
06926 default:
06927 break;
06928 }
06929 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06930 break;
06931 case AST_CONTROL_HOLD:
06932 #ifdef HAVE_PRI
06933 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06934 if (!pri_grab(p, p->pri)) {
06935 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06936 pri_rel(p->pri);
06937 } else
06938 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06939 } else
06940 #endif
06941 ast_moh_start(chan, data, p->mohinterpret);
06942 break;
06943 case AST_CONTROL_UNHOLD:
06944 #ifdef HAVE_PRI
06945 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06946 if (!pri_grab(p, p->pri)) {
06947 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06948 pri_rel(p->pri);
06949 } else
06950 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06951 } else
06952 #endif
06953 ast_moh_stop(chan);
06954 break;
06955 case AST_CONTROL_RADIO_KEY:
06956 if (p->radio)
06957 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06958 res = 0;
06959 break;
06960 case AST_CONTROL_RADIO_UNKEY:
06961 if (p->radio)
06962 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06963 res = 0;
06964 break;
06965 case AST_CONTROL_FLASH:
06966
06967 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06968
06969 p->dop.dialstr[0] = '\0';
06970 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06971 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06972 chan->name, strerror(errno));
06973 } else
06974 res = 0;
06975 } else
06976 res = 0;
06977 break;
06978 case AST_CONTROL_SRCUPDATE:
06979 res = 0;
06980 break;
06981 case -1:
06982 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06983 break;
06984 }
06985 } else
06986 res = 0;
06987 ast_mutex_unlock(&p->lock);
06988 return res;
06989 }
06990
06991 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
06992 {
06993 struct ast_channel *tmp;
06994 int deflaw;
06995 int res;
06996 int x,y;
06997 int features;
06998 char *b2 = NULL;
06999 struct dahdi_params ps;
07000 char chanprefix[*dahdi_chan_name_len + 4];
07001
07002 if (i->subs[index].owner) {
07003 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
07004 return NULL;
07005 }
07006 y = 1;
07007 do {
07008 if (b2)
07009 free(b2);
07010 #ifdef HAVE_PRI
07011 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07012 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07013 else
07014 #endif
07015 if (i->channel == CHAN_PSEUDO)
07016 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
07017 else
07018 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
07019 for (x = 0; x < 3; x++) {
07020 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
07021 break;
07022 }
07023 y++;
07024 } while (x < 3);
07025 strcpy(chanprefix, dahdi_chan_name);
07026 strcat(chanprefix, "/%s");
07027 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
07028 if (b2)
07029 free(b2);
07030 if (!tmp)
07031 return NULL;
07032 tmp->tech = chan_tech;
07033 memset(&ps, 0, sizeof(ps));
07034 ps.channo = i->channel;
07035 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07036 if (res) {
07037 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07038 ps.curlaw = DAHDI_LAW_MULAW;
07039 }
07040 if (ps.curlaw == DAHDI_LAW_ALAW)
07041 deflaw = AST_FORMAT_ALAW;
07042 else
07043 deflaw = AST_FORMAT_ULAW;
07044 if (law) {
07045 if (law == DAHDI_LAW_ALAW)
07046 deflaw = AST_FORMAT_ALAW;
07047 else
07048 deflaw = AST_FORMAT_ULAW;
07049 }
07050 tmp->fds[0] = i->subs[index].dfd;
07051 tmp->nativeformats = deflaw;
07052
07053 tmp->rawreadformat = deflaw;
07054 tmp->readformat = deflaw;
07055 tmp->rawwriteformat = deflaw;
07056 tmp->writeformat = deflaw;
07057 i->subs[index].linear = 0;
07058 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
07059 features = 0;
07060 if (index == SUB_REAL) {
07061 if (i->busydetect && CANBUSYDETECT(i))
07062 features |= DSP_FEATURE_BUSY_DETECT;
07063 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
07064 features |= DSP_FEATURE_CALL_PROGRESS;
07065 if ((!i->outgoing && (i->callprogress & 4)) ||
07066 (i->outgoing && (i->callprogress & 2))) {
07067 features |= DSP_FEATURE_FAX_DETECT;
07068 }
07069 #ifdef DAHDI_TONEDETECT
07070 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07071 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
07072 #endif
07073 i->hardwaredtmf = 0;
07074 features |= DSP_FEATURE_DTMF_DETECT;
07075 #ifdef DAHDI_TONEDETECT
07076 } else if (NEED_MFDETECT(i)) {
07077 i->hardwaredtmf = 1;
07078 features |= DSP_FEATURE_DTMF_DETECT;
07079 }
07080 #endif
07081 }
07082 if (features) {
07083 if (i->dsp) {
07084 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
07085 } else {
07086 if (i->channel != CHAN_PSEUDO)
07087 i->dsp = ast_dsp_new();
07088 else
07089 i->dsp = NULL;
07090 if (i->dsp) {
07091 i->dsp_features = features;
07092 #ifdef HAVE_PRI
07093
07094 if (i->outgoing && (i->sig == SIG_PRI)) {
07095
07096
07097 i->dsp_features = features & ~DSP_PROGRESS_TALK;
07098 features = 0;
07099 }
07100 #endif
07101 ast_dsp_set_features(i->dsp, features);
07102 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07103 if (!ast_strlen_zero(progzone))
07104 ast_dsp_set_call_progress_zone(i->dsp, progzone);
07105 if (i->busydetect && CANBUSYDETECT(i)) {
07106 if(i->silencethreshold > 0)
07107 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
07108 ast_dsp_set_busy_count(i->dsp, i->busycount);
07109 if(i->busytonelength > 0)
07110 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
07111 if((i->busytonelength == i->busyquietlength) && i->busycompare)
07112 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
07113 }
07114 }
07115 }
07116 }
07117
07118 if (state == AST_STATE_RING)
07119 tmp->rings = 1;
07120 tmp->tech_pvt = i;
07121 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07122
07123 tmp->callgroup = i->callgroup;
07124 tmp->pickupgroup = i->pickupgroup;
07125 }
07126 if (!ast_strlen_zero(i->language))
07127 ast_string_field_set(tmp, language, i->language);
07128 if (!i->owner)
07129 i->owner = tmp;
07130 if (!ast_strlen_zero(i->accountcode))
07131 ast_string_field_set(tmp, accountcode, i->accountcode);
07132 if (i->amaflags)
07133 tmp->amaflags = i->amaflags;
07134 i->subs[index].owner = tmp;
07135 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07136 ast_string_field_set(tmp, call_forward, i->call_forward);
07137
07138 if (!i->adsi)
07139 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07140 if (!ast_strlen_zero(i->exten))
07141 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07142 if (!ast_strlen_zero(i->rdnis))
07143 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07144 if (!ast_strlen_zero(i->dnid))
07145 tmp->cid.cid_dnid = ast_strdup(i->dnid);
07146
07147
07148
07149 #ifdef PRI_ANI
07150 if (!ast_strlen_zero(i->cid_ani))
07151 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07152 else
07153 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07154 #else
07155 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07156 #endif
07157 tmp->cid.cid_pres = i->callingpres;
07158 tmp->cid.cid_ton = i->cid_ton;
07159 #ifdef HAVE_PRI
07160 tmp->transfercapability = transfercapability;
07161 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07162 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
07163 i->digital = 1;
07164
07165 i->isidlecall = 0;
07166 i->alreadyhungup = 0;
07167 #endif
07168
07169 i->fake_event = 0;
07170
07171 dahdi_confmute(i, 0);
07172
07173 ast_jb_configure(tmp, &global_jbconf);
07174 if (startpbx) {
07175
07176 #ifdef HAVE_OPENR2
07177 if (i->mfcr2call) {
07178 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07179 }
07180 #endif
07181
07182 if (ast_pbx_start(tmp)) {
07183 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07184 ast_hangup(tmp);
07185 i->owner = NULL;
07186 return NULL;
07187 }
07188 }
07189
07190 ast_module_ref(ast_module_info->self);
07191
07192 return tmp;
07193 }
07194
07195
07196 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
07197 {
07198 char c;
07199
07200 *str = 0;
07201 for (;;)
07202 {
07203
07204 c = ast_waitfordigit(chan, ms);
07205
07206 if (c < 1)
07207 return c;
07208 *str++ = c;
07209 *str = 0;
07210 if (strchr(term, c))
07211 return 1;
07212 }
07213 }
07214
07215 static int dahdi_wink(struct dahdi_pvt *p, int index)
07216 {
07217 int j;
07218 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
07219 for (;;)
07220 {
07221
07222 j = DAHDI_IOMUX_SIGEVENT;
07223
07224 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
07225
07226 if (j & DAHDI_IOMUX_SIGEVENT) break;
07227 }
07228
07229 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
07230 return 0;
07231 }
07232
07233 static void *ss_thread(void *data)
07234 {
07235 struct ast_channel *chan = data;
07236 struct dahdi_pvt *p = chan->tech_pvt;
07237 char exten[AST_MAX_EXTENSION] = "";
07238 char exten2[AST_MAX_EXTENSION] = "";
07239 unsigned char buf[256];
07240 char dtmfcid[300];
07241 char dtmfbuf[300];
07242 struct callerid_state *cs = NULL;
07243 char *name = NULL, *number = NULL;
07244 int distMatches;
07245 int curRingData[3];
07246 int receivedRingT;
07247 int counter1;
07248 int counter;
07249 int samples = 0;
07250 struct ast_smdi_md_message *smdi_msg = NULL;
07251 int flags = 0;
07252 int i;
07253 int timeout;
07254 int getforward = 0;
07255 char *s1, *s2;
07256 int len = 0;
07257 int res;
07258 int index;
07259
07260 ast_mutex_lock(&ss_thread_lock);
07261 ss_thread_count++;
07262 ast_mutex_unlock(&ss_thread_lock);
07263
07264
07265
07266 if (!p) {
07267 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
07268 ast_hangup(chan);
07269 goto quit;
07270 }
07271 if (option_verbose > 2)
07272 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
07273 index = dahdi_get_index(chan, p, 0);
07274 if (index < 0) {
07275 ast_hangup(chan);
07276 goto quit;
07277 }
07278 if (p->dsp)
07279 ast_dsp_digitreset(p->dsp);
07280 switch (p->sig) {
07281 #ifdef HAVE_PRI
07282 case SIG_PRI:
07283
07284 ast_copy_string(exten, p->exten, sizeof(exten));
07285 len = strlen(exten);
07286 res = 0;
07287 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07288 if (len && !ast_ignore_pattern(chan->context, exten))
07289 tone_zone_play_tone(p->subs[index].dfd, -1);
07290 else
07291 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07292 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
07293 timeout = matchdigittimeout;
07294 else
07295 timeout = gendigittimeout;
07296 res = ast_waitfordigit(chan, timeout);
07297 if (res < 0) {
07298 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07299 ast_hangup(chan);
07300 goto quit;
07301 } else if (res) {
07302 exten[len++] = res;
07303 exten[len] = '\0';
07304 } else
07305 break;
07306 }
07307
07308 if (ast_strlen_zero(exten)) {
07309 if (option_verbose > 2)
07310 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
07311 exten[0] = 's';
07312 exten[1] = '\0';
07313 }
07314 tone_zone_play_tone(p->subs[index].dfd, -1);
07315 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
07316
07317 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07318 if (p->dsp) {
07319 ast_dsp_digitreset(p->dsp);
07320 }
07321 #if defined(ISSUE_16789)
07322
07323
07324
07325
07326
07327
07328
07329
07330
07331
07332
07333
07334 if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
07335 && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07336 ast_mutex_lock(&p->lock);
07337 if (p->pri->pri) {
07338 if (!pri_grab(p, p->pri)) {
07339 if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
07340 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07341 }
07342 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
07343 pri_rel(p->pri);
07344 } else {
07345 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07346 }
07347 }
07348 ast_mutex_unlock(&p->lock);
07349 }
07350 #endif
07351
07352 dahdi_enable_ec(p);
07353 ast_setstate(chan, AST_STATE_RING);
07354 res = ast_pbx_run(chan);
07355 if (res) {
07356 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
07357 }
07358 } else {
07359 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
07360 chan->hangupcause = AST_CAUSE_UNALLOCATED;
07361 ast_hangup(chan);
07362 p->exten[0] = '\0';
07363
07364 p->call = NULL;
07365 }
07366 goto quit;
07367 break;
07368 #endif
07369 case SIG_FEATD:
07370 case SIG_FEATDMF:
07371 case SIG_FEATDMF_TA:
07372 case SIG_E911:
07373 case SIG_FGC_CAMAMF:
07374 case SIG_FEATB:
07375 case SIG_EMWINK:
07376 case SIG_SF_FEATD:
07377 case SIG_SF_FEATDMF:
07378 case SIG_SF_FEATB:
07379 case SIG_SFWINK:
07380 if (dahdi_wink(p, index))
07381 goto quit;
07382
07383 case SIG_EM:
07384 case SIG_EM_E1:
07385 case SIG_SF:
07386 case SIG_FGC_CAMA:
07387 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07388 if (p->dsp)
07389 ast_dsp_digitreset(p->dsp);
07390
07391 if (p->dsp) {
07392 if (NEED_MFDETECT(p))
07393 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
07394 else
07395 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07396 }
07397 memset(dtmfbuf, 0, sizeof(dtmfbuf));
07398
07399 if (!p->immediate)
07400
07401 res = ast_waitfordigit(chan, 5000);
07402 else
07403 res = 0;
07404 if (res > 0) {
07405
07406 dtmfbuf[0] = res;
07407 switch (p->sig) {
07408 case SIG_FEATD:
07409 case SIG_SF_FEATD:
07410 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07411 if (res > 0)
07412 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07413 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07414 break;
07415 case SIG_FEATDMF_TA:
07416 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07417 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07418 if (dahdi_wink(p, index)) goto quit;
07419 dtmfbuf[0] = 0;
07420
07421 res = ast_waitfordigit(chan, 5000);
07422 if (res <= 0) break;
07423 dtmfbuf[0] = res;
07424
07425 case SIG_FEATDMF:
07426 case SIG_E911:
07427 case SIG_FGC_CAMAMF:
07428 case SIG_SF_FEATDMF:
07429 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07430
07431 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
07432 {
07433 if (dahdi_wink(p, index)) goto quit;
07434 dtmfbuf[0] = 0;
07435
07436 res = ast_waitfordigit(chan, 5000);
07437 if (res <= 0) break;
07438 dtmfbuf[0] = res;
07439 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07440 }
07441 if (res > 0) {
07442
07443 if (p->sig == SIG_E911)
07444 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07445 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
07446 }
07447 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07448 break;
07449 case SIG_FEATB:
07450 case SIG_SF_FEATB:
07451 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07452 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07453 break;
07454 case SIG_EMWINK:
07455
07456
07457
07458
07459 if (res == '*') {
07460 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07461 if (res > 0)
07462 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07463 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07464 break;
07465 }
07466 default:
07467
07468 len = 1;
07469 dtmfbuf[len] = '\0';
07470 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07471 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07472 timeout = matchdigittimeout;
07473 } else {
07474 timeout = gendigittimeout;
07475 }
07476 res = ast_waitfordigit(chan, timeout);
07477 if (res < 0) {
07478 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07479 ast_hangup(chan);
07480 goto quit;
07481 } else if (res) {
07482 dtmfbuf[len++] = res;
07483 dtmfbuf[len] = '\0';
07484 } else {
07485 break;
07486 }
07487 }
07488 break;
07489 }
07490 }
07491 if (res == -1) {
07492 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
07493 ast_hangup(chan);
07494 goto quit;
07495 } else if (res < 0) {
07496 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
07497 ast_hangup(chan);
07498 goto quit;
07499 }
07500
07501 if (p->sig == SIG_FGC_CAMA) {
07502 char anibuf[100];
07503
07504 if (ast_safe_sleep(chan,1000) == -1) {
07505 ast_hangup(chan);
07506 goto quit;
07507 }
07508 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07509 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
07510 res = my_getsigstr(chan, anibuf, "#", 10000);
07511 if ((res > 0) && (strlen(anibuf) > 2)) {
07512 if (anibuf[strlen(anibuf) - 1] == '#')
07513 anibuf[strlen(anibuf) - 1] = 0;
07514 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07515 }
07516 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07517 }
07518
07519 ast_copy_string(exten, dtmfbuf, sizeof(exten));
07520 if (ast_strlen_zero(exten))
07521 ast_copy_string(exten, "s", sizeof(exten));
07522 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07523
07524 if (exten[0] == '*') {
07525 char *stringp=NULL;
07526 ast_copy_string(exten2, exten, sizeof(exten2));
07527
07528 stringp=exten2 +1;
07529 s1 = strsep(&stringp, "*");
07530 s2 = strsep(&stringp, "*");
07531 if (s2) {
07532 if (!ast_strlen_zero(p->cid_num))
07533 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07534 else
07535 ast_set_callerid(chan, s1, NULL, s1);
07536 ast_copy_string(exten, s2, sizeof(exten));
07537 } else
07538 ast_copy_string(exten, s1, sizeof(exten));
07539 } else if (p->sig == SIG_FEATD)
07540 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07541 }
07542 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07543 if (exten[0] == '*') {
07544 char *stringp=NULL;
07545 ast_copy_string(exten2, exten, sizeof(exten2));
07546
07547 stringp=exten2 +1;
07548 s1 = strsep(&stringp, "#");
07549 s2 = strsep(&stringp, "#");
07550 if (s2) {
07551 if (!ast_strlen_zero(p->cid_num))
07552 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07553 else
07554 if (*(s1 + 2))
07555 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07556 ast_copy_string(exten, s2 + 1, sizeof(exten));
07557 } else
07558 ast_copy_string(exten, s1 + 2, sizeof(exten));
07559 } else
07560 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07561 }
07562 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07563 if (exten[0] == '*') {
07564 char *stringp=NULL;
07565 ast_copy_string(exten2, exten, sizeof(exten2));
07566
07567 stringp=exten2 +1;
07568 s1 = strsep(&stringp, "#");
07569 s2 = strsep(&stringp, "#");
07570 if (s2 && (*(s2 + 1) == '0')) {
07571 if (*(s2 + 2))
07572 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07573 }
07574 if (s1) ast_copy_string(exten, s1, sizeof(exten));
07575 else ast_copy_string(exten, "911", sizeof(exten));
07576 } else
07577 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
07578 }
07579 if (p->sig == SIG_FEATB) {
07580 if (exten[0] == '*') {
07581 char *stringp=NULL;
07582 ast_copy_string(exten2, exten, sizeof(exten2));
07583
07584 stringp=exten2 +1;
07585 s1 = strsep(&stringp, "#");
07586 ast_copy_string(exten, exten2 + 1, sizeof(exten));
07587 } else
07588 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
07589 }
07590 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07591 dahdi_wink(p, index);
07592
07593
07594
07595 if (ast_safe_sleep(chan, 100)) {
07596 ast_hangup(chan);
07597 goto quit;
07598 }
07599 }
07600 dahdi_enable_ec(p);
07601 if (NEED_MFDETECT(p)) {
07602 if (p->dsp) {
07603 if (!p->hardwaredtmf)
07604 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07605 else {
07606 ast_dsp_free(p->dsp);
07607 p->dsp = NULL;
07608 }
07609 }
07610 }
07611
07612 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07613 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07614 if (p->dsp) ast_dsp_digitreset(p->dsp);
07615 res = ast_pbx_run(chan);
07616 if (res) {
07617 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07618 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07619 }
07620 goto quit;
07621 } else {
07622 if (option_verbose > 2)
07623 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07624 sleep(2);
07625 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07626 if (res < 0)
07627 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07628 else
07629 sleep(1);
07630 res = ast_streamfile(chan, "ss-noservice", chan->language);
07631 if (res >= 0)
07632 ast_waitstream(chan, "");
07633 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07634 ast_hangup(chan);
07635 goto quit;
07636 }
07637 break;
07638 case SIG_FXOLS:
07639 case SIG_FXOGS:
07640 case SIG_FXOKS:
07641
07642 timeout = firstdigittimeout;
07643
07644
07645 if (p->subs[SUB_THREEWAY].owner)
07646 timeout = 999999;
07647 while (len < AST_MAX_EXTENSION-1) {
07648
07649
07650 if (p->immediate)
07651 res = 's';
07652 else
07653 res = ast_waitfordigit(chan, timeout);
07654 timeout = 0;
07655 if (res < 0) {
07656 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07657 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07658 ast_hangup(chan);
07659 goto quit;
07660 } else if (res) {
07661 exten[len++]=res;
07662 exten[len] = '\0';
07663 }
07664 if (!ast_ignore_pattern(chan->context, exten))
07665 tone_zone_play_tone(p->subs[index].dfd, -1);
07666 else
07667 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07668 if (!strcmp(exten,ast_pickup_ext())) {
07669
07670
07671
07672
07673 if (index == SUB_REAL) {
07674
07675 if (p->subs[SUB_THREEWAY].owner) {
07676
07677
07678 alloc_sub(p, SUB_CALLWAIT);
07679 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07680 unalloc_sub(p, SUB_THREEWAY);
07681 }
07682 dahdi_enable_ec(p);
07683 if (ast_pickup_call(chan)) {
07684 ast_log(LOG_DEBUG, "No call pickup possible...\n");
07685 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07686 dahdi_wait_event(p->subs[index].dfd);
07687 }
07688 ast_hangup(chan);
07689 goto quit;
07690 } else {
07691 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07692 ast_hangup(chan);
07693 goto quit;
07694 }
07695
07696 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07697 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07698 if (getforward) {
07699
07700 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
07701 if (option_verbose > 2)
07702 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07703 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07704 if (res)
07705 break;
07706 usleep(500000);
07707 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07708 sleep(1);
07709 memset(exten, 0, sizeof(exten));
07710 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07711 len = 0;
07712 getforward = 0;
07713 } else {
07714 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07715 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07716 if (!ast_strlen_zero(p->cid_num)) {
07717 if (!p->hidecallerid)
07718 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07719 else
07720 ast_set_callerid(chan, NULL, NULL, p->cid_num);
07721 }
07722 if (!ast_strlen_zero(p->cid_name)) {
07723 if (!p->hidecallerid)
07724 ast_set_callerid(chan, NULL, p->cid_name, NULL);
07725 }
07726 ast_setstate(chan, AST_STATE_RING);
07727 dahdi_enable_ec(p);
07728 res = ast_pbx_run(chan);
07729 if (res) {
07730 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07731 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07732 }
07733 goto quit;
07734 }
07735 } else {
07736
07737
07738 timeout = matchdigittimeout;
07739 }
07740 } else if (res == 0) {
07741 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07742 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07743 dahdi_wait_event(p->subs[index].dfd);
07744 ast_hangup(chan);
07745 goto quit;
07746 } else if (p->callwaiting && !strcmp(exten, "*70")) {
07747 if (option_verbose > 2)
07748 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07749
07750 p->callwaiting = 0;
07751 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07752 if (res) {
07753 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07754 chan->name, strerror(errno));
07755 }
07756 len = 0;
07757 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07758 memset(exten, 0, sizeof(exten));
07759 timeout = firstdigittimeout;
07760
07761 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07762 if (option_verbose > 2)
07763 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07764
07765 p->hidecallerid = 1;
07766 if (chan->cid.cid_num)
07767 free(chan->cid.cid_num);
07768 chan->cid.cid_num = NULL;
07769 if (chan->cid.cid_name)
07770 free(chan->cid.cid_name);
07771 chan->cid.cid_name = NULL;
07772 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07773 if (res) {
07774 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07775 chan->name, strerror(errno));
07776 }
07777 len = 0;
07778 memset(exten, 0, sizeof(exten));
07779 timeout = firstdigittimeout;
07780 } else if (p->callreturn && !strcmp(exten, "*69")) {
07781 res = 0;
07782 if (!ast_strlen_zero(p->lastcid_num)) {
07783 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07784 }
07785 if (!res)
07786 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07787 break;
07788 } else if (!strcmp(exten, "*78")) {
07789
07790 if (option_verbose > 2)
07791 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07792 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07793 "Channel: %s/%d\r\n"
07794 "Status: enabled\r\n", dahdi_chan_name, p->channel);
07795 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07796 p->dnd = 1;
07797 getforward = 0;
07798 memset(exten, 0, sizeof(exten));
07799 len = 0;
07800 } else if (!strcmp(exten, "*79")) {
07801
07802 if (option_verbose > 2)
07803 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07804 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07805 "Channel: %s/%d\r\n"
07806 "Status: disabled\r\n", dahdi_chan_name, p->channel);
07807 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07808 p->dnd = 0;
07809 getforward = 0;
07810 memset(exten, 0, sizeof(exten));
07811 len = 0;
07812 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07813 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07814 getforward = 1;
07815 memset(exten, 0, sizeof(exten));
07816 len = 0;
07817 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07818 if (option_verbose > 2)
07819 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07820 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07821 memset(p->call_forward, 0, sizeof(p->call_forward));
07822 getforward = 0;
07823 memset(exten, 0, sizeof(exten));
07824 len = 0;
07825 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07826 p->subs[SUB_THREEWAY].owner &&
07827 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07828
07829
07830 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07831 if (option_verbose > 2)
07832 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07833 break;
07834 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07835 if (option_verbose > 2)
07836 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07837 res = ast_db_put("blacklist", p->lastcid_num, "1");
07838 if (!res) {
07839 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07840 memset(exten, 0, sizeof(exten));
07841 len = 0;
07842 }
07843 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07844 if (option_verbose > 2)
07845 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07846
07847 p->hidecallerid = 0;
07848 if (chan->cid.cid_num)
07849 free(chan->cid.cid_num);
07850 chan->cid.cid_num = NULL;
07851 if (chan->cid.cid_name)
07852 free(chan->cid.cid_name);
07853 chan->cid.cid_name = NULL;
07854 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07855 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07856 if (res) {
07857 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07858 chan->name, strerror(errno));
07859 }
07860 len = 0;
07861 memset(exten, 0, sizeof(exten));
07862 timeout = firstdigittimeout;
07863 } else if (!strcmp(exten, "*0")) {
07864 struct ast_channel *nbridge =
07865 p->subs[SUB_THREEWAY].owner;
07866 struct dahdi_pvt *pbridge = NULL;
07867
07868 if (nbridge && ast_bridged_channel(nbridge))
07869 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07870 if (nbridge && pbridge &&
07871 (nbridge->tech == chan_tech) &&
07872 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07873 ISTRUNK(pbridge)) {
07874 int func = DAHDI_FLASH;
07875
07876 p->dop.dialstr[0] = '\0';
07877
07878 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07879 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07880 nbridge->name, strerror(errno));
07881 }
07882 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07883 unalloc_sub(p, SUB_THREEWAY);
07884 p->owner = p->subs[SUB_REAL].owner;
07885 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07886 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07887 ast_hangup(chan);
07888 goto quit;
07889 } else {
07890 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07891 dahdi_wait_event(p->subs[index].dfd);
07892 tone_zone_play_tone(p->subs[index].dfd, -1);
07893 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07894 unalloc_sub(p, SUB_THREEWAY);
07895 p->owner = p->subs[SUB_REAL].owner;
07896 ast_hangup(chan);
07897 goto quit;
07898 }
07899 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07900 ((exten[0] != '*') || (strlen(exten) > 2))) {
07901 if (option_debug)
07902 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
07903 break;
07904 }
07905 if (!timeout)
07906 timeout = gendigittimeout;
07907 if (len && !ast_ignore_pattern(chan->context, exten))
07908 tone_zone_play_tone(p->subs[index].dfd, -1);
07909 }
07910 break;
07911 case SIG_FXSLS:
07912 case SIG_FXSGS:
07913 case SIG_FXSKS:
07914 #ifdef HAVE_PRI
07915 if (p->pri) {
07916
07917 struct ast_frame *f;
07918 int res;
07919 time_t start;
07920
07921 time(&start);
07922 ast_setstate(chan, AST_STATE_RING);
07923 while (time(NULL) < start + 3) {
07924 res = ast_waitfor(chan, 1000);
07925 if (res) {
07926 f = ast_read(chan);
07927 if (!f) {
07928 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07929 ast_hangup(chan);
07930 goto quit;
07931 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07932 res = 1;
07933 } else
07934 res = 0;
07935 ast_frfree(f);
07936 if (res) {
07937 ast_log(LOG_DEBUG, "Got ring!\n");
07938 res = 0;
07939 break;
07940 }
07941 }
07942 }
07943 }
07944 #endif
07945
07946 if (p->use_smdi && p->smdi_iface) {
07947 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07948
07949 if (smdi_msg != NULL) {
07950 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07951
07952 if (smdi_msg->type == 'B')
07953 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07954 else if (smdi_msg->type == 'N')
07955 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07956
07957 ast_log(LOG_DEBUG, "Received SMDI message on %s\n", chan->name);
07958 } else {
07959 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07960 }
07961 }
07962
07963 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07964 number = smdi_msg->calling_st;
07965
07966
07967
07968
07969 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
07970 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
07971
07972 if (p->cid_signalling == CID_SIG_DTMF) {
07973 int i = 0;
07974 cs = NULL;
07975 ast_log(LOG_DEBUG, "Receiving DTMF cid on channel %s\n", chan->name);
07976 dahdi_setlinear(p->subs[index].dfd, 0);
07977
07978
07979
07980
07981
07982
07983 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
07984 res = 4000;
07985 for (;;) {
07986 struct ast_frame *f;
07987 res = ast_waitfor(chan, res);
07988 if (res <= 0) {
07989
07990
07991
07992
07993
07994 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07995 "Exiting simple switch\n");
07996 ast_hangup(chan);
07997 goto quit;
07998 }
07999 f = ast_read(chan);
08000 if (!f)
08001 break;
08002 if (f->frametype == AST_FRAME_DTMF) {
08003 if (i < ARRAY_LEN(dtmfbuf) - 1) {
08004 dtmfbuf[i++] = f->subclass;
08005 }
08006 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
08007 res = 4000;
08008 }
08009 ast_frfree(f);
08010 if (chan->_state == AST_STATE_RING ||
08011 chan->_state == AST_STATE_RINGING)
08012 break;
08013 }
08014 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08015 dtmfbuf[i] = '\0';
08016 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
08017
08018 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
08019 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08020 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", dtmfcid, flags);
08021
08022 if (!ast_strlen_zero(dtmfcid))
08023 number = dtmfcid;
08024 else
08025 number = NULL;
08026
08027 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08028 cs = callerid_new(p->cid_signalling);
08029 if (cs) {
08030 samples = 0;
08031 #if 1
08032 bump_gains(p);
08033 #endif
08034
08035 dahdi_setlinear(p->subs[index].dfd, 0);
08036
08037
08038 for (;;) {
08039 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08040 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
08041 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08042 callerid_free(cs);
08043 ast_hangup(chan);
08044 goto quit;
08045 }
08046 if (i & DAHDI_IOMUX_SIGEVENT) {
08047 res = dahdi_get_event(p->subs[index].dfd);
08048 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08049 if (res == DAHDI_EVENT_NOALARM) {
08050 p->inalarm = 0;
08051 }
08052
08053 if (p->cid_signalling == CID_SIG_V23_JP) {
08054 #ifdef DAHDI_EVENT_RINGBEGIN
08055 if (res == DAHDI_EVENT_RINGBEGIN) {
08056 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08057 usleep(1);
08058 }
08059 #endif
08060 } else {
08061 res = 0;
08062 break;
08063 }
08064 } else if (i & DAHDI_IOMUX_READ) {
08065 res = read(p->subs[index].dfd, buf, sizeof(buf));
08066 if (res < 0) {
08067 if (errno != ELAST) {
08068 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08069 callerid_free(cs);
08070 ast_hangup(chan);
08071 goto quit;
08072 }
08073 break;
08074 }
08075 samples += res;
08076
08077 if (p->cid_signalling == CID_SIG_V23_JP) {
08078 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08079 } else {
08080 res = callerid_feed(cs, buf, res, AST_LAW(p));
08081 }
08082 if (res < 0) {
08083
08084
08085
08086
08087 ast_log(LOG_WARNING,
08088 "Failed to decode CallerID on channel '%s'\n",
08089 chan->name);
08090 break;
08091 } else if (res)
08092 break;
08093 else if (samples > (8000 * 10))
08094 break;
08095 }
08096 }
08097 if (res == 1) {
08098 callerid_get(cs, &name, &number, &flags);
08099 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08100 }
08101
08102 if (p->cid_signalling == CID_SIG_V23_JP) {
08103 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08104 usleep(1);
08105 }
08106
08107
08108 res = 4000;
08109 for (;;) {
08110 struct ast_frame *f;
08111 res = ast_waitfor(chan, res);
08112 if (res <= 0) {
08113 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08114 "Exiting simple switch\n");
08115 ast_hangup(chan);
08116 goto quit;
08117 }
08118 if (!(f = ast_read(chan))) {
08119 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08120 ast_hangup(chan);
08121 goto quit;
08122 }
08123 ast_frfree(f);
08124 if (chan->_state == AST_STATE_RING ||
08125 chan->_state == AST_STATE_RINGING)
08126 break;
08127 }
08128
08129
08130
08131 if (p->usedistinctiveringdetection) {
08132 len = 0;
08133 distMatches = 0;
08134
08135 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
08136 curRingData[receivedRingT] = 0;
08137 receivedRingT = 0;
08138 counter = 0;
08139 counter1 = 0;
08140
08141 if (strcmp(p->context,p->defcontext) != 0) {
08142 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08143 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08144 }
08145
08146 for (;;) {
08147 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08148 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
08149 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08150 callerid_free(cs);
08151 ast_hangup(chan);
08152 goto quit;
08153 }
08154 if (i & DAHDI_IOMUX_SIGEVENT) {
08155 res = dahdi_get_event(p->subs[index].dfd);
08156 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08157 if (res == DAHDI_EVENT_NOALARM) {
08158 p->inalarm = 0;
08159 }
08160 res = 0;
08161
08162
08163 curRingData[receivedRingT] = p->ringt;
08164
08165 if (p->ringt < p->ringt_base/2)
08166 break;
08167
08168
08169 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
08170 break;
08171 } else if (i & DAHDI_IOMUX_READ) {
08172 res = read(p->subs[index].dfd, buf, sizeof(buf));
08173 if (res < 0) {
08174 if (errno != ELAST) {
08175 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08176 callerid_free(cs);
08177 ast_hangup(chan);
08178 goto quit;
08179 }
08180 break;
08181 }
08182 if (p->ringt)
08183 p->ringt--;
08184 if (p->ringt == 1) {
08185 res = -1;
08186 break;
08187 }
08188 }
08189 }
08190 if (option_verbose > 2)
08191
08192 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08193
08194 for (counter = 0; counter < 3; counter++) {
08195
08196
08197 distMatches = 0;
08198 for (counter1 = 0; counter1 < 3; counter1++) {
08199 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
08200 (p->drings.ringnum[counter].ring[counter1]-10)) {
08201 distMatches++;
08202 }
08203 }
08204 if (distMatches == 3) {
08205
08206 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08207 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08208 if (option_verbose > 2)
08209 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
08210 break;
08211 }
08212 }
08213 }
08214
08215 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
08216 #if 1
08217 restore_gains(p);
08218 #endif
08219 } else
08220 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08221 } else {
08222 ast_log(LOG_WARNING, "Channel %s in prering "
08223 "state, but I have nothing to do. "
08224 "Terminating simple switch, should be "
08225 "restarted by the actual ring.\n",
08226 chan->name);
08227 ast_hangup(chan);
08228 goto quit;
08229 }
08230 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
08231
08232 cs = callerid_new(p->cid_signalling);
08233 if (cs) {
08234 #if 1
08235 bump_gains(p);
08236 #endif
08237 samples = 0;
08238 len = 0;
08239 distMatches = 0;
08240
08241 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
08242 curRingData[receivedRingT] = 0;
08243 receivedRingT = 0;
08244 counter = 0;
08245 counter1 = 0;
08246
08247 if (strcmp(p->context,p->defcontext) != 0) {
08248 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08249 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08250 }
08251
08252
08253 dahdi_setlinear(p->subs[index].dfd, 0);
08254 for (;;) {
08255 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08256 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
08257 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08258 callerid_free(cs);
08259 ast_hangup(chan);
08260 goto quit;
08261 }
08262 if (i & DAHDI_IOMUX_SIGEVENT) {
08263 res = dahdi_get_event(p->subs[index].dfd);
08264 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08265 if (res == DAHDI_EVENT_NOALARM) {
08266 p->inalarm = 0;
08267 }
08268
08269 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
08270 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
08271 p->polarity = POLARITY_IDLE;
08272 callerid_free(cs);
08273 ast_hangup(chan);
08274 goto quit;
08275 }
08276 res = 0;
08277
08278
08279 curRingData[receivedRingT] = p->ringt;
08280
08281 if (p->ringt < p->ringt_base/2)
08282 break;
08283
08284
08285 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
08286 break;
08287 } else if (i & DAHDI_IOMUX_READ) {
08288 res = read(p->subs[index].dfd, buf, sizeof(buf));
08289 if (res < 0) {
08290 if (errno != ELAST) {
08291 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08292 callerid_free(cs);
08293 ast_hangup(chan);
08294 goto quit;
08295 }
08296 break;
08297 }
08298 if (p->ringt)
08299 p->ringt--;
08300 if (p->ringt == 1) {
08301 res = -1;
08302 break;
08303 }
08304 samples += res;
08305 res = callerid_feed(cs, buf, res, AST_LAW(p));
08306 if (res < 0) {
08307
08308
08309
08310
08311 ast_log(LOG_WARNING,
08312 "Failed to decode CallerID on channel '%s'\n",
08313 chan->name);
08314 break;
08315 } else if (res)
08316 break;
08317 else if (samples > (8000 * 10))
08318 break;
08319 }
08320 }
08321 if (res == 1) {
08322 callerid_get(cs, &name, &number, &flags);
08323 if (option_debug)
08324 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08325 }
08326 if (distinctiveringaftercid == 1) {
08327
08328 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
08329 curRingData[receivedRingT] = 0;
08330 }
08331 receivedRingT = 0;
08332 if (option_verbose > 2)
08333 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
08334 for (;;) {
08335 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08336 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
08337 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08338 callerid_free(cs);
08339 ast_hangup(chan);
08340 goto quit;
08341 }
08342 if (i & DAHDI_IOMUX_SIGEVENT) {
08343 res = dahdi_get_event(p->subs[index].dfd);
08344 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08345 if (res == DAHDI_EVENT_NOALARM) {
08346 p->inalarm = 0;
08347 }
08348 res = 0;
08349
08350
08351 curRingData[receivedRingT] = p->ringt;
08352
08353 if (p->ringt < p->ringt_base/2)
08354 break;
08355
08356
08357 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
08358 break;
08359 } else if (i & DAHDI_IOMUX_READ) {
08360 res = read(p->subs[index].dfd, buf, sizeof(buf));
08361 if (res < 0) {
08362 if (errno != ELAST) {
08363 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08364 callerid_free(cs);
08365 ast_hangup(chan);
08366 goto quit;
08367 }
08368 break;
08369 }
08370 if (p->ringt)
08371 p->ringt--;
08372 if (p->ringt == 1) {
08373 res = -1;
08374 break;
08375 }
08376 }
08377 }
08378 }
08379 if (p->usedistinctiveringdetection) {
08380 if (option_verbose > 2)
08381
08382 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08383
08384 for (counter = 0; counter < 3; counter++) {
08385
08386
08387 if (option_verbose > 2)
08388
08389 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
08390 p->drings.ringnum[counter].ring[0],
08391 p->drings.ringnum[counter].ring[1],
08392 p->drings.ringnum[counter].ring[2]);
08393 distMatches = 0;
08394 for (counter1 = 0; counter1 < 3; counter1++) {
08395 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
08396 (p->drings.ringnum[counter].ring[counter1]-10)) {
08397 distMatches++;
08398 }
08399 }
08400 if (distMatches == 3) {
08401
08402 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08403 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08404 if (option_verbose > 2)
08405 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
08406 break;
08407 }
08408 }
08409 }
08410
08411 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
08412 #if 1
08413 restore_gains(p);
08414 #endif
08415 if (res < 0) {
08416 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
08417 }
08418 } else
08419 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08420 }
08421 else
08422 cs = NULL;
08423
08424 if (number)
08425 ast_shrink_phone_number(number);
08426 ast_set_callerid(chan, number, name, number);
08427
08428 if (smdi_msg)
08429 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
08430
08431 if (cs)
08432 callerid_free(cs);
08433
08434 ast_setstate(chan, AST_STATE_RING);
08435 chan->rings = 1;
08436 p->ringt = p->ringt_base;
08437 res = ast_pbx_run(chan);
08438 if (res) {
08439 ast_hangup(chan);
08440 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08441 }
08442 goto quit;
08443 default:
08444 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
08445 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
08446 if (res < 0)
08447 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08448 }
08449 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
08450 if (res < 0)
08451 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08452 ast_hangup(chan);
08453 quit:
08454 ast_mutex_lock(&ss_thread_lock);
08455 ss_thread_count--;
08456 ast_cond_signal(&ss_thread_complete);
08457 ast_mutex_unlock(&ss_thread_lock);
08458 return NULL;
08459 }
08460
08461 static int calc_energy(const unsigned char *buf, int len, int law)
08462 {
08463 int x;
08464 int sum = 0;
08465 int ssum = 0, mean = 0;
08466
08467 if (!len)
08468 return 0;
08469
08470
08471 for (x = 0; x < len; x++)
08472 ssum += (law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
08473
08474 mean = ssum / len;
08475
08476 for (x = 0; x < len; x++) {
08477 sum += abs((law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])) - mean);
08478 if (option_verbose > 7)
08479 ast_log(LOG_WARNING, "x %i, bufx: %i sum %i, ssum %i\n", x, buf[x], sum, ssum);
08480 }
08481
08482 if (option_verbose > 5)
08483 ast_log(LOG_WARNING, "mean %i, energy %i\n", mean, sum/len);
08484
08485 return sum / len;
08486 }
08487
08488
08489 static int dahdi_destroy_channel_bynum(int channel)
08490 {
08491 struct dahdi_pvt *tmp = NULL;
08492 struct dahdi_pvt *prev = NULL;
08493
08494 ast_mutex_lock(&iflock);
08495 tmp = iflist;
08496 while (tmp) {
08497 if (tmp->channel == channel) {
08498 int x = DAHDI_FLASH;
08499 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08500 destroy_channel(prev, tmp, 1);
08501 ast_mutex_unlock(&iflock);
08502 ast_module_unref(ast_module_info->self);
08503 return RESULT_SUCCESS;
08504 }
08505 prev = tmp;
08506 tmp = tmp->next;
08507 }
08508 ast_mutex_unlock(&iflock);
08509 return RESULT_FAILURE;
08510 }
08511
08512 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
08513 {
08514 int res;
08515 pthread_t threadid;
08516 pthread_attr_t attr;
08517 struct ast_channel *chan;
08518 pthread_attr_init(&attr);
08519 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08520
08521 switch (event) {
08522 case DAHDI_EVENT_NONE:
08523 case DAHDI_EVENT_BITSCHANGED:
08524 break;
08525 case DAHDI_EVENT_WINKFLASH:
08526 case DAHDI_EVENT_RINGOFFHOOK:
08527 if (i->inalarm) break;
08528 if (i->radio) break;
08529
08530 switch (i->sig) {
08531 case SIG_FXOLS:
08532 case SIG_FXOGS:
08533 case SIG_FXOKS:
08534 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08535 if (res && (errno == EBUSY))
08536 break;
08537
08538
08539 free(i->cidspill);
08540 i->cidspill = NULL;
08541 restore_conference(i);
08542
08543 if (i->immediate) {
08544 dahdi_enable_ec(i);
08545
08546 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08547 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08548 if (!chan) {
08549 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08550 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08551 if (res < 0)
08552 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08553 }
08554 } else {
08555
08556 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08557 if (chan) {
08558 if (has_voicemail(i))
08559 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08560 else
08561 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08562 if (res < 0)
08563 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08564 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08565 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08566 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08567 if (res < 0)
08568 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08569 ast_hangup(chan);
08570 }
08571 } else
08572 ast_log(LOG_WARNING, "Unable to create channel\n");
08573 }
08574 break;
08575 case SIG_FXSLS:
08576 case SIG_FXSGS:
08577 case SIG_FXSKS:
08578 i->ringt = i->ringt_base;
08579
08580 case SIG_EMWINK:
08581 case SIG_FEATD:
08582 case SIG_FEATDMF:
08583 case SIG_FEATDMF_TA:
08584 case SIG_E911:
08585 case SIG_FGC_CAMA:
08586 case SIG_FGC_CAMAMF:
08587 case SIG_FEATB:
08588 case SIG_EM:
08589 case SIG_EM_E1:
08590 case SIG_SFWINK:
08591 case SIG_SF_FEATD:
08592 case SIG_SF_FEATDMF:
08593 case SIG_SF_FEATB:
08594 case SIG_SF:
08595
08596 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08597 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08598 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08599 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08600 if (res < 0)
08601 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08602 ast_hangup(chan);
08603 } else if (!chan) {
08604 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08605 }
08606 break;
08607 default:
08608 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08609 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08610 if (res < 0)
08611 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08612 pthread_attr_destroy(&attr);
08613 return NULL;
08614 }
08615 break;
08616 case DAHDI_EVENT_NOALARM:
08617 i->inalarm = 0;
08618 #if defined(HAVE_PRI)
08619 i->resetting = 0;
08620 #endif
08621 if (!i->unknown_alarm) {
08622 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08623 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08624 "Channel: %d\r\n", i->channel);
08625 } else {
08626 i->unknown_alarm = 0;
08627 }
08628 break;
08629 case DAHDI_EVENT_ALARM:
08630 i->inalarm = 1;
08631 #if defined(HAVE_PRI)
08632 i->resetting = 0;
08633 #endif
08634 res = get_alarms(i);
08635 handle_alarms(i, res);
08636
08637 case DAHDI_EVENT_ONHOOK:
08638 if (i->radio)
08639 break;
08640
08641 switch (i->sig) {
08642 case SIG_FXOLS:
08643 case SIG_FXOGS:
08644 case SIG_FEATD:
08645 case SIG_FEATDMF:
08646 case SIG_FEATDMF_TA:
08647 case SIG_E911:
08648 case SIG_FGC_CAMA:
08649 case SIG_FGC_CAMAMF:
08650 case SIG_FEATB:
08651 case SIG_EM:
08652 case SIG_EM_E1:
08653 case SIG_EMWINK:
08654 case SIG_SF_FEATD:
08655 case SIG_SF_FEATDMF:
08656 case SIG_SF_FEATB:
08657 case SIG_SF:
08658 case SIG_SFWINK:
08659 case SIG_FXSLS:
08660 case SIG_FXSGS:
08661 case SIG_FXSKS:
08662 case SIG_GR303FXSKS:
08663 dahdi_disable_ec(i);
08664 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08665 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08666 break;
08667 case SIG_GR303FXOKS:
08668 case SIG_FXOKS:
08669 dahdi_disable_ec(i);
08670
08671 #ifdef ZHONE_HACK
08672 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08673 usleep(1);
08674 #endif
08675 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08676 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08677 break;
08678 case SIG_PRI:
08679 dahdi_disable_ec(i);
08680 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08681 break;
08682 default:
08683 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08684 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08685 pthread_attr_destroy(&attr);
08686 return NULL;
08687 }
08688 break;
08689 case DAHDI_EVENT_POLARITY:
08690 switch (i->sig) {
08691 case SIG_FXSLS:
08692 case SIG_FXSKS:
08693 case SIG_FXSGS:
08694
08695
08696
08697
08698 if (i->hanguponpolarityswitch)
08699 i->polarity = POLARITY_REV;
08700
08701 if (i->cid_start == CID_START_POLARITY) {
08702 i->polarity = POLARITY_REV;
08703 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08704 "CID detection on channel %d\n",
08705 i->channel);
08706 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08707 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08708 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08709 }
08710 }
08711 break;
08712 default:
08713 ast_log(LOG_WARNING, "handle_init_event detected "
08714 "polarity reversal on non-FXO (SIG_FXS) "
08715 "interface %d\n", i->channel);
08716 }
08717 break;
08718 case DAHDI_EVENT_REMOVED:
08719 ast_log(LOG_NOTICE,
08720 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08721 i->channel);
08722 pthread_attr_destroy(&attr);
08723 return i;
08724 }
08725 pthread_attr_destroy(&attr);
08726 return NULL;
08727 }
08728
08729 static void *do_monitor(void *data)
08730 {
08731 int count, res, res2, spoint, pollres=0;
08732 struct dahdi_pvt *i;
08733 struct dahdi_pvt *last = NULL;
08734 struct dahdi_pvt *doomed;
08735 time_t thispass = 0, lastpass = 0;
08736 int found;
08737 char buf[1024];
08738 struct pollfd *pfds=NULL;
08739 int lastalloc = -1;
08740
08741
08742
08743 #if 0
08744 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08745 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08746 return NULL;
08747 }
08748 ast_log(LOG_DEBUG, "Monitor starting...\n");
08749 #endif
08750 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08751
08752 for (;;) {
08753
08754 ast_mutex_lock(&iflock);
08755 if (!pfds || (lastalloc != ifcount)) {
08756 if (pfds) {
08757 free(pfds);
08758 pfds = NULL;
08759 }
08760 if (ifcount) {
08761 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08762 ast_mutex_unlock(&iflock);
08763 return NULL;
08764 }
08765 }
08766 lastalloc = ifcount;
08767 }
08768
08769
08770 count = 0;
08771 i = iflist;
08772 while (i) {
08773 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08774 if (!i->owner && !i->subs[SUB_REAL].owner) {
08775
08776 pfds[count].fd = i->subs[SUB_REAL].dfd;
08777 pfds[count].events = POLLPRI;
08778 pfds[count].revents = 0;
08779
08780 if (i->cidspill ||
08781 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
08782 pfds[count].events |= POLLIN;
08783 }
08784 count++;
08785 }
08786 }
08787 i = i->next;
08788 }
08789
08790 ast_mutex_unlock(&iflock);
08791
08792 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08793 pthread_testcancel();
08794
08795 res = poll(pfds, count, 1000);
08796 pthread_testcancel();
08797 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08798
08799
08800 if (res < 0) {
08801 if ((errno != EAGAIN) && (errno != EINTR))
08802 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08803 continue;
08804 }
08805
08806
08807 ast_mutex_lock(&iflock);
08808 found = 0;
08809 spoint = 0;
08810 lastpass = thispass;
08811 thispass = time(NULL);
08812 doomed = NULL;
08813 for (i = iflist;; i = i->next) {
08814 if (doomed) {
08815 int res;
08816 res = dahdi_destroy_channel_bynum(doomed->channel);
08817 if (!res) {
08818 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08819 }
08820 doomed = NULL;
08821 }
08822 if (!i) {
08823 break;
08824 }
08825 if (thispass != lastpass) {
08826 if (!found && ((i == last) || ((i == iflist) && !last))) {
08827 last = i;
08828 if (last) {
08829 if (!last->cidspill
08830 && !last->owner
08831 && !ast_strlen_zero(last->mailbox)
08832 && (thispass - last->onhooktime > 3)
08833 && (last->sig & __DAHDI_SIG_FXO)) {
08834 res = ast_app_has_voicemail(last->mailbox, NULL);
08835 if (last->msgstate != res) {
08836 int x;
08837 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08838 x = DAHDI_FLUSH_BOTH;
08839 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08840 if (res2)
08841 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08842 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08843
08844 x = 4000;
08845 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08846 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08847 last->cidpos = 0;
08848 last->msgstate = res;
08849 last->onhooktime = thispass;
08850 }
08851 found ++;
08852 }
08853 }
08854 last = last->next;
08855 }
08856 }
08857 }
08858 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08859 if (i->radio && !i->owner)
08860 {
08861 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08862 if (res)
08863 {
08864 if (option_debug)
08865 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08866
08867 ast_mutex_unlock(&iflock);
08868 doomed = handle_init_event(i, res);
08869 ast_mutex_lock(&iflock);
08870 }
08871 continue;
08872 }
08873 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08874 if (pollres & POLLIN) {
08875 if (i->owner || i->subs[SUB_REAL].owner) {
08876 #ifdef HAVE_PRI
08877 if (!i->pri)
08878 #endif
08879 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08880 continue;
08881 }
08882 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08883 if (res > 0) {
08884
08885
08886 if (i->cid_start == CID_START_DTMF_NOALERT) {
08887 int energy;
08888 struct timeval now;
08889
08890
08891
08892 if (1 == i->dtmfcid_holdoff_state) {
08893 gettimeofday(&i->dtmfcid_delay, NULL);
08894 i->dtmfcid_holdoff_state = 2;
08895 } else if (2 == i->dtmfcid_holdoff_state) {
08896 gettimeofday(&now, NULL);
08897 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
08898 i->dtmfcid_holdoff_state = 0;
08899 }
08900 } else {
08901 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
08902 if (energy > dtmfcid_level) {
08903 pthread_t threadid;
08904 struct ast_channel *chan;
08905 ast_mutex_unlock(&iflock);
08906 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08907 if (!chan) {
08908 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08909 } else {
08910 pthread_attr_t attr;
08911 pthread_attr_init(&attr);
08912 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08913 res = ast_pthread_create(&threadid, &attr, ss_thread, chan);
08914 if (res) {
08915 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08916 } else {
08917 i->dtmfcid_holdoff_state = 1;
08918 }
08919 }
08920 ast_mutex_lock(&iflock);
08921 }
08922 }
08923 }
08924 } else {
08925 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08926 }
08927 }
08928 if (pollres & POLLPRI) {
08929 if (i->owner || i->subs[SUB_REAL].owner) {
08930 #ifdef HAVE_PRI
08931 if (!i->pri)
08932 #endif
08933 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08934 continue;
08935 }
08936 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08937 if (option_debug)
08938 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08939
08940 ast_mutex_unlock(&iflock);
08941 doomed = handle_init_event(i, res);
08942 ast_mutex_lock(&iflock);
08943 }
08944 }
08945 }
08946 ast_mutex_unlock(&iflock);
08947 }
08948
08949 return NULL;
08950
08951 }
08952
08953 static int restart_monitor(void)
08954 {
08955 pthread_attr_t attr;
08956 pthread_attr_init(&attr);
08957 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08958
08959 if (monitor_thread == AST_PTHREADT_STOP)
08960 return 0;
08961 ast_mutex_lock(&monlock);
08962 if (monitor_thread == pthread_self()) {
08963 ast_mutex_unlock(&monlock);
08964 ast_log(LOG_WARNING, "Cannot kill myself\n");
08965 return -1;
08966 }
08967 if (monitor_thread != AST_PTHREADT_NULL) {
08968
08969 pthread_kill(monitor_thread, SIGURG);
08970 } else {
08971
08972 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08973 ast_mutex_unlock(&monlock);
08974 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08975 pthread_attr_destroy(&attr);
08976 return -1;
08977 }
08978 }
08979 ast_mutex_unlock(&monlock);
08980 pthread_attr_destroy(&attr);
08981 return 0;
08982 }
08983
08984 #ifdef HAVE_OPENR2
08985 static struct dahdi_mfcr2 *mfcr2_get_context(int id)
08986 {
08987 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08988 ast_log(LOG_ERROR, "No more R2 links available!.\n");
08989 return NULL;
08990 }
08991 return &r2links[id];
08992 }
08993 #endif
08994
08995 #ifdef HAVE_PRI
08996 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08997 {
08998 int x;
08999 int trunkgroup;
09000
09001 trunkgroup = pris[*span].mastertrunkgroup;
09002 if (trunkgroup) {
09003
09004 for (x = 0; x < NUM_SPANS; x++) {
09005 if (pris[x].trunkgroup == trunkgroup) {
09006 *span = x;
09007 return 0;
09008 }
09009 }
09010 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
09011 *span = -1;
09012 } else {
09013 if (pris[*span].trunkgroup) {
09014 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
09015 *span = -1;
09016 } else if (pris[*span].mastertrunkgroup) {
09017 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
09018 *span = -1;
09019 } else {
09020 if (si->totalchans == 31) {
09021
09022 pris[*span].dchannels[0] = 16 + offset;
09023 } else if (si->totalchans == 24) {
09024
09025 pris[*span].dchannels[0] = 24 + offset;
09026 } else if (si->totalchans == 3) {
09027
09028 pris[*span].dchannels[0] = 3 + offset;
09029 } else {
09030 ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
09031 *span = -1;
09032 return 0;
09033 }
09034 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
09035 pris[*span].offset = offset;
09036 pris[*span].span = *span + 1;
09037 }
09038 }
09039 return 0;
09040 }
09041
09042 static int pri_create_trunkgroup(int trunkgroup, int *channels)
09043 {
09044 struct dahdi_spaninfo si;
09045 struct dahdi_params p;
09046 int fd;
09047 int span;
09048 int ospan=0;
09049 int x,y;
09050 for (x = 0; x < NUM_SPANS; x++) {
09051 if (pris[x].trunkgroup == trunkgroup) {
09052 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
09053 return -1;
09054 }
09055 }
09056 for (y = 0; y < NUM_DCHANS; y++) {
09057 if (!channels[y])
09058 break;
09059 memset(&si, 0, sizeof(si));
09060 memset(&p, 0, sizeof(p));
09061 fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
09062 if (fd < 0) {
09063 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
09064 return -1;
09065 }
09066 x = channels[y];
09067 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
09068 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
09069 close(fd);
09070 return -1;
09071 }
09072 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
09073 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
09074 return -1;
09075 }
09076 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
09077 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
09078 close(fd);
09079 return -1;
09080 }
09081 span = p.spanno - 1;
09082 if (pris[span].trunkgroup) {
09083 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
09084 close(fd);
09085 return -1;
09086 }
09087 if (pris[span].pvts[0]) {
09088 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
09089 close(fd);
09090 return -1;
09091 }
09092 if (!y) {
09093 pris[span].trunkgroup = trunkgroup;
09094 pris[span].offset = channels[y] - p.chanpos;
09095 ospan = span;
09096 }
09097 pris[ospan].dchannels[y] = channels[y];
09098 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
09099 pris[span].span = span + 1;
09100 close(fd);
09101 }
09102 return 0;
09103 }
09104
09105 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
09106 {
09107 if (pris[span].mastertrunkgroup) {
09108 ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
09109 return -1;
09110 }
09111 pris[span].mastertrunkgroup = trunkgroup;
09112 pris[span].prilogicalspan = logicalspan;
09113 return 0;
09114 }
09115
09116 #endif
09117
09118 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
09119 {
09120
09121 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
09122 char fn[80];
09123 #if 1
09124 struct dahdi_bufferinfo bi;
09125 #endif
09126 int res;
09127 int span=0;
09128 int here = 0;
09129 int x;
09130 struct dahdi_pvt **wlist;
09131 struct dahdi_pvt **wend;
09132 struct dahdi_params p;
09133
09134 wlist = &iflist;
09135 wend = &ifend;
09136
09137 #ifdef HAVE_PRI
09138 if (pri) {
09139 wlist = &pri->crvs;
09140 wend = &pri->crvend;
09141 }
09142 #endif
09143
09144 tmp2 = *wlist;
09145 prev = NULL;
09146
09147 while (tmp2) {
09148 if (!tmp2->destroy) {
09149 if (tmp2->channel == channel) {
09150 tmp = tmp2;
09151 here = 1;
09152 break;
09153 }
09154 if (tmp2->channel > channel) {
09155 break;
09156 }
09157 }
09158 prev = tmp2;
09159 tmp2 = tmp2->next;
09160 }
09161
09162 if (!here && reloading != 1) {
09163 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
09164 if (tmp)
09165 free(tmp);
09166 return NULL;
09167 }
09168 ast_mutex_init(&tmp->lock);
09169 ifcount++;
09170 for (x = 0; x < 3; x++)
09171 tmp->subs[x].dfd = -1;
09172 tmp->channel = channel;
09173 tmp->priindication_oob = conf->chan.priindication_oob;
09174 }
09175
09176 if (tmp) {
09177 int chan_sig = conf->chan.sig;
09178 if (!here) {
09179 if ((channel != CHAN_PSEUDO) && !pri) {
09180 int count = 0;
09181 snprintf(fn, sizeof(fn), "%d", channel);
09182
09183 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
09184 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
09185 usleep(1);
09186 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
09187 count++;
09188 }
09189
09190 if (tmp->subs[SUB_REAL].dfd < 0) {
09191 ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
09192 destroy_dahdi_pvt(&tmp);
09193 return NULL;
09194 }
09195 memset(&p, 0, sizeof(p));
09196 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
09197 if (res < 0) {
09198 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
09199 destroy_dahdi_pvt(&tmp);
09200 return NULL;
09201 }
09202 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
09203 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype));
09204 destroy_dahdi_pvt(&tmp);
09205 return NULL;
09206 }
09207 tmp->law = p.curlaw;
09208 tmp->span = p.spanno;
09209 span = p.spanno - 1;
09210 } else {
09211 if (channel == CHAN_PSEUDO)
09212 chan_sig = 0;
09213 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
09214 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
09215 return NULL;
09216 }
09217 }
09218 tmp->outsigmod = conf->chan.outsigmod;
09219
09220 #ifdef HAVE_PRI
09221 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
09222 int offset;
09223 int myswitchtype;
09224 int matchesdchan;
09225 int x,y;
09226 offset = 0;
09227 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
09228 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
09229 destroy_dahdi_pvt(&tmp);
09230 return NULL;
09231 }
09232 if (span >= NUM_SPANS) {
09233 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
09234 destroy_dahdi_pvt(&tmp);
09235 return NULL;
09236 } else {
09237 struct dahdi_spaninfo si;
09238 si.spanno = 0;
09239 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
09240 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
09241 destroy_dahdi_pvt(&tmp);
09242 return NULL;
09243 }
09244
09245 tmp->logicalspan = pris[span].prilogicalspan;
09246 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
09247 if (span < 0) {
09248 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
09249 destroy_dahdi_pvt(&tmp);
09250 return NULL;
09251 }
09252 if (chan_sig == SIG_PRI)
09253 myswitchtype = conf->pri.switchtype;
09254 else
09255 myswitchtype = PRI_SWITCH_GR303_TMC;
09256
09257 matchesdchan=0;
09258 for (x = 0; x < NUM_SPANS; x++) {
09259 for (y = 0; y < NUM_DCHANS; y++) {
09260 if (pris[x].dchannels[y] == tmp->channel) {
09261 matchesdchan = 1;
09262 break;
09263 }
09264 }
09265 }
09266 offset = p.chanpos;
09267 if (!matchesdchan) {
09268 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
09269 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
09270 destroy_dahdi_pvt(&tmp);
09271 return NULL;
09272 }
09273 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
09274 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
09275 destroy_dahdi_pvt(&tmp);
09276 return NULL;
09277 }
09278 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
09279 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
09280 destroy_dahdi_pvt(&tmp);
09281 return NULL;
09282 }
09283 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
09284 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
09285 destroy_dahdi_pvt(&tmp);
09286 return NULL;
09287 }
09288 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
09289 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
09290 destroy_dahdi_pvt(&tmp);
09291 return NULL;
09292 }
09293 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
09294 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
09295 destroy_dahdi_pvt(&tmp);
09296 return NULL;
09297 }
09298 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
09299 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
09300 destroy_dahdi_pvt(&tmp);
09301 return NULL;
09302 }
09303 if (pris[span].numchans >= MAX_CHANNELS) {
09304 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
09305 pris[span].trunkgroup);
09306 destroy_dahdi_pvt(&tmp);
09307 return NULL;
09308 }
09309 pris[span].nodetype = conf->pri.nodetype;
09310 pris[span].switchtype = myswitchtype;
09311 pris[span].nsf = conf->pri.nsf;
09312 pris[span].dialplan = conf->pri.dialplan;
09313 pris[span].localdialplan = conf->pri.localdialplan;
09314 pris[span].pvts[pris[span].numchans++] = tmp;
09315 pris[span].minunused = conf->pri.minunused;
09316 pris[span].minidle = conf->pri.minidle;
09317 pris[span].overlapdial = conf->pri.overlapdial;
09318 #ifdef HAVE_PRI_INBANDDISCONNECT
09319 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
09320 #endif
09321 pris[span].facilityenable = conf->pri.facilityenable;
09322 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
09323 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
09324 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
09325 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
09326 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
09327 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
09328 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
09329 pris[span].resetinterval = conf->pri.resetinterval;
09330
09331 tmp->pri = &pris[span];
09332 tmp->prioffset = offset;
09333 tmp->call = NULL;
09334
09335 tmp->priexclusive = conf->chan.priexclusive;
09336 } else {
09337 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
09338 destroy_dahdi_pvt(&tmp);
09339 return NULL;
09340 }
09341 }
09342 } else {
09343 tmp->prioffset = 0;
09344 }
09345 #endif
09346
09347 #ifdef HAVE_OPENR2
09348 if (chan_sig == SIG_MFCR2 && reloading != 1) {
09349 char logdir[OR2_MAX_PATH];
09350 struct dahdi_mfcr2 *dahdi_r2;
09351 int threshold = 0;
09352 int snres = 0;
09353 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
09354 if (!dahdi_r2) {
09355 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
09356 } else if (!dahdi_r2->protocol_context){
09357 char tmplogdir[] = "/tmp";
09358 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
09359 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
09360 if (!dahdi_r2->protocol_context) {
09361 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
09362 destroy_dahdi_pvt(&tmp);
09363 return NULL;
09364 }
09365 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
09366 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
09367 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
09368 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
09369 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
09370 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
09371 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
09372 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
09373 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
09374 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
09375 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
09376 #endif
09377 if (ast_strlen_zero(mfcr2_cur_logdir)) {
09378 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
09379 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09380 }
09381 } else {
09382 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
09383 if (snres >= sizeof(logdir)) {
09384 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
09385 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
09386 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09387 }
09388 } else {
09389 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
09390 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
09391 }
09392 }
09393 }
09394 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
09395 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
09396 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
09397 }
09398 }
09399 }
09400 if (dahdi_r2) {
09401
09402 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
09403 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
09404 tmp->subs[SUB_REAL].dfd, NULL, NULL);
09405 if (!tmp->r2chan) {
09406 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
09407 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
09408 destroy_dahdi_pvt(&tmp);
09409 return NULL;
09410 }
09411 openr2_chan_set_client_data(tmp->r2chan, tmp);
09412
09413 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
09414 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
09415 if (mfcr2_cur_call_files) {
09416 openr2_chan_enable_call_files(tmp->r2chan);
09417 }
09418 tmp->mfcr2_category = mfcr2_cur_category;
09419 tmp->mfcr2 = dahdi_r2;
09420 tmp->mfcr2call = 0;
09421 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
09422 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
09423 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
09424 tmp->mfcr2_ani_index = 0;
09425 tmp->mfcr2_dnis_index = 0;
09426 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
09427 tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
09428 }
09429 }
09430 #endif
09431
09432 } else {
09433 chan_sig = tmp->sig;
09434 if (tmp->subs[SUB_REAL].dfd > -1) {
09435 memset(&p, 0, sizeof(p));
09436 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
09437 }
09438 }
09439
09440 switch (chan_sig) {
09441 case SIG_FXSKS:
09442 case SIG_FXSLS:
09443 case SIG_EM:
09444 case SIG_EM_E1:
09445 case SIG_EMWINK:
09446 case SIG_FEATD:
09447 case SIG_FEATDMF:
09448 case SIG_FEATDMF_TA:
09449 case SIG_FEATB:
09450 case SIG_E911:
09451 case SIG_SF:
09452 case SIG_SFWINK:
09453 case SIG_FGC_CAMA:
09454 case SIG_FGC_CAMAMF:
09455 case SIG_SF_FEATD:
09456 case SIG_SF_FEATDMF:
09457 case SIG_SF_FEATB:
09458 p.starttime = 250;
09459 break;
09460 }
09461
09462 if (tmp->radio) {
09463
09464 p.channo = channel;
09465 p.rxwinktime = 1;
09466 p.rxflashtime = 1;
09467 p.starttime = 1;
09468 p.debouncetime = 5;
09469 }
09470 if (!tmp->radio) {
09471 p.channo = channel;
09472
09473 if (conf->timing.prewinktime >= 0)
09474 p.prewinktime = conf->timing.prewinktime;
09475 if (conf->timing.preflashtime >= 0)
09476 p.preflashtime = conf->timing.preflashtime;
09477 if (conf->timing.winktime >= 0)
09478 p.winktime = conf->timing.winktime;
09479 if (conf->timing.flashtime >= 0)
09480 p.flashtime = conf->timing.flashtime;
09481 if (conf->timing.starttime >= 0)
09482 p.starttime = conf->timing.starttime;
09483 if (conf->timing.rxwinktime >= 0)
09484 p.rxwinktime = conf->timing.rxwinktime;
09485 if (conf->timing.rxflashtime >= 0)
09486 p.rxflashtime = conf->timing.rxflashtime;
09487 if (conf->timing.debouncetime >= 0)
09488 p.debouncetime = conf->timing.debouncetime;
09489 }
09490
09491
09492 if (tmp->subs[SUB_REAL].dfd >= 0)
09493 {
09494 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09495 if (res < 0) {
09496 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09497 destroy_dahdi_pvt(&tmp);
09498 return NULL;
09499 }
09500 }
09501 #if 1
09502 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09503 memset(&bi, 0, sizeof(bi));
09504 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09505 if (!res) {
09506 bi.txbufpolicy = conf->chan.buf_policy;
09507 bi.rxbufpolicy = conf->chan.buf_policy;
09508 bi.numbufs = conf->chan.buf_no;
09509 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09510 if (res < 0) {
09511 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09512 }
09513 } else {
09514 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09515 }
09516 tmp->buf_policy = conf->chan.buf_policy;
09517 tmp->buf_no = conf->chan.buf_no;
09518
09519
09520
09521
09522 tmp->bufsize = bi.bufsize;
09523 }
09524 #endif
09525 tmp->immediate = conf->chan.immediate;
09526 tmp->transfertobusy = conf->chan.transfertobusy;
09527 tmp->sig = chan_sig;
09528 tmp->ringt_base = ringt_base;
09529 tmp->firstradio = 0;
09530 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09531 tmp->permcallwaiting = conf->chan.callwaiting;
09532 else
09533 tmp->permcallwaiting = 0;
09534
09535 tmp->destroy = 0;
09536 tmp->drings = drings;
09537 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
09538 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09539 tmp->threewaycalling = conf->chan.threewaycalling;
09540 tmp->adsi = conf->chan.adsi;
09541 tmp->use_smdi = conf->chan.use_smdi;
09542 tmp->permhidecallerid = conf->chan.hidecallerid;
09543 tmp->hidecalleridname = conf->chan.hidecalleridname;
09544 tmp->callreturn = conf->chan.callreturn;
09545 tmp->echocancel = conf->chan.echocancel;
09546 tmp->echotraining = conf->chan.echotraining;
09547 tmp->pulse = conf->chan.pulse;
09548 if (tmp->echocancel)
09549 tmp->echocanbridged = conf->chan.echocanbridged;
09550 else {
09551 if (conf->chan.echocanbridged)
09552 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09553 tmp->echocanbridged = 0;
09554 }
09555 tmp->busydetect = conf->chan.busydetect;
09556 tmp->busycount = conf->chan.busycount;
09557 tmp->busycompare = conf->chan.busycompare;
09558 tmp->busytonelength = conf->chan.busytonelength;
09559 tmp->busyquietlength = conf->chan.busyquietlength;
09560 tmp->busyfuzziness = conf->chan.busyfuzziness;
09561 tmp->silencethreshold = conf->chan.silencethreshold;
09562 tmp->callprogress = conf->chan.callprogress;
09563 tmp->cancallforward = conf->chan.cancallforward;
09564 tmp->dtmfrelax = conf->chan.dtmfrelax;
09565 tmp->callwaiting = tmp->permcallwaiting;
09566 tmp->hidecallerid = tmp->permhidecallerid;
09567 tmp->channel = channel;
09568 tmp->stripmsd = conf->chan.stripmsd;
09569 tmp->use_callerid = conf->chan.use_callerid;
09570 tmp->cid_signalling = conf->chan.cid_signalling;
09571 tmp->cid_start = conf->chan.cid_start;
09572 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09573 tmp->restrictcid = conf->chan.restrictcid;
09574 tmp->use_callingpres = conf->chan.use_callingpres;
09575 if (tmp->usedistinctiveringdetection) {
09576 if (!tmp->use_callerid) {
09577 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09578 tmp->use_callerid = 1;
09579 }
09580 }
09581
09582 if (tmp->cid_signalling == CID_SIG_SMDI) {
09583 if (!tmp->use_smdi) {
09584 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09585 tmp->use_smdi = 1;
09586 }
09587 }
09588 if (tmp->use_smdi) {
09589 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09590 if (!(tmp->smdi_iface)) {
09591 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09592 tmp->use_smdi = 0;
09593 }
09594 }
09595
09596 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09597 tmp->amaflags = conf->chan.amaflags;
09598 if (!here) {
09599 tmp->confno = -1;
09600 tmp->propconfno = -1;
09601 }
09602 tmp->canpark = conf->chan.canpark;
09603 tmp->transfer = conf->chan.transfer;
09604 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09605 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09606 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09607 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09608 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09609 tmp->cid_ton = 0;
09610 if (chan_sig != SIG_PRI) {
09611 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09612 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09613 } else {
09614 tmp->cid_num[0] = '\0';
09615 tmp->cid_name[0] = '\0';
09616 }
09617 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09618 tmp->msgstate = -1;
09619 tmp->group = conf->chan.group;
09620 tmp->callgroup = conf->chan.callgroup;
09621 tmp->pickupgroup= conf->chan.pickupgroup;
09622 tmp->rxgain = conf->chan.rxgain;
09623 tmp->txgain = conf->chan.txgain;
09624 tmp->tonezone = conf->chan.tonezone;
09625 tmp->onhooktime = time(NULL);
09626 if (tmp->subs[SUB_REAL].dfd > -1) {
09627 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09628 if (tmp->dsp)
09629 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09630 update_conf(tmp);
09631 if (!here) {
09632 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09633
09634 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09635 }
09636 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09637 #ifdef HAVE_PRI
09638
09639 if (tmp->pri && !pri_is_up(tmp->pri)) {
09640 tmp->inalarm = 1;
09641 tmp->resetting = 0;
09642 }
09643 #endif
09644 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09645 tmp->inalarm = 1;
09646 #if defined(HAVE_PRI)
09647 tmp->resetting = 0;
09648 #endif
09649 handle_alarms(tmp, res);
09650 } else {
09651
09652
09653
09654
09655
09656
09657
09658
09659
09660
09661 tmp->unknown_alarm = 1;
09662 }
09663 }
09664
09665 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09666 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09667 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09668 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09669
09670 }
09671 if (tmp && !here) {
09672
09673 if (!*wlist) {
09674 *wlist = tmp;
09675 tmp->prev = NULL;
09676 tmp->next = NULL;
09677 *wend = tmp;
09678 } else {
09679
09680 struct dahdi_pvt *working = *wlist;
09681
09682
09683 if (working->channel > tmp->channel) {
09684 tmp->next = *wlist;
09685 tmp->prev = NULL;
09686 (*wlist)->prev = tmp;
09687 *wlist = tmp;
09688 } else {
09689
09690 while (working) {
09691
09692 if (working->next) {
09693 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09694 tmp->next = working->next;
09695 tmp->prev = working;
09696 working->next->prev = tmp;
09697 working->next = tmp;
09698 break;
09699 }
09700 } else {
09701
09702 if (working->channel < tmp->channel) {
09703 working->next = tmp;
09704 tmp->next = NULL;
09705 tmp->prev = working;
09706 *wend = tmp;
09707 break;
09708 }
09709 }
09710 working = working->next;
09711 }
09712 }
09713 }
09714 }
09715 return tmp;
09716 }
09717
09718 #if defined(HAVE_PRI)
09719
09720
09721
09722
09723
09724
09725
09726
09727
09728 static int sig_pri_is_chan_in_use(struct dahdi_pvt *pvt)
09729 {
09730 return pvt->owner || pvt->call || pvt->allocated || pvt->resetting || pvt->inalarm;
09731 }
09732 #endif
09733
09734 #if defined(HAVE_PRI)
09735
09736
09737
09738
09739
09740
09741
09742
09743
09744 static int sig_pri_is_chan_available(struct dahdi_pvt *pvt)
09745 {
09746 return !sig_pri_is_chan_in_use(pvt);
09747 }
09748 #endif
09749
09750 #if defined(HAVE_PRI)
09751
09752
09753
09754
09755
09756
09757
09758
09759
09760
09761 static int sig_pri_available_check(struct dahdi_pvt *pvt)
09762 {
09763
09764
09765
09766
09767 if (sig_pri_is_chan_available(pvt)) {
09768 return 1;
09769 }
09770 return 0;
09771 }
09772 #endif
09773
09774 #if defined(HAVE_PRI)
09775 static int sig_pri_available(struct dahdi_pvt *pvt)
09776 {
09777 struct dahdi_pvt *p = pvt;
09778 struct dahdi_pri *pri;
09779
09780 if (!p->pri) {
09781
09782 return 0;
09783 }
09784 pri = p->pri;
09785
09786 ast_mutex_lock(&pri->lock);
09787 if (sig_pri_available_check(p)) {
09788 p->allocated = 1;
09789 ast_mutex_unlock(&pri->lock);
09790 return 1;
09791 }
09792
09793 ast_mutex_unlock(&pri->lock);
09794 return 0;
09795 }
09796 #endif
09797
09798 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09799 {
09800 int res;
09801 struct dahdi_params par;
09802
09803
09804 if (groupmatch) {
09805 if ((p->group & groupmatch) != groupmatch)
09806 return 0;
09807 *groupmatched = 1;
09808 }
09809
09810 if (channelmatch != -1) {
09811 if (p->channel != channelmatch)
09812 return 0;
09813 *channelmatched = 1;
09814 }
09815
09816 #if defined(HAVE_PRI)
09817 switch (p->sig) {
09818 case SIG_PRI_LIB_HANDLE_CASES:
09819 return sig_pri_available(p);
09820 default:
09821 break;
09822 }
09823 #endif
09824
09825
09826 if (busy) {
09827 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09828 *busy = 1;
09829 }
09830
09831 if (p->dnd)
09832 return 0;
09833
09834 if (p->guardtime && (time(NULL) < p->guardtime))
09835 return 0;
09836
09837
09838 if (!p->owner) {
09839 #ifdef HAVE_PRI
09840
09841 if (p->pri) {
09842
09843 return sig_pri_available(p);
09844 }
09845 #endif
09846
09847 #ifdef HAVE_OPENR2
09848
09849 if (p->mfcr2) {
09850 if (p->mfcr2call || p->mfcr2block)
09851 return 0;
09852 else
09853 return 1;
09854 }
09855 #endif
09856
09857 if (!(p->radio || (p->oprmode < 0)))
09858 {
09859 if (!p->sig || (p->sig == SIG_FXSLS))
09860 return 1;
09861
09862 if (p->subs[SUB_REAL].dfd > -1) {
09863 memset(&par, 0, sizeof(par));
09864 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09865 } else {
09866
09867 res = 0;
09868 par.rxisoffhook = 0;
09869 }
09870 if (res) {
09871 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09872 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09873
09874
09875
09876 if (par.rxbits > -1)
09877 return 1;
09878 if (par.rxisoffhook)
09879 return 1;
09880 else
09881 #ifdef DAHDI_CHECK_HOOKSTATE
09882 return 0;
09883 #else
09884 return 1;
09885 #endif
09886 } else if (par.rxisoffhook) {
09887 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09888
09889 return 0;
09890 }
09891 }
09892 return 1;
09893 }
09894
09895
09896 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09897 return 0;
09898
09899 if (!p->callwaiting) {
09900
09901 return 0;
09902 }
09903
09904 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09905
09906 return 0;
09907 }
09908
09909 if ((p->owner->_state != AST_STATE_UP) &&
09910 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09911
09912 return 0;
09913 }
09914 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09915
09916 return 0;
09917 }
09918
09919 return 1;
09920 }
09921
09922 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09923 {
09924 struct dahdi_pvt *p;
09925 struct dahdi_bufferinfo bi;
09926 int res;
09927
09928 if ((p = ast_malloc(sizeof(*p)))) {
09929 memcpy(p, src, sizeof(struct dahdi_pvt));
09930 ast_mutex_init(&p->lock);
09931 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09932
09933 if (p->subs[SUB_REAL].dfd < 0) {
09934 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09935 destroy_dahdi_pvt(&p);
09936 return NULL;
09937 }
09938 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09939 if (!res) {
09940 bi.txbufpolicy = p->buf_policy;
09941 bi.rxbufpolicy = p->buf_policy;
09942 bi.numbufs = p->buf_no;
09943 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09944 if (res < 0) {
09945 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09946 }
09947 } else
09948 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09949 }
09950 p->destroy = 1;
09951 p->next = iflist;
09952 p->prev = NULL;
09953 iflist = p;
09954 if (iflist->next)
09955 iflist->next->prev = p;
09956 return p;
09957 }
09958
09959
09960 #ifdef HAVE_PRI
09961
09962
09963
09964
09965
09966
09967
09968
09969
09970
09971
09972
09973
09974 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards, int orig)
09975 {
09976 int x;
09977 if (backwards)
09978 x = pri->numchans;
09979 else
09980 x = 0;
09981 for (;;) {
09982 if (backwards && (x < 0))
09983 break;
09984 if (!backwards && (x >= pri->numchans))
09985 break;
09986 if (pri->pvts[x]
09987 && sig_pri_is_chan_available(pri->pvts[x])) {
09988 if (orig < 0) {
09989 ast_log(LOG_NOTICE, "Found empty available channel %d/%d\n",
09990 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09991 return x;
09992 } else {
09993 if (pri->pvts[x]->group & pri->pvts[orig]->group) {
09994 ast_log(LOG_NOTICE, "Found empty channel %d/%d available belonging to same group that %d/%d\n (x: %d)", pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset,
09995 pri->pvts[x]->logicalspan, pri->pvts[orig]->prioffset, x);
09996 return x;
09997 } else {
09998 ast_log(LOG_DEBUG, "Empty channel %d/%d available but not belongs to same group that %d/%d (x: %d)\n", pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset,
09999 pri->pvts[x]->logicalspan, pri->pvts[orig]->prioffset, x);
10000 }
10001 }
10002 }
10003 if (backwards)
10004 x--;
10005 else
10006 x++;
10007 }
10008 return -1;
10009 }
10010 #endif
10011
10012 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
10013 {
10014 ast_group_t groupmatch = 0;
10015 int channelmatch = -1;
10016 int roundrobin = 0;
10017 int callwait = 0;
10018 int busy = 0;
10019 struct dahdi_pvt *p;
10020 struct ast_channel *tmp = NULL;
10021 char *dest=NULL;
10022 int x;
10023 char *s;
10024 char opt=0;
10025 int res=0, y=0;
10026 int backwards = 0;
10027 #ifdef HAVE_PRI
10028 int crv;
10029 int bearer = -1;
10030 int trunkgroup;
10031 struct dahdi_pri *pri=NULL;
10032 #endif
10033 struct dahdi_pvt *exit, *start, *end;
10034 ast_mutex_t *lock;
10035 int channelmatched = 0;
10036 int groupmatched = 0;
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056 lock = &iflock;
10057 start = iflist;
10058 end = ifend;
10059 if (data) {
10060 dest = ast_strdupa((char *)data);
10061 } else {
10062 ast_log(LOG_WARNING, "Channel requested with no data\n");
10063 return NULL;
10064 }
10065 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
10066
10067 char *stringp;
10068
10069 stringp = dest + 1;
10070 s = strsep(&stringp, "/");
10071 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10072 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
10073 return NULL;
10074 }
10075 groupmatch = ((ast_group_t) 1 << x);
10076 if (toupper(dest[0]) == 'G') {
10077 if (dest[0] == 'G') {
10078 backwards = 1;
10079 p = ifend;
10080 } else
10081 p = iflist;
10082 } else {
10083 if (dest[0] == 'R') {
10084 backwards = 1;
10085 p = round_robin[x]?round_robin[x]->prev:ifend;
10086 if (!p)
10087 p = ifend;
10088 } else {
10089 p = round_robin[x]?round_robin[x]->next:iflist;
10090 if (!p)
10091 p = iflist;
10092 }
10093 roundrobin = 1;
10094 }
10095 } else {
10096 char *stringp;
10097
10098 stringp = dest;
10099 s = strsep(&stringp, "/");
10100 p = iflist;
10101 if (!strcasecmp(s, "pseudo")) {
10102
10103 x = CHAN_PSEUDO;
10104 channelmatch = x;
10105 }
10106 #ifdef HAVE_PRI
10107 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
10108 if ((trunkgroup < 1) || (crv < 1)) {
10109 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
10110 return NULL;
10111 }
10112 res--;
10113 for (x = 0; x < NUM_SPANS; x++) {
10114 if (pris[x].trunkgroup == trunkgroup) {
10115 pri = pris + x;
10116 lock = &pri->lock;
10117 start = pri->crvs;
10118 end = pri->crvend;
10119 break;
10120 }
10121 }
10122 if (!pri) {
10123 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
10124 return NULL;
10125 }
10126 channelmatch = crv;
10127 p = pris[x].crvs;
10128 }
10129 #endif
10130 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10131 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
10132 return NULL;
10133 } else {
10134 channelmatch = x;
10135 }
10136 }
10137
10138 ast_mutex_lock(lock);
10139 exit = p;
10140 while (p && !tmp) {
10141 if (roundrobin)
10142 round_robin[x] = p;
10143 #if 0
10144 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
10145 #endif
10146
10147 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
10148 if (option_debug)
10149 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
10150 if (p->inalarm)
10151 goto next;
10152
10153 callwait = (p->owner != NULL);
10154 #ifdef HAVE_PRI
10155 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
10156 if (p->sig != SIG_FXSKS) {
10157
10158
10159 bearer = pri_find_empty_chan(pri, 0, -1);
10160 if (bearer < 0) {
10161 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
10162 p = NULL;
10163 break;
10164 }
10165 pri_assign_bearer(p, pri, pri->pvts[bearer]);
10166 } else {
10167 if (alloc_sub(p, 0)) {
10168 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
10169 p = NULL;
10170 break;
10171 } else
10172 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
10173 p->pri = pri;
10174 }
10175 }
10176 #endif
10177
10178 #ifdef HAVE_OPENR2
10179 if (p->mfcr2) {
10180 ast_mutex_lock(&p->lock);
10181 if (p->mfcr2call) {
10182 ast_mutex_unlock(&p->lock);
10183 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
10184 goto next;
10185 }
10186 if (p->mfcr2block) {
10187 ast_mutex_unlock(&p->lock);
10188 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
10189 goto next;
10190 }
10191 p->mfcr2call = 1;
10192 ast_mutex_unlock(&p->lock);
10193 }
10194 #endif
10195
10196 if (p->channel == CHAN_PSEUDO) {
10197 p = chandup(p);
10198 if (!p) {
10199 break;
10200 }
10201 }
10202 if (p->owner) {
10203 if (alloc_sub(p, SUB_CALLWAIT)) {
10204 p = NULL;
10205 break;
10206 }
10207 }
10208 #if defined(HAVE_PRI)
10209 switch (p->sig) {
10210 case SIG_GR303FXOKS:
10211 case SIG_GR303FXSKS:
10212 case SIG_PRI_LIB_HANDLE_CASES:
10213
10214
10215
10216
10217
10218 ast_mutex_lock(&p->lock);
10219 ast_mutex_unlock(&p->lock);
10220 break;
10221 default:
10222 break;
10223 }
10224 #endif
10225 p->outgoing = 1;
10226 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
10227 if (!tmp) {
10228 p->outgoing = 0;
10229 #if defined(HAVE_PRI)
10230
10231
10232
10233
10234 p->allocated = 0;
10235 #endif
10236 }
10237 #ifdef HAVE_PRI
10238 if (p->bearer) {
10239
10240 p->bearer->owner = tmp;
10241 }
10242 #endif
10243
10244 if (res > 1) {
10245 if (opt == 'c') {
10246
10247 p->confirmanswer = 1;
10248 } else if (opt == 'r') {
10249
10250 if (res < 3)
10251 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
10252 else
10253 p->distinctivering = y;
10254 } else if (opt == 'd') {
10255
10256 p->digital = 1;
10257 if (tmp)
10258 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
10259 } else {
10260 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
10261 }
10262 }
10263
10264 if (tmp && callwait)
10265 tmp->cdrflags |= AST_CDR_CALLWAIT;
10266 break;
10267 }
10268 next:
10269 if (backwards) {
10270 p = p->prev;
10271 if (!p)
10272 p = end;
10273 } else {
10274 p = p->next;
10275 if (!p)
10276 p = start;
10277 }
10278
10279 if (p == exit)
10280 break;
10281 }
10282 ast_mutex_unlock(lock);
10283 restart_monitor();
10284 if (callwait)
10285 *cause = AST_CAUSE_BUSY;
10286 else if (!tmp) {
10287 if (channelmatched) {
10288 if (busy)
10289 *cause = AST_CAUSE_BUSY;
10290 } else if (groupmatched) {
10291 *cause = AST_CAUSE_CONGESTION;
10292 }
10293 }
10294
10295 return tmp;
10296 }
10297
10298 #ifdef HAVE_OPENR2
10299 static void *mfcr2_monitor(void *data)
10300 {
10301 struct dahdi_pvt *p;
10302 struct dahdi_mfcr2 *mfcr2 = data;
10303
10304
10305
10306
10307
10308 struct pollfd pollers[mfcr2->numchans];
10309 int maxsleep = 20;
10310 int res = 0;
10311 int i = 0;
10312 int pollsize = 0;
10313 int oldstate = 0;
10314 int was_idle = 0;
10315 int quit_loop = 0;
10316
10317
10318 for (i = 0; i < mfcr2->numchans; i++) {
10319 p = mfcr2->pvts[i];
10320 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
10321 if (openr2_chan_set_idle(p->r2chan)) {
10322 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
10323 } else {
10324 ast_mutex_lock(&p->lock);
10325 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
10326 mfcr2->pvts[i]->mfcr2call = 0;
10327 ast_mutex_unlock(&p->lock);
10328 }
10329 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
10330 }
10331 while(1) {
10332
10333
10334 pollsize = 0;
10335 for (i = 0; i < mfcr2->numchans; i++) {
10336 pollers[i].events = 0;
10337 pollers[i].revents = 0;
10338 if (mfcr2->pvts[i]->owner) {
10339 continue;
10340 }
10341 if (!mfcr2->pvts[i]->r2chan) {
10342 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
10343 quit_loop = 1;
10344 break;
10345 }
10346 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
10347 pollers[i].events = POLLIN | POLLPRI;
10348 pollsize++;
10349 }
10350 if (quit_loop) {
10351 break;
10352 }
10353
10354 if (pollsize == 0) {
10355 if (!was_idle) {
10356 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
10357 was_idle = 1;
10358 }
10359 poll(NULL, 0, maxsleep);
10360 continue;
10361 }
10362 was_idle = 0;
10363
10364
10365
10366 pthread_testcancel();
10367 res = poll(pollers, mfcr2->numchans, maxsleep);
10368 pthread_testcancel();
10369 if ((res < 0) && (errno != EINTR)) {
10370 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
10371 break;
10372 }
10373
10374 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
10375 for (i = 0; i < mfcr2->numchans; i++) {
10376 if ((pollers[i].revents & POLLPRI) || (pollers[i].revents & POLLIN)) {
10377 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
10378 }
10379 }
10380 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
10381 }
10382 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
10383 return 0;
10384 }
10385 #endif
10386
10387 #if defined(HAVE_PRI)
10388 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10389 {
10390 struct dahdi_pvt *p;
10391 p = pri->crvs;
10392 while (p) {
10393 if (p->channel == crv)
10394 return p;
10395 p = p->next;
10396 }
10397 return NULL;
10398 }
10399 #endif
10400
10401 #if defined(HAVE_PRI)
10402
10403
10404
10405
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415 static void sig_pri_lock_owner(struct dahdi_pri *pri, int chanpos)
10416 {
10417 for (;;) {
10418 if (!pri->pvts[chanpos]->owner) {
10419
10420 break;
10421 }
10422 if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
10423
10424 break;
10425 }
10426
10427 ast_mutex_unlock(&pri->lock);
10428 DEADLOCK_AVOIDANCE(&pri->pvts[chanpos]->lock);
10429 ast_mutex_lock(&pri->lock);
10430 }
10431 }
10432 #endif
10433
10434 #if defined(HAVE_PRI)
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449 static void pri_queue_frame(struct dahdi_pri *pri, int chanpos, struct ast_frame *frame)
10450 {
10451 sig_pri_lock_owner(pri, chanpos);
10452 if (pri->pvts[chanpos]->owner) {
10453 ast_queue_frame(pri->pvts[chanpos]->owner, frame);
10454 ast_channel_unlock(pri->pvts[chanpos]->owner);
10455 }
10456 }
10457 #endif
10458
10459 #if defined(HAVE_PRI)
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
10473
10474 static void pri_queue_control(struct dahdi_pri *pri, int chanpos, int subclass)
10475 {
10476 struct ast_frame f = {AST_FRAME_CONTROL, };
10477
10478 f.subclass = subclass;
10479 pri_queue_frame(pri, chanpos, &f);
10480 }
10481 #endif
10482
10483 #if defined(HAVE_PRI)
10484
10485
10486
10487
10488
10489
10490
10491
10492
10493
10494
10495
10496
10497 static int pri_find_principle_by_call(struct dahdi_pri *pri, q931_call *call)
10498 {
10499 int idx;
10500
10501 if (!call) {
10502
10503 return -1;
10504 }
10505 for (idx = 0; idx < pri->numchans; ++idx) {
10506 if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
10507
10508 return idx;
10509 }
10510 }
10511 return -1;
10512 }
10513 #endif
10514
10515 #if defined(HAVE_PRI)
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528
10529 static void sig_pri_kill_call(struct dahdi_pri *pri, q931_call *call, int cause)
10530 {
10531 int chanpos;
10532
10533 chanpos = pri_find_principle_by_call(pri, call);
10534 if (chanpos < 0) {
10535 pri_hangup(pri->pri, call, cause);
10536 return;
10537 }
10538 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10539 if (!pri->pvts[chanpos]->owner) {
10540 pri_hangup(pri->pri, call, cause);
10541 pri->pvts[chanpos]->call = NULL;
10542 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10543 return;
10544 }
10545 pri->pvts[chanpos]->owner->hangupcause = cause;
10546 pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
10547 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10548 }
10549 #endif
10550
10551 #if defined(HAVE_PRI)
10552
10553
10554
10555
10556
10557
10558
10559
10560
10561
10562
10563
10564 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10565 {
10566 int x;
10567 int span = PRI_SPAN(channel);
10568 int spanfd;
10569 struct dahdi_params param;
10570 int principle = -1;
10571 int explicit = PRI_EXPLICIT(channel);
10572 channel = PRI_CHANNEL(channel);
10573
10574 if (!explicit) {
10575 spanfd = pri_active_dchan_fd(pri);
10576 memset(¶m, 0, sizeof(param));
10577 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
10578 return -1;
10579 span = pris[param.spanno - 1].prilogicalspan;
10580 }
10581
10582 for (x = 0; x < pri->numchans; x++) {
10583 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10584 principle = x;
10585 break;
10586 }
10587 }
10588
10589 return principle;
10590 }
10591 #endif
10592
10593 #if defined(HAVE_PRI)
10594
10595
10596
10597
10598
10599
10600
10601
10602
10603
10604
10605
10606
10607 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10608 {
10609 int x;
10610 struct dahdi_pvt *crv;
10611 if (!c) {
10612 if (principle < 0)
10613 return -1;
10614 return principle;
10615 }
10616 if ((principle > -1) &&
10617 (principle < pri->numchans) &&
10618 (pri->pvts[principle]) &&
10619 (pri->pvts[principle]->call == c))
10620 return principle;
10621
10622 for (x = 0; x < pri->numchans; x++) {
10623 if (!pri->pvts[x])
10624 continue;
10625 if (pri->pvts[x]->call == c) {
10626
10627 if (principle != x) {
10628 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10629
10630
10631 ast_mutex_lock(&old->lock);
10632 sig_pri_lock_owner(pri, x);
10633 ast_mutex_lock(&new->lock);
10634
10635 if (option_verbose > 2) {
10636 ast_verbose(VERBOSE_PREFIX_3
10637 "Moving call (%s) from channel %d to %d.\n",
10638 old->owner ? old->owner->name : "",
10639 old->channel, new->channel);
10640 }
10641 if (!sig_pri_is_chan_available(new)) {
10642 ast_log(LOG_WARNING,
10643 "Can't move call (%s) from channel %d to %d. It is already in use.\n",
10644 old->owner ? old->owner->name : "",
10645 old->channel, new->channel);
10646 ast_mutex_unlock(&new->lock);
10647 if (old->owner) {
10648 ast_mutex_unlock(&old->owner->lock);
10649 }
10650 ast_mutex_unlock(&old->lock);
10651 return -1;
10652 }
10653
10654
10655 new->owner = old->owner;
10656 old->owner = NULL;
10657 if (new->owner) {
10658 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
10659 new->owner->tech_pvt = new;
10660 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
10661 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10662 old->subs[SUB_REAL].owner = NULL;
10663 } else
10664 ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
10665 new->call = old->call;
10666 old->call = NULL;
10667
10668
10669 new->dsp = old->dsp;
10670 new->dsp_features = old->dsp_features;
10671 old->dsp = NULL;
10672 old->dsp_features = 0;
10673
10674
10675 new->alreadyhungup = old->alreadyhungup;
10676 new->isidlecall = old->isidlecall;
10677 new->progress = old->progress;
10678 new->allocated = old->allocated;
10679 new->outgoing = old->outgoing;
10680 new->digital = old->digital;
10681 old->alreadyhungup = 0;
10682 old->isidlecall = 0;
10683 old->progress = 0;
10684 old->allocated = 0;
10685 old->outgoing = 0;
10686 old->digital = 0;
10687
10688
10689 new->call_level = old->call_level;
10690 old->call_level = DAHDI_CALL_LEVEL_IDLE;
10691
10692 ast_mutex_unlock(&old->lock);
10693 if (new->owner) {
10694 ast_mutex_unlock(&new->owner->lock);
10695 }
10696 ast_mutex_unlock(&new->lock);
10697 }
10698 return principle;
10699 }
10700 }
10701
10702 crv = pri->crvs;
10703 while (crv) {
10704 if (crv->call == c) {
10705
10706 if (crv->bearer)
10707 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10708 else if (pri->pvts[principle]->owner)
10709 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10710 else {
10711
10712
10713 dahdi_close_sub(crv, SUB_REAL);
10714 pri->pvts[principle]->call = crv->call;
10715 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10716 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
10717 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10718 pri->trunkgroup, crv->channel);
10719 wakeup_sub(crv, SUB_REAL, pri);
10720 }
10721 return principle;
10722 }
10723 crv = crv->next;
10724 }
10725 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10726 return -1;
10727 }
10728 #endif
10729
10730 #if defined(HAVE_PRI)
10731
10732
10733
10734
10735
10736
10737
10738
10739
10740
10741
10742
10743
10744
10745
10746
10747
10748
10749 static int pri_find_fixup_principle(struct dahdi_pri *pri, int channel, q931_call *call)
10750 {
10751 int chanpos;
10752
10753 chanpos = pri_find_principle(pri, channel);
10754 if (chanpos < 0) {
10755 ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
10756 pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
10757 sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
10758 return -1;
10759 }
10760 chanpos = pri_fixup_principle(pri, chanpos, call);
10761 if (chanpos < 0) {
10762 ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
10763 pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
10764
10765
10766
10767
10768
10769
10770
10771 sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
10772 return -1;
10773 }
10774 return chanpos;
10775 }
10776 #endif
10777
10778 #if defined(HAVE_PRI)
10779 static void *do_idle_thread(void *vchan)
10780 {
10781 struct ast_channel *chan = vchan;
10782 struct dahdi_pvt *pvt = chan->tech_pvt;
10783 struct ast_frame *f;
10784 char ex[80];
10785
10786 int newms, ms = 30000;
10787 if (option_verbose > 2)
10788 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
10789 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10790 if (ast_call(chan, ex, 0)) {
10791 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10792 ast_hangup(chan);
10793 return NULL;
10794 }
10795 while ((newms = ast_waitfor(chan, ms)) > 0) {
10796 f = ast_read(chan);
10797 if (!f) {
10798
10799 break;
10800 }
10801 if (f->frametype == AST_FRAME_CONTROL) {
10802 switch (f->subclass) {
10803 case AST_CONTROL_ANSWER:
10804
10805 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10806 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10807 chan->priority = 1;
10808 if (option_verbose > 3)
10809 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10810 ast_pbx_run(chan);
10811
10812 return NULL;
10813 case AST_CONTROL_BUSY:
10814 if (option_verbose > 3)
10815 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
10816 break;
10817 case AST_CONTROL_CONGESTION:
10818 if (option_verbose > 3)
10819 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
10820 break;
10821 };
10822 }
10823 ast_frfree(f);
10824 ms = newms;
10825 }
10826
10827 ast_hangup(chan);
10828 return NULL;
10829 }
10830
10831 #ifndef PRI_RESTART
10832 #error "Upgrade your libpri"
10833 #endif
10834 static void dahdi_pri_message(struct pri *pri, char *s)
10835 {
10836 int x, y;
10837 int dchan = -1, span = -1;
10838 int dchancount = 0;
10839
10840 if (pri) {
10841 for (x = 0; x < NUM_SPANS; x++) {
10842 for (y = 0; y < NUM_DCHANS; y++) {
10843 if (pris[x].dchans[y])
10844 dchancount++;
10845
10846 if (pris[x].dchans[y] == pri)
10847 dchan = y;
10848 }
10849 if (dchan >= 0) {
10850 span = x;
10851 break;
10852 }
10853 dchancount = 0;
10854 }
10855 if ((dchan >= 0) && (span >= 0)) {
10856 if (dchancount > 1)
10857 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10858 else
10859 ast_verbose("%s", s);
10860 } else
10861 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
10862 } else
10863 ast_verbose("%s", s);
10864
10865 ast_mutex_lock(&pridebugfdlock);
10866
10867 if (pridebugfd >= 0) {
10868 if (write(pridebugfd, s, strlen(s)) < 0) {
10869 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10870 }
10871 }
10872
10873 ast_mutex_unlock(&pridebugfdlock);
10874 }
10875
10876 static void dahdi_pri_error(struct pri *pri, char *s)
10877 {
10878 int x, y;
10879 int dchan = -1, span = -1;
10880 int dchancount = 0;
10881
10882 if (pri) {
10883 for (x = 0; x < NUM_SPANS; x++) {
10884 for (y = 0; y < NUM_DCHANS; y++) {
10885 if (pris[x].dchans[y])
10886 dchancount++;
10887
10888 if (pris[x].dchans[y] == pri)
10889 dchan = y;
10890 }
10891 if (dchan >= 0) {
10892 span = x;
10893 break;
10894 }
10895 dchancount = 0;
10896 }
10897 if ((dchan >= 0) && (span >= 0)) {
10898 if (dchancount > 1)
10899 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10900 else
10901 ast_log(LOG_ERROR, "%s", s);
10902 } else
10903 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
10904 } else
10905 ast_log(LOG_ERROR, "%s", s);
10906
10907 ast_mutex_lock(&pridebugfdlock);
10908
10909 if (pridebugfd >= 0) {
10910 if (write(pridebugfd, s, strlen(s)) < 0) {
10911 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10912 }
10913 }
10914
10915 ast_mutex_unlock(&pridebugfdlock);
10916 }
10917
10918
10919
10920
10921
10922
10923
10924
10925
10926
10927
10928 static void pri_check_restart(struct dahdi_pri *pri)
10929 {
10930 for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) {
10931 if (!pri->pvts[pri->resetpos]
10932 || sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) {
10933 continue;
10934 }
10935 break;
10936 }
10937 if (pri->resetpos < pri->numchans) {
10938
10939 pri->pvts[pri->resetpos]->resetting = 1;
10940 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10941 } else {
10942 pri->resetting = 0;
10943 time(&pri->lastreset);
10944 }
10945 }
10946
10947 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10948 {
10949 int x;
10950 int redo;
10951 ast_mutex_unlock(&pri->lock);
10952 ast_mutex_lock(&p->lock);
10953 do {
10954 redo = 0;
10955 for (x = 0; x < 3; x++) {
10956 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
10957 redo++;
10958 DEADLOCK_AVOIDANCE(&p->lock);
10959 }
10960 if (p->subs[x].owner) {
10961 ast_queue_hangup(p->subs[x].owner);
10962 ast_mutex_unlock(&p->subs[x].owner->lock);
10963 }
10964 }
10965 } while (redo);
10966 ast_mutex_unlock(&p->lock);
10967 ast_mutex_lock(&pri->lock);
10968 return 0;
10969 }
10970
10971 static char * redirectingreason2str(int redirectingreason)
10972 {
10973 switch (redirectingreason) {
10974 case 0:
10975 return "UNKNOWN";
10976 case 1:
10977 return "BUSY";
10978 case 2:
10979 return "NO_REPLY";
10980 case 0xF:
10981 return "UNCONDITIONAL";
10982 default:
10983 return "NOREDIRECT";
10984 }
10985 }
10986
10987 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10988 {
10989 if (ast_strlen_zero(number)) {
10990 if (size) {
10991 *buf = '\0';
10992 }
10993 return;
10994 }
10995
10996 switch (plan) {
10997 case PRI_INTERNATIONAL_ISDN:
10998 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10999 break;
11000 case PRI_NATIONAL_ISDN:
11001 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
11002 break;
11003 case PRI_LOCAL_ISDN:
11004 snprintf(buf, size, "%s%s", pri->localprefix, number);
11005 break;
11006 case PRI_PRIVATE:
11007 snprintf(buf, size, "%s%s", pri->privateprefix, number);
11008 break;
11009 case PRI_UNKNOWN:
11010 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
11011 break;
11012 default:
11013 snprintf(buf, size, "%s", number);
11014 break;
11015 }
11016 }
11017
11018 static int dahdi_setlaw(int dfd, int law)
11019 {
11020 int res;
11021 res = ioctl(dfd, DAHDI_SETLAW, &law);
11022 if (res)
11023 return res;
11024 return 0;
11025 }
11026
11027 static void *pri_dchannel(void *vpri)
11028 {
11029 struct dahdi_pri *pri = vpri;
11030 pri_event *e;
11031 struct pollfd fds[NUM_DCHANS];
11032 int res;
11033 int chanpos = 0, origchanpos = 0;
11034 int x;
11035 int haveidles;
11036 int activeidles;
11037 int nextidle = -1;
11038 struct ast_channel *c;
11039 struct timeval tv, lowest, *next;
11040 struct timeval lastidle = { 0, 0 };
11041 int doidling=0;
11042 char *cc;
11043 char idlen[80];
11044 struct ast_channel *idle;
11045 pthread_t p;
11046 time_t t;
11047 int i, which=-1;
11048 int numdchans;
11049 int cause=0;
11050 struct dahdi_pvt *crv;
11051 pthread_t threadid;
11052 pthread_attr_t attr;
11053 char ani2str[6];
11054 char plancallingnum[256];
11055 char plancallingani[256];
11056 char calledtonstr[10];
11057 unsigned int len;
11058
11059 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11060
11061 gettimeofday(&lastidle, NULL);
11062 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
11063
11064 cc = strchr(pri->idleext, '@');
11065 if (cc) {
11066 *cc = '\0';
11067 cc++;
11068 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
11069 #if 0
11070
11071 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
11072 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
11073 else
11074 #endif
11075 doidling = 1;
11076 } else
11077 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
11078 }
11079 for (;;) {
11080 for (i = 0; i < NUM_DCHANS; i++) {
11081 if (!pri->dchannels[i])
11082 break;
11083 fds[i].fd = pri->fds[i];
11084 fds[i].events = POLLIN | POLLPRI;
11085 fds[i].revents = 0;
11086 }
11087 numdchans = i;
11088 time(&t);
11089 ast_mutex_lock(&pri->lock);
11090 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
11091 if (pri->resetting && pri_is_up(pri)) {
11092 if (pri->resetpos < 0) {
11093 pri_check_restart(pri);
11094 }
11095 } else {
11096 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
11097 pri->resetting = 1;
11098 pri->resetpos = -1;
11099 }
11100 }
11101 }
11102
11103 if (doidling && pri_is_up(pri)) {
11104 nextidle = -1;
11105 haveidles = 0;
11106 activeidles = 0;
11107 for (x = pri->numchans; x >= 0; x--) {
11108 if (pri->pvts[x]) {
11109 if (sig_pri_is_chan_available(pri->pvts[x])) {
11110 if (haveidles < pri->minunused) {
11111 haveidles++;
11112 } else {
11113 nextidle = x;
11114 break;
11115 }
11116 } else if (pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
11117 activeidles++;
11118 }
11119 }
11120 }
11121 if (nextidle > -1) {
11122 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
11123
11124 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
11125
11126
11127
11128
11129 ast_mutex_unlock(&pri->lock);
11130 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
11131 ast_mutex_lock(&pri->lock);
11132 if (idle) {
11133 pri->pvts[nextidle]->isidlecall = 1;
11134 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
11135 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
11136 ast_mutex_unlock(&pri->lock);
11137 ast_hangup(idle);
11138 ast_mutex_lock(&pri->lock);
11139 }
11140 } else {
11141 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
11142 }
11143 gettimeofday(&lastidle, NULL);
11144 }
11145 } else if ((haveidles < pri->minunused) &&
11146 (activeidles > pri->minidle)) {
11147
11148
11149 for (x = pri->numchans; x >= 0; x--) {
11150
11151 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
11152 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11153 haveidles++;
11154
11155
11156 if ((haveidles >= pri->minunused) ||
11157 (activeidles <= pri->minidle))
11158 break;
11159 }
11160 }
11161 }
11162 }
11163
11164 lowest = ast_tv(60, 0);
11165 for (i = 0; i < NUM_DCHANS; i++) {
11166
11167 if (!pri->dchannels[i])
11168 break;
11169 if ((next = pri_schedule_next(pri->dchans[i]))) {
11170
11171 tv = ast_tvsub(*next, ast_tvnow());
11172 if (tv.tv_sec < 0) {
11173 tv = ast_tv(0,0);
11174 }
11175 if (doidling || pri->resetting) {
11176 if (tv.tv_sec > 1) {
11177 tv = ast_tv(1, 0);
11178 }
11179 } else {
11180 if (tv.tv_sec > 60) {
11181 tv = ast_tv(60, 0);
11182 }
11183 }
11184 } else if (doidling || pri->resetting) {
11185
11186
11187 tv = ast_tv(1,0);
11188 } else {
11189
11190 tv = ast_tv(60, 0);
11191 }
11192 if (!i || ast_tvcmp(tv, lowest) < 0) {
11193 lowest = tv;
11194 }
11195 }
11196 ast_mutex_unlock(&pri->lock);
11197
11198 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11199 pthread_testcancel();
11200 e = NULL;
11201 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11202 pthread_testcancel();
11203 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11204
11205 ast_mutex_lock(&pri->lock);
11206 if (!res) {
11207 for (which = 0; which < NUM_DCHANS; which++) {
11208 if (!pri->dchans[which])
11209 break;
11210
11211 e = pri_schedule_run(pri->dchans[which]);
11212 if (e)
11213 break;
11214 }
11215 } else if (res > -1) {
11216 for (which = 0; which < NUM_DCHANS; which++) {
11217 if (!pri->dchans[which])
11218 break;
11219 if (fds[which].revents & POLLPRI) {
11220
11221 x = 0;
11222 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11223 if (x)
11224 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
11225
11226 if (x == DAHDI_EVENT_ALARM) {
11227 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11228 pri_find_dchan(pri);
11229 } else if (x == DAHDI_EVENT_NOALARM) {
11230 pri->dchanavail[which] |= DCHAN_NOTINALARM;
11231 pri_restart(pri->dchans[which]);
11232 }
11233
11234 if (option_debug)
11235 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11236 } else if (fds[which].revents & POLLIN) {
11237 e = pri_check_event(pri->dchans[which]);
11238 }
11239 if (e)
11240 break;
11241 }
11242 } else if (errno != EINTR)
11243 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11244
11245 if (e) {
11246 if (pri->debug)
11247 pri_dump_event(pri->dchans[which], e);
11248
11249 if (e->e != PRI_EVENT_DCHAN_DOWN) {
11250 if (!(pri->dchanavail[which] & DCHAN_UP)) {
11251 if (option_verbose > 1)
11252 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11253 }
11254 pri->dchanavail[which] |= DCHAN_UP;
11255 } else {
11256 if (pri->dchanavail[which] & DCHAN_UP) {
11257 if (option_verbose > 1)
11258 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11259 }
11260 pri->dchanavail[which] &= ~DCHAN_UP;
11261 }
11262
11263 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11264
11265 pri->pri = pri->dchans[which];
11266
11267 switch (e->e) {
11268 case PRI_EVENT_DCHAN_UP:
11269 pri->no_d_channels = 0;
11270 if (!pri->pri) pri_find_dchan(pri);
11271
11272
11273 time(&pri->lastreset);
11274
11275
11276 if (pri->resetinterval > -1) {
11277 pri->lastreset -= pri->resetinterval;
11278 pri->lastreset += 5;
11279 }
11280
11281 pri->resetting = 0;
11282 for (i = 0; i < pri->numchans; i++) {
11283 if (pri->pvts[i]) {
11284 pri->pvts[i]->inalarm = 0;
11285 pri->pvts[i]->resetting = 0;
11286 }
11287 }
11288 break;
11289 case PRI_EVENT_DCHAN_DOWN:
11290 pri_find_dchan(pri);
11291 if (!pri_is_up(pri)) {
11292
11293 pri->resetting = 0;
11294 for (i = 0; i < pri->numchans; i++) {
11295 struct dahdi_pvt *p = pri->pvts[i];
11296 if (p) {
11297 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11298
11299 if (p->call) {
11300 if (p->pri && p->pri->pri) {
11301 pri_destroycall(p->pri->pri, p->call);
11302 p->call = NULL;
11303 } else
11304 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
11305 }
11306 if (p->realcall) {
11307 pri_hangup_all(p->realcall, pri);
11308 } else if (p->owner)
11309 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11310 }
11311 p->inalarm = 1;
11312 p->resetting = 0;
11313 }
11314 }
11315 }
11316 break;
11317 case PRI_EVENT_RESTART:
11318 if (e->restart.channel > -1 && PRI_CHANNEL(e->ring.channel) != 0xFF) {
11319 chanpos = pri_find_principle(pri, e->restart.channel);
11320 if (chanpos < 0)
11321 ast_log(LOG_WARNING,
11322 "Span %d: Restart requested on odd/unavailable channel number %d/%d\n",
11323 pri->span, PRI_SPAN(e->restart.channel),
11324 PRI_CHANNEL(e->restart.channel));
11325 else {
11326 if (option_verbose > 2)
11327 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d restarted\n",
11328 pri->span, PRI_SPAN(e->restart.channel),
11329 PRI_CHANNEL(e->restart.channel));
11330 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11331 if (pri->pvts[chanpos]->call) {
11332 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11333 pri->pvts[chanpos]->call = NULL;
11334 }
11335
11336 if (pri->pvts[chanpos]->realcall)
11337 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11338 else if (pri->pvts[chanpos]->owner)
11339 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11340 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11341 }
11342 } else {
11343 if (option_verbose > 2)
11344 ast_verbose(VERBOSE_PREFIX_2 "Restart requested on entire span %d\n",
11345 pri->span);
11346 for (x = 0; x < pri->numchans; x++)
11347 if (pri->pvts[x]) {
11348 ast_mutex_lock(&pri->pvts[x]->lock);
11349 if (pri->pvts[x]->call) {
11350 pri_destroycall(pri->pri, pri->pvts[x]->call);
11351 pri->pvts[x]->call = NULL;
11352 }
11353 if (pri->pvts[x]->realcall)
11354 pri_hangup_all(pri->pvts[x]->realcall, pri);
11355 else if (pri->pvts[x]->owner)
11356 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11357 ast_mutex_unlock(&pri->pvts[x]->lock);
11358 }
11359 }
11360 break;
11361 case PRI_EVENT_KEYPAD_DIGIT:
11362 chanpos = pri_find_principle_by_call(pri, e->digit.call);
11363 if (chanpos < 0) {
11364 ast_log(LOG_WARNING,
11365 "Span %d: Received keypad digits for unknown call.\n", pri->span);
11366 break;
11367 }
11368 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11369
11370 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11371 && pri->pvts[chanpos]->owner) {
11372
11373 int digitlen = strlen(e->digit.digits);
11374 char digit;
11375 int i;
11376 for (i = 0; i < digitlen; i++) {
11377 digit = e->digit.digits[i];
11378 {
11379 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11380 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11381 }
11382 }
11383 }
11384 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11385 break;
11386
11387 case PRI_EVENT_INFO_RECEIVED:
11388 chanpos = pri_find_principle_by_call(pri, e->ring.call);
11389 if (chanpos < 0) {
11390 ast_log(LOG_WARNING,
11391 "Span %d: Received INFORMATION for unknown call.\n", pri->span);
11392 break;
11393 }
11394 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11395
11396 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11397 && pri->pvts[chanpos]->owner) {
11398
11399 int digitlen = strlen(e->ring.callednum);
11400 char digit;
11401 int i;
11402 for (i = 0; i < digitlen; i++) {
11403 digit = e->ring.callednum[i];
11404 {
11405 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11406 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11407 }
11408 }
11409 }
11410 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11411 break;
11412 case PRI_EVENT_RING:
11413 crv = NULL;
11414 chanpos = pri_find_principle_by_call(pri, e->ring.call);
11415 if (-1 < chanpos) {
11416
11417 ast_log(LOG_WARNING,
11418 "Span %d: Got SETUP with duplicate call ptr. Dropping call.\n",
11419 pri->span);
11420 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
11421 break;
11422 }
11423 if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
11424
11425 chanpos = pri_find_empty_chan(pri, 1, -1);
11426 } else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
11427
11428 {
11429
11430 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INCOMPATIBLE_DESTINATION);
11431 break;
11432 }
11433 } else {
11434
11435 chanpos = pri_find_principle(pri, e->ring.channel);
11436 ast_log(LOG_DEBUG, "chanpos %d channel %d\n", chanpos, PRI_CHANNEL(e->ring.channel));
11437 origchanpos = chanpos;
11438 if (chanpos < 0) {
11439 ast_log(LOG_NOTICE,
11440 "Span %d: SETUP on unconfigured channel %d/%d\n",
11441 pri->span, PRI_SPAN(e->ring.channel),
11442 PRI_CHANNEL(e->ring.channel));
11443 } else if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
11444
11445 ast_log(LOG_NOTICE,
11446 "Span %d: SETUP requested unavailable channel %d/%d. Attempting to renegotiate.\n",
11447 pri->span, PRI_SPAN(e->ring.channel),
11448 PRI_CHANNEL(e->ring.channel));
11449 chanpos = -1;
11450 }
11451 #if defined(ALWAYS_PICK_CHANNEL)
11452 if (e->ring.flexible) {
11453 chanpos = -1;
11454 }
11455 #endif
11456 if (chanpos < 0 && e->ring.flexible) {
11457
11458 chanpos = pri_find_empty_chan(pri, 1, origchanpos);
11459 }
11460 }
11461 if (chanpos < 0) {
11462 if (e->ring.flexible) {
11463 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11464 } else {
11465 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11466 }
11467 break;
11468 }
11469
11470 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11471 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11472
11473 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11474 if (crv)
11475 ast_mutex_lock(&crv->lock);
11476 if (!crv || crv->owner) {
11477 pri->pvts[chanpos]->call = NULL;
11478 if (crv) {
11479 if (crv->owner)
11480 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11481 ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
11482 } else
11483 ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
11484 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11485 if (crv)
11486 ast_mutex_unlock(&crv->lock);
11487 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11488 break;
11489 }
11490 }
11491
11492
11493 pri->pvts[chanpos]->call = e->ring.call;
11494
11495 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11496 if (pri->pvts[chanpos]->use_callerid) {
11497 ast_shrink_phone_number(plancallingnum);
11498 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11499 #ifdef PRI_ANI
11500 if (!ast_strlen_zero(e->ring.callingani)) {
11501 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11502 ast_shrink_phone_number(plancallingani);
11503 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11504 } else {
11505 pri->pvts[chanpos]->cid_ani[0] = '\0';
11506 }
11507 #endif
11508 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11509 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
11510 } else {
11511 pri->pvts[chanpos]->cid_num[0] = '\0';
11512 pri->pvts[chanpos]->cid_ani[0] = '\0';
11513 pri->pvts[chanpos]->cid_name[0] = '\0';
11514 pri->pvts[chanpos]->cid_ton = 0;
11515 }
11516 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11517 e->ring.redirectingnum, e->ring.callingplanrdnis);
11518
11519
11520 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11521
11522
11523 if (pri->pvts[chanpos]->immediate) {
11524 if (option_verbose > 2)
11525 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
11526 pri->pvts[chanpos]->exten[0] = 's';
11527 pri->pvts[chanpos]->exten[1] = '\0';
11528 }
11529
11530 else if (!ast_strlen_zero(e->ring.callednum)) {
11531 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11532 } else if (pri->overlapdial)
11533 pri->pvts[chanpos]->exten[0] = '\0';
11534 else {
11535
11536 pri->pvts[chanpos]->exten[0] = 's';
11537 pri->pvts[chanpos]->exten[1] = '\0';
11538 }
11539
11540 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11541 if (option_verbose > 2)
11542 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
11543 pri->pvts[chanpos]->exten[0] = 's';
11544 pri->pvts[chanpos]->exten[1] = '\0';
11545 }
11546
11547
11548 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11549 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11550
11551 int law;
11552 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11553
11554 law = 1;
11555 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11556 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11557 }
11558 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11559 law = DAHDI_LAW_ALAW;
11560 else
11561 law = DAHDI_LAW_MULAW;
11562 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11563 if (res < 0)
11564 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11565 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11566 if (res < 0)
11567 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11568 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11569
11570 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11571 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11572 } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11573 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
11574 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11575 } else {
11576 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
11577 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11578 }
11579
11580 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11581
11582
11583 if (!e->ring.complete
11584 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11585 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11586
11587
11588
11589
11590
11591
11592 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11593 ast_mutex_unlock(&pri->lock);
11594 if (crv) {
11595
11596 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11597 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11598 pri->pvts[chanpos]->owner = &inuse;
11599 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11600 } else {
11601 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11602 }
11603 ast_mutex_lock(&pri->lock);
11604 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11605 if (c) {
11606 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11607 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11608 }
11609 if (e->ring.ani2 >= 0) {
11610 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11611 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11612 }
11613
11614 #ifdef SUPPORT_USERUSER
11615 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11616 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11617 }
11618 #endif
11619
11620 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11621 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11622 if (e->ring.redirectingreason >= 0)
11623 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11624
11625 if (!pri->pvts[chanpos]->digital) {
11626
11627
11628
11629
11630 pri->pvts[chanpos]->progress = 1;
11631 pri_progress(pri->pri, e->ring.call,
11632 PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11633 }
11634 }
11635
11636 pthread_attr_init(&attr);
11637 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11638 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
11639 if (option_verbose > 2)
11640 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11641 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11642 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11643 } else {
11644 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11645 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11646 if (c) {
11647
11648 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11649 ast_mutex_unlock(&pri->lock);
11650 ast_hangup(c);
11651 ast_mutex_lock(&pri->lock);
11652 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11653 } else {
11654 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11655 pri->pvts[chanpos]->call = NULL;
11656 }
11657 }
11658 pthread_attr_destroy(&attr);
11659 } else {
11660
11661
11662
11663
11664
11665
11666 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11667 ast_mutex_unlock(&pri->lock);
11668 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
11669 ast_mutex_lock(&pri->lock);
11670 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11671 if (c) {
11672
11673
11674
11675
11676
11677
11678
11679
11680 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11681 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11682 }
11683 if (e->ring.ani2 >= 0) {
11684 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11685 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11686 }
11687
11688 #ifdef SUPPORT_USERUSER
11689 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11690 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11691 }
11692 #endif
11693
11694 if (e->ring.redirectingreason >= 0)
11695 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11696
11697 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11698 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11699 }
11700 if (c && !ast_pbx_start(c)) {
11701 if (option_verbose > 2)
11702 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11703 plancallingnum, pri->pvts[chanpos]->exten,
11704 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11705
11706 dahdi_enable_ec(pri->pvts[chanpos]);
11707 } else {
11708 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11709 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11710 if (c) {
11711
11712 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11713 ast_mutex_unlock(&pri->lock);
11714 ast_hangup(c);
11715 ast_mutex_lock(&pri->lock);
11716 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11717 } else {
11718 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11719 pri->pvts[chanpos]->call = NULL;
11720 }
11721 }
11722 }
11723 } else {
11724 if (option_verbose > 2)
11725 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Extension %s@%s does not exist. Rejecting call from '%s'.\n",
11726 pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context,
11727 pri->pvts[chanpos]->cid_num);
11728 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11729 pri->pvts[chanpos]->call = NULL;
11730 pri->pvts[chanpos]->exten[0] = '\0';
11731 }
11732 if (crv)
11733 ast_mutex_unlock(&crv->lock);
11734 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11735 break;
11736 case PRI_EVENT_RINGING:
11737 chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
11738 e->ringing.call);
11739 if (chanpos < 0) {
11740 break;
11741 }
11742 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11743 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11744 dahdi_enable_ec(pri->pvts[chanpos]);
11745 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11746 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
11747 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
11748 }
11749 } else
11750 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
11751 if (
11752 #ifdef PRI_PROGRESS_MASK
11753 e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
11754 #else
11755 e->ringing.progress == 8
11756 #endif
11757 ) {
11758
11759 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11760
11761 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11762 pri->pvts[chanpos]->dsp_features = 0;
11763 }
11764 }
11765
11766 #ifdef SUPPORT_USERUSER
11767 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11768 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11769 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11770 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11771 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11772 }
11773 #endif
11774
11775 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11776 break;
11777 case PRI_EVENT_PROGRESS:
11778 chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
11779 e->proceeding.call);
11780 if (chanpos < 0) {
11781 break;
11782 }
11783 if ((!pri->pvts[chanpos]->progress)
11784 #ifdef PRI_PROGRESS_MASK
11785 || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
11786 #else
11787 || (e->proceeding.progress == 8)
11788 #endif
11789 ) {
11790 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11791
11792 if (e->proceeding.cause > -1) {
11793 if (option_verbose > 2)
11794 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
11795
11796
11797 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11798 if (pri->pvts[chanpos]->owner) {
11799 if (option_verbose > 2)
11800 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11801
11802 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11803 f.subclass = AST_CONTROL_BUSY;
11804 }
11805 }
11806 }
11807
11808 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11809 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11810 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11811 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11812 if (
11813 #ifdef PRI_PROGRESS_MASK
11814 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
11815 #else
11816 e->proceeding.progress == 8
11817 #endif
11818 ) {
11819
11820 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11821 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11822 pri->pvts[chanpos]->dsp_features = 0;
11823 }
11824
11825 f.subclass = AST_CONTROL_PROGRESS;
11826 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11827 }
11828 pri->pvts[chanpos]->progress = 1;
11829 pri->pvts[chanpos]->dialing = 0;
11830 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11831 }
11832 break;
11833 case PRI_EVENT_PROCEEDING:
11834 chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
11835 e->proceeding.call);
11836 if (chanpos < 0) {
11837 break;
11838 }
11839 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11840 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
11841 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11842
11843 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11844 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11845 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11846 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11847 if (
11848 #ifdef PRI_PROGRESS_MASK
11849 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
11850 #else
11851 e->proceeding.progress == 8
11852 #endif
11853 ) {
11854
11855 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11856 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11857 pri->pvts[chanpos]->dsp_features = 0;
11858 }
11859
11860 f.subclass = AST_CONTROL_PROGRESS;
11861 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11862 }
11863 pri->pvts[chanpos]->dialing = 0;
11864 }
11865 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11866 break;
11867 case PRI_EVENT_FACNAME:
11868 chanpos = pri_find_principle_by_call(pri, e->facname.call);
11869 if (chanpos < 0) {
11870 ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
11871 pri->span);
11872 break;
11873 }
11874 if (pri->pvts[chanpos]->use_callerid) {
11875
11876 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11877 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11878 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11879 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
11880 dahdi_enable_ec(pri->pvts[chanpos]);
11881 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11882 }
11883 break;
11884 case PRI_EVENT_ANSWER:
11885 chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
11886 if (chanpos < 0) {
11887 break;
11888 }
11889 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11890
11891
11892
11893
11894
11895 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11896 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11897 pri->pvts[chanpos]->dsp_features = 0;
11898 }
11899 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11900 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
11901 x = DAHDI_START;
11902 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11903 if (res < 0) {
11904 if (errno != EINPROGRESS) {
11905 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11906 }
11907 }
11908 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11909 pri->pvts[chanpos]->dialing = 1;
11910
11911 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11912 if (res < 0) {
11913 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11914 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11915 } else
11916 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11917 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11918 } else if (pri->pvts[chanpos]->confirmanswer) {
11919 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11920 } else {
11921 pri->pvts[chanpos]->dialing = 0;
11922 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
11923 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
11924 }
11925 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11926
11927 dahdi_enable_ec(pri->pvts[chanpos]);
11928 }
11929
11930 #ifdef SUPPORT_USERUSER
11931 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11932 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11933 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11934 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11935 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11936 }
11937 #endif
11938
11939 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11940 break;
11941 case PRI_EVENT_HANGUP:
11942 chanpos = pri_find_principle_by_call(pri, e->hangup.call);
11943 if (chanpos < 0) {
11944
11945
11946
11947
11948 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
11949 break;
11950 }
11951 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11952 switch (e->hangup.cause) {
11953 case PRI_CAUSE_INVALID_CALL_REFERENCE:
11954
11955
11956
11957
11958 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
11959 pri->pvts[chanpos]->call = NULL;
11960 break;
11961 default:
11962 break;
11963 }
11964 if (!pri->pvts[chanpos]->alreadyhungup) {
11965
11966 pri->pvts[chanpos]->alreadyhungup = 1;
11967 if (pri->pvts[chanpos]->realcall)
11968 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11969 else if (pri->pvts[chanpos]->owner) {
11970
11971 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11972 switch (pri->pvts[chanpos]->owner->_state) {
11973 case AST_STATE_BUSY:
11974 case AST_STATE_UP:
11975 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11976 break;
11977 default:
11978 if (!pri->pvts[chanpos]->outgoing) {
11979
11980
11981
11982
11983 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11984 break;
11985 }
11986 switch (e->hangup.cause) {
11987 case PRI_CAUSE_USER_BUSY:
11988 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11989 break;
11990 case PRI_CAUSE_CALL_REJECTED:
11991 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11992 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11993 case PRI_CAUSE_SWITCH_CONGESTION:
11994 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11995 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11996 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11997 break;
11998 default:
11999 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12000 break;
12001 }
12002 break;
12003 }
12004 } else {
12005
12006
12007
12008
12009 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
12010 pri->pvts[chanpos]->call = NULL;
12011 }
12012 if (option_verbose > 2)
12013 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup, cause %d\n",
12014 pri->span, pri->pvts[chanpos]->logicalspan,
12015 pri->pvts[chanpos]->prioffset, e->hangup.cause);
12016 } else {
12017
12018 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
12019 pri->pvts[chanpos]->call = NULL;
12020 }
12021 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
12022 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
12023 && !pri->resetting && !pri->pvts[chanpos]->resetting) {
12024 if (option_verbose > 2)
12025 ast_verbose(VERBOSE_PREFIX_3
12026 "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
12027 pri->span, pri->pvts[chanpos]->logicalspan,
12028 pri->pvts[chanpos]->prioffset);
12029 pri->pvts[chanpos]->resetting = 1;
12030 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
12031 }
12032 #endif
12033 if (e->hangup.aoc_units > -1)
12034 if (option_verbose > 2)
12035 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
12036 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
12037
12038 #ifdef SUPPORT_USERUSER
12039 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
12040 struct ast_channel *owner = pri->pvts[chanpos]->owner;
12041 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12042 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
12043 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12044 }
12045 #endif
12046
12047 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12048 break;
12049 #ifndef PRI_EVENT_HANGUP_REQ
12050 #error please update libpri
12051 #endif
12052 case PRI_EVENT_HANGUP_REQ:
12053 chanpos = pri_find_principle_by_call(pri, e->hangup.call);
12054 if (chanpos < 0) {
12055
12056
12057
12058
12059 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
12060 break;
12061 }
12062 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12063 switch (e->hangup.cause) {
12064 case PRI_CAUSE_INVALID_CALL_REFERENCE:
12065
12066
12067
12068
12069
12070
12071 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
12072 pri->pvts[chanpos]->call = NULL;
12073 break;
12074 default:
12075 break;
12076 }
12077 if (pri->pvts[chanpos]->realcall)
12078 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12079 else if (pri->pvts[chanpos]->owner) {
12080 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
12081 switch (pri->pvts[chanpos]->owner->_state) {
12082 case AST_STATE_BUSY:
12083 case AST_STATE_UP:
12084 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12085 break;
12086 default:
12087 if (!pri->pvts[chanpos]->outgoing) {
12088
12089
12090
12091
12092 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12093 break;
12094 }
12095 switch (e->hangup.cause) {
12096 case PRI_CAUSE_USER_BUSY:
12097 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
12098 break;
12099 case PRI_CAUSE_CALL_REJECTED:
12100 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
12101 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
12102 case PRI_CAUSE_SWITCH_CONGESTION:
12103 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
12104 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
12105 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
12106 break;
12107 default:
12108 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12109 break;
12110 }
12111 break;
12112 }
12113 if (option_verbose > 2)
12114 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup request, cause %d\n",
12115 pri->span, pri->pvts[chanpos]->logicalspan,
12116 pri->pvts[chanpos]->prioffset, e->hangup.cause);
12117 if (e->hangup.aoc_units > -1)
12118 if (option_verbose > 2)
12119 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
12120 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
12121 } else {
12122
12123
12124
12125
12126 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
12127 pri->pvts[chanpos]->call = NULL;
12128 }
12129 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
12130 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
12131 && !pri->resetting && !pri->pvts[chanpos]->resetting) {
12132 if (option_verbose > 2)
12133 ast_verbose(VERBOSE_PREFIX_3
12134 "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
12135 pri->span, pri->pvts[chanpos]->logicalspan,
12136 pri->pvts[chanpos]->prioffset);
12137 pri->pvts[chanpos]->resetting = 1;
12138 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
12139 }
12140 #endif
12141
12142 #ifdef SUPPORT_USERUSER
12143 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
12144 struct ast_channel *owner = pri->pvts[chanpos]->owner;
12145 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12146 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
12147 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12148 }
12149 #endif
12150
12151 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12152 break;
12153 case PRI_EVENT_HANGUP_ACK:
12154 chanpos = pri_find_principle_by_call(pri, e->hangup.call);
12155 if (chanpos < 0) {
12156 break;
12157 }
12158 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12159 pri->pvts[chanpos]->call = NULL;
12160 if (pri->pvts[chanpos]->owner) {
12161 if (option_verbose > 2)
12162 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup ACK\n",
12163 pri->span, pri->pvts[chanpos]->logicalspan,
12164 pri->pvts[chanpos]->prioffset);
12165 }
12166 #ifdef SUPPORT_USERUSER
12167 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
12168 struct ast_channel *owner = pri->pvts[chanpos]->owner;
12169 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12170 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
12171 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12172 }
12173 #endif
12174
12175 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12176 break;
12177 case PRI_EVENT_CONFIG_ERR:
12178 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
12179 break;
12180 case PRI_EVENT_RESTART_ACK:
12181 chanpos = pri_find_principle(pri, e->restartack.channel);
12182 if (chanpos < 0) {
12183
12184
12185
12186 for (x = 0; x < pri->numchans; x++) {
12187 if (pri->pvts[x] && pri->pvts[x]->resetting) {
12188 chanpos = x;
12189 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12190 ast_log(LOG_DEBUG,
12191 "Span %d: Assuming restart ack is for channel %d/%d\n",
12192 pri->span, pri->pvts[chanpos]->logicalspan,
12193 pri->pvts[chanpos]->prioffset);
12194 if (pri->pvts[chanpos]->realcall)
12195 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12196 else if (pri->pvts[chanpos]->owner) {
12197 ast_log(LOG_WARNING,
12198 "Span %d: Got restart ack on channel %d/%d with owner\n",
12199 pri->span, pri->pvts[chanpos]->logicalspan,
12200 pri->pvts[chanpos]->prioffset);
12201 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12202 }
12203 pri->pvts[chanpos]->resetting = 0;
12204 if (option_verbose > 2)
12205 ast_verbose(VERBOSE_PREFIX_3
12206 "Span %d: Channel %d/%d successfully restarted\n",
12207 pri->span, pri->pvts[chanpos]->logicalspan,
12208 pri->pvts[chanpos]->prioffset);
12209 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12210 if (pri->resetting)
12211 pri_check_restart(pri);
12212 break;
12213 }
12214 }
12215 if (chanpos < 0) {
12216 ast_log(LOG_WARNING,
12217 "Span %d: Restart ACK on strange channel %d/%d\n",
12218 pri->span, PRI_SPAN(e->restartack.channel),
12219 PRI_CHANNEL(e->restartack.channel));
12220 }
12221 } else {
12222 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12223 if (pri->pvts[chanpos]->realcall)
12224 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12225 else if (pri->pvts[chanpos]->owner) {
12226 ast_log(LOG_WARNING,
12227 "Span %d: Got restart ack on channel %d/%d with owner\n",
12228 pri->span, pri->pvts[chanpos]->logicalspan,
12229 pri->pvts[chanpos]->prioffset);
12230 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12231 }
12232 pri->pvts[chanpos]->resetting = 0;
12233 if (option_verbose > 2)
12234 ast_verbose(VERBOSE_PREFIX_3
12235 "Span %d: Channel %d/%d successfully restarted\n",
12236 pri->span, pri->pvts[chanpos]->logicalspan,
12237 pri->pvts[chanpos]->prioffset);
12238 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12239 if (pri->resetting)
12240 pri_check_restart(pri);
12241 }
12242 break;
12243 case PRI_EVENT_SETUP_ACK:
12244 chanpos = pri_find_fixup_principle(pri, e->setup_ack.channel,
12245 e->setup_ack.call);
12246 if (chanpos < 0) {
12247 break;
12248 }
12249 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12250 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
12251 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
12252 }
12253
12254
12255 len = strlen(pri->pvts[chanpos]->dialdest);
12256 for (x = 0; x < len; ++x) {
12257 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
12258 pri_information(pri->pri, pri->pvts[chanpos]->call,
12259 pri->pvts[chanpos]->dialdest[x]);
12260 }
12261
12262 if (!pri->pvts[chanpos]->progress
12263 && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
12264 && !pri->pvts[chanpos]->digital) {
12265
12266
12267
12268
12269 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
12270 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12271 pri->pvts[chanpos]->progress = 1;
12272 pri->pvts[chanpos]->dialing = 0;
12273 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
12274 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
12275 pri->pvts[chanpos]->dsp_features = 0;
12276 }
12277 }
12278 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12279 break;
12280 case PRI_EVENT_NOTIFY:
12281 #if defined(HAVE_PRI_CALL_HOLD)
12282 chanpos = pri_find_principle_by_call(pri, e->notify.call);
12283 if (chanpos < 0) {
12284 ast_log(LOG_WARNING, "Span %d: Received NOTIFY for unknown call.\n",
12285 pri->span);
12286 break;
12287 }
12288 #else
12289
12290
12291
12292
12293
12294 chanpos = pri_find_principle(pri, e->notify.channel);
12295 if (chanpos < 0) {
12296 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
12297 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
12298 break;
12299 }
12300 #endif
12301 {
12302 struct ast_frame f = { AST_FRAME_CONTROL, };
12303 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12304 switch (e->notify.info) {
12305 case PRI_NOTIFY_REMOTE_HOLD:
12306 f.subclass = AST_CONTROL_HOLD;
12307 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12308 break;
12309 case PRI_NOTIFY_REMOTE_RETRIEVAL:
12310 f.subclass = AST_CONTROL_UNHOLD;
12311 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12312 break;
12313 }
12314 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12315 }
12316 break;
12317 default:
12318 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
12319 }
12320 }
12321 ast_mutex_unlock(&pri->lock);
12322 }
12323
12324 return NULL;
12325 }
12326
12327 static int start_pri(struct dahdi_pri *pri)
12328 {
12329 int res, x;
12330 struct dahdi_params p;
12331 struct dahdi_bufferinfo bi;
12332 struct dahdi_spaninfo si;
12333 int i;
12334
12335 for (i = 0; i < NUM_DCHANS; i++) {
12336 if (!pri->dchannels[i])
12337 break;
12338 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
12339 x = pri->dchannels[i];
12340 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
12341 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12342 return -1;
12343 }
12344 memset(&p, 0, sizeof(p));
12345 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12346 if (res) {
12347 dahdi_close_pri_fd(pri, i);
12348 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12349 return -1;
12350 }
12351 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12352 dahdi_close_pri_fd(pri, i);
12353 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
12354 return -1;
12355 }
12356 memset(&si, 0, sizeof(si));
12357 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12358 if (res) {
12359 dahdi_close_pri_fd(pri, i);
12360 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12361 }
12362 if (!si.alarms)
12363 pri->dchanavail[i] |= DCHAN_NOTINALARM;
12364 else
12365 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12366 memset(&bi, 0, sizeof(bi));
12367 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12368 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12369 bi.numbufs = 32;
12370 bi.bufsize = 1024;
12371 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12372 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12373 dahdi_close_pri_fd(pri, i);
12374 return -1;
12375 }
12376 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12377
12378 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12379 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12380 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12381 #ifdef HAVE_PRI_INBANDDISCONNECT
12382 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12383 #endif
12384
12385 if (i)
12386 pri_enslave(pri->dchans[0], pri->dchans[i]);
12387 if (!pri->dchans[i]) {
12388 dahdi_close_pri_fd(pri, i);
12389 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12390 return -1;
12391 }
12392 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12393 pri_set_nsf(pri->dchans[i], pri->nsf);
12394 #ifdef PRI_GETSET_TIMERS
12395 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12396 if (pritimers[x] != 0)
12397 pri_set_timer(pri->dchans[i], x, pritimers[x]);
12398 }
12399 #endif
12400 }
12401
12402 pri->pri = pri->dchans[0];
12403 pri->resetpos = -1;
12404 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12405 for (i = 0; i < NUM_DCHANS; i++) {
12406 if (!pri->dchannels[i])
12407 break;
12408 dahdi_close_pri_fd(pri, i);
12409 }
12410 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12411 return -1;
12412 }
12413 return 0;
12414 }
12415
12416 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
12417 {
12418 int which, span;
12419 char *ret = NULL;
12420
12421 if (pos != rpos)
12422 return ret;
12423
12424 for (which = span = 0; span < NUM_SPANS; span++) {
12425 if (pris[span].pri && ++which > state) {
12426 if (asprintf(&ret, "%d", span + 1) < 0) {
12427 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12428 }
12429 break;
12430 }
12431 }
12432 return ret;
12433 }
12434
12435 static char *complete_span_4(const char *line, const char *word, int pos, int state)
12436 {
12437 return complete_span_helper(line,word,pos,state,3);
12438 }
12439
12440 static char *complete_span_5(const char *line, const char *word, int pos, int state)
12441 {
12442 return complete_span_helper(line,word,pos,state,4);
12443 }
12444
12445 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
12446 {
12447 int myfd;
12448
12449 if (!strncasecmp(argv[1], "set", 3)) {
12450 if (argc < 5)
12451 return RESULT_SHOWUSAGE;
12452
12453 if (ast_strlen_zero(argv[4]))
12454 return RESULT_SHOWUSAGE;
12455
12456 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
12457 if (myfd < 0) {
12458 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
12459 return RESULT_SUCCESS;
12460 }
12461
12462 ast_mutex_lock(&pridebugfdlock);
12463
12464 if (pridebugfd >= 0)
12465 close(pridebugfd);
12466
12467 pridebugfd = myfd;
12468 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
12469
12470 ast_mutex_unlock(&pridebugfdlock);
12471
12472 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
12473 } else {
12474
12475 ast_mutex_lock(&pridebugfdlock);
12476 close(pridebugfd);
12477 pridebugfd = -1;
12478 ast_cli(fd, "PRI debug output to file disabled\n");
12479 ast_mutex_unlock(&pridebugfdlock);
12480 }
12481
12482 return RESULT_SUCCESS;
12483 }
12484
12485 #ifdef HAVE_PRI_VERSION
12486 static int handle_pri_version(int fd, int agc, char *argv[]) {
12487 ast_cli(fd, "libpri version: %s\n", pri_get_version());
12488 return RESULT_SUCCESS;
12489 }
12490 #endif
12491
12492 static int handle_pri_debug(int fd, int argc, char *argv[])
12493 {
12494 int span;
12495 int x;
12496 if (argc < 4) {
12497 return RESULT_SHOWUSAGE;
12498 }
12499 span = atoi(argv[3]);
12500 if ((span < 1) || (span > NUM_SPANS)) {
12501 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
12502 return RESULT_SUCCESS;
12503 }
12504 if (!pris[span-1].pri) {
12505 ast_cli(fd, "No PRI running on span %d\n", span);
12506 return RESULT_SUCCESS;
12507 }
12508 for (x = 0; x < NUM_DCHANS; x++) {
12509 if (pris[span-1].dchans[x])
12510 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12511 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12512 PRI_DEBUG_Q921_STATE);
12513 }
12514 ast_cli(fd, "Enabled debugging on span %d\n", span);
12515 return RESULT_SUCCESS;
12516 }
12517
12518
12519
12520 static int handle_pri_no_debug(int fd, int argc, char *argv[])
12521 {
12522 int span;
12523 int x;
12524 if (argc < 5)
12525 return RESULT_SHOWUSAGE;
12526 span = atoi(argv[4]);
12527 if ((span < 1) || (span > NUM_SPANS)) {
12528 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
12529 return RESULT_SUCCESS;
12530 }
12531 if (!pris[span-1].pri) {
12532 ast_cli(fd, "No PRI running on span %d\n", span);
12533 return RESULT_SUCCESS;
12534 }
12535 for (x = 0; x < NUM_DCHANS; x++) {
12536 if (pris[span-1].dchans[x])
12537 pri_set_debug(pris[span-1].dchans[x], 0);
12538 }
12539 ast_cli(fd, "Disabled debugging on span %d\n", span);
12540 return RESULT_SUCCESS;
12541 }
12542
12543 static int handle_pri_really_debug(int fd, int argc, char *argv[])
12544 {
12545 int span;
12546 int x;
12547 if (argc < 5)
12548 return RESULT_SHOWUSAGE;
12549 span = atoi(argv[4]);
12550 if ((span < 1) || (span > NUM_SPANS)) {
12551 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
12552 return RESULT_SUCCESS;
12553 }
12554 if (!pris[span-1].pri) {
12555 ast_cli(fd, "No PRI running on span %d\n", span);
12556 return RESULT_SUCCESS;
12557 }
12558 for (x = 0; x < NUM_DCHANS; x++) {
12559 if (pris[span-1].dchans[x])
12560 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12561 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12562 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12563 }
12564 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12565 return RESULT_SUCCESS;
12566 }
12567
12568 static void build_status(char *s, size_t len, int status, int active)
12569 {
12570 if (!s || len < 1) {
12571 return;
12572 }
12573 s[0] = '\0';
12574 if (status & DCHAN_PROVISIONED)
12575 strncat(s, "Provisioned, ", len - strlen(s) - 1);
12576 if (!(status & DCHAN_NOTINALARM))
12577 strncat(s, "In Alarm, ", len - strlen(s) - 1);
12578 if (status & DCHAN_UP)
12579 strncat(s, "Up", len - strlen(s) - 1);
12580 else
12581 strncat(s, "Down", len - strlen(s) - 1);
12582 if (active)
12583 strncat(s, ", Active", len - strlen(s) - 1);
12584 else
12585 strncat(s, ", Standby", len - strlen(s) - 1);
12586 s[len - 1] = '\0';
12587 }
12588
12589 static int handle_pri_show_spans(int fd, int argc, char *argv[])
12590 {
12591 int span;
12592 int x;
12593 char status[256];
12594 if (argc != 3)
12595 return RESULT_SHOWUSAGE;
12596
12597 for (span = 0; span < NUM_SPANS; span++) {
12598 if (pris[span].pri) {
12599 for (x = 0; x < NUM_DCHANS; x++) {
12600 if (pris[span].dchannels[x]) {
12601 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12602 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12603 }
12604 }
12605 }
12606 }
12607 return RESULT_SUCCESS;
12608 }
12609
12610 static int handle_pri_show_span(int fd, int argc, char *argv[])
12611 {
12612 int span;
12613 int x;
12614 char status[256];
12615 if (argc < 4)
12616 return RESULT_SHOWUSAGE;
12617 span = atoi(argv[3]);
12618 if ((span < 1) || (span > NUM_SPANS)) {
12619 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
12620 return RESULT_SUCCESS;
12621 }
12622 if (!pris[span-1].pri) {
12623 ast_cli(fd, "No PRI running on span %d\n", span);
12624 return RESULT_SUCCESS;
12625 }
12626 for (x = 0; x < NUM_DCHANS; x++) {
12627 if (pris[span-1].dchannels[x]) {
12628 #ifdef PRI_DUMP_INFO_STR
12629 char *info_str = NULL;
12630 #endif
12631 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12632 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12633 ast_cli(fd, "Status: %s\n", status);
12634 ast_mutex_lock(&pris[span - 1].lock);
12635 #ifdef PRI_DUMP_INFO_STR
12636 info_str = pri_dump_info_str(pris[span-1].pri);
12637 if (info_str) {
12638 ast_cli(fd, "%s", info_str);
12639 free(info_str);
12640 }
12641 #else
12642 pri_dump_info(pris[span-1].pri);
12643 #endif
12644 ast_mutex_unlock(&pris[span - 1].lock);
12645 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12646 }
12647 }
12648 return RESULT_SUCCESS;
12649 }
12650
12651 static int handle_pri_show_debug(int fd, int argc, char *argv[])
12652 {
12653 int x;
12654 int span;
12655 int count=0;
12656 int debug=0;
12657
12658 for (span = 0; span < NUM_SPANS; span++) {
12659 if (pris[span].pri) {
12660 for (x = 0; x < NUM_DCHANS; x++) {
12661 debug = 0;
12662 if (pris[span].dchans[x]) {
12663 debug = pri_get_debug(pris[span].dchans[x]);
12664 ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
12665 count++;
12666 }
12667 }
12668 }
12669
12670 }
12671 ast_mutex_lock(&pridebugfdlock);
12672 if (pridebugfd >= 0)
12673 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
12674 ast_mutex_unlock(&pridebugfdlock);
12675
12676 if (!count)
12677 ast_cli(fd, "No debug set or no PRI running\n");
12678 return RESULT_SUCCESS;
12679 }
12680
12681 static const char pri_debug_help[] =
12682 "Usage: pri debug span <span>\n"
12683 " Enables debugging on a given PRI span\n";
12684
12685 static const char pri_no_debug_help[] =
12686 "Usage: pri no debug span <span>\n"
12687 " Disables debugging on a given PRI span\n";
12688
12689 static const char pri_really_debug_help[] =
12690 "Usage: pri intensive debug span <span>\n"
12691 " Enables debugging down to the Q.921 level\n";
12692
12693 static const char pri_show_span_help[] =
12694 "Usage: pri show span <span>\n"
12695 " Displays PRI Information on a given PRI span\n";
12696
12697 static const char pri_show_spans_help[] =
12698 "Usage: pri show spans\n"
12699 " Displays PRI Information\n";
12700
12701 static struct ast_cli_entry dahdi_pri_cli[] = {
12702 { { "pri", "debug", "span", NULL },
12703 handle_pri_debug, "Enables PRI debugging on a span",
12704 pri_debug_help, complete_span_4 },
12705
12706 { { "pri", "no", "debug", "span", NULL },
12707 handle_pri_no_debug, "Disables PRI debugging on a span",
12708 pri_no_debug_help, complete_span_5 },
12709
12710 { { "pri", "intense", "debug", "span", NULL },
12711 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
12712 pri_really_debug_help, complete_span_5 },
12713
12714 { { "pri", "show", "spans", NULL },
12715 handle_pri_show_spans, "Displays PRI Information",
12716 pri_show_spans_help },
12717
12718 { { "pri", "show", "span", NULL },
12719 handle_pri_show_span, "Displays PRI Information",
12720 pri_show_span_help, complete_span_4 },
12721
12722 { { "pri", "show", "debug", NULL },
12723 handle_pri_show_debug, "Displays current PRI debug settings" },
12724
12725 { { "pri", "set", "debug", "file", NULL },
12726 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
12727
12728 { { "pri", "unset", "debug", "file", NULL },
12729 handle_pri_set_debug_file, "Ends PRI debug output to file" },
12730
12731 #ifdef HAVE_PRI_VERSION
12732 { { "pri", "show", "version", NULL },
12733 handle_pri_version, "Displays version of libpri" },
12734 #endif
12735 };
12736
12737 #endif
12738
12739 #ifdef HAVE_OPENR2
12740
12741 static int handle_mfcr2_version(int fd, int argc, char *argv[])
12742 {
12743 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
12744 return RESULT_SUCCESS;
12745 }
12746
12747 static int handle_mfcr2_show_variants(int fd, int argc, char *argv[])
12748 {
12749 #define FORMAT "%4s %40s\n"
12750 int numvariants = 0;
12751 int i;
12752 const openr2_variant_entry_t *variants;
12753 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
12754 ast_cli(fd, "Failed to get list of variants.\n");
12755 return RESULT_FAILURE;
12756 }
12757 ast_cli(fd, FORMAT, "Variant Code", "Country");
12758 for (i = 0; i < numvariants; i++) {
12759 ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
12760 }
12761 return RESULT_SUCCESS;
12762 #undef FORMAT
12763 }
12764
12765 static int handle_mfcr2_show_channels(int fd, int argc, char *argv[])
12766 {
12767 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
12768 int filtertype = 0;
12769 int targetnum = 0;
12770 char channo[5];
12771 char anino[5];
12772 char dnisno[5];
12773 struct dahdi_pvt *p;
12774 openr2_context_t *r2context;
12775 openr2_variant_t r2variant;
12776 if (!((argc == 3) || (argc == 5))) {
12777 return RESULT_SHOWUSAGE;
12778 }
12779 if (argc == 5) {
12780 if (!strcasecmp(argv[3], "group")) {
12781 targetnum = atoi(argv[4]);
12782 if ((targetnum < 0) || (targetnum > 63))
12783 return RESULT_SHOWUSAGE;
12784 targetnum = 1 << targetnum;
12785 filtertype = 1;
12786 } else if (!strcasecmp(argv[3], "context")) {
12787 filtertype = 2;
12788 } else {
12789 return RESULT_SHOWUSAGE;
12790 }
12791 }
12792 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
12793 ast_mutex_lock(&iflock);
12794 p = iflist;
12795 while (p) {
12796 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12797 p = p->next;
12798 continue;
12799 }
12800 if (filtertype) {
12801 switch(filtertype) {
12802 case 1:
12803 if (p->group != targetnum) {
12804 p = p->next;
12805 continue;
12806 }
12807 break;
12808 case 2:
12809 if (strcasecmp(p->context, argv[4])) {
12810 p= p->next;
12811 continue;
12812 }
12813 break;
12814 default:
12815 ;
12816 }
12817 }
12818 r2context = openr2_chan_get_context(p->r2chan);
12819 r2variant = openr2_context_get_variant(r2context);
12820 snprintf(channo, sizeof(channo), "%d", p->channel);
12821 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
12822 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
12823 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
12824 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
12825 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
12826 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
12827 p = p->next;
12828 }
12829 ast_mutex_unlock(&iflock);
12830 return RESULT_SUCCESS;
12831 #undef FORMAT
12832 }
12833
12834 static int handle_mfcr2_set_debug(int fd, int argc, char *argv[])
12835 {
12836 struct dahdi_pvt *p = NULL;
12837 int channo = 0;
12838 char *toklevel = NULL;
12839 char *saveptr = NULL;
12840 char *logval = NULL;
12841 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
12842 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
12843 if (argc < 4) {
12844 return RESULT_SHOWUSAGE;
12845 }
12846 channo = (argc == 5) ? atoi(argv[4]) : -1;
12847 logval = ast_strdupa(argv[3]);
12848 toklevel = strtok_r(logval, ",", &saveptr);
12849 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
12850 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
12851 return RESULT_FAILURE;
12852 } else if (OR2_LOG_NOTHING == tmplevel) {
12853 loglevel = tmplevel;
12854 } else {
12855 loglevel |= tmplevel;
12856 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
12857 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
12858 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
12859 continue;
12860 }
12861 loglevel |= tmplevel;
12862 }
12863 }
12864 ast_mutex_lock(&iflock);
12865 p = iflist;
12866 while (p) {
12867 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12868 p = p->next;
12869 continue;
12870 }
12871 if ((channo != -1) && (p->channel != channo )) {
12872 p = p->next;
12873 continue;
12874 }
12875 openr2_chan_set_log_level(p->r2chan, loglevel);
12876 if (channo != -1) {
12877 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
12878 break;
12879 } else {
12880 p = p->next;
12881 }
12882 }
12883 if ((channo != -1) && !p) {
12884 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12885 }
12886 if (channo == -1) {
12887 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
12888 }
12889 ast_mutex_unlock(&iflock);
12890 return RESULT_SUCCESS;
12891 }
12892
12893 static int handle_mfcr2_call_files(int fd, int argc, char *argv[])
12894 {
12895 struct dahdi_pvt *p = NULL;
12896 int channo = 0;
12897 if (argc < 4) {
12898 return RESULT_SHOWUSAGE;
12899 }
12900 channo = (argc == 5) ? atoi(argv[4]) : -1;
12901 ast_mutex_lock(&iflock);
12902 p = iflist;
12903 while (p) {
12904 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12905 p = p->next;
12906 continue;
12907 }
12908 if ((channo != -1) && (p->channel != channo )) {
12909 p = p->next;
12910 continue;
12911 }
12912 if (ast_true(argv[3])) {
12913 openr2_chan_enable_call_files(p->r2chan);
12914 } else {
12915 openr2_chan_disable_call_files(p->r2chan);
12916 }
12917 if (channo != -1) {
12918 if (ast_true(argv[3])) {
12919 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
12920 } else {
12921 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
12922 }
12923 break;
12924 } else {
12925 p = p->next;
12926 }
12927 }
12928 if ((channo != -1) && !p) {
12929 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12930 }
12931 if (channo == -1) {
12932 if (ast_true(argv[3])) {
12933 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
12934 } else {
12935 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
12936 }
12937 }
12938 ast_mutex_unlock(&iflock);
12939 return RESULT_SUCCESS;
12940 }
12941
12942 static int handle_mfcr2_set_idle(int fd, int argc, char *argv[])
12943 {
12944 struct dahdi_pvt *p = NULL;
12945 int channo = 0;
12946 channo = (argc == 4) ? atoi(argv[3]) : -1;
12947 ast_mutex_lock(&iflock);
12948 p = iflist;
12949 while (p) {
12950 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12951 p = p->next;
12952 continue;
12953 }
12954 if ((channo != -1) && (p->channel != channo )) {
12955 p = p->next;
12956 continue;
12957 }
12958 if (!openr2_chan_set_idle(p->r2chan)) {
12959 ast_mutex_lock(&p->lock);
12960 p->mfcr2call = 0;
12961 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
12962 ast_mutex_unlock(&p->lock);
12963 }
12964 if (channo != -1) {
12965 break;
12966 } else {
12967 p = p->next;
12968 }
12969 }
12970 if ((channo != -1) && !p) {
12971 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12972 }
12973 ast_mutex_unlock(&iflock);
12974 return RESULT_SUCCESS;
12975 }
12976
12977 static int handle_mfcr2_set_blocked(int fd, int argc, char *argv[])
12978 {
12979 struct dahdi_pvt *p = NULL;
12980 int channo = 0;
12981 channo = (argc == 4) ? atoi(argv[3]) : -1;
12982 ast_mutex_lock(&iflock);
12983 p = iflist;
12984 while (p) {
12985 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12986 p = p->next;
12987 continue;
12988 }
12989 if ((channo != -1) && (p->channel != channo )) {
12990 p = p->next;
12991 continue;
12992 }
12993 if (!openr2_chan_set_blocked(p->r2chan)) {
12994 ast_mutex_lock(&p->lock);
12995 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
12996 ast_mutex_unlock(&p->lock);
12997 } else {
12998 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
12999 }
13000 if (channo != -1) {
13001 break;
13002 } else {
13003 p = p->next;
13004 }
13005 }
13006 if ((channo != -1) && !p) {
13007 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
13008 }
13009 ast_mutex_unlock(&iflock);
13010 return RESULT_SUCCESS;
13011 }
13012
13013 static const char dahdi_r2_version_help[] =
13014 "Usage: mfcr2 show version\n"
13015 " Shows the version of the OpenR2 library being used.\n";
13016 static const char dahdi_r2_variants_help[] =
13017 "Usage: mfcr2 show variants\n"
13018 " Show supported MFC/R2 variants.\n";
13019 static const char dahdi_r2_showchannels_help[] =
13020 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
13021 " Shows the zap channels configured with MFC/R2 signaling.\n";
13022 static const char dahdi_r2_setdebug_help[] =
13023 "Usage: mfcr2 set debug <loglevel> <channel>\n"
13024 " Set a new logging level for the specified channel.\n"
13025 " If no channel is specified the logging level will be applied to all channels.\n";
13026 static const char dahdi_r2_callfiles_help[] =
13027 "Usage: mfcr2 call files [on|off] <channel>\n"
13028 " Enable call files creation on the specified channel.\n"
13029 " If no channel is specified call files creation policy will be applied to all channels.\n";
13030 static const char dahdi_r2_setidle_help[] =
13031 "Usage: mfcr2 set idle <channel>\n"
13032 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
13033 " Force the given channel into IDLE state.\n"
13034 " If no channel is specified, all channels will be set to IDLE.\n";
13035 static const char dahdi_r2_setblocked_help[] =
13036 "Usage: mfcr2 set blocked <channel>\n"
13037 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
13038 " Force the given channel into BLOCKED state.\n"
13039 " If no channel is specified, all channels will be set to BLOCKED.\n";
13040
13041 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
13042 { { "mfcr2", "show", "version", NULL },
13043 handle_mfcr2_version, "Show OpenR2 library version",
13044 dahdi_r2_version_help },
13045
13046 { { "mfcr2", "show", "variants", NULL },
13047 handle_mfcr2_show_variants, "Show supported MFC/R2 variants",
13048 dahdi_r2_variants_help },
13049
13050 { { "mfcr2", "show", "channels", NULL },
13051 handle_mfcr2_show_channels, "Show MFC/R2 channels",
13052 dahdi_r2_showchannels_help },
13053
13054 { { "mfcr2", "set", "debug", NULL },
13055 handle_mfcr2_set_debug, "Set MFC/R2 channel logging level",
13056 dahdi_r2_setdebug_help },
13057
13058 { { "mfcr2", "call", "files", NULL },
13059 handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files",
13060 dahdi_r2_callfiles_help },
13061
13062 { { "mfcr2", "set", "idle", NULL },
13063 handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE",
13064 dahdi_r2_setidle_help },
13065
13066 { { "mfcr2", "set", "blocked", NULL },
13067 handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED",
13068 dahdi_r2_setblocked_help }
13069
13070 };
13071
13072 #endif
13073
13074 static int dahdi_destroy_channel(int fd, int argc, char **argv)
13075 {
13076 int channel;
13077
13078 if (argc != 4)
13079 return RESULT_SHOWUSAGE;
13080
13081 channel = atoi(argv[3]);
13082
13083 return dahdi_destroy_channel_bynum(channel);
13084 }
13085
13086 static void dahdi_softhangup_all(void)
13087 {
13088 struct dahdi_pvt *p;
13089 retry:
13090 ast_mutex_lock(&iflock);
13091 for (p = iflist; p; p = p->next) {
13092 ast_mutex_lock(&p->lock);
13093 if (p->owner && !p->restartpending) {
13094 if (ast_channel_trylock(p->owner)) {
13095 if (option_debug > 2)
13096 ast_verbose("Avoiding deadlock\n");
13097
13098 ast_mutex_unlock(&p->lock);
13099 ast_mutex_unlock(&iflock);
13100 goto retry;
13101 }
13102 if (option_debug > 2)
13103 ast_verbose("Softhanging up on %s\n", p->owner->name);
13104 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
13105 p->restartpending = 1;
13106 num_restart_pending++;
13107 ast_channel_unlock(p->owner);
13108 }
13109 ast_mutex_unlock(&p->lock);
13110 }
13111 ast_mutex_unlock(&iflock);
13112 }
13113
13114 static int setup_dahdi(int reload);
13115 static int dahdi_restart(void)
13116 {
13117
13118 #ifdef HAVE_OPENR2
13119 int r;
13120 #endif
13121
13122 #if defined(HAVE_PRI)
13123 int i, j;
13124 #endif
13125 int cancel_code;
13126 struct dahdi_pvt *p;
13127
13128 ast_mutex_lock(&restart_lock);
13129
13130 if (option_verbose)
13131 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
13132 dahdi_softhangup_all();
13133 if (option_verbose > 3)
13134 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
13135
13136 #ifdef HAVE_OPENR2
13137 for (r = 0; r < NUM_SPANS; r++) {
13138 if (r2links[r].master != AST_PTHREADT_NULL) {
13139 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
13140 pthread_cancel(r2links[r].master);
13141 pthread_join(r2links[r].master, NULL);
13142 openr2_context_delete(r2links[r].protocol_context);
13143 }
13144 }
13145 init_mfcr2_globals();
13146 #endif
13147
13148 #if defined(HAVE_PRI)
13149 for (i = 0; i < NUM_SPANS; i++) {
13150 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
13151 cancel_code = pthread_cancel(pris[i].master);
13152 pthread_kill(pris[i].master, SIGURG);
13153 if (option_debug > 3)
13154 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
13155 pthread_join(pris[i].master, NULL);
13156 if (option_debug > 3)
13157 ast_verbose("Joined thread of span %d\n", i);
13158 }
13159 }
13160 #endif
13161
13162 ast_mutex_lock(&monlock);
13163 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
13164 cancel_code = pthread_cancel(monitor_thread);
13165 pthread_kill(monitor_thread, SIGURG);
13166 if (option_debug > 3)
13167 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
13168 pthread_join(monitor_thread, NULL);
13169 if (option_debug > 3)
13170 ast_verbose("Joined monitor thread\n");
13171 }
13172 monitor_thread = AST_PTHREADT_NULL;
13173
13174 ast_mutex_lock(&ss_thread_lock);
13175 while (ss_thread_count > 0) {
13176 int x = DAHDI_FLASH;
13177 if (option_debug > 2)
13178 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
13179
13180 for (p = iflist; p; p = p->next) {
13181 if (p->owner)
13182 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13183 }
13184 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
13185 }
13186
13187
13188 dahdi_softhangup_all();
13189 if (option_verbose > 3)
13190 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
13191 destroy_all_channels();
13192 if (option_debug)
13193 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
13194
13195 ast_mutex_unlock(&monlock);
13196
13197 #ifdef HAVE_PRI
13198 for (i = 0; i < NUM_SPANS; i++) {
13199 for (j = 0; j < NUM_DCHANS; j++)
13200 dahdi_close_pri_fd(&(pris[i]), j);
13201 }
13202
13203 memset(pris, 0, sizeof(pris));
13204 for (i = 0; i < NUM_SPANS; i++) {
13205 ast_mutex_init(&pris[i].lock);
13206 pris[i].offset = -1;
13207 pris[i].master = AST_PTHREADT_NULL;
13208 for (j = 0; j < NUM_DCHANS; j++)
13209 pris[i].fds[j] = -1;
13210 }
13211 pri_set_error(dahdi_pri_error);
13212 pri_set_message(dahdi_pri_message);
13213 #endif
13214
13215 if (setup_dahdi(2) != 0) {
13216 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
13217 ast_mutex_unlock(&ss_thread_lock);
13218 return 1;
13219 }
13220 ast_mutex_unlock(&ss_thread_lock);
13221 ast_mutex_unlock(&restart_lock);
13222 return 0;
13223 }
13224
13225 static int dahdi_restart_cmd(int fd, int argc, char **argv)
13226 {
13227 if (argc != 2) {
13228 return RESULT_SHOWUSAGE;
13229 }
13230
13231 if (dahdi_restart() != 0)
13232 return RESULT_FAILURE;
13233 return RESULT_SUCCESS;
13234 }
13235
13236 static int dahdi_show_channels(int fd, int argc, char **argv)
13237 {
13238 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
13239 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
13240 struct dahdi_pvt *tmp = NULL;
13241 char tmps[20] = "";
13242 ast_mutex_t *lock;
13243 struct dahdi_pvt *start;
13244 #ifdef HAVE_PRI
13245 int trunkgroup;
13246 struct dahdi_pri *pri = NULL;
13247 int x;
13248 #endif
13249
13250 lock = &iflock;
13251 start = iflist;
13252
13253 #ifdef HAVE_PRI
13254 if (argc == 4) {
13255 if ((trunkgroup = atoi(argv[3])) < 1)
13256 return RESULT_SHOWUSAGE;
13257 for (x = 0; x < NUM_SPANS; x++) {
13258 if (pris[x].trunkgroup == trunkgroup) {
13259 pri = pris + x;
13260 break;
13261 }
13262 }
13263 if (pri) {
13264 start = pri->crvs;
13265 lock = &pri->lock;
13266 } else {
13267 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13268 return RESULT_FAILURE;
13269 }
13270 } else
13271 #endif
13272 if (argc != 3)
13273 return RESULT_SHOWUSAGE;
13274
13275 ast_mutex_lock(lock);
13276 #ifdef HAVE_PRI
13277 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
13278 #else
13279 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
13280 #endif
13281
13282 tmp = start;
13283 while (tmp) {
13284 if (tmp->channel > 0) {
13285 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
13286 } else
13287 ast_copy_string(tmps, "pseudo", sizeof(tmps));
13288 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
13289 tmp = tmp->next;
13290 }
13291 ast_mutex_unlock(lock);
13292 return RESULT_SUCCESS;
13293 #undef FORMAT
13294 #undef FORMAT2
13295 }
13296
13297 static int dahdi_show_channel(int fd, int argc, char **argv)
13298 {
13299 int channel;
13300 struct dahdi_pvt *tmp = NULL;
13301 struct dahdi_confinfo ci;
13302 struct dahdi_params ps;
13303 int x;
13304 ast_mutex_t *lock;
13305 struct dahdi_pvt *start;
13306 #ifdef HAVE_PRI
13307 char *c;
13308 int trunkgroup;
13309 struct dahdi_pri *pri=NULL;
13310 #endif
13311
13312 lock = &iflock;
13313 start = iflist;
13314
13315 if (argc != 4)
13316 return RESULT_SHOWUSAGE;
13317 #ifdef HAVE_PRI
13318 if ((c = strchr(argv[3], ':'))) {
13319 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
13320 return RESULT_SHOWUSAGE;
13321 if ((trunkgroup < 1) || (channel < 1))
13322 return RESULT_SHOWUSAGE;
13323 for (x = 0; x < NUM_SPANS; x++) {
13324 if (pris[x].trunkgroup == trunkgroup) {
13325 pri = pris + x;
13326 break;
13327 }
13328 }
13329 if (pri) {
13330 start = pri->crvs;
13331 lock = &pri->lock;
13332 } else {
13333 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13334 return RESULT_FAILURE;
13335 }
13336 } else
13337 #endif
13338 channel = atoi(argv[3]);
13339
13340 ast_mutex_lock(lock);
13341 tmp = start;
13342 while (tmp) {
13343 if (tmp->channel == channel) {
13344 #ifdef HAVE_PRI
13345 if (pri)
13346 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
13347 else
13348 #endif
13349 ast_cli(fd, "Channel: %d\n", tmp->channel);
13350 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
13351 ast_cli(fd, "Span: %d\n", tmp->span);
13352 ast_cli(fd, "Extension: %s\n", tmp->exten);
13353 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
13354 ast_cli(fd, "Context: %s\n", tmp->context);
13355 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
13356 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
13357 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
13358 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
13359 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
13360 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
13361 ast_cli(fd, "Radio: %d\n", tmp->radio);
13362 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
13363 ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
13364 ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
13365 ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
13366 ast_cli(fd, "Confno: %d\n", tmp->confno);
13367 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
13368 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
13369 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
13370 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
13371 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
13372 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
13373 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
13374 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
13375 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
13376 if (tmp->master)
13377 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
13378 for (x = 0; x < MAX_SLAVES; x++) {
13379 if (tmp->slaves[x])
13380 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
13381 }
13382
13383 #ifdef HAVE_OPENR2
13384 if (tmp->mfcr2) {
13385 char calldir[OR2_MAX_PATH];
13386 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
13387 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
13388 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
13389 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
13390 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
13391 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
13392 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
13393 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
13394 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
13395 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
13396 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
13397 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
13398 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13399 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
13400 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
13401 #endif
13402 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
13403 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
13404 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
13405 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
13406 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
13407 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
13408 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
13409 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
13410 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
13411 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
13412 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
13413 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
13414 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
13415 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
13416 }
13417 #endif
13418
13419 #ifdef HAVE_PRI
13420 if (tmp->pri) {
13421 ast_cli(fd, "PRI Flags: ");
13422 if (tmp->resetting)
13423 ast_cli(fd, "Resetting ");
13424 if (tmp->call)
13425 ast_cli(fd, "Call ");
13426 if (tmp->bearer)
13427 ast_cli(fd, "Bearer ");
13428 if (tmp->allocated) {
13429 ast_cli(fd, "Allocated ");
13430 }
13431 ast_cli(fd, "\n");
13432 if (tmp->logicalspan)
13433 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
13434 else
13435 ast_cli(fd, "PRI Logical Span: Implicit\n");
13436 }
13437 #endif
13438 memset(&ci, 0, sizeof(ci));
13439 ps.channo = tmp->channel;
13440 if (tmp->subs[SUB_REAL].dfd > -1) {
13441 memset(&ci, 0, sizeof(ci));
13442 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
13443 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
13444 }
13445 #ifdef DAHDI_GETCONFMUTE
13446 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
13447 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
13448 }
13449 #endif
13450 memset(&ps, 0, sizeof(ps));
13451 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
13452 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
13453 } else {
13454 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
13455 }
13456 }
13457 if (ISTRUNK(tmp)) {
13458 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
13459 if (!ast_strlen_zero(progzone))
13460 ast_cli(fd, "Progress Zone: %s\n", progzone);
13461 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
13462 if(tmp->busydetect) {
13463 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
13464 if(tmp->busytonelength > 0) {
13465 ast_cli(fd, "Busy Pattern:\n");
13466 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
13467 if (tmp->busyquietlength > 0)
13468 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
13469 else
13470 ast_cli(fd, " -- Detect Tone Only\n");
13471 if(tmp->busyfuzziness > 0)
13472 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
13473 }
13474 }
13475 }
13476 ast_mutex_unlock(lock);
13477 return RESULT_SUCCESS;
13478 }
13479 tmp = tmp->next;
13480 }
13481
13482 ast_cli(fd, "Unable to find given channel %d\n", channel);
13483 ast_mutex_unlock(lock);
13484 return RESULT_FAILURE;
13485 }
13486
13487 static char dahdi_show_cadences_usage[] =
13488 "Usage: dahdi show cadences\n"
13489 " Shows all cadences currently defined\n";
13490
13491 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
13492 {
13493 int i, j;
13494 for (i = 0; i < num_cadence; i++) {
13495 char output[1024];
13496 char tmp[16], tmp2[64];
13497 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
13498 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
13499
13500 for (j = 0; j < 16; j++) {
13501 if (cadences[i].ringcadence[j] == 0)
13502 break;
13503 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
13504 if (cidrings[i] * 2 - 1 == j)
13505 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
13506 else
13507 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
13508 if (j != 0)
13509 strncat(output, ",", sizeof(output) - strlen(output) - 1);
13510 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
13511 }
13512 ast_cli(fd,"%s\n",output);
13513 }
13514 return 0;
13515 }
13516
13517
13518 static int dahdi_show_status(int fd, int argc, char *argv[]) {
13519 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
13520 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
13521
13522 int span;
13523 int res;
13524 char alarms[50];
13525
13526 int ctl;
13527 struct dahdi_spaninfo s;
13528
13529 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
13530 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
13531 ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
13532 return RESULT_FAILURE;
13533 }
13534 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
13535
13536 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13537 s.spanno = span;
13538 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13539 if (res) {
13540 continue;
13541 }
13542 alarms[0] = '\0';
13543 if (s.alarms > 0) {
13544 if (s.alarms & DAHDI_ALARM_BLUE)
13545 strcat(alarms, "BLU/");
13546 if (s.alarms & DAHDI_ALARM_YELLOW)
13547 strcat(alarms, "YEL/");
13548 if (s.alarms & DAHDI_ALARM_RED)
13549 strcat(alarms, "RED/");
13550 if (s.alarms & DAHDI_ALARM_LOOPBACK)
13551 strcat(alarms, "LB/");
13552 if (s.alarms & DAHDI_ALARM_RECOVER)
13553 strcat(alarms, "REC/");
13554 if (s.alarms & DAHDI_ALARM_NOTOPEN)
13555 strcat(alarms, "NOP/");
13556 if (!strlen(alarms))
13557 strcat(alarms, "UUU/");
13558 if (strlen(alarms)) {
13559
13560 alarms[strlen(alarms) - 1] = '\0';
13561 }
13562 } else {
13563 if (s.numchans)
13564 strcpy(alarms, "OK");
13565 else
13566 strcpy(alarms, "UNCONFIGURED");
13567 }
13568
13569 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
13570 }
13571 close(ctl);
13572
13573 return RESULT_SUCCESS;
13574 #undef FORMAT
13575 #undef FORMAT2
13576 }
13577
13578 static char show_channels_usage[] =
13579 "Usage: dahdi show channels\n"
13580 " Shows a list of available channels\n";
13581
13582 static char show_channel_usage[] =
13583 "Usage: dahdi show channel <chan num>\n"
13584 " Detailed information about a given channel\n";
13585
13586 static char dahdi_show_status_usage[] =
13587 "Usage: dahdi show status\n"
13588 " Shows a list of DAHDI cards with status\n";
13589
13590 static char destroy_channel_usage[] =
13591 "Usage: dahdi destroy channel <chan num>\n"
13592 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
13593
13594 static char dahdi_restart_usage[] =
13595 "Usage: dahdi restart\n"
13596 " Restarts the DAHDI channels: destroys them all and then\n"
13597 " re-reads them from chan_dahdi.conf.\n"
13598 " Note that this will STOP any running CALL on DAHDI channels.\n"
13599 "";
13600
13601 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
13602 { "zap", "show", "cadences", NULL },
13603 handle_dahdi_show_cadences, NULL,
13604 NULL };
13605
13606 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
13607 { "zap", "show", "channels", NULL },
13608 dahdi_show_channels, NULL,
13609 NULL };
13610
13611 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
13612 { "zap", "show", "channel", NULL },
13613 dahdi_show_channel, NULL,
13614 NULL };
13615
13616 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
13617 { "zap", "destroy", "channel", NULL },
13618 dahdi_destroy_channel, NULL,
13619 NULL };
13620
13621 static struct ast_cli_entry cli_zap_restart_deprecated = {
13622 { "zap", "restart", NULL },
13623 dahdi_restart_cmd, NULL,
13624 NULL };
13625
13626 static struct ast_cli_entry cli_zap_show_status_deprecated = {
13627 { "zap", "show", "status", NULL },
13628 dahdi_show_status, NULL,
13629 NULL };
13630
13631 static struct ast_cli_entry dahdi_cli[] = {
13632 { { "dahdi", "show", "cadences", NULL },
13633 handle_dahdi_show_cadences, "List cadences",
13634 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
13635
13636 { { "dahdi", "show", "channels", NULL},
13637 dahdi_show_channels, "Show active DAHDI channels",
13638 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
13639
13640 { { "dahdi", "show", "channel", NULL},
13641 dahdi_show_channel, "Show information on a channel",
13642 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
13643
13644 { { "dahdi", "destroy", "channel", NULL},
13645 dahdi_destroy_channel, "Destroy a channel",
13646 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
13647
13648 { { "dahdi", "restart", NULL},
13649 dahdi_restart_cmd, "Fully restart DAHDI channels",
13650 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
13651
13652 { { "dahdi", "show", "status", NULL},
13653 dahdi_show_status, "Show all DAHDI cards status",
13654 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
13655 };
13656
13657 #define TRANSFER 0
13658 #define HANGUP 1
13659
13660 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13661 {
13662 if (p) {
13663 switch (mode) {
13664 case TRANSFER:
13665 p->fake_event = DAHDI_EVENT_WINKFLASH;
13666 break;
13667 case HANGUP:
13668 p->fake_event = DAHDI_EVENT_ONHOOK;
13669 break;
13670 default:
13671 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
13672 }
13673 }
13674 return 0;
13675 }
13676 static struct dahdi_pvt *find_channel(int channel)
13677 {
13678 struct dahdi_pvt *p = iflist;
13679 while (p) {
13680 if (p->channel == channel) {
13681 break;
13682 }
13683 p = p->next;
13684 }
13685 return p;
13686 }
13687
13688 #define local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
13689 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
13690
13691 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
13692 {
13693 struct dahdi_pvt *p = NULL;
13694 const char *channel = local_astman_header(m, "Channel", zap_mode);
13695
13696 if (ast_strlen_zero(channel)) {
13697 astman_send_error(s, m, "No channel specified");
13698 return 0;
13699 }
13700 if (!(p = find_channel(atoi(channel)))) {
13701 astman_send_error(s, m, "No such channel");
13702 return 0;
13703 }
13704 p->dnd = dnd;
13705 local_astman_ack(s, m, "DND", zap_mode);
13706
13707 return 0;
13708 }
13709
13710 static int zap_action_dndon(struct mansession *s, const struct message *m)
13711 {
13712 return __action_dnd(s, m, 1, 1);
13713 }
13714
13715 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
13716 {
13717 return __action_dnd(s, m, 0, 1);
13718 }
13719
13720 static int zap_action_dndoff(struct mansession *s, const struct message *m)
13721 {
13722 return __action_dnd(s, m, 1, 0);
13723 }
13724
13725 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
13726 {
13727 return __action_dnd(s, m, 0, 0);
13728 }
13729
13730 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
13731 {
13732 struct dahdi_pvt *p = NULL;
13733 const char *channel = local_astman_header(m, "Channel", zap_mode);
13734
13735 if (ast_strlen_zero(channel)) {
13736 astman_send_error(s, m, "No channel specified");
13737 return 0;
13738 }
13739 if (!(p = find_channel(atoi(channel)))) {
13740 astman_send_error(s, m, "No such channel");
13741 return 0;
13742 }
13743 dahdi_fake_event(p,TRANSFER);
13744 local_astman_ack(s, m, "Transfer", zap_mode);
13745
13746 return 0;
13747 }
13748
13749 static int zap_action_transfer(struct mansession *s, const struct message *m)
13750 {
13751 return __action_transfer(s, m, 1);
13752 }
13753
13754 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
13755 {
13756 return __action_transfer(s, m, 0);
13757 }
13758
13759 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
13760 {
13761 struct dahdi_pvt *p = NULL;
13762 const char *channel = local_astman_header(m, "Channel", zap_mode);
13763
13764 if (ast_strlen_zero(channel)) {
13765 astman_send_error(s, m, "No channel specified");
13766 return 0;
13767 }
13768 if (!(p = find_channel(atoi(channel)))) {
13769 astman_send_error(s, m, "No such channel");
13770 return 0;
13771 }
13772 dahdi_fake_event(p, HANGUP);
13773 local_astman_ack(s, m, "Hangup", zap_mode);
13774 return 0;
13775 }
13776
13777 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
13778 {
13779 return __action_transferhangup(s, m, 1);
13780 }
13781
13782 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
13783 {
13784 return __action_transferhangup(s, m, 0);
13785 }
13786
13787 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
13788 {
13789 struct dahdi_pvt *p = NULL;
13790 const char *channel = local_astman_header(m, "Channel", zap_mode);
13791 const char *number = astman_get_header(m, "Number");
13792 int i;
13793
13794 if (ast_strlen_zero(channel)) {
13795 astman_send_error(s, m, "No channel specified");
13796 return 0;
13797 }
13798 if (ast_strlen_zero(number)) {
13799 astman_send_error(s, m, "No number specified");
13800 return 0;
13801 }
13802 if (!(p = find_channel(atoi(channel)))) {
13803 astman_send_error(s, m, "No such channel");
13804 return 0;
13805 }
13806 if (!p->owner) {
13807 astman_send_error(s, m, "Channel does not have an owner");
13808 return 0;
13809 }
13810 for (i = 0; i < strlen(number); i++) {
13811 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13812
13813 dahdi_queue_frame(p, &f, NULL);
13814 }
13815 local_astman_ack(s, m, "DialOffHook", zap_mode);
13816
13817 return 0;
13818 }
13819
13820 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
13821 {
13822 return __action_dialoffhook(s, m, 1);
13823 }
13824
13825 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
13826 {
13827 return __action_dialoffhook(s, m, 0);
13828 }
13829
13830 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
13831 {
13832 struct dahdi_pvt *tmp = NULL;
13833 const char *id = astman_get_header(m, "ActionID");
13834 char idText[256] = "";
13835
13836 local_astman_ack(s, m, " channel status will follow", zap_mode);
13837 if (!ast_strlen_zero(id))
13838 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
13839
13840 ast_mutex_lock(&iflock);
13841
13842 tmp = iflist;
13843 while (tmp) {
13844 if (tmp->channel > 0) {
13845 int alarm = get_alarms(tmp);
13846 astman_append(s,
13847 "Event: %sShowChannels\r\n"
13848 "Channel: %d\r\n"
13849 "Signalling: %s\r\n"
13850 "Context: %s\r\n"
13851 "DND: %s\r\n"
13852 "Alarm: %s\r\n"
13853 "%s"
13854 "\r\n",
13855 dahdi_chan_name,
13856 tmp->channel, sig2str(tmp->sig), tmp->context,
13857 tmp->dnd ? "Enabled" : "Disabled",
13858 alarm2str(alarm), idText);
13859 }
13860
13861 tmp = tmp->next;
13862 }
13863
13864 ast_mutex_unlock(&iflock);
13865
13866 astman_append(s,
13867 "Event: %sShowChannelsComplete\r\n"
13868 "%s"
13869 "\r\n",
13870 dahdi_chan_name,
13871 idText);
13872 return 0;
13873 }
13874
13875 static int zap_action_showchannels(struct mansession *s, const struct message *m)
13876 {
13877 return __action_showchannels(s, m, 1);
13878 }
13879
13880 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
13881 {
13882 return __action_showchannels(s, m, 0);
13883 }
13884
13885 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
13886 {
13887 if (dahdi_restart() != 0) {
13888 if (zap_mode) {
13889 astman_send_error(s, m, "Failed to restart Zap");
13890 } else {
13891 astman_send_error(s, m, "Failed to restart DAHDI");
13892 }
13893 return 1;
13894 }
13895 local_astman_ack(s, m, "Restart: Success", zap_mode);
13896 return 0;
13897 }
13898
13899 static int zap_action_restart(struct mansession *s, const struct message *m)
13900 {
13901 return __action_restart(s, m, 1);
13902 }
13903
13904 static int dahdi_action_restart(struct mansession *s, const struct message *m)
13905 {
13906 return __action_restart(s, m, 0);
13907 }
13908
13909 #define local_astman_unregister(a) do { \
13910 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13911 ast_manager_unregister("DAHDI" a); \
13912 } \
13913 ast_manager_unregister("Zap" a); \
13914 } while (0)
13915
13916 static int __unload_module(void)
13917 {
13918 struct dahdi_pvt *p;
13919
13920 #ifdef HAVE_OPENR2
13921 int r;
13922 #endif
13923
13924 #ifdef HAVE_PRI
13925 int i, j;
13926 for (i = 0; i < NUM_SPANS; i++) {
13927 if (pris[i].master != AST_PTHREADT_NULL)
13928 pthread_cancel(pris[i].master);
13929 }
13930 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13931
13932 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13933 ast_unregister_application(dahdi_send_keypad_facility_app);
13934 }
13935 ast_unregister_application(zap_send_keypad_facility_app);
13936 #endif
13937
13938 #ifdef HAVE_OPENR2
13939 for (r = 0; r < NUM_SPANS; r++) {
13940 if (r2links[r].master != AST_PTHREADT_NULL) {
13941 pthread_cancel(r2links[r].master);
13942 pthread_join(r2links[r].master, NULL);
13943 }
13944 }
13945 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
13946 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13947 ast_unregister_application(dahdi_accept_r2_call_app);
13948 }
13949 ast_unregister_application(zap_accept_r2_call_app);
13950 #endif
13951
13952 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13953 local_astman_unregister("DialOffHook");
13954 local_astman_unregister("Hangup");
13955 local_astman_unregister("Transfer");
13956 local_astman_unregister("DNDoff");
13957 local_astman_unregister("DNDon");
13958 local_astman_unregister("ShowChannels");
13959 local_astman_unregister("Restart");
13960 ast_channel_unregister(chan_tech);
13961 ast_mutex_lock(&iflock);
13962
13963 p = iflist;
13964 while (p) {
13965 if (p->owner)
13966 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
13967 p = p->next;
13968 }
13969 ast_mutex_unlock(&iflock);
13970 ast_mutex_lock(&monlock);
13971 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
13972 pthread_cancel(monitor_thread);
13973 pthread_kill(monitor_thread, SIGURG);
13974 pthread_join(monitor_thread, NULL);
13975 }
13976 monitor_thread = AST_PTHREADT_STOP;
13977 ast_mutex_unlock(&monlock);
13978
13979 destroy_all_channels();
13980 #ifdef HAVE_PRI
13981 for (i = 0; i < NUM_SPANS; i++) {
13982 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
13983 pthread_join(pris[i].master, NULL);
13984 for (j = 0; j < NUM_DCHANS; j++) {
13985 dahdi_close_pri_fd(&(pris[i]), j);
13986 }
13987 }
13988 #endif
13989
13990 #ifdef HAVE_OPENR2
13991 for (r = 0; r < NUM_SPANS; r++) {
13992 if (r2links[r].protocol_context) {
13993 openr2_context_delete(r2links[r].protocol_context);
13994 }
13995 }
13996 #endif
13997
13998 ast_cond_destroy(&ss_thread_complete);
13999 return 0;
14000 }
14001
14002 static int unload_module(void)
14003 {
14004 #ifdef HAVE_PRI
14005 int y;
14006 for (y = 0; y < NUM_SPANS; y++)
14007 ast_mutex_destroy(&pris[y].lock);
14008 #endif
14009 return __unload_module();
14010 }
14011
14012 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
14013 {
14014 char *c, *chan;
14015 int x, start, finish;
14016 struct dahdi_pvt *tmp;
14017 #ifdef HAVE_PRI
14018 struct dahdi_pri *pri;
14019 int trunkgroup, y;
14020 #endif
14021
14022 if ((reload == 0) && (conf->chan.sig < 0)) {
14023 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14024 return -1;
14025 }
14026
14027 c = ast_strdupa(value);
14028
14029 #ifdef HAVE_PRI
14030 pri = NULL;
14031 if (iscrv) {
14032 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14033 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
14034 return -1;
14035 }
14036 if (trunkgroup < 1) {
14037 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
14038 return -1;
14039 }
14040 c += y;
14041 for (y = 0; y < NUM_SPANS; y++) {
14042 if (pris[y].trunkgroup == trunkgroup) {
14043 pri = pris + y;
14044 break;
14045 }
14046 }
14047 if (!pri) {
14048 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
14049 return -1;
14050 }
14051 }
14052 #endif
14053
14054 while ((chan = strsep(&c, ","))) {
14055 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14056
14057 } else if (sscanf(chan, "%30d", &start)) {
14058
14059 finish = start;
14060 } else if (!strcasecmp(chan, "pseudo")) {
14061 finish = start = CHAN_PSEUDO;
14062 if (found_pseudo)
14063 *found_pseudo = 1;
14064 } else {
14065 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14066 return -1;
14067 }
14068 if (finish < start) {
14069 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14070 x = finish;
14071 finish = start;
14072 start = x;
14073 }
14074
14075 for (x = start; x <= finish; x++) {
14076 #ifdef HAVE_PRI
14077 tmp = mkintf(x, conf, pri, reload);
14078 #else
14079 tmp = mkintf(x, conf, NULL, reload);
14080 #endif
14081
14082 if (tmp) {
14083 if (option_verbose > 2) {
14084 #ifdef HAVE_PRI
14085 if (pri)
14086 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14087 else
14088 #endif
14089 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14090 }
14091 } else {
14092 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14093 (reload == 1) ? "reconfigure" : "register", value);
14094 return -1;
14095 }
14096 }
14097
14098 #ifdef HAVE_OPENR2
14099 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
14100 mfcr2_cur_context_index++;
14101 }
14102 #endif
14103
14104 }
14105
14106 return 0;
14107 }
14108
14109
14110
14111 #define MAX_CHANLIST_LEN 80
14112 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
14113 {
14114 struct dahdi_pvt *tmp;
14115 int y;
14116 int found_pseudo = 0;
14117 char dahdichan[MAX_CHANLIST_LEN] = {};
14118
14119 for (; v; v = v->next) {
14120 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14121 continue;
14122
14123
14124 if (!strcasecmp(v->name, "channel")
14125 #ifdef HAVE_PRI
14126 || !strcasecmp(v->name, "crv")
14127 #endif
14128 ) {
14129 int iscrv;
14130 if (skipchannels)
14131 continue;
14132 iscrv = !strcasecmp(v->name, "crv");
14133 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14134 return -1;
14135 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
14136 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14137 if (v->name[0] == 'z' || v->name[0] == 'Z') {
14138 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
14139 }
14140 } else if (!strcasecmp(v->name, "buffers")) {
14141 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
14142 ast_log(LOG_WARNING, "Using default buffer policy.\n");
14143 confp->chan.buf_no = numbufs;
14144 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14145 }
14146 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14147 if (ast_true(v->value))
14148 confp->chan.usedistinctiveringdetection = 1;
14149 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14150 if (ast_true(v->value))
14151 distinctiveringaftercid = 1;
14152 } else if (!strcasecmp(v->name, "dring1context")) {
14153 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
14154 } else if (!strcasecmp(v->name, "dring2context")) {
14155 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
14156 } else if (!strcasecmp(v->name, "dring3context")) {
14157 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
14158 } else if (!strcasecmp(v->name, "dring1")) {
14159 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
14160 } else if (!strcasecmp(v->name, "dring2")) {
14161 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
14162 } else if (!strcasecmp(v->name, "dring3")) {
14163 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
14164 } else if (!strcasecmp(v->name, "usecallerid")) {
14165 confp->chan.use_callerid = ast_true(v->value);
14166 } else if (!strcasecmp(v->name, "cidsignalling")) {
14167 if (!strcasecmp(v->value, "bell"))
14168 confp->chan.cid_signalling = CID_SIG_BELL;
14169 else if (!strcasecmp(v->value, "v23"))
14170 confp->chan.cid_signalling = CID_SIG_V23;
14171 else if (!strcasecmp(v->value, "dtmf"))
14172 confp->chan.cid_signalling = CID_SIG_DTMF;
14173 else if (!strcasecmp(v->value, "smdi"))
14174 confp->chan.cid_signalling = CID_SIG_SMDI;
14175 else if (!strcasecmp(v->value, "v23_jp"))
14176 confp->chan.cid_signalling = CID_SIG_V23_JP;
14177 else if (ast_true(v->value))
14178 confp->chan.cid_signalling = CID_SIG_BELL;
14179 } else if (!strcasecmp(v->name, "cidstart")) {
14180 if (!strcasecmp(v->value, "ring"))
14181 confp->chan.cid_start = CID_START_RING;
14182 else if (!strcasecmp(v->value, "polarity"))
14183 confp->chan.cid_start = CID_START_POLARITY;
14184 else if (!strcasecmp(v->value, "dtmf"))
14185 confp->chan.cid_start = CID_START_DTMF_NOALERT;
14186 else if (ast_true(v->value))
14187 confp->chan.cid_start = CID_START_RING;
14188 } else if (!strcasecmp(v->name, "threewaycalling")) {
14189 confp->chan.threewaycalling = ast_true(v->value);
14190 } else if (!strcasecmp(v->name, "cancallforward")) {
14191 confp->chan.cancallforward = ast_true(v->value);
14192 } else if (!strcasecmp(v->name, "relaxdtmf")) {
14193 if (ast_true(v->value))
14194 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14195 else
14196 confp->chan.dtmfrelax = 0;
14197 } else if (!strcasecmp(v->name, "mailbox")) {
14198 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14199 } else if (!strcasecmp(v->name, "hasvoicemail")) {
14200 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14201 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14202 }
14203 } else if (!strcasecmp(v->name, "adsi")) {
14204 confp->chan.adsi = ast_true(v->value);
14205 } else if (!strcasecmp(v->name, "usesmdi")) {
14206 confp->chan.use_smdi = ast_true(v->value);
14207 } else if (!strcasecmp(v->name, "smdiport")) {
14208 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14209 } else if (!strcasecmp(v->name, "transfer")) {
14210 confp->chan.transfer = ast_true(v->value);
14211 } else if (!strcasecmp(v->name, "canpark")) {
14212 confp->chan.canpark = ast_true(v->value);
14213 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14214 confp->chan.echocanbridged = ast_true(v->value);
14215 } else if (!strcasecmp(v->name, "busydetect")) {
14216 confp->chan.busydetect = ast_true(v->value);
14217 } else if (!strcasecmp(v->name, "busycount")) {
14218 confp->chan.busycount = atoi(v->value);
14219 } else if (!strcasecmp(v->name, "silencethreshold")) {
14220 confp->chan.silencethreshold = atoi(v->value);
14221 } else if (!strcasecmp(v->name, "busycompare")) {
14222 confp->chan.busycompare = ast_true(v->value);
14223 } else if (!strcasecmp(v->name, "busypattern")) {
14224 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
14225 if (count == 1)
14226 confp->chan.busyquietlength = 0;
14227 else if (count < 1)
14228 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
14229 } else if (!strcasecmp(v->name, "busyfuzziness")) {
14230 confp->chan.busyfuzziness = atoi(v->value);
14231 } else if (!strcasecmp(v->name, "callprogress")) {
14232 if (ast_true(v->value))
14233 confp->chan.callprogress |= 1;
14234 else
14235 confp->chan.callprogress &= ~1;
14236 } else if (!strcasecmp(v->name, "faxdetect")) {
14237 if (!strcasecmp(v->value, "incoming")) {
14238 confp->chan.callprogress |= 4;
14239 confp->chan.callprogress &= ~2;
14240 } else if (!strcasecmp(v->value, "outgoing")) {
14241 confp->chan.callprogress &= ~4;
14242 confp->chan.callprogress |= 2;
14243 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14244 confp->chan.callprogress |= 6;
14245 else
14246 confp->chan.callprogress &= ~6;
14247 } else if (!strcasecmp(v->name, "echocancel")) {
14248 if (!ast_strlen_zero(v->value)) {
14249 y = atoi(v->value);
14250 } else
14251 y = 0;
14252 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
14253 confp->chan.echocancel = y;
14254 else {
14255 confp->chan.echocancel = ast_true(v->value);
14256 if (confp->chan.echocancel)
14257 confp->chan.echocancel=128;
14258 }
14259 } else if (!strcasecmp(v->name, "echotraining")) {
14260 if (sscanf(v->value, "%30d", &y) == 1) {
14261 if ((y < 10) || (y > 4000)) {
14262 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
14263 } else {
14264 confp->chan.echotraining = y;
14265 }
14266 } else if (ast_true(v->value)) {
14267 confp->chan.echotraining = 400;
14268 } else
14269 confp->chan.echotraining = 0;
14270 } else if (!strcasecmp(v->name, "hidecallerid")) {
14271 confp->chan.hidecallerid = ast_true(v->value);
14272 } else if (!strcasecmp(v->name, "hidecalleridname")) {
14273 confp->chan.hidecalleridname = ast_true(v->value);
14274 } else if (!strcasecmp(v->name, "pulsedial")) {
14275 confp->chan.pulse = ast_true(v->value);
14276 } else if (!strcasecmp(v->name, "callreturn")) {
14277 confp->chan.callreturn = ast_true(v->value);
14278 } else if (!strcasecmp(v->name, "callwaiting")) {
14279 confp->chan.callwaiting = ast_true(v->value);
14280 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14281 confp->chan.callwaitingcallerid = ast_true(v->value);
14282 } else if (!strcasecmp(v->name, "context")) {
14283 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14284 } else if (!strcasecmp(v->name, "language")) {
14285 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14286 } else if (!strcasecmp(v->name, "progzone")) {
14287 ast_copy_string(progzone, v->value, sizeof(progzone));
14288 } else if (!strcasecmp(v->name, "mohinterpret")
14289 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14290 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14291 } else if (!strcasecmp(v->name, "mohsuggest")) {
14292 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14293 } else if (!strcasecmp(v->name, "stripmsd")) {
14294 confp->chan.stripmsd = atoi(v->value);
14295 } else if (!strcasecmp(v->name, "jitterbuffers")) {
14296 numbufs = atoi(v->value);
14297 } else if (!strcasecmp(v->name, "group")) {
14298 confp->chan.group = ast_get_group(v->value);
14299 } else if (!strcasecmp(v->name, "callgroup")) {
14300 confp->chan.callgroup = ast_get_group(v->value);
14301 } else if (!strcasecmp(v->name, "pickupgroup")) {
14302 confp->chan.pickupgroup = ast_get_group(v->value);
14303 } else if (!strcasecmp(v->name, "immediate")) {
14304 confp->chan.immediate = ast_true(v->value);
14305 } else if (!strcasecmp(v->name, "transfertobusy")) {
14306 confp->chan.transfertobusy = ast_true(v->value);
14307 } else if (!strcasecmp(v->name, "rxgain")) {
14308 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
14309 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
14310 }
14311 } else if (!strcasecmp(v->name, "txgain")) {
14312 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
14313 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
14314 }
14315 } else if (!strcasecmp(v->name, "tonezone")) {
14316 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
14317 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
14318 }
14319 } else if (!strcasecmp(v->name, "callerid")) {
14320 if (!strcasecmp(v->value, "asreceived")) {
14321 confp->chan.cid_num[0] = '\0';
14322 confp->chan.cid_name[0] = '\0';
14323 } else {
14324 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14325 }
14326 } else if (!strcasecmp(v->name, "fullname")) {
14327 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14328 } else if (!strcasecmp(v->name, "cid_number")) {
14329 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14330 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
14331 confp->chan.dahditrcallerid = ast_true(v->value);
14332 if (strstr(v->name, "zap")) {
14333 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
14334 }
14335 } else if (!strcasecmp(v->name, "restrictcid")) {
14336 confp->chan.restrictcid = ast_true(v->value);
14337 } else if (!strcasecmp(v->name, "usecallingpres")) {
14338 confp->chan.use_callingpres = ast_true(v->value);
14339 } else if (!strcasecmp(v->name, "accountcode")) {
14340 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14341 } else if (!strcasecmp(v->name, "amaflags")) {
14342 y = ast_cdr_amaflags2int(v->value);
14343 if (y < 0)
14344 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
14345 else
14346 confp->chan.amaflags = y;
14347 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14348 confp->chan.polarityonanswerdelay = atoi(v->value);
14349 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14350 confp->chan.answeronpolarityswitch = ast_true(v->value);
14351 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14352 confp->chan.hanguponpolarityswitch = ast_true(v->value);
14353 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14354 confp->chan.sendcalleridafter = atoi(v->value);
14355 } else if (reload != 1) {
14356 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14357 confp->chan.outsigmod = -1;
14358 if (!strcasecmp(v->value, "em")) {
14359 confp->chan.sig = SIG_EM;
14360 } else if (!strcasecmp(v->value, "em_e1")) {
14361 confp->chan.sig = SIG_EM_E1;
14362 } else if (!strcasecmp(v->value, "em_w")) {
14363 confp->chan.sig = SIG_EMWINK;
14364 confp->chan.radio = 0;
14365 } else if (!strcasecmp(v->value, "fxs_ls")) {
14366 confp->chan.sig = SIG_FXSLS;
14367 confp->chan.radio = 0;
14368 } else if (!strcasecmp(v->value, "fxs_gs")) {
14369 confp->chan.sig = SIG_FXSGS;
14370 confp->chan.radio = 0;
14371 } else if (!strcasecmp(v->value, "fxs_ks")) {
14372 confp->chan.sig = SIG_FXSKS;
14373 confp->chan.radio = 0;
14374 } else if (!strcasecmp(v->value, "fxo_ls")) {
14375 confp->chan.sig = SIG_FXOLS;
14376 confp->chan.radio = 0;
14377 } else if (!strcasecmp(v->value, "fxo_gs")) {
14378 confp->chan.sig = SIG_FXOGS;
14379 confp->chan.radio = 0;
14380 } else if (!strcasecmp(v->value, "fxo_ks")) {
14381 confp->chan.sig = SIG_FXOKS;
14382 confp->chan.radio = 0;
14383 } else if (!strcasecmp(v->value, "fxs_rx")) {
14384 confp->chan.sig = SIG_FXSKS;
14385 confp->chan.radio = 1;
14386 } else if (!strcasecmp(v->value, "fxo_rx")) {
14387 confp->chan.sig = SIG_FXOLS;
14388 confp->chan.radio = 1;
14389 } else if (!strcasecmp(v->value, "fxs_tx")) {
14390 confp->chan.sig = SIG_FXSLS;
14391 confp->chan.radio = 1;
14392 } else if (!strcasecmp(v->value, "fxo_tx")) {
14393 confp->chan.sig = SIG_FXOGS;
14394 confp->chan.radio = 1;
14395 } else if (!strcasecmp(v->value, "em_rx")) {
14396 confp->chan.sig = SIG_EM;
14397 confp->chan.radio = 1;
14398 } else if (!strcasecmp(v->value, "em_tx")) {
14399 confp->chan.sig = SIG_EM;
14400 confp->chan.radio = 1;
14401 } else if (!strcasecmp(v->value, "em_rxtx")) {
14402 confp->chan.sig = SIG_EM;
14403 confp->chan.radio = 2;
14404 } else if (!strcasecmp(v->value, "em_txrx")) {
14405 confp->chan.sig = SIG_EM;
14406 confp->chan.radio = 2;
14407 } else if (!strcasecmp(v->value, "sf")) {
14408 confp->chan.sig = SIG_SF;
14409 confp->chan.radio = 0;
14410 } else if (!strcasecmp(v->value, "sf_w")) {
14411 confp->chan.sig = SIG_SFWINK;
14412 confp->chan.radio = 0;
14413 } else if (!strcasecmp(v->value, "sf_featd")) {
14414 confp->chan.sig = SIG_FEATD;
14415 confp->chan.radio = 0;
14416 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14417 confp->chan.sig = SIG_FEATDMF;
14418 confp->chan.radio = 0;
14419 } else if (!strcasecmp(v->value, "sf_featb")) {
14420 confp->chan.sig = SIG_SF_FEATB;
14421 confp->chan.radio = 0;
14422 } else if (!strcasecmp(v->value, "sf")) {
14423 confp->chan.sig = SIG_SF;
14424 confp->chan.radio = 0;
14425 } else if (!strcasecmp(v->value, "sf_rx")) {
14426 confp->chan.sig = SIG_SF;
14427 confp->chan.radio = 1;
14428 } else if (!strcasecmp(v->value, "sf_tx")) {
14429 confp->chan.sig = SIG_SF;
14430 confp->chan.radio = 1;
14431 } else if (!strcasecmp(v->value, "sf_rxtx")) {
14432 confp->chan.sig = SIG_SF;
14433 confp->chan.radio = 2;
14434 } else if (!strcasecmp(v->value, "sf_txrx")) {
14435 confp->chan.sig = SIG_SF;
14436 confp->chan.radio = 2;
14437 } else if (!strcasecmp(v->value, "featd")) {
14438 confp->chan.sig = SIG_FEATD;
14439 confp->chan.radio = 0;
14440 } else if (!strcasecmp(v->value, "featdmf")) {
14441 confp->chan.sig = SIG_FEATDMF;
14442 confp->chan.radio = 0;
14443 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14444 confp->chan.sig = SIG_FEATDMF_TA;
14445 confp->chan.radio = 0;
14446 } else if (!strcasecmp(v->value, "e911")) {
14447 confp->chan.sig = SIG_E911;
14448 confp->chan.radio = 0;
14449 } else if (!strcasecmp(v->value, "fgccama")) {
14450 confp->chan.sig = SIG_FGC_CAMA;
14451 confp->chan.radio = 0;
14452 } else if (!strcasecmp(v->value, "fgccamamf")) {
14453 confp->chan.sig = SIG_FGC_CAMAMF;
14454 confp->chan.radio = 0;
14455 } else if (!strcasecmp(v->value, "featb")) {
14456 confp->chan.sig = SIG_FEATB;
14457 confp->chan.radio = 0;
14458 #ifdef HAVE_OPENR2
14459 } else if (!strcasecmp(v->value, "mfcr2")) {
14460 confp->chan.sig = SIG_MFCR2;
14461 #endif
14462
14463 #ifdef HAVE_PRI
14464 } else if (!strcasecmp(v->value, "pri_net")) {
14465 confp->chan.radio = 0;
14466 confp->chan.sig = SIG_PRI;
14467 confp->pri.nodetype = PRI_NETWORK;
14468 } else if (!strcasecmp(v->value, "pri_cpe")) {
14469 confp->chan.sig = SIG_PRI;
14470 confp->chan.radio = 0;
14471 confp->pri.nodetype = PRI_CPE;
14472 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14473 confp->chan.sig = SIG_GR303FXOKS;
14474 confp->chan.radio = 0;
14475 confp->pri.nodetype = PRI_NETWORK;
14476 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14477 confp->chan.sig = SIG_GR303FXSKS;
14478 confp->chan.radio = 0;
14479 confp->pri.nodetype = PRI_CPE;
14480 #endif
14481 } else {
14482 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
14483 }
14484 } else if (!strcasecmp(v->name, "outsignalling")) {
14485 if (!strcasecmp(v->value, "em")) {
14486 confp->chan.outsigmod = SIG_EM;
14487 } else if (!strcasecmp(v->value, "em_e1")) {
14488 confp->chan.outsigmod = SIG_EM_E1;
14489 } else if (!strcasecmp(v->value, "em_w")) {
14490 confp->chan.outsigmod = SIG_EMWINK;
14491 } else if (!strcasecmp(v->value, "sf")) {
14492 confp->chan.outsigmod = SIG_SF;
14493 } else if (!strcasecmp(v->value, "sf_w")) {
14494 confp->chan.outsigmod = SIG_SFWINK;
14495 } else if (!strcasecmp(v->value, "sf_featd")) {
14496 confp->chan.outsigmod = SIG_FEATD;
14497 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14498 confp->chan.outsigmod = SIG_FEATDMF;
14499 } else if (!strcasecmp(v->value, "sf_featb")) {
14500 confp->chan.outsigmod = SIG_SF_FEATB;
14501 } else if (!strcasecmp(v->value, "sf")) {
14502 confp->chan.outsigmod = SIG_SF;
14503 } else if (!strcasecmp(v->value, "featd")) {
14504 confp->chan.outsigmod = SIG_FEATD;
14505 } else if (!strcasecmp(v->value, "featdmf")) {
14506 confp->chan.outsigmod = SIG_FEATDMF;
14507 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14508 confp->chan.outsigmod = SIG_FEATDMF_TA;
14509 } else if (!strcasecmp(v->value, "e911")) {
14510 confp->chan.outsigmod = SIG_E911;
14511 } else if (!strcasecmp(v->value, "fgccama")) {
14512 confp->chan.outsigmod = SIG_FGC_CAMA;
14513 } else if (!strcasecmp(v->value, "fgccamamf")) {
14514 confp->chan.outsigmod = SIG_FGC_CAMAMF;
14515 } else if (!strcasecmp(v->value, "featb")) {
14516 confp->chan.outsigmod = SIG_FEATB;
14517 } else {
14518 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
14519 }
14520 #ifdef HAVE_PRI
14521 } else if (!strcasecmp(v->name, "pridialplan")) {
14522 if (!strcasecmp(v->value, "national")) {
14523 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14524 } else if (!strcasecmp(v->value, "unknown")) {
14525 confp->pri.dialplan = PRI_UNKNOWN + 1;
14526 } else if (!strcasecmp(v->value, "private")) {
14527 confp->pri.dialplan = PRI_PRIVATE + 1;
14528 } else if (!strcasecmp(v->value, "international")) {
14529 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14530 } else if (!strcasecmp(v->value, "local")) {
14531 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14532 } else if (!strcasecmp(v->value, "dynamic")) {
14533 confp->pri.dialplan = -1;
14534 } else {
14535 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14536 }
14537 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14538 if (!strcasecmp(v->value, "national")) {
14539 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14540 } else if (!strcasecmp(v->value, "unknown")) {
14541 confp->pri.localdialplan = PRI_UNKNOWN + 1;
14542 } else if (!strcasecmp(v->value, "private")) {
14543 confp->pri.localdialplan = PRI_PRIVATE + 1;
14544 } else if (!strcasecmp(v->value, "international")) {
14545 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14546 } else if (!strcasecmp(v->value, "local")) {
14547 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14548 } else if (!strcasecmp(v->value, "dynamic")) {
14549 confp->pri.localdialplan = -1;
14550 } else {
14551 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14552 }
14553 } else if (!strcasecmp(v->name, "switchtype")) {
14554 if (!strcasecmp(v->value, "national"))
14555 confp->pri.switchtype = PRI_SWITCH_NI2;
14556 else if (!strcasecmp(v->value, "ni1"))
14557 confp->pri.switchtype = PRI_SWITCH_NI1;
14558 else if (!strcasecmp(v->value, "dms100"))
14559 confp->pri.switchtype = PRI_SWITCH_DMS100;
14560 else if (!strcasecmp(v->value, "4ess"))
14561 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14562 else if (!strcasecmp(v->value, "5ess"))
14563 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14564 else if (!strcasecmp(v->value, "euroisdn"))
14565 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14566 else if (!strcasecmp(v->value, "qsig"))
14567 confp->pri.switchtype = PRI_SWITCH_QSIG;
14568 else {
14569 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
14570 return -1;
14571 }
14572 } else if (!strcasecmp(v->name, "nsf")) {
14573 if (!strcasecmp(v->value, "sdn"))
14574 confp->pri.nsf = PRI_NSF_SDN;
14575 else if (!strcasecmp(v->value, "megacom"))
14576 confp->pri.nsf = PRI_NSF_MEGACOM;
14577 else if (!strcasecmp(v->value, "tollfreemegacom"))
14578 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14579 else if (!strcasecmp(v->value, "accunet"))
14580 confp->pri.nsf = PRI_NSF_ACCUNET;
14581 else if (!strcasecmp(v->value, "none"))
14582 confp->pri.nsf = PRI_NSF_NONE;
14583 else {
14584 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
14585 confp->pri.nsf = PRI_NSF_NONE;
14586 }
14587 } else if (!strcasecmp(v->name, "priindication")) {
14588 if (!strcasecmp(v->value, "outofband"))
14589 confp->chan.priindication_oob = 1;
14590 else if (!strcasecmp(v->value, "inband"))
14591 confp->chan.priindication_oob = 0;
14592 else
14593 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
14594 v->value, v->lineno);
14595 } else if (!strcasecmp(v->name, "priexclusive")) {
14596 confp->chan.priexclusive = ast_true(v->value);
14597 } else if (!strcasecmp(v->name, "internationalprefix")) {
14598 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14599 } else if (!strcasecmp(v->name, "nationalprefix")) {
14600 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14601 } else if (!strcasecmp(v->name, "localprefix")) {
14602 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14603 } else if (!strcasecmp(v->name, "privateprefix")) {
14604 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14605 } else if (!strcasecmp(v->name, "unknownprefix")) {
14606 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14607 } else if (!strcasecmp(v->name, "resetinterval")) {
14608 if (!strcasecmp(v->value, "never"))
14609 confp->pri.resetinterval = -1;
14610 else if (atoi(v->value) >= 60)
14611 confp->pri.resetinterval = atoi(v->value);
14612 else
14613 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
14614 v->value, v->lineno);
14615 } else if (!strcasecmp(v->name, "minunused")) {
14616 confp->pri.minunused = atoi(v->value);
14617 } else if (!strcasecmp(v->name, "minidle")) {
14618 confp->pri.minidle = atoi(v->value);
14619 } else if (!strcasecmp(v->name, "idleext")) {
14620 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14621 } else if (!strcasecmp(v->name, "idledial")) {
14622 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14623 } else if (!strcasecmp(v->name, "overlapdial")) {
14624 if (ast_true(v->value)) {
14625 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14626 } else if (!strcasecmp(v->value, "incoming")) {
14627 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14628 } else if (!strcasecmp(v->value, "outgoing")) {
14629 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14630 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14631 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14632 } else {
14633 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14634 }
14635 #ifdef HAVE_PRI_INBANDDISCONNECT
14636 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14637 confp->pri.inbanddisconnect = ast_true(v->value);
14638 #endif
14639 } else if (!strcasecmp(v->name, "pritimer")) {
14640 #ifdef PRI_GETSET_TIMERS
14641 char tmp[20];
14642 char *timerc;
14643 char *c;
14644 int timer;
14645 int timeridx;
14646
14647 ast_copy_string(tmp, v->value, sizeof(tmp));
14648 c = tmp;
14649 timerc = strsep(&c, ",");
14650 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
14651 timeridx = pri_timer2idx(timerc);
14652 timer = atoi(c);
14653 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
14654 ast_log(LOG_WARNING,
14655 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
14656 v->lineno);
14657 } else if (!timer) {
14658 ast_log(LOG_WARNING,
14659 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
14660 c, timerc, v->lineno);
14661 } else {
14662 pritimers[timeridx] = timer;
14663 }
14664 } else {
14665 ast_log(LOG_WARNING,
14666 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
14667 v->value, v->lineno);
14668 }
14669 #endif
14670 } else if (!strcasecmp(v->name, "facilityenable")) {
14671 confp->pri.facilityenable = ast_true(v->value);
14672 #endif
14673
14674 #ifdef HAVE_OPENR2
14675 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
14676 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
14677 ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", mfcr2_cur_r2proto_file);
14678 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
14679 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
14680 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
14681 mfcr2_cur_variant = openr2_proto_get_variant(v->value);
14682 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
14683 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
14684 }
14685 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
14686 mfcr2_cur_mfback_timeout = atoi(v->value);
14687 if (!mfcr2_cur_mfback_timeout) {
14688 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
14689 mfcr2_cur_mfback_timeout = -1;
14690 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
14691 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
14692 }
14693 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
14694 mfcr2_cur_metering_pulse_timeout = atoi(v->value);
14695 if (mfcr2_cur_metering_pulse_timeout > 500) {
14696 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
14697 }
14698 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
14699 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
14700 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
14701 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
14702 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
14703 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
14704 mfcr2_cur_dtmf_time_on = atoi(v->value);
14705 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
14706 mfcr2_cur_dtmf_time_off = atoi(v->value);
14707 #endif
14708 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
14709 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
14710 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
14711 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
14712 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
14713 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
14714 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
14715 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
14716 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
14717 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
14718 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
14719 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
14720 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
14721 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
14722 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
14723 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
14724 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
14725 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
14726 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
14727 mfcr2_cur_max_ani = atoi(v->value);
14728 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
14729 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
14730 }
14731 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
14732 mfcr2_cur_max_dnis = atoi(v->value);
14733 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
14734 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
14735 }
14736 } else if (!strcasecmp(v->name, "mfcr2_category")) {
14737 mfcr2_cur_category = openr2_proto_get_category(v->value);
14738 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
14739 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
14740 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
14741 v->value, v->lineno);
14742 }
14743 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
14744 openr2_log_level_t tmplevel;
14745 char *toklevel = NULL;
14746 char *saveptr = NULL;
14747 char *logval = ast_strdupa(v->value);
14748 toklevel = strtok_r(logval, ",", &saveptr);
14749 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14750 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
14751 } else if (OR2_LOG_NOTHING == tmplevel) {
14752 mfcr2_cur_loglevel = tmplevel;
14753 } else {
14754 mfcr2_cur_loglevel |= tmplevel;
14755 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14756 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14757 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
14758 continue;
14759 }
14760 mfcr2_cur_loglevel |= tmplevel;
14761 }
14762 }
14763 #endif
14764
14765 } else if (!strcasecmp(v->name, "cadence")) {
14766
14767 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14768 int i;
14769 struct dahdi_ring_cadence new_cadence;
14770 int cid_location = -1;
14771 int firstcadencepos = 0;
14772 char original_args[80];
14773 int cadence_is_ok = 1;
14774
14775 ast_copy_string(original_args, v->value, sizeof(original_args));
14776
14777 element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
14778
14779
14780 if (element_count % 2 == 1) {
14781 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
14782 cadence_is_ok = 0;
14783 }
14784
14785
14786 for (i = 0; i < element_count; i++) {
14787 if (c[i] == 0) {
14788 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
14789 cadence_is_ok = 0;
14790 break;
14791 } else if (c[i] < 0) {
14792 if (i % 2 == 1) {
14793
14794 if (cid_location == -1) {
14795 cid_location = i;
14796 c[i] *= -1;
14797 } else {
14798 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
14799 cadence_is_ok = 0;
14800 break;
14801 }
14802 } else {
14803 if (firstcadencepos == 0) {
14804 firstcadencepos = i;
14805
14806 } else {
14807 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
14808 cadence_is_ok = 0;
14809 break;
14810 }
14811 }
14812 }
14813 }
14814
14815
14816 for (i = 0; i < 16; i++) {
14817 new_cadence.ringcadence[i] = c[i];
14818 }
14819
14820 if (cadence_is_ok) {
14821
14822 if (element_count < 2) {
14823 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
14824 } else {
14825 if (cid_location == -1) {
14826
14827 cid_location = 1;
14828 } else {
14829
14830 cid_location = (cid_location + 1) / 2;
14831 }
14832
14833 if (!user_has_defined_cadences++)
14834
14835 num_cadence = 0;
14836 if ((num_cadence+1) >= NUM_CADENCE_MAX)
14837 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
14838 else {
14839 cadences[num_cadence] = new_cadence;
14840 cidrings[num_cadence++] = cid_location;
14841 if (option_verbose > 2)
14842 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
14843 }
14844 }
14845 }
14846 } else if (!strcasecmp(v->name, "ringtimeout")) {
14847 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
14848 } else if (!strcasecmp(v->name, "prewink")) {
14849 confp->timing.prewinktime = atoi(v->value);
14850 } else if (!strcasecmp(v->name, "preflash")) {
14851 confp->timing.preflashtime = atoi(v->value);
14852 } else if (!strcasecmp(v->name, "wink")) {
14853 confp->timing.winktime = atoi(v->value);
14854 } else if (!strcasecmp(v->name, "flash")) {
14855 confp->timing.flashtime = atoi(v->value);
14856 } else if (!strcasecmp(v->name, "start")) {
14857 confp->timing.starttime = atoi(v->value);
14858 } else if (!strcasecmp(v->name, "rxwink")) {
14859 confp->timing.rxwinktime = atoi(v->value);
14860 } else if (!strcasecmp(v->name, "rxflash")) {
14861 confp->timing.rxflashtime = atoi(v->value);
14862 } else if (!strcasecmp(v->name, "debounce")) {
14863 confp->timing.debouncetime = atoi(v->value);
14864 } else if (!strcasecmp(v->name, "toneduration")) {
14865 int toneduration;
14866 int ctlfd;
14867 int res;
14868 struct dahdi_dialparams dps;
14869
14870 ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
14871
14872 if (ctlfd == -1) {
14873 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
14874 return -1;
14875 }
14876
14877 toneduration = atoi(v->value);
14878 if (toneduration > -1) {
14879 memset(&dps, 0, sizeof(dps));
14880
14881 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
14882 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
14883 if (res < 0) {
14884 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
14885 close(ctlfd);
14886 return -1;
14887 }
14888 }
14889 close(ctlfd);
14890 } else if (!strcasecmp(v->name, "defaultcic")) {
14891 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
14892 } else if (!strcasecmp(v->name, "defaultozz")) {
14893 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
14894 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
14895 dtmfcid_level = atoi(v->value);
14896 }
14897 } else if (!skipchannels)
14898 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
14899 }
14900 if (dahdichan[0]) {
14901
14902
14903 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
14904 return -1;
14905 }
14906 }
14907
14908
14909 if (!found_pseudo && reload != 1) {
14910
14911
14912
14913
14914 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
14915
14916 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
14917
14918 if (tmp) {
14919 if (option_verbose > 2)
14920 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
14921 } else {
14922 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
14923 }
14924 }
14925 return 0;
14926 }
14927
14928 static int setup_dahdi(int reload)
14929 {
14930 struct ast_config *cfg;
14931 struct ast_variable *v;
14932 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
14933 int res;
14934
14935 #ifdef HAVE_PRI
14936 char *c;
14937 int spanno;
14938 int i, x;
14939 int logicalspan;
14940 int trunkgroup;
14941 int dchannels[NUM_DCHANS];
14942 #endif
14943
14944 #ifdef HAVE_ZAPTEL
14945 int load_from_zapata_conf = 1;
14946 #else
14947 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
14948 #endif
14949
14950 if (load_from_zapata_conf) {
14951 if (!(cfg = ast_config_load("zapata.conf"))) {
14952 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
14953 return 0;
14954 }
14955 } else {
14956 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
14957 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
14958 return 0;
14959 }
14960 }
14961
14962
14963 ast_mutex_lock(&iflock);
14964 #ifdef HAVE_PRI
14965 if (reload != 1) {
14966
14967 v = ast_variable_browse(cfg, "trunkgroups");
14968 while (v) {
14969 if (!strcasecmp(v->name, "trunkgroup")) {
14970 trunkgroup = atoi(v->value);
14971 if (trunkgroup > 0) {
14972 if ((c = strchr(v->value, ','))) {
14973 i = 0;
14974 memset(dchannels, 0, sizeof(dchannels));
14975 while (c && (i < NUM_DCHANS)) {
14976 dchannels[i] = atoi(c + 1);
14977 if (dchannels[i] < 0) {
14978 ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14979 } else
14980 i++;
14981 c = strchr(c + 1, ',');
14982 }
14983 if (i) {
14984 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
14985 ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
14986 } else if (option_verbose > 1)
14987 ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
14988 } else
14989 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14990 } else
14991 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14992 } else
14993 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
14994 } else if (!strcasecmp(v->name, "spanmap")) {
14995 spanno = atoi(v->value);
14996 if (spanno > 0) {
14997 if ((c = strchr(v->value, ','))) {
14998 trunkgroup = atoi(c + 1);
14999 if (trunkgroup > 0) {
15000 if ((c = strchr(c + 1, ',')))
15001 logicalspan = atoi(c + 1);
15002 else
15003 logicalspan = 0;
15004 if (logicalspan >= 0) {
15005 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15006 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15007 } else if (option_verbose > 1)
15008 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15009 } else
15010 ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
15011 } else
15012 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15013 } else
15014 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15015 } else
15016 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15017 } else {
15018 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15019 }
15020 v = v->next;
15021 }
15022 }
15023 #endif
15024
15025
15026 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
15027
15028 v = ast_variable_browse(cfg, "channels");
15029 res = process_dahdi(&conf, "", v, reload, 0);
15030 ast_mutex_unlock(&iflock);
15031 ast_config_destroy(cfg);
15032 if (res)
15033 return res;
15034 cfg = ast_config_load("users.conf");
15035 if (cfg) {
15036 char *cat;
15037
15038
15039 conf = dahdi_chan_conf_default();
15040 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
15041 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15042 if (!strcasecmp(cat, "general"))
15043 continue;
15044 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
15045 struct dahdi_chan_conf sect_conf;
15046 memcpy(§_conf, &conf, sizeof(sect_conf));
15047
15048 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
15049 }
15050 }
15051 ast_config_destroy(cfg);
15052 }
15053 #ifdef HAVE_PRI
15054 if (reload != 1) {
15055 for (x = 0; x < NUM_SPANS; x++) {
15056 if (pris[x].pvts[0]) {
15057 if (start_pri(pris + x)) {
15058 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15059 return -1;
15060 } else if (option_verbose > 1)
15061 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
15062 }
15063 }
15064 }
15065 #endif
15066
15067 #ifdef HAVE_OPENR2
15068 if (reload != 1) {
15069 int x;
15070 for (x = 0; x < NUM_SPANS; x++) {
15071 if (r2links[x].protocol_context) {
15072 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
15073 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
15074 return -1;
15075 } else {
15076 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
15077 }
15078 }
15079 }
15080 }
15081 #endif
15082
15083
15084 restart_monitor();
15085 return 0;
15086 }
15087
15088 #define local_astman_register(a, b, c, d) do { \
15089 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
15090 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
15091 } \
15092 ast_manager_register("Zap" a, b, zap_ ## c, d); \
15093 } while (0)
15094
15095 static int load_module(void)
15096 {
15097 int res;
15098
15099 #ifdef HAVE_PRI
15100 int y,i;
15101 memset(pris, 0, sizeof(pris));
15102 for (y = 0; y < NUM_SPANS; y++) {
15103 ast_mutex_init(&pris[y].lock);
15104 pris[y].offset = -1;
15105 pris[y].master = AST_PTHREADT_NULL;
15106 for (i = 0; i < NUM_DCHANS; i++)
15107 pris[y].fds[i] = -1;
15108 }
15109 pri_set_error(dahdi_pri_error);
15110 pri_set_message(dahdi_pri_message);
15111 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
15112 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15113 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15114 }
15115 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
15116 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
15117 #endif
15118
15119 #ifdef HAVE_OPENR2
15120 init_mfcr2_globals();
15121 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
15122 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
15123 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
15124 }
15125 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
15126 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
15127 #endif
15128
15129 if ((res = setup_dahdi(0))) {
15130 return AST_MODULE_LOAD_DECLINE;
15131 }
15132 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
15133 chan_tech = &dahdi_tech;
15134 } else {
15135 chan_tech = &zap_tech;
15136 }
15137 if (ast_channel_register(chan_tech)) {
15138 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
15139 __unload_module();
15140 return -1;
15141 }
15142 #ifdef HAVE_PRI
15143 ast_string_field_init(&inuse, 16);
15144 ast_string_field_set(&inuse, name, "GR-303InUse");
15145 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
15146 #endif
15147
15148 #ifdef HAVE_OPENR2
15149 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
15150 #endif
15151
15152 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
15153
15154 memset(round_robin, 0, sizeof(round_robin));
15155 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
15156 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
15157 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
15158 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
15159 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
15160 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
15161 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
15162
15163 ast_cond_init(&ss_thread_complete, NULL);
15164
15165 return res;
15166 }
15167
15168 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15169 {
15170 #define END_SILENCE_LEN 400
15171 #define HEADER_MS 50
15172 #define TRAILER_MS 5
15173 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15174 #define ASCII_BYTES_PER_CHAR 80
15175
15176 unsigned char *buf,*mybuf;
15177 struct dahdi_pvt *p = c->tech_pvt;
15178 struct pollfd fds[1];
15179 int size,res,fd,len,x;
15180 int bytes=0;
15181
15182 float cr = 1.0;
15183 float ci = 0.0;
15184 float scont = 0.0;
15185 int index;
15186
15187 index = dahdi_get_index(c, p, 0);
15188 if (index < 0) {
15189 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
15190 return -1;
15191 }
15192 if (!text[0]) return(0);
15193 if ((!p->tdd) && (!p->mate)) return(0);
15194 if (p->mate)
15195 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15196 else
15197 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15198 if (!buf)
15199 return -1;
15200 mybuf = buf;
15201 if (p->mate) {
15202 int codec = AST_LAW(p);
15203 for (x = 0; x < HEADER_MS; x++) {
15204 PUT_CLID_MARKMS;
15205 }
15206
15207 for (x = 0; text[x]; x++) {
15208 PUT_CLID(text[x]);
15209 }
15210 for (x = 0; x < TRAILER_MS; x++) {
15211 PUT_CLID_MARKMS;
15212 }
15213 len = bytes;
15214 buf = mybuf;
15215 } else {
15216 len = tdd_generate(p->tdd, buf, text);
15217 if (len < 1) {
15218 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15219 free(mybuf);
15220 return -1;
15221 }
15222 }
15223 memset(buf + len, 0x7f, END_SILENCE_LEN);
15224 len += END_SILENCE_LEN;
15225 fd = p->subs[index].dfd;
15226 while (len) {
15227 if (ast_check_hangup(c)) {
15228 free(mybuf);
15229 return -1;
15230 }
15231 size = len;
15232 if (size > READ_SIZE)
15233 size = READ_SIZE;
15234 fds[0].fd = fd;
15235 fds[0].events = POLLOUT | POLLPRI;
15236 fds[0].revents = 0;
15237 res = poll(fds, 1, -1);
15238 if (!res) {
15239 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
15240 continue;
15241 }
15242
15243 if (fds[0].revents & POLLPRI) {
15244 ast_free(mybuf);
15245 return -1;
15246 }
15247 if (!(fds[0].revents & POLLOUT)) {
15248 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
15249 continue;
15250 }
15251 res = write(fd, buf, size);
15252 if (res != size) {
15253 if (res == -1) {
15254 free(mybuf);
15255 return -1;
15256 }
15257 if (option_debug)
15258 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15259 break;
15260 }
15261 len -= size;
15262 buf += size;
15263 }
15264 free(mybuf);
15265 return(0);
15266 }
15267
15268
15269 static int reload(void)
15270 {
15271 int res = 0;
15272
15273 res = setup_dahdi(1);
15274 if (res) {
15275 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15276 return -1;
15277 }
15278 return 0;
15279 }
15280
15281
15282
15283
15284
15285 #ifdef HAVE_PRI
15286 #define tdesc "DAHDI Telephony w/PRI"
15287 #else
15288 #define tdesc "DAHDI Telephony"
15289 #endif
15290
15291 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15292 .load = load_module,
15293 .unload = unload_module,
15294 .reload = reload,
15295 );
15296
15297