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: 227275 $")
00052
00053 #include <stdio.h>
00054 #include <string.h>
00055 #ifdef __NetBSD__
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
00147
00148
00149
00150
00151
00152 #define DEFAULT_CIDRINGS 1
00153
00154 #define CHANNEL_PSEUDO -12
00155
00156 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00157
00158
00159 #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))
00160
00161 static const char tdesc[] = "DAHDI Telephony Driver"
00162 #ifdef HAVE_PRI
00163 " w/PRI"
00164 #endif
00165 #ifdef HAVE_OPENR2
00166 " w/OPENR2"
00167 #endif
00168 ;
00169
00170 #define SIG_EM DAHDI_SIG_EM
00171 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00173 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00174 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00175 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00176 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00177 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00178 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00179 #define SIG_FXSLS DAHDI_SIG_FXSLS
00180 #define SIG_FXSGS DAHDI_SIG_FXSGS
00181 #define SIG_FXSKS DAHDI_SIG_FXSKS
00182 #define SIG_FXOLS DAHDI_SIG_FXOLS
00183 #define SIG_FXOGS DAHDI_SIG_FXOGS
00184 #define SIG_FXOKS DAHDI_SIG_FXOKS
00185 #define SIG_PRI DAHDI_SIG_CLEAR
00186 #define SIG_MFCR2 DAHDI_SIG_CAS
00187 #define SIG_SF DAHDI_SIG_SF
00188 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00189 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00190 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00191 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00192 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00193 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00194 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00195
00196 #define NUM_SPANS 32
00197 #define NUM_DCHANS 4
00198 #define MAX_CHANNELS 672
00199
00200 #define CHAN_PSEUDO -2
00201
00202 #define DCHAN_PROVISIONED (1 << 0)
00203 #define DCHAN_NOTINALARM (1 << 1)
00204 #define DCHAN_UP (1 << 2)
00205
00206 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00207
00208
00209 #define DAHDI_OVERLAPDIAL_NONE 0
00210 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00211 #define DAHDI_OVERLAPDIAL_INCOMING 2
00212 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00213
00214 static char defaultcic[64] = "";
00215 static char defaultozz[64] = "";
00216
00217 static char progzone[10] = "";
00218
00219 static int distinctiveringaftercid = 0;
00220
00221 static int numbufs = 4;
00222
00223 #ifdef HAVE_PRI
00224 static struct ast_channel inuse;
00225 #ifdef PRI_GETSET_TIMERS
00226 static int pritimers[PRI_MAX_TIMERS];
00227 #endif
00228 static int pridebugfd = -1;
00229 static char pridebugfilename[1024] = "";
00230 #endif
00231
00232
00233 static int firstdigittimeout = 16000;
00234
00235
00236 static int gendigittimeout = 8000;
00237
00238
00239 static int matchdigittimeout = 3000;
00240
00241
00242 AST_MUTEX_DEFINE_STATIC(iflock);
00243
00244
00245 static int ifcount = 0;
00246
00247 #ifdef HAVE_PRI
00248 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00249 #endif
00250
00251
00252
00253 AST_MUTEX_DEFINE_STATIC(monlock);
00254
00255
00256
00257 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00258 static ast_cond_t ss_thread_complete;
00259 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00260 AST_MUTEX_DEFINE_STATIC(restart_lock);
00261 static int ss_thread_count = 0;
00262 static int num_restart_pending = 0;
00263
00264 static int restart_monitor(void);
00265
00266 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);
00267
00268 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00269
00270
00271 static inline int dahdi_get_event(int fd)
00272 {
00273 int j;
00274 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00275 return -1;
00276 return j;
00277 }
00278
00279
00280 static inline int dahdi_wait_event(int fd)
00281 {
00282 int i, j = 0;
00283 i = DAHDI_IOMUX_SIGEVENT;
00284 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00285 return -1;
00286 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00287 return -1;
00288 return j;
00289 }
00290
00291
00292 #define READ_SIZE 160
00293
00294 #define MASK_AVAIL (1 << 0)
00295 #define MASK_INUSE (1 << 1)
00296
00297 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00298 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00299 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00300 #define MIN_MS_SINCE_FLASH ( (2000) )
00301 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00302
00303 struct dahdi_pvt;
00304
00305
00306
00307
00308
00309 static int ringt_base = DEFAULT_RINGT;
00310
00311 #ifdef HAVE_OPENR2
00312
00313 struct dahdi_mfcr2 {
00314 pthread_t master;
00315 openr2_context_t *protocol_context;
00316 struct dahdi_pvt *pvts[MAX_CHANNELS];
00317 int numchans;
00318 };
00319
00320 static struct dahdi_mfcr2 r2links[NUM_SPANS];
00321 static openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN;
00322 static int mfcr2_cur_mfback_timeout = -1;
00323 static int mfcr2_cur_metering_pulse_timeout = -1;
00324 static int mfcr2_cur_max_ani = 10;
00325 static int mfcr2_cur_max_dnis = 4;
00326 static int mfcr2_cur_get_ani_first = -1;
00327 static int mfcr2_cur_skip_category = -1;
00328 static int mfcr2_cur_context_index = 0;
00329 static int mfcr2_cur_call_files = 0;
00330 static int mfcr2_cur_allow_collect_calls = 0;
00331 static int mfcr2_cur_accept_on_offer = 1;
00332 static int mfcr2_cur_charge_calls = 1;
00333 static int mfcr2_cur_forced_release = 0;
00334 static int mfcr2_cur_double_answer = 0;
00335 static int mfcr2_cur_immediate_accept = -1;
00336
00337 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00338 static int mfcr2_cur_dtmf_dialing = -1;
00339 static int mfcr2_cur_dtmf_detection = -1;
00340 static int mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
00341 static int mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
00342 #endif
00343 static char mfcr2_cur_logdir[OR2_MAX_PATH];
00344 static char mfcr2_cur_r2proto_file[OR2_MAX_PATH];
00345 static openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
00346 static openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
00347
00348 #endif
00349
00350 #ifdef HAVE_PRI
00351
00352 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00353 #define PRI_CHANNEL(p) ((p) & 0xff)
00354 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00355 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00356
00357 struct dahdi_pri {
00358 pthread_t master;
00359 ast_mutex_t lock;
00360 char idleext[AST_MAX_EXTENSION];
00361 char idlecontext[AST_MAX_CONTEXT];
00362 char idledial[AST_MAX_EXTENSION];
00363 int minunused;
00364 int minidle;
00365 int nodetype;
00366 int switchtype;
00367 int nsf;
00368 int dialplan;
00369 int localdialplan;
00370 char internationalprefix[10];
00371 char nationalprefix[10];
00372 char localprefix[20];
00373 char privateprefix[20];
00374 char unknownprefix[20];
00375 int dchannels[NUM_DCHANS];
00376 int trunkgroup;
00377 int mastertrunkgroup;
00378 int prilogicalspan;
00379 int numchans;
00380 int overlapdial;
00381 int facilityenable;
00382 struct pri *dchans[NUM_DCHANS];
00383 int dchanavail[NUM_DCHANS];
00384 struct pri *pri;
00385
00386 int debug;
00387 int fds[NUM_DCHANS];
00388
00389 int offset;
00390
00391 int span;
00392
00393 int resetting;
00394
00395 int resetpos;
00396 #ifdef HAVE_PRI_INBANDDISCONNECT
00397 unsigned int inbanddisconnect:1;
00398 #endif
00399 time_t lastreset;
00400 long resetinterval;
00401 struct dahdi_pvt *pvts[MAX_CHANNELS];
00402 struct dahdi_pvt *crvs;
00403 struct dahdi_pvt *crvend;
00404 };
00405
00406
00407 static struct dahdi_pri pris[NUM_SPANS];
00408
00409 #if 0
00410 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00411 #else
00412 #define DEFAULT_PRI_DEBUG 0
00413 #endif
00414
00415 static inline void pri_rel(struct dahdi_pri *pri)
00416 {
00417 ast_mutex_unlock(&pri->lock);
00418 }
00419
00420 #else
00421
00422 struct dahdi_pri;
00423 #endif
00424
00425 #define SUB_REAL 0
00426 #define SUB_CALLWAIT 1
00427 #define SUB_THREEWAY 2
00428
00429
00430 #define POLARITY_IDLE 0
00431 #define POLARITY_REV 1
00432
00433
00434 static struct dahdi_distRings drings;
00435
00436 struct distRingData {
00437 int ring[3];
00438 };
00439 struct ringContextData {
00440 char contextData[AST_MAX_CONTEXT];
00441 };
00442 struct dahdi_distRings {
00443 struct distRingData ringnum[3];
00444 struct ringContextData ringContext[3];
00445 };
00446
00447 static char *subnames[] = {
00448 "Real",
00449 "Callwait",
00450 "Threeway"
00451 };
00452
00453 struct dahdi_subchannel {
00454 int dfd;
00455 struct ast_channel *owner;
00456 int chan;
00457 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00458 struct ast_frame f;
00459 unsigned int needringing:1;
00460 unsigned int needbusy:1;
00461 unsigned int needcongestion:1;
00462 unsigned int needcallerid:1;
00463 unsigned int needanswer:1;
00464 unsigned int needflash:1;
00465 unsigned int needhold:1;
00466 unsigned int needunhold:1;
00467 unsigned int linear:1;
00468 unsigned int inthreeway:1;
00469 struct dahdi_confinfo curconf;
00470 };
00471
00472 #define CONF_USER_REAL (1 << 0)
00473 #define CONF_USER_THIRDCALL (1 << 1)
00474
00475 #define MAX_SLAVES 4
00476
00477 static struct dahdi_pvt {
00478 ast_mutex_t lock;
00479 struct ast_channel *owner;
00480
00481
00482 struct dahdi_subchannel sub_unused;
00483 struct dahdi_subchannel subs[3];
00484 struct dahdi_confinfo saveconf;
00485
00486 struct dahdi_pvt *slaves[MAX_SLAVES];
00487 struct dahdi_pvt *master;
00488 int inconference;
00489
00490 int buf_no;
00491 int buf_policy;
00492 int sig;
00493
00494
00495
00496
00497 int radio;
00498 int outsigmod;
00499 int oprmode;
00500 struct dahdi_pvt *oprpeer;
00501
00502 float rxgain;
00503
00504 float txgain;
00505 int tonezone;
00506 struct dahdi_pvt *next;
00507 struct dahdi_pvt *prev;
00508
00509
00510
00511
00512
00513
00514
00515 unsigned int adsi:1;
00516
00517
00518
00519
00520
00521 unsigned int answeronpolarityswitch:1;
00522
00523
00524
00525
00526
00527 unsigned int busydetect:1;
00528
00529
00530
00531
00532
00533 unsigned int callreturn:1;
00534
00535
00536
00537
00538
00539
00540 unsigned int callwaiting:1;
00541
00542
00543
00544
00545 unsigned int callwaitingcallerid:1;
00546
00547
00548
00549
00550
00551
00552 unsigned int cancallforward:1;
00553
00554
00555
00556
00557 unsigned int canpark:1;
00558
00559 unsigned int confirmanswer:1;
00560
00561
00562
00563
00564 unsigned int destroy:1;
00565 unsigned int didtdd:1;
00566
00567 unsigned int dialednone:1;
00568
00569 unsigned int dialing:1;
00570
00571 unsigned int digital:1;
00572
00573 unsigned int dnd:1;
00574
00575 unsigned int echobreak:1;
00576
00577
00578
00579
00580
00581 unsigned int echocanbridged:1;
00582
00583 unsigned int echocanon:1;
00584
00585 unsigned int faxhandled:1;
00586
00587 unsigned int firstradio:1;
00588
00589
00590
00591
00592 unsigned int hanguponpolarityswitch:1;
00593
00594 unsigned int hardwaredtmf:1;
00595
00596
00597
00598
00599
00600
00601 unsigned int hidecallerid:1;
00602
00603
00604
00605
00606
00607 unsigned int hidecalleridname:1;
00608
00609 unsigned int ignoredtmf:1;
00610
00611
00612
00613
00614
00615 unsigned int immediate:1;
00616
00617 unsigned int inalarm:1;
00618 unsigned int unknown_alarm:1;
00619
00620 unsigned int mate:1;
00621
00622 unsigned int outgoing:1;
00623
00624
00625
00626
00627
00628
00629 unsigned int permcallwaiting:1;
00630
00631
00632
00633
00634 unsigned int permhidecallerid:1;
00635
00636
00637
00638
00639 unsigned int priindication_oob:1;
00640
00641
00642
00643
00644 unsigned int priexclusive:1;
00645
00646
00647
00648
00649 unsigned int pulse:1;
00650
00651 unsigned int pulsedial:1;
00652 unsigned int restartpending:1;
00653
00654
00655
00656
00657
00658 unsigned int restrictcid:1;
00659
00660
00661
00662
00663 unsigned int threewaycalling:1;
00664
00665
00666
00667
00668
00669
00670
00671
00672 unsigned int transfer:1;
00673
00674
00675
00676
00677
00678
00679
00680 unsigned int use_callerid:1;
00681
00682
00683
00684
00685
00686
00687 unsigned int use_callingpres:1;
00688
00689
00690
00691
00692
00693 unsigned int usedistinctiveringdetection:1;
00694
00695
00696
00697
00698 unsigned int dahditrcallerid:1;
00699
00700
00701
00702
00703 unsigned int transfertobusy:1;
00704 #if defined(HAVE_PRI)
00705
00706 unsigned int alerting:1;
00707
00708 unsigned int alreadyhungup:1;
00709
00710
00711
00712
00713 unsigned int isidlecall:1;
00714
00715
00716
00717
00718 unsigned int proceeding:1;
00719
00720 unsigned int progress:1;
00721
00722
00723
00724
00725 unsigned int resetting:1;
00726
00727
00728
00729
00730 unsigned int setup_ack:1;
00731 #endif
00732
00733
00734
00735
00736 unsigned int use_smdi:1;
00737
00738 struct ast_smdi_interface *smdi_iface;
00739
00740
00741 struct dahdi_distRings drings;
00742
00743
00744
00745
00746
00747 char context[AST_MAX_CONTEXT];
00748
00749
00750
00751 char defcontext[AST_MAX_CONTEXT];
00752
00753 char exten[AST_MAX_EXTENSION];
00754
00755
00756
00757
00758 char language[MAX_LANGUAGE];
00759
00760
00761
00762
00763 char mohinterpret[MAX_MUSICCLASS];
00764
00765
00766
00767
00768 char mohsuggest[MAX_MUSICCLASS];
00769 #ifdef PRI_ANI
00770
00771 char cid_ani[AST_MAX_EXTENSION];
00772 #endif
00773
00774 char cid_num[AST_MAX_EXTENSION];
00775
00776 int cid_ton;
00777
00778 char cid_name[AST_MAX_EXTENSION];
00779
00780 char lastcid_num[AST_MAX_EXTENSION];
00781
00782 char lastcid_name[AST_MAX_EXTENSION];
00783 char *origcid_num;
00784 char *origcid_name;
00785
00786 char callwait_num[AST_MAX_EXTENSION];
00787
00788 char callwait_name[AST_MAX_EXTENSION];
00789
00790 char rdnis[AST_MAX_EXTENSION];
00791
00792 char dnid[AST_MAX_EXTENSION];
00793
00794
00795
00796
00797 ast_group_t group;
00798
00799 int law;
00800 int confno;
00801 int confusers;
00802 int propconfno;
00803
00804
00805
00806
00807 ast_group_t callgroup;
00808
00809
00810
00811
00812 ast_group_t pickupgroup;
00813 int channel;
00814 int span;
00815 time_t guardtime;
00816 int cid_signalling;
00817 int cid_start;
00818 int callingpres;
00819 int callwaitingrepeat;
00820 int cidcwexpire;
00821
00822 unsigned char *cidspill;
00823
00824 int cidpos;
00825
00826 int cidlen;
00827
00828 int ringt;
00829
00830
00831
00832
00833 int ringt_base;
00834
00835
00836
00837
00838
00839
00840 int stripmsd;
00841
00842 int callwaitcas;
00843
00844 int callwaitrings;
00845
00846 int echocancel;
00847
00848
00849
00850
00851 int echotraining;
00852
00853 char echorest[20];
00854
00855
00856
00857
00858 int busycount;
00859
00860
00861
00862
00863 int busycompare;
00864
00865
00866
00867
00868 int busytonelength;
00869
00870
00871
00872
00873 int busyquietlength;
00874
00875
00876
00877
00878 int busyfuzziness;
00879
00880
00881
00882
00883 int silencethreshold;
00884
00885
00886
00887
00888 int callprogress;
00889 struct timeval flashtime;
00890
00891 struct ast_dsp *dsp;
00892
00893
00894 struct dahdi_dialoperation dop;
00895 int whichwink;
00896
00897 char finaldial[64];
00898 char accountcode[AST_MAX_ACCOUNT_CODE];
00899 int amaflags;
00900 struct tdd_state *tdd;
00901
00902 char call_forward[AST_MAX_EXTENSION];
00903
00904
00905
00906
00907 char mailbox[AST_MAX_EXTENSION];
00908
00909 char dialdest[256];
00910
00911 int onhooktime;
00912
00913 int msgstate;
00914 int distinctivering;
00915 int cidrings;
00916 int dtmfrelax;
00917
00918 int fake_event;
00919
00920
00921
00922
00923 int polarityonanswerdelay;
00924
00925 struct timeval polaritydelaytv;
00926
00927
00928
00929
00930 int sendcalleridafter;
00931 #ifdef HAVE_PRI
00932
00933 struct dahdi_pri *pri;
00934
00935 struct dahdi_pvt *bearer;
00936
00937 struct dahdi_pvt *realcall;
00938
00939 q931_call *call;
00940
00941 int prioffset;
00942
00943 int logicalspan;
00944 #endif
00945 #ifdef HAVE_OPENR2
00946 int mfcr2call;
00947 int mfcr2block;
00948 struct dahdi_mfcr2 *mfcr2;
00949 openr2_chan_t *r2chan;
00950 openr2_calling_party_category_t mfcr2_recvd_category;
00951 openr2_calling_party_category_t mfcr2_category;
00952 int mfcr2_accept_on_offer;
00953 int mfcr2_charge_calls;
00954 int mfcr2_allow_collect_calls;
00955 int mfcr2_forced_release;
00956 int mfcr2_dnis_index;
00957 int mfcr2_ani_index;
00958 int mfcr2_dnis_matched;
00959 int mfcr2_call_accepted;
00960 #endif
00961
00962 int polarity;
00963
00964 int dsp_features;
00965
00966 char begindigit;
00967 } *iflist = NULL, *ifend = NULL;
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 struct dahdi_chan_conf {
00980 struct dahdi_pvt chan;
00981 #ifdef HAVE_PRI
00982 struct dahdi_pri pri;
00983 #endif
00984 struct dahdi_params timing;
00985
00986
00987
00988
00989
00990 char smdi_port[SMDI_MAX_FILENAME_LEN];
00991 };
00992
00993
00994 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
00995
00996
00997
00998 struct dahdi_chan_conf conf = {
00999 #ifdef HAVE_PRI
01000 .pri = {
01001 .nsf = PRI_NSF_NONE,
01002 .switchtype = PRI_SWITCH_NI2,
01003 .dialplan = PRI_NATIONAL_ISDN + 1,
01004 .localdialplan = PRI_NATIONAL_ISDN + 1,
01005 .nodetype = PRI_CPE,
01006
01007 .minunused = 2,
01008 .idleext = "",
01009 .idledial = "",
01010 .internationalprefix = "",
01011 .nationalprefix = "",
01012 .localprefix = "",
01013 .privateprefix = "",
01014 .unknownprefix = "",
01015
01016 .resetinterval = 3600
01017 },
01018 #endif
01019 .chan = {
01020 .context = "default",
01021 .cid_num = "",
01022 .cid_name = "",
01023 .mohinterpret = "default",
01024 .mohsuggest = "",
01025 .transfertobusy = 1,
01026
01027 .cid_signalling = CID_SIG_BELL,
01028 .cid_start = CID_START_RING,
01029 .dahditrcallerid = 0,
01030 .use_callerid = 1,
01031 .sig = -1,
01032 .outsigmod = -1,
01033
01034 .tonezone = -1,
01035
01036 .echocancel = 1,
01037
01038 .busycount = 3,
01039 .busycompare = 0,
01040 .busytonelength = 0,
01041 .busyquietlength = 0,
01042 .busyfuzziness = 0,
01043 .silencethreshold = 0,
01044
01045 .accountcode = "",
01046
01047 .mailbox = "",
01048
01049
01050 .polarityonanswerdelay = 600,
01051
01052 .sendcalleridafter = DEFAULT_CIDRINGS,
01053
01054 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01055 .buf_no = numbufs
01056 },
01057 .timing = {
01058 .prewinktime = -1,
01059 .preflashtime = -1,
01060 .winktime = -1,
01061 .flashtime = -1,
01062 .starttime = -1,
01063 .rxwinktime = -1,
01064 .rxflashtime = -1,
01065 .debouncetime = -1
01066 },
01067 .smdi_port = "/dev/ttyS0",
01068 };
01069
01070 return conf;
01071 }
01072
01073
01074 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01075 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01076 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01077 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01078 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01079 static int dahdi_hangup(struct ast_channel *ast);
01080 static int dahdi_answer(struct ast_channel *ast);
01081 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01082 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01083 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01084 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01085 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01086 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01087 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
01088
01089 static const struct ast_channel_tech dahdi_tech = {
01090 .type = "DAHDI",
01091 .description = tdesc,
01092 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01093 .requester = dahdi_request,
01094 .send_digit_begin = dahdi_digit_begin,
01095 .send_digit_end = dahdi_digit_end,
01096 .send_text = dahdi_sendtext,
01097 .call = dahdi_call,
01098 .hangup = dahdi_hangup,
01099 .answer = dahdi_answer,
01100 .read = dahdi_read,
01101 .write = dahdi_write,
01102 .bridge = dahdi_bridge,
01103 .exception = dahdi_exception,
01104 .indicate = dahdi_indicate,
01105 .fixup = dahdi_fixup,
01106 .setoption = dahdi_setoption,
01107 .func_channel_read = dahdi_func_read,
01108 };
01109
01110 static const struct ast_channel_tech zap_tech = {
01111 .type = "Zap",
01112 .description = tdesc,
01113 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01114 .requester = dahdi_request,
01115 .send_digit_begin = dahdi_digit_begin,
01116 .send_digit_end = dahdi_digit_end,
01117 .send_text = dahdi_sendtext,
01118 .call = dahdi_call,
01119 .hangup = dahdi_hangup,
01120 .answer = dahdi_answer,
01121 .read = dahdi_read,
01122 .write = dahdi_write,
01123 .bridge = dahdi_bridge,
01124 .exception = dahdi_exception,
01125 .indicate = dahdi_indicate,
01126 .fixup = dahdi_fixup,
01127 .setoption = dahdi_setoption,
01128 .func_channel_read = dahdi_func_read,
01129 };
01130
01131 static const struct ast_channel_tech *chan_tech;
01132
01133 #ifdef HAVE_PRI
01134 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01135 #else
01136 #define GET_CHANNEL(p) ((p)->channel)
01137 #endif
01138
01139 struct dahdi_pvt *round_robin[32];
01140
01141 #ifdef HAVE_PRI
01142 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01143 {
01144 int res;
01145
01146 do {
01147 res = ast_mutex_trylock(&pri->lock);
01148 if (res) {
01149 DEADLOCK_AVOIDANCE(&pvt->lock);
01150 }
01151 } while (res);
01152
01153 if (pri->master != AST_PTHREADT_NULL)
01154 pthread_kill(pri->master, SIGURG);
01155 return 0;
01156 }
01157 #endif
01158
01159 #define NUM_CADENCE_MAX 25
01160 static int num_cadence = 4;
01161 static int user_has_defined_cadences = 0;
01162
01163 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01164 { { 125, 125, 2000, 4000 } },
01165 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01166 { { 125, 125, 125, 125, 125, 4000 } },
01167 { { 1000, 500, 2500, 5000 } },
01168 };
01169
01170
01171
01172
01173
01174 static int cidrings[NUM_CADENCE_MAX] = {
01175 2,
01176 4,
01177 3,
01178 2,
01179 };
01180
01181 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01182 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01183
01184 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01185 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01186
01187 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01188 {
01189 int res;
01190 if (p->subs[SUB_REAL].owner == ast)
01191 res = 0;
01192 else if (p->subs[SUB_CALLWAIT].owner == ast)
01193 res = 1;
01194 else if (p->subs[SUB_THREEWAY].owner == ast)
01195 res = 2;
01196 else {
01197 res = -1;
01198 if (!nullok)
01199 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01200 }
01201 return res;
01202 }
01203
01204 #ifdef HAVE_PRI
01205 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01206 #else
01207 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01208 #endif
01209 {
01210 #ifdef HAVE_PRI
01211 if (pri)
01212 ast_mutex_unlock(&pri->lock);
01213 #endif
01214 for (;;) {
01215 if (p->subs[a].owner) {
01216 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
01217 DEADLOCK_AVOIDANCE(&p->lock);
01218 } else {
01219 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01220 ast_mutex_unlock(&p->subs[a].owner->lock);
01221 break;
01222 }
01223 } else
01224 break;
01225 }
01226 #ifdef HAVE_PRI
01227 if (pri)
01228 ast_mutex_lock(&pri->lock);
01229 #endif
01230 }
01231
01232 #ifdef HAVE_PRI
01233 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
01234 #else
01235 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
01236 #endif
01237 {
01238
01239 #ifdef HAVE_PRI
01240 if (pri)
01241 ast_mutex_unlock(&pri->lock);
01242 #endif
01243 for (;;) {
01244 if (p->owner) {
01245 if (ast_mutex_trylock(&p->owner->lock)) {
01246 DEADLOCK_AVOIDANCE(&p->lock);
01247 } else {
01248 ast_queue_frame(p->owner, f);
01249 ast_mutex_unlock(&p->owner->lock);
01250 break;
01251 }
01252 } else
01253 break;
01254 }
01255 #ifdef HAVE_PRI
01256 if (pri)
01257 ast_mutex_lock(&pri->lock);
01258 #endif
01259 }
01260
01261 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability);
01262 #ifdef HAVE_OPENR2
01263 static void init_mfcr2_globals(void)
01264 {
01265 int r;
01266 mfcr2_cur_context_index = 0;
01267 mfcr2_cur_variant = OR2_VAR_UNKNOWN;
01268 mfcr2_cur_mfback_timeout = -1;
01269 mfcr2_cur_metering_pulse_timeout = -1;
01270 mfcr2_cur_max_ani = 10;
01271 mfcr2_cur_max_dnis = 4;
01272 mfcr2_cur_get_ani_first = -1;
01273 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01274 mfcr2_cur_dtmf_dialing = -1;
01275 mfcr2_cur_dtmf_detection = -1;
01276 mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
01277 mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
01278 #endif
01279 mfcr2_cur_skip_category = -1;
01280 mfcr2_cur_call_files = 0;
01281 mfcr2_cur_allow_collect_calls = 0;
01282 mfcr2_cur_forced_release = 0;
01283 mfcr2_cur_double_answer = 0;
01284 mfcr2_cur_immediate_accept = -1;
01285 mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
01286 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
01287 memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir));
01288 memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file));
01289 memset(r2links, 0, sizeof(r2links));
01290 for (r = 0; r < NUM_SPANS; r++) {
01291 r2links[r].master = AST_PTHREADT_NULL;
01292 }
01293 }
01294
01295 static int dahdi_r2_answer(struct dahdi_pvt *p)
01296 {
01297 int res = 0;
01298
01299
01300
01301 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01302 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01303 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01304 if (!double_answer) {
01305
01306
01307 res = openr2_chan_answer_call(p->r2chan);
01308 } else if (wants_double_answer) {
01309 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01310 } else {
01311 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01312 }
01313 #else
01314 res = openr2_chan_answer_call(p->r2chan);
01315 #endif
01316 return res;
01317 }
01318
01319 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01320 {
01321 openr2_calling_party_category_t cat;
01322 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01323 struct dahdi_pvt *p = c->tech_pvt;
01324 if (ast_strlen_zero(catstr)) {
01325 ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n",
01326 c->name, openr2_proto_get_category_string(p->mfcr2_category));
01327 return p->mfcr2_category;
01328 }
01329 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01330 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01331 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01332 return p->mfcr2_category;
01333 }
01334 ast_log(LOG_DEBUG, "Using category %s\n", catstr);
01335 return cat;
01336 }
01337
01338 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01339 {
01340 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01341 ast_mutex_lock(&p->lock);
01342 if (p->mfcr2call) {
01343 ast_mutex_unlock(&p->lock);
01344
01345
01346
01347
01348
01349 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01350 return;
01351 }
01352 p->mfcr2call = 1;
01353
01354 p->cid_name[0] = 0;
01355 p->cid_num[0] = 0;
01356 p->rdnis[0] = 0;
01357 p->exten[0] = 0;
01358 p->mfcr2_ani_index = 0;
01359 p->mfcr2_dnis_index = 0;
01360 p->mfcr2_dnis_matched = 0;
01361 p->mfcr2_call_accepted = 0;
01362 ast_mutex_unlock(&p->lock);
01363 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01364 }
01365
01366 static void handle_alarms(struct dahdi_pvt *p, int alarms);
01367 static int get_alarms(struct dahdi_pvt *p);
01368 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01369 {
01370 int res;
01371 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01372 ast_mutex_lock(&p->lock);
01373 p->inalarm = alarm ? 1 : 0;
01374 if (p->inalarm) {
01375 res = get_alarms(p);
01376
01377 handle_alarms(p, res);
01378 } else {
01379 if (!p->unknown_alarm) {
01380 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01381 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01382 } else {
01383 p->unknown_alarm = 0;
01384 }
01385 }
01386 ast_mutex_unlock(&p->lock);
01387 ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan));
01388 }
01389
01390 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01391 {
01392 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01393 }
01394
01395 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01396 {
01397 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01398 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01399 if (p->owner) {
01400 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01401 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01402 }
01403 ast_mutex_lock(&p->lock);
01404 p->mfcr2call = 0;
01405 ast_mutex_unlock(&p->lock);
01406 }
01407
01408 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01409 {
01410 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01411 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01412 p->channel, openr2_proto_get_disconnect_string(cause));
01413
01414 openr2_chan_set_idle(p->r2chan);
01415 ast_mutex_lock(&p->lock);
01416 p->mfcr2call = 0;
01417 ast_mutex_unlock(&p->lock);
01418 }
01419 }
01420
01421 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01422 {
01423 struct dahdi_pvt *p;
01424 struct ast_channel *c;
01425 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01426 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category));
01427 p = openr2_chan_get_client_data(r2chan);
01428 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01429 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel);
01430 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01431 return;
01432 }
01433 ast_mutex_lock(&p->lock);
01434 p->mfcr2_recvd_category = category;
01435
01436 if (!p->use_callerid) {
01437 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01438 p->cid_num[0] = 0;
01439 p->cid_name[0] = 0;
01440 }
01441
01442 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01443 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01444 p->exten[0] = 's';
01445 p->exten[1] = 0;
01446 }
01447 ast_mutex_unlock(&p->lock);
01448 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01449 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01450 p->channel, p->exten, p->context);
01451 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01452 } else {
01453
01454 if (!p->mfcr2_accept_on_offer) {
01455 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01456 if (!c) {
01457 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01458 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01459 }
01460
01461
01462 } else if (p->mfcr2_charge_calls) {
01463 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel);
01464 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01465 } else {
01466 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel);
01467 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01468 }
01469 }
01470 }
01471
01472 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01473 {
01474 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01475 ast_verbose("MFC/R2 call end on chan %d\n", p->channel);
01476 ast_mutex_lock(&p->lock);
01477 p->mfcr2call = 0;
01478 ast_mutex_unlock(&p->lock);
01479 }
01480
01481 static void dahdi_enable_ec(struct dahdi_pvt *p);
01482 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01483 {
01484 struct dahdi_pvt *p = NULL;
01485 struct ast_channel *c = NULL;
01486 p = openr2_chan_get_client_data(r2chan);
01487 dahdi_enable_ec(p);
01488 p->mfcr2_call_accepted = 1;
01489 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01490 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01491
01492
01493
01494
01495 if (!p->mfcr2_accept_on_offer) {
01496 openr2_chan_disable_read(r2chan);
01497 ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01498 dahdi_r2_answer(p);
01499 return;
01500 }
01501 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01502 if (c) {
01503
01504 openr2_chan_disable_read(r2chan);
01505 } else {
01506 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01507 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01508 return;
01509 }
01510 } else {
01511 ast_verbose("Call accepted on forward channel %d\n", p->channel);
01512 p->subs[SUB_REAL].needringing = 1;
01513 p->dialing = 0;
01514
01515 openr2_chan_disable_read(r2chan);
01516 }
01517 }
01518
01519 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01520 {
01521 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01522 ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan));
01523 p->subs[SUB_REAL].needanswer = 1;
01524 }
01525
01526 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01527 {
01528
01529 }
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01553 {
01554 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01555 ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan));
01556 ast_mutex_lock(&p->lock);
01557 if (p->owner) {
01558
01559
01560 if (p->owner->_state == AST_STATE_UP) {
01561 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01562 ast_mutex_unlock(&p->lock);
01563 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01564
01565 switch (cause) {
01566 case OR2_CAUSE_BUSY_NUMBER:
01567 p->owner->hangupcause = AST_CAUSE_BUSY;
01568 p->subs[SUB_REAL].needbusy = 1;
01569 break;
01570 case OR2_CAUSE_NUMBER_CHANGED:
01571 p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED;
01572 p->subs[SUB_REAL].needcongestion = 1;
01573 break;
01574 case OR2_CAUSE_NETWORK_CONGESTION:
01575 p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
01576 p->subs[SUB_REAL].needcongestion = 1;
01577 break;
01578 case OR2_CAUSE_OUT_OF_ORDER:
01579 p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01580 p->subs[SUB_REAL].needcongestion = 1;
01581 break;
01582 case OR2_CAUSE_UNALLOCATED_NUMBER:
01583 p->owner->hangupcause = AST_CAUSE_UNALLOCATED;
01584 p->subs[SUB_REAL].needcongestion = 1;
01585 break;
01586 case OR2_CAUSE_NO_ANSWER:
01587 p->owner->hangupcause = AST_CAUSE_NO_ANSWER;
01588 p->subs[SUB_REAL].needcongestion = 1;
01589 break;
01590 case OR2_CAUSE_UNSPECIFIED:
01591 p->owner->hangupcause = AST_CAUSE_NOTDEFINED;
01592 p->subs[SUB_REAL].needcongestion = 1;
01593 break;
01594 case OR2_CAUSE_NORMAL_CLEARING:
01595 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01596 p->subs[SUB_REAL].needcongestion = 1;
01597 break;
01598 default:
01599 ast_log(LOG_WARNING, "Unhandled cause %d\n", cause);
01600 }
01601 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01602 ast_mutex_unlock(&p->lock);
01603 } else {
01604 ast_mutex_unlock(&p->lock);
01605
01606
01607 ast_queue_hangup(p->owner);
01608 }
01609 } else {
01610 ast_mutex_unlock(&p->lock);
01611
01612 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01613 }
01614 }
01615
01616 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01617 {
01618 switch (level) {
01619 case OR2_LOG_NOTICE:
01620 ast_verbose("%s", logmessage);
01621 break;
01622 case OR2_LOG_WARNING:
01623 ast_log(LOG_WARNING, "%s", logmessage);
01624 break;
01625 case OR2_LOG_ERROR:
01626 ast_log(LOG_ERROR, "%s", logmessage);
01627 break;
01628 case OR2_LOG_STACK_TRACE:
01629 case OR2_LOG_MF_TRACE:
01630 case OR2_LOG_CAS_TRACE:
01631 case OR2_LOG_DEBUG:
01632 case OR2_LOG_EX_DEBUG:
01633 ast_log(LOG_DEBUG, "%s", logmessage);
01634 break;
01635 default:
01636 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01637 ast_log(LOG_NOTICE, "%s", logmessage);
01638 break;
01639 }
01640 }
01641
01642 #define DAHDI_R2_REMOTE_BLOCK (1 << 0)
01643 #define DAHDI_R2_LOCAL_BLOCK (1 << 1)
01644 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01645 {
01646 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01647 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel);
01648 ast_mutex_lock(&p->lock);
01649 p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK;
01650 ast_mutex_unlock(&p->lock);
01651 }
01652
01653 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01654 {
01655 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01656 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01657 ast_mutex_lock(&p->lock);
01658 p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK;
01659 ast_mutex_unlock(&p->lock);
01660 }
01661
01662 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01663 __attribute__((format (printf, 3, 0)));
01664 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01665 {
01666 char logmsg[256];
01667 char completemsg[sizeof(logmsg)+50];
01668 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01669 snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg);
01670 dahdi_r2_write_log(level, completemsg);
01671 }
01672
01673 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01674 __attribute__((format (printf, 3, 0)));
01675 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01676 {
01677 char logmsg[256];
01678 char completemsg[sizeof(logmsg)+50];
01679 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01680 snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg);
01681 dahdi_r2_write_log(level, completemsg);
01682 }
01683
01684 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01685 {
01686 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01687
01688 if (p->immediate) {
01689 return 0;
01690 }
01691 p->exten[p->mfcr2_dnis_index] = digit;
01692 p->rdnis[p->mfcr2_dnis_index] = digit;
01693 p->mfcr2_dnis_index++;
01694 p->exten[p->mfcr2_dnis_index] = 0;
01695 p->rdnis[p->mfcr2_dnis_index] = 0;
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705 if ((p->mfcr2_dnis_matched ||
01706 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
01707 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01708 return 0;
01709 }
01710
01711 return 1;
01712 }
01713
01714 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
01715 {
01716 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01717 p->cid_num[p->mfcr2_ani_index] = digit;
01718 p->cid_name[p->mfcr2_ani_index] = digit;
01719 p->mfcr2_ani_index++;
01720 p->cid_num[p->mfcr2_ani_index] = 0;
01721 p->cid_name[p->mfcr2_ani_index] = 0;
01722 }
01723
01724 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
01725 {
01726 ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
01727 }
01728
01729 static openr2_event_interface_t dahdi_r2_event_iface = {
01730 .on_call_init = dahdi_r2_on_call_init,
01731 .on_call_offered = dahdi_r2_on_call_offered,
01732 .on_call_accepted = dahdi_r2_on_call_accepted,
01733 .on_call_answered = dahdi_r2_on_call_answered,
01734 .on_call_disconnect = dahdi_r2_on_call_disconnect,
01735 .on_call_end = dahdi_r2_on_call_end,
01736 .on_call_read = dahdi_r2_on_call_read,
01737 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
01738 .on_os_error = dahdi_r2_on_os_error,
01739 .on_protocol_error = dahdi_r2_on_protocol_error,
01740 .on_line_blocked = dahdi_r2_on_line_blocked,
01741 .on_line_idle = dahdi_r2_on_line_idle,
01742
01743 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
01744 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
01745 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
01746
01747 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
01748 };
01749
01750 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
01751 {
01752 return AST_ALAW(sample);
01753 }
01754
01755 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
01756 {
01757 return AST_LIN2A(sample);
01758 }
01759
01760 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
01761 dahdi_r2_alaw_to_linear,
01762 dahdi_r2_linear_to_alaw
01763 };
01764
01765 #endif
01766
01767 static int restore_gains(struct dahdi_pvt *p);
01768
01769 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01770 {
01771 int tchan;
01772 int tinthreeway;
01773 struct ast_channel *towner;
01774
01775 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01776
01777 tchan = p->subs[a].chan;
01778 towner = p->subs[a].owner;
01779 tinthreeway = p->subs[a].inthreeway;
01780
01781 p->subs[a].chan = p->subs[b].chan;
01782 p->subs[a].owner = p->subs[b].owner;
01783 p->subs[a].inthreeway = p->subs[b].inthreeway;
01784
01785 p->subs[b].chan = tchan;
01786 p->subs[b].owner = towner;
01787 p->subs[b].inthreeway = tinthreeway;
01788
01789 if (p->subs[a].owner)
01790 p->subs[a].owner->fds[0] = p->subs[a].dfd;
01791 if (p->subs[b].owner)
01792 p->subs[b].owner->fds[0] = p->subs[b].dfd;
01793 wakeup_sub(p, a, NULL);
01794 wakeup_sub(p, b, NULL);
01795 }
01796
01797 static int dahdi_open(char *fn)
01798 {
01799 int fd;
01800 int isnum;
01801 int chan = 0;
01802 int bs;
01803 int x;
01804 isnum = 1;
01805 for (x = 0; x < strlen(fn); x++) {
01806 if (!isdigit(fn[x])) {
01807 isnum = 0;
01808 break;
01809 }
01810 }
01811 if (isnum) {
01812 chan = atoi(fn);
01813 if (chan < 1) {
01814 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01815 return -1;
01816 }
01817 fn = DAHDI_FILE_CHANNEL;
01818 }
01819 fd = open(fn, O_RDWR | O_NONBLOCK);
01820 if (fd < 0) {
01821 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01822 return -1;
01823 }
01824 if (chan) {
01825 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01826 x = errno;
01827 close(fd);
01828 errno = x;
01829 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01830 return -1;
01831 }
01832 }
01833 bs = READ_SIZE;
01834 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01835 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01836 x = errno;
01837 close(fd);
01838 errno = x;
01839 return -1;
01840 }
01841 return fd;
01842 }
01843
01844 static void dahdi_close(int fd)
01845 {
01846 if (fd > 0)
01847 close(fd);
01848 }
01849
01850 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01851 {
01852 dahdi_close(chan_pvt->subs[sub_num].dfd);
01853 chan_pvt->subs[sub_num].dfd = -1;
01854 }
01855
01856 #ifdef HAVE_PRI
01857 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01858 {
01859 dahdi_close(pri->fds[fd_num]);
01860 pri->fds[fd_num] = -1;
01861 }
01862 #endif
01863
01864 static int dahdi_setlinear(int dfd, int linear)
01865 {
01866 int res;
01867 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01868 if (res)
01869 return res;
01870 return 0;
01871 }
01872
01873
01874 static int alloc_sub(struct dahdi_pvt *p, int x)
01875 {
01876 struct dahdi_bufferinfo bi;
01877 int res;
01878 if (p->subs[x].dfd < 0) {
01879 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01880 if (p->subs[x].dfd > -1) {
01881 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01882 if (!res) {
01883 bi.txbufpolicy = p->buf_policy;
01884 bi.rxbufpolicy = p->buf_policy;
01885 bi.numbufs = p->buf_no;
01886 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01887 if (res < 0) {
01888 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01889 }
01890 } else
01891 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01892 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01893 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01894 dahdi_close_sub(p, x);
01895 return -1;
01896 }
01897 if (option_debug)
01898 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01899 return 0;
01900 } else
01901 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01902 return -1;
01903 }
01904 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01905 return -1;
01906 }
01907
01908 static int unalloc_sub(struct dahdi_pvt *p, int x)
01909 {
01910 if (!x) {
01911 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01912 return -1;
01913 }
01914 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01915 dahdi_close_sub(p, x);
01916 p->subs[x].linear = 0;
01917 p->subs[x].chan = 0;
01918 p->subs[x].owner = NULL;
01919 p->subs[x].inthreeway = 0;
01920 p->polarity = POLARITY_IDLE;
01921 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01922 return 0;
01923 }
01924
01925 static int digit_to_dtmfindex(char digit)
01926 {
01927 if (isdigit(digit))
01928 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01929 else if (digit >= 'A' && digit <= 'D')
01930 return DAHDI_TONE_DTMF_A + (digit - 'A');
01931 else if (digit >= 'a' && digit <= 'd')
01932 return DAHDI_TONE_DTMF_A + (digit - 'a');
01933 else if (digit == '*')
01934 return DAHDI_TONE_DTMF_s;
01935 else if (digit == '#')
01936 return DAHDI_TONE_DTMF_p;
01937 else
01938 return -1;
01939 }
01940
01941 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01942 {
01943 struct dahdi_pvt *pvt;
01944 int index;
01945 int dtmf = -1;
01946
01947 pvt = chan->tech_pvt;
01948
01949 ast_mutex_lock(&pvt->lock);
01950
01951 index = dahdi_get_index(chan, pvt, 0);
01952
01953 if ((index != SUB_REAL) || !pvt->owner)
01954 goto out;
01955
01956 #ifdef HAVE_PRI
01957 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01958 if (pvt->setup_ack) {
01959 if (!pri_grab(pvt, pvt->pri)) {
01960 pri_information(pvt->pri->pri, pvt->call, digit);
01961 pri_rel(pvt->pri);
01962 } else
01963 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01964 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01965 int res;
01966 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01967 res = strlen(pvt->dialdest);
01968 pvt->dialdest[res++] = digit;
01969 pvt->dialdest[res] = '\0';
01970 }
01971 goto out;
01972 }
01973 #endif
01974 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01975 goto out;
01976
01977 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01978 int res;
01979 struct dahdi_dialoperation zo = {
01980 .op = DAHDI_DIAL_OP_APPEND,
01981 .dialstr[0] = 'T',
01982 .dialstr[1] = digit,
01983 .dialstr[2] = 0,
01984 };
01985 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01986 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01987 else
01988 pvt->dialing = 1;
01989 } else {
01990 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01991 pvt->dialing = 1;
01992 pvt->begindigit = digit;
01993 }
01994
01995 out:
01996 ast_mutex_unlock(&pvt->lock);
01997
01998 return 0;
01999 }
02000
02001 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02002 {
02003 struct dahdi_pvt *pvt;
02004 int res = 0;
02005 int index;
02006 int x;
02007
02008 pvt = chan->tech_pvt;
02009
02010 ast_mutex_lock(&pvt->lock);
02011
02012 index = dahdi_get_index(chan, pvt, 0);
02013
02014 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
02015 goto out;
02016
02017 #ifdef HAVE_PRI
02018
02019 if (pvt->sig == SIG_PRI && !pvt->begindigit)
02020 goto out;
02021 #endif
02022
02023 if (pvt->begindigit) {
02024 x = -1;
02025 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
02026 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02027 pvt->dialing = 0;
02028 pvt->begindigit = 0;
02029 }
02030
02031 out:
02032 ast_mutex_unlock(&pvt->lock);
02033
02034 return res;
02035 }
02036
02037 static char *events[] = {
02038 "No event",
02039 "On hook",
02040 "Ring/Answered",
02041 "Wink/Flash",
02042 "Alarm",
02043 "No more alarm",
02044 "HDLC Abort",
02045 "HDLC Overrun",
02046 "HDLC Bad FCS",
02047 "Dial Complete",
02048 "Ringer On",
02049 "Ringer Off",
02050 "Hook Transition Complete",
02051 "Bits Changed",
02052 "Pulse Start",
02053 "Timer Expired",
02054 "Timer Ping",
02055 "Polarity Reversal",
02056 "Ring Begin",
02057 };
02058
02059 static struct {
02060 int alarm;
02061 char *name;
02062 } alarms[] = {
02063 { DAHDI_ALARM_RED, "Red Alarm" },
02064 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02065 { DAHDI_ALARM_BLUE, "Blue Alarm" },
02066 { DAHDI_ALARM_RECOVER, "Recovering" },
02067 { DAHDI_ALARM_LOOPBACK, "Loopback" },
02068 { DAHDI_ALARM_NOTOPEN, "Not Open" },
02069 { DAHDI_ALARM_NONE, "None" },
02070 };
02071
02072 static char *alarm2str(int alarm)
02073 {
02074 int x;
02075 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
02076 if (alarms[x].alarm & alarm)
02077 return alarms[x].name;
02078 }
02079 return alarm ? "Unknown Alarm" : "No Alarm";
02080 }
02081
02082 static char *event2str(int event)
02083 {
02084 static char buf[256];
02085 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
02086 return events[event];
02087 sprintf(buf, "Event %d", event);
02088 return buf;
02089 }
02090
02091 #ifdef HAVE_PRI
02092 static char *dialplan2str(int dialplan)
02093 {
02094 if (dialplan == -1) {
02095 return("Dynamically set dialplan in ISDN");
02096 }
02097 return (pri_plan2str(dialplan));
02098 }
02099 #endif
02100
02101 static char *dahdi_sig2str(int sig)
02102 {
02103 static char buf[256];
02104 switch (sig) {
02105 case SIG_EM:
02106 return "E & M Immediate";
02107 case SIG_EMWINK:
02108 return "E & M Wink";
02109 case SIG_EM_E1:
02110 return "E & M E1";
02111 case SIG_FEATD:
02112 return "Feature Group D (DTMF)";
02113 case SIG_FEATDMF:
02114 return "Feature Group D (MF)";
02115 case SIG_FEATDMF_TA:
02116 return "Feature Groud D (MF) Tandem Access";
02117 case SIG_FEATB:
02118 return "Feature Group B (MF)";
02119 case SIG_E911:
02120 return "E911 (MF)";
02121 case SIG_FGC_CAMA:
02122 return "FGC/CAMA (Dialpulse)";
02123 case SIG_FGC_CAMAMF:
02124 return "FGC/CAMA (MF)";
02125 case SIG_FXSLS:
02126 return "FXS Loopstart";
02127 case SIG_FXSGS:
02128 return "FXS Groundstart";
02129 case SIG_FXSKS:
02130 return "FXS Kewlstart";
02131 case SIG_FXOLS:
02132 return "FXO Loopstart";
02133 case SIG_FXOGS:
02134 return "FXO Groundstart";
02135 case SIG_FXOKS:
02136 return "FXO Kewlstart";
02137 case SIG_PRI:
02138 return "ISDN PRI";
02139 case SIG_MFCR2:
02140 return "MFC/R2";
02141 case SIG_SF:
02142 return "SF (Tone) Immediate";
02143 case SIG_SFWINK:
02144 return "SF (Tone) Wink";
02145 case SIG_SF_FEATD:
02146 return "SF (Tone) with Feature Group D (DTMF)";
02147 case SIG_SF_FEATDMF:
02148 return "SF (Tone) with Feature Group D (MF)";
02149 case SIG_SF_FEATB:
02150 return "SF (Tone) with Feature Group B (MF)";
02151 case SIG_GR303FXOKS:
02152 return "GR-303 with FXOKS";
02153 case SIG_GR303FXSKS:
02154 return "GR-303 with FXSKS";
02155 case 0:
02156 return "Pseudo";
02157 default:
02158 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02159 return buf;
02160 }
02161 }
02162
02163 #define sig2str dahdi_sig2str
02164
02165 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
02166 {
02167
02168
02169 struct dahdi_confinfo zi;
02170
02171 memset(&zi, 0, sizeof(zi));
02172 zi.chan = 0;
02173
02174 if (slavechannel > 0) {
02175
02176 zi.confmode = DAHDI_CONF_DIGITALMON;
02177 zi.confno = slavechannel;
02178 } else {
02179 if (!index) {
02180
02181 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02182 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02183 } else
02184 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02185 zi.confno = p->confno;
02186 }
02187 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02188 return 0;
02189 if (c->dfd < 0)
02190 return 0;
02191 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02192 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02193 return -1;
02194 }
02195 if (slavechannel < 1) {
02196 p->confno = zi.confno;
02197 }
02198 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02199 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02200 return 0;
02201 }
02202
02203 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02204 {
02205
02206 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02207 return 1;
02208
02209 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02210 return 1;
02211 return 0;
02212 }
02213
02214 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
02215 {
02216 struct dahdi_confinfo zi;
02217 if (
02218 (c->dfd < 0) ||
02219
02220 !isourconf(p, c)
02221
02222 ) return 0;
02223 memset(&zi, 0, sizeof(zi));
02224 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02225 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02226 return -1;
02227 }
02228 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02229 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02230 return 0;
02231 }
02232
02233 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02234 {
02235 int x;
02236 int useslavenative;
02237 struct dahdi_pvt *slave = NULL;
02238
02239 useslavenative = 1;
02240
02241 for (x = 0; x < 3; x++) {
02242
02243
02244 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02245 useslavenative = 0;
02246 }
02247
02248
02249 if (useslavenative) {
02250 for (x = 0; x < MAX_SLAVES; x++) {
02251 if (p->slaves[x]) {
02252 if (slave) {
02253
02254
02255 slave = NULL;
02256 useslavenative = 0;
02257 break;
02258 } else {
02259
02260 slave = p->slaves[x];
02261 }
02262 }
02263 }
02264 }
02265
02266 if (!slave)
02267 useslavenative = 0;
02268 else if (slave->law != p->law) {
02269 useslavenative = 0;
02270 slave = NULL;
02271 }
02272 if (out)
02273 *out = slave;
02274 return useslavenative;
02275 }
02276
02277 static int reset_conf(struct dahdi_pvt *p)
02278 {
02279 p->confno = -1;
02280 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02281 if (p->subs[SUB_REAL].dfd > -1) {
02282 struct dahdi_confinfo zi;
02283
02284 memset(&zi, 0, sizeof(zi));
02285 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02286 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02287 }
02288 return 0;
02289 }
02290
02291 static int update_conf(struct dahdi_pvt *p)
02292 {
02293 int needconf = 0;
02294 int x;
02295 int useslavenative;
02296 struct dahdi_pvt *slave = NULL;
02297
02298 useslavenative = isslavenative(p, &slave);
02299
02300 for (x = 0; x < 3; x++) {
02301
02302 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02303 conf_add(p, &p->subs[x], x, 0);
02304 needconf++;
02305 } else {
02306 conf_del(p, &p->subs[x], x);
02307 }
02308 }
02309
02310
02311 for (x = 0; x < MAX_SLAVES; x++) {
02312 if (p->slaves[x]) {
02313 if (useslavenative)
02314 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02315 else {
02316 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02317 needconf++;
02318 }
02319 }
02320 }
02321
02322 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02323 if (useslavenative)
02324 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02325 else {
02326 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02327 needconf++;
02328 }
02329 }
02330
02331 if (p->master) {
02332 if (isslavenative(p->master, NULL)) {
02333 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02334 } else {
02335 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02336 }
02337 }
02338 if (!needconf) {
02339
02340
02341 p->confno = -1;
02342 }
02343 if (option_debug)
02344 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02345 return 0;
02346 }
02347
02348 static void dahdi_enable_ec(struct dahdi_pvt *p)
02349 {
02350 int x;
02351 int res;
02352 if (!p)
02353 return;
02354 if (p->echocanon) {
02355 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
02356 return;
02357 }
02358 if (p->digital) {
02359 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
02360 return;
02361 }
02362 if (p->echocancel) {
02363 if (p->sig == SIG_PRI) {
02364 x = 1;
02365 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02366 if (res)
02367 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02368 }
02369 x = p->echocancel;
02370 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02371 if (res)
02372 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02373 else {
02374 p->echocanon = 1;
02375 if (option_debug)
02376 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
02377 }
02378 } else if (option_debug)
02379 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
02380 }
02381
02382 static void dahdi_train_ec(struct dahdi_pvt *p)
02383 {
02384 int x;
02385 int res;
02386 if (p && p->echocancel && p->echotraining) {
02387 x = p->echotraining;
02388 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02389 if (res)
02390 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02391 else {
02392 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
02393 }
02394 } else
02395 ast_log(LOG_DEBUG, "No echo training requested\n");
02396 }
02397
02398 static void dahdi_disable_ec(struct dahdi_pvt *p)
02399 {
02400 int x;
02401 int res;
02402 if (p->echocancel) {
02403 x = 0;
02404 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02405 if (res)
02406 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02407 else if (option_debug)
02408 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
02409 }
02410 p->echocanon = 0;
02411 }
02412
02413 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02414 {
02415 int j;
02416 int k;
02417 float linear_gain = pow(10.0, gain / 20.0);
02418
02419 switch (law) {
02420 case DAHDI_LAW_ALAW:
02421 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02422 if (gain) {
02423 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02424 if (k > 32767) k = 32767;
02425 if (k < -32767) k = -32767;
02426 g->txgain[j] = AST_LIN2A(k);
02427 } else {
02428 g->txgain[j] = j;
02429 }
02430 }
02431 break;
02432 case DAHDI_LAW_MULAW:
02433 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02434 if (gain) {
02435 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02436 if (k > 32767) k = 32767;
02437 if (k < -32767) k = -32767;
02438 g->txgain[j] = AST_LIN2MU(k);
02439 } else {
02440 g->txgain[j] = j;
02441 }
02442 }
02443 break;
02444 }
02445 }
02446
02447 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02448 {
02449 int j;
02450 int k;
02451 float linear_gain = pow(10.0, gain / 20.0);
02452
02453 switch (law) {
02454 case DAHDI_LAW_ALAW:
02455 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02456 if (gain) {
02457 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02458 if (k > 32767) k = 32767;
02459 if (k < -32767) k = -32767;
02460 g->rxgain[j] = AST_LIN2A(k);
02461 } else {
02462 g->rxgain[j] = j;
02463 }
02464 }
02465 break;
02466 case DAHDI_LAW_MULAW:
02467 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02468 if (gain) {
02469 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02470 if (k > 32767) k = 32767;
02471 if (k < -32767) k = -32767;
02472 g->rxgain[j] = AST_LIN2MU(k);
02473 } else {
02474 g->rxgain[j] = j;
02475 }
02476 }
02477 break;
02478 }
02479 }
02480
02481 static int set_actual_txgain(int fd, int chan, float gain, int law)
02482 {
02483 struct dahdi_gains g;
02484 int res;
02485
02486 memset(&g, 0, sizeof(g));
02487 g.chan = chan;
02488 res = ioctl(fd, DAHDI_GETGAINS, &g);
02489 if (res) {
02490 if (option_debug)
02491 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02492 return res;
02493 }
02494
02495 fill_txgain(&g, gain, law);
02496
02497 return ioctl(fd, DAHDI_SETGAINS, &g);
02498 }
02499
02500 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02501 {
02502 struct dahdi_gains g;
02503 int res;
02504
02505 memset(&g, 0, sizeof(g));
02506 g.chan = chan;
02507 res = ioctl(fd, DAHDI_GETGAINS, &g);
02508 if (res) {
02509 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02510 return res;
02511 }
02512
02513 fill_rxgain(&g, gain, law);
02514
02515 return ioctl(fd, DAHDI_SETGAINS, &g);
02516 }
02517
02518 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02519 {
02520 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02521 }
02522
02523 static int bump_gains(struct dahdi_pvt *p)
02524 {
02525 int res;
02526
02527
02528 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
02529 if (res) {
02530 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02531 return -1;
02532 }
02533
02534 return 0;
02535 }
02536
02537 static int restore_gains(struct dahdi_pvt *p)
02538 {
02539 int res;
02540
02541 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02542 if (res) {
02543 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02544 return -1;
02545 }
02546
02547 return 0;
02548 }
02549
02550 static inline int dahdi_set_hook(int fd, int hs)
02551 {
02552 int x, res;
02553
02554 x = hs;
02555 res = ioctl(fd, DAHDI_HOOK, &x);
02556
02557 if (res < 0) {
02558 if (errno == EINPROGRESS)
02559 return 0;
02560 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02561
02562 }
02563
02564 return res;
02565 }
02566
02567 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02568 {
02569 int x, y, res;
02570 x = muted;
02571 if (p->sig == SIG_PRI) {
02572 y = 1;
02573 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02574 if (res)
02575 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02576 }
02577 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02578 if (res < 0)
02579 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02580 return res;
02581 }
02582
02583 static int save_conference(struct dahdi_pvt *p)
02584 {
02585 struct dahdi_confinfo c;
02586 int res;
02587 if (p->saveconf.confmode) {
02588 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02589 return -1;
02590 }
02591 p->saveconf.chan = 0;
02592 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02593 if (res) {
02594 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02595 p->saveconf.confmode = 0;
02596 return -1;
02597 }
02598 memset(&c, 0, sizeof(c));
02599 c.confmode = DAHDI_CONF_NORMAL;
02600 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02601 if (res) {
02602 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02603 return -1;
02604 }
02605 if (option_debug)
02606 ast_log(LOG_DEBUG, "Disabled conferencing\n");
02607 return 0;
02608 }
02609
02610 static int restore_conference(struct dahdi_pvt *p)
02611 {
02612 int res;
02613 if (p->saveconf.confmode) {
02614 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02615 p->saveconf.confmode = 0;
02616 if (res) {
02617 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02618 return -1;
02619 }
02620 }
02621 if (option_debug)
02622 ast_log(LOG_DEBUG, "Restored conferencing\n");
02623 return 0;
02624 }
02625
02626 static int send_callerid(struct dahdi_pvt *p);
02627
02628 static int send_cwcidspill(struct dahdi_pvt *p)
02629 {
02630 p->callwaitcas = 0;
02631 p->cidcwexpire = 0;
02632 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02633 return -1;
02634 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02635
02636 p->cidlen += READ_SIZE * 4;
02637 p->cidpos = 0;
02638 send_callerid(p);
02639 if (option_verbose > 2)
02640 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02641 return 0;
02642 }
02643
02644 static int has_voicemail(struct dahdi_pvt *p)
02645 {
02646
02647 return ast_app_has_voicemail(p->mailbox, NULL);
02648 }
02649
02650 static int send_callerid(struct dahdi_pvt *p)
02651 {
02652
02653 int res;
02654
02655 if (p->subs[SUB_REAL].linear) {
02656 p->subs[SUB_REAL].linear = 0;
02657 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02658 }
02659 while (p->cidpos < p->cidlen) {
02660 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02661 if (res < 0) {
02662 if (errno == EAGAIN)
02663 return 0;
02664 else {
02665 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02666 return -1;
02667 }
02668 }
02669 if (!res)
02670 return 0;
02671 p->cidpos += res;
02672 }
02673 free(p->cidspill);
02674 p->cidspill = NULL;
02675 if (p->callwaitcas) {
02676
02677 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02678 } else
02679 restore_conference(p);
02680 return 0;
02681 }
02682
02683 static int dahdi_callwait(struct ast_channel *ast)
02684 {
02685 struct dahdi_pvt *p = ast->tech_pvt;
02686 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02687 if (p->cidspill) {
02688 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02689 free(p->cidspill);
02690 }
02691 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02692 return -1;
02693 save_conference(p);
02694
02695 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02696 if (!p->callwaitrings && p->callwaitingcallerid) {
02697 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02698 p->callwaitcas = 1;
02699 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02700 } else {
02701 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02702 p->callwaitcas = 0;
02703 p->cidlen = 2400 + READ_SIZE * 4;
02704 }
02705 p->cidpos = 0;
02706 send_callerid(p);
02707
02708 return 0;
02709 }
02710
02711 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02712 {
02713 struct dahdi_pvt *p = ast->tech_pvt;
02714 int x, res, index,mysig;
02715 char *c, *n, *l;
02716 #ifdef HAVE_PRI
02717 char *s = NULL;
02718 #endif
02719 char dest[256];
02720 ast_mutex_lock(&p->lock);
02721 ast_copy_string(dest, rdest, sizeof(dest));
02722 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02723 if ((ast->_state == AST_STATE_BUSY)) {
02724 p->subs[SUB_REAL].needbusy = 1;
02725 ast_mutex_unlock(&p->lock);
02726 return 0;
02727 }
02728 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02729 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02730 ast_mutex_unlock(&p->lock);
02731 return -1;
02732 }
02733 p->dialednone = 0;
02734 if ((p->radio || (p->oprmode < 0)))
02735 {
02736
02737 ast_setstate(ast, AST_STATE_UP);
02738 ast_mutex_unlock(&p->lock);
02739 return 0;
02740 }
02741 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02742 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02743 if (res)
02744 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02745 p->outgoing = 1;
02746
02747 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02748
02749 mysig = p->sig;
02750 if (p->outsigmod > -1)
02751 mysig = p->outsigmod;
02752
02753 switch (mysig) {
02754 case SIG_FXOLS:
02755 case SIG_FXOGS:
02756 case SIG_FXOKS:
02757 if (p->owner == ast) {
02758
02759
02760
02761 p->dialing = 1;
02762 if (p->use_callerid) {
02763
02764 if (p->cidspill) {
02765 ast_log(LOG_WARNING, "cidspill already exists??\n");
02766 free(p->cidspill);
02767 }
02768 p->callwaitcas = 0;
02769 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02770 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02771 p->cidpos = 0;
02772 send_callerid(p);
02773 }
02774 }
02775
02776 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02777 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02778 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02779 p->cidrings = cidrings[p->distinctivering - 1];
02780 } else {
02781 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02782 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02783 p->cidrings = p->sendcalleridafter;
02784 }
02785
02786
02787 c = strchr(dest, '/');
02788 if (c)
02789 c++;
02790 if (c && (strlen(c) < p->stripmsd)) {
02791 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02792 c = NULL;
02793 }
02794 if (c) {
02795 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02796 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02797 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02798 } else {
02799 p->dop.dialstr[0] = '\0';
02800 }
02801 x = DAHDI_RING;
02802 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02803 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02804 ast_mutex_unlock(&p->lock);
02805 return -1;
02806 }
02807 p->dialing = 1;
02808 } else {
02809
02810 p->callwaitrings = 0;
02811 if (ast->cid.cid_num)
02812 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02813 else
02814 p->callwait_num[0] = '\0';
02815 if (ast->cid.cid_name)
02816 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02817 else
02818 p->callwait_name[0] = '\0';
02819
02820 if (dahdi_callwait(ast)) {
02821 ast_mutex_unlock(&p->lock);
02822 return -1;
02823 }
02824
02825 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02826 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02827
02828 }
02829 n = ast->cid.cid_name;
02830 l = ast->cid.cid_num;
02831 if (l)
02832 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02833 else
02834 p->lastcid_num[0] = '\0';
02835 if (n)
02836 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02837 else
02838 p->lastcid_name[0] = '\0';
02839 ast_setstate(ast, AST_STATE_RINGING);
02840 index = dahdi_get_index(ast, p, 0);
02841 if (index > -1) {
02842 p->subs[index].needringing = 1;
02843 }
02844 break;
02845 case SIG_FXSLS:
02846 case SIG_FXSGS:
02847 case SIG_FXSKS:
02848 case SIG_EMWINK:
02849 case SIG_EM:
02850 case SIG_EM_E1:
02851 case SIG_FEATD:
02852 case SIG_FEATDMF:
02853 case SIG_E911:
02854 case SIG_FGC_CAMA:
02855 case SIG_FGC_CAMAMF:
02856 case SIG_FEATB:
02857 case SIG_SFWINK:
02858 case SIG_SF:
02859 case SIG_SF_FEATD:
02860 case SIG_SF_FEATDMF:
02861 case SIG_FEATDMF_TA:
02862 case SIG_SF_FEATB:
02863 c = strchr(dest, '/');
02864 if (c)
02865 c++;
02866 else
02867 c = "";
02868 if (strlen(c) < p->stripmsd) {
02869 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02870 ast_mutex_unlock(&p->lock);
02871 return -1;
02872 }
02873 #ifdef HAVE_PRI
02874
02875 if (!p->pri) {
02876 #endif
02877 x = DAHDI_START;
02878 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02879 if (res < 0) {
02880 if (errno != EINPROGRESS) {
02881 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02882 ast_mutex_unlock(&p->lock);
02883 return -1;
02884 }
02885 }
02886 #ifdef HAVE_PRI
02887 }
02888 #endif
02889 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02890 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02891
02892 c += p->stripmsd;
02893
02894 switch (mysig) {
02895 case SIG_FEATD:
02896 l = ast->cid.cid_num;
02897 if (l)
02898 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02899 else
02900 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02901 break;
02902 case SIG_FEATDMF:
02903 l = ast->cid.cid_num;
02904 if (l)
02905 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02906 else
02907 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02908 break;
02909 case SIG_FEATDMF_TA:
02910 {
02911 const char *cic, *ozz;
02912
02913
02914 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02915 if (!ozz)
02916 ozz = defaultozz;
02917 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02918 if (!cic)
02919 cic = defaultcic;
02920 if (!ozz || !cic) {
02921 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02922 ast_mutex_unlock(&p->lock);
02923 return -1;
02924 }
02925 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02926 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02927 p->whichwink = 0;
02928 }
02929 break;
02930 case SIG_E911:
02931 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02932 break;
02933 case SIG_FGC_CAMA:
02934 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02935 break;
02936 case SIG_FGC_CAMAMF:
02937 case SIG_FEATB:
02938 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02939 break;
02940 default:
02941 if (p->pulse)
02942 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02943 else
02944 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02945 break;
02946 }
02947
02948 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02949 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02950 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02951 p->echorest[sizeof(p->echorest) - 1] = '\0';
02952 p->echobreak = 1;
02953 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02954 } else
02955 p->echobreak = 0;
02956 if (!res) {
02957 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02958 int saveerr = errno;
02959
02960 x = DAHDI_ONHOOK;
02961 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02962 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02963 ast_mutex_unlock(&p->lock);
02964 return -1;
02965 }
02966 } else
02967 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res);
02968 p->dialing = 1;
02969 if (ast_strlen_zero(c))
02970 p->dialednone = 1;
02971 ast_setstate(ast, AST_STATE_DIALING);
02972 break;
02973 case 0:
02974
02975 ast_setstate(ast, AST_STATE_UP);
02976 break;
02977 case SIG_PRI:
02978 case SIG_MFCR2:
02979
02980 p->dialdest[0] = '\0';
02981 p->dialing = 1;
02982 break;
02983 default:
02984 ast_log(LOG_DEBUG, "not yet implemented\n");
02985 ast_mutex_unlock(&p->lock);
02986 return -1;
02987 }
02988 #ifdef HAVE_OPENR2
02989 if (p->mfcr2) {
02990 int strip = p->stripmsd;
02991 int callres = 0;
02992 c = strchr(dest, '/');
02993 if (c) {
02994 c++;
02995 } else {
02996 c = dest;
02997 }
02998 if (!p->hidecallerid) {
02999 l = ast->cid.cid_num;
03000 } else {
03001 l = NULL;
03002 }
03003 if (strlen(c) < strip) {
03004 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
03005 strip = 0;
03006 }
03007 p->dialing = 1;
03008 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast));
03009 if (-1 == callres) {
03010 ast_mutex_unlock(&p->lock);
03011 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03012 return -1;
03013 }
03014 ast_setstate(ast, AST_STATE_DIALING);
03015 }
03016 #endif
03017 #ifdef HAVE_PRI
03018 if (p->pri) {
03019 struct pri_sr *sr;
03020 #ifdef SUPPORT_USERUSER
03021 const char *useruser;
03022 #endif
03023 int pridialplan;
03024 int dp_strip;
03025 int prilocaldialplan;
03026 int ldp_strip;
03027 int exclusive;
03028 const char *rr_str;
03029 int redirect_reason;
03030
03031 c = strchr(dest, '/');
03032 if (c) {
03033 c++;
03034 } else {
03035 c = "";
03036 }
03037
03038 l = NULL;
03039 n = NULL;
03040 if (!p->hidecallerid) {
03041 l = ast->cid.cid_num;
03042 if (!p->hidecalleridname) {
03043 n = ast->cid.cid_name;
03044 }
03045 }
03046
03047
03048 if (strlen(c) < p->stripmsd) {
03049 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03050 ast_mutex_unlock(&p->lock);
03051 return -1;
03052 }
03053 if (mysig != SIG_FXSKS) {
03054 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03055 s = strchr(c + p->stripmsd, 'w');
03056 if (s) {
03057 if (strlen(s) > 1)
03058 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03059 else
03060 p->dop.dialstr[0] = '\0';
03061 *s = '\0';
03062 } else {
03063 p->dop.dialstr[0] = '\0';
03064 }
03065 }
03066 if (pri_grab(p, p->pri)) {
03067 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03068 ast_mutex_unlock(&p->lock);
03069 return -1;
03070 }
03071 if (!(p->call = pri_new_call(p->pri->pri))) {
03072 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03073 pri_rel(p->pri);
03074 ast_mutex_unlock(&p->lock);
03075 return -1;
03076 }
03077 if (!(sr = pri_sr_new())) {
03078 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03079 pri_destroycall(p->pri->pri, p->call);
03080 p->call = NULL;
03081 pri_rel(p->pri);
03082 ast_mutex_unlock(&p->lock);
03083 return -1;
03084 }
03085 if (p->bearer || (mysig == SIG_FXSKS)) {
03086 if (p->bearer) {
03087 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);
03088 p->bearer->call = p->call;
03089 } else
03090 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
03091 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03092 }
03093 p->digital = IS_DIGITAL(ast->transfercapability);
03094
03095
03096 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03097 exclusive = 1;
03098 } else {
03099 exclusive = 0;
03100 }
03101
03102 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03103 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03104 (p->digital ? -1 :
03105 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03106 if (p->pri->facilityenable)
03107 pri_facility_enable(p->pri->pri);
03108
03109 if (option_verbose > 2)
03110 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03111 dp_strip = 0;
03112 pridialplan = p->pri->dialplan - 1;
03113 if (pridialplan == -2) {
03114 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03115 dp_strip = strlen(p->pri->internationalprefix);
03116 pridialplan = PRI_INTERNATIONAL_ISDN;
03117 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03118 dp_strip = strlen(p->pri->nationalprefix);
03119 pridialplan = PRI_NATIONAL_ISDN;
03120 } else {
03121 pridialplan = PRI_LOCAL_ISDN;
03122 }
03123 }
03124 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03125
03126 ldp_strip = 0;
03127 prilocaldialplan = p->pri->localdialplan - 1;
03128 if ((l != NULL) && (prilocaldialplan == -2)) {
03129 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03130 ldp_strip = strlen(p->pri->internationalprefix);
03131 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03132 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03133 ldp_strip = strlen(p->pri->nationalprefix);
03134 prilocaldialplan = PRI_NATIONAL_ISDN;
03135 } else {
03136 prilocaldialplan = PRI_LOCAL_ISDN;
03137 }
03138 }
03139 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03140 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03141 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03142 if (!strcasecmp(rr_str, "UNKNOWN"))
03143 redirect_reason = 0;
03144 else if (!strcasecmp(rr_str, "BUSY"))
03145 redirect_reason = 1;
03146 else if (!strcasecmp(rr_str, "NO_REPLY"))
03147 redirect_reason = 2;
03148 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03149 redirect_reason = 15;
03150 else
03151 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03152 } else
03153 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03154 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03155
03156 #ifdef SUPPORT_USERUSER
03157
03158 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03159
03160 if (useruser)
03161 pri_sr_set_useruser(sr, useruser);
03162 #endif
03163
03164 if (pri_setup(p->pri->pri, p->call, sr)) {
03165 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03166 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03167 pri_rel(p->pri);
03168 ast_mutex_unlock(&p->lock);
03169 pri_sr_free(sr);
03170 return -1;
03171 }
03172 pri_sr_free(sr);
03173 ast_setstate(ast, AST_STATE_DIALING);
03174 pri_rel(p->pri);
03175 }
03176 #endif
03177 ast_mutex_unlock(&p->lock);
03178 return 0;
03179 }
03180
03181 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03182 {
03183 struct dahdi_pvt *p = *pvt;
03184
03185 if (p->prev)
03186 p->prev->next = p->next;
03187 if (p->next)
03188 p->next->prev = p->prev;
03189 if (p->use_smdi)
03190 ast_smdi_interface_unref(p->smdi_iface);
03191 ast_mutex_destroy(&p->lock);
03192 dahdi_close_sub(p, SUB_REAL);
03193 if (p->owner)
03194 p->owner->tech_pvt = NULL;
03195 free(p);
03196 *pvt = NULL;
03197 }
03198
03199 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03200 {
03201 int owned = 0;
03202 int i = 0;
03203
03204 if (!now) {
03205 if (cur->owner) {
03206 owned = 1;
03207 }
03208
03209 for (i = 0; i < 3; i++) {
03210 if (cur->subs[i].owner) {
03211 owned = 1;
03212 }
03213 }
03214 if (!owned) {
03215 if (prev) {
03216 prev->next = cur->next;
03217 if (prev->next)
03218 prev->next->prev = prev;
03219 else
03220 ifend = prev;
03221 } else {
03222 iflist = cur->next;
03223 if (iflist)
03224 iflist->prev = NULL;
03225 else
03226 ifend = NULL;
03227 }
03228 destroy_dahdi_pvt(&cur);
03229 }
03230 } else {
03231 if (prev) {
03232 prev->next = cur->next;
03233 if (prev->next)
03234 prev->next->prev = prev;
03235 else
03236 ifend = prev;
03237 } else {
03238 iflist = cur->next;
03239 if (iflist)
03240 iflist->prev = NULL;
03241 else
03242 ifend = NULL;
03243 }
03244 destroy_dahdi_pvt(&cur);
03245 }
03246 return 0;
03247 }
03248
03249 static void destroy_all_channels(void)
03250 {
03251 int x;
03252 struct dahdi_pvt *p, *pl;
03253
03254 while (num_restart_pending) {
03255 usleep(1);
03256 }
03257
03258 ast_mutex_lock(&iflock);
03259
03260 p = iflist;
03261 while (p) {
03262
03263 if (p->cidspill)
03264 ast_free(p->cidspill);
03265 pl = p;
03266 p = p->next;
03267 x = pl->channel;
03268
03269 if (pl)
03270 destroy_dahdi_pvt(&pl);
03271 if (option_verbose > 2)
03272 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03273 }
03274 iflist = NULL;
03275 ifcount = 0;
03276 ast_mutex_unlock(&iflock);
03277 }
03278
03279 #ifdef HAVE_PRI
03280 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03281 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
03282
03283 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03284 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03285
03286 static char *dahdi_send_keypad_facility_descrip =
03287 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03288 " IE over the current channel.\n";
03289 static char *zap_send_keypad_facility_descrip =
03290 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03291 " IE over the current channel.\n";
03292
03293 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
03294 {
03295
03296 struct dahdi_pvt *p;
03297 char *digits = (char *) data;
03298
03299 if (ast_strlen_zero(digits)) {
03300 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
03301 return -1;
03302 }
03303
03304 p = (struct dahdi_pvt *)chan->tech_pvt;
03305
03306 if (!p) {
03307 ast_log(LOG_DEBUG, "Unable to find technology private\n");
03308 return -1;
03309 }
03310
03311 ast_mutex_lock(&p->lock);
03312
03313 if (!p->pri || !p->call) {
03314 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
03315 ast_mutex_unlock(&p->lock);
03316 return -1;
03317 }
03318
03319 if (!pri_grab(p, p->pri)) {
03320 pri_keypad_facility(p->pri->pri, p->call, digits);
03321 pri_rel(p->pri);
03322 } else {
03323 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
03324 ast_mutex_unlock(&p->lock);
03325 return -1;
03326 }
03327
03328 ast_mutex_unlock(&p->lock);
03329
03330 return 0;
03331 }
03332
03333 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03334 {
03335 return send_keypad_facility_exec(chan, data);
03336 }
03337
03338 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03339 {
03340 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);
03341 return send_keypad_facility_exec(chan, data);
03342 }
03343
03344 static int pri_is_up(struct dahdi_pri *pri)
03345 {
03346 int x;
03347 for (x = 0; x < NUM_DCHANS; x++) {
03348 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03349 return 1;
03350 }
03351 return 0;
03352 }
03353
03354 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03355 {
03356 bearer->owner = &inuse;
03357 bearer->realcall = crv;
03358 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03359 if (crv->subs[SUB_REAL].owner)
03360 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03361 crv->bearer = bearer;
03362 crv->call = bearer->call;
03363 crv->pri = pri;
03364 return 0;
03365 }
03366
03367 static char *pri_order(int level)
03368 {
03369 switch (level) {
03370 case 0:
03371 return "Primary";
03372 case 1:
03373 return "Secondary";
03374 case 2:
03375 return "Tertiary";
03376 case 3:
03377 return "Quaternary";
03378 default:
03379 return "<Unknown>";
03380 }
03381 }
03382
03383
03384 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03385 {
03386 int x = -1;
03387
03388 for (x = 0; x < NUM_DCHANS; x++) {
03389 if ((pri->dchans[x] == pri->pri))
03390 break;
03391 }
03392
03393 return pri->fds[x];
03394 }
03395
03396 static int pri_find_dchan(struct dahdi_pri *pri)
03397 {
03398 int oldslot = -1;
03399 struct pri *old;
03400 int newslot = -1;
03401 int x;
03402 old = pri->pri;
03403 for (x = 0; x < NUM_DCHANS; x++) {
03404 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03405 newslot = x;
03406 if (pri->dchans[x] == old) {
03407 oldslot = x;
03408 }
03409 }
03410 if (newslot < 0) {
03411 newslot = 0;
03412 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03413 pri->dchannels[newslot]);
03414 }
03415 if (old && (oldslot != newslot))
03416 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03417 pri->dchannels[oldslot], pri->dchannels[newslot]);
03418 pri->pri = pri->dchans[newslot];
03419 return 0;
03420 }
03421 #endif
03422
03423 #ifdef HAVE_OPENR2
03424 static char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
03425 static char *zap_accept_r2_call_app = "ZapAcceptR2Call";
03426
03427 static char *dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03428 static char *zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03429
03430 static char *dahdi_accept_r2_call_descrip =
03431 " DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03432 " You can specify yes or no as argument to accept with or without charge.\n";
03433
03434 static char *zap_accept_r2_call_descrip =
03435 " ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03436 " You can specify yes or no as argument to accept with or without charge.\n";
03437
03438 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
03439 {
03440
03441 openr2_call_mode_t accept_mode;
03442 int res, timeout, maxloops;
03443 struct ast_frame *f;
03444 struct dahdi_pvt *p;
03445 char *parse;
03446 AST_DECLARE_APP_ARGS(args,
03447 AST_APP_ARG(charge);
03448 );
03449
03450 if (ast_strlen_zero(data)) {
03451 ast_log(LOG_DEBUG, "No data sent to application!\n");
03452 return -1;
03453 }
03454
03455 if (chan->tech != &dahdi_tech) {
03456 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
03457 return -1;
03458 }
03459
03460 p = (struct dahdi_pvt *)chan->tech_pvt;
03461 if (!p) {
03462 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
03463 return -1;
03464 }
03465
03466 parse = ast_strdupa(data);
03467 AST_STANDARD_APP_ARGS(args, parse);
03468
03469 if (ast_strlen_zero(args.charge)) {
03470 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
03471 return -1;
03472 }
03473
03474 ast_mutex_lock(&p->lock);
03475 if (!p->mfcr2 || !p->mfcr2call) {
03476 ast_mutex_unlock(&p->lock);
03477 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
03478 return -1;
03479 }
03480
03481 if (p->mfcr2_call_accepted) {
03482 ast_mutex_unlock(&p->lock);
03483 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
03484 return 0;
03485 }
03486 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
03487 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
03488 ast_mutex_unlock(&p->lock);
03489 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03490 return -1;
03491 }
03492 ast_mutex_unlock(&p->lock);
03493
03494 res = 0;
03495 timeout = 100;
03496 maxloops = 50;
03497
03498 while (maxloops > 0) {
03499 maxloops--;
03500 if (ast_check_hangup(chan)) {
03501 break;
03502 }
03503 res = ast_waitfor(chan, timeout);
03504 if (res < 0) {
03505 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
03506 res = -1;
03507 break;
03508 }
03509 if (res == 0) {
03510 continue;
03511 }
03512 f = ast_read(chan);
03513 if (!f) {
03514 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
03515 res = -1;
03516 break;
03517 }
03518 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
03519 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
03520 ast_frfree(f);
03521 res = -1;
03522 break;
03523 }
03524 ast_frfree(f);
03525 ast_mutex_lock(&p->lock);
03526 if (p->mfcr2_call_accepted) {
03527 ast_mutex_unlock(&p->lock);
03528 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
03529 break;
03530 }
03531 ast_mutex_unlock(&p->lock);
03532 }
03533 if (res == -1) {
03534 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03535 }
03536 return res;
03537 }
03538
03539 static int zap_accept_r2_call_exec(struct ast_channel *chan, void *data)
03540 {
03541 return dahdi_accept_r2_call_exec(chan, data);
03542 }
03543
03544 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
03545 {
03546 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
03547 switch (cause) {
03548 case AST_CAUSE_USER_BUSY:
03549 case AST_CAUSE_CALL_REJECTED:
03550 case AST_CAUSE_INTERWORKING:
03551 r2cause = OR2_CAUSE_BUSY_NUMBER;
03552 break;
03553
03554 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
03555 case AST_CAUSE_SWITCH_CONGESTION:
03556 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
03557 break;
03558
03559 case AST_CAUSE_UNALLOCATED:
03560 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
03561 break;
03562
03563 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
03564 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03565 r2cause = OR2_CAUSE_OUT_OF_ORDER;
03566 break;
03567
03568 case AST_CAUSE_NO_ANSWER:
03569 case AST_CAUSE_NO_USER_RESPONSE:
03570 r2cause = OR2_CAUSE_NO_ANSWER;
03571 break;
03572
03573 default:
03574 r2cause = OR2_CAUSE_NORMAL_CLEARING;
03575 break;
03576 }
03577 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n",
03578 r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
03579 return r2cause;
03580 }
03581 #endif
03582
03583 static int dahdi_hangup(struct ast_channel *ast)
03584 {
03585 int res;
03586 int index,x, law;
03587
03588 struct dahdi_pvt *p = ast->tech_pvt;
03589 struct dahdi_pvt *tmp = NULL;
03590 struct dahdi_pvt *prev = NULL;
03591 struct dahdi_params par;
03592
03593 if (option_debug)
03594 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
03595 if (!ast->tech_pvt) {
03596 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03597 return 0;
03598 }
03599
03600 ast_mutex_lock(&p->lock);
03601
03602 index = dahdi_get_index(ast, p, 1);
03603
03604 if (p->sig == SIG_PRI) {
03605 x = 1;
03606 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03607 p->cid_num[0] = '\0';
03608 p->cid_name[0] = '\0';
03609 }
03610
03611 x = 0;
03612 dahdi_confmute(p, 0);
03613 restore_gains(p);
03614 if (p->origcid_num) {
03615 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03616 free(p->origcid_num);
03617 p->origcid_num = NULL;
03618 }
03619 if (p->origcid_name) {
03620 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03621 free(p->origcid_name);
03622 p->origcid_name = NULL;
03623 }
03624 if (p->dsp)
03625 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03626 p->exten[0] = '\0';
03627
03628 if (option_debug)
03629 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03630 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03631 p->ignoredtmf = 0;
03632
03633 if (index > -1) {
03634
03635 p->subs[index].owner = NULL;
03636 p->subs[index].needanswer = 0;
03637 p->subs[index].needflash = 0;
03638 p->subs[index].needringing = 0;
03639 p->subs[index].needbusy = 0;
03640 p->subs[index].needcongestion = 0;
03641 p->subs[index].linear = 0;
03642 p->subs[index].needcallerid = 0;
03643 p->polarity = POLARITY_IDLE;
03644 dahdi_setlinear(p->subs[index].dfd, 0);
03645 if (index == SUB_REAL) {
03646 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03647 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
03648 if (p->subs[SUB_CALLWAIT].inthreeway) {
03649
03650 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
03651
03652 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03653 unalloc_sub(p, SUB_CALLWAIT);
03654 p->owner = NULL;
03655 } else {
03656
03657 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03658 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03659 unalloc_sub(p, SUB_THREEWAY);
03660 if (p->subs[SUB_REAL].inthreeway) {
03661
03662
03663 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03664 p->owner = p->subs[SUB_REAL].owner;
03665 } else {
03666
03667 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03668 p->owner = NULL;
03669 }
03670 p->subs[SUB_REAL].inthreeway = 0;
03671 }
03672 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03673
03674 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03675 unalloc_sub(p, SUB_CALLWAIT);
03676 p->owner = p->subs[SUB_REAL].owner;
03677 if (p->owner->_state != AST_STATE_UP)
03678 p->subs[SUB_REAL].needanswer = 1;
03679 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03680 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03681 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03682 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03683 unalloc_sub(p, SUB_THREEWAY);
03684 if (p->subs[SUB_REAL].inthreeway) {
03685
03686
03687 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03688 p->owner = p->subs[SUB_REAL].owner;
03689 } else {
03690
03691 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03692 p->owner = NULL;
03693 }
03694 p->subs[SUB_REAL].inthreeway = 0;
03695 }
03696 } else if (index == SUB_CALLWAIT) {
03697
03698 if (p->subs[SUB_CALLWAIT].inthreeway) {
03699
03700
03701 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03702 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03703 S_OR(p->mohsuggest, NULL),
03704 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03705 }
03706 p->subs[SUB_THREEWAY].inthreeway = 0;
03707
03708 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03709 unalloc_sub(p, SUB_THREEWAY);
03710 } else
03711 unalloc_sub(p, SUB_CALLWAIT);
03712 } else if (index == SUB_THREEWAY) {
03713 if (p->subs[SUB_CALLWAIT].inthreeway) {
03714
03715
03716 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03717 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03718 S_OR(p->mohsuggest, NULL),
03719 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03720 }
03721 p->subs[SUB_CALLWAIT].inthreeway = 0;
03722 }
03723 p->subs[SUB_REAL].inthreeway = 0;
03724
03725
03726 unalloc_sub(p, SUB_THREEWAY);
03727 } else {
03728
03729 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03730 }
03731 }
03732
03733 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03734 p->owner = NULL;
03735 p->ringt = 0;
03736 p->distinctivering = 0;
03737 p->confirmanswer = 0;
03738 p->cidrings = 1;
03739 p->outgoing = 0;
03740 p->digital = 0;
03741 p->faxhandled = 0;
03742 p->pulsedial = 0;
03743 p->onhooktime = time(NULL);
03744 #ifdef HAVE_PRI
03745 p->proceeding = 0;
03746 p->dialing = 0;
03747 p->progress = 0;
03748 p->alerting = 0;
03749 p->setup_ack = 0;
03750 #endif
03751 if (p->dsp) {
03752 ast_dsp_free(p->dsp);
03753 p->dsp = NULL;
03754 }
03755
03756 law = DAHDI_LAW_DEFAULT;
03757 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03758 if (res < 0)
03759 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03760
03761 #ifdef HAVE_OPENR2
03762 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
03763 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
03764 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
03765 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
03766 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
03767 } else {
03768 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
03769 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
03770 openr2_call_disconnect_cause_t r2cause = r2cause_user
03771 ? dahdi_ast_cause_to_r2_cause(r2cause_user)
03772 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
03773 dahdi_r2_disconnect_call(p, r2cause);
03774 }
03775 } else if (p->mfcr2call) {
03776 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
03777 p->mfcr2call = 0;
03778 }
03779 #endif
03780 #ifdef HAVE_PRI
03781 if (p->pri) {
03782 #ifdef SUPPORT_USERUSER
03783 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03784 #endif
03785
03786
03787 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03788 if (!pri_grab(p, p->pri)) {
03789 if (p->alreadyhungup) {
03790 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
03791
03792 #ifdef SUPPORT_USERUSER
03793 pri_call_set_useruser(p->call, useruser);
03794 #endif
03795
03796 pri_hangup(p->pri->pri, p->call, -1);
03797 p->call = NULL;
03798 if (p->bearer)
03799 p->bearer->call = NULL;
03800 } else {
03801 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03802 int icause = ast->hangupcause ? ast->hangupcause : -1;
03803 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03804
03805 #ifdef SUPPORT_USERUSER
03806 pri_call_set_useruser(p->call, useruser);
03807 #endif
03808
03809 p->alreadyhungup = 1;
03810 if (p->bearer)
03811 p->bearer->alreadyhungup = 1;
03812 if (cause) {
03813 if (atoi(cause))
03814 icause = atoi(cause);
03815 }
03816 pri_hangup(p->pri->pri, p->call, icause);
03817 }
03818 if (res < 0)
03819 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03820 pri_rel(p->pri);
03821 } else {
03822 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03823 res = -1;
03824 }
03825 } else {
03826 if (p->bearer)
03827 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03828 p->call = NULL;
03829 res = 0;
03830 }
03831 }
03832 #endif
03833 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
03834 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03835 if (res < 0) {
03836 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03837 }
03838 switch (p->sig) {
03839 case SIG_FXOGS:
03840 case SIG_FXOLS:
03841 case SIG_FXOKS:
03842 memset(&par, 0, sizeof(par));
03843 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03844 if (!res) {
03845 #if 0
03846 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03847 #endif
03848
03849 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03850 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03851 else
03852 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03853 }
03854 break;
03855 case SIG_FXSGS:
03856 case SIG_FXSLS:
03857 case SIG_FXSKS:
03858
03859
03860 if (ast->_state != AST_STATE_RESERVED) {
03861 time(&p->guardtime);
03862 p->guardtime += 2;
03863 }
03864 break;
03865 default:
03866 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03867 }
03868 if (p->cidspill)
03869 free(p->cidspill);
03870 if (p->sig)
03871 dahdi_disable_ec(p);
03872 x = 0;
03873 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03874 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03875 p->didtdd = 0;
03876 p->cidspill = NULL;
03877 p->callwaitcas = 0;
03878 p->callwaiting = p->permcallwaiting;
03879 p->hidecallerid = p->permhidecallerid;
03880 p->dialing = 0;
03881 p->rdnis[0] = '\0';
03882 update_conf(p);
03883 reset_conf(p);
03884
03885 if (p->sig == SIG_PRI) {
03886 x = 0;
03887 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03888 }
03889 #ifdef HAVE_PRI
03890 if (p->bearer) {
03891 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03892
03893
03894 update_conf(p->bearer);
03895 reset_conf(p->bearer);
03896 p->bearer->owner = NULL;
03897 p->bearer->realcall = NULL;
03898 p->bearer = NULL;
03899 p->subs[SUB_REAL].dfd = -1;
03900 p->pri = NULL;
03901 }
03902 #endif
03903 if (num_restart_pending == 0)
03904 restart_monitor();
03905 }
03906
03907 p->callwaitingrepeat = 0;
03908 p->cidcwexpire = 0;
03909 p->oprmode = 0;
03910 ast->tech_pvt = NULL;
03911 ast_mutex_unlock(&p->lock);
03912 ast_module_unref(ast_module_info->self);
03913 if (option_verbose > 2)
03914 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03915
03916 ast_mutex_lock(&iflock);
03917
03918 if (p->restartpending) {
03919 num_restart_pending--;
03920 }
03921
03922 tmp = iflist;
03923 prev = NULL;
03924 if (p->destroy) {
03925 while (tmp) {
03926 if (tmp == p) {
03927 destroy_channel(prev, tmp, 0);
03928 break;
03929 } else {
03930 prev = tmp;
03931 tmp = tmp->next;
03932 }
03933 }
03934 }
03935 ast_mutex_unlock(&iflock);
03936 return 0;
03937 }
03938
03939 static int dahdi_answer(struct ast_channel *ast)
03940 {
03941 struct dahdi_pvt *p = ast->tech_pvt;
03942 int res = 0;
03943 int index;
03944 int oldstate = ast->_state;
03945 ast_setstate(ast, AST_STATE_UP);
03946 ast_mutex_lock(&p->lock);
03947 index = dahdi_get_index(ast, p, 0);
03948 if (index < 0)
03949 index = SUB_REAL;
03950
03951 if ((p->radio || (p->oprmode < 0))) {
03952 ast_mutex_unlock(&p->lock);
03953 return 0;
03954 }
03955 switch (p->sig) {
03956 case SIG_FXSLS:
03957 case SIG_FXSGS:
03958 case SIG_FXSKS:
03959 p->ringt = 0;
03960
03961 case SIG_EM:
03962 case SIG_EM_E1:
03963 case SIG_EMWINK:
03964 case SIG_FEATD:
03965 case SIG_FEATDMF:
03966 case SIG_FEATDMF_TA:
03967 case SIG_E911:
03968 case SIG_FGC_CAMA:
03969 case SIG_FGC_CAMAMF:
03970 case SIG_FEATB:
03971 case SIG_SF:
03972 case SIG_SFWINK:
03973 case SIG_SF_FEATD:
03974 case SIG_SF_FEATDMF:
03975 case SIG_SF_FEATB:
03976 case SIG_FXOLS:
03977 case SIG_FXOGS:
03978 case SIG_FXOKS:
03979
03980 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03981 if (p->hanguponpolarityswitch) {
03982 gettimeofday(&p->polaritydelaytv, NULL);
03983 }
03984 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03985 tone_zone_play_tone(p->subs[index].dfd, -1);
03986 p->dialing = 0;
03987 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03988 if (oldstate == AST_STATE_RINGING) {
03989 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03990 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03991 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03992 p->owner = p->subs[SUB_REAL].owner;
03993 }
03994 }
03995 if (p->sig & __DAHDI_SIG_FXS) {
03996 dahdi_enable_ec(p);
03997 dahdi_train_ec(p);
03998 }
03999 break;
04000 #ifdef HAVE_PRI
04001 case SIG_PRI:
04002
04003 if (!pri_grab(p, p->pri)) {
04004 p->proceeding = 1;
04005 p->dialing = 0;
04006 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04007 pri_rel(p->pri);
04008 } else {
04009 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04010 res = -1;
04011 }
04012 break;
04013 #endif
04014 #ifdef HAVE_OPENR2
04015 case SIG_MFCR2:
04016 if (!p->mfcr2_accept_on_offer) {
04017
04018
04019 if (p->mfcr2_charge_calls) {
04020 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
04021 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04022 } else {
04023 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
04024 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04025 }
04026 } else {
04027 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04028 res = dahdi_r2_answer(p);
04029 }
04030 break;
04031 #endif
04032 case 0:
04033 ast_mutex_unlock(&p->lock);
04034 return 0;
04035 default:
04036 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04037 res = -1;
04038 }
04039 ast_mutex_unlock(&p->lock);
04040 return res;
04041 }
04042
04043 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04044 {
04045 char *cp;
04046 signed char *scp;
04047 int x;
04048 int index;
04049 struct dahdi_pvt *p = chan->tech_pvt, *pp;
04050 struct oprmode *oprmode;
04051
04052
04053
04054 if (!data || (datalen < 1)) {
04055 errno = EINVAL;
04056 return -1;
04057 }
04058
04059 switch (option) {
04060 case AST_OPTION_TXGAIN:
04061 scp = (signed char *) data;
04062 index = dahdi_get_index(chan, p, 0);
04063 if (index < 0) {
04064 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04065 return -1;
04066 }
04067 if (option_debug)
04068 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04069 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
04070 case AST_OPTION_RXGAIN:
04071 scp = (signed char *) data;
04072 index = dahdi_get_index(chan, p, 0);
04073 if (index < 0) {
04074 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04075 return -1;
04076 }
04077 if (option_debug)
04078 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04079 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
04080 case AST_OPTION_TONE_VERIFY:
04081 if (!p->dsp)
04082 break;
04083 cp = (char *) data;
04084 switch (*cp) {
04085 case 1:
04086 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04087 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
04088 break;
04089 case 2:
04090 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04091 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
04092 break;
04093 default:
04094 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04095 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
04096 break;
04097 }
04098 break;
04099 case AST_OPTION_TDD:
04100
04101 cp = (char *) data;
04102 p->mate = 0;
04103 if (!*cp) {
04104 if (option_debug)
04105 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04106 if (p->tdd)
04107 tdd_free(p->tdd);
04108 p->tdd = 0;
04109 break;
04110 }
04111 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
04112 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04113 dahdi_disable_ec(p);
04114
04115 if (!p->didtdd) {
04116 unsigned char mybuf[41000];
04117 unsigned char *buf;
04118 int size, res, fd, len;
04119 struct pollfd fds[1];
04120
04121 buf = mybuf;
04122 memset(buf, 0x7f, sizeof(mybuf));
04123 ast_tdd_gen_ecdisa(buf + 16000, 16000);
04124 len = 40000;
04125 index = dahdi_get_index(chan, p, 0);
04126 if (index < 0) {
04127 ast_log(LOG_WARNING, "No index in TDD?\n");
04128 return -1;
04129 }
04130 fd = p->subs[index].dfd;
04131 while (len) {
04132 if (ast_check_hangup(chan))
04133 return -1;
04134 size = len;
04135 if (size > READ_SIZE)
04136 size = READ_SIZE;
04137 fds[0].fd = fd;
04138 fds[0].events = POLLPRI | POLLOUT;
04139 fds[0].revents = 0;
04140 res = poll(fds, 1, -1);
04141 if (!res) {
04142 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
04143 continue;
04144 }
04145
04146 if (fds[0].revents & POLLPRI)
04147 return -1;
04148 if (!(fds[0].revents & POLLOUT)) {
04149 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
04150 continue;
04151 }
04152 res = write(fd, buf, size);
04153 if (res != size) {
04154 if (res == -1) return -1;
04155 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04156 break;
04157 }
04158 len -= size;
04159 buf += size;
04160 }
04161 p->didtdd = 1;
04162 }
04163 if (*cp == 2) {
04164 if (p->tdd)
04165 tdd_free(p->tdd);
04166 p->tdd = 0;
04167 p->mate = 1;
04168 break;
04169 }
04170 if (!p->tdd) {
04171 p->tdd = tdd_new();
04172 }
04173 break;
04174 case AST_OPTION_RELAXDTMF:
04175 if (!p->dsp)
04176 break;
04177 cp = (char *) data;
04178 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04179 *cp ? "ON" : "OFF", (int) *cp, chan->name);
04180 p->dtmfrelax = 0;
04181 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
04182 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04183 break;
04184 case AST_OPTION_AUDIO_MODE:
04185 cp = (char *) data;
04186 if (!*cp) {
04187 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04188 x = 0;
04189 dahdi_disable_ec(p);
04190 } else {
04191 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04192 x = 1;
04193 }
04194 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04195 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04196 break;
04197 case AST_OPTION_OPRMODE:
04198 oprmode = (struct oprmode *) data;
04199 pp = oprmode->peer->tech_pvt;
04200 p->oprmode = pp->oprmode = 0;
04201
04202 p->oprpeer = pp;
04203 pp->oprpeer = p;
04204
04205 if (oprmode->mode)
04206 {
04207 pp->oprmode = oprmode->mode;
04208 p->oprmode = -oprmode->mode;
04209 }
04210 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
04211 oprmode->mode, chan->name,oprmode->peer->name);;
04212 break;
04213 case AST_OPTION_ECHOCAN:
04214 cp = (char *) data;
04215 if (*cp) {
04216 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
04217 dahdi_enable_ec(p);
04218 } else {
04219 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
04220 dahdi_disable_ec(p);
04221 }
04222 break;
04223 }
04224 errno = 0;
04225
04226 return 0;
04227 }
04228
04229 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
04230 {
04231 struct dahdi_pvt *p = chan->tech_pvt;
04232
04233 if (!strcasecmp(data, "rxgain")) {
04234 ast_mutex_lock(&p->lock);
04235 snprintf(buf, len, "%f", p->rxgain);
04236 ast_mutex_unlock(&p->lock);
04237 } else if (!strcasecmp(data, "txgain")) {
04238 ast_mutex_lock(&p->lock);
04239 snprintf(buf, len, "%f", p->txgain);
04240 ast_mutex_unlock(&p->lock);
04241 } else {
04242 ast_copy_string(buf, "", len);
04243 }
04244 return 0;
04245 }
04246
04247
04248 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04249 {
04250
04251 int x;
04252 int hasslaves;
04253 if (!master)
04254 return;
04255 if (needlock) {
04256 ast_mutex_lock(&master->lock);
04257 if (slave) {
04258 while (ast_mutex_trylock(&slave->lock)) {
04259 DEADLOCK_AVOIDANCE(&master->lock);
04260 }
04261 }
04262 }
04263 hasslaves = 0;
04264 for (x = 0; x < MAX_SLAVES; x++) {
04265 if (master->slaves[x]) {
04266 if (!slave || (master->slaves[x] == slave)) {
04267
04268 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04269 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04270 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04271 master->slaves[x]->master = NULL;
04272 master->slaves[x] = NULL;
04273 } else
04274 hasslaves = 1;
04275 }
04276 if (!hasslaves)
04277 master->inconference = 0;
04278 }
04279 if (!slave) {
04280 if (master->master) {
04281
04282 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04283 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04284 hasslaves = 0;
04285 for (x = 0; x < MAX_SLAVES; x++) {
04286 if (master->master->slaves[x] == master)
04287 master->master->slaves[x] = NULL;
04288 else if (master->master->slaves[x])
04289 hasslaves = 1;
04290 }
04291 if (!hasslaves)
04292 master->master->inconference = 0;
04293 }
04294 master->master = NULL;
04295 }
04296 update_conf(master);
04297 if (needlock) {
04298 if (slave)
04299 ast_mutex_unlock(&slave->lock);
04300 ast_mutex_unlock(&master->lock);
04301 }
04302 }
04303
04304 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04305 int x;
04306 if (!slave || !master) {
04307 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04308 return;
04309 }
04310 for (x = 0; x < MAX_SLAVES; x++) {
04311 if (!master->slaves[x]) {
04312 master->slaves[x] = slave;
04313 break;
04314 }
04315 }
04316 if (x >= MAX_SLAVES) {
04317 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04318 master->slaves[MAX_SLAVES - 1] = slave;
04319 }
04320 if (slave->master)
04321 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04322 slave->master = master;
04323
04324 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04325 }
04326
04327 static void disable_dtmf_detect(struct dahdi_pvt *p)
04328 {
04329 #ifdef DAHDI_TONEDETECT
04330 int val;
04331 #endif
04332
04333 p->ignoredtmf = 1;
04334
04335 #ifdef DAHDI_TONEDETECT
04336 val = 0;
04337 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04338 #endif
04339 if (!p->hardwaredtmf && p->dsp) {
04340 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04341 ast_dsp_set_features(p->dsp, p->dsp_features);
04342 }
04343 }
04344
04345 static void enable_dtmf_detect(struct dahdi_pvt *p)
04346 {
04347 #ifdef DAHDI_TONEDETECT
04348 int val;
04349 #endif
04350
04351 if (p->channel == CHAN_PSEUDO)
04352 return;
04353
04354 p->ignoredtmf = 0;
04355
04356 #ifdef DAHDI_TONEDETECT
04357 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04358 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04359 #endif
04360 if (!p->hardwaredtmf && p->dsp) {
04361 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04362 ast_dsp_set_features(p->dsp, p->dsp_features);
04363 }
04364 }
04365
04366 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)
04367 {
04368 struct ast_channel *who;
04369 struct dahdi_pvt *p0, *p1, *op0, *op1;
04370 struct dahdi_pvt *master = NULL, *slave = NULL;
04371 struct ast_frame *f;
04372 int inconf = 0;
04373 int nothingok = 1;
04374 int ofd0, ofd1;
04375 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04376 int os0 = -1, os1 = -1;
04377 int priority = 0;
04378 struct ast_channel *oc0, *oc1;
04379 enum ast_bridge_result res;
04380
04381 #ifdef PRI_2BCT
04382 int triedtopribridge = 0;
04383 q931_call *q931c0 = NULL, *q931c1 = NULL;
04384 #endif
04385
04386
04387
04388
04389
04390
04391 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04392 return AST_BRIDGE_FAILED_NOWARN;
04393
04394 ast_mutex_lock(&c0->lock);
04395 while (ast_mutex_trylock(&c1->lock)) {
04396 DEADLOCK_AVOIDANCE(&c0->lock);
04397 }
04398
04399 p0 = c0->tech_pvt;
04400 p1 = c1->tech_pvt;
04401
04402 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04403 ast_mutex_unlock(&c0->lock);
04404 ast_mutex_unlock(&c1->lock);
04405 return AST_BRIDGE_FAILED_NOWARN;
04406 }
04407
04408 oi0 = dahdi_get_index(c0, p0, 0);
04409 oi1 = dahdi_get_index(c1, p1, 0);
04410 if ((oi0 < 0) || (oi1 < 0)) {
04411 ast_mutex_unlock(&c0->lock);
04412 ast_mutex_unlock(&c1->lock);
04413 return AST_BRIDGE_FAILED;
04414 }
04415
04416 op0 = p0 = c0->tech_pvt;
04417 op1 = p1 = c1->tech_pvt;
04418 ofd0 = c0->fds[0];
04419 ofd1 = c1->fds[0];
04420 oc0 = p0->owner;
04421 oc1 = p1->owner;
04422
04423 if (ast_mutex_trylock(&p0->lock)) {
04424
04425 ast_mutex_unlock(&c0->lock);
04426 ast_mutex_unlock(&c1->lock);
04427 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04428 return AST_BRIDGE_RETRY;
04429 }
04430 if (ast_mutex_trylock(&p1->lock)) {
04431
04432 ast_mutex_unlock(&p0->lock);
04433 ast_mutex_unlock(&c0->lock);
04434 ast_mutex_unlock(&c1->lock);
04435 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04436 return AST_BRIDGE_RETRY;
04437 }
04438
04439 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04440 if (p0->owner && p1->owner) {
04441
04442 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04443 master = p0;
04444 slave = p1;
04445 inconf = 1;
04446 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04447 master = p1;
04448 slave = p0;
04449 inconf = 1;
04450 } else {
04451 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04452 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04453 p0->channel,
04454 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04455 p0->subs[SUB_REAL].inthreeway, p0->channel,
04456 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04457 p1->subs[SUB_REAL].inthreeway);
04458 }
04459 nothingok = 0;
04460 }
04461 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04462 if (p1->subs[SUB_THREEWAY].inthreeway) {
04463 master = p1;
04464 slave = p0;
04465 nothingok = 0;
04466 }
04467 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04468 if (p0->subs[SUB_THREEWAY].inthreeway) {
04469 master = p0;
04470 slave = p1;
04471 nothingok = 0;
04472 }
04473 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04474
04475
04476 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04477 master = p1;
04478 slave = p0;
04479 nothingok = 0;
04480 }
04481 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04482
04483 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04484 master = p0;
04485 slave = p1;
04486 nothingok = 0;
04487 }
04488 }
04489 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
04490 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04491 if (master && slave) {
04492
04493
04494
04495 if ((oi1 == SUB_THREEWAY) &&
04496 p1->subs[SUB_THREEWAY].inthreeway &&
04497 p1->subs[SUB_REAL].owner &&
04498 p1->subs[SUB_REAL].inthreeway &&
04499 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04500 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04501 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04502 os1 = p1->subs[SUB_REAL].owner->_state;
04503 } else {
04504 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04505 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04506 }
04507 if ((oi0 == SUB_THREEWAY) &&
04508 p0->subs[SUB_THREEWAY].inthreeway &&
04509 p0->subs[SUB_REAL].owner &&
04510 p0->subs[SUB_REAL].inthreeway &&
04511 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04512 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04513 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04514 os0 = p0->subs[SUB_REAL].owner->_state;
04515 } else {
04516 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04517 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04518 }
04519 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04520 if (!p0->echocanbridged || !p1->echocanbridged) {
04521
04522 dahdi_disable_ec(p0);
04523 dahdi_disable_ec(p1);
04524 }
04525 }
04526 dahdi_link(slave, master);
04527 master->inconference = inconf;
04528 } else if (!nothingok)
04529 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04530
04531 update_conf(p0);
04532 update_conf(p1);
04533 t0 = p0->subs[SUB_REAL].inthreeway;
04534 t1 = p1->subs[SUB_REAL].inthreeway;
04535
04536 ast_mutex_unlock(&p0->lock);
04537 ast_mutex_unlock(&p1->lock);
04538
04539 ast_mutex_unlock(&c0->lock);
04540 ast_mutex_unlock(&c1->lock);
04541
04542
04543 if ((!master || !slave) && !nothingok) {
04544 dahdi_enable_ec(p0);
04545 dahdi_enable_ec(p1);
04546 return AST_BRIDGE_FAILED;
04547 }
04548
04549 if (option_verbose > 2)
04550 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
04551
04552 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04553 disable_dtmf_detect(op0);
04554
04555 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04556 disable_dtmf_detect(op1);
04557
04558 for (;;) {
04559 struct ast_channel *c0_priority[2] = {c0, c1};
04560 struct ast_channel *c1_priority[2] = {c1, c0};
04561
04562
04563
04564 ast_mutex_lock(&c0->lock);
04565 while (ast_mutex_trylock(&c1->lock)) {
04566 DEADLOCK_AVOIDANCE(&c0->lock);
04567 }
04568
04569 p0 = c0->tech_pvt;
04570 p1 = c1->tech_pvt;
04571
04572 if (op0 == p0)
04573 i0 = dahdi_get_index(c0, p0, 1);
04574 if (op1 == p1)
04575 i1 = dahdi_get_index(c1, p1, 1);
04576 ast_mutex_unlock(&c0->lock);
04577 ast_mutex_unlock(&c1->lock);
04578
04579 if (!timeoutms ||
04580 (op0 != p0) ||
04581 (op1 != p1) ||
04582 (ofd0 != c0->fds[0]) ||
04583 (ofd1 != c1->fds[0]) ||
04584 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04585 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04586 (oc0 != p0->owner) ||
04587 (oc1 != p1->owner) ||
04588 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04589 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04590 (oi0 != i0) ||
04591 (oi1 != i1)) {
04592 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04593 op0->channel, oi0, op1->channel, oi1);
04594 res = AST_BRIDGE_RETRY;
04595 goto return_from_bridge;
04596 }
04597
04598 #ifdef PRI_2BCT
04599 q931c0 = p0->call;
04600 q931c1 = p1->call;
04601 if (p0->transfer && p1->transfer
04602 && q931c0 && q931c1
04603 && !triedtopribridge) {
04604 pri_channel_bridge(q931c0, q931c1);
04605 triedtopribridge = 1;
04606 }
04607 #endif
04608
04609 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04610 if (!who) {
04611 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
04612 continue;
04613 }
04614 f = ast_read(who);
04615 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04616 *fo = f;
04617 *rc = who;
04618 res = AST_BRIDGE_COMPLETE;
04619 goto return_from_bridge;
04620 }
04621 if (f->frametype == AST_FRAME_DTMF) {
04622 if ((who == c0) && p0->pulsedial) {
04623 ast_write(c1, f);
04624 } else if ((who == c1) && p1->pulsedial) {
04625 ast_write(c0, f);
04626 } else {
04627 *fo = f;
04628 *rc = who;
04629 res = AST_BRIDGE_COMPLETE;
04630 goto return_from_bridge;
04631 }
04632 }
04633 ast_frfree(f);
04634
04635
04636 priority = !priority;
04637 }
04638
04639 return_from_bridge:
04640 if (op0 == p0)
04641 dahdi_enable_ec(p0);
04642
04643 if (op1 == p1)
04644 dahdi_enable_ec(p1);
04645
04646 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04647 enable_dtmf_detect(op0);
04648
04649 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04650 enable_dtmf_detect(op1);
04651
04652 dahdi_unlink(slave, master, 1);
04653
04654 return res;
04655 }
04656
04657 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04658 {
04659 struct dahdi_pvt *p = newchan->tech_pvt;
04660 int x;
04661 ast_mutex_lock(&p->lock);
04662 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
04663 if (p->owner == oldchan) {
04664 p->owner = newchan;
04665 }
04666 for (x = 0; x < 3; x++)
04667 if (p->subs[x].owner == oldchan) {
04668 if (!x)
04669 dahdi_unlink(NULL, p, 0);
04670 p->subs[x].owner = newchan;
04671 }
04672 if (newchan->_state == AST_STATE_RINGING)
04673 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04674 update_conf(p);
04675 ast_mutex_unlock(&p->lock);
04676 return 0;
04677 }
04678
04679 static int dahdi_ring_phone(struct dahdi_pvt *p)
04680 {
04681 int x;
04682 int res;
04683
04684 x = 0;
04685 x = DAHDI_ONHOOK;
04686 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04687 do {
04688 x = DAHDI_RING;
04689 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04690 if (res) {
04691 switch (errno) {
04692 case EBUSY:
04693 case EINTR:
04694
04695 usleep(10000);
04696 continue;
04697 case EINPROGRESS:
04698 res = 0;
04699 break;
04700 default:
04701 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04702 res = 0;
04703 }
04704 }
04705 } while (res);
04706 return res;
04707 }
04708
04709 static void *ss_thread(void *data);
04710
04711 static int attempt_transfer(struct dahdi_pvt *p)
04712 {
04713
04714
04715
04716 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04717
04718
04719 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04720 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04721 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04722 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04723 }
04724 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04725 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04726 }
04727 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04728 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04729 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04730 return -1;
04731 }
04732
04733 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04734 unalloc_sub(p, SUB_THREEWAY);
04735 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04736 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04737 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04738 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04739 }
04740 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04741 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04742 }
04743 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04744 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04745 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04746 return -1;
04747 }
04748
04749 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04750 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
04751 unalloc_sub(p, SUB_THREEWAY);
04752
04753 return 1;
04754 } else {
04755 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04756 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04757 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04758 return -1;
04759 }
04760 return 0;
04761 }
04762
04763 static int check_for_conference(struct dahdi_pvt *p)
04764 {
04765 struct dahdi_confinfo ci;
04766
04767 if (p->master || (p->confno > -1))
04768 return 0;
04769 memset(&ci, 0, sizeof(ci));
04770 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04771 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04772 return 0;
04773 }
04774
04775
04776
04777 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04778 if (option_verbose > 2)
04779 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
04780 return 1;
04781 }
04782 return 0;
04783 }
04784
04785 static int get_alarms(struct dahdi_pvt *p)
04786 {
04787 int res;
04788 struct dahdi_spaninfo zi;
04789 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04790
04791
04792
04793
04794
04795 struct dahdi_params params;
04796 #endif
04797
04798 memset(&zi, 0, sizeof(zi));
04799 zi.spanno = p->span;
04800
04801
04802 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
04803 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04804 return 0;
04805 }
04806 if (zi.alarms != DAHDI_ALARM_NONE)
04807 return zi.alarms;
04808 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04809
04810 memset(¶ms, 0, sizeof(params));
04811 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04812 return params.chan_alarms;
04813
04814 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04815 #endif
04816 return DAHDI_ALARM_NONE;
04817 }
04818
04819 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04820 {
04821 struct dahdi_pvt *p = ast->tech_pvt;
04822 struct ast_frame *f = *dest;
04823
04824 if (option_debug)
04825 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04826
04827 if (p->confirmanswer) {
04828 if (option_debug)
04829 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04830
04831
04832 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04833 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04834 *dest = &p->subs[index].f;
04835
04836 p->confirmanswer = 0;
04837 } else if (p->callwaitcas) {
04838 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04839 if (option_debug)
04840 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04841 if (p->cidspill)
04842 free(p->cidspill);
04843 send_cwcidspill(p);
04844 }
04845 if ((f->subclass != 'm') && (f->subclass != 'u'))
04846 p->callwaitcas = 0;
04847 p->subs[index].f.frametype = AST_FRAME_NULL;
04848 p->subs[index].f.subclass = 0;
04849 *dest = &p->subs[index].f;
04850 } else if (f->subclass == 'f') {
04851
04852 if ((p->callprogress & 0x6) && !p->faxhandled) {
04853 p->faxhandled = 1;
04854 if (strcmp(ast->exten, "fax")) {
04855 const char *target_context = S_OR(ast->macrocontext, ast->context);
04856
04857
04858
04859
04860
04861 ast_mutex_unlock(&p->lock);
04862 ast_channel_unlock(ast);
04863 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04864 ast_channel_lock(ast);
04865 ast_mutex_lock(&p->lock);
04866 if (option_verbose > 2)
04867 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04868
04869 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04870 if (ast_async_goto(ast, target_context, "fax", 1))
04871 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04872 } else {
04873 ast_channel_lock(ast);
04874 ast_mutex_lock(&p->lock);
04875 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04876 }
04877 } else if (option_debug)
04878 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04879 } else if (option_debug)
04880 ast_log(LOG_DEBUG, "Fax already handled\n");
04881 dahdi_confmute(p, 0);
04882 p->subs[index].f.frametype = AST_FRAME_NULL;
04883 p->subs[index].f.subclass = 0;
04884 *dest = &p->subs[index].f;
04885 } else if (f->subclass == 'm') {
04886
04887 dahdi_confmute(p, 1);
04888 p->subs[index].f.frametype = AST_FRAME_NULL;
04889 p->subs[index].f.subclass = 0;
04890 *dest = &p->subs[index].f;
04891 } else if (f->subclass == 'u') {
04892
04893 dahdi_confmute(p, 0);
04894 p->subs[index].f.frametype = AST_FRAME_NULL;
04895 p->subs[index].f.subclass = 0;
04896 *dest = &p->subs[index].f;
04897 } else
04898 dahdi_confmute(p, 0);
04899 }
04900
04901 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04902 {
04903 const char *alarm_str = alarm2str(alarms);
04904
04905
04906
04907 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04908 p->unknown_alarm = 1;
04909 return;
04910 } else {
04911 p->unknown_alarm = 0;
04912 }
04913
04914 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04915 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04916 "Alarm: %s\r\n"
04917 "Channel: %d\r\n",
04918 alarm_str, p->channel);
04919 }
04920
04921 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04922 {
04923 int res, x;
04924 int index, mysig;
04925 char *c;
04926 struct dahdi_pvt *p = ast->tech_pvt;
04927 pthread_t threadid;
04928 pthread_attr_t attr;
04929 struct ast_channel *chan;
04930 struct ast_frame *f;
04931
04932 index = dahdi_get_index(ast, p, 0);
04933 mysig = p->sig;
04934 if (p->outsigmod > -1)
04935 mysig = p->outsigmod;
04936 p->subs[index].f.frametype = AST_FRAME_NULL;
04937 p->subs[index].f.subclass = 0;
04938 p->subs[index].f.datalen = 0;
04939 p->subs[index].f.samples = 0;
04940 p->subs[index].f.mallocd = 0;
04941 p->subs[index].f.offset = 0;
04942 p->subs[index].f.src = "dahdi_handle_event";
04943 p->subs[index].f.data = NULL;
04944 f = &p->subs[index].f;
04945
04946 if (index < 0)
04947 return &p->subs[index].f;
04948 if (p->fake_event) {
04949 res = p->fake_event;
04950 p->fake_event = 0;
04951 } else
04952 res = dahdi_get_event(p->subs[index].dfd);
04953
04954 if (option_debug)
04955 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04956
04957 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04958 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04959
04960 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04961 #ifdef HAVE_PRI
04962 if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04963
04964 } else {
04965 #endif
04966 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04967 p->subs[index].f.subclass = res & 0xff;
04968 #ifdef HAVE_PRI
04969 }
04970 #endif
04971 dahdi_handle_dtmfup(ast, index, &f);
04972 return f;
04973 }
04974
04975 if (res & DAHDI_EVENT_DTMFDOWN) {
04976 if (option_debug)
04977 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04978
04979 dahdi_confmute(p, 1);
04980 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04981 p->subs[index].f.subclass = res & 0xff;
04982 return &p->subs[index].f;
04983 }
04984
04985 switch (res) {
04986 #ifdef DAHDI_EVENT_EC_DISABLED
04987 case DAHDI_EVENT_EC_DISABLED:
04988 if (option_verbose > 2)
04989 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04990 p->echocanon = 0;
04991 break;
04992 #endif
04993 case DAHDI_EVENT_BITSCHANGED:
04994 #ifdef HAVE_OPENR2
04995 if (p->sig != SIG_MFCR2) {
04996 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04997 } else {
04998 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
04999 openr2_chan_handle_cas(p->r2chan);
05000 }
05001 #else
05002 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05003 #endif
05004 case DAHDI_EVENT_PULSE_START:
05005
05006 if (!ast->pbx)
05007 tone_zone_play_tone(p->subs[index].dfd, -1);
05008 break;
05009 case DAHDI_EVENT_DIALCOMPLETE:
05010 #ifdef HAVE_OPENR2
05011 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05012
05013
05014 break;
05015 }
05016 #endif
05017 if (p->inalarm) break;
05018 if ((p->radio || (p->oprmode < 0))) break;
05019 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
05020 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05021 return NULL;
05022 }
05023 if (!x) {
05024 dahdi_enable_ec(p);
05025 if (p->echobreak) {
05026 dahdi_train_ec(p);
05027 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05028 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05029 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05030 p->echobreak = 0;
05031 } else {
05032 p->dialing = 0;
05033 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05034
05035 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05036 ast_setstate(ast, AST_STATE_UP);
05037 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05038 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05039 break;
05040 } else {
05041
05042 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05043 }
05044 }
05045 if (ast->_state == AST_STATE_DIALING) {
05046 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05047 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
05048 } 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)))) {
05049 ast_setstate(ast, AST_STATE_RINGING);
05050 } else if (!p->answeronpolarityswitch) {
05051 ast_setstate(ast, AST_STATE_UP);
05052 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05053 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05054
05055 p->polarity = POLARITY_REV;
05056 } else {
05057
05058 p->polarity = POLARITY_IDLE;
05059 }
05060 }
05061 }
05062 }
05063 break;
05064 case DAHDI_EVENT_ALARM:
05065 #ifdef HAVE_PRI
05066 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05067
05068 if (p->call) {
05069 if (p->pri && p->pri->pri) {
05070 if (!pri_grab(p, p->pri)) {
05071 pri_hangup(p->pri->pri, p->call, -1);
05072 pri_destroycall(p->pri->pri, p->call);
05073 p->call = NULL;
05074 pri_rel(p->pri);
05075 } else
05076 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05077 } else
05078 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05079 }
05080 if (p->owner)
05081 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05082 }
05083 if (p->bearer)
05084 p->bearer->inalarm = 1;
05085 else
05086 #endif
05087 p->inalarm = 1;
05088 res = get_alarms(p);
05089 handle_alarms(p, res);
05090 #ifdef HAVE_PRI
05091 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05092
05093 } else {
05094 break;
05095 }
05096 #endif
05097 #ifdef HAVE_OPENR2
05098 if (p->sig == SIG_MFCR2)
05099 break;
05100 #endif
05101 case DAHDI_EVENT_ONHOOK:
05102 if (p->radio) {
05103 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05104 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05105 break;
05106 }
05107 if (p->oprmode < 0)
05108 {
05109 if (p->oprmode != -1) break;
05110 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05111 {
05112
05113 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05114 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05115 save_conference(p->oprpeer);
05116 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05117 }
05118 break;
05119 }
05120 switch (p->sig) {
05121 case SIG_FXOLS:
05122 case SIG_FXOGS:
05123 case SIG_FXOKS:
05124 p->onhooktime = time(NULL);
05125 p->msgstate = -1;
05126
05127 if (index == SUB_REAL) {
05128
05129 if (p->subs[SUB_CALLWAIT].owner) {
05130
05131 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05132 if (option_verbose > 2)
05133 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05134 unalloc_sub(p, SUB_CALLWAIT);
05135 #if 0
05136 p->subs[index].needanswer = 0;
05137 p->subs[index].needringing = 0;
05138 #endif
05139 p->callwaitingrepeat = 0;
05140 p->cidcwexpire = 0;
05141 p->owner = NULL;
05142
05143 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05144 p->dialing = 1;
05145 dahdi_ring_phone(p);
05146 } else if (p->subs[SUB_THREEWAY].owner) {
05147 unsigned int mssinceflash;
05148
05149
05150 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
05151
05152 ast_mutex_unlock(&p->lock);
05153 DEADLOCK_AVOIDANCE(&ast->lock);
05154
05155
05156
05157 ast_mutex_lock(&p->lock);
05158 if (p->owner != ast) {
05159 ast_log(LOG_WARNING, "This isn't good...\n");
05160 return NULL;
05161 }
05162 }
05163 if (!p->subs[SUB_THREEWAY].owner) {
05164 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05165 return NULL;
05166 }
05167 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05168 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
05169 if (mssinceflash < MIN_MS_SINCE_FLASH) {
05170
05171
05172 if (p->subs[SUB_THREEWAY].owner)
05173 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
05174 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05175 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05176 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05177 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05178 if (p->transfer) {
05179
05180 p->subs[SUB_REAL].inthreeway = 0;
05181 p->subs[SUB_THREEWAY].inthreeway = 0;
05182
05183 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05184 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05185
05186 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05187 p->owner = NULL;
05188
05189 dahdi_ring_phone(p);
05190 } else {
05191 if ((res = attempt_transfer(p)) < 0) {
05192 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05193 if (p->subs[SUB_THREEWAY].owner)
05194 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05195 } else if (res) {
05196
05197 if (p->subs[SUB_THREEWAY].owner)
05198 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05199 break;
05200 }
05201 }
05202 } else {
05203 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05204 if (p->subs[SUB_THREEWAY].owner)
05205 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05206 }
05207 } else {
05208 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05209
05210 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05211 p->owner = NULL;
05212
05213 dahdi_ring_phone(p);
05214 }
05215 }
05216 } else {
05217 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
05218 }
05219
05220 default:
05221 dahdi_disable_ec(p);
05222 return NULL;
05223 }
05224 break;
05225 case DAHDI_EVENT_RINGOFFHOOK:
05226 if (p->inalarm) break;
05227 if (p->oprmode < 0)
05228 {
05229 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05230 {
05231
05232 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05233 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
05234 restore_conference(p->oprpeer);
05235 }
05236 break;
05237 }
05238 if (p->radio)
05239 {
05240 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05241 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05242 break;
05243 }
05244
05245
05246 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05247 c = strchr(p->dialdest, '/');
05248 if (c)
05249 c++;
05250 else
05251 c = p->dialdest;
05252 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05253 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05254 if (strlen(p->dop.dialstr) > 4) {
05255 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05256 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05257 p->echorest[sizeof(p->echorest) - 1] = '\0';
05258 p->echobreak = 1;
05259 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05260 } else
05261 p->echobreak = 0;
05262 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05263 int saveerr = errno;
05264
05265 x = DAHDI_ONHOOK;
05266 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05267 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05268 return NULL;
05269 }
05270 p->dialing = 1;
05271 return &p->subs[index].f;
05272 }
05273 switch (p->sig) {
05274 case SIG_FXOLS:
05275 case SIG_FXOGS:
05276 case SIG_FXOKS:
05277 switch (ast->_state) {
05278 case AST_STATE_RINGING:
05279 dahdi_enable_ec(p);
05280 dahdi_train_ec(p);
05281 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05282 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05283
05284 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05285 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
05286 if (p->cidspill) {
05287
05288 free(p->cidspill);
05289 p->cidspill = NULL;
05290 }
05291 p->dialing = 0;
05292 p->callwaitcas = 0;
05293 if (p->confirmanswer) {
05294
05295 p->subs[index].f.frametype = AST_FRAME_NULL;
05296 p->subs[index].f.subclass = 0;
05297 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05298
05299 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05300 if (res < 0) {
05301 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05302 p->dop.dialstr[0] = '\0';
05303 return NULL;
05304 } else {
05305 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05306 p->subs[index].f.frametype = AST_FRAME_NULL;
05307 p->subs[index].f.subclass = 0;
05308 p->dialing = 1;
05309 }
05310 p->dop.dialstr[0] = '\0';
05311 ast_setstate(ast, AST_STATE_DIALING);
05312 } else
05313 ast_setstate(ast, AST_STATE_UP);
05314 return &p->subs[index].f;
05315 case AST_STATE_DOWN:
05316 ast_setstate(ast, AST_STATE_RING);
05317 ast->rings = 1;
05318 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05319 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05320 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
05321 return &p->subs[index].f;
05322 case AST_STATE_UP:
05323
05324 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05325
05326 if (ast_bridged_channel(p->owner))
05327 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05328 p->subs[index].needunhold = 1;
05329 break;
05330 case AST_STATE_RESERVED:
05331
05332 if (has_voicemail(p))
05333 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05334 else
05335 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05336 break;
05337 default:
05338 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05339 }
05340 break;
05341 case SIG_FXSLS:
05342 case SIG_FXSGS:
05343 case SIG_FXSKS:
05344 if (ast->_state == AST_STATE_RING) {
05345 p->ringt = p->ringt_base;
05346 }
05347
05348
05349 case SIG_EM:
05350 case SIG_EM_E1:
05351 case SIG_EMWINK:
05352 case SIG_FEATD:
05353 case SIG_FEATDMF:
05354 case SIG_FEATDMF_TA:
05355 case SIG_E911:
05356 case SIG_FGC_CAMA:
05357 case SIG_FGC_CAMAMF:
05358 case SIG_FEATB:
05359 case SIG_SF:
05360 case SIG_SFWINK:
05361 case SIG_SF_FEATD:
05362 case SIG_SF_FEATDMF:
05363 case SIG_SF_FEATB:
05364 if (ast->_state == AST_STATE_PRERING)
05365 ast_setstate(ast, AST_STATE_RING);
05366 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05367 if (option_debug)
05368 ast_log(LOG_DEBUG, "Ring detected\n");
05369 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05370 p->subs[index].f.subclass = AST_CONTROL_RING;
05371 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05372 if (option_debug)
05373 ast_log(LOG_DEBUG, "Line answered\n");
05374 if (p->confirmanswer) {
05375 p->subs[index].f.frametype = AST_FRAME_NULL;
05376 p->subs[index].f.subclass = 0;
05377 } else {
05378 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05379 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05380 ast_setstate(ast, AST_STATE_UP);
05381 }
05382 } else if (ast->_state != AST_STATE_RING)
05383 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05384 break;
05385 default:
05386 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05387 }
05388 break;
05389 #ifdef DAHDI_EVENT_RINGBEGIN
05390 case DAHDI_EVENT_RINGBEGIN:
05391 switch (p->sig) {
05392 case SIG_FXSLS:
05393 case SIG_FXSGS:
05394 case SIG_FXSKS:
05395 if (ast->_state == AST_STATE_RING) {
05396 p->ringt = p->ringt_base;
05397 }
05398 break;
05399 }
05400 break;
05401 #endif
05402 case DAHDI_EVENT_RINGEROFF:
05403 if (p->inalarm) break;
05404 if ((p->radio || (p->oprmode < 0))) break;
05405 ast->rings++;
05406 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05407 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05408 free(p->cidspill);
05409 p->cidspill = NULL;
05410 p->callwaitcas = 0;
05411 }
05412 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05413 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05414 break;
05415 case DAHDI_EVENT_RINGERON:
05416 break;
05417 case DAHDI_EVENT_NOALARM:
05418 p->inalarm = 0;
05419 #ifdef HAVE_PRI
05420
05421 if (p->bearer)
05422 p->bearer->inalarm = 0;
05423 #endif
05424 if (!p->unknown_alarm) {
05425 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05426 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05427 "Channel: %d\r\n", p->channel);
05428 } else {
05429 p->unknown_alarm = 0;
05430 }
05431 break;
05432 case DAHDI_EVENT_WINKFLASH:
05433 if (p->inalarm) break;
05434 if (p->radio) break;
05435 if (p->oprmode < 0) break;
05436 if (p->oprmode > 1)
05437 {
05438 struct dahdi_params par;
05439
05440 memset(&par, 0, sizeof(par));
05441 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05442 {
05443 if (!par.rxisoffhook)
05444 {
05445
05446 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05447 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05448 save_conference(p);
05449 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05450 }
05451 }
05452 break;
05453 }
05454
05455 gettimeofday(&p->flashtime, NULL);
05456 switch (mysig) {
05457 case SIG_FXOLS:
05458 case SIG_FXOGS:
05459 case SIG_FXOKS:
05460 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05461 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05462 p->callwaitcas = 0;
05463
05464 if (index != SUB_REAL) {
05465 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05466 goto winkflashdone;
05467 }
05468
05469 if (p->subs[SUB_CALLWAIT].owner) {
05470
05471 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05472 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05473 p->owner = p->subs[SUB_REAL].owner;
05474 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
05475 if (p->owner->_state == AST_STATE_RINGING) {
05476 ast_setstate(p->owner, AST_STATE_UP);
05477 p->subs[SUB_REAL].needanswer = 1;
05478 }
05479 p->callwaitingrepeat = 0;
05480 p->cidcwexpire = 0;
05481
05482 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05483 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05484 S_OR(p->mohsuggest, NULL),
05485 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05486 }
05487 p->subs[SUB_CALLWAIT].needhold = 1;
05488 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05489 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05490 S_OR(p->mohsuggest, NULL),
05491 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05492 }
05493 p->subs[SUB_REAL].needunhold = 1;
05494 } else if (!p->subs[SUB_THREEWAY].owner) {
05495 if (!p->threewaycalling) {
05496
05497 p->subs[SUB_REAL].needflash = 1;
05498 goto winkflashdone;
05499 } else if (!check_for_conference(p)) {
05500 char cid_num[256];
05501 char cid_name[256];
05502
05503 cid_num[0] = 0;
05504 cid_name[0] = 0;
05505 if (p->dahditrcallerid && p->owner) {
05506 if (p->owner->cid.cid_num)
05507 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05508 if (p->owner->cid.cid_name)
05509 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05510 }
05511
05512
05513 if (!((ast->pbx) ||
05514 (ast->_state == AST_STATE_UP) ||
05515 (ast->_state == AST_STATE_RING))) {
05516 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
05517 goto winkflashdone;
05518 }
05519 if (alloc_sub(p, SUB_THREEWAY)) {
05520 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05521 goto winkflashdone;
05522 }
05523
05524 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05525 if (p->dahditrcallerid) {
05526 if (!p->origcid_num)
05527 p->origcid_num = ast_strdup(p->cid_num);
05528 if (!p->origcid_name)
05529 p->origcid_name = ast_strdup(p->cid_name);
05530 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05531 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05532 }
05533
05534 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05535
05536 dahdi_disable_ec(p);
05537 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05538 if (res)
05539 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05540 p->owner = chan;
05541 pthread_attr_init(&attr);
05542 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05543 if (!chan) {
05544 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05545 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
05546 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05547 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05548 dahdi_enable_ec(p);
05549 ast_hangup(chan);
05550 } else {
05551 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05552 int way3bridge = 0, cdr3way = 0;
05553
05554 if (!other) {
05555 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05556 } else
05557 way3bridge = 1;
05558
05559 if (p->subs[SUB_THREEWAY].owner->cdr)
05560 cdr3way = 1;
05561
05562 if (option_verbose > 2)
05563 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
05564
05565 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05566 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05567 S_OR(p->mohsuggest, NULL),
05568 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05569 }
05570 p->subs[SUB_THREEWAY].needhold = 1;
05571 }
05572 pthread_attr_destroy(&attr);
05573 }
05574 } else {
05575
05576 if (p->subs[SUB_THREEWAY].inthreeway) {
05577
05578 if (option_debug)
05579 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05580
05581 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05582
05583 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05584 p->owner = p->subs[SUB_REAL].owner;
05585 }
05586
05587 if (option_verbose > 2)
05588 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05589 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05590 p->subs[SUB_REAL].inthreeway = 0;
05591 p->subs[SUB_THREEWAY].inthreeway = 0;
05592 } else {
05593
05594 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05595 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05596 int otherindex = SUB_THREEWAY;
05597 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05598 int way3bridge = 0, cdr3way = 0;
05599
05600 if (!other) {
05601 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05602 } else
05603 way3bridge = 1;
05604
05605 if (p->subs[SUB_THREEWAY].owner->cdr)
05606 cdr3way = 1;
05607
05608 if (option_verbose > 2)
05609 ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05610
05611 p->subs[SUB_THREEWAY].inthreeway = 1;
05612 p->subs[SUB_REAL].inthreeway = 1;
05613 if (ast->_state == AST_STATE_UP) {
05614 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05615 otherindex = SUB_REAL;
05616 }
05617 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05618 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05619 p->subs[otherindex].needunhold = 1;
05620 p->owner = p->subs[SUB_REAL].owner;
05621 if (ast->_state == AST_STATE_RINGING) {
05622 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
05623 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05624 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05625 }
05626 } else {
05627 if (option_verbose > 2)
05628 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05629 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05630 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05631 p->owner = p->subs[SUB_REAL].owner;
05632 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05633 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05634 p->subs[SUB_REAL].needunhold = 1;
05635 dahdi_enable_ec(p);
05636 }
05637
05638 }
05639 }
05640 winkflashdone:
05641 update_conf(p);
05642 break;
05643 case SIG_EM:
05644 case SIG_EM_E1:
05645 case SIG_FEATD:
05646 case SIG_SF:
05647 case SIG_SFWINK:
05648 case SIG_SF_FEATD:
05649 case SIG_FXSLS:
05650 case SIG_FXSGS:
05651 if (p->dialing)
05652 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
05653 else
05654 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05655 break;
05656 case SIG_FEATDMF_TA:
05657 switch (p->whichwink) {
05658 case 0:
05659 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05660 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05661 break;
05662 case 1:
05663 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05664 break;
05665 case 2:
05666 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05667 return NULL;
05668 }
05669 p->whichwink++;
05670
05671 case SIG_FEATDMF:
05672 case SIG_E911:
05673 case SIG_FGC_CAMAMF:
05674 case SIG_FGC_CAMA:
05675 case SIG_FEATB:
05676 case SIG_SF_FEATDMF:
05677 case SIG_SF_FEATB:
05678 case SIG_EMWINK:
05679
05680 if (!ast_strlen_zero(p->dop.dialstr)) {
05681 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05682 if (res < 0) {
05683 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05684 p->dop.dialstr[0] = '\0';
05685 return NULL;
05686 } else
05687 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05688 }
05689 p->dop.dialstr[0] = '\0';
05690 break;
05691 default:
05692 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
05693 }
05694 break;
05695 case DAHDI_EVENT_HOOKCOMPLETE:
05696 if (p->inalarm) break;
05697 if ((p->radio || (p->oprmode < 0))) break;
05698 switch (mysig) {
05699 case SIG_FXSLS:
05700 case SIG_FXSGS:
05701 case SIG_FXSKS:
05702 case SIG_EM:
05703 case SIG_EM_E1:
05704 case SIG_EMWINK:
05705 case SIG_FEATD:
05706 case SIG_SF:
05707 case SIG_SFWINK:
05708 case SIG_SF_FEATD:
05709 if (!ast_strlen_zero(p->dop.dialstr)) {
05710 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05711 if (res < 0) {
05712 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05713 p->dop.dialstr[0] = '\0';
05714 return NULL;
05715 } else
05716 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05717 }
05718 p->dop.dialstr[0] = '\0';
05719 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05720 break;
05721 case SIG_FEATDMF:
05722 case SIG_FEATDMF_TA:
05723 case SIG_E911:
05724 case SIG_FGC_CAMA:
05725 case SIG_FGC_CAMAMF:
05726 case SIG_FEATB:
05727 case SIG_SF_FEATDMF:
05728 case SIG_SF_FEATB:
05729 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05730 break;
05731 default:
05732 break;
05733 }
05734 break;
05735 case DAHDI_EVENT_POLARITY:
05736
05737
05738
05739
05740
05741
05742 if (p->polarity == POLARITY_IDLE) {
05743 p->polarity = POLARITY_REV;
05744 if (p->answeronpolarityswitch &&
05745 ((ast->_state == AST_STATE_DIALING) ||
05746 (ast->_state == AST_STATE_RINGING))) {
05747 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
05748 ast_setstate(p->owner, AST_STATE_UP);
05749 if (p->hanguponpolarityswitch) {
05750 gettimeofday(&p->polaritydelaytv, NULL);
05751 }
05752 } else
05753 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
05754 }
05755
05756
05757 if (p->hanguponpolarityswitch &&
05758 (p->polarityonanswerdelay > 0) &&
05759 (p->polarity == POLARITY_REV) &&
05760 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
05761
05762 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) );
05763
05764 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05765 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
05766 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05767 p->polarity = POLARITY_IDLE;
05768 } else {
05769 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);
05770 }
05771 } else {
05772 p->polarity = POLARITY_IDLE;
05773 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
05774 }
05775
05776 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) );
05777 break;
05778 default:
05779 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05780 }
05781 return &p->subs[index].f;
05782 }
05783
05784 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05785 {
05786 struct dahdi_pvt *p = ast->tech_pvt;
05787 int res;
05788 int usedindex=-1;
05789 int index;
05790 struct ast_frame *f;
05791
05792
05793 index = dahdi_get_index(ast, p, 1);
05794
05795 p->subs[index].f.frametype = AST_FRAME_NULL;
05796 p->subs[index].f.datalen = 0;
05797 p->subs[index].f.samples = 0;
05798 p->subs[index].f.mallocd = 0;
05799 p->subs[index].f.offset = 0;
05800 p->subs[index].f.subclass = 0;
05801 p->subs[index].f.delivery = ast_tv(0,0);
05802 p->subs[index].f.src = "dahdi_exception";
05803 p->subs[index].f.data = NULL;
05804
05805
05806 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05807
05808
05809
05810
05811
05812 if (p->fake_event) {
05813 res = p->fake_event;
05814 p->fake_event = 0;
05815 } else
05816 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05817
05818 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05819 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05820 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
05821 p->owner = p->subs[SUB_REAL].owner;
05822 if (p->owner && ast_bridged_channel(p->owner))
05823 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05824 p->subs[SUB_REAL].needunhold = 1;
05825 }
05826 switch (res) {
05827 case DAHDI_EVENT_ONHOOK:
05828 dahdi_disable_ec(p);
05829 if (p->owner) {
05830 if (option_verbose > 2)
05831 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
05832 dahdi_ring_phone(p);
05833 p->callwaitingrepeat = 0;
05834 p->cidcwexpire = 0;
05835 } else
05836 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05837 update_conf(p);
05838 break;
05839 case DAHDI_EVENT_RINGOFFHOOK:
05840 dahdi_enable_ec(p);
05841 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05842 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05843 p->subs[SUB_REAL].needanswer = 1;
05844 p->dialing = 0;
05845 }
05846 break;
05847 case DAHDI_EVENT_HOOKCOMPLETE:
05848 case DAHDI_EVENT_RINGERON:
05849 case DAHDI_EVENT_RINGEROFF:
05850
05851 break;
05852 case DAHDI_EVENT_WINKFLASH:
05853 gettimeofday(&p->flashtime, NULL);
05854 if (p->owner) {
05855 if (option_verbose > 2)
05856 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05857 if (p->owner->_state != AST_STATE_UP) {
05858
05859 usedindex = dahdi_get_index(p->owner, p, 0);
05860 if (usedindex > -1) {
05861 p->subs[usedindex].needanswer = 1;
05862 }
05863 ast_setstate(p->owner, AST_STATE_UP);
05864 }
05865 p->callwaitingrepeat = 0;
05866 p->cidcwexpire = 0;
05867 if (ast_bridged_channel(p->owner))
05868 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05869 p->subs[SUB_REAL].needunhold = 1;
05870 } else
05871 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05872 update_conf(p);
05873 break;
05874 default:
05875 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05876 }
05877 f = &p->subs[index].f;
05878 return f;
05879 }
05880 if (!(p->radio || (p->oprmode < 0)) && option_debug)
05881 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05882
05883 if (ast != p->owner) {
05884 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05885 f = &p->subs[index].f;
05886 return f;
05887 }
05888 f = dahdi_handle_event(ast);
05889 return f;
05890 }
05891
05892 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05893 {
05894 struct dahdi_pvt *p = ast->tech_pvt;
05895 struct ast_frame *f;
05896 ast_mutex_lock(&p->lock);
05897 f = __dahdi_exception(ast);
05898 ast_mutex_unlock(&p->lock);
05899 return f;
05900 }
05901
05902 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05903 {
05904 struct dahdi_pvt *p = ast->tech_pvt;
05905 int res;
05906 int index;
05907 void *readbuf;
05908 struct ast_frame *f;
05909
05910 while (ast_mutex_trylock(&p->lock)) {
05911 DEADLOCK_AVOIDANCE(&ast->lock);
05912 }
05913
05914 index = dahdi_get_index(ast, p, 0);
05915
05916
05917 if (index < 0) {
05918 ast_log(LOG_WARNING, "We dont exist?\n");
05919 ast_mutex_unlock(&p->lock);
05920 return NULL;
05921 }
05922
05923 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05924 ast_mutex_unlock(&p->lock);
05925 return NULL;
05926 }
05927
05928 p->subs[index].f.frametype = AST_FRAME_NULL;
05929 p->subs[index].f.datalen = 0;
05930 p->subs[index].f.samples = 0;
05931 p->subs[index].f.mallocd = 0;
05932 p->subs[index].f.offset = 0;
05933 p->subs[index].f.subclass = 0;
05934 p->subs[index].f.delivery = ast_tv(0,0);
05935 p->subs[index].f.src = "dahdi_read";
05936 p->subs[index].f.data = NULL;
05937
05938
05939 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05940 {
05941 struct dahdi_params ps;
05942
05943 memset(&ps, 0, sizeof(ps));
05944 ps.channo = p->channel;
05945 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05946 ast_mutex_unlock(&p->lock);
05947 return NULL;
05948 }
05949 p->firstradio = 1;
05950 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05951 if (ps.rxisoffhook)
05952 {
05953 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05954 }
05955 else
05956 {
05957 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05958 }
05959 ast_mutex_unlock(&p->lock);
05960 return &p->subs[index].f;
05961 }
05962 if (p->ringt == 1) {
05963 ast_mutex_unlock(&p->lock);
05964 return NULL;
05965 }
05966 else if (p->ringt > 0)
05967 p->ringt--;
05968
05969 #ifdef HAVE_OPENR2
05970 if (p->mfcr2) {
05971 openr2_chan_process_event(p->r2chan);
05972 }
05973 #endif
05974
05975 if (p->subs[index].needringing) {
05976
05977 p->subs[index].needringing = 0;
05978 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05979 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05980 ast_setstate(ast, AST_STATE_RINGING);
05981 ast_mutex_unlock(&p->lock);
05982 return &p->subs[index].f;
05983 }
05984
05985 if (p->subs[index].needbusy) {
05986
05987 p->subs[index].needbusy = 0;
05988 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05989 p->subs[index].f.subclass = AST_CONTROL_BUSY;
05990 ast_mutex_unlock(&p->lock);
05991 return &p->subs[index].f;
05992 }
05993
05994 if (p->subs[index].needcongestion) {
05995
05996 p->subs[index].needcongestion = 0;
05997 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05998 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
05999 ast_mutex_unlock(&p->lock);
06000 return &p->subs[index].f;
06001 }
06002
06003 if (p->subs[index].needcallerid) {
06004 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06005 S_OR(p->lastcid_name, NULL),
06006 S_OR(p->lastcid_num, NULL)
06007 );
06008 p->subs[index].needcallerid = 0;
06009 }
06010
06011 if (p->subs[index].needanswer) {
06012
06013 p->subs[index].needanswer = 0;
06014 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06015 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
06016 ast_mutex_unlock(&p->lock);
06017 return &p->subs[index].f;
06018 }
06019
06020 #ifdef HAVE_OPENR2
06021 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06022
06023
06024
06025
06026 p->subs[index].f.frametype = AST_FRAME_NULL;
06027 p->subs[index].f.subclass = 0;
06028 p->subs[index].f.samples = 0;
06029 p->subs[index].f.mallocd = 0;
06030 p->subs[index].f.offset = 0;
06031 p->subs[index].f.data = NULL;
06032 p->subs[index].f.datalen= 0;
06033 ast_mutex_unlock(&p->lock);
06034 return &p->subs[index].f;
06035 }
06036 #endif
06037
06038 if (p->subs[index].needflash) {
06039
06040 p->subs[index].needflash = 0;
06041 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06042 p->subs[index].f.subclass = AST_CONTROL_FLASH;
06043 ast_mutex_unlock(&p->lock);
06044 return &p->subs[index].f;
06045 }
06046
06047 if (p->subs[index].needhold) {
06048
06049 p->subs[index].needhold = 0;
06050 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06051 p->subs[index].f.subclass = AST_CONTROL_HOLD;
06052 ast_mutex_unlock(&p->lock);
06053 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
06054 return &p->subs[index].f;
06055 }
06056
06057 if (p->subs[index].needunhold) {
06058
06059 p->subs[index].needunhold = 0;
06060 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06061 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
06062 ast_mutex_unlock(&p->lock);
06063 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
06064 return &p->subs[index].f;
06065 }
06066
06067 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06068 if (!p->subs[index].linear) {
06069 p->subs[index].linear = 1;
06070 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06071 if (res)
06072 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
06073 }
06074 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06075 (ast->rawreadformat == AST_FORMAT_ALAW)) {
06076 if (p->subs[index].linear) {
06077 p->subs[index].linear = 0;
06078 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06079 if (res)
06080 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
06081 }
06082 } else {
06083 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06084 ast_mutex_unlock(&p->lock);
06085 return NULL;
06086 }
06087 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
06088 CHECK_BLOCKING(ast);
06089 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06090 ast_clear_flag(ast, AST_FLAG_BLOCKING);
06091
06092 if (res < 0) {
06093 f = NULL;
06094 if (res == -1) {
06095 if (errno == EAGAIN) {
06096
06097 ast_mutex_unlock(&p->lock);
06098 return &p->subs[index].f;
06099 } else if (errno == ELAST) {
06100 f = __dahdi_exception(ast);
06101 } else
06102 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06103 }
06104 ast_mutex_unlock(&p->lock);
06105 return f;
06106 }
06107 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06108 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06109 f = __dahdi_exception(ast);
06110 ast_mutex_unlock(&p->lock);
06111 return f;
06112 }
06113 if (p->tdd) {
06114 int c;
06115
06116 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06117 if (c < 0) {
06118 ast_log(LOG_DEBUG,"tdd_feed failed\n");
06119 ast_mutex_unlock(&p->lock);
06120 return NULL;
06121 }
06122 if (c) {
06123 p->subs[index].f.subclass = 0;
06124 p->subs[index].f.frametype = AST_FRAME_TEXT;
06125 p->subs[index].f.mallocd = 0;
06126 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06127 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06128 p->subs[index].f.datalen = 1;
06129 *((char *) p->subs[index].f.data) = c;
06130 ast_mutex_unlock(&p->lock);
06131 return &p->subs[index].f;
06132 }
06133 }
06134
06135 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06136 p->callwaitingrepeat--;
06137 }
06138 if (p->cidcwexpire)
06139 p->cidcwexpire--;
06140
06141 if (p->callwaitingrepeat == 1) {
06142 p->callwaitrings++;
06143 dahdi_callwait(ast);
06144 }
06145
06146 if (p->cidcwexpire == 1) {
06147 if (option_verbose > 2)
06148 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06149 restore_conference(p);
06150 }
06151 if (p->subs[index].linear) {
06152 p->subs[index].f.datalen = READ_SIZE * 2;
06153 } else
06154 p->subs[index].f.datalen = READ_SIZE;
06155
06156
06157 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06158 send_callerid(p);
06159 }
06160
06161 p->subs[index].f.frametype = AST_FRAME_VOICE;
06162 p->subs[index].f.subclass = ast->rawreadformat;
06163 p->subs[index].f.samples = READ_SIZE;
06164 p->subs[index].f.mallocd = 0;
06165 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06166 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06167 #if 0
06168 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06169 #endif
06170 if (p->dialing ||
06171 (index && (ast->_state != AST_STATE_UP)) ||
06172 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
06173 ) {
06174
06175
06176 p->subs[index].f.frametype = AST_FRAME_NULL;
06177 p->subs[index].f.subclass = 0;
06178 p->subs[index].f.samples = 0;
06179 p->subs[index].f.mallocd = 0;
06180 p->subs[index].f.offset = 0;
06181 p->subs[index].f.data = NULL;
06182 p->subs[index].f.datalen= 0;
06183 }
06184 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
06185
06186 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06187 if (f) {
06188 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06189 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06190
06191
06192 f = NULL;
06193 }
06194 } else if (f->frametype == AST_FRAME_DTMF) {
06195 #ifdef HAVE_PRI
06196 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial &&
06197 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
06198 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06199
06200 f->frametype = AST_FRAME_NULL;
06201 f->subclass = 0;
06202 }
06203 #endif
06204
06205 p->pulsedial = 0;
06206 }
06207 }
06208 } else
06209 f = &p->subs[index].f;
06210
06211 if (f && (f->frametype == AST_FRAME_DTMF))
06212 dahdi_handle_dtmfup(ast, index, &f);
06213
06214
06215 if (p->fake_event)
06216 ast_set_flag(ast, AST_FLAG_EXCEPTION);
06217
06218 ast_mutex_unlock(&p->lock);
06219 return f;
06220 }
06221
06222 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
06223 {
06224 int sent=0;
06225 int size;
06226 int res;
06227 int fd;
06228 fd = p->subs[index].dfd;
06229 while (len) {
06230 size = len;
06231 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06232 size = (linear ? READ_SIZE * 2 : READ_SIZE);
06233 res = write(fd, buf, size);
06234 if (res != size) {
06235 if (option_debug)
06236 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06237 return sent;
06238 }
06239 len -= size;
06240 buf += size;
06241 }
06242 return sent;
06243 }
06244
06245 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06246 {
06247 struct dahdi_pvt *p = ast->tech_pvt;
06248 int res;
06249 int index;
06250 index = dahdi_get_index(ast, p, 0);
06251 if (index < 0) {
06252 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06253 return -1;
06254 }
06255
06256 #if 0
06257 #ifdef HAVE_PRI
06258 ast_mutex_lock(&p->lock);
06259 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06260 if (p->pri->pri) {
06261 if (!pri_grab(p, p->pri)) {
06262 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06263 pri_rel(p->pri);
06264 } else
06265 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06266 }
06267 p->proceeding=1;
06268 }
06269 ast_mutex_unlock(&p->lock);
06270 #endif
06271 #endif
06272
06273 if (frame->frametype != AST_FRAME_VOICE) {
06274 if (frame->frametype != AST_FRAME_IMAGE)
06275 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06276 return 0;
06277 }
06278 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06279 (frame->subclass != AST_FORMAT_ULAW) &&
06280 (frame->subclass != AST_FORMAT_ALAW)) {
06281 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06282 return -1;
06283 }
06284 if (p->dialing) {
06285 if (option_debug)
06286 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06287 return 0;
06288 }
06289 if (!p->owner) {
06290 if (option_debug)
06291 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06292 return 0;
06293 }
06294 if (p->cidspill) {
06295 if (option_debug)
06296 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
06297 return 0;
06298 }
06299
06300 if (!frame->data || !frame->datalen)
06301 return 0;
06302
06303 if (frame->subclass == AST_FORMAT_SLINEAR) {
06304 if (!p->subs[index].linear) {
06305 p->subs[index].linear = 1;
06306 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06307 if (res)
06308 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06309 }
06310 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06311 } else {
06312
06313 if (p->subs[index].linear) {
06314 p->subs[index].linear = 0;
06315 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06316 if (res)
06317 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06318 }
06319 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06320 }
06321 if (res < 0) {
06322 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06323 return -1;
06324 }
06325 return 0;
06326 }
06327
06328 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06329 {
06330 struct dahdi_pvt *p = chan->tech_pvt;
06331 int res=-1;
06332 int index;
06333 int func = DAHDI_FLASH;
06334 ast_mutex_lock(&p->lock);
06335 index = dahdi_get_index(chan, p, 0);
06336 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06337 #ifdef HAVE_OPENR2
06338 if (p->mfcr2 && !p->mfcr2_call_accepted) {
06339 ast_mutex_unlock(&p->lock);
06340
06341
06342 return 0;
06343 }
06344 #endif
06345 if (index == SUB_REAL) {
06346 switch (condition) {
06347 case AST_CONTROL_BUSY:
06348 #ifdef HAVE_PRI
06349 if (p->priindication_oob && p->sig == SIG_PRI) {
06350 chan->hangupcause = AST_CAUSE_USER_BUSY;
06351 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06352 res = 0;
06353 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06354 if (p->pri->pri) {
06355 if (!pri_grab(p, p->pri)) {
06356 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06357 pri_rel(p->pri);
06358 }
06359 else
06360 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06361 }
06362 p->progress = 1;
06363 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06364 } else
06365 #endif
06366 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06367 break;
06368 case AST_CONTROL_RINGING:
06369 #ifdef HAVE_PRI
06370 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06371 if (p->pri->pri) {
06372 if (!pri_grab(p, p->pri)) {
06373 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06374 pri_rel(p->pri);
06375 }
06376 else
06377 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06378 }
06379 p->alerting = 1;
06380 }
06381 #endif
06382 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06383 if (chan->_state != AST_STATE_UP) {
06384 if ((chan->_state != AST_STATE_RING) ||
06385 ((p->sig != SIG_FXSKS) &&
06386 (p->sig != SIG_FXSLS) &&
06387 (p->sig != SIG_FXSGS)))
06388 ast_setstate(chan, AST_STATE_RINGING);
06389 }
06390 break;
06391 case AST_CONTROL_PROCEEDING:
06392 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06393 #ifdef HAVE_PRI
06394 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06395 if (p->pri->pri) {
06396 if (!pri_grab(p, p->pri)) {
06397 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06398 pri_rel(p->pri);
06399 }
06400 else
06401 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06402 }
06403 p->proceeding = 1;
06404 p->dialing = 0;
06405 }
06406 #endif
06407
06408 res = 0;
06409 break;
06410 case AST_CONTROL_PROGRESS:
06411 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06412 #ifdef HAVE_PRI
06413 p->digital = 0;
06414 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06415 if (p->pri->pri) {
06416 if (!pri_grab(p, p->pri)) {
06417 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06418 pri_rel(p->pri);
06419 }
06420 else
06421 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06422 }
06423 p->progress = 1;
06424 }
06425 #endif
06426
06427 res = 0;
06428 break;
06429 case AST_CONTROL_CONGESTION:
06430 chan->hangupcause = AST_CAUSE_CONGESTION;
06431 #ifdef HAVE_PRI
06432 if (p->priindication_oob && p->sig == SIG_PRI) {
06433 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06434 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06435 res = 0;
06436 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06437 if (p->pri) {
06438 if (!pri_grab(p, p->pri)) {
06439 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06440 pri_rel(p->pri);
06441 } else
06442 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06443 }
06444 p->progress = 1;
06445 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06446 } else
06447 #endif
06448 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06449 break;
06450 case AST_CONTROL_HOLD:
06451 #ifdef HAVE_PRI
06452 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06453 if (!pri_grab(p, p->pri)) {
06454 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06455 pri_rel(p->pri);
06456 } else
06457 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06458 } else
06459 #endif
06460 ast_moh_start(chan, data, p->mohinterpret);
06461 break;
06462 case AST_CONTROL_UNHOLD:
06463 #ifdef HAVE_PRI
06464 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06465 if (!pri_grab(p, p->pri)) {
06466 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06467 pri_rel(p->pri);
06468 } else
06469 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06470 } else
06471 #endif
06472 ast_moh_stop(chan);
06473 break;
06474 case AST_CONTROL_RADIO_KEY:
06475 if (p->radio)
06476 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06477 res = 0;
06478 break;
06479 case AST_CONTROL_RADIO_UNKEY:
06480 if (p->radio)
06481 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06482 res = 0;
06483 break;
06484 case AST_CONTROL_FLASH:
06485
06486 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06487
06488 p->dop.dialstr[0] = '\0';
06489 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06490 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06491 chan->name, strerror(errno));
06492 } else
06493 res = 0;
06494 } else
06495 res = 0;
06496 break;
06497 case AST_CONTROL_SRCUPDATE:
06498 res = 0;
06499 break;
06500 case -1:
06501 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06502 break;
06503 }
06504 } else
06505 res = 0;
06506 ast_mutex_unlock(&p->lock);
06507 return res;
06508 }
06509
06510 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
06511 {
06512 struct ast_channel *tmp;
06513 int deflaw;
06514 int res;
06515 int x,y;
06516 int features;
06517 char *b2 = NULL;
06518 struct dahdi_params ps;
06519 char chanprefix[*dahdi_chan_name_len + 4];
06520
06521 if (i->subs[index].owner) {
06522 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
06523 return NULL;
06524 }
06525 y = 1;
06526 do {
06527 if (b2)
06528 free(b2);
06529 #ifdef HAVE_PRI
06530 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06531 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06532 else
06533 #endif
06534 if (i->channel == CHAN_PSEUDO)
06535 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
06536 else
06537 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
06538 for (x = 0; x < 3; x++) {
06539 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
06540 break;
06541 }
06542 y++;
06543 } while (x < 3);
06544 strcpy(chanprefix, dahdi_chan_name);
06545 strcat(chanprefix, "/%s");
06546 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
06547 if (b2)
06548 free(b2);
06549 if (!tmp)
06550 return NULL;
06551 tmp->tech = chan_tech;
06552 memset(&ps, 0, sizeof(ps));
06553 ps.channo = i->channel;
06554 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06555 if (res) {
06556 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06557 ps.curlaw = DAHDI_LAW_MULAW;
06558 }
06559 if (ps.curlaw == DAHDI_LAW_ALAW)
06560 deflaw = AST_FORMAT_ALAW;
06561 else
06562 deflaw = AST_FORMAT_ULAW;
06563 if (law) {
06564 if (law == DAHDI_LAW_ALAW)
06565 deflaw = AST_FORMAT_ALAW;
06566 else
06567 deflaw = AST_FORMAT_ULAW;
06568 }
06569 tmp->fds[0] = i->subs[index].dfd;
06570 tmp->nativeformats = deflaw;
06571
06572 tmp->rawreadformat = deflaw;
06573 tmp->readformat = deflaw;
06574 tmp->rawwriteformat = deflaw;
06575 tmp->writeformat = deflaw;
06576 i->subs[index].linear = 0;
06577 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
06578 features = 0;
06579 if (index == SUB_REAL) {
06580 if (i->busydetect && CANBUSYDETECT(i))
06581 features |= DSP_FEATURE_BUSY_DETECT;
06582 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
06583 features |= DSP_FEATURE_CALL_PROGRESS;
06584 if ((!i->outgoing && (i->callprogress & 4)) ||
06585 (i->outgoing && (i->callprogress & 2))) {
06586 features |= DSP_FEATURE_FAX_DETECT;
06587 }
06588 #ifdef DAHDI_TONEDETECT
06589 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06590 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
06591 #endif
06592 i->hardwaredtmf = 0;
06593 features |= DSP_FEATURE_DTMF_DETECT;
06594 #ifdef DAHDI_TONEDETECT
06595 } else if (NEED_MFDETECT(i)) {
06596 i->hardwaredtmf = 1;
06597 features |= DSP_FEATURE_DTMF_DETECT;
06598 }
06599 #endif
06600 }
06601 if (features) {
06602 if (i->dsp) {
06603 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
06604 } else {
06605 if (i->channel != CHAN_PSEUDO)
06606 i->dsp = ast_dsp_new();
06607 else
06608 i->dsp = NULL;
06609 if (i->dsp) {
06610 i->dsp_features = features;
06611 #ifdef HAVE_PRI
06612
06613 if (i->outgoing && (i->sig == SIG_PRI)) {
06614
06615
06616 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06617 features = 0;
06618 }
06619 #endif
06620 ast_dsp_set_features(i->dsp, features);
06621 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06622 if (!ast_strlen_zero(progzone))
06623 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06624 if (i->busydetect && CANBUSYDETECT(i)) {
06625 if(i->silencethreshold > 0)
06626 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06627 ast_dsp_set_busy_count(i->dsp, i->busycount);
06628 if(i->busytonelength > 0)
06629 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06630 if((i->busytonelength == i->busyquietlength) && i->busycompare)
06631 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06632 }
06633 }
06634 }
06635 }
06636
06637 if (state == AST_STATE_RING)
06638 tmp->rings = 1;
06639 tmp->tech_pvt = i;
06640 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06641
06642 tmp->callgroup = i->callgroup;
06643 tmp->pickupgroup = i->pickupgroup;
06644 }
06645 if (!ast_strlen_zero(i->language))
06646 ast_string_field_set(tmp, language, i->language);
06647 if (!i->owner)
06648 i->owner = tmp;
06649 if (!ast_strlen_zero(i->accountcode))
06650 ast_string_field_set(tmp, accountcode, i->accountcode);
06651 if (i->amaflags)
06652 tmp->amaflags = i->amaflags;
06653 i->subs[index].owner = tmp;
06654 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06655 ast_string_field_set(tmp, call_forward, i->call_forward);
06656
06657 if (!i->adsi)
06658 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06659 if (!ast_strlen_zero(i->exten))
06660 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06661 if (!ast_strlen_zero(i->rdnis))
06662 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06663 if (!ast_strlen_zero(i->dnid))
06664 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06665
06666
06667
06668 #ifdef PRI_ANI
06669 if (!ast_strlen_zero(i->cid_ani))
06670 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06671 else
06672 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06673 #else
06674 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06675 #endif
06676 tmp->cid.cid_pres = i->callingpres;
06677 tmp->cid.cid_ton = i->cid_ton;
06678 #ifdef HAVE_PRI
06679 tmp->transfercapability = transfercapability;
06680 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06681 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
06682 i->digital = 1;
06683
06684 i->isidlecall = 0;
06685 i->alreadyhungup = 0;
06686 #endif
06687
06688 i->fake_event = 0;
06689
06690 dahdi_confmute(i, 0);
06691
06692 ast_jb_configure(tmp, &global_jbconf);
06693 if (startpbx) {
06694 #ifdef HAVE_OPENR2
06695 if (i->mfcr2call) {
06696 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
06697 }
06698 #endif
06699 if (ast_pbx_start(tmp)) {
06700 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06701 ast_hangup(tmp);
06702 i->owner = NULL;
06703 return NULL;
06704 }
06705 }
06706
06707 ast_module_ref(ast_module_info->self);
06708
06709 return tmp;
06710 }
06711
06712
06713 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06714 {
06715 char c;
06716
06717 *str = 0;
06718 for (;;)
06719 {
06720
06721 c = ast_waitfordigit(chan, ms);
06722
06723 if (c < 1)
06724 return c;
06725 *str++ = c;
06726 *str = 0;
06727 if (strchr(term, c))
06728 return 1;
06729 }
06730 }
06731
06732 static int dahdi_wink(struct dahdi_pvt *p, int index)
06733 {
06734 int j;
06735 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06736 for (;;)
06737 {
06738
06739 j = DAHDI_IOMUX_SIGEVENT;
06740
06741 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06742
06743 if (j & DAHDI_IOMUX_SIGEVENT) break;
06744 }
06745
06746 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06747 return 0;
06748 }
06749
06750 static void *ss_thread(void *data)
06751 {
06752 struct ast_channel *chan = data;
06753 struct dahdi_pvt *p = chan->tech_pvt;
06754 char exten[AST_MAX_EXTENSION] = "";
06755 char exten2[AST_MAX_EXTENSION] = "";
06756 unsigned char buf[256];
06757 char dtmfcid[300];
06758 char dtmfbuf[300];
06759 struct callerid_state *cs = NULL;
06760 char *name = NULL, *number = NULL;
06761 int distMatches;
06762 int curRingData[3];
06763 int receivedRingT;
06764 int counter1;
06765 int counter;
06766 int samples = 0;
06767 struct ast_smdi_md_message *smdi_msg = NULL;
06768 int flags = 0;
06769 int i;
06770 int timeout;
06771 int getforward = 0;
06772 char *s1, *s2;
06773 int len = 0;
06774 int res;
06775 int index;
06776
06777 ast_mutex_lock(&ss_thread_lock);
06778 ss_thread_count++;
06779 ast_mutex_unlock(&ss_thread_lock);
06780
06781
06782
06783 if (!p) {
06784 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06785 ast_hangup(chan);
06786 goto quit;
06787 }
06788 if (option_verbose > 2)
06789 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
06790 index = dahdi_get_index(chan, p, 1);
06791 if (index < 0) {
06792 ast_log(LOG_WARNING, "Huh?\n");
06793 ast_hangup(chan);
06794 goto quit;
06795 }
06796 if (p->dsp)
06797 ast_dsp_digitreset(p->dsp);
06798 switch (p->sig) {
06799 #ifdef HAVE_PRI
06800 case SIG_PRI:
06801
06802 ast_copy_string(exten, p->exten, sizeof(exten));
06803 len = strlen(exten);
06804 res = 0;
06805 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06806 if (len && !ast_ignore_pattern(chan->context, exten))
06807 tone_zone_play_tone(p->subs[index].dfd, -1);
06808 else
06809 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06810 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06811 timeout = matchdigittimeout;
06812 else
06813 timeout = gendigittimeout;
06814 res = ast_waitfordigit(chan, timeout);
06815 if (res < 0) {
06816 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06817 ast_hangup(chan);
06818 goto quit;
06819 } else if (res) {
06820 exten[len++] = res;
06821 exten[len] = '\0';
06822 } else
06823 break;
06824 }
06825
06826 if (ast_strlen_zero(exten)) {
06827 if (option_verbose > 2)
06828 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
06829 exten[0] = 's';
06830 exten[1] = '\0';
06831 }
06832 tone_zone_play_tone(p->subs[index].dfd, -1);
06833 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06834
06835 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06836 if (p->dsp) ast_dsp_digitreset(p->dsp);
06837 dahdi_enable_ec(p);
06838 ast_setstate(chan, AST_STATE_RING);
06839 res = ast_pbx_run(chan);
06840 if (res) {
06841 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06842 }
06843 } else {
06844 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06845 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06846 ast_hangup(chan);
06847 p->exten[0] = '\0';
06848
06849 p->call = NULL;
06850 }
06851 goto quit;
06852 break;
06853 #endif
06854 case SIG_FEATD:
06855 case SIG_FEATDMF:
06856 case SIG_FEATDMF_TA:
06857 case SIG_E911:
06858 case SIG_FGC_CAMAMF:
06859 case SIG_FEATB:
06860 case SIG_EMWINK:
06861 case SIG_SF_FEATD:
06862 case SIG_SF_FEATDMF:
06863 case SIG_SF_FEATB:
06864 case SIG_SFWINK:
06865 if (dahdi_wink(p, index))
06866 goto quit;
06867
06868 case SIG_EM:
06869 case SIG_EM_E1:
06870 case SIG_SF:
06871 case SIG_FGC_CAMA:
06872 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06873 if (p->dsp)
06874 ast_dsp_digitreset(p->dsp);
06875
06876 if (p->dsp) {
06877 if (NEED_MFDETECT(p))
06878 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06879 else
06880 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06881 }
06882 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06883
06884 if (!p->immediate)
06885
06886 res = ast_waitfordigit(chan, 5000);
06887 else
06888 res = 0;
06889 if (res > 0) {
06890
06891 dtmfbuf[0] = res;
06892 switch (p->sig) {
06893 case SIG_FEATD:
06894 case SIG_SF_FEATD:
06895 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06896 if (res > 0)
06897 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06898 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06899 break;
06900 case SIG_FEATDMF_TA:
06901 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06902 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06903 if (dahdi_wink(p, index)) goto quit;
06904 dtmfbuf[0] = 0;
06905
06906 res = ast_waitfordigit(chan, 5000);
06907 if (res <= 0) break;
06908 dtmfbuf[0] = res;
06909
06910 case SIG_FEATDMF:
06911 case SIG_E911:
06912 case SIG_FGC_CAMAMF:
06913 case SIG_SF_FEATDMF:
06914 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06915
06916 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06917 {
06918 if (dahdi_wink(p, index)) goto quit;
06919 dtmfbuf[0] = 0;
06920
06921 res = ast_waitfordigit(chan, 5000);
06922 if (res <= 0) break;
06923 dtmfbuf[0] = res;
06924 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06925 }
06926 if (res > 0) {
06927
06928 if (p->sig == SIG_E911)
06929 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06930 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06931 }
06932 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06933 break;
06934 case SIG_FEATB:
06935 case SIG_SF_FEATB:
06936 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06937 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06938 break;
06939 case SIG_EMWINK:
06940
06941
06942
06943
06944 if (res == '*') {
06945 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06946 if (res > 0)
06947 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06948 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06949 break;
06950 }
06951 default:
06952
06953 len = 1;
06954 dtmfbuf[len] = '\0';
06955 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06956 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06957 timeout = matchdigittimeout;
06958 } else {
06959 timeout = gendigittimeout;
06960 }
06961 res = ast_waitfordigit(chan, timeout);
06962 if (res < 0) {
06963 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06964 ast_hangup(chan);
06965 goto quit;
06966 } else if (res) {
06967 dtmfbuf[len++] = res;
06968 dtmfbuf[len] = '\0';
06969 } else {
06970 break;
06971 }
06972 }
06973 break;
06974 }
06975 }
06976 if (res == -1) {
06977 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06978 ast_hangup(chan);
06979 goto quit;
06980 } else if (res < 0) {
06981 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06982 ast_hangup(chan);
06983 goto quit;
06984 }
06985
06986 if (p->sig == SIG_FGC_CAMA) {
06987 char anibuf[100];
06988
06989 if (ast_safe_sleep(chan,1000) == -1) {
06990 ast_hangup(chan);
06991 goto quit;
06992 }
06993 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06994 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06995 res = my_getsigstr(chan, anibuf, "#", 10000);
06996 if ((res > 0) && (strlen(anibuf) > 2)) {
06997 if (anibuf[strlen(anibuf) - 1] == '#')
06998 anibuf[strlen(anibuf) - 1] = 0;
06999 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07000 }
07001 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07002 }
07003
07004 ast_copy_string(exten, dtmfbuf, sizeof(exten));
07005 if (ast_strlen_zero(exten))
07006 ast_copy_string(exten, "s", sizeof(exten));
07007 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07008
07009 if (exten[0] == '*') {
07010 char *stringp=NULL;
07011 ast_copy_string(exten2, exten, sizeof(exten2));
07012
07013 stringp=exten2 +1;
07014 s1 = strsep(&stringp, "*");
07015 s2 = strsep(&stringp, "*");
07016 if (s2) {
07017 if (!ast_strlen_zero(p->cid_num))
07018 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07019 else
07020 ast_set_callerid(chan, s1, NULL, s1);
07021 ast_copy_string(exten, s2, sizeof(exten));
07022 } else
07023 ast_copy_string(exten, s1, sizeof(exten));
07024 } else if (p->sig == SIG_FEATD)
07025 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07026 }
07027 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07028 if (exten[0] == '*') {
07029 char *stringp=NULL;
07030 ast_copy_string(exten2, exten, sizeof(exten2));
07031
07032 stringp=exten2 +1;
07033 s1 = strsep(&stringp, "#");
07034 s2 = strsep(&stringp, "#");
07035 if (s2) {
07036 if (!ast_strlen_zero(p->cid_num))
07037 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07038 else
07039 if (*(s1 + 2))
07040 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07041 ast_copy_string(exten, s2 + 1, sizeof(exten));
07042 } else
07043 ast_copy_string(exten, s1 + 2, sizeof(exten));
07044 } else
07045 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07046 }
07047 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07048 if (exten[0] == '*') {
07049 char *stringp=NULL;
07050 ast_copy_string(exten2, exten, sizeof(exten2));
07051
07052 stringp=exten2 +1;
07053 s1 = strsep(&stringp, "#");
07054 s2 = strsep(&stringp, "#");
07055 if (s2 && (*(s2 + 1) == '0')) {
07056 if (*(s2 + 2))
07057 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07058 }
07059 if (s1) ast_copy_string(exten, s1, sizeof(exten));
07060 else ast_copy_string(exten, "911", sizeof(exten));
07061 } else
07062 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
07063 }
07064 if (p->sig == SIG_FEATB) {
07065 if (exten[0] == '*') {
07066 char *stringp=NULL;
07067 ast_copy_string(exten2, exten, sizeof(exten2));
07068
07069 stringp=exten2 +1;
07070 s1 = strsep(&stringp, "#");
07071 ast_copy_string(exten, exten2 + 1, sizeof(exten));
07072 } else
07073 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
07074 }
07075 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07076 dahdi_wink(p, index);
07077
07078
07079
07080 if (ast_safe_sleep(chan,100)) goto quit;
07081 }
07082 dahdi_enable_ec(p);
07083 if (NEED_MFDETECT(p)) {
07084 if (p->dsp) {
07085 if (!p->hardwaredtmf)
07086 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07087 else {
07088 ast_dsp_free(p->dsp);
07089 p->dsp = NULL;
07090 }
07091 }
07092 }
07093
07094 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07095 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07096 if (p->dsp) ast_dsp_digitreset(p->dsp);
07097 res = ast_pbx_run(chan);
07098 if (res) {
07099 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07100 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07101 }
07102 goto quit;
07103 } else {
07104 if (option_verbose > 2)
07105 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07106 sleep(2);
07107 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07108 if (res < 0)
07109 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07110 else
07111 sleep(1);
07112 res = ast_streamfile(chan, "ss-noservice", chan->language);
07113 if (res >= 0)
07114 ast_waitstream(chan, "");
07115 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07116 ast_hangup(chan);
07117 goto quit;
07118 }
07119 break;
07120 case SIG_FXOLS:
07121 case SIG_FXOGS:
07122 case SIG_FXOKS:
07123
07124 timeout = firstdigittimeout;
07125
07126
07127 if (p->subs[SUB_THREEWAY].owner)
07128 timeout = 999999;
07129 while (len < AST_MAX_EXTENSION-1) {
07130
07131
07132 if (p->immediate)
07133 res = 's';
07134 else
07135 res = ast_waitfordigit(chan, timeout);
07136 timeout = 0;
07137 if (res < 0) {
07138 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07139 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07140 ast_hangup(chan);
07141 goto quit;
07142 } else if (res) {
07143 exten[len++]=res;
07144 exten[len] = '\0';
07145 }
07146 if (!ast_ignore_pattern(chan->context, exten))
07147 tone_zone_play_tone(p->subs[index].dfd, -1);
07148 else
07149 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07150 if (!strcmp(exten,ast_pickup_ext())) {
07151
07152
07153
07154
07155 if (index == SUB_REAL) {
07156
07157 if (p->subs[SUB_THREEWAY].owner) {
07158
07159
07160 alloc_sub(p, SUB_CALLWAIT);
07161 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07162 unalloc_sub(p, SUB_THREEWAY);
07163 }
07164 dahdi_enable_ec(p);
07165 if (ast_pickup_call(chan)) {
07166 ast_log(LOG_DEBUG, "No call pickup possible...\n");
07167 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07168 dahdi_wait_event(p->subs[index].dfd);
07169 }
07170 ast_hangup(chan);
07171 goto quit;
07172 } else {
07173 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07174 ast_hangup(chan);
07175 goto quit;
07176 }
07177
07178 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07179 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07180 if (getforward) {
07181
07182 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
07183 if (option_verbose > 2)
07184 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07185 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07186 if (res)
07187 break;
07188 usleep(500000);
07189 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07190 sleep(1);
07191 memset(exten, 0, sizeof(exten));
07192 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07193 len = 0;
07194 getforward = 0;
07195 } else {
07196 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07197 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07198 if (!ast_strlen_zero(p->cid_num)) {
07199 if (!p->hidecallerid)
07200 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07201 else
07202 ast_set_callerid(chan, NULL, NULL, p->cid_num);
07203 }
07204 if (!ast_strlen_zero(p->cid_name)) {
07205 if (!p->hidecallerid)
07206 ast_set_callerid(chan, NULL, p->cid_name, NULL);
07207 }
07208 ast_setstate(chan, AST_STATE_RING);
07209 dahdi_enable_ec(p);
07210 res = ast_pbx_run(chan);
07211 if (res) {
07212 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07213 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07214 }
07215 goto quit;
07216 }
07217 } else {
07218
07219
07220 timeout = matchdigittimeout;
07221 }
07222 } else if (res == 0) {
07223 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07224 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07225 dahdi_wait_event(p->subs[index].dfd);
07226 ast_hangup(chan);
07227 goto quit;
07228 } else if (p->callwaiting && !strcmp(exten, "*70")) {
07229 if (option_verbose > 2)
07230 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07231
07232 p->callwaiting = 0;
07233 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07234 if (res) {
07235 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07236 chan->name, strerror(errno));
07237 }
07238 len = 0;
07239 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07240 memset(exten, 0, sizeof(exten));
07241 timeout = firstdigittimeout;
07242
07243 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07244 if (option_verbose > 2)
07245 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07246
07247 p->hidecallerid = 1;
07248 if (chan->cid.cid_num)
07249 free(chan->cid.cid_num);
07250 chan->cid.cid_num = NULL;
07251 if (chan->cid.cid_name)
07252 free(chan->cid.cid_name);
07253 chan->cid.cid_name = NULL;
07254 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07255 if (res) {
07256 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07257 chan->name, strerror(errno));
07258 }
07259 len = 0;
07260 memset(exten, 0, sizeof(exten));
07261 timeout = firstdigittimeout;
07262 } else if (p->callreturn && !strcmp(exten, "*69")) {
07263 res = 0;
07264 if (!ast_strlen_zero(p->lastcid_num)) {
07265 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07266 }
07267 if (!res)
07268 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07269 break;
07270 } else if (!strcmp(exten, "*78")) {
07271
07272 if (option_verbose > 2)
07273 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07274 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07275 "Channel: %s/%d\r\n"
07276 "Status: enabled\r\n", dahdi_chan_name, p->channel);
07277 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07278 p->dnd = 1;
07279 getforward = 0;
07280 memset(exten, 0, sizeof(exten));
07281 len = 0;
07282 } else if (!strcmp(exten, "*79")) {
07283
07284 if (option_verbose > 2)
07285 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07286 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07287 "Channel: %s/%d\r\n"
07288 "Status: disabled\r\n", dahdi_chan_name, p->channel);
07289 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07290 p->dnd = 0;
07291 getforward = 0;
07292 memset(exten, 0, sizeof(exten));
07293 len = 0;
07294 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07295 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07296 getforward = 1;
07297 memset(exten, 0, sizeof(exten));
07298 len = 0;
07299 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07300 if (option_verbose > 2)
07301 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07302 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07303 memset(p->call_forward, 0, sizeof(p->call_forward));
07304 getforward = 0;
07305 memset(exten, 0, sizeof(exten));
07306 len = 0;
07307 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07308 p->subs[SUB_THREEWAY].owner &&
07309 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07310
07311
07312 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07313 if (option_verbose > 2)
07314 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07315 break;
07316 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07317 if (option_verbose > 2)
07318 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07319 res = ast_db_put("blacklist", p->lastcid_num, "1");
07320 if (!res) {
07321 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07322 memset(exten, 0, sizeof(exten));
07323 len = 0;
07324 }
07325 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07326 if (option_verbose > 2)
07327 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07328
07329 p->hidecallerid = 0;
07330 if (chan->cid.cid_num)
07331 free(chan->cid.cid_num);
07332 chan->cid.cid_num = NULL;
07333 if (chan->cid.cid_name)
07334 free(chan->cid.cid_name);
07335 chan->cid.cid_name = NULL;
07336 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07337 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07338 if (res) {
07339 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07340 chan->name, strerror(errno));
07341 }
07342 len = 0;
07343 memset(exten, 0, sizeof(exten));
07344 timeout = firstdigittimeout;
07345 } else if (!strcmp(exten, "*0")) {
07346 struct ast_channel *nbridge =
07347 p->subs[SUB_THREEWAY].owner;
07348 struct dahdi_pvt *pbridge = NULL;
07349
07350 if (nbridge && ast_bridged_channel(nbridge))
07351 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07352 if (nbridge && pbridge &&
07353 (nbridge->tech == chan_tech) &&
07354 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07355 ISTRUNK(pbridge)) {
07356 int func = DAHDI_FLASH;
07357
07358 p->dop.dialstr[0] = '\0';
07359
07360 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07361 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07362 nbridge->name, strerror(errno));
07363 }
07364 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07365 unalloc_sub(p, SUB_THREEWAY);
07366 p->owner = p->subs[SUB_REAL].owner;
07367 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07368 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07369 ast_hangup(chan);
07370 goto quit;
07371 } else {
07372 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07373 dahdi_wait_event(p->subs[index].dfd);
07374 tone_zone_play_tone(p->subs[index].dfd, -1);
07375 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07376 unalloc_sub(p, SUB_THREEWAY);
07377 p->owner = p->subs[SUB_REAL].owner;
07378 ast_hangup(chan);
07379 goto quit;
07380 }
07381 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07382 ((exten[0] != '*') || (strlen(exten) > 2))) {
07383 if (option_debug)
07384 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);
07385 break;
07386 }
07387 if (!timeout)
07388 timeout = gendigittimeout;
07389 if (len && !ast_ignore_pattern(chan->context, exten))
07390 tone_zone_play_tone(p->subs[index].dfd, -1);
07391 }
07392 break;
07393 case SIG_FXSLS:
07394 case SIG_FXSGS:
07395 case SIG_FXSKS:
07396 #ifdef HAVE_PRI
07397 if (p->pri) {
07398
07399 struct ast_frame *f;
07400 int res;
07401 time_t start;
07402
07403 time(&start);
07404 ast_setstate(chan, AST_STATE_RING);
07405 while (time(NULL) < start + 3) {
07406 res = ast_waitfor(chan, 1000);
07407 if (res) {
07408 f = ast_read(chan);
07409 if (!f) {
07410 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07411 ast_hangup(chan);
07412 goto quit;
07413 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07414 res = 1;
07415 } else
07416 res = 0;
07417 ast_frfree(f);
07418 if (res) {
07419 ast_log(LOG_DEBUG, "Got ring!\n");
07420 res = 0;
07421 break;
07422 }
07423 }
07424 }
07425 }
07426 #endif
07427
07428 if (p->use_smdi && p->smdi_iface) {
07429 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07430
07431 if (smdi_msg != NULL) {
07432 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07433
07434 if (smdi_msg->type == 'B')
07435 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07436 else if (smdi_msg->type == 'N')
07437 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07438
07439 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
07440 } else {
07441 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07442 }
07443 }
07444
07445 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07446 number = smdi_msg->calling_st;
07447
07448
07449
07450
07451 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
07452
07453 if (p->cid_signalling == CID_SIG_DTMF) {
07454 int i = 0;
07455 cs = NULL;
07456 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
07457 "channel %s\n", chan->name);
07458 dahdi_setlinear(p->subs[index].dfd, 0);
07459 res = 2000;
07460 for (;;) {
07461 struct ast_frame *f;
07462 res = ast_waitfor(chan, res);
07463 if (res <= 0) {
07464 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07465 "Exiting simple switch\n");
07466 ast_hangup(chan);
07467 goto quit;
07468 }
07469 f = ast_read(chan);
07470 if (!f)
07471 break;
07472 if (f->frametype == AST_FRAME_DTMF) {
07473 dtmfbuf[i++] = f->subclass;
07474 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07475 res = 2000;
07476 }
07477 ast_frfree(f);
07478 if (chan->_state == AST_STATE_RING ||
07479 chan->_state == AST_STATE_RINGING)
07480 break;
07481 }
07482 dtmfbuf[i] = '\0';
07483 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07484
07485 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
07486 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07487 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07488 dtmfcid, flags);
07489
07490 if (!ast_strlen_zero(dtmfcid))
07491 number = dtmfcid;
07492 else
07493 number = NULL;
07494
07495 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07496 cs = callerid_new(p->cid_signalling);
07497 if (cs) {
07498 samples = 0;
07499 #if 1
07500 bump_gains(p);
07501 #endif
07502
07503 dahdi_setlinear(p->subs[index].dfd, 0);
07504
07505
07506 for (;;) {
07507 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07508 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07509 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07510 callerid_free(cs);
07511 ast_hangup(chan);
07512 goto quit;
07513 }
07514 if (i & DAHDI_IOMUX_SIGEVENT) {
07515 res = dahdi_get_event(p->subs[index].dfd);
07516 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07517
07518 if (p->cid_signalling == CID_SIG_V23_JP) {
07519 #ifdef DAHDI_EVENT_RINGBEGIN
07520 if (res == DAHDI_EVENT_RINGBEGIN) {
07521 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07522 usleep(1);
07523 }
07524 #endif
07525 } else {
07526 res = 0;
07527 break;
07528 }
07529 } else if (i & DAHDI_IOMUX_READ) {
07530 res = read(p->subs[index].dfd, buf, sizeof(buf));
07531 if (res < 0) {
07532 if (errno != ELAST) {
07533 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07534 callerid_free(cs);
07535 ast_hangup(chan);
07536 goto quit;
07537 }
07538 break;
07539 }
07540 samples += res;
07541
07542 if (p->cid_signalling == CID_SIG_V23_JP) {
07543 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07544 } else {
07545 res = callerid_feed(cs, buf, res, AST_LAW(p));
07546 }
07547
07548 if (res < 0) {
07549 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07550 break;
07551 } else if (res)
07552 break;
07553 else if (samples > (8000 * 10))
07554 break;
07555 }
07556 }
07557 if (res == 1) {
07558 callerid_get(cs, &name, &number, &flags);
07559 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07560 }
07561
07562 if (p->cid_signalling == CID_SIG_V23_JP) {
07563 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07564 usleep(1);
07565 res = 4000;
07566 } else {
07567
07568
07569 res = 2000;
07570 }
07571
07572 for (;;) {
07573 struct ast_frame *f;
07574 res = ast_waitfor(chan, res);
07575 if (res <= 0) {
07576 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07577 "Exiting simple switch\n");
07578 ast_hangup(chan);
07579 goto quit;
07580 }
07581 if (!(f = ast_read(chan))) {
07582 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07583 ast_hangup(chan);
07584 goto quit;
07585 }
07586 ast_frfree(f);
07587 if (chan->_state == AST_STATE_RING ||
07588 chan->_state == AST_STATE_RINGING)
07589 break;
07590 }
07591
07592
07593
07594 if (p->usedistinctiveringdetection) {
07595 len = 0;
07596 distMatches = 0;
07597
07598 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07599 curRingData[receivedRingT] = 0;
07600 receivedRingT = 0;
07601 counter = 0;
07602 counter1 = 0;
07603
07604 if (strcmp(p->context,p->defcontext) != 0) {
07605 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07606 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07607 }
07608
07609 for (;;) {
07610 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07611 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07612 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07613 callerid_free(cs);
07614 ast_hangup(chan);
07615 goto quit;
07616 }
07617 if (i & DAHDI_IOMUX_SIGEVENT) {
07618 res = dahdi_get_event(p->subs[index].dfd);
07619 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07620 res = 0;
07621
07622
07623 curRingData[receivedRingT] = p->ringt;
07624
07625 if (p->ringt < p->ringt_base/2)
07626 break;
07627
07628
07629 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07630 break;
07631 } else if (i & DAHDI_IOMUX_READ) {
07632 res = read(p->subs[index].dfd, buf, sizeof(buf));
07633 if (res < 0) {
07634 if (errno != ELAST) {
07635 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07636 callerid_free(cs);
07637 ast_hangup(chan);
07638 goto quit;
07639 }
07640 break;
07641 }
07642 if (p->ringt)
07643 p->ringt--;
07644 if (p->ringt == 1) {
07645 res = -1;
07646 break;
07647 }
07648 }
07649 }
07650 if (option_verbose > 2)
07651
07652 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07653
07654 for (counter = 0; counter < 3; counter++) {
07655
07656
07657 distMatches = 0;
07658 for (counter1 = 0; counter1 < 3; counter1++) {
07659 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07660 (p->drings.ringnum[counter].ring[counter1]-10)) {
07661 distMatches++;
07662 }
07663 }
07664 if (distMatches == 3) {
07665
07666 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07667 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07668 if (option_verbose > 2)
07669 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07670 break;
07671 }
07672 }
07673 }
07674
07675 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07676 #if 1
07677 restore_gains(p);
07678 #endif
07679 } else
07680 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07681 } else {
07682 ast_log(LOG_WARNING, "Channel %s in prering "
07683 "state, but I have nothing to do. "
07684 "Terminating simple switch, should be "
07685 "restarted by the actual ring.\n",
07686 chan->name);
07687 ast_hangup(chan);
07688 goto quit;
07689 }
07690 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07691
07692 cs = callerid_new(p->cid_signalling);
07693 if (cs) {
07694 #if 1
07695 bump_gains(p);
07696 #endif
07697 samples = 0;
07698 len = 0;
07699 distMatches = 0;
07700
07701 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07702 curRingData[receivedRingT] = 0;
07703 receivedRingT = 0;
07704 counter = 0;
07705 counter1 = 0;
07706
07707 if (strcmp(p->context,p->defcontext) != 0) {
07708 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07709 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07710 }
07711
07712
07713 dahdi_setlinear(p->subs[index].dfd, 0);
07714 for (;;) {
07715 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07716 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07717 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07718 callerid_free(cs);
07719 ast_hangup(chan);
07720 goto quit;
07721 }
07722 if (i & DAHDI_IOMUX_SIGEVENT) {
07723 res = dahdi_get_event(p->subs[index].dfd);
07724 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07725
07726 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07727 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07728 p->polarity = POLARITY_IDLE;
07729 callerid_free(cs);
07730 ast_hangup(chan);
07731 goto quit;
07732 }
07733 res = 0;
07734
07735
07736 curRingData[receivedRingT] = p->ringt;
07737
07738 if (p->ringt < p->ringt_base/2)
07739 break;
07740
07741
07742 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07743 break;
07744 } else if (i & DAHDI_IOMUX_READ) {
07745 res = read(p->subs[index].dfd, buf, sizeof(buf));
07746 if (res < 0) {
07747 if (errno != ELAST) {
07748 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07749 callerid_free(cs);
07750 ast_hangup(chan);
07751 goto quit;
07752 }
07753 break;
07754 }
07755 if (p->ringt)
07756 p->ringt--;
07757 if (p->ringt == 1) {
07758 res = -1;
07759 break;
07760 }
07761 samples += res;
07762 res = callerid_feed(cs, buf, res, AST_LAW(p));
07763 if (res < 0) {
07764 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07765 break;
07766 } else if (res)
07767 break;
07768 else if (samples > (8000 * 10))
07769 break;
07770 }
07771 }
07772 if (res == 1) {
07773 callerid_get(cs, &name, &number, &flags);
07774 if (option_debug)
07775 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07776 }
07777 if (distinctiveringaftercid == 1) {
07778
07779 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07780 curRingData[receivedRingT] = 0;
07781 }
07782 receivedRingT = 0;
07783 if (option_verbose > 2)
07784 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
07785 for (;;) {
07786 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07787 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07788 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07789 callerid_free(cs);
07790 ast_hangup(chan);
07791 goto quit;
07792 }
07793 if (i & DAHDI_IOMUX_SIGEVENT) {
07794 res = dahdi_get_event(p->subs[index].dfd);
07795 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07796 res = 0;
07797
07798
07799 curRingData[receivedRingT] = p->ringt;
07800
07801 if (p->ringt < p->ringt_base/2)
07802 break;
07803
07804
07805 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07806 break;
07807 } else if (i & DAHDI_IOMUX_READ) {
07808 res = read(p->subs[index].dfd, buf, sizeof(buf));
07809 if (res < 0) {
07810 if (errno != ELAST) {
07811 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07812 callerid_free(cs);
07813 ast_hangup(chan);
07814 goto quit;
07815 }
07816 break;
07817 }
07818 if (p->ringt)
07819 p->ringt--;
07820 if (p->ringt == 1) {
07821 res = -1;
07822 break;
07823 }
07824 }
07825 }
07826 }
07827 if (p->usedistinctiveringdetection) {
07828 if (option_verbose > 2)
07829
07830 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07831
07832 for (counter = 0; counter < 3; counter++) {
07833
07834
07835 if (option_verbose > 2)
07836
07837 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
07838 p->drings.ringnum[counter].ring[0],
07839 p->drings.ringnum[counter].ring[1],
07840 p->drings.ringnum[counter].ring[2]);
07841 distMatches = 0;
07842 for (counter1 = 0; counter1 < 3; counter1++) {
07843 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07844 (p->drings.ringnum[counter].ring[counter1]-10)) {
07845 distMatches++;
07846 }
07847 }
07848 if (distMatches == 3) {
07849
07850 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07851 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07852 if (option_verbose > 2)
07853 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07854 break;
07855 }
07856 }
07857 }
07858
07859 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07860 #if 1
07861 restore_gains(p);
07862 #endif
07863 if (res < 0) {
07864 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07865 }
07866 } else
07867 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07868 }
07869 else
07870 cs = NULL;
07871
07872 if (number)
07873 ast_shrink_phone_number(number);
07874 ast_set_callerid(chan, number, name, number);
07875
07876 if (smdi_msg)
07877 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07878
07879 if (cs)
07880 callerid_free(cs);
07881
07882 ast_setstate(chan, AST_STATE_RING);
07883 chan->rings = 1;
07884 p->ringt = p->ringt_base;
07885 res = ast_pbx_run(chan);
07886 if (res) {
07887 ast_hangup(chan);
07888 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07889 }
07890 goto quit;
07891 default:
07892 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07893 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07894 if (res < 0)
07895 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07896 }
07897 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07898 if (res < 0)
07899 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07900 ast_hangup(chan);
07901 quit:
07902 ast_mutex_lock(&ss_thread_lock);
07903 ss_thread_count--;
07904 ast_cond_signal(&ss_thread_complete);
07905 ast_mutex_unlock(&ss_thread_lock);
07906 return NULL;
07907 }
07908
07909
07910 static int dahdi_destroy_channel_bynum(int channel)
07911 {
07912 struct dahdi_pvt *tmp = NULL;
07913 struct dahdi_pvt *prev = NULL;
07914
07915 ast_mutex_lock(&iflock);
07916 tmp = iflist;
07917 while (tmp) {
07918 if (tmp->channel == channel) {
07919 int x = DAHDI_FLASH;
07920 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07921 destroy_channel(prev, tmp, 1);
07922 ast_mutex_unlock(&iflock);
07923 ast_module_unref(ast_module_info->self);
07924 return RESULT_SUCCESS;
07925 }
07926 prev = tmp;
07927 tmp = tmp->next;
07928 }
07929 ast_mutex_unlock(&iflock);
07930 return RESULT_FAILURE;
07931 }
07932
07933 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
07934 {
07935 int res;
07936 pthread_t threadid;
07937 pthread_attr_t attr;
07938 struct ast_channel *chan;
07939 pthread_attr_init(&attr);
07940 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07941
07942 switch (event) {
07943 case DAHDI_EVENT_NONE:
07944 case DAHDI_EVENT_BITSCHANGED:
07945 break;
07946 case DAHDI_EVENT_WINKFLASH:
07947 case DAHDI_EVENT_RINGOFFHOOK:
07948 if (i->inalarm) break;
07949 if (i->radio) break;
07950
07951 switch (i->sig) {
07952 case SIG_FXOLS:
07953 case SIG_FXOGS:
07954 case SIG_FXOKS:
07955 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07956 if (res && (errno == EBUSY))
07957 break;
07958 if (i->cidspill) {
07959
07960 free(i->cidspill);
07961 i->cidspill = NULL;
07962 }
07963 if (i->immediate) {
07964 dahdi_enable_ec(i);
07965
07966 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07967 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07968 if (!chan) {
07969 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07970 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07971 if (res < 0)
07972 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07973 }
07974 } else {
07975
07976 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07977 if (chan) {
07978 if (has_voicemail(i))
07979 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07980 else
07981 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07982 if (res < 0)
07983 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
07984 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07985 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07986 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07987 if (res < 0)
07988 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07989 ast_hangup(chan);
07990 }
07991 } else
07992 ast_log(LOG_WARNING, "Unable to create channel\n");
07993 }
07994 break;
07995 case SIG_FXSLS:
07996 case SIG_FXSGS:
07997 case SIG_FXSKS:
07998 i->ringt = i->ringt_base;
07999
08000 case SIG_EMWINK:
08001 case SIG_FEATD:
08002 case SIG_FEATDMF:
08003 case SIG_FEATDMF_TA:
08004 case SIG_E911:
08005 case SIG_FGC_CAMA:
08006 case SIG_FGC_CAMAMF:
08007 case SIG_FEATB:
08008 case SIG_EM:
08009 case SIG_EM_E1:
08010 case SIG_SFWINK:
08011 case SIG_SF_FEATD:
08012 case SIG_SF_FEATDMF:
08013 case SIG_SF_FEATB:
08014 case SIG_SF:
08015
08016 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08017 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08018 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08019 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08020 if (res < 0)
08021 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08022 ast_hangup(chan);
08023 } else if (!chan) {
08024 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08025 }
08026 break;
08027 default:
08028 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08029 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08030 if (res < 0)
08031 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08032 pthread_attr_destroy(&attr);
08033 return NULL;
08034 }
08035 break;
08036 case DAHDI_EVENT_NOALARM:
08037 i->inalarm = 0;
08038 if (!i->unknown_alarm) {
08039 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08040 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08041 "Channel: %d\r\n", i->channel);
08042 } else {
08043 i->unknown_alarm = 0;
08044 }
08045 break;
08046 case DAHDI_EVENT_ALARM:
08047 i->inalarm = 1;
08048 res = get_alarms(i);
08049 handle_alarms(i, res);
08050
08051 case DAHDI_EVENT_ONHOOK:
08052 if (i->radio)
08053 break;
08054
08055 switch (i->sig) {
08056 case SIG_FXOLS:
08057 case SIG_FXOGS:
08058 case SIG_FEATD:
08059 case SIG_FEATDMF:
08060 case SIG_FEATDMF_TA:
08061 case SIG_E911:
08062 case SIG_FGC_CAMA:
08063 case SIG_FGC_CAMAMF:
08064 case SIG_FEATB:
08065 case SIG_EM:
08066 case SIG_EM_E1:
08067 case SIG_EMWINK:
08068 case SIG_SF_FEATD:
08069 case SIG_SF_FEATDMF:
08070 case SIG_SF_FEATB:
08071 case SIG_SF:
08072 case SIG_SFWINK:
08073 case SIG_FXSLS:
08074 case SIG_FXSGS:
08075 case SIG_FXSKS:
08076 case SIG_GR303FXSKS:
08077 dahdi_disable_ec(i);
08078 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08079 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08080 break;
08081 case SIG_GR303FXOKS:
08082 case SIG_FXOKS:
08083 dahdi_disable_ec(i);
08084
08085 #ifdef ZHONE_HACK
08086 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08087 usleep(1);
08088 #endif
08089 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08090 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08091 break;
08092 case SIG_PRI:
08093 dahdi_disable_ec(i);
08094 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08095 break;
08096 default:
08097 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08098 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08099 pthread_attr_destroy(&attr);
08100 return NULL;
08101 }
08102 break;
08103 case DAHDI_EVENT_POLARITY:
08104 switch (i->sig) {
08105 case SIG_FXSLS:
08106 case SIG_FXSKS:
08107 case SIG_FXSGS:
08108
08109
08110
08111
08112 if (i->hanguponpolarityswitch)
08113 i->polarity = POLARITY_REV;
08114
08115 if (i->cid_start == CID_START_POLARITY) {
08116 i->polarity = POLARITY_REV;
08117 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08118 "CID detection on channel %d\n",
08119 i->channel);
08120 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08121 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08122 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08123 }
08124 }
08125 break;
08126 default:
08127 ast_log(LOG_WARNING, "handle_init_event detected "
08128 "polarity reversal on non-FXO (SIG_FXS) "
08129 "interface %d\n", i->channel);
08130 }
08131 break;
08132 case DAHDI_EVENT_REMOVED:
08133 ast_log(LOG_NOTICE,
08134 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08135 i->channel);
08136 pthread_attr_destroy(&attr);
08137 return i;
08138 }
08139 pthread_attr_destroy(&attr);
08140 return NULL;
08141 }
08142
08143 static void *do_monitor(void *data)
08144 {
08145 int count, res, res2, spoint, pollres=0;
08146 struct dahdi_pvt *i;
08147 struct dahdi_pvt *last = NULL;
08148 struct dahdi_pvt *doomed;
08149 time_t thispass = 0, lastpass = 0;
08150 int found;
08151 char buf[1024];
08152 struct pollfd *pfds=NULL;
08153 int lastalloc = -1;
08154
08155
08156
08157 #if 0
08158 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08159 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08160 return NULL;
08161 }
08162 ast_log(LOG_DEBUG, "Monitor starting...\n");
08163 #endif
08164 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08165
08166 for (;;) {
08167
08168 ast_mutex_lock(&iflock);
08169 if (!pfds || (lastalloc != ifcount)) {
08170 if (pfds) {
08171 free(pfds);
08172 pfds = NULL;
08173 }
08174 if (ifcount) {
08175 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08176 ast_mutex_unlock(&iflock);
08177 return NULL;
08178 }
08179 }
08180 lastalloc = ifcount;
08181 }
08182
08183
08184 count = 0;
08185 i = iflist;
08186 while (i) {
08187 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08188 if (!i->owner && !i->subs[SUB_REAL].owner) {
08189
08190 pfds[count].fd = i->subs[SUB_REAL].dfd;
08191 pfds[count].events = POLLPRI;
08192 pfds[count].revents = 0;
08193
08194 if (i->cidspill)
08195 pfds[count].events |= POLLIN;
08196 count++;
08197 }
08198 }
08199 i = i->next;
08200 }
08201
08202 ast_mutex_unlock(&iflock);
08203
08204 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08205 pthread_testcancel();
08206
08207 res = poll(pfds, count, 1000);
08208 pthread_testcancel();
08209 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08210
08211
08212 if (res < 0) {
08213 if ((errno != EAGAIN) && (errno != EINTR))
08214 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08215 continue;
08216 }
08217
08218
08219 ast_mutex_lock(&iflock);
08220 found = 0;
08221 spoint = 0;
08222 lastpass = thispass;
08223 thispass = time(NULL);
08224 doomed = NULL;
08225 for (i = iflist;; i = i->next) {
08226 if (doomed) {
08227 int res;
08228 res = dahdi_destroy_channel_bynum(doomed->channel);
08229 if (!res) {
08230 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08231 }
08232 doomed = NULL;
08233 }
08234 if (!i) {
08235 break;
08236 }
08237 if (thispass != lastpass) {
08238 if (!found && ((i == last) || ((i == iflist) && !last))) {
08239 last = i;
08240 if (last) {
08241 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08242 (last->sig & __DAHDI_SIG_FXO)) {
08243 res = ast_app_has_voicemail(last->mailbox, NULL);
08244 if (last->msgstate != res) {
08245 int x;
08246 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08247 x = DAHDI_FLUSH_BOTH;
08248 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08249 if (res2)
08250 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08251 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08252
08253 x = 4000;
08254 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08255 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08256 last->cidpos = 0;
08257 last->msgstate = res;
08258 last->onhooktime = thispass;
08259 }
08260 found ++;
08261 }
08262 }
08263 last = last->next;
08264 }
08265 }
08266 }
08267 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08268 if (i->radio && !i->owner)
08269 {
08270 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08271 if (res)
08272 {
08273 if (option_debug)
08274 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08275
08276 ast_mutex_unlock(&iflock);
08277 doomed = handle_init_event(i, res);
08278 ast_mutex_lock(&iflock);
08279 }
08280 continue;
08281 }
08282 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08283 if (pollres & POLLIN) {
08284 if (i->owner || i->subs[SUB_REAL].owner) {
08285 #ifdef HAVE_PRI
08286 if (!i->pri)
08287 #endif
08288 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08289 continue;
08290 }
08291 if (!i->cidspill) {
08292 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08293 continue;
08294 }
08295 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08296 if (res > 0) {
08297
08298 if (res > i->cidlen - i->cidpos)
08299 res = i->cidlen - i->cidpos;
08300 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
08301 if (res2 > 0) {
08302 i->cidpos += res2;
08303 if (i->cidpos >= i->cidlen) {
08304 free(i->cidspill);
08305 i->cidspill = 0;
08306 i->cidpos = 0;
08307 i->cidlen = 0;
08308 }
08309 } else {
08310 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
08311 i->msgstate = -1;
08312 }
08313 } else {
08314 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08315 }
08316 }
08317 if (pollres & POLLPRI) {
08318 if (i->owner || i->subs[SUB_REAL].owner) {
08319 #ifdef HAVE_PRI
08320 if (!i->pri)
08321 #endif
08322 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08323 continue;
08324 }
08325 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08326 if (option_debug)
08327 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08328
08329 ast_mutex_unlock(&iflock);
08330 doomed = handle_init_event(i, res);
08331 ast_mutex_lock(&iflock);
08332 }
08333 }
08334 }
08335 ast_mutex_unlock(&iflock);
08336 }
08337
08338 return NULL;
08339
08340 }
08341
08342 static int restart_monitor(void)
08343 {
08344 pthread_attr_t attr;
08345 pthread_attr_init(&attr);
08346 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08347
08348 if (monitor_thread == AST_PTHREADT_STOP)
08349 return 0;
08350 ast_mutex_lock(&monlock);
08351 if (monitor_thread == pthread_self()) {
08352 ast_mutex_unlock(&monlock);
08353 ast_log(LOG_WARNING, "Cannot kill myself\n");
08354 return -1;
08355 }
08356 if (monitor_thread != AST_PTHREADT_NULL) {
08357
08358 pthread_kill(monitor_thread, SIGURG);
08359 } else {
08360
08361 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08362 ast_mutex_unlock(&monlock);
08363 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08364 pthread_attr_destroy(&attr);
08365 return -1;
08366 }
08367 }
08368 ast_mutex_unlock(&monlock);
08369 pthread_attr_destroy(&attr);
08370 return 0;
08371 }
08372
08373 #ifdef HAVE_OPENR2
08374 static struct dahdi_mfcr2 *mfcr2_get_context(int id)
08375 {
08376 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08377 ast_log(LOG_ERROR, "No more R2 links available!.\n");
08378 return NULL;
08379 }
08380 return &r2links[id];
08381 }
08382 #endif
08383
08384 #ifdef HAVE_PRI
08385 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08386 {
08387 int x;
08388 int trunkgroup;
08389
08390 trunkgroup = pris[*span].mastertrunkgroup;
08391 if (trunkgroup) {
08392
08393 for (x = 0; x < NUM_SPANS; x++) {
08394 if (pris[x].trunkgroup == trunkgroup) {
08395 *span = x;
08396 return 0;
08397 }
08398 }
08399 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08400 *span = -1;
08401 } else {
08402 if (pris[*span].trunkgroup) {
08403 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08404 *span = -1;
08405 } else if (pris[*span].mastertrunkgroup) {
08406 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08407 *span = -1;
08408 } else {
08409 if (si->totalchans == 31) {
08410
08411 pris[*span].dchannels[0] = 16 + offset;
08412 } else if (si->totalchans == 24) {
08413
08414 pris[*span].dchannels[0] = 24 + offset;
08415 } else if (si->totalchans == 3) {
08416
08417 pris[*span].dchannels[0] = 3 + offset;
08418 } else {
08419 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);
08420 *span = -1;
08421 return 0;
08422 }
08423 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08424 pris[*span].offset = offset;
08425 pris[*span].span = *span + 1;
08426 }
08427 }
08428 return 0;
08429 }
08430
08431 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08432 {
08433 struct dahdi_spaninfo si;
08434 struct dahdi_params p;
08435 int fd;
08436 int span;
08437 int ospan=0;
08438 int x,y;
08439 for (x = 0; x < NUM_SPANS; x++) {
08440 if (pris[x].trunkgroup == trunkgroup) {
08441 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08442 return -1;
08443 }
08444 }
08445 for (y = 0; y < NUM_DCHANS; y++) {
08446 if (!channels[y])
08447 break;
08448 memset(&si, 0, sizeof(si));
08449 memset(&p, 0, sizeof(p));
08450 fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
08451 if (fd < 0) {
08452 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08453 return -1;
08454 }
08455 x = channels[y];
08456 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08457 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08458 close(fd);
08459 return -1;
08460 }
08461 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08462 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08463 return -1;
08464 }
08465 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08466 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08467 close(fd);
08468 return -1;
08469 }
08470 span = p.spanno - 1;
08471 if (pris[span].trunkgroup) {
08472 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08473 close(fd);
08474 return -1;
08475 }
08476 if (pris[span].pvts[0]) {
08477 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08478 close(fd);
08479 return -1;
08480 }
08481 if (!y) {
08482 pris[span].trunkgroup = trunkgroup;
08483 pris[span].offset = channels[y] - p.chanpos;
08484 ospan = span;
08485 }
08486 pris[ospan].dchannels[y] = channels[y];
08487 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08488 pris[span].span = span + 1;
08489 close(fd);
08490 }
08491 return 0;
08492 }
08493
08494 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08495 {
08496 if (pris[span].mastertrunkgroup) {
08497 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);
08498 return -1;
08499 }
08500 pris[span].mastertrunkgroup = trunkgroup;
08501 pris[span].prilogicalspan = logicalspan;
08502 return 0;
08503 }
08504
08505 #endif
08506
08507 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08508 {
08509
08510 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08511 char fn[80];
08512 #if 1
08513 struct dahdi_bufferinfo bi;
08514 #endif
08515 int res;
08516 int span=0;
08517 int here = 0;
08518 int x;
08519 struct dahdi_pvt **wlist;
08520 struct dahdi_pvt **wend;
08521 struct dahdi_params p;
08522
08523 wlist = &iflist;
08524 wend = &ifend;
08525
08526 #ifdef HAVE_PRI
08527 if (pri) {
08528 wlist = &pri->crvs;
08529 wend = &pri->crvend;
08530 }
08531 #endif
08532
08533 tmp2 = *wlist;
08534 prev = NULL;
08535
08536 while (tmp2) {
08537 if (!tmp2->destroy) {
08538 if (tmp2->channel == channel) {
08539 tmp = tmp2;
08540 here = 1;
08541 break;
08542 }
08543 if (tmp2->channel > channel) {
08544 break;
08545 }
08546 }
08547 prev = tmp2;
08548 tmp2 = tmp2->next;
08549 }
08550
08551 if (!here && reloading != 1) {
08552 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08553 if (tmp)
08554 free(tmp);
08555 return NULL;
08556 }
08557 ast_mutex_init(&tmp->lock);
08558 ifcount++;
08559 for (x = 0; x < 3; x++)
08560 tmp->subs[x].dfd = -1;
08561 tmp->channel = channel;
08562 tmp->priindication_oob = conf->chan.priindication_oob;
08563 }
08564
08565 if (tmp) {
08566 int chan_sig = conf->chan.sig;
08567 if (!here) {
08568 if ((channel != CHAN_PSEUDO) && !pri) {
08569 int count = 0;
08570 snprintf(fn, sizeof(fn), "%d", channel);
08571
08572 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08573 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08574 usleep(1);
08575 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08576 count++;
08577 }
08578
08579 if (tmp->subs[SUB_REAL].dfd < 0) {
08580 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);
08581 destroy_dahdi_pvt(&tmp);
08582 return NULL;
08583 }
08584 memset(&p, 0, sizeof(p));
08585 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08586 if (res < 0) {
08587 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08588 destroy_dahdi_pvt(&tmp);
08589 return NULL;
08590 }
08591 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
08592 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));
08593 destroy_dahdi_pvt(&tmp);
08594 return NULL;
08595 }
08596 tmp->law = p.curlaw;
08597 tmp->span = p.spanno;
08598 span = p.spanno - 1;
08599 } else {
08600 if (channel == CHAN_PSEUDO)
08601 chan_sig = 0;
08602 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08603 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08604 return NULL;
08605 }
08606 }
08607 #ifdef HAVE_PRI
08608 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08609 int offset;
08610 int myswitchtype;
08611 int matchesdchan;
08612 int x,y;
08613 offset = 0;
08614 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08615 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08616 destroy_dahdi_pvt(&tmp);
08617 return NULL;
08618 }
08619 if (span >= NUM_SPANS) {
08620 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08621 destroy_dahdi_pvt(&tmp);
08622 return NULL;
08623 } else {
08624 struct dahdi_spaninfo si;
08625 si.spanno = 0;
08626 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08627 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08628 destroy_dahdi_pvt(&tmp);
08629 return NULL;
08630 }
08631
08632 tmp->logicalspan = pris[span].prilogicalspan;
08633 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08634 if (span < 0) {
08635 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08636 destroy_dahdi_pvt(&tmp);
08637 return NULL;
08638 }
08639 if (chan_sig == SIG_PRI)
08640 myswitchtype = conf->pri.switchtype;
08641 else
08642 myswitchtype = PRI_SWITCH_GR303_TMC;
08643
08644 matchesdchan=0;
08645 for (x = 0; x < NUM_SPANS; x++) {
08646 for (y = 0; y < NUM_DCHANS; y++) {
08647 if (pris[x].dchannels[y] == tmp->channel) {
08648 matchesdchan = 1;
08649 break;
08650 }
08651 }
08652 }
08653 offset = p.chanpos;
08654 if (!matchesdchan) {
08655 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08656 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08657 destroy_dahdi_pvt(&tmp);
08658 return NULL;
08659 }
08660 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08661 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08662 destroy_dahdi_pvt(&tmp);
08663 return NULL;
08664 }
08665 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08666 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08667 destroy_dahdi_pvt(&tmp);
08668 return NULL;
08669 }
08670 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08671 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08672 destroy_dahdi_pvt(&tmp);
08673 return NULL;
08674 }
08675 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08676 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08677 destroy_dahdi_pvt(&tmp);
08678 return NULL;
08679 }
08680 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08681 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08682 destroy_dahdi_pvt(&tmp);
08683 return NULL;
08684 }
08685 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08686 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08687 destroy_dahdi_pvt(&tmp);
08688 return NULL;
08689 }
08690 if (pris[span].numchans >= MAX_CHANNELS) {
08691 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08692 pris[span].trunkgroup);
08693 destroy_dahdi_pvt(&tmp);
08694 return NULL;
08695 }
08696 pris[span].nodetype = conf->pri.nodetype;
08697 pris[span].switchtype = myswitchtype;
08698 pris[span].nsf = conf->pri.nsf;
08699 pris[span].dialplan = conf->pri.dialplan;
08700 pris[span].localdialplan = conf->pri.localdialplan;
08701 pris[span].pvts[pris[span].numchans++] = tmp;
08702 pris[span].minunused = conf->pri.minunused;
08703 pris[span].minidle = conf->pri.minidle;
08704 pris[span].overlapdial = conf->pri.overlapdial;
08705 #ifdef HAVE_PRI_INBANDDISCONNECT
08706 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08707 #endif
08708 pris[span].facilityenable = conf->pri.facilityenable;
08709 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08710 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08711 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08712 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08713 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08714 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08715 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08716 pris[span].resetinterval = conf->pri.resetinterval;
08717
08718 tmp->pri = &pris[span];
08719 tmp->prioffset = offset;
08720 tmp->call = NULL;
08721 } else {
08722 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08723 destroy_dahdi_pvt(&tmp);
08724 return NULL;
08725 }
08726 }
08727 } else {
08728 tmp->prioffset = 0;
08729 }
08730 #endif
08731 #ifdef HAVE_OPENR2
08732 if (chan_sig == SIG_MFCR2 && reloading != 1) {
08733 char logdir[OR2_MAX_PATH];
08734 struct dahdi_mfcr2 *dahdi_r2;
08735 int threshold = 0;
08736 int snres = 0;
08737 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
08738 if (!dahdi_r2) {
08739 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
08740 } else if (!dahdi_r2->protocol_context){
08741 char tmplogdir[] = "/tmp";
08742 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
08743 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
08744 if (!dahdi_r2->protocol_context) {
08745 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
08746 destroy_dahdi_pvt(&tmp);
08747 return NULL;
08748 }
08749 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
08750 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
08751 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
08752 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
08753 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
08754 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
08755 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
08756 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
08757 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
08758 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
08759 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
08760 #endif
08761 if (ast_strlen_zero(mfcr2_cur_logdir)) {
08762 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
08763 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08764 }
08765 } else {
08766 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
08767 if (snres >= sizeof(logdir)) {
08768 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
08769 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08770 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08771 }
08772 } else {
08773 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08774 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
08775 }
08776 }
08777 }
08778 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
08779 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
08780 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
08781 }
08782 }
08783 }
08784 if (dahdi_r2) {
08785
08786 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
08787 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
08788 tmp->subs[SUB_REAL].dfd, NULL, NULL);
08789 if (!tmp->r2chan) {
08790 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
08791 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
08792 destroy_dahdi_pvt(&tmp);
08793 return NULL;
08794 }
08795 openr2_chan_set_client_data(tmp->r2chan, tmp);
08796
08797 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
08798 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
08799 if (mfcr2_cur_call_files) {
08800 openr2_chan_enable_call_files(tmp->r2chan);
08801 }
08802 tmp->mfcr2_category = mfcr2_cur_category;
08803 tmp->mfcr2 = dahdi_r2;
08804 tmp->mfcr2call = 0;
08805 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
08806 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
08807 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
08808 tmp->mfcr2_ani_index = 0;
08809 tmp->mfcr2_dnis_index = 0;
08810 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
08811 tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
08812 }
08813 }
08814 #endif
08815 } else {
08816 chan_sig = tmp->sig;
08817 if (tmp->subs[SUB_REAL].dfd > -1) {
08818 memset(&p, 0, sizeof(p));
08819 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08820 }
08821 }
08822
08823 switch (chan_sig) {
08824 case SIG_FXSKS:
08825 case SIG_FXSLS:
08826 case SIG_EM:
08827 case SIG_EM_E1:
08828 case SIG_EMWINK:
08829 case SIG_FEATD:
08830 case SIG_FEATDMF:
08831 case SIG_FEATDMF_TA:
08832 case SIG_FEATB:
08833 case SIG_E911:
08834 case SIG_SF:
08835 case SIG_SFWINK:
08836 case SIG_FGC_CAMA:
08837 case SIG_FGC_CAMAMF:
08838 case SIG_SF_FEATD:
08839 case SIG_SF_FEATDMF:
08840 case SIG_SF_FEATB:
08841 p.starttime = 250;
08842 break;
08843 }
08844
08845 if (tmp->radio) {
08846
08847 p.channo = channel;
08848 p.rxwinktime = 1;
08849 p.rxflashtime = 1;
08850 p.starttime = 1;
08851 p.debouncetime = 5;
08852 }
08853 if (!tmp->radio) {
08854 p.channo = channel;
08855
08856 if (conf->timing.prewinktime >= 0)
08857 p.prewinktime = conf->timing.prewinktime;
08858 if (conf->timing.preflashtime >= 0)
08859 p.preflashtime = conf->timing.preflashtime;
08860 if (conf->timing.winktime >= 0)
08861 p.winktime = conf->timing.winktime;
08862 if (conf->timing.flashtime >= 0)
08863 p.flashtime = conf->timing.flashtime;
08864 if (conf->timing.starttime >= 0)
08865 p.starttime = conf->timing.starttime;
08866 if (conf->timing.rxwinktime >= 0)
08867 p.rxwinktime = conf->timing.rxwinktime;
08868 if (conf->timing.rxflashtime >= 0)
08869 p.rxflashtime = conf->timing.rxflashtime;
08870 if (conf->timing.debouncetime >= 0)
08871 p.debouncetime = conf->timing.debouncetime;
08872 }
08873
08874
08875 if (tmp->subs[SUB_REAL].dfd >= 0)
08876 {
08877 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
08878 if (res < 0) {
08879 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
08880 destroy_dahdi_pvt(&tmp);
08881 return NULL;
08882 }
08883 }
08884 #if 1
08885 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
08886 memset(&bi, 0, sizeof(bi));
08887 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08888 if (!res) {
08889 bi.txbufpolicy = conf->chan.buf_policy;
08890 bi.rxbufpolicy = conf->chan.buf_policy;
08891 bi.numbufs = conf->chan.buf_no;
08892 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08893 if (res < 0) {
08894 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
08895 }
08896 } else
08897 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
08898 }
08899 #endif
08900 tmp->immediate = conf->chan.immediate;
08901 tmp->transfertobusy = conf->chan.transfertobusy;
08902 tmp->sig = chan_sig;
08903 tmp->outsigmod = conf->chan.outsigmod;
08904 tmp->ringt_base = ringt_base;
08905 tmp->firstradio = 0;
08906 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
08907 tmp->permcallwaiting = conf->chan.callwaiting;
08908 else
08909 tmp->permcallwaiting = 0;
08910
08911 tmp->destroy = 0;
08912 tmp->drings = drings;
08913 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
08914 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
08915 tmp->threewaycalling = conf->chan.threewaycalling;
08916 tmp->adsi = conf->chan.adsi;
08917 tmp->use_smdi = conf->chan.use_smdi;
08918 tmp->permhidecallerid = conf->chan.hidecallerid;
08919 tmp->callreturn = conf->chan.callreturn;
08920 tmp->echocancel = conf->chan.echocancel;
08921 tmp->echotraining = conf->chan.echotraining;
08922 tmp->pulse = conf->chan.pulse;
08923 if (tmp->echocancel)
08924 tmp->echocanbridged = conf->chan.echocanbridged;
08925 else {
08926 if (conf->chan.echocanbridged)
08927 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
08928 tmp->echocanbridged = 0;
08929 }
08930 tmp->busydetect = conf->chan.busydetect;
08931 tmp->busycount = conf->chan.busycount;
08932 tmp->busycompare = conf->chan.busycompare;
08933 tmp->busytonelength = conf->chan.busytonelength;
08934 tmp->busyquietlength = conf->chan.busyquietlength;
08935 tmp->busyfuzziness = conf->chan.busyfuzziness;
08936 tmp->silencethreshold = conf->chan.silencethreshold;
08937 tmp->callprogress = conf->chan.callprogress;
08938 tmp->cancallforward = conf->chan.cancallforward;
08939 tmp->dtmfrelax = conf->chan.dtmfrelax;
08940 tmp->callwaiting = tmp->permcallwaiting;
08941 tmp->hidecallerid = tmp->permhidecallerid;
08942 tmp->channel = channel;
08943 tmp->stripmsd = conf->chan.stripmsd;
08944 tmp->use_callerid = conf->chan.use_callerid;
08945 tmp->cid_signalling = conf->chan.cid_signalling;
08946 tmp->cid_start = conf->chan.cid_start;
08947 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
08948 tmp->restrictcid = conf->chan.restrictcid;
08949 tmp->use_callingpres = conf->chan.use_callingpres;
08950 tmp->priexclusive = conf->chan.priexclusive;
08951 if (tmp->usedistinctiveringdetection) {
08952 if (!tmp->use_callerid) {
08953 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
08954 tmp->use_callerid = 1;
08955 }
08956 }
08957
08958 if (tmp->cid_signalling == CID_SIG_SMDI) {
08959 if (!tmp->use_smdi) {
08960 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
08961 tmp->use_smdi = 1;
08962 }
08963 }
08964 if (tmp->use_smdi) {
08965 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
08966 if (!(tmp->smdi_iface)) {
08967 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
08968 tmp->use_smdi = 0;
08969 }
08970 }
08971
08972 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
08973 tmp->amaflags = conf->chan.amaflags;
08974 if (!here) {
08975 tmp->confno = -1;
08976 tmp->propconfno = -1;
08977 }
08978 tmp->canpark = conf->chan.canpark;
08979 tmp->transfer = conf->chan.transfer;
08980 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
08981 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
08982 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
08983 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
08984 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
08985 tmp->cid_ton = 0;
08986 if (chan_sig != SIG_PRI) {
08987 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
08988 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
08989 } else {
08990 tmp->cid_num[0] = '\0';
08991 tmp->cid_name[0] = '\0';
08992 }
08993 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
08994 tmp->msgstate = -1;
08995 tmp->group = conf->chan.group;
08996 tmp->callgroup = conf->chan.callgroup;
08997 tmp->pickupgroup= conf->chan.pickupgroup;
08998 tmp->rxgain = conf->chan.rxgain;
08999 tmp->txgain = conf->chan.txgain;
09000 tmp->tonezone = conf->chan.tonezone;
09001 tmp->onhooktime = time(NULL);
09002 if (tmp->subs[SUB_REAL].dfd > -1) {
09003 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09004 if (tmp->dsp)
09005 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09006 update_conf(tmp);
09007 if (!here) {
09008 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09009
09010 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09011 }
09012 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09013 #ifdef HAVE_PRI
09014
09015 if (tmp->pri && !pri_is_up(tmp->pri)) {
09016 tmp->inalarm = 1;
09017 }
09018 #endif
09019 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09020 tmp->inalarm = 1;
09021 handle_alarms(tmp, res);
09022 } else {
09023
09024
09025
09026
09027
09028
09029
09030
09031
09032
09033 tmp->unknown_alarm = 1;
09034 }
09035 }
09036
09037 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09038 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09039 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09040 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09041
09042 }
09043 if (tmp && !here) {
09044
09045 if (!*wlist) {
09046 *wlist = tmp;
09047 tmp->prev = NULL;
09048 tmp->next = NULL;
09049 *wend = tmp;
09050 } else {
09051
09052 struct dahdi_pvt *working = *wlist;
09053
09054
09055 if (working->channel > tmp->channel) {
09056 tmp->next = *wlist;
09057 tmp->prev = NULL;
09058 (*wlist)->prev = tmp;
09059 *wlist = tmp;
09060 } else {
09061
09062 while (working) {
09063
09064 if (working->next) {
09065 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09066 tmp->next = working->next;
09067 tmp->prev = working;
09068 working->next->prev = tmp;
09069 working->next = tmp;
09070 break;
09071 }
09072 } else {
09073
09074 if (working->channel < tmp->channel) {
09075 working->next = tmp;
09076 tmp->next = NULL;
09077 tmp->prev = working;
09078 *wend = tmp;
09079 break;
09080 }
09081 }
09082 working = working->next;
09083 }
09084 }
09085 }
09086 }
09087 return tmp;
09088 }
09089
09090 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09091 {
09092 int res;
09093 struct dahdi_params par;
09094
09095
09096 if (groupmatch) {
09097 if ((p->group & groupmatch) != groupmatch)
09098 return 0;
09099 *groupmatched = 1;
09100 }
09101
09102 if (channelmatch != -1) {
09103 if (p->channel != channelmatch)
09104 return 0;
09105 *channelmatched = 1;
09106 }
09107
09108 if (busy) {
09109 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09110 *busy = 1;
09111 }
09112
09113 if (p->dnd)
09114 return 0;
09115
09116 if (p->guardtime && (time(NULL) < p->guardtime))
09117 return 0;
09118
09119
09120 if (!p->owner) {
09121 #ifdef HAVE_PRI
09122
09123 if (p->pri) {
09124 if (p->resetting || p->call)
09125 return 0;
09126 else
09127 return 1;
09128 }
09129 #endif
09130 #ifdef HAVE_OPENR2
09131
09132 if (p->mfcr2) {
09133 if (p->mfcr2call || p->mfcr2block)
09134 return 0;
09135 else
09136 return 1;
09137 }
09138 #endif
09139 if (!(p->radio || (p->oprmode < 0)))
09140 {
09141 if (!p->sig || (p->sig == SIG_FXSLS))
09142 return 1;
09143
09144 if (p->subs[SUB_REAL].dfd > -1) {
09145 memset(&par, 0, sizeof(par));
09146 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09147 } else {
09148
09149 res = 0;
09150 par.rxisoffhook = 0;
09151 }
09152 if (res) {
09153 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09154 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09155
09156
09157
09158 if (par.rxbits > -1)
09159 return 1;
09160 if (par.rxisoffhook)
09161 return 1;
09162 else
09163 #ifdef DAHDI_CHECK_HOOKSTATE
09164 return 0;
09165 #else
09166 return 1;
09167 #endif
09168 } else if (par.rxisoffhook) {
09169 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09170
09171 return 0;
09172 }
09173 }
09174 return 1;
09175 }
09176
09177
09178 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09179 return 0;
09180
09181 if (!p->callwaiting) {
09182
09183 return 0;
09184 }
09185
09186 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09187
09188 return 0;
09189 }
09190
09191 if ((p->owner->_state != AST_STATE_UP) &&
09192 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09193
09194 return 0;
09195 }
09196 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09197
09198 return 0;
09199 }
09200
09201 return 1;
09202 }
09203
09204 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09205 {
09206 struct dahdi_pvt *p;
09207 struct dahdi_bufferinfo bi;
09208 int res;
09209
09210 if ((p = ast_malloc(sizeof(*p)))) {
09211 memcpy(p, src, sizeof(struct dahdi_pvt));
09212 ast_mutex_init(&p->lock);
09213 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09214
09215 if (p->subs[SUB_REAL].dfd < 0) {
09216 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09217 destroy_dahdi_pvt(&p);
09218 return NULL;
09219 }
09220 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09221 if (!res) {
09222 bi.txbufpolicy = p->buf_policy;
09223 bi.rxbufpolicy = p->buf_policy;
09224 bi.numbufs = p->buf_no;
09225 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09226 if (res < 0) {
09227 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09228 }
09229 } else
09230 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09231 }
09232 p->destroy = 1;
09233 p->next = iflist;
09234 p->prev = NULL;
09235 iflist = p;
09236 if (iflist->next)
09237 iflist->next->prev = p;
09238 return p;
09239 }
09240
09241
09242 #ifdef HAVE_PRI
09243 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09244 {
09245 int x;
09246 if (backwards)
09247 x = pri->numchans;
09248 else
09249 x = 0;
09250 for (;;) {
09251 if (backwards && (x < 0))
09252 break;
09253 if (!backwards && (x >= pri->numchans))
09254 break;
09255 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09256 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
09257 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09258 return x;
09259 }
09260 if (backwards)
09261 x--;
09262 else
09263 x++;
09264 }
09265 return -1;
09266 }
09267 #endif
09268
09269 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09270 {
09271 ast_group_t groupmatch = 0;
09272 int channelmatch = -1;
09273 int roundrobin = 0;
09274 int callwait = 0;
09275 int busy = 0;
09276 struct dahdi_pvt *p;
09277 struct ast_channel *tmp = NULL;
09278 char *dest=NULL;
09279 int x;
09280 char *s;
09281 char opt=0;
09282 int res=0, y=0;
09283 int backwards = 0;
09284 #ifdef HAVE_PRI
09285 int crv;
09286 int bearer = -1;
09287 int trunkgroup;
09288 struct dahdi_pri *pri=NULL;
09289 #endif
09290 struct dahdi_pvt *exit, *start, *end;
09291 ast_mutex_t *lock;
09292 int channelmatched = 0;
09293 int groupmatched = 0;
09294
09295
09296
09297
09298
09299
09300
09301
09302
09303
09304
09305
09306
09307
09308
09309
09310
09311
09312
09313 lock = &iflock;
09314 start = iflist;
09315 end = ifend;
09316 if (data) {
09317 dest = ast_strdupa((char *)data);
09318 } else {
09319 ast_log(LOG_WARNING, "Channel requested with no data\n");
09320 return NULL;
09321 }
09322 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09323
09324 char *stringp;
09325
09326 stringp = dest + 1;
09327 s = strsep(&stringp, "/");
09328 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09329 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09330 return NULL;
09331 }
09332 groupmatch = ((ast_group_t) 1 << x);
09333 if (toupper(dest[0]) == 'G') {
09334 if (dest[0] == 'G') {
09335 backwards = 1;
09336 p = ifend;
09337 } else
09338 p = iflist;
09339 } else {
09340 if (dest[0] == 'R') {
09341 backwards = 1;
09342 p = round_robin[x]?round_robin[x]->prev:ifend;
09343 if (!p)
09344 p = ifend;
09345 } else {
09346 p = round_robin[x]?round_robin[x]->next:iflist;
09347 if (!p)
09348 p = iflist;
09349 }
09350 roundrobin = 1;
09351 }
09352 } else {
09353 char *stringp;
09354
09355 stringp = dest;
09356 s = strsep(&stringp, "/");
09357 p = iflist;
09358 if (!strcasecmp(s, "pseudo")) {
09359
09360 x = CHAN_PSEUDO;
09361 channelmatch = x;
09362 }
09363 #ifdef HAVE_PRI
09364 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09365 if ((trunkgroup < 1) || (crv < 1)) {
09366 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09367 return NULL;
09368 }
09369 res--;
09370 for (x = 0; x < NUM_SPANS; x++) {
09371 if (pris[x].trunkgroup == trunkgroup) {
09372 pri = pris + x;
09373 lock = &pri->lock;
09374 start = pri->crvs;
09375 end = pri->crvend;
09376 break;
09377 }
09378 }
09379 if (!pri) {
09380 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09381 return NULL;
09382 }
09383 channelmatch = crv;
09384 p = pris[x].crvs;
09385 }
09386 #endif
09387 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09388 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09389 return NULL;
09390 } else {
09391 channelmatch = x;
09392 }
09393 }
09394
09395 ast_mutex_lock(lock);
09396 exit = p;
09397 while (p && !tmp) {
09398 if (roundrobin)
09399 round_robin[x] = p;
09400 #if 0
09401 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09402 #endif
09403
09404 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09405 if (option_debug)
09406 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
09407 if (p->inalarm)
09408 goto next;
09409
09410 callwait = (p->owner != NULL);
09411 #ifdef HAVE_PRI
09412 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09413 if (p->sig != SIG_FXSKS) {
09414
09415
09416 bearer = pri_find_empty_chan(pri, 0);
09417 if (bearer < 0) {
09418 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09419 p = NULL;
09420 break;
09421 }
09422 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09423 } else {
09424 if (alloc_sub(p, 0)) {
09425 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09426 p = NULL;
09427 break;
09428 } else
09429 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
09430 p->pri = pri;
09431 }
09432 }
09433 #endif
09434 #ifdef HAVE_OPENR2
09435 if (p->mfcr2) {
09436 ast_mutex_lock(&p->lock);
09437 if (p->mfcr2call) {
09438 ast_mutex_unlock(&p->lock);
09439 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
09440 goto next;
09441 }
09442 if (p->mfcr2block) {
09443 ast_mutex_unlock(&p->lock);
09444 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
09445 goto next;
09446 }
09447 p->mfcr2call = 1;
09448 ast_mutex_unlock(&p->lock);
09449 }
09450 #endif
09451 if (p->channel == CHAN_PSEUDO) {
09452 p = chandup(p);
09453 if (!p) {
09454 break;
09455 }
09456 }
09457 if (p->owner) {
09458 if (alloc_sub(p, SUB_CALLWAIT)) {
09459 p = NULL;
09460 break;
09461 }
09462 }
09463 p->outgoing = 1;
09464 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09465 if (!tmp) {
09466 p->outgoing = 0;
09467 }
09468 #ifdef HAVE_PRI
09469 if (p->bearer) {
09470
09471 p->bearer->owner = tmp;
09472 }
09473 #endif
09474
09475 if (res > 1) {
09476 if (opt == 'c') {
09477
09478 p->confirmanswer = 1;
09479 } else if (opt == 'r') {
09480
09481 if (res < 3)
09482 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09483 else
09484 p->distinctivering = y;
09485 } else if (opt == 'd') {
09486
09487 p->digital = 1;
09488 if (tmp)
09489 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09490 } else {
09491 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09492 }
09493 }
09494
09495 if (tmp && callwait)
09496 tmp->cdrflags |= AST_CDR_CALLWAIT;
09497 break;
09498 }
09499 next:
09500 if (backwards) {
09501 p = p->prev;
09502 if (!p)
09503 p = end;
09504 } else {
09505 p = p->next;
09506 if (!p)
09507 p = start;
09508 }
09509
09510 if (p == exit)
09511 break;
09512 }
09513 ast_mutex_unlock(lock);
09514 restart_monitor();
09515 if (callwait)
09516 *cause = AST_CAUSE_BUSY;
09517 else if (!tmp) {
09518 if (channelmatched) {
09519 if (busy)
09520 *cause = AST_CAUSE_BUSY;
09521 } else if (groupmatched) {
09522 *cause = AST_CAUSE_CONGESTION;
09523 }
09524 }
09525
09526 return tmp;
09527 }
09528
09529 #ifdef HAVE_OPENR2
09530 static void *mfcr2_monitor(void *data)
09531 {
09532 struct dahdi_pvt *p;
09533 struct dahdi_mfcr2 *mfcr2 = data;
09534
09535
09536
09537
09538
09539 struct pollfd pollers[sizeof(mfcr2->pvts)];
09540 int maxsleep = 20;
09541 int res = 0;
09542 int i = 0;
09543 int pollsize = 0;
09544 int oldstate = 0;
09545 int was_idle = 0;
09546 int quit_loop = 0;
09547
09548
09549 for (i = 0; i < mfcr2->numchans; i++) {
09550 p = mfcr2->pvts[i];
09551 if (openr2_chan_set_idle(p->r2chan)) {
09552 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
09553 } else {
09554 ast_mutex_lock(&p->lock);
09555 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
09556 mfcr2->pvts[i]->mfcr2call = 0;
09557 ast_mutex_unlock(&p->lock);
09558 }
09559 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
09560 }
09561 while(1) {
09562
09563
09564 pollsize = 0;
09565 for (i = 0; i < mfcr2->numchans; i++) {
09566 pollers[i].revents = 0;
09567 pollers[i].events = 0;
09568 if (mfcr2->pvts[i]->owner) {
09569 continue;
09570 }
09571 if (!mfcr2->pvts[i]->r2chan) {
09572 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
09573 quit_loop = 1;
09574 break;
09575 }
09576 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
09577 pollers[i].events = POLLIN | POLLPRI;
09578 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
09579 pollsize++;
09580 }
09581 if (quit_loop) {
09582 break;
09583 }
09584
09585 if (pollsize == 0) {
09586 if (!was_idle) {
09587 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
09588 was_idle = 1;
09589 }
09590 poll(NULL, 0, maxsleep);
09591 continue;
09592 }
09593 was_idle = 0;
09594
09595
09596
09597 pthread_testcancel();
09598 res = poll(pollers, pollsize, maxsleep);
09599 pthread_testcancel();
09600 if ((res < 0) && (errno != EINTR)) {
09601 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
09602 break;
09603 }
09604
09605 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
09606 for (i = 0; i < mfcr2->numchans; i++) {
09607 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
09608 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
09609 }
09610 }
09611 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
09612 }
09613 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
09614 return 0;
09615 }
09616 #endif
09617
09618
09619 #ifdef HAVE_PRI
09620 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
09621 {
09622 struct dahdi_pvt *p;
09623 p = pri->crvs;
09624 while (p) {
09625 if (p->channel == crv)
09626 return p;
09627 p = p->next;
09628 }
09629 return NULL;
09630 }
09631
09632
09633 static int pri_find_principle(struct dahdi_pri *pri, int channel)
09634 {
09635 int x;
09636 int span = PRI_SPAN(channel);
09637 int spanfd;
09638 struct dahdi_params param;
09639 int principle = -1;
09640 int explicit = PRI_EXPLICIT(channel);
09641 channel = PRI_CHANNEL(channel);
09642
09643 if (!explicit) {
09644 spanfd = pri_active_dchan_fd(pri);
09645 memset(¶m, 0, sizeof(param));
09646 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
09647 return -1;
09648 span = pris[param.spanno - 1].prilogicalspan;
09649 }
09650
09651 for (x = 0; x < pri->numchans; x++) {
09652 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
09653 principle = x;
09654 break;
09655 }
09656 }
09657
09658 return principle;
09659 }
09660
09661 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
09662 {
09663 int x;
09664 struct dahdi_pvt *crv;
09665 if (!c) {
09666 if (principle < 0)
09667 return -1;
09668 return principle;
09669 }
09670 if ((principle > -1) &&
09671 (principle < pri->numchans) &&
09672 (pri->pvts[principle]) &&
09673 (pri->pvts[principle]->call == c))
09674 return principle;
09675
09676 for (x = 0; x < pri->numchans; x++) {
09677 if (!pri->pvts[x])
09678 continue;
09679 if (pri->pvts[x]->call == c) {
09680
09681 if (principle != x) {
09682 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
09683
09684 if (option_verbose > 2)
09685 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
09686 old->channel, new->channel);
09687 if (new->owner) {
09688 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
09689 old->channel, new->channel, new->channel);
09690 return -1;
09691 }
09692
09693 new->owner = old->owner;
09694 old->owner = NULL;
09695 if (new->owner) {
09696 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
09697 new->owner->tech_pvt = new;
09698 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
09699 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
09700 old->subs[SUB_REAL].owner = NULL;
09701 } else
09702 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);
09703 new->call = old->call;
09704 old->call = NULL;
09705
09706
09707 new->dsp = old->dsp;
09708 new->dsp_features = old->dsp_features;
09709 old->dsp = NULL;
09710 old->dsp_features = 0;
09711 }
09712 return principle;
09713 }
09714 }
09715
09716 crv = pri->crvs;
09717 while (crv) {
09718 if (crv->call == c) {
09719
09720 if (crv->bearer)
09721 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
09722 else if (pri->pvts[principle]->owner)
09723 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
09724 else {
09725
09726
09727 dahdi_close_sub(crv, SUB_REAL);
09728 pri->pvts[principle]->call = crv->call;
09729 pri_assign_bearer(crv, pri, pri->pvts[principle]);
09730 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
09731 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
09732 pri->trunkgroup, crv->channel);
09733 wakeup_sub(crv, SUB_REAL, pri);
09734 }
09735 return principle;
09736 }
09737 crv = crv->next;
09738 }
09739 ast_log(LOG_WARNING, "Call specified, but not found?\n");
09740 return -1;
09741 }
09742
09743 static void *do_idle_thread(void *vchan)
09744 {
09745 struct ast_channel *chan = vchan;
09746 struct dahdi_pvt *pvt = chan->tech_pvt;
09747 struct ast_frame *f;
09748 char ex[80];
09749
09750 int newms, ms = 30000;
09751 if (option_verbose > 2)
09752 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
09753 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
09754 if (ast_call(chan, ex, 0)) {
09755 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
09756 ast_hangup(chan);
09757 return NULL;
09758 }
09759 while ((newms = ast_waitfor(chan, ms)) > 0) {
09760 f = ast_read(chan);
09761 if (!f) {
09762
09763 break;
09764 }
09765 if (f->frametype == AST_FRAME_CONTROL) {
09766 switch (f->subclass) {
09767 case AST_CONTROL_ANSWER:
09768
09769 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
09770 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
09771 chan->priority = 1;
09772 if (option_verbose > 3)
09773 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
09774 ast_pbx_run(chan);
09775
09776 return NULL;
09777 case AST_CONTROL_BUSY:
09778 if (option_verbose > 3)
09779 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
09780 break;
09781 case AST_CONTROL_CONGESTION:
09782 if (option_verbose > 3)
09783 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
09784 break;
09785 };
09786 }
09787 ast_frfree(f);
09788 ms = newms;
09789 }
09790
09791 ast_hangup(chan);
09792 return NULL;
09793 }
09794
09795 #ifndef PRI_RESTART
09796 #error "Upgrade your libpri"
09797 #endif
09798 static void dahdi_pri_message(struct pri *pri, char *s)
09799 {
09800 int x, y;
09801 int dchan = -1, span = -1;
09802 int dchancount = 0;
09803
09804 if (pri) {
09805 for (x = 0; x < NUM_SPANS; x++) {
09806 for (y = 0; y < NUM_DCHANS; y++) {
09807 if (pris[x].dchans[y])
09808 dchancount++;
09809
09810 if (pris[x].dchans[y] == pri)
09811 dchan = y;
09812 }
09813 if (dchan >= 0) {
09814 span = x;
09815 break;
09816 }
09817 dchancount = 0;
09818 }
09819 if ((dchan >= 0) && (span >= 0)) {
09820 if (dchancount > 1)
09821 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
09822 else
09823 ast_verbose("%s", s);
09824 } else
09825 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09826 } else
09827 ast_verbose("%s", s);
09828
09829 ast_mutex_lock(&pridebugfdlock);
09830
09831 if (pridebugfd >= 0) {
09832 if (write(pridebugfd, s, strlen(s)) < 0) {
09833 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09834 }
09835 }
09836
09837 ast_mutex_unlock(&pridebugfdlock);
09838 }
09839
09840 static void dahdi_pri_error(struct pri *pri, char *s)
09841 {
09842 int x, y;
09843 int dchan = -1, span = -1;
09844 int dchancount = 0;
09845
09846 if (pri) {
09847 for (x = 0; x < NUM_SPANS; x++) {
09848 for (y = 0; y < NUM_DCHANS; y++) {
09849 if (pris[x].dchans[y])
09850 dchancount++;
09851
09852 if (pris[x].dchans[y] == pri)
09853 dchan = y;
09854 }
09855 if (dchan >= 0) {
09856 span = x;
09857 break;
09858 }
09859 dchancount = 0;
09860 }
09861 if ((dchan >= 0) && (span >= 0)) {
09862 if (dchancount > 1)
09863 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
09864 else
09865 ast_log(LOG_ERROR, "%s", s);
09866 } else
09867 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09868 } else
09869 ast_log(LOG_ERROR, "%s", s);
09870
09871 ast_mutex_lock(&pridebugfdlock);
09872
09873 if (pridebugfd >= 0) {
09874 if (write(pridebugfd, s, strlen(s)) < 0) {
09875 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09876 }
09877 }
09878
09879 ast_mutex_unlock(&pridebugfdlock);
09880 }
09881
09882 static int pri_check_restart(struct dahdi_pri *pri)
09883 {
09884 do {
09885 pri->resetpos++;
09886 } while ((pri->resetpos < pri->numchans) &&
09887 (!pri->pvts[pri->resetpos] ||
09888 pri->pvts[pri->resetpos]->call ||
09889 pri->pvts[pri->resetpos]->resetting));
09890 if (pri->resetpos < pri->numchans) {
09891
09892 pri->pvts[pri->resetpos]->resetting = 1;
09893 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
09894 } else {
09895 pri->resetting = 0;
09896 time(&pri->lastreset);
09897 }
09898 return 0;
09899 }
09900
09901 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
09902 {
09903 int x;
09904 int redo;
09905 ast_mutex_unlock(&pri->lock);
09906 ast_mutex_lock(&p->lock);
09907 do {
09908 redo = 0;
09909 for (x = 0; x < 3; x++) {
09910 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
09911 redo++;
09912 DEADLOCK_AVOIDANCE(&p->lock);
09913 }
09914 if (p->subs[x].owner) {
09915 ast_queue_hangup(p->subs[x].owner);
09916 ast_mutex_unlock(&p->subs[x].owner->lock);
09917 }
09918 }
09919 } while (redo);
09920 ast_mutex_unlock(&p->lock);
09921 ast_mutex_lock(&pri->lock);
09922 return 0;
09923 }
09924
09925 static char * redirectingreason2str(int redirectingreason)
09926 {
09927 switch (redirectingreason) {
09928 case 0:
09929 return "UNKNOWN";
09930 case 1:
09931 return "BUSY";
09932 case 2:
09933 return "NO_REPLY";
09934 case 0xF:
09935 return "UNCONDITIONAL";
09936 default:
09937 return "NOREDIRECT";
09938 }
09939 }
09940
09941 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
09942 {
09943 if (ast_strlen_zero(number)) {
09944 if (size) {
09945 *buf = '\0';
09946 }
09947 return;
09948 }
09949
09950 switch (plan) {
09951 case PRI_INTERNATIONAL_ISDN:
09952 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
09953 break;
09954 case PRI_NATIONAL_ISDN:
09955 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
09956 break;
09957 case PRI_LOCAL_ISDN:
09958 snprintf(buf, size, "%s%s", pri->localprefix, number);
09959 break;
09960 case PRI_PRIVATE:
09961 snprintf(buf, size, "%s%s", pri->privateprefix, number);
09962 break;
09963 case PRI_UNKNOWN:
09964 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
09965 break;
09966 default:
09967 snprintf(buf, size, "%s", number);
09968 break;
09969 }
09970 }
09971
09972 static int dahdi_setlaw(int dfd, int law)
09973 {
09974 int res;
09975 res = ioctl(dfd, DAHDI_SETLAW, &law);
09976 if (res)
09977 return res;
09978 return 0;
09979 }
09980
09981 static void *pri_dchannel(void *vpri)
09982 {
09983 struct dahdi_pri *pri = vpri;
09984 pri_event *e;
09985 struct pollfd fds[NUM_DCHANS];
09986 int res;
09987 int chanpos = 0;
09988 int x;
09989 int haveidles;
09990 int activeidles;
09991 int nextidle = -1;
09992 struct ast_channel *c;
09993 struct timeval tv, lowest, *next;
09994 struct timeval lastidle = { 0, 0 };
09995 int doidling=0;
09996 char *cc;
09997 char idlen[80];
09998 struct ast_channel *idle;
09999 pthread_t p;
10000 time_t t;
10001 int i, which=-1;
10002 int numdchans;
10003 int cause=0;
10004 struct dahdi_pvt *crv;
10005 pthread_t threadid;
10006 pthread_attr_t attr;
10007 char ani2str[6];
10008 char plancallingnum[256];
10009 char plancallingani[256];
10010 char calledtonstr[10];
10011
10012 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10013
10014 gettimeofday(&lastidle, NULL);
10015 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10016
10017 cc = strchr(pri->idleext, '@');
10018 if (cc) {
10019 *cc = '\0';
10020 cc++;
10021 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10022 #if 0
10023
10024 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10025 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10026 else
10027 #endif
10028 doidling = 1;
10029 } else
10030 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10031 }
10032 for (;;) {
10033 for (i = 0; i < NUM_DCHANS; i++) {
10034 if (!pri->dchannels[i])
10035 break;
10036 fds[i].fd = pri->fds[i];
10037 fds[i].events = POLLIN | POLLPRI;
10038 fds[i].revents = 0;
10039 }
10040 numdchans = i;
10041 time(&t);
10042 ast_mutex_lock(&pri->lock);
10043 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10044 if (pri->resetting && pri_is_up(pri)) {
10045 if (pri->resetpos < 0)
10046 pri_check_restart(pri);
10047 } else {
10048 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10049 pri->resetting = 1;
10050 pri->resetpos = -1;
10051 }
10052 }
10053 }
10054
10055 if (doidling && pri_is_up(pri)) {
10056 nextidle = -1;
10057 haveidles = 0;
10058 activeidles = 0;
10059 for (x = pri->numchans; x >= 0; x--) {
10060 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10061 !pri->pvts[x]->call) {
10062 if (haveidles < pri->minunused) {
10063 haveidles++;
10064 } else if (!pri->pvts[x]->resetting) {
10065 nextidle = x;
10066 break;
10067 }
10068 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10069 activeidles++;
10070 }
10071 if (nextidle > -1) {
10072 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10073
10074 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10075 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
10076 if (idle) {
10077 pri->pvts[nextidle]->isidlecall = 1;
10078 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10079 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10080 dahdi_hangup(idle);
10081 }
10082 } else
10083 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10084 gettimeofday(&lastidle, NULL);
10085 }
10086 } else if ((haveidles < pri->minunused) &&
10087 (activeidles > pri->minidle)) {
10088
10089
10090 for (x = pri->numchans; x >= 0; x--) {
10091
10092 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10093 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10094 haveidles++;
10095
10096
10097 if ((haveidles >= pri->minunused) ||
10098 (activeidles <= pri->minidle))
10099 break;
10100 }
10101 }
10102 }
10103 }
10104
10105 lowest = ast_tv(60, 0);
10106 for (i = 0; i < NUM_DCHANS; i++) {
10107
10108 if (!pri->dchannels[i])
10109 break;
10110 if ((next = pri_schedule_next(pri->dchans[i]))) {
10111
10112 tv = ast_tvsub(*next, ast_tvnow());
10113 if (tv.tv_sec < 0) {
10114 tv = ast_tv(0,0);
10115 }
10116 if (doidling || pri->resetting) {
10117 if (tv.tv_sec > 1) {
10118 tv = ast_tv(1, 0);
10119 }
10120 } else {
10121 if (tv.tv_sec > 60) {
10122 tv = ast_tv(60, 0);
10123 }
10124 }
10125 } else if (doidling || pri->resetting) {
10126
10127
10128 tv = ast_tv(1,0);
10129 } else {
10130
10131 tv = ast_tv(60, 0);
10132 }
10133 if (!i || ast_tvcmp(tv, lowest) < 0) {
10134 lowest = tv;
10135 }
10136 }
10137 ast_mutex_unlock(&pri->lock);
10138
10139 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10140 pthread_testcancel();
10141 e = NULL;
10142 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10143 pthread_testcancel();
10144 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10145
10146 ast_mutex_lock(&pri->lock);
10147 if (!res) {
10148 for (which = 0; which < NUM_DCHANS; which++) {
10149 if (!pri->dchans[which])
10150 break;
10151
10152 e = pri_schedule_run(pri->dchans[which]);
10153 if (e)
10154 break;
10155 }
10156 } else if (res > -1) {
10157 for (which = 0; which < NUM_DCHANS; which++) {
10158 if (!pri->dchans[which])
10159 break;
10160 if (fds[which].revents & POLLPRI) {
10161
10162 x = 0;
10163 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10164 if (x)
10165 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);
10166
10167 if (x == DAHDI_EVENT_ALARM) {
10168 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10169 pri_find_dchan(pri);
10170 } else if (x == DAHDI_EVENT_NOALARM) {
10171 pri->dchanavail[which] |= DCHAN_NOTINALARM;
10172 pri_restart(pri->dchans[which]);
10173 }
10174
10175 if (option_debug)
10176 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10177 } else if (fds[which].revents & POLLIN) {
10178 e = pri_check_event(pri->dchans[which]);
10179 }
10180 if (e)
10181 break;
10182 }
10183 } else if (errno != EINTR)
10184 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10185
10186 if (e) {
10187 if (pri->debug)
10188 pri_dump_event(pri->dchans[which], e);
10189
10190 if (e->e != PRI_EVENT_DCHAN_DOWN) {
10191 if (!(pri->dchanavail[which] & DCHAN_UP)) {
10192 if (option_verbose > 1)
10193 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10194 }
10195 pri->dchanavail[which] |= DCHAN_UP;
10196 } else {
10197 if (pri->dchanavail[which] & DCHAN_UP) {
10198 if (option_verbose > 1)
10199 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10200 }
10201 pri->dchanavail[which] &= ~DCHAN_UP;
10202 }
10203
10204 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10205
10206 pri->pri = pri->dchans[which];
10207
10208 switch (e->e) {
10209 case PRI_EVENT_DCHAN_UP:
10210 if (!pri->pri) pri_find_dchan(pri);
10211
10212
10213 time(&pri->lastreset);
10214
10215
10216 if (pri->resetinterval > -1) {
10217 pri->lastreset -= pri->resetinterval;
10218 pri->lastreset += 5;
10219 }
10220 pri->resetting = 0;
10221
10222 for (i = 0; i < pri->numchans; i++)
10223 if (pri->pvts[i]) {
10224 pri->pvts[i]->inalarm = 0;
10225 }
10226 break;
10227 case PRI_EVENT_DCHAN_DOWN:
10228 pri_find_dchan(pri);
10229 if (!pri_is_up(pri)) {
10230 pri->resetting = 0;
10231
10232 for (i = 0; i < pri->numchans; i++) {
10233 struct dahdi_pvt *p = pri->pvts[i];
10234 if (p) {
10235 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10236
10237 if (p->call) {
10238 if (p->pri && p->pri->pri) {
10239 pri_hangup(p->pri->pri, p->call, -1);
10240 pri_destroycall(p->pri->pri, p->call);
10241 p->call = NULL;
10242 } else
10243 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10244 }
10245 if (p->realcall) {
10246 pri_hangup_all(p->realcall, pri);
10247 } else if (p->owner)
10248 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10249 }
10250 p->inalarm = 1;
10251 }
10252 }
10253 }
10254 break;
10255 case PRI_EVENT_RESTART:
10256 if (e->restart.channel > -1) {
10257 chanpos = pri_find_principle(pri, e->restart.channel);
10258 if (chanpos < 0)
10259 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10260 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10261 else {
10262 if (option_verbose > 2)
10263 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
10264 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10265 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10266 if (pri->pvts[chanpos]->call) {
10267 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10268 pri->pvts[chanpos]->call = NULL;
10269 }
10270
10271 if (pri->pvts[chanpos]->realcall)
10272 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10273 else if (pri->pvts[chanpos]->owner)
10274 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10275 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10276 }
10277 } else {
10278 if (option_verbose > 2)
10279 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
10280 for (x = 0; x < pri->numchans; x++)
10281 if (pri->pvts[x]) {
10282 ast_mutex_lock(&pri->pvts[x]->lock);
10283 if (pri->pvts[x]->call) {
10284 pri_destroycall(pri->pri, pri->pvts[x]->call);
10285 pri->pvts[x]->call = NULL;
10286 }
10287 if (pri->pvts[x]->realcall)
10288 pri_hangup_all(pri->pvts[x]->realcall, pri);
10289 else if (pri->pvts[x]->owner)
10290 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10291 ast_mutex_unlock(&pri->pvts[x]->lock);
10292 }
10293 }
10294 break;
10295 case PRI_EVENT_KEYPAD_DIGIT:
10296 chanpos = pri_find_principle(pri, e->digit.channel);
10297 if (chanpos < 0) {
10298 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10299 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10300 } else {
10301 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10302 if (chanpos > -1) {
10303 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10304
10305 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
10306
10307 int digitlen = strlen(e->digit.digits);
10308 char digit;
10309 int i;
10310 for (i = 0; i < digitlen; i++) {
10311 digit = e->digit.digits[i];
10312 {
10313 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10314 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10315 }
10316 }
10317 }
10318 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10319 }
10320 }
10321 break;
10322
10323 case PRI_EVENT_INFO_RECEIVED:
10324 chanpos = pri_find_principle(pri, e->ring.channel);
10325 if (chanpos < 0) {
10326 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
10327 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10328 } else {
10329 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
10330 if (chanpos > -1) {
10331 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10332
10333 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
10334
10335 int digitlen = strlen(e->ring.callednum);
10336 char digit;
10337 int i;
10338 for (i = 0; i < digitlen; i++) {
10339 digit = e->ring.callednum[i];
10340 {
10341 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10342 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10343 }
10344 }
10345 }
10346 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10347 }
10348 }
10349 break;
10350 case PRI_EVENT_RING:
10351 crv = NULL;
10352 if (e->ring.channel == -1)
10353 chanpos = pri_find_empty_chan(pri, 1);
10354 else
10355 chanpos = pri_find_principle(pri, e->ring.channel);
10356
10357 if (chanpos < 0) {
10358 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
10359 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10360 } else {
10361 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10362 if (pri->pvts[chanpos]->owner) {
10363 if (pri->pvts[chanpos]->call == e->ring.call) {
10364 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
10365 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10366 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10367 break;
10368 } else {
10369
10370 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
10371 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10372 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10373 chanpos = -1;
10374 }
10375 }
10376 if (chanpos > -1)
10377 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10378 }
10379 if ((chanpos < 0) && (e->ring.flexible))
10380 chanpos = pri_find_empty_chan(pri, 1);
10381 if (chanpos > -1) {
10382 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10383 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
10384
10385 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
10386 if (crv)
10387 ast_mutex_lock(&crv->lock);
10388 if (!crv || crv->owner) {
10389 pri->pvts[chanpos]->call = NULL;
10390 if (crv) {
10391 if (crv->owner)
10392 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10393 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);
10394 } else
10395 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);
10396 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
10397 if (crv)
10398 ast_mutex_unlock(&crv->lock);
10399 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10400 break;
10401 }
10402 }
10403 pri->pvts[chanpos]->call = e->ring.call;
10404 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
10405 if (pri->pvts[chanpos]->use_callerid) {
10406 ast_shrink_phone_number(plancallingnum);
10407 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
10408 #ifdef PRI_ANI
10409 if (!ast_strlen_zero(e->ring.callingani)) {
10410 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
10411 ast_shrink_phone_number(plancallingani);
10412 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
10413 } else {
10414 pri->pvts[chanpos]->cid_ani[0] = '\0';
10415 }
10416 #endif
10417 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
10418 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
10419 } else {
10420 pri->pvts[chanpos]->cid_num[0] = '\0';
10421 pri->pvts[chanpos]->cid_ani[0] = '\0';
10422 pri->pvts[chanpos]->cid_name[0] = '\0';
10423 pri->pvts[chanpos]->cid_ton = 0;
10424 }
10425 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
10426 e->ring.redirectingnum, e->ring.callingplanrdnis);
10427
10428 if (pri->pvts[chanpos]->immediate) {
10429 if (option_verbose > 2)
10430 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
10431 pri->pvts[chanpos]->exten[0] = 's';
10432 pri->pvts[chanpos]->exten[1] = '\0';
10433 }
10434
10435 else if (!ast_strlen_zero(e->ring.callednum)) {
10436 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
10437 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10438 } else if (pri->overlapdial)
10439 pri->pvts[chanpos]->exten[0] = '\0';
10440 else {
10441
10442 pri->pvts[chanpos]->exten[0] = 's';
10443 pri->pvts[chanpos]->exten[1] = '\0';
10444 }
10445
10446 if (!ast_strlen_zero(e->ring.callednum))
10447 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10448
10449 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
10450 if (option_verbose > 2)
10451 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
10452 pri->pvts[chanpos]->exten[0] = 's';
10453 pri->pvts[chanpos]->exten[1] = '\0';
10454 }
10455
10456
10457 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
10458 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10459
10460 int law;
10461 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
10462
10463 law = 1;
10464 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
10465 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
10466 }
10467 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
10468 law = DAHDI_LAW_ALAW;
10469 else
10470 law = DAHDI_LAW_MULAW;
10471 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
10472 if (res < 0)
10473 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
10474 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10475 if (res < 0)
10476 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
10477 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
10478
10479 pri->pvts[chanpos]->proceeding = 1;
10480 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
10481 } else {
10482 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
10483 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10484 else
10485 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10486 }
10487
10488 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
10489
10490
10491 if (!e->ring.complete
10492 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
10493 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10494
10495
10496
10497
10498 ast_mutex_unlock(&pri->lock);
10499 if (crv) {
10500
10501 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
10502 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10503 pri->pvts[chanpos]->owner = &inuse;
10504 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
10505 } else {
10506 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10507 }
10508 ast_mutex_lock(&pri->lock);
10509 if (c) {
10510 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10511 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10512 }
10513 if (e->ring.ani2 >= 0) {
10514 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10515 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10516 }
10517
10518 #ifdef SUPPORT_USERUSER
10519 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10520 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10521 }
10522 #endif
10523
10524 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10525 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10526 if (e->ring.redirectingreason >= 0)
10527 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10528 }
10529
10530 pthread_attr_init(&attr);
10531 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10532 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
10533 if (option_verbose > 2)
10534 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10535 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
10536 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10537 } else {
10538 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10539 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10540 if (c)
10541 ast_hangup(c);
10542 else {
10543 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10544 pri->pvts[chanpos]->call = NULL;
10545 }
10546 }
10547 pthread_attr_destroy(&attr);
10548 } else {
10549
10550
10551
10552
10553 ast_mutex_unlock(&pri->lock);
10554 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
10555 ast_mutex_lock(&pri->lock);
10556 if (c) {
10557
10558
10559
10560
10561
10562
10563
10564
10565 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10566 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10567 }
10568 if (e->ring.ani2 >= 0) {
10569 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10570 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10571 }
10572
10573 #ifdef SUPPORT_USERUSER
10574 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10575 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10576 }
10577 #endif
10578
10579 if (e->ring.redirectingreason >= 0)
10580 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10581
10582 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10583 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10584 }
10585 if (c && !ast_pbx_start(c)) {
10586 if (option_verbose > 2)
10587 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10588 plancallingnum, pri->pvts[chanpos]->exten,
10589 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10590
10591 dahdi_enable_ec(pri->pvts[chanpos]);
10592 } else {
10593 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10594 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10595 if (c) {
10596 ast_hangup(c);
10597 } else {
10598 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10599 pri->pvts[chanpos]->call = NULL;
10600 }
10601 }
10602 }
10603 } else {
10604 if (option_verbose > 2)
10605 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
10606 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
10607 pri->pvts[chanpos]->prioffset, pri->span);
10608 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
10609 pri->pvts[chanpos]->call = NULL;
10610 pri->pvts[chanpos]->exten[0] = '\0';
10611 }
10612 if (crv)
10613 ast_mutex_unlock(&crv->lock);
10614 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10615 } else {
10616 if (e->ring.flexible)
10617 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
10618 else
10619 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
10620 }
10621 break;
10622 case PRI_EVENT_RINGING:
10623 chanpos = pri_find_principle(pri, e->ringing.channel);
10624 if (chanpos < 0) {
10625 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
10626 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10627 } else {
10628 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
10629 if (chanpos < 0) {
10630 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
10631 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10632 } else {
10633 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10634 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10635 dahdi_enable_ec(pri->pvts[chanpos]);
10636 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
10637 pri->pvts[chanpos]->alerting = 1;
10638 } else
10639 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
10640 #ifdef PRI_PROGRESS_MASK
10641 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10642 #else
10643 if (e->ringing.progress == 8) {
10644 #endif
10645
10646 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10647
10648 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
10649 pri->pvts[chanpos]->dsp_features = 0;
10650 }
10651 }
10652
10653 #ifdef SUPPORT_USERUSER
10654 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
10655 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10656 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10657 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
10658 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10659 }
10660 #endif
10661
10662 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10663 }
10664 }
10665 break;
10666 case PRI_EVENT_PROGRESS:
10667
10668 chanpos = pri_find_principle(pri, e->proceeding.channel);
10669 if (chanpos > -1) {
10670 #ifdef PRI_PROGRESS_MASK
10671 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
10672 #else
10673 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
10674 #endif
10675 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10676
10677 if (e->proceeding.cause > -1) {
10678 if (option_verbose > 2)
10679 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
10680
10681
10682 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
10683 if (pri->pvts[chanpos]->owner) {
10684 if (option_verbose > 2)
10685 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
10686
10687 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
10688 f.subclass = AST_CONTROL_BUSY;
10689 }
10690 }
10691 }
10692
10693 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10694 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
10695 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10696 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10697 #ifdef PRI_PROGRESS_MASK
10698 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10699 #else
10700 if (e->proceeding.progress == 8) {
10701 #endif
10702
10703 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10704 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10705 pri->pvts[chanpos]->dsp_features = 0;
10706 }
10707
10708 f.subclass = AST_CONTROL_PROGRESS;
10709 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10710 }
10711 pri->pvts[chanpos]->progress = 1;
10712 pri->pvts[chanpos]->dialing = 0;
10713 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10714 }
10715 }
10716 break;
10717 case PRI_EVENT_PROCEEDING:
10718 chanpos = pri_find_principle(pri, e->proceeding.channel);
10719 if (chanpos > -1) {
10720 if (!pri->pvts[chanpos]->proceeding) {
10721 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10722
10723 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10724 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
10725 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10726 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10727 #ifdef PRI_PROGRESS_MASK
10728 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10729 #else
10730 if (e->proceeding.progress == 8) {
10731 #endif
10732
10733 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10734 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10735 pri->pvts[chanpos]->dsp_features = 0;
10736 }
10737
10738 f.subclass = AST_CONTROL_PROGRESS;
10739 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10740 }
10741 pri->pvts[chanpos]->proceeding = 1;
10742 pri->pvts[chanpos]->dialing = 0;
10743 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10744 }
10745 }
10746 break;
10747 case PRI_EVENT_FACNAME:
10748 chanpos = pri_find_principle(pri, e->facname.channel);
10749 if (chanpos < 0) {
10750 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
10751 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10752 } else {
10753 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
10754 if (chanpos < 0) {
10755 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
10756 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10757 } else {
10758
10759 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10760 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
10761 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
10762 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
10763 dahdi_enable_ec(pri->pvts[chanpos]);
10764 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10765 }
10766 }
10767 break;
10768 case PRI_EVENT_ANSWER:
10769 chanpos = pri_find_principle(pri, e->answer.channel);
10770 if (chanpos < 0) {
10771 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
10772 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10773 } else {
10774 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
10775 if (chanpos < 0) {
10776 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
10777 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10778 } else {
10779 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10780
10781
10782
10783
10784
10785 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10786 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10787 pri->pvts[chanpos]->dsp_features = 0;
10788 }
10789 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
10790 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
10791 x = DAHDI_START;
10792 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10793 if (res < 0) {
10794 if (errno != EINPROGRESS) {
10795 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
10796 }
10797 }
10798 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10799 pri->pvts[chanpos]->dialing = 1;
10800
10801 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
10802 if (res < 0) {
10803 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
10804 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10805 } else
10806 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
10807 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10808 } else if (pri->pvts[chanpos]->confirmanswer) {
10809 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
10810 } else {
10811 pri->pvts[chanpos]->dialing = 0;
10812 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
10813
10814 dahdi_enable_ec(pri->pvts[chanpos]);
10815 }
10816
10817 #ifdef SUPPORT_USERUSER
10818 if (!ast_strlen_zero(e->answer.useruserinfo)) {
10819 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10820 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10821 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
10822 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10823 }
10824 #endif
10825
10826 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10827 }
10828 }
10829 break;
10830 case PRI_EVENT_HANGUP:
10831 chanpos = pri_find_principle(pri, e->hangup.channel);
10832 if (chanpos < 0) {
10833 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
10834 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10835 } else {
10836 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10837 if (chanpos > -1) {
10838 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10839 if (!pri->pvts[chanpos]->alreadyhungup) {
10840
10841 pri->pvts[chanpos]->alreadyhungup = 1;
10842 if (pri->pvts[chanpos]->realcall)
10843 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10844 else if (pri->pvts[chanpos]->owner) {
10845
10846 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10847 switch (pri->pvts[chanpos]->owner->_state) {
10848 case AST_STATE_BUSY:
10849 case AST_STATE_UP:
10850 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10851 break;
10852 default:
10853 switch (e->hangup.cause) {
10854 case PRI_CAUSE_USER_BUSY:
10855 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10856 break;
10857 case PRI_CAUSE_CALL_REJECTED:
10858 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10859 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10860 case PRI_CAUSE_SWITCH_CONGESTION:
10861 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10862 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10863 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10864 break;
10865 default:
10866 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10867 }
10868 break;
10869 }
10870 }
10871 if (option_verbose > 2)
10872 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
10873 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
10874 } else {
10875 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10876 pri->pvts[chanpos]->call = NULL;
10877 }
10878 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10879 if (option_verbose > 2)
10880 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
10881 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10882 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10883 pri->pvts[chanpos]->resetting = 1;
10884 }
10885 if (e->hangup.aoc_units > -1)
10886 if (option_verbose > 2)
10887 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10888 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10889
10890 #ifdef SUPPORT_USERUSER
10891 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
10892 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10893 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10894 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10895 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10896 }
10897 #endif
10898
10899 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10900 } else {
10901 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
10902 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10903 }
10904 }
10905 break;
10906 #ifndef PRI_EVENT_HANGUP_REQ
10907 #error please update libpri
10908 #endif
10909 case PRI_EVENT_HANGUP_REQ:
10910 chanpos = pri_find_principle(pri, e->hangup.channel);
10911 if (chanpos < 0) {
10912 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
10913 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10914 } else {
10915 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10916 if (chanpos > -1) {
10917 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10918 if (pri->pvts[chanpos]->realcall)
10919 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10920 else if (pri->pvts[chanpos]->owner) {
10921 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10922 switch (pri->pvts[chanpos]->owner->_state) {
10923 case AST_STATE_BUSY:
10924 case AST_STATE_UP:
10925 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10926 break;
10927 default:
10928 switch (e->hangup.cause) {
10929 case PRI_CAUSE_USER_BUSY:
10930 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10931 break;
10932 case PRI_CAUSE_CALL_REJECTED:
10933 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10934 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10935 case PRI_CAUSE_SWITCH_CONGESTION:
10936 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10937 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10938 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10939 break;
10940 default:
10941 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10942 }
10943 break;
10944 }
10945 if (option_verbose > 2)
10946 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
10947 if (e->hangup.aoc_units > -1)
10948 if (option_verbose > 2)
10949 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10950 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10951 } else {
10952 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10953 pri->pvts[chanpos]->call = NULL;
10954 }
10955 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10956 if (option_verbose > 2)
10957 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
10958 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10959 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10960 pri->pvts[chanpos]->resetting = 1;
10961 }
10962
10963 #ifdef SUPPORT_USERUSER
10964 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
10965 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10966 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10967 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10968 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10969 }
10970 #endif
10971
10972 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10973 } else {
10974 ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10975 }
10976 }
10977 break;
10978 case PRI_EVENT_HANGUP_ACK:
10979 chanpos = pri_find_principle(pri, e->hangup.channel);
10980 if (chanpos < 0) {
10981 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
10982 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10983 } else {
10984 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10985 if (chanpos > -1) {
10986 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10987 pri->pvts[chanpos]->call = NULL;
10988 pri->pvts[chanpos]->resetting = 0;
10989 if (pri->pvts[chanpos]->owner) {
10990 if (option_verbose > 2)
10991 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10992 }
10993
10994 #ifdef SUPPORT_USERUSER
10995 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
10996 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10997 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10998 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10999 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11000 }
11001 #endif
11002
11003 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11004 }
11005 }
11006 break;
11007 case PRI_EVENT_CONFIG_ERR:
11008 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11009 break;
11010 case PRI_EVENT_RESTART_ACK:
11011 chanpos = pri_find_principle(pri, e->restartack.channel);
11012 if (chanpos < 0) {
11013
11014
11015
11016 for (x = 0; x < pri->numchans; x++) {
11017 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11018 chanpos = x;
11019 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11020 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11021 pri->pvts[chanpos]->prioffset, pri->span);
11022 if (pri->pvts[chanpos]->realcall)
11023 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11024 else if (pri->pvts[chanpos]->owner) {
11025 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11026 pri->pvts[chanpos]->prioffset, pri->span);
11027 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11028 }
11029 pri->pvts[chanpos]->resetting = 0;
11030 if (option_verbose > 2)
11031 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11032 pri->pvts[chanpos]->prioffset, pri->span);
11033 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11034 if (pri->resetting)
11035 pri_check_restart(pri);
11036 break;
11037 }
11038 }
11039 if (chanpos < 0) {
11040 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11041 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11042 }
11043 } else {
11044 if (pri->pvts[chanpos]) {
11045 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11046 if (pri->pvts[chanpos]->realcall)
11047 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11048 else if (pri->pvts[chanpos]->owner) {
11049 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11050 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11051 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11052 }
11053 pri->pvts[chanpos]->resetting = 0;
11054 if (option_verbose > 2)
11055 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11056 pri->pvts[chanpos]->prioffset, pri->span);
11057 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11058 if (pri->resetting)
11059 pri_check_restart(pri);
11060 }
11061 }
11062 break;
11063 case PRI_EVENT_SETUP_ACK:
11064 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11065 if (chanpos < 0) {
11066 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11067 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11068 } else {
11069 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11070 if (chanpos > -1) {
11071 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11072 pri->pvts[chanpos]->setup_ack = 1;
11073
11074 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11075 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11076 pri_information(pri->pri, pri->pvts[chanpos]->call,
11077 pri->pvts[chanpos]->dialdest[x]);
11078 }
11079 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11080 } else
11081 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11082 }
11083 break;
11084 case PRI_EVENT_NOTIFY:
11085 chanpos = pri_find_principle(pri, e->notify.channel);
11086 if (chanpos < 0) {
11087 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11088 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11089 } else {
11090 struct ast_frame f = { AST_FRAME_CONTROL, };
11091 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11092 switch (e->notify.info) {
11093 case PRI_NOTIFY_REMOTE_HOLD:
11094 f.subclass = AST_CONTROL_HOLD;
11095 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11096 break;
11097 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11098 f.subclass = AST_CONTROL_UNHOLD;
11099 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11100 break;
11101 }
11102 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11103 }
11104 break;
11105 default:
11106 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
11107 }
11108 }
11109 ast_mutex_unlock(&pri->lock);
11110 }
11111
11112 return NULL;
11113 }
11114
11115 static int start_pri(struct dahdi_pri *pri)
11116 {
11117 int res, x;
11118 struct dahdi_params p;
11119 struct dahdi_bufferinfo bi;
11120 struct dahdi_spaninfo si;
11121 int i;
11122
11123 for (i = 0; i < NUM_DCHANS; i++) {
11124 if (!pri->dchannels[i])
11125 break;
11126 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
11127 x = pri->dchannels[i];
11128 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11129 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11130 return -1;
11131 }
11132 memset(&p, 0, sizeof(p));
11133 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11134 if (res) {
11135 dahdi_close_pri_fd(pri, i);
11136 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11137 return -1;
11138 }
11139 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11140 dahdi_close_pri_fd(pri, i);
11141 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
11142 return -1;
11143 }
11144 memset(&si, 0, sizeof(si));
11145 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11146 if (res) {
11147 dahdi_close_pri_fd(pri, i);
11148 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11149 }
11150 if (!si.alarms)
11151 pri->dchanavail[i] |= DCHAN_NOTINALARM;
11152 else
11153 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11154 memset(&bi, 0, sizeof(bi));
11155 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11156 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11157 bi.numbufs = 32;
11158 bi.bufsize = 1024;
11159 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11160 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11161 dahdi_close_pri_fd(pri, i);
11162 return -1;
11163 }
11164 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11165
11166 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11167 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11168 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11169 #ifdef HAVE_PRI_INBANDDISCONNECT
11170 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11171 #endif
11172
11173 if (i)
11174 pri_enslave(pri->dchans[0], pri->dchans[i]);
11175 if (!pri->dchans[i]) {
11176 dahdi_close_pri_fd(pri, i);
11177 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11178 return -1;
11179 }
11180 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11181 pri_set_nsf(pri->dchans[i], pri->nsf);
11182 #ifdef PRI_GETSET_TIMERS
11183 for (x = 0; x < PRI_MAX_TIMERS; x++) {
11184 if (pritimers[x] != 0)
11185 pri_set_timer(pri->dchans[i], x, pritimers[x]);
11186 }
11187 #endif
11188 }
11189
11190 pri->pri = pri->dchans[0];
11191 pri->resetpos = -1;
11192 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11193 for (i = 0; i < NUM_DCHANS; i++) {
11194 if (!pri->dchannels[i])
11195 break;
11196 dahdi_close_pri_fd(pri, i);
11197 }
11198 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11199 return -1;
11200 }
11201 return 0;
11202 }
11203
11204 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
11205 {
11206 int which, span;
11207 char *ret = NULL;
11208
11209 if (pos != rpos)
11210 return ret;
11211
11212 for (which = span = 0; span < NUM_SPANS; span++) {
11213 if (pris[span].pri && ++which > state) {
11214 if (asprintf(&ret, "%d", span + 1) < 0) {
11215 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11216 }
11217 break;
11218 }
11219 }
11220 return ret;
11221 }
11222
11223 static char *complete_span_4(const char *line, const char *word, int pos, int state)
11224 {
11225 return complete_span_helper(line,word,pos,state,3);
11226 }
11227
11228 static char *complete_span_5(const char *line, const char *word, int pos, int state)
11229 {
11230 return complete_span_helper(line,word,pos,state,4);
11231 }
11232
11233 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
11234 {
11235 int myfd;
11236
11237 if (!strncasecmp(argv[1], "set", 3)) {
11238 if (argc < 5)
11239 return RESULT_SHOWUSAGE;
11240
11241 if (ast_strlen_zero(argv[4]))
11242 return RESULT_SHOWUSAGE;
11243
11244 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
11245 if (myfd < 0) {
11246 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
11247 return RESULT_SUCCESS;
11248 }
11249
11250 ast_mutex_lock(&pridebugfdlock);
11251
11252 if (pridebugfd >= 0)
11253 close(pridebugfd);
11254
11255 pridebugfd = myfd;
11256 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
11257
11258 ast_mutex_unlock(&pridebugfdlock);
11259
11260 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
11261 } else {
11262
11263 ast_mutex_lock(&pridebugfdlock);
11264 close(pridebugfd);
11265 pridebugfd = -1;
11266 ast_cli(fd, "PRI debug output to file disabled\n");
11267 ast_mutex_unlock(&pridebugfdlock);
11268 }
11269
11270 return RESULT_SUCCESS;
11271 }
11272
11273 #ifdef HAVE_PRI_VERSION
11274 static int handle_pri_version(int fd, int agc, char *argv[]) {
11275 ast_cli(fd, "libpri version: %s\n", pri_get_version());
11276 return RESULT_SUCCESS;
11277 }
11278 #endif
11279
11280 static int handle_pri_debug(int fd, int argc, char *argv[])
11281 {
11282 int span;
11283 int x;
11284 if (argc < 4) {
11285 return RESULT_SHOWUSAGE;
11286 }
11287 span = atoi(argv[3]);
11288 if ((span < 1) || (span > NUM_SPANS)) {
11289 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11290 return RESULT_SUCCESS;
11291 }
11292 if (!pris[span-1].pri) {
11293 ast_cli(fd, "No PRI running on span %d\n", span);
11294 return RESULT_SUCCESS;
11295 }
11296 for (x = 0; x < NUM_DCHANS; x++) {
11297 if (pris[span-1].dchans[x])
11298 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11299 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11300 PRI_DEBUG_Q921_STATE);
11301 }
11302 ast_cli(fd, "Enabled debugging on span %d\n", span);
11303 return RESULT_SUCCESS;
11304 }
11305
11306
11307
11308 static int handle_pri_no_debug(int fd, int argc, char *argv[])
11309 {
11310 int span;
11311 int x;
11312 if (argc < 5)
11313 return RESULT_SHOWUSAGE;
11314 span = atoi(argv[4]);
11315 if ((span < 1) || (span > NUM_SPANS)) {
11316 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11317 return RESULT_SUCCESS;
11318 }
11319 if (!pris[span-1].pri) {
11320 ast_cli(fd, "No PRI running on span %d\n", span);
11321 return RESULT_SUCCESS;
11322 }
11323 for (x = 0; x < NUM_DCHANS; x++) {
11324 if (pris[span-1].dchans[x])
11325 pri_set_debug(pris[span-1].dchans[x], 0);
11326 }
11327 ast_cli(fd, "Disabled debugging on span %d\n", span);
11328 return RESULT_SUCCESS;
11329 }
11330
11331 static int handle_pri_really_debug(int fd, int argc, char *argv[])
11332 {
11333 int span;
11334 int x;
11335 if (argc < 5)
11336 return RESULT_SHOWUSAGE;
11337 span = atoi(argv[4]);
11338 if ((span < 1) || (span > NUM_SPANS)) {
11339 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11340 return RESULT_SUCCESS;
11341 }
11342 if (!pris[span-1].pri) {
11343 ast_cli(fd, "No PRI running on span %d\n", span);
11344 return RESULT_SUCCESS;
11345 }
11346 for (x = 0; x < NUM_DCHANS; x++) {
11347 if (pris[span-1].dchans[x])
11348 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11349 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11350 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11351 }
11352 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11353 return RESULT_SUCCESS;
11354 }
11355
11356 static void build_status(char *s, size_t len, int status, int active)
11357 {
11358 if (!s || len < 1) {
11359 return;
11360 }
11361 s[0] = '\0';
11362 if (status & DCHAN_PROVISIONED)
11363 strncat(s, "Provisioned, ", len - strlen(s) - 1);
11364 if (!(status & DCHAN_NOTINALARM))
11365 strncat(s, "In Alarm, ", len - strlen(s) - 1);
11366 if (status & DCHAN_UP)
11367 strncat(s, "Up", len - strlen(s) - 1);
11368 else
11369 strncat(s, "Down", len - strlen(s) - 1);
11370 if (active)
11371 strncat(s, ", Active", len - strlen(s) - 1);
11372 else
11373 strncat(s, ", Standby", len - strlen(s) - 1);
11374 s[len - 1] = '\0';
11375 }
11376
11377 static int handle_pri_show_spans(int fd, int argc, char *argv[])
11378 {
11379 int span;
11380 int x;
11381 char status[256];
11382 if (argc != 3)
11383 return RESULT_SHOWUSAGE;
11384
11385 for (span = 0; span < NUM_SPANS; span++) {
11386 if (pris[span].pri) {
11387 for (x = 0; x < NUM_DCHANS; x++) {
11388 if (pris[span].dchannels[x]) {
11389 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11390 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11391 }
11392 }
11393 }
11394 }
11395 return RESULT_SUCCESS;
11396 }
11397
11398 static int handle_pri_show_span(int fd, int argc, char *argv[])
11399 {
11400 int span;
11401 int x;
11402 char status[256];
11403 if (argc < 4)
11404 return RESULT_SHOWUSAGE;
11405 span = atoi(argv[3]);
11406 if ((span < 1) || (span > NUM_SPANS)) {
11407 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11408 return RESULT_SUCCESS;
11409 }
11410 if (!pris[span-1].pri) {
11411 ast_cli(fd, "No PRI running on span %d\n", span);
11412 return RESULT_SUCCESS;
11413 }
11414 for (x = 0; x < NUM_DCHANS; x++) {
11415 if (pris[span-1].dchannels[x]) {
11416 #ifdef PRI_DUMP_INFO_STR
11417 char *info_str = NULL;
11418 #endif
11419 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11420 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11421 ast_cli(fd, "Status: %s\n", status);
11422 #ifdef PRI_DUMP_INFO_STR
11423 info_str = pri_dump_info_str(pris[span-1].pri);
11424 if (info_str) {
11425 ast_cli(fd, "%s", info_str);
11426 free(info_str);
11427 }
11428 #else
11429 pri_dump_info(pris[span-1].pri);
11430 #endif
11431 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11432 }
11433 }
11434 return RESULT_SUCCESS;
11435 }
11436
11437 static int handle_pri_show_debug(int fd, int argc, char *argv[])
11438 {
11439 int x;
11440 int span;
11441 int count=0;
11442 int debug=0;
11443
11444 for (span = 0; span < NUM_SPANS; span++) {
11445 if (pris[span].pri) {
11446 for (x = 0; x < NUM_DCHANS; x++) {
11447 debug = 0;
11448 if (pris[span].dchans[x]) {
11449 debug = pri_get_debug(pris[span].dchans[x]);
11450 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" );
11451 count++;
11452 }
11453 }
11454 }
11455
11456 }
11457 ast_mutex_lock(&pridebugfdlock);
11458 if (pridebugfd >= 0)
11459 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
11460 ast_mutex_unlock(&pridebugfdlock);
11461
11462 if (!count)
11463 ast_cli(fd, "No debug set or no PRI running\n");
11464 return RESULT_SUCCESS;
11465 }
11466
11467 static const char pri_debug_help[] =
11468 "Usage: pri debug span <span>\n"
11469 " Enables debugging on a given PRI span\n";
11470
11471 static const char pri_no_debug_help[] =
11472 "Usage: pri no debug span <span>\n"
11473 " Disables debugging on a given PRI span\n";
11474
11475 static const char pri_really_debug_help[] =
11476 "Usage: pri intensive debug span <span>\n"
11477 " Enables debugging down to the Q.921 level\n";
11478
11479 static const char pri_show_span_help[] =
11480 "Usage: pri show span <span>\n"
11481 " Displays PRI Information on a given PRI span\n";
11482
11483 static const char pri_show_spans_help[] =
11484 "Usage: pri show spans\n"
11485 " Displays PRI Information\n";
11486
11487 static struct ast_cli_entry dahdi_pri_cli[] = {
11488 { { "pri", "debug", "span", NULL },
11489 handle_pri_debug, "Enables PRI debugging on a span",
11490 pri_debug_help, complete_span_4 },
11491
11492 { { "pri", "no", "debug", "span", NULL },
11493 handle_pri_no_debug, "Disables PRI debugging on a span",
11494 pri_no_debug_help, complete_span_5 },
11495
11496 { { "pri", "intense", "debug", "span", NULL },
11497 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
11498 pri_really_debug_help, complete_span_5 },
11499
11500 { { "pri", "show", "spans", NULL },
11501 handle_pri_show_spans, "Displays PRI Information",
11502 pri_show_spans_help },
11503
11504 { { "pri", "show", "span", NULL },
11505 handle_pri_show_span, "Displays PRI Information",
11506 pri_show_span_help, complete_span_4 },
11507
11508 { { "pri", "show", "debug", NULL },
11509 handle_pri_show_debug, "Displays current PRI debug settings" },
11510
11511 { { "pri", "set", "debug", "file", NULL },
11512 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
11513
11514 { { "pri", "unset", "debug", "file", NULL },
11515 handle_pri_set_debug_file, "Ends PRI debug output to file" },
11516
11517 #ifdef HAVE_PRI_VERSION
11518 { { "pri", "show", "version", NULL },
11519 handle_pri_version, "Displays version of libpri" },
11520 #endif
11521 };
11522
11523 #endif
11524
11525 #ifdef HAVE_OPENR2
11526
11527 static int handle_mfcr2_version(int fd, int argc, char *argv[])
11528 {
11529 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11530 return RESULT_SUCCESS;
11531 }
11532
11533 static int handle_mfcr2_show_variants(int fd, int argc, char *argv[])
11534 {
11535 #define FORMAT "%4s %40s\n"
11536 int numvariants = 0;
11537 int i;
11538 const openr2_variant_entry_t *variants;
11539 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
11540 ast_cli(fd, "Failed to get list of variants.\n");
11541 return RESULT_FAILURE;
11542 }
11543 ast_cli(fd, FORMAT, "Variant Code", "Country");
11544 for (i = 0; i < numvariants; i++) {
11545 ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
11546 }
11547 return RESULT_SUCCESS;
11548 #undef FORMAT
11549 }
11550
11551 static int handle_mfcr2_show_channels(int fd, int argc, char *argv[])
11552 {
11553 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
11554 int filtertype = 0;
11555 int targetnum = 0;
11556 char channo[5];
11557 char anino[5];
11558 char dnisno[5];
11559 struct dahdi_pvt *p;
11560 openr2_context_t *r2context;
11561 openr2_variant_t r2variant;
11562 if (!((argc == 3) || (argc == 5))) {
11563 return RESULT_SHOWUSAGE;
11564 }
11565 if (argc == 5) {
11566 if (!strcasecmp(argv[3], "group")) {
11567 targetnum = atoi(argv[4]);
11568 if ((targetnum < 0) || (targetnum > 63))
11569 return RESULT_SHOWUSAGE;
11570 targetnum = 1 << targetnum;
11571 filtertype = 1;
11572 } else if (!strcasecmp(argv[3], "context")) {
11573 filtertype = 2;
11574 } else {
11575 return RESULT_SHOWUSAGE;
11576 }
11577 }
11578 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
11579 ast_mutex_lock(&iflock);
11580 p = iflist;
11581 while (p) {
11582 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11583 p = p->next;
11584 continue;
11585 }
11586 if (filtertype) {
11587 switch(filtertype) {
11588 case 1:
11589 if (p->group != targetnum) {
11590 p = p->next;
11591 continue;
11592 }
11593 break;
11594 case 2:
11595 if (strcasecmp(p->context, argv[4])) {
11596 p= p->next;
11597 continue;
11598 }
11599 break;
11600 default:
11601 ;
11602 }
11603 }
11604 r2context = openr2_chan_get_context(p->r2chan);
11605 r2variant = openr2_context_get_variant(r2context);
11606 snprintf(channo, sizeof(channo), "%d", p->channel);
11607 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
11608 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
11609 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
11610 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
11611 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
11612 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
11613 p = p->next;
11614 }
11615 ast_mutex_unlock(&iflock);
11616 return RESULT_SUCCESS;
11617 #undef FORMAT
11618 }
11619
11620 static int handle_mfcr2_set_debug(int fd, int argc, char *argv[])
11621 {
11622 struct dahdi_pvt *p = NULL;
11623 int channo = 0;
11624 char *toklevel = NULL;
11625 char *saveptr = NULL;
11626 char *logval = NULL;
11627 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
11628 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
11629 if (argc < 4) {
11630 return RESULT_SHOWUSAGE;
11631 }
11632 channo = (argc == 5) ? atoi(argv[4]) : -1;
11633 logval = ast_strdupa(argv[3]);
11634 toklevel = strtok_r(logval, ",", &saveptr);
11635 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11636 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
11637 return RESULT_FAILURE;
11638 } else if (OR2_LOG_NOTHING == tmplevel) {
11639 loglevel = tmplevel;
11640 } else {
11641 loglevel |= tmplevel;
11642 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
11643 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11644 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
11645 continue;
11646 }
11647 loglevel |= tmplevel;
11648 }
11649 }
11650 ast_mutex_lock(&iflock);
11651 p = iflist;
11652 while (p) {
11653 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11654 p = p->next;
11655 continue;
11656 }
11657 if ((channo != -1) && (p->channel != channo )) {
11658 p = p->next;
11659 continue;
11660 }
11661 openr2_chan_set_log_level(p->r2chan, loglevel);
11662 if (channo != -1) {
11663 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
11664 break;
11665 } else {
11666 p = p->next;
11667 }
11668 }
11669 if ((channo != -1) && !p) {
11670 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11671 }
11672 if (channo == -1) {
11673 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
11674 }
11675 ast_mutex_unlock(&iflock);
11676 return RESULT_SUCCESS;
11677 }
11678
11679 static int handle_mfcr2_call_files(int fd, int argc, char *argv[])
11680 {
11681 struct dahdi_pvt *p = NULL;
11682 int channo = 0;
11683 if (argc < 4) {
11684 return RESULT_SHOWUSAGE;
11685 }
11686 channo = (argc == 5) ? atoi(argv[4]) : -1;
11687 ast_mutex_lock(&iflock);
11688 p = iflist;
11689 while (p) {
11690 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11691 p = p->next;
11692 continue;
11693 }
11694 if ((channo != -1) && (p->channel != channo )) {
11695 p = p->next;
11696 continue;
11697 }
11698 if (ast_true(argv[3])) {
11699 openr2_chan_enable_call_files(p->r2chan);
11700 } else {
11701 openr2_chan_disable_call_files(p->r2chan);
11702 }
11703 if (channo != -1) {
11704 if (ast_true(argv[3])) {
11705 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
11706 } else {
11707 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
11708 }
11709 break;
11710 } else {
11711 p = p->next;
11712 }
11713 }
11714 if ((channo != -1) && !p) {
11715 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11716 }
11717 if (channo == -1) {
11718 if (ast_true(argv[3])) {
11719 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
11720 } else {
11721 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
11722 }
11723 }
11724 ast_mutex_unlock(&iflock);
11725 return RESULT_SUCCESS;
11726 }
11727
11728 static int handle_mfcr2_set_idle(int fd, int argc, char *argv[])
11729 {
11730 struct dahdi_pvt *p = NULL;
11731 int channo = 0;
11732 channo = (argc == 4) ? atoi(argv[3]) : -1;
11733 ast_mutex_lock(&iflock);
11734 p = iflist;
11735 while (p) {
11736 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11737 p = p->next;
11738 continue;
11739 }
11740 if ((channo != -1) && (p->channel != channo )) {
11741 p = p->next;
11742 continue;
11743 }
11744 if (!openr2_chan_set_idle(p->r2chan)) {
11745 ast_mutex_lock(&p->lock);
11746 p->mfcr2call = 0;
11747 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
11748 ast_mutex_unlock(&p->lock);
11749 }
11750 if (channo != -1) {
11751 break;
11752 } else {
11753 p = p->next;
11754 }
11755 }
11756 if ((channo != -1) && !p) {
11757 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11758 }
11759 ast_mutex_unlock(&iflock);
11760 return RESULT_SUCCESS;
11761 }
11762
11763 static int handle_mfcr2_set_blocked(int fd, int argc, char *argv[])
11764 {
11765 struct dahdi_pvt *p = NULL;
11766 int channo = 0;
11767 channo = (argc == 4) ? atoi(argv[3]) : -1;
11768 ast_mutex_lock(&iflock);
11769 p = iflist;
11770 while (p) {
11771 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11772 p = p->next;
11773 continue;
11774 }
11775 if ((channo != -1) && (p->channel != channo )) {
11776 p = p->next;
11777 continue;
11778 }
11779 if (!openr2_chan_set_blocked(p->r2chan)) {
11780 ast_mutex_lock(&p->lock);
11781 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
11782 ast_mutex_unlock(&p->lock);
11783 } else {
11784 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
11785 }
11786 if (channo != -1) {
11787 break;
11788 } else {
11789 p = p->next;
11790 }
11791 }
11792 if ((channo != -1) && !p) {
11793 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11794 }
11795 ast_mutex_unlock(&iflock);
11796 return RESULT_SUCCESS;
11797 }
11798
11799 static const char dahdi_r2_version_help[] =
11800 "Usage: mfcr2 show version\n"
11801 " Shows the version of the OpenR2 library being used.\n";
11802 static const char dahdi_r2_variants_help[] =
11803 "Usage: mfcr2 show variants\n"
11804 " Show supported MFC/R2 variants.\n";
11805 static const char dahdi_r2_showchannels_help[] =
11806 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
11807 " Shows the zap channels configured with MFC/R2 signaling.\n";
11808 static const char dahdi_r2_setdebug_help[] =
11809 "Usage: mfcr2 set debug <loglevel> <channel>\n"
11810 " Set a new logging level for the specified channel.\n"
11811 " If no channel is specified the logging level will be applied to all channels.\n";
11812 static const char dahdi_r2_callfiles_help[] =
11813 "Usage: mfcr2 call files [on|off] <channel>\n"
11814 " Enable call files creation on the specified channel.\n"
11815 " If no channel is specified call files creation policy will be applied to all channels.\n";
11816 static const char dahdi_r2_setidle_help[] =
11817 "Usage: mfcr2 set idle <channel>\n"
11818 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11819 " Force the given channel into IDLE state.\n"
11820 " If no channel is specified, all channels will be set to IDLE.\n";
11821 static const char dahdi_r2_setblocked_help[] =
11822 "Usage: mfcr2 set blocked <channel>\n"
11823 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11824 " Force the given channel into BLOCKED state.\n"
11825 " If no channel is specified, all channels will be set to BLOCKED.\n";
11826
11827 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
11828 { { "mfcr2", "show", "version", NULL },
11829 handle_mfcr2_version, "Show OpenR2 library version",
11830 dahdi_r2_version_help },
11831
11832 { { "mfcr2", "show", "variants", NULL },
11833 handle_mfcr2_show_variants, "Show supported MFC/R2 variants",
11834 dahdi_r2_variants_help },
11835
11836 { { "mfcr2", "show", "channels", NULL },
11837 handle_mfcr2_show_channels, "Show MFC/R2 channels",
11838 dahdi_r2_showchannels_help },
11839
11840 { { "mfcr2", "set", "debug", NULL },
11841 handle_mfcr2_set_debug, "Set MFC/R2 channel logging level",
11842 dahdi_r2_setdebug_help },
11843
11844 { { "mfcr2", "call", "files", NULL },
11845 handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files",
11846 dahdi_r2_callfiles_help },
11847
11848 { { "mfcr2", "set", "idle", NULL },
11849 handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE",
11850 dahdi_r2_setidle_help },
11851
11852 { { "mfcr2", "set", "blocked", NULL },
11853 handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED",
11854 dahdi_r2_setblocked_help }
11855
11856 };
11857
11858 #endif
11859
11860 static int dahdi_destroy_channel(int fd, int argc, char **argv)
11861 {
11862 int channel;
11863
11864 if (argc != 4)
11865 return RESULT_SHOWUSAGE;
11866
11867 channel = atoi(argv[3]);
11868
11869 return dahdi_destroy_channel_bynum(channel);
11870 }
11871
11872 static void dahdi_softhangup_all(void)
11873 {
11874 struct dahdi_pvt *p;
11875 retry:
11876 ast_mutex_lock(&iflock);
11877 for (p = iflist; p; p = p->next) {
11878 ast_mutex_lock(&p->lock);
11879 if (p->owner && !p->restartpending) {
11880 if (ast_channel_trylock(p->owner)) {
11881 if (option_debug > 2)
11882 ast_verbose("Avoiding deadlock\n");
11883
11884 ast_mutex_unlock(&p->lock);
11885 ast_mutex_unlock(&iflock);
11886 goto retry;
11887 }
11888 if (option_debug > 2)
11889 ast_verbose("Softhanging up on %s\n", p->owner->name);
11890 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11891 p->restartpending = 1;
11892 num_restart_pending++;
11893 ast_channel_unlock(p->owner);
11894 }
11895 ast_mutex_unlock(&p->lock);
11896 }
11897 ast_mutex_unlock(&iflock);
11898 }
11899
11900 static int setup_dahdi(int reload);
11901 static int dahdi_restart(void)
11902 {
11903 #ifdef HAVE_OPENR2
11904 int r;
11905 #endif
11906 #if defined(HAVE_PRI)
11907 int i, j;
11908 #endif
11909 int cancel_code;
11910 struct dahdi_pvt *p;
11911
11912 ast_mutex_lock(&restart_lock);
11913
11914 if (option_verbose)
11915 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
11916 dahdi_softhangup_all();
11917 if (option_verbose > 3)
11918 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
11919
11920 #ifdef HAVE_OPENR2
11921 for (r = 0; r < NUM_SPANS; r++) {
11922 if (r2links[r].master != AST_PTHREADT_NULL) {
11923 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
11924 pthread_cancel(r2links[r].master);
11925 pthread_join(r2links[r].master, NULL);
11926 openr2_context_delete(r2links[r].protocol_context);
11927 }
11928 }
11929 init_mfcr2_globals();
11930 #endif
11931
11932 #if defined(HAVE_PRI)
11933 for (i = 0; i < NUM_SPANS; i++) {
11934 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
11935 cancel_code = pthread_cancel(pris[i].master);
11936 pthread_kill(pris[i].master, SIGURG);
11937 if (option_debug > 3)
11938 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
11939 pthread_join(pris[i].master, NULL);
11940 if (option_debug > 3)
11941 ast_verbose("Joined thread of span %d\n", i);
11942 }
11943 }
11944 #endif
11945
11946 ast_mutex_lock(&monlock);
11947 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11948 cancel_code = pthread_cancel(monitor_thread);
11949 pthread_kill(monitor_thread, SIGURG);
11950 if (option_debug > 3)
11951 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
11952 pthread_join(monitor_thread, NULL);
11953 if (option_debug > 3)
11954 ast_verbose("Joined monitor thread\n");
11955 }
11956 monitor_thread = AST_PTHREADT_NULL;
11957
11958 ast_mutex_lock(&ss_thread_lock);
11959 while (ss_thread_count > 0) {
11960 int x = DAHDI_FLASH;
11961 if (option_debug > 2)
11962 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
11963
11964 for (p = iflist; p; p = p->next) {
11965 if (p->owner)
11966 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11967 }
11968 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
11969 }
11970
11971
11972 dahdi_softhangup_all();
11973 if (option_verbose > 3)
11974 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
11975 destroy_all_channels();
11976 if (option_debug)
11977 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
11978
11979 ast_mutex_unlock(&monlock);
11980
11981 #ifdef HAVE_PRI
11982 for (i = 0; i < NUM_SPANS; i++) {
11983 for (j = 0; j < NUM_DCHANS; j++)
11984 dahdi_close_pri_fd(&(pris[i]), j);
11985 }
11986
11987 memset(pris, 0, sizeof(pris));
11988 for (i = 0; i < NUM_SPANS; i++) {
11989 ast_mutex_init(&pris[i].lock);
11990 pris[i].offset = -1;
11991 pris[i].master = AST_PTHREADT_NULL;
11992 for (j = 0; j < NUM_DCHANS; j++)
11993 pris[i].fds[j] = -1;
11994 }
11995 pri_set_error(dahdi_pri_error);
11996 pri_set_message(dahdi_pri_message);
11997 #endif
11998
11999 if (setup_dahdi(2) != 0) {
12000 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12001 ast_mutex_unlock(&ss_thread_lock);
12002 return 1;
12003 }
12004 ast_mutex_unlock(&ss_thread_lock);
12005 ast_mutex_unlock(&restart_lock);
12006 return 0;
12007 }
12008
12009 static int dahdi_restart_cmd(int fd, int argc, char **argv)
12010 {
12011 if (argc != 2) {
12012 return RESULT_SHOWUSAGE;
12013 }
12014
12015 if (dahdi_restart() != 0)
12016 return RESULT_FAILURE;
12017 return RESULT_SUCCESS;
12018 }
12019
12020 static int dahdi_show_channels(int fd, int argc, char **argv)
12021 {
12022 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12023 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12024 struct dahdi_pvt *tmp = NULL;
12025 char tmps[20] = "";
12026 ast_mutex_t *lock;
12027 struct dahdi_pvt *start;
12028 #ifdef HAVE_PRI
12029 int trunkgroup;
12030 struct dahdi_pri *pri = NULL;
12031 int x;
12032 #endif
12033
12034 lock = &iflock;
12035 start = iflist;
12036
12037 #ifdef HAVE_PRI
12038 if (argc == 4) {
12039 if ((trunkgroup = atoi(argv[3])) < 1)
12040 return RESULT_SHOWUSAGE;
12041 for (x = 0; x < NUM_SPANS; x++) {
12042 if (pris[x].trunkgroup == trunkgroup) {
12043 pri = pris + x;
12044 break;
12045 }
12046 }
12047 if (pri) {
12048 start = pri->crvs;
12049 lock = &pri->lock;
12050 } else {
12051 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12052 return RESULT_FAILURE;
12053 }
12054 } else
12055 #endif
12056 if (argc != 3)
12057 return RESULT_SHOWUSAGE;
12058
12059 ast_mutex_lock(lock);
12060 #ifdef HAVE_PRI
12061 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
12062 #else
12063 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
12064 #endif
12065
12066 tmp = start;
12067 while (tmp) {
12068 if (tmp->channel > 0) {
12069 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12070 } else
12071 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12072 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
12073 tmp = tmp->next;
12074 }
12075 ast_mutex_unlock(lock);
12076 return RESULT_SUCCESS;
12077 #undef FORMAT
12078 #undef FORMAT2
12079 }
12080
12081 static int dahdi_show_channel(int fd, int argc, char **argv)
12082 {
12083 int channel;
12084 struct dahdi_pvt *tmp = NULL;
12085 struct dahdi_confinfo ci;
12086 struct dahdi_params ps;
12087 int x;
12088 ast_mutex_t *lock;
12089 struct dahdi_pvt *start;
12090 #ifdef HAVE_PRI
12091 char *c;
12092 int trunkgroup;
12093 struct dahdi_pri *pri=NULL;
12094 #endif
12095
12096 lock = &iflock;
12097 start = iflist;
12098
12099 if (argc != 4)
12100 return RESULT_SHOWUSAGE;
12101 #ifdef HAVE_PRI
12102 if ((c = strchr(argv[3], ':'))) {
12103 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12104 return RESULT_SHOWUSAGE;
12105 if ((trunkgroup < 1) || (channel < 1))
12106 return RESULT_SHOWUSAGE;
12107 for (x = 0; x < NUM_SPANS; x++) {
12108 if (pris[x].trunkgroup == trunkgroup) {
12109 pri = pris + x;
12110 break;
12111 }
12112 }
12113 if (pri) {
12114 start = pri->crvs;
12115 lock = &pri->lock;
12116 } else {
12117 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12118 return RESULT_FAILURE;
12119 }
12120 } else
12121 #endif
12122 channel = atoi(argv[3]);
12123
12124 ast_mutex_lock(lock);
12125 tmp = start;
12126 while (tmp) {
12127 if (tmp->channel == channel) {
12128 #ifdef HAVE_PRI
12129 if (pri)
12130 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12131 else
12132 #endif
12133 ast_cli(fd, "Channel: %d\n", tmp->channel);
12134 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12135 ast_cli(fd, "Span: %d\n", tmp->span);
12136 ast_cli(fd, "Extension: %s\n", tmp->exten);
12137 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12138 ast_cli(fd, "Context: %s\n", tmp->context);
12139 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
12140 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
12141 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
12142 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
12143 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
12144 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12145 ast_cli(fd, "Radio: %d\n", tmp->radio);
12146 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12147 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)" : "");
12148 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)" : "");
12149 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)" : "");
12150 ast_cli(fd, "Confno: %d\n", tmp->confno);
12151 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
12152 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
12153 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12154 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12155 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12156 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12157 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12158 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12159 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
12160 if (tmp->master)
12161 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
12162 for (x = 0; x < MAX_SLAVES; x++) {
12163 if (tmp->slaves[x])
12164 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12165 }
12166 #ifdef HAVE_OPENR2
12167 if (tmp->mfcr2) {
12168 char calldir[OR2_MAX_PATH];
12169 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
12170 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
12171 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
12172 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
12173 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
12174 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
12175 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
12176 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
12177 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
12178 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
12179 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
12180 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
12181 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12182 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
12183 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
12184 #endif
12185 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
12186 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
12187 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
12188 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
12189 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
12190 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
12191 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
12192 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
12193 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
12194 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
12195 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
12196 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
12197 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
12198 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
12199 }
12200 #endif
12201 #ifdef HAVE_PRI
12202 if (tmp->pri) {
12203 ast_cli(fd, "PRI Flags: ");
12204 if (tmp->resetting)
12205 ast_cli(fd, "Resetting ");
12206 if (tmp->call)
12207 ast_cli(fd, "Call ");
12208 if (tmp->bearer)
12209 ast_cli(fd, "Bearer ");
12210 ast_cli(fd, "\n");
12211 if (tmp->logicalspan)
12212 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12213 else
12214 ast_cli(fd, "PRI Logical Span: Implicit\n");
12215 }
12216
12217 #endif
12218 memset(&ci, 0, sizeof(ci));
12219 ps.channo = tmp->channel;
12220 if (tmp->subs[SUB_REAL].dfd > -1) {
12221 memset(&ci, 0, sizeof(ci));
12222 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12223 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12224 }
12225 #ifdef DAHDI_GETCONFMUTE
12226 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12227 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12228 }
12229 #endif
12230 memset(&ps, 0, sizeof(ps));
12231 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12232 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12233 } else {
12234 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12235 }
12236 }
12237 if (ISTRUNK(tmp)) {
12238 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
12239 if (!ast_strlen_zero(progzone))
12240 ast_cli(fd, "Progress Zone: %s\n", progzone);
12241 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
12242 if(tmp->busydetect) {
12243 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
12244 if(tmp->busytonelength > 0) {
12245 ast_cli(fd, "Busy Pattern:\n");
12246 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12247 if (tmp->busyquietlength > 0)
12248 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12249 else
12250 ast_cli(fd, " -- Detect Tone Only\n");
12251 if(tmp->busyfuzziness > 0)
12252 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12253 }
12254 }
12255 }
12256 ast_mutex_unlock(lock);
12257 return RESULT_SUCCESS;
12258 }
12259 tmp = tmp->next;
12260 }
12261
12262 ast_cli(fd, "Unable to find given channel %d\n", channel);
12263 ast_mutex_unlock(lock);
12264 return RESULT_FAILURE;
12265 }
12266
12267 static char dahdi_show_cadences_usage[] =
12268 "Usage: dahdi show cadences\n"
12269 " Shows all cadences currently defined\n";
12270
12271 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
12272 {
12273 int i, j;
12274 for (i = 0; i < num_cadence; i++) {
12275 char output[1024];
12276 char tmp[16], tmp2[64];
12277 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12278 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12279
12280 for (j = 0; j < 16; j++) {
12281 if (cadences[i].ringcadence[j] == 0)
12282 break;
12283 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12284 if (cidrings[i] * 2 - 1 == j)
12285 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12286 else
12287 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12288 if (j != 0)
12289 strncat(output, ",", sizeof(output) - strlen(output) - 1);
12290 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12291 }
12292 ast_cli(fd,"%s\n",output);
12293 }
12294 return 0;
12295 }
12296
12297
12298 static int dahdi_show_status(int fd, int argc, char *argv[]) {
12299 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12300 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12301
12302 int span;
12303 int res;
12304 char alarms[50];
12305
12306 int ctl;
12307 struct dahdi_spaninfo s;
12308
12309 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
12310 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
12311 ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
12312 return RESULT_FAILURE;
12313 }
12314 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
12315
12316 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12317 s.spanno = span;
12318 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12319 if (res) {
12320 continue;
12321 }
12322 alarms[0] = '\0';
12323 if (s.alarms > 0) {
12324 if (s.alarms & DAHDI_ALARM_BLUE)
12325 strcat(alarms, "BLU/");
12326 if (s.alarms & DAHDI_ALARM_YELLOW)
12327 strcat(alarms, "YEL/");
12328 if (s.alarms & DAHDI_ALARM_RED)
12329 strcat(alarms, "RED/");
12330 if (s.alarms & DAHDI_ALARM_LOOPBACK)
12331 strcat(alarms, "LB/");
12332 if (s.alarms & DAHDI_ALARM_RECOVER)
12333 strcat(alarms, "REC/");
12334 if (s.alarms & DAHDI_ALARM_NOTOPEN)
12335 strcat(alarms, "NOP/");
12336 if (!strlen(alarms))
12337 strcat(alarms, "UUU/");
12338 if (strlen(alarms)) {
12339
12340 alarms[strlen(alarms) - 1] = '\0';
12341 }
12342 } else {
12343 if (s.numchans)
12344 strcpy(alarms, "OK");
12345 else
12346 strcpy(alarms, "UNCONFIGURED");
12347 }
12348
12349 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12350 }
12351 close(ctl);
12352
12353 return RESULT_SUCCESS;
12354 #undef FORMAT
12355 #undef FORMAT2
12356 }
12357
12358 static char show_channels_usage[] =
12359 "Usage: dahdi show channels\n"
12360 " Shows a list of available channels\n";
12361
12362 static char show_channel_usage[] =
12363 "Usage: dahdi show channel <chan num>\n"
12364 " Detailed information about a given channel\n";
12365
12366 static char dahdi_show_status_usage[] =
12367 "Usage: dahdi show status\n"
12368 " Shows a list of DAHDI cards with status\n";
12369
12370 static char destroy_channel_usage[] =
12371 "Usage: dahdi destroy channel <chan num>\n"
12372 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12373
12374 static char dahdi_restart_usage[] =
12375 "Usage: dahdi restart\n"
12376 " Restarts the DAHDI channels: destroys them all and then\n"
12377 " re-reads them from chan_dahdi.conf.\n"
12378 " Note that this will STOP any running CALL on DAHDI channels.\n"
12379 "";
12380
12381 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
12382 { "zap", "show", "cadences", NULL },
12383 handle_dahdi_show_cadences, NULL,
12384 NULL };
12385
12386 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
12387 { "zap", "show", "channels", NULL },
12388 dahdi_show_channels, NULL,
12389 NULL };
12390
12391 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
12392 { "zap", "show", "channel", NULL },
12393 dahdi_show_channel, NULL,
12394 NULL };
12395
12396 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
12397 { "zap", "destroy", "channel", NULL },
12398 dahdi_destroy_channel, NULL,
12399 NULL };
12400
12401 static struct ast_cli_entry cli_zap_restart_deprecated = {
12402 { "zap", "restart", NULL },
12403 dahdi_restart_cmd, NULL,
12404 NULL };
12405
12406 static struct ast_cli_entry cli_zap_show_status_deprecated = {
12407 { "zap", "show", "status", NULL },
12408 dahdi_show_status, NULL,
12409 NULL };
12410
12411 static struct ast_cli_entry dahdi_cli[] = {
12412 { { "dahdi", "show", "cadences", NULL },
12413 handle_dahdi_show_cadences, "List cadences",
12414 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
12415
12416 { { "dahdi", "show", "channels", NULL},
12417 dahdi_show_channels, "Show active DAHDI channels",
12418 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
12419
12420 { { "dahdi", "show", "channel", NULL},
12421 dahdi_show_channel, "Show information on a channel",
12422 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
12423
12424 { { "dahdi", "destroy", "channel", NULL},
12425 dahdi_destroy_channel, "Destroy a channel",
12426 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
12427
12428 { { "dahdi", "restart", NULL},
12429 dahdi_restart_cmd, "Fully restart DAHDI channels",
12430 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
12431
12432 { { "dahdi", "show", "status", NULL},
12433 dahdi_show_status, "Show all DAHDI cards status",
12434 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
12435 };
12436
12437 #define TRANSFER 0
12438 #define HANGUP 1
12439
12440 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
12441 {
12442 if (p) {
12443 switch (mode) {
12444 case TRANSFER:
12445 p->fake_event = DAHDI_EVENT_WINKFLASH;
12446 break;
12447 case HANGUP:
12448 p->fake_event = DAHDI_EVENT_ONHOOK;
12449 break;
12450 default:
12451 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
12452 }
12453 }
12454 return 0;
12455 }
12456 static struct dahdi_pvt *find_channel(int channel)
12457 {
12458 struct dahdi_pvt *p = iflist;
12459 while (p) {
12460 if (p->channel == channel) {
12461 break;
12462 }
12463 p = p->next;
12464 }
12465 return p;
12466 }
12467
12468 #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)
12469 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
12470
12471 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
12472 {
12473 struct dahdi_pvt *p = NULL;
12474 const char *channel = local_astman_header(m, "Channel", zap_mode);
12475
12476 if (ast_strlen_zero(channel)) {
12477 astman_send_error(s, m, "No channel specified");
12478 return 0;
12479 }
12480 if (!(p = find_channel(atoi(channel)))) {
12481 astman_send_error(s, m, "No such channel");
12482 return 0;
12483 }
12484 p->dnd = dnd;
12485 local_astman_ack(s, m, "DND", zap_mode);
12486
12487 return 0;
12488 }
12489
12490 static int zap_action_dndon(struct mansession *s, const struct message *m)
12491 {
12492 return __action_dnd(s, m, 1, 1);
12493 }
12494
12495 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
12496 {
12497 return __action_dnd(s, m, 0, 1);
12498 }
12499
12500 static int zap_action_dndoff(struct mansession *s, const struct message *m)
12501 {
12502 return __action_dnd(s, m, 1, 0);
12503 }
12504
12505 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
12506 {
12507 return __action_dnd(s, m, 0, 0);
12508 }
12509
12510 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
12511 {
12512 struct dahdi_pvt *p = NULL;
12513 const char *channel = local_astman_header(m, "Channel", zap_mode);
12514
12515 if (ast_strlen_zero(channel)) {
12516 astman_send_error(s, m, "No channel specified");
12517 return 0;
12518 }
12519 if (!(p = find_channel(atoi(channel)))) {
12520 astman_send_error(s, m, "No such channel");
12521 return 0;
12522 }
12523 dahdi_fake_event(p,TRANSFER);
12524 local_astman_ack(s, m, "Transfer", zap_mode);
12525
12526 return 0;
12527 }
12528
12529 static int zap_action_transfer(struct mansession *s, const struct message *m)
12530 {
12531 return __action_transfer(s, m, 1);
12532 }
12533
12534 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
12535 {
12536 return __action_transfer(s, m, 0);
12537 }
12538
12539 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
12540 {
12541 struct dahdi_pvt *p = NULL;
12542 const char *channel = local_astman_header(m, "Channel", zap_mode);
12543
12544 if (ast_strlen_zero(channel)) {
12545 astman_send_error(s, m, "No channel specified");
12546 return 0;
12547 }
12548 if (!(p = find_channel(atoi(channel)))) {
12549 astman_send_error(s, m, "No such channel");
12550 return 0;
12551 }
12552 dahdi_fake_event(p, HANGUP);
12553 local_astman_ack(s, m, "Hangup", zap_mode);
12554 return 0;
12555 }
12556
12557 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
12558 {
12559 return __action_transferhangup(s, m, 1);
12560 }
12561
12562 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
12563 {
12564 return __action_transferhangup(s, m, 0);
12565 }
12566
12567 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
12568 {
12569 struct dahdi_pvt *p = NULL;
12570 const char *channel = local_astman_header(m, "Channel", zap_mode);
12571 const char *number = astman_get_header(m, "Number");
12572 int i;
12573
12574 if (ast_strlen_zero(channel)) {
12575 astman_send_error(s, m, "No channel specified");
12576 return 0;
12577 }
12578 if (ast_strlen_zero(number)) {
12579 astman_send_error(s, m, "No number specified");
12580 return 0;
12581 }
12582 if (!(p = find_channel(atoi(channel)))) {
12583 astman_send_error(s, m, "No such channel");
12584 return 0;
12585 }
12586 if (!p->owner) {
12587 astman_send_error(s, m, "Channel does not have an owner");
12588 return 0;
12589 }
12590 for (i = 0; i < strlen(number); i++) {
12591 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12592
12593 dahdi_queue_frame(p, &f, NULL);
12594 }
12595 local_astman_ack(s, m, "DialOffHook", zap_mode);
12596
12597 return 0;
12598 }
12599
12600 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
12601 {
12602 return __action_dialoffhook(s, m, 1);
12603 }
12604
12605 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
12606 {
12607 return __action_dialoffhook(s, m, 0);
12608 }
12609
12610 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
12611 {
12612 struct dahdi_pvt *tmp = NULL;
12613 const char *id = astman_get_header(m, "ActionID");
12614 char idText[256] = "";
12615
12616 local_astman_ack(s, m, " channel status will follow", zap_mode);
12617 if (!ast_strlen_zero(id))
12618 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12619
12620 ast_mutex_lock(&iflock);
12621
12622 tmp = iflist;
12623 while (tmp) {
12624 if (tmp->channel > 0) {
12625 int alarm = get_alarms(tmp);
12626 astman_append(s,
12627 "Event: %sShowChannels\r\n"
12628 "Channel: %d\r\n"
12629 "Signalling: %s\r\n"
12630 "Context: %s\r\n"
12631 "DND: %s\r\n"
12632 "Alarm: %s\r\n"
12633 "%s"
12634 "\r\n",
12635 dahdi_chan_name,
12636 tmp->channel, sig2str(tmp->sig), tmp->context,
12637 tmp->dnd ? "Enabled" : "Disabled",
12638 alarm2str(alarm), idText);
12639 }
12640
12641 tmp = tmp->next;
12642 }
12643
12644 ast_mutex_unlock(&iflock);
12645
12646 astman_append(s,
12647 "Event: %sShowChannelsComplete\r\n"
12648 "%s"
12649 "\r\n",
12650 dahdi_chan_name,
12651 idText);
12652 return 0;
12653 }
12654
12655 static int zap_action_showchannels(struct mansession *s, const struct message *m)
12656 {
12657 return __action_showchannels(s, m, 1);
12658 }
12659
12660 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
12661 {
12662 return __action_showchannels(s, m, 0);
12663 }
12664
12665 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
12666 {
12667 if (dahdi_restart() != 0) {
12668 if (zap_mode) {
12669 astman_send_error(s, m, "Failed to restart Zap");
12670 } else {
12671 astman_send_error(s, m, "Failed to restart DAHDI");
12672 }
12673 return 1;
12674 }
12675 local_astman_ack(s, m, "Restart: Success", zap_mode);
12676 return 0;
12677 }
12678
12679 static int zap_action_restart(struct mansession *s, const struct message *m)
12680 {
12681 return __action_restart(s, m, 1);
12682 }
12683
12684 static int dahdi_action_restart(struct mansession *s, const struct message *m)
12685 {
12686 return __action_restart(s, m, 0);
12687 }
12688
12689 #define local_astman_unregister(a) do { \
12690 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12691 ast_manager_unregister("DAHDI" a); \
12692 } \
12693 ast_manager_unregister("Zap" a); \
12694 } while (0)
12695
12696 static int __unload_module(void)
12697 {
12698 struct dahdi_pvt *p;
12699 #ifdef HAVE_OPENR2
12700 int r;
12701 #endif
12702 #ifdef HAVE_PRI
12703 int i, j;
12704 for (i = 0; i < NUM_SPANS; i++) {
12705 if (pris[i].master != AST_PTHREADT_NULL)
12706 pthread_cancel(pris[i].master);
12707 }
12708 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12709
12710 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12711 ast_unregister_application(dahdi_send_keypad_facility_app);
12712 }
12713 ast_unregister_application(zap_send_keypad_facility_app);
12714 #endif
12715 #ifdef HAVE_OPENR2
12716 for (r = 0; r < NUM_SPANS; r++) {
12717 if (r2links[r].master != AST_PTHREADT_NULL) {
12718 pthread_cancel(r2links[r].master);
12719 pthread_join(r2links[r].master, NULL);
12720 }
12721 }
12722 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
12723 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12724 ast_unregister_application(dahdi_accept_r2_call_app);
12725 }
12726 ast_unregister_application(zap_accept_r2_call_app);
12727 #endif
12728 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12729 local_astman_unregister("DialOffHook");
12730 local_astman_unregister("Hangup");
12731 local_astman_unregister("Transfer");
12732 local_astman_unregister("DNDoff");
12733 local_astman_unregister("DNDon");
12734 local_astman_unregister("ShowChannels");
12735 local_astman_unregister("Restart");
12736 ast_channel_unregister(chan_tech);
12737 ast_mutex_lock(&iflock);
12738
12739 p = iflist;
12740 while (p) {
12741 if (p->owner)
12742 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12743 p = p->next;
12744 }
12745 ast_mutex_unlock(&iflock);
12746 ast_mutex_lock(&monlock);
12747 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12748 pthread_cancel(monitor_thread);
12749 pthread_kill(monitor_thread, SIGURG);
12750 pthread_join(monitor_thread, NULL);
12751 }
12752 monitor_thread = AST_PTHREADT_STOP;
12753 ast_mutex_unlock(&monlock);
12754
12755 destroy_all_channels();
12756 #ifdef HAVE_PRI
12757 for (i = 0; i < NUM_SPANS; i++) {
12758 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12759 pthread_join(pris[i].master, NULL);
12760 for (j = 0; j < NUM_DCHANS; j++) {
12761 dahdi_close_pri_fd(&(pris[i]), j);
12762 }
12763 }
12764 #endif
12765 #ifdef HAVE_OPENR2
12766 for (r = 0; r < NUM_SPANS; r++) {
12767 if (r2links[r].protocol_context) {
12768 openr2_context_delete(r2links[r].protocol_context);
12769 }
12770 }
12771 #endif
12772 ast_cond_destroy(&ss_thread_complete);
12773 return 0;
12774 }
12775
12776 static int unload_module(void)
12777 {
12778 #ifdef HAVE_PRI
12779 int y;
12780 for (y = 0; y < NUM_SPANS; y++)
12781 ast_mutex_destroy(&pris[y].lock);
12782 #endif
12783 return __unload_module();
12784 }
12785
12786 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
12787 {
12788 char *c, *chan;
12789 int x, start, finish;
12790 struct dahdi_pvt *tmp;
12791 #ifdef HAVE_PRI
12792 struct dahdi_pri *pri;
12793 int trunkgroup, y;
12794 #endif
12795
12796 if ((reload == 0) && (conf->chan.sig < 0)) {
12797 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12798 return -1;
12799 }
12800
12801 c = ast_strdupa(value);
12802
12803 #ifdef HAVE_PRI
12804 pri = NULL;
12805 if (iscrv) {
12806 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
12807 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12808 return -1;
12809 }
12810 if (trunkgroup < 1) {
12811 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12812 return -1;
12813 }
12814 c += y;
12815 for (y = 0; y < NUM_SPANS; y++) {
12816 if (pris[y].trunkgroup == trunkgroup) {
12817 pri = pris + y;
12818 break;
12819 }
12820 }
12821 if (!pri) {
12822 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12823 return -1;
12824 }
12825 }
12826 #endif
12827
12828 while ((chan = strsep(&c, ","))) {
12829 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
12830
12831 } else if (sscanf(chan, "%30d", &start)) {
12832
12833 finish = start;
12834 } else if (!strcasecmp(chan, "pseudo")) {
12835 finish = start = CHAN_PSEUDO;
12836 if (found_pseudo)
12837 *found_pseudo = 1;
12838 } else {
12839 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12840 return -1;
12841 }
12842 if (finish < start) {
12843 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12844 x = finish;
12845 finish = start;
12846 start = x;
12847 }
12848
12849 for (x = start; x <= finish; x++) {
12850 #ifdef HAVE_PRI
12851 tmp = mkintf(x, conf, pri, reload);
12852 #else
12853 tmp = mkintf(x, conf, NULL, reload);
12854 #endif
12855
12856 if (tmp) {
12857 if (option_verbose > 2) {
12858 #ifdef HAVE_PRI
12859 if (pri)
12860 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12861 else
12862 #endif
12863 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12864 }
12865 } else {
12866 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12867 (reload == 1) ? "reconfigure" : "register", value);
12868 return -1;
12869 }
12870 }
12871 #ifdef HAVE_OPENR2
12872 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
12873 mfcr2_cur_context_index++;
12874 }
12875 #endif
12876 }
12877
12878 return 0;
12879 }
12880
12881
12882
12883 #define MAX_CHANLIST_LEN 80
12884 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
12885 {
12886 struct dahdi_pvt *tmp;
12887 int y;
12888 int found_pseudo = 0;
12889 char dahdichan[MAX_CHANLIST_LEN] = {};
12890
12891 for (; v; v = v->next) {
12892 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
12893 continue;
12894
12895
12896 if (!strcasecmp(v->name, "channel")
12897 #ifdef HAVE_PRI
12898 || !strcasecmp(v->name, "crv")
12899 #endif
12900 ) {
12901 int iscrv;
12902 if (skipchannels)
12903 continue;
12904 iscrv = !strcasecmp(v->name, "crv");
12905 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
12906 return -1;
12907 } else if (!strcasecmp(v->name, "buffers")) {
12908 int res;
12909 char policy[21] = "";
12910
12911 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
12912 if (res != 2) {
12913 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
12914 confp->chan.buf_no = numbufs;
12915 continue;
12916 }
12917 if (confp->chan.buf_no < 0)
12918 confp->chan.buf_no = numbufs;
12919 if (!strcasecmp(policy, "full")) {
12920 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
12921 } else if (!strcasecmp(policy, "immediate")) {
12922 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
12923 } else {
12924 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
12925 }
12926 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
12927 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
12928 if (v->name[0] == 'z' || v->name[0] == 'Z') {
12929 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
12930 }
12931 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
12932 if (ast_true(v->value))
12933 confp->chan.usedistinctiveringdetection = 1;
12934 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
12935 if (ast_true(v->value))
12936 distinctiveringaftercid = 1;
12937 } else if (!strcasecmp(v->name, "dring1context")) {
12938 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
12939 } else if (!strcasecmp(v->name, "dring2context")) {
12940 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
12941 } else if (!strcasecmp(v->name, "dring3context")) {
12942 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
12943 } else if (!strcasecmp(v->name, "dring1")) {
12944 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
12945 } else if (!strcasecmp(v->name, "dring2")) {
12946 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
12947 } else if (!strcasecmp(v->name, "dring3")) {
12948 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
12949 } else if (!strcasecmp(v->name, "usecallerid")) {
12950 confp->chan.use_callerid = ast_true(v->value);
12951 } else if (!strcasecmp(v->name, "cidsignalling")) {
12952 if (!strcasecmp(v->value, "bell"))
12953 confp->chan.cid_signalling = CID_SIG_BELL;
12954 else if (!strcasecmp(v->value, "v23"))
12955 confp->chan.cid_signalling = CID_SIG_V23;
12956 else if (!strcasecmp(v->value, "dtmf"))
12957 confp->chan.cid_signalling = CID_SIG_DTMF;
12958 else if (!strcasecmp(v->value, "smdi"))
12959 confp->chan.cid_signalling = CID_SIG_SMDI;
12960 else if (!strcasecmp(v->value, "v23_jp"))
12961 confp->chan.cid_signalling = CID_SIG_V23_JP;
12962 else if (ast_true(v->value))
12963 confp->chan.cid_signalling = CID_SIG_BELL;
12964 } else if (!strcasecmp(v->name, "cidstart")) {
12965 if (!strcasecmp(v->value, "ring"))
12966 confp->chan.cid_start = CID_START_RING;
12967 else if (!strcasecmp(v->value, "polarity"))
12968 confp->chan.cid_start = CID_START_POLARITY;
12969 else if (ast_true(v->value))
12970 confp->chan.cid_start = CID_START_RING;
12971 } else if (!strcasecmp(v->name, "threewaycalling")) {
12972 confp->chan.threewaycalling = ast_true(v->value);
12973 } else if (!strcasecmp(v->name, "cancallforward")) {
12974 confp->chan.cancallforward = ast_true(v->value);
12975 } else if (!strcasecmp(v->name, "relaxdtmf")) {
12976 if (ast_true(v->value))
12977 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
12978 else
12979 confp->chan.dtmfrelax = 0;
12980 } else if (!strcasecmp(v->name, "mailbox")) {
12981 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
12982 } else if (!strcasecmp(v->name, "hasvoicemail")) {
12983 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
12984 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
12985 }
12986 } else if (!strcasecmp(v->name, "adsi")) {
12987 confp->chan.adsi = ast_true(v->value);
12988 } else if (!strcasecmp(v->name, "usesmdi")) {
12989 confp->chan.use_smdi = ast_true(v->value);
12990 } else if (!strcasecmp(v->name, "smdiport")) {
12991 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
12992 } else if (!strcasecmp(v->name, "transfer")) {
12993 confp->chan.transfer = ast_true(v->value);
12994 } else if (!strcasecmp(v->name, "canpark")) {
12995 confp->chan.canpark = ast_true(v->value);
12996 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
12997 confp->chan.echocanbridged = ast_true(v->value);
12998 } else if (!strcasecmp(v->name, "busydetect")) {
12999 confp->chan.busydetect = ast_true(v->value);
13000 } else if (!strcasecmp(v->name, "busycount")) {
13001 confp->chan.busycount = atoi(v->value);
13002 } else if (!strcasecmp(v->name, "silencethreshold")) {
13003 confp->chan.silencethreshold = atoi(v->value);
13004 } else if (!strcasecmp(v->name, "busycompare")) {
13005 confp->chan.busycompare = ast_true(v->value);
13006 } else if (!strcasecmp(v->name, "busypattern")) {
13007 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
13008 if (count == 1)
13009 confp->chan.busyquietlength = 0;
13010 else if (count < 1)
13011 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
13012 } else if (!strcasecmp(v->name, "busyfuzziness")) {
13013 confp->chan.busyfuzziness = atoi(v->value);
13014 } else if (!strcasecmp(v->name, "callprogress")) {
13015 if (ast_true(v->value))
13016 confp->chan.callprogress |= 1;
13017 else
13018 confp->chan.callprogress &= ~1;
13019 } else if (!strcasecmp(v->name, "faxdetect")) {
13020 if (!strcasecmp(v->value, "incoming")) {
13021 confp->chan.callprogress |= 4;
13022 confp->chan.callprogress &= ~2;
13023 } else if (!strcasecmp(v->value, "outgoing")) {
13024 confp->chan.callprogress &= ~4;
13025 confp->chan.callprogress |= 2;
13026 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
13027 confp->chan.callprogress |= 6;
13028 else
13029 confp->chan.callprogress &= ~6;
13030 } else if (!strcasecmp(v->name, "echocancel")) {
13031 if (!ast_strlen_zero(v->value)) {
13032 y = atoi(v->value);
13033 } else
13034 y = 0;
13035 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
13036 confp->chan.echocancel = y;
13037 else {
13038 confp->chan.echocancel = ast_true(v->value);
13039 if (confp->chan.echocancel)
13040 confp->chan.echocancel=128;
13041 }
13042 } else if (!strcasecmp(v->name, "echotraining")) {
13043 if (sscanf(v->value, "%30d", &y) == 1) {
13044 if ((y < 10) || (y > 4000)) {
13045 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
13046 } else {
13047 confp->chan.echotraining = y;
13048 }
13049 } else if (ast_true(v->value)) {
13050 confp->chan.echotraining = 400;
13051 } else
13052 confp->chan.echotraining = 0;
13053 } else if (!strcasecmp(v->name, "hidecallerid")) {
13054 confp->chan.hidecallerid = ast_true(v->value);
13055 } else if (!strcasecmp(v->name, "hidecalleridname")) {
13056 confp->chan.hidecalleridname = ast_true(v->value);
13057 } else if (!strcasecmp(v->name, "pulsedial")) {
13058 confp->chan.pulse = ast_true(v->value);
13059 } else if (!strcasecmp(v->name, "callreturn")) {
13060 confp->chan.callreturn = ast_true(v->value);
13061 } else if (!strcasecmp(v->name, "callwaiting")) {
13062 confp->chan.callwaiting = ast_true(v->value);
13063 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
13064 confp->chan.callwaitingcallerid = ast_true(v->value);
13065 } else if (!strcasecmp(v->name, "context")) {
13066 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
13067 } else if (!strcasecmp(v->name, "language")) {
13068 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
13069 } else if (!strcasecmp(v->name, "progzone")) {
13070 ast_copy_string(progzone, v->value, sizeof(progzone));
13071 } else if (!strcasecmp(v->name, "mohinterpret")
13072 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
13073 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
13074 } else if (!strcasecmp(v->name, "mohsuggest")) {
13075 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
13076 } else if (!strcasecmp(v->name, "stripmsd")) {
13077 confp->chan.stripmsd = atoi(v->value);
13078 } else if (!strcasecmp(v->name, "jitterbuffers")) {
13079 numbufs = atoi(v->value);
13080 } else if (!strcasecmp(v->name, "group")) {
13081 confp->chan.group = ast_get_group(v->value);
13082 } else if (!strcasecmp(v->name, "callgroup")) {
13083 confp->chan.callgroup = ast_get_group(v->value);
13084 } else if (!strcasecmp(v->name, "pickupgroup")) {
13085 confp->chan.pickupgroup = ast_get_group(v->value);
13086 } else if (!strcasecmp(v->name, "immediate")) {
13087 confp->chan.immediate = ast_true(v->value);
13088 } else if (!strcasecmp(v->name, "transfertobusy")) {
13089 confp->chan.transfertobusy = ast_true(v->value);
13090 } else if (!strcasecmp(v->name, "rxgain")) {
13091 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
13092 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
13093 }
13094 } else if (!strcasecmp(v->name, "txgain")) {
13095 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
13096 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
13097 }
13098 } else if (!strcasecmp(v->name, "tonezone")) {
13099 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
13100 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
13101 }
13102 } else if (!strcasecmp(v->name, "callerid")) {
13103 if (!strcasecmp(v->value, "asreceived")) {
13104 confp->chan.cid_num[0] = '\0';
13105 confp->chan.cid_name[0] = '\0';
13106 } else {
13107 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
13108 }
13109 } else if (!strcasecmp(v->name, "fullname")) {
13110 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
13111 } else if (!strcasecmp(v->name, "cid_number")) {
13112 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
13113 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
13114 confp->chan.dahditrcallerid = ast_true(v->value);
13115 if (strstr(v->name, "zap")) {
13116 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
13117 }
13118 } else if (!strcasecmp(v->name, "restrictcid")) {
13119 confp->chan.restrictcid = ast_true(v->value);
13120 } else if (!strcasecmp(v->name, "usecallingpres")) {
13121 confp->chan.use_callingpres = ast_true(v->value);
13122 } else if (!strcasecmp(v->name, "accountcode")) {
13123 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
13124 } else if (!strcasecmp(v->name, "amaflags")) {
13125 y = ast_cdr_amaflags2int(v->value);
13126 if (y < 0)
13127 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
13128 else
13129 confp->chan.amaflags = y;
13130 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
13131 confp->chan.polarityonanswerdelay = atoi(v->value);
13132 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
13133 confp->chan.answeronpolarityswitch = ast_true(v->value);
13134 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
13135 confp->chan.hanguponpolarityswitch = ast_true(v->value);
13136 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
13137 confp->chan.sendcalleridafter = atoi(v->value);
13138 } else if (reload != 1) {
13139 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
13140 confp->chan.outsigmod = -1;
13141 if (!strcasecmp(v->value, "em")) {
13142 confp->chan.sig = SIG_EM;
13143 } else if (!strcasecmp(v->value, "em_e1")) {
13144 confp->chan.sig = SIG_EM_E1;
13145 } else if (!strcasecmp(v->value, "em_w")) {
13146 confp->chan.sig = SIG_EMWINK;
13147 confp->chan.radio = 0;
13148 } else if (!strcasecmp(v->value, "fxs_ls")) {
13149 confp->chan.sig = SIG_FXSLS;
13150 confp->chan.radio = 0;
13151 } else if (!strcasecmp(v->value, "fxs_gs")) {
13152 confp->chan.sig = SIG_FXSGS;
13153 confp->chan.radio = 0;
13154 } else if (!strcasecmp(v->value, "fxs_ks")) {
13155 confp->chan.sig = SIG_FXSKS;
13156 confp->chan.radio = 0;
13157 } else if (!strcasecmp(v->value, "fxo_ls")) {
13158 confp->chan.sig = SIG_FXOLS;
13159 confp->chan.radio = 0;
13160 } else if (!strcasecmp(v->value, "fxo_gs")) {
13161 confp->chan.sig = SIG_FXOGS;
13162 confp->chan.radio = 0;
13163 } else if (!strcasecmp(v->value, "fxo_ks")) {
13164 confp->chan.sig = SIG_FXOKS;
13165 confp->chan.radio = 0;
13166 } else if (!strcasecmp(v->value, "fxs_rx")) {
13167 confp->chan.sig = SIG_FXSKS;
13168 confp->chan.radio = 1;
13169 } else if (!strcasecmp(v->value, "fxo_rx")) {
13170 confp->chan.sig = SIG_FXOLS;
13171 confp->chan.radio = 1;
13172 } else if (!strcasecmp(v->value, "fxs_tx")) {
13173 confp->chan.sig = SIG_FXSLS;
13174 confp->chan.radio = 1;
13175 } else if (!strcasecmp(v->value, "fxo_tx")) {
13176 confp->chan.sig = SIG_FXOGS;
13177 confp->chan.radio = 1;
13178 } else if (!strcasecmp(v->value, "em_rx")) {
13179 confp->chan.sig = SIG_EM;
13180 confp->chan.radio = 1;
13181 } else if (!strcasecmp(v->value, "em_tx")) {
13182 confp->chan.sig = SIG_EM;
13183 confp->chan.radio = 1;
13184 } else if (!strcasecmp(v->value, "em_rxtx")) {
13185 confp->chan.sig = SIG_EM;
13186 confp->chan.radio = 2;
13187 } else if (!strcasecmp(v->value, "em_txrx")) {
13188 confp->chan.sig = SIG_EM;
13189 confp->chan.radio = 2;
13190 } else if (!strcasecmp(v->value, "sf")) {
13191 confp->chan.sig = SIG_SF;
13192 confp->chan.radio = 0;
13193 } else if (!strcasecmp(v->value, "sf_w")) {
13194 confp->chan.sig = SIG_SFWINK;
13195 confp->chan.radio = 0;
13196 } else if (!strcasecmp(v->value, "sf_featd")) {
13197 confp->chan.sig = SIG_FEATD;
13198 confp->chan.radio = 0;
13199 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13200 confp->chan.sig = SIG_FEATDMF;
13201 confp->chan.radio = 0;
13202 } else if (!strcasecmp(v->value, "sf_featb")) {
13203 confp->chan.sig = SIG_SF_FEATB;
13204 confp->chan.radio = 0;
13205 } else if (!strcasecmp(v->value, "sf")) {
13206 confp->chan.sig = SIG_SF;
13207 confp->chan.radio = 0;
13208 } else if (!strcasecmp(v->value, "sf_rx")) {
13209 confp->chan.sig = SIG_SF;
13210 confp->chan.radio = 1;
13211 } else if (!strcasecmp(v->value, "sf_tx")) {
13212 confp->chan.sig = SIG_SF;
13213 confp->chan.radio = 1;
13214 } else if (!strcasecmp(v->value, "sf_rxtx")) {
13215 confp->chan.sig = SIG_SF;
13216 confp->chan.radio = 2;
13217 } else if (!strcasecmp(v->value, "sf_txrx")) {
13218 confp->chan.sig = SIG_SF;
13219 confp->chan.radio = 2;
13220 } else if (!strcasecmp(v->value, "featd")) {
13221 confp->chan.sig = SIG_FEATD;
13222 confp->chan.radio = 0;
13223 } else if (!strcasecmp(v->value, "featdmf")) {
13224 confp->chan.sig = SIG_FEATDMF;
13225 confp->chan.radio = 0;
13226 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13227 confp->chan.sig = SIG_FEATDMF_TA;
13228 confp->chan.radio = 0;
13229 } else if (!strcasecmp(v->value, "e911")) {
13230 confp->chan.sig = SIG_E911;
13231 confp->chan.radio = 0;
13232 } else if (!strcasecmp(v->value, "fgccama")) {
13233 confp->chan.sig = SIG_FGC_CAMA;
13234 confp->chan.radio = 0;
13235 } else if (!strcasecmp(v->value, "fgccamamf")) {
13236 confp->chan.sig = SIG_FGC_CAMAMF;
13237 confp->chan.radio = 0;
13238 } else if (!strcasecmp(v->value, "featb")) {
13239 confp->chan.sig = SIG_FEATB;
13240 confp->chan.radio = 0;
13241 #ifdef HAVE_OPENR2
13242 } else if (!strcasecmp(v->value, "mfcr2")) {
13243 confp->chan.sig = SIG_MFCR2;
13244 #endif
13245 #ifdef HAVE_PRI
13246 } else if (!strcasecmp(v->value, "pri_net")) {
13247 confp->chan.radio = 0;
13248 confp->chan.sig = SIG_PRI;
13249 confp->pri.nodetype = PRI_NETWORK;
13250 } else if (!strcasecmp(v->value, "pri_cpe")) {
13251 confp->chan.sig = SIG_PRI;
13252 confp->chan.radio = 0;
13253 confp->pri.nodetype = PRI_CPE;
13254 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
13255 confp->chan.sig = SIG_GR303FXOKS;
13256 confp->chan.radio = 0;
13257 confp->pri.nodetype = PRI_NETWORK;
13258 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
13259 confp->chan.sig = SIG_GR303FXSKS;
13260 confp->chan.radio = 0;
13261 confp->pri.nodetype = PRI_CPE;
13262 #endif
13263 } else {
13264 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13265 }
13266 } else if (!strcasecmp(v->name, "outsignalling")) {
13267 if (!strcasecmp(v->value, "em")) {
13268 confp->chan.outsigmod = SIG_EM;
13269 } else if (!strcasecmp(v->value, "em_e1")) {
13270 confp->chan.outsigmod = SIG_EM_E1;
13271 } else if (!strcasecmp(v->value, "em_w")) {
13272 confp->chan.outsigmod = SIG_EMWINK;
13273 } else if (!strcasecmp(v->value, "sf")) {
13274 confp->chan.outsigmod = SIG_SF;
13275 } else if (!strcasecmp(v->value, "sf_w")) {
13276 confp->chan.outsigmod = SIG_SFWINK;
13277 } else if (!strcasecmp(v->value, "sf_featd")) {
13278 confp->chan.outsigmod = SIG_FEATD;
13279 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13280 confp->chan.outsigmod = SIG_FEATDMF;
13281 } else if (!strcasecmp(v->value, "sf_featb")) {
13282 confp->chan.outsigmod = SIG_SF_FEATB;
13283 } else if (!strcasecmp(v->value, "sf")) {
13284 confp->chan.outsigmod = SIG_SF;
13285 } else if (!strcasecmp(v->value, "featd")) {
13286 confp->chan.outsigmod = SIG_FEATD;
13287 } else if (!strcasecmp(v->value, "featdmf")) {
13288 confp->chan.outsigmod = SIG_FEATDMF;
13289 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13290 confp->chan.outsigmod = SIG_FEATDMF_TA;
13291 } else if (!strcasecmp(v->value, "e911")) {
13292 confp->chan.outsigmod = SIG_E911;
13293 } else if (!strcasecmp(v->value, "fgccama")) {
13294 confp->chan.outsigmod = SIG_FGC_CAMA;
13295 } else if (!strcasecmp(v->value, "fgccamamf")) {
13296 confp->chan.outsigmod = SIG_FGC_CAMAMF;
13297 } else if (!strcasecmp(v->value, "featb")) {
13298 confp->chan.outsigmod = SIG_FEATB;
13299 } else {
13300 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13301 }
13302 #ifdef HAVE_PRI
13303 } else if (!strcasecmp(v->name, "pridialplan")) {
13304 if (!strcasecmp(v->value, "national")) {
13305 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
13306 } else if (!strcasecmp(v->value, "unknown")) {
13307 confp->pri.dialplan = PRI_UNKNOWN + 1;
13308 } else if (!strcasecmp(v->value, "private")) {
13309 confp->pri.dialplan = PRI_PRIVATE + 1;
13310 } else if (!strcasecmp(v->value, "international")) {
13311 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
13312 } else if (!strcasecmp(v->value, "local")) {
13313 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
13314 } else if (!strcasecmp(v->value, "dynamic")) {
13315 confp->pri.dialplan = -1;
13316 } else {
13317 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13318 }
13319 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
13320 if (!strcasecmp(v->value, "national")) {
13321 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
13322 } else if (!strcasecmp(v->value, "unknown")) {
13323 confp->pri.localdialplan = PRI_UNKNOWN + 1;
13324 } else if (!strcasecmp(v->value, "private")) {
13325 confp->pri.localdialplan = PRI_PRIVATE + 1;
13326 } else if (!strcasecmp(v->value, "international")) {
13327 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
13328 } else if (!strcasecmp(v->value, "local")) {
13329 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
13330 } else if (!strcasecmp(v->value, "dynamic")) {
13331 confp->pri.localdialplan = -1;
13332 } else {
13333 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13334 }
13335 } else if (!strcasecmp(v->name, "switchtype")) {
13336 if (!strcasecmp(v->value, "national"))
13337 confp->pri.switchtype = PRI_SWITCH_NI2;
13338 else if (!strcasecmp(v->value, "ni1"))
13339 confp->pri.switchtype = PRI_SWITCH_NI1;
13340 else if (!strcasecmp(v->value, "dms100"))
13341 confp->pri.switchtype = PRI_SWITCH_DMS100;
13342 else if (!strcasecmp(v->value, "4ess"))
13343 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
13344 else if (!strcasecmp(v->value, "5ess"))
13345 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
13346 else if (!strcasecmp(v->value, "euroisdn"))
13347 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
13348 else if (!strcasecmp(v->value, "qsig"))
13349 confp->pri.switchtype = PRI_SWITCH_QSIG;
13350 else {
13351 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
13352 return -1;
13353 }
13354 } else if (!strcasecmp(v->name, "nsf")) {
13355 if (!strcasecmp(v->value, "sdn"))
13356 confp->pri.nsf = PRI_NSF_SDN;
13357 else if (!strcasecmp(v->value, "megacom"))
13358 confp->pri.nsf = PRI_NSF_MEGACOM;
13359 else if (!strcasecmp(v->value, "tollfreemegacom"))
13360 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
13361 else if (!strcasecmp(v->value, "accunet"))
13362 confp->pri.nsf = PRI_NSF_ACCUNET;
13363 else if (!strcasecmp(v->value, "none"))
13364 confp->pri.nsf = PRI_NSF_NONE;
13365 else {
13366 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
13367 confp->pri.nsf = PRI_NSF_NONE;
13368 }
13369 } else if (!strcasecmp(v->name, "priindication")) {
13370 if (!strcasecmp(v->value, "outofband"))
13371 confp->chan.priindication_oob = 1;
13372 else if (!strcasecmp(v->value, "inband"))
13373 confp->chan.priindication_oob = 0;
13374 else
13375 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
13376 v->value, v->lineno);
13377 } else if (!strcasecmp(v->name, "priexclusive")) {
13378 confp->chan.priexclusive = ast_true(v->value);
13379 } else if (!strcasecmp(v->name, "internationalprefix")) {
13380 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
13381 } else if (!strcasecmp(v->name, "nationalprefix")) {
13382 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
13383 } else if (!strcasecmp(v->name, "localprefix")) {
13384 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
13385 } else if (!strcasecmp(v->name, "privateprefix")) {
13386 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
13387 } else if (!strcasecmp(v->name, "unknownprefix")) {
13388 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
13389 } else if (!strcasecmp(v->name, "resetinterval")) {
13390 if (!strcasecmp(v->value, "never"))
13391 confp->pri.resetinterval = -1;
13392 else if (atoi(v->value) >= 60)
13393 confp->pri.resetinterval = atoi(v->value);
13394 else
13395 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
13396 v->value, v->lineno);
13397 } else if (!strcasecmp(v->name, "minunused")) {
13398 confp->pri.minunused = atoi(v->value);
13399 } else if (!strcasecmp(v->name, "minidle")) {
13400 confp->pri.minidle = atoi(v->value);
13401 } else if (!strcasecmp(v->name, "idleext")) {
13402 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
13403 } else if (!strcasecmp(v->name, "idledial")) {
13404 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
13405 } else if (!strcasecmp(v->name, "overlapdial")) {
13406 if (ast_true(v->value)) {
13407 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13408 } else if (!strcasecmp(v->value, "incoming")) {
13409 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
13410 } else if (!strcasecmp(v->value, "outgoing")) {
13411 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
13412 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
13413 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13414 } else {
13415 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
13416 }
13417 #ifdef HAVE_PRI_INBANDDISCONNECT
13418 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
13419 confp->pri.inbanddisconnect = ast_true(v->value);
13420 #endif
13421 } else if (!strcasecmp(v->name, "pritimer")) {
13422 #ifdef PRI_GETSET_TIMERS
13423 char tmp[20];
13424 char *timerc;
13425 char *c;
13426 int timer;
13427 int timeridx;
13428
13429 ast_copy_string(tmp, v->value, sizeof(tmp));
13430 c = tmp;
13431 timerc = strsep(&c, ",");
13432 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
13433 timeridx = pri_timer2idx(timerc);
13434 timer = atoi(c);
13435 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
13436 ast_log(LOG_WARNING,
13437 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
13438 v->lineno);
13439 } else if (!timer) {
13440 ast_log(LOG_WARNING,
13441 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
13442 c, timerc, v->lineno);
13443 } else {
13444 pritimers[timeridx] = timer;
13445 }
13446 } else {
13447 ast_log(LOG_WARNING,
13448 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
13449 v->value, v->lineno);
13450 }
13451 #endif
13452 } else if (!strcasecmp(v->name, "facilityenable")) {
13453 confp->pri.facilityenable = ast_true(v->value);
13454 #endif
13455 #ifdef HAVE_OPENR2
13456 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
13457 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
13458 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);
13459 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
13460 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
13461 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
13462 mfcr2_cur_variant = openr2_proto_get_variant(v->value);
13463 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
13464 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
13465 }
13466 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
13467 mfcr2_cur_mfback_timeout = atoi(v->value);
13468 if (!mfcr2_cur_mfback_timeout) {
13469 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
13470 mfcr2_cur_mfback_timeout = -1;
13471 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
13472 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
13473 }
13474 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
13475 mfcr2_cur_metering_pulse_timeout = atoi(v->value);
13476 if (mfcr2_cur_metering_pulse_timeout > 500) {
13477 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
13478 }
13479 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13480 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
13481 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
13482 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
13483 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
13484 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
13485 mfcr2_cur_dtmf_time_on = atoi(v->value);
13486 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
13487 mfcr2_cur_dtmf_time_off = atoi(v->value);
13488 #endif
13489 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
13490 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
13491 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
13492 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
13493 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
13494 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
13495 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
13496 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
13497 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
13498 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
13499 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
13500 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
13501 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
13502 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
13503 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
13504 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
13505 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
13506 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
13507 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
13508 mfcr2_cur_max_ani = atoi(v->value);
13509 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
13510 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
13511 }
13512 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
13513 mfcr2_cur_max_dnis = atoi(v->value);
13514 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
13515 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
13516 }
13517 } else if (!strcasecmp(v->name, "mfcr2_category")) {
13518 mfcr2_cur_category = openr2_proto_get_category(v->value);
13519 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
13520 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
13521 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
13522 v->value, v->lineno);
13523 }
13524 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
13525 openr2_log_level_t tmplevel;
13526 char *toklevel = NULL;
13527 char *saveptr = NULL;
13528 char *logval = ast_strdupa(v->value);
13529 toklevel = strtok_r(logval, ",", &saveptr);
13530 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13531 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
13532 } else if (OR2_LOG_NOTHING == tmplevel) {
13533 mfcr2_cur_loglevel = tmplevel;
13534 } else {
13535 mfcr2_cur_loglevel |= tmplevel;
13536 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
13537 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13538 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
13539 continue;
13540 }
13541 mfcr2_cur_loglevel |= tmplevel;
13542 }
13543 }
13544 #endif
13545
13546 } else if (!strcasecmp(v->name, "cadence")) {
13547
13548 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
13549 int i;
13550 struct dahdi_ring_cadence new_cadence;
13551 int cid_location = -1;
13552 int firstcadencepos = 0;
13553 char original_args[80];
13554 int cadence_is_ok = 1;
13555
13556 ast_copy_string(original_args, v->value, sizeof(original_args));
13557
13558 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]);
13559
13560
13561 if (element_count % 2 == 1) {
13562 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
13563 cadence_is_ok = 0;
13564 }
13565
13566
13567 for (i = 0; i < element_count; i++) {
13568 if (c[i] == 0) {
13569 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
13570 cadence_is_ok = 0;
13571 break;
13572 } else if (c[i] < 0) {
13573 if (i % 2 == 1) {
13574
13575 if (cid_location == -1) {
13576 cid_location = i;
13577 c[i] *= -1;
13578 } else {
13579 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
13580 cadence_is_ok = 0;
13581 break;
13582 }
13583 } else {
13584 if (firstcadencepos == 0) {
13585 firstcadencepos = i;
13586
13587 } else {
13588 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
13589 cadence_is_ok = 0;
13590 break;
13591 }
13592 }
13593 }
13594 }
13595
13596
13597 for (i = 0; i < 16; i++) {
13598 new_cadence.ringcadence[i] = c[i];
13599 }
13600
13601 if (cadence_is_ok) {
13602
13603 if (element_count < 2) {
13604 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
13605 } else {
13606 if (cid_location == -1) {
13607
13608 cid_location = 1;
13609 } else {
13610
13611 cid_location = (cid_location + 1) / 2;
13612 }
13613
13614 if (!user_has_defined_cadences++)
13615
13616 num_cadence = 0;
13617 if ((num_cadence+1) >= NUM_CADENCE_MAX)
13618 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
13619 else {
13620 cadences[num_cadence] = new_cadence;
13621 cidrings[num_cadence++] = cid_location;
13622 if (option_verbose > 2)
13623 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
13624 }
13625 }
13626 }
13627 } else if (!strcasecmp(v->name, "ringtimeout")) {
13628 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
13629 } else if (!strcasecmp(v->name, "prewink")) {
13630 confp->timing.prewinktime = atoi(v->value);
13631 } else if (!strcasecmp(v->name, "preflash")) {
13632 confp->timing.preflashtime = atoi(v->value);
13633 } else if (!strcasecmp(v->name, "wink")) {
13634 confp->timing.winktime = atoi(v->value);
13635 } else if (!strcasecmp(v->name, "flash")) {
13636 confp->timing.flashtime = atoi(v->value);
13637 } else if (!strcasecmp(v->name, "start")) {
13638 confp->timing.starttime = atoi(v->value);
13639 } else if (!strcasecmp(v->name, "rxwink")) {
13640 confp->timing.rxwinktime = atoi(v->value);
13641 } else if (!strcasecmp(v->name, "rxflash")) {
13642 confp->timing.rxflashtime = atoi(v->value);
13643 } else if (!strcasecmp(v->name, "debounce")) {
13644 confp->timing.debouncetime = atoi(v->value);
13645 } else if (!strcasecmp(v->name, "toneduration")) {
13646 int toneduration;
13647 int ctlfd;
13648 int res;
13649 struct dahdi_dialparams dps;
13650
13651 ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
13652
13653 if (ctlfd == -1) {
13654 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
13655 return -1;
13656 }
13657
13658 toneduration = atoi(v->value);
13659 if (toneduration > -1) {
13660 memset(&dps, 0, sizeof(dps));
13661
13662 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
13663 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
13664 if (res < 0) {
13665 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
13666 return -1;
13667 }
13668 }
13669 close(ctlfd);
13670 } else if (!strcasecmp(v->name, "defaultcic")) {
13671 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
13672 } else if (!strcasecmp(v->name, "defaultozz")) {
13673 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
13674 }
13675 } else if (!skipchannels)
13676 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
13677 }
13678 if (dahdichan[0]) {
13679
13680
13681 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
13682 return -1;
13683 }
13684 }
13685
13686
13687 if (!found_pseudo && reload != 1) {
13688
13689
13690
13691
13692 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13693
13694 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
13695
13696 if (tmp) {
13697 if (option_verbose > 2)
13698 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
13699 } else {
13700 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
13701 }
13702 }
13703 return 0;
13704 }
13705
13706 static int setup_dahdi(int reload)
13707 {
13708 struct ast_config *cfg;
13709 struct ast_variable *v;
13710 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13711 int res;
13712
13713 #ifdef HAVE_PRI
13714 char *c;
13715 int spanno;
13716 int i, x;
13717 int logicalspan;
13718 int trunkgroup;
13719 int dchannels[NUM_DCHANS];
13720 #endif
13721
13722 #ifdef HAVE_ZAPTEL
13723 int load_from_zapata_conf = 1;
13724 #else
13725 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
13726 #endif
13727
13728 if (load_from_zapata_conf) {
13729 if (!(cfg = ast_config_load("zapata.conf"))) {
13730 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13731 return 0;
13732 }
13733 } else {
13734 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13735 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13736 return 0;
13737 }
13738 }
13739
13740
13741 ast_mutex_lock(&iflock);
13742 #ifdef HAVE_PRI
13743 if (reload != 1) {
13744
13745 v = ast_variable_browse(cfg, "trunkgroups");
13746 while (v) {
13747 if (!strcasecmp(v->name, "trunkgroup")) {
13748 trunkgroup = atoi(v->value);
13749 if (trunkgroup > 0) {
13750 if ((c = strchr(v->value, ','))) {
13751 i = 0;
13752 memset(dchannels, 0, sizeof(dchannels));
13753 while (c && (i < NUM_DCHANS)) {
13754 dchannels[i] = atoi(c + 1);
13755 if (dchannels[i] < 0) {
13756 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);
13757 } else
13758 i++;
13759 c = strchr(c + 1, ',');
13760 }
13761 if (i) {
13762 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13763 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);
13764 } else if (option_verbose > 1)
13765 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");
13766 } else
13767 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13768 } else
13769 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13770 } else
13771 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13772 } else if (!strcasecmp(v->name, "spanmap")) {
13773 spanno = atoi(v->value);
13774 if (spanno > 0) {
13775 if ((c = strchr(v->value, ','))) {
13776 trunkgroup = atoi(c + 1);
13777 if (trunkgroup > 0) {
13778 if ((c = strchr(c + 1, ',')))
13779 logicalspan = atoi(c + 1);
13780 else
13781 logicalspan = 0;
13782 if (logicalspan >= 0) {
13783 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13784 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13785 } else if (option_verbose > 1)
13786 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13787 } else
13788 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);
13789 } else
13790 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13791 } else
13792 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13793 } else
13794 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13795 } else {
13796 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13797 }
13798 v = v->next;
13799 }
13800 }
13801 #endif
13802
13803
13804 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13805
13806 v = ast_variable_browse(cfg, "channels");
13807 res = process_dahdi(&conf, "", v, reload, 0);
13808 ast_mutex_unlock(&iflock);
13809 ast_config_destroy(cfg);
13810 if (res)
13811 return res;
13812 cfg = ast_config_load("users.conf");
13813 if (cfg) {
13814 char *cat;
13815 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13816 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13817 if (!strcasecmp(cat, "general"))
13818 continue;
13819 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
13820 struct dahdi_chan_conf sect_conf;
13821 memcpy(§_conf, &conf, sizeof(sect_conf));
13822
13823 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13824 }
13825 }
13826 ast_config_destroy(cfg);
13827 }
13828 #ifdef HAVE_PRI
13829 if (reload != 1) {
13830 for (x = 0; x < NUM_SPANS; x++) {
13831 if (pris[x].pvts[0]) {
13832 if (start_pri(pris + x)) {
13833 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13834 return -1;
13835 } else if (option_verbose > 1)
13836 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13837 }
13838 }
13839 }
13840 #endif
13841 #ifdef HAVE_OPENR2
13842 if (reload != 1) {
13843 int x;
13844 for (x = 0; x < NUM_SPANS; x++) {
13845 if (r2links[x].protocol_context) {
13846 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
13847 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
13848 return -1;
13849 } else {
13850 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
13851 }
13852 }
13853 }
13854 }
13855 #endif
13856
13857 restart_monitor();
13858 return 0;
13859 }
13860
13861 #define local_astman_register(a, b, c, d) do { \
13862 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13863 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
13864 } \
13865 ast_manager_register("Zap" a, b, zap_ ## c, d); \
13866 } while (0)
13867
13868 static int load_module(void)
13869 {
13870 int res;
13871
13872 #ifdef HAVE_PRI
13873 int y,i;
13874 memset(pris, 0, sizeof(pris));
13875 for (y = 0; y < NUM_SPANS; y++) {
13876 ast_mutex_init(&pris[y].lock);
13877 pris[y].offset = -1;
13878 pris[y].master = AST_PTHREADT_NULL;
13879 for (i = 0; i < NUM_DCHANS; i++)
13880 pris[y].fds[i] = -1;
13881 }
13882 pri_set_error(dahdi_pri_error);
13883 pri_set_message(dahdi_pri_message);
13884 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13885 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13886 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13887 }
13888 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13889 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13890 #endif
13891 #ifdef HAVE_OPENR2
13892 init_mfcr2_globals();
13893 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13894 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
13895 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
13896 }
13897 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
13898 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
13899 #endif
13900 if ((res = setup_dahdi(0))) {
13901 return AST_MODULE_LOAD_DECLINE;
13902 }
13903 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13904 chan_tech = &dahdi_tech;
13905 } else {
13906 chan_tech = &zap_tech;
13907 }
13908 if (ast_channel_register(chan_tech)) {
13909 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
13910 __unload_module();
13911 return -1;
13912 }
13913 #ifdef HAVE_PRI
13914 ast_string_field_init(&inuse, 16);
13915 ast_string_field_set(&inuse, name, "GR-303InUse");
13916 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13917 #endif
13918 #ifdef HAVE_OPENR2
13919 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
13920 #endif
13921 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13922
13923 memset(round_robin, 0, sizeof(round_robin));
13924 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
13925 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
13926 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
13927 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
13928 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
13929 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
13930 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
13931
13932 ast_cond_init(&ss_thread_complete, NULL);
13933
13934 return res;
13935 }
13936
13937 static int dahdi_sendtext(struct ast_channel *c, const char *text)
13938 {
13939 #define END_SILENCE_LEN 400
13940 #define HEADER_MS 50
13941 #define TRAILER_MS 5
13942 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
13943 #define ASCII_BYTES_PER_CHAR 80
13944
13945 unsigned char *buf,*mybuf;
13946 struct dahdi_pvt *p = c->tech_pvt;
13947 struct pollfd fds[1];
13948 int size,res,fd,len,x;
13949 int bytes=0;
13950
13951 float cr = 1.0;
13952 float ci = 0.0;
13953 float scont = 0.0;
13954 int index;
13955
13956 index = dahdi_get_index(c, p, 0);
13957 if (index < 0) {
13958 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
13959 return -1;
13960 }
13961 if (!text[0]) return(0);
13962 if ((!p->tdd) && (!p->mate)) return(0);
13963 if (p->mate)
13964 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
13965 else
13966 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
13967 if (!buf)
13968 return -1;
13969 mybuf = buf;
13970 if (p->mate) {
13971 int codec = AST_LAW(p);
13972 for (x = 0; x < HEADER_MS; x++) {
13973 PUT_CLID_MARKMS;
13974 }
13975
13976 for (x = 0; text[x]; x++) {
13977 PUT_CLID(text[x]);
13978 }
13979 for (x = 0; x < TRAILER_MS; x++) {
13980 PUT_CLID_MARKMS;
13981 }
13982 len = bytes;
13983 buf = mybuf;
13984 } else {
13985 len = tdd_generate(p->tdd, buf, text);
13986 if (len < 1) {
13987 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
13988 free(mybuf);
13989 return -1;
13990 }
13991 }
13992 memset(buf + len, 0x7f, END_SILENCE_LEN);
13993 len += END_SILENCE_LEN;
13994 fd = p->subs[index].dfd;
13995 while (len) {
13996 if (ast_check_hangup(c)) {
13997 free(mybuf);
13998 return -1;
13999 }
14000 size = len;
14001 if (size > READ_SIZE)
14002 size = READ_SIZE;
14003 fds[0].fd = fd;
14004 fds[0].events = POLLOUT | POLLPRI;
14005 fds[0].revents = 0;
14006 res = poll(fds, 1, -1);
14007 if (!res) {
14008 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
14009 continue;
14010 }
14011
14012 if (fds[0].revents & POLLPRI) {
14013 ast_free(mybuf);
14014 return -1;
14015 }
14016 if (!(fds[0].revents & POLLOUT)) {
14017 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
14018 continue;
14019 }
14020 res = write(fd, buf, size);
14021 if (res != size) {
14022 if (res == -1) {
14023 free(mybuf);
14024 return -1;
14025 }
14026 if (option_debug)
14027 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14028 break;
14029 }
14030 len -= size;
14031 buf += size;
14032 }
14033 free(mybuf);
14034 return(0);
14035 }
14036
14037
14038 static int reload(void)
14039 {
14040 int res = 0;
14041
14042 res = setup_dahdi(1);
14043 if (res) {
14044 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14045 return -1;
14046 }
14047 return 0;
14048 }
14049
14050
14051
14052
14053
14054 #ifdef HAVE_PRI
14055 #define tdesc "DAHDI Telephony w/PRI"
14056 #else
14057 #define tdesc "DAHDI Telephony"
14058 #endif
14059
14060 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
14061 .load = load_module,
14062 .unload = unload_module,
14063 .reload = reload,
14064 );
14065
14066