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: 232090 $")
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 if (IS_DIGITAL(ast->transfercapability)) {
02748 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02749 } else {
02750 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02751 }
02752
02753 mysig = p->sig;
02754 if (p->outsigmod > -1)
02755 mysig = p->outsigmod;
02756
02757 switch (mysig) {
02758 case SIG_FXOLS:
02759 case SIG_FXOGS:
02760 case SIG_FXOKS:
02761 if (p->owner == ast) {
02762
02763
02764
02765 p->dialing = 1;
02766 if (p->use_callerid) {
02767
02768 if (p->cidspill) {
02769 ast_log(LOG_WARNING, "cidspill already exists??\n");
02770 free(p->cidspill);
02771 }
02772 p->callwaitcas = 0;
02773 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02774 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02775 p->cidpos = 0;
02776 send_callerid(p);
02777 }
02778 }
02779
02780 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02781 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02782 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02783 p->cidrings = cidrings[p->distinctivering - 1];
02784 } else {
02785 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02786 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02787 p->cidrings = p->sendcalleridafter;
02788 }
02789
02790
02791 c = strchr(dest, '/');
02792 if (c)
02793 c++;
02794 if (c && (strlen(c) < p->stripmsd)) {
02795 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02796 c = NULL;
02797 }
02798 if (c) {
02799 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02800 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02801 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02802 } else {
02803 p->dop.dialstr[0] = '\0';
02804 }
02805 x = DAHDI_RING;
02806 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02807 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02808 ast_mutex_unlock(&p->lock);
02809 return -1;
02810 }
02811 p->dialing = 1;
02812 } else {
02813
02814 p->callwaitrings = 0;
02815 if (ast->cid.cid_num)
02816 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02817 else
02818 p->callwait_num[0] = '\0';
02819 if (ast->cid.cid_name)
02820 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02821 else
02822 p->callwait_name[0] = '\0';
02823
02824 if (dahdi_callwait(ast)) {
02825 ast_mutex_unlock(&p->lock);
02826 return -1;
02827 }
02828
02829 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02830 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02831
02832 }
02833 n = ast->cid.cid_name;
02834 l = ast->cid.cid_num;
02835 if (l)
02836 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02837 else
02838 p->lastcid_num[0] = '\0';
02839 if (n)
02840 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02841 else
02842 p->lastcid_name[0] = '\0';
02843 ast_setstate(ast, AST_STATE_RINGING);
02844 index = dahdi_get_index(ast, p, 0);
02845 if (index > -1) {
02846 p->subs[index].needringing = 1;
02847 }
02848 break;
02849 case SIG_FXSLS:
02850 case SIG_FXSGS:
02851 case SIG_FXSKS:
02852 case SIG_EMWINK:
02853 case SIG_EM:
02854 case SIG_EM_E1:
02855 case SIG_FEATD:
02856 case SIG_FEATDMF:
02857 case SIG_E911:
02858 case SIG_FGC_CAMA:
02859 case SIG_FGC_CAMAMF:
02860 case SIG_FEATB:
02861 case SIG_SFWINK:
02862 case SIG_SF:
02863 case SIG_SF_FEATD:
02864 case SIG_SF_FEATDMF:
02865 case SIG_FEATDMF_TA:
02866 case SIG_SF_FEATB:
02867 c = strchr(dest, '/');
02868 if (c)
02869 c++;
02870 else
02871 c = "";
02872 if (strlen(c) < p->stripmsd) {
02873 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02874 ast_mutex_unlock(&p->lock);
02875 return -1;
02876 }
02877 #ifdef HAVE_PRI
02878
02879 if (!p->pri) {
02880 #endif
02881 x = DAHDI_START;
02882 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02883 if (res < 0) {
02884 if (errno != EINPROGRESS) {
02885 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02886 ast_mutex_unlock(&p->lock);
02887 return -1;
02888 }
02889 }
02890 #ifdef HAVE_PRI
02891 }
02892 #endif
02893 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02894 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02895
02896 c += p->stripmsd;
02897
02898 switch (mysig) {
02899 case SIG_FEATD:
02900 l = ast->cid.cid_num;
02901 if (l)
02902 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02903 else
02904 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02905 break;
02906 case SIG_FEATDMF:
02907 l = ast->cid.cid_num;
02908 if (l)
02909 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02910 else
02911 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02912 break;
02913 case SIG_FEATDMF_TA:
02914 {
02915 const char *cic, *ozz;
02916
02917
02918 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02919 if (!ozz)
02920 ozz = defaultozz;
02921 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02922 if (!cic)
02923 cic = defaultcic;
02924 if (!ozz || !cic) {
02925 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02926 ast_mutex_unlock(&p->lock);
02927 return -1;
02928 }
02929 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02930 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02931 p->whichwink = 0;
02932 }
02933 break;
02934 case SIG_E911:
02935 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02936 break;
02937 case SIG_FGC_CAMA:
02938 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02939 break;
02940 case SIG_FGC_CAMAMF:
02941 case SIG_FEATB:
02942 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02943 break;
02944 default:
02945 if (p->pulse)
02946 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02947 else
02948 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02949 break;
02950 }
02951
02952 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02953 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02954 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02955 p->echorest[sizeof(p->echorest) - 1] = '\0';
02956 p->echobreak = 1;
02957 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02958 } else
02959 p->echobreak = 0;
02960 if (!res) {
02961 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02962 int saveerr = errno;
02963
02964 x = DAHDI_ONHOOK;
02965 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02966 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02967 ast_mutex_unlock(&p->lock);
02968 return -1;
02969 }
02970 } else
02971 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res);
02972 p->dialing = 1;
02973 if (ast_strlen_zero(c))
02974 p->dialednone = 1;
02975 ast_setstate(ast, AST_STATE_DIALING);
02976 break;
02977 case 0:
02978
02979 ast_setstate(ast, AST_STATE_UP);
02980 break;
02981 case SIG_PRI:
02982 case SIG_MFCR2:
02983
02984 p->dialdest[0] = '\0';
02985 p->dialing = 1;
02986 break;
02987 default:
02988 ast_log(LOG_DEBUG, "not yet implemented\n");
02989 ast_mutex_unlock(&p->lock);
02990 return -1;
02991 }
02992 #ifdef HAVE_OPENR2
02993 if (p->mfcr2) {
02994 int strip = p->stripmsd;
02995 int callres = 0;
02996 c = strchr(dest, '/');
02997 if (c) {
02998 c++;
02999 } else {
03000 c = dest;
03001 }
03002 if (!p->hidecallerid) {
03003 l = ast->cid.cid_num;
03004 } else {
03005 l = NULL;
03006 }
03007 if (strlen(c) < strip) {
03008 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
03009 strip = 0;
03010 }
03011 p->dialing = 1;
03012 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast));
03013 if (-1 == callres) {
03014 ast_mutex_unlock(&p->lock);
03015 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03016 return -1;
03017 }
03018 ast_setstate(ast, AST_STATE_DIALING);
03019 }
03020 #endif
03021 #ifdef HAVE_PRI
03022 if (p->pri) {
03023 struct pri_sr *sr;
03024 #ifdef SUPPORT_USERUSER
03025 const char *useruser;
03026 #endif
03027 int pridialplan;
03028 int dp_strip;
03029 int prilocaldialplan;
03030 int ldp_strip;
03031 int exclusive;
03032 const char *rr_str;
03033 int redirect_reason;
03034
03035 c = strchr(dest, '/');
03036 if (c) {
03037 c++;
03038 } else {
03039 c = "";
03040 }
03041
03042 l = NULL;
03043 n = NULL;
03044 if (!p->hidecallerid) {
03045 l = ast->cid.cid_num;
03046 if (!p->hidecalleridname) {
03047 n = ast->cid.cid_name;
03048 }
03049 }
03050
03051
03052 if (strlen(c) < p->stripmsd) {
03053 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03054 ast_mutex_unlock(&p->lock);
03055 return -1;
03056 }
03057 if (mysig != SIG_FXSKS) {
03058 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03059 s = strchr(c + p->stripmsd, 'w');
03060 if (s) {
03061 if (strlen(s) > 1)
03062 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03063 else
03064 p->dop.dialstr[0] = '\0';
03065 *s = '\0';
03066 } else {
03067 p->dop.dialstr[0] = '\0';
03068 }
03069 }
03070 if (pri_grab(p, p->pri)) {
03071 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03072 ast_mutex_unlock(&p->lock);
03073 return -1;
03074 }
03075 if (!(p->call = pri_new_call(p->pri->pri))) {
03076 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03077 pri_rel(p->pri);
03078 ast_mutex_unlock(&p->lock);
03079 return -1;
03080 }
03081 if (!(sr = pri_sr_new())) {
03082 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03083 pri_destroycall(p->pri->pri, p->call);
03084 p->call = NULL;
03085 pri_rel(p->pri);
03086 ast_mutex_unlock(&p->lock);
03087 return -1;
03088 }
03089 if (p->bearer || (mysig == SIG_FXSKS)) {
03090 if (p->bearer) {
03091 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);
03092 p->bearer->call = p->call;
03093 } else
03094 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
03095 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03096 }
03097 p->digital = IS_DIGITAL(ast->transfercapability);
03098
03099
03100 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03101 exclusive = 1;
03102 } else {
03103 exclusive = 0;
03104 }
03105
03106 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03107 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03108 (p->digital ? -1 :
03109 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03110 if (p->pri->facilityenable)
03111 pri_facility_enable(p->pri->pri);
03112
03113 if (option_verbose > 2)
03114 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03115 dp_strip = 0;
03116 pridialplan = p->pri->dialplan - 1;
03117 if (pridialplan == -2) {
03118 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03119 dp_strip = strlen(p->pri->internationalprefix);
03120 pridialplan = PRI_INTERNATIONAL_ISDN;
03121 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03122 dp_strip = strlen(p->pri->nationalprefix);
03123 pridialplan = PRI_NATIONAL_ISDN;
03124 } else {
03125 pridialplan = PRI_LOCAL_ISDN;
03126 }
03127 }
03128 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03129
03130 ldp_strip = 0;
03131 prilocaldialplan = p->pri->localdialplan - 1;
03132 if ((l != NULL) && (prilocaldialplan == -2)) {
03133 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03134 ldp_strip = strlen(p->pri->internationalprefix);
03135 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03136 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03137 ldp_strip = strlen(p->pri->nationalprefix);
03138 prilocaldialplan = PRI_NATIONAL_ISDN;
03139 } else {
03140 prilocaldialplan = PRI_LOCAL_ISDN;
03141 }
03142 }
03143 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03144 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03145 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03146 if (!strcasecmp(rr_str, "UNKNOWN"))
03147 redirect_reason = 0;
03148 else if (!strcasecmp(rr_str, "BUSY"))
03149 redirect_reason = 1;
03150 else if (!strcasecmp(rr_str, "NO_REPLY"))
03151 redirect_reason = 2;
03152 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03153 redirect_reason = 15;
03154 else
03155 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03156 } else
03157 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03158 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03159
03160 #ifdef SUPPORT_USERUSER
03161
03162 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03163
03164 if (useruser)
03165 pri_sr_set_useruser(sr, useruser);
03166 #endif
03167
03168 if (pri_setup(p->pri->pri, p->call, sr)) {
03169 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03170 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03171 pri_rel(p->pri);
03172 ast_mutex_unlock(&p->lock);
03173 pri_sr_free(sr);
03174 return -1;
03175 }
03176 pri_sr_free(sr);
03177 ast_setstate(ast, AST_STATE_DIALING);
03178 pri_rel(p->pri);
03179 }
03180 #endif
03181 ast_mutex_unlock(&p->lock);
03182 return 0;
03183 }
03184
03185 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03186 {
03187 struct dahdi_pvt *p = *pvt;
03188
03189 if (p->prev)
03190 p->prev->next = p->next;
03191 if (p->next)
03192 p->next->prev = p->prev;
03193 if (p->use_smdi)
03194 ast_smdi_interface_unref(p->smdi_iface);
03195 ast_mutex_destroy(&p->lock);
03196 dahdi_close_sub(p, SUB_REAL);
03197 if (p->owner)
03198 p->owner->tech_pvt = NULL;
03199 free(p);
03200 *pvt = NULL;
03201 }
03202
03203 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03204 {
03205 int owned = 0;
03206 int i = 0;
03207
03208 if (!now) {
03209 if (cur->owner) {
03210 owned = 1;
03211 }
03212
03213 for (i = 0; i < 3; i++) {
03214 if (cur->subs[i].owner) {
03215 owned = 1;
03216 }
03217 }
03218 if (!owned) {
03219 if (prev) {
03220 prev->next = cur->next;
03221 if (prev->next)
03222 prev->next->prev = prev;
03223 else
03224 ifend = prev;
03225 } else {
03226 iflist = cur->next;
03227 if (iflist)
03228 iflist->prev = NULL;
03229 else
03230 ifend = NULL;
03231 }
03232 destroy_dahdi_pvt(&cur);
03233 }
03234 } else {
03235 if (prev) {
03236 prev->next = cur->next;
03237 if (prev->next)
03238 prev->next->prev = prev;
03239 else
03240 ifend = prev;
03241 } else {
03242 iflist = cur->next;
03243 if (iflist)
03244 iflist->prev = NULL;
03245 else
03246 ifend = NULL;
03247 }
03248 destroy_dahdi_pvt(&cur);
03249 }
03250 return 0;
03251 }
03252
03253 static void destroy_all_channels(void)
03254 {
03255 int x;
03256 struct dahdi_pvt *p, *pl;
03257
03258 while (num_restart_pending) {
03259 usleep(1);
03260 }
03261
03262 ast_mutex_lock(&iflock);
03263
03264 p = iflist;
03265 while (p) {
03266
03267 if (p->cidspill)
03268 ast_free(p->cidspill);
03269 pl = p;
03270 p = p->next;
03271 x = pl->channel;
03272
03273 if (pl)
03274 destroy_dahdi_pvt(&pl);
03275 if (option_verbose > 2)
03276 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03277 }
03278 iflist = NULL;
03279 ifcount = 0;
03280 ast_mutex_unlock(&iflock);
03281 }
03282
03283 #ifdef HAVE_PRI
03284 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03285 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
03286
03287 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03288 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03289
03290 static char *dahdi_send_keypad_facility_descrip =
03291 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03292 " IE over the current channel.\n";
03293 static char *zap_send_keypad_facility_descrip =
03294 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03295 " IE over the current channel.\n";
03296
03297 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
03298 {
03299
03300 struct dahdi_pvt *p;
03301 char *digits = (char *) data;
03302
03303 if (ast_strlen_zero(digits)) {
03304 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
03305 return -1;
03306 }
03307
03308 p = (struct dahdi_pvt *)chan->tech_pvt;
03309
03310 if (!p) {
03311 ast_log(LOG_DEBUG, "Unable to find technology private\n");
03312 return -1;
03313 }
03314
03315 ast_mutex_lock(&p->lock);
03316
03317 if (!p->pri || !p->call) {
03318 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
03319 ast_mutex_unlock(&p->lock);
03320 return -1;
03321 }
03322
03323 if (!pri_grab(p, p->pri)) {
03324 pri_keypad_facility(p->pri->pri, p->call, digits);
03325 pri_rel(p->pri);
03326 } else {
03327 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
03328 ast_mutex_unlock(&p->lock);
03329 return -1;
03330 }
03331
03332 ast_mutex_unlock(&p->lock);
03333
03334 return 0;
03335 }
03336
03337 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03338 {
03339 return send_keypad_facility_exec(chan, data);
03340 }
03341
03342 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03343 {
03344 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);
03345 return send_keypad_facility_exec(chan, data);
03346 }
03347
03348 static int pri_is_up(struct dahdi_pri *pri)
03349 {
03350 int x;
03351 for (x = 0; x < NUM_DCHANS; x++) {
03352 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03353 return 1;
03354 }
03355 return 0;
03356 }
03357
03358 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03359 {
03360 bearer->owner = &inuse;
03361 bearer->realcall = crv;
03362 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03363 if (crv->subs[SUB_REAL].owner)
03364 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03365 crv->bearer = bearer;
03366 crv->call = bearer->call;
03367 crv->pri = pri;
03368 return 0;
03369 }
03370
03371 static char *pri_order(int level)
03372 {
03373 switch (level) {
03374 case 0:
03375 return "Primary";
03376 case 1:
03377 return "Secondary";
03378 case 2:
03379 return "Tertiary";
03380 case 3:
03381 return "Quaternary";
03382 default:
03383 return "<Unknown>";
03384 }
03385 }
03386
03387
03388 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03389 {
03390 int x = -1;
03391
03392 for (x = 0; x < NUM_DCHANS; x++) {
03393 if ((pri->dchans[x] == pri->pri))
03394 break;
03395 }
03396
03397 return pri->fds[x];
03398 }
03399
03400 static int pri_find_dchan(struct dahdi_pri *pri)
03401 {
03402 int oldslot = -1;
03403 struct pri *old;
03404 int newslot = -1;
03405 int x;
03406 old = pri->pri;
03407 for (x = 0; x < NUM_DCHANS; x++) {
03408 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03409 newslot = x;
03410 if (pri->dchans[x] == old) {
03411 oldslot = x;
03412 }
03413 }
03414 if (newslot < 0) {
03415 newslot = 0;
03416 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03417 pri->dchannels[newslot]);
03418 }
03419 if (old && (oldslot != newslot))
03420 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03421 pri->dchannels[oldslot], pri->dchannels[newslot]);
03422 pri->pri = pri->dchans[newslot];
03423 return 0;
03424 }
03425 #endif
03426
03427 #ifdef HAVE_OPENR2
03428 static char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
03429 static char *zap_accept_r2_call_app = "ZapAcceptR2Call";
03430
03431 static char *dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03432 static char *zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03433
03434 static char *dahdi_accept_r2_call_descrip =
03435 " DAHDIAcceptR2Call(): 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 char *zap_accept_r2_call_descrip =
03439 " ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03440 " You can specify yes or no as argument to accept with or without charge.\n";
03441
03442 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
03443 {
03444
03445 openr2_call_mode_t accept_mode;
03446 int res, timeout, maxloops;
03447 struct ast_frame *f;
03448 struct dahdi_pvt *p;
03449 char *parse;
03450 AST_DECLARE_APP_ARGS(args,
03451 AST_APP_ARG(charge);
03452 );
03453
03454 if (ast_strlen_zero(data)) {
03455 ast_log(LOG_DEBUG, "No data sent to application!\n");
03456 return -1;
03457 }
03458
03459 if (chan->tech != &dahdi_tech) {
03460 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
03461 return -1;
03462 }
03463
03464 p = (struct dahdi_pvt *)chan->tech_pvt;
03465 if (!p) {
03466 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
03467 return -1;
03468 }
03469
03470 parse = ast_strdupa(data);
03471 AST_STANDARD_APP_ARGS(args, parse);
03472
03473 if (ast_strlen_zero(args.charge)) {
03474 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
03475 return -1;
03476 }
03477
03478 ast_mutex_lock(&p->lock);
03479 if (!p->mfcr2 || !p->mfcr2call) {
03480 ast_mutex_unlock(&p->lock);
03481 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
03482 return -1;
03483 }
03484
03485 if (p->mfcr2_call_accepted) {
03486 ast_mutex_unlock(&p->lock);
03487 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
03488 return 0;
03489 }
03490 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
03491 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
03492 ast_mutex_unlock(&p->lock);
03493 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03494 return -1;
03495 }
03496 ast_mutex_unlock(&p->lock);
03497
03498 res = 0;
03499 timeout = 100;
03500 maxloops = 50;
03501
03502 while (maxloops > 0) {
03503 maxloops--;
03504 if (ast_check_hangup(chan)) {
03505 break;
03506 }
03507 res = ast_waitfor(chan, timeout);
03508 if (res < 0) {
03509 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
03510 res = -1;
03511 break;
03512 }
03513 if (res == 0) {
03514 continue;
03515 }
03516 f = ast_read(chan);
03517 if (!f) {
03518 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
03519 res = -1;
03520 break;
03521 }
03522 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
03523 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
03524 ast_frfree(f);
03525 res = -1;
03526 break;
03527 }
03528 ast_frfree(f);
03529 ast_mutex_lock(&p->lock);
03530 if (p->mfcr2_call_accepted) {
03531 ast_mutex_unlock(&p->lock);
03532 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
03533 break;
03534 }
03535 ast_mutex_unlock(&p->lock);
03536 }
03537 if (res == -1) {
03538 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03539 }
03540 return res;
03541 }
03542
03543 static int zap_accept_r2_call_exec(struct ast_channel *chan, void *data)
03544 {
03545 return dahdi_accept_r2_call_exec(chan, data);
03546 }
03547
03548 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
03549 {
03550 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
03551 switch (cause) {
03552 case AST_CAUSE_USER_BUSY:
03553 case AST_CAUSE_CALL_REJECTED:
03554 case AST_CAUSE_INTERWORKING:
03555 r2cause = OR2_CAUSE_BUSY_NUMBER;
03556 break;
03557
03558 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
03559 case AST_CAUSE_SWITCH_CONGESTION:
03560 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
03561 break;
03562
03563 case AST_CAUSE_UNALLOCATED:
03564 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
03565 break;
03566
03567 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
03568 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03569 r2cause = OR2_CAUSE_OUT_OF_ORDER;
03570 break;
03571
03572 case AST_CAUSE_NO_ANSWER:
03573 case AST_CAUSE_NO_USER_RESPONSE:
03574 r2cause = OR2_CAUSE_NO_ANSWER;
03575 break;
03576
03577 default:
03578 r2cause = OR2_CAUSE_NORMAL_CLEARING;
03579 break;
03580 }
03581 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n",
03582 r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
03583 return r2cause;
03584 }
03585 #endif
03586
03587 static int dahdi_hangup(struct ast_channel *ast)
03588 {
03589 int res;
03590 int index,x, law;
03591
03592 struct dahdi_pvt *p = ast->tech_pvt;
03593 struct dahdi_pvt *tmp = NULL;
03594 struct dahdi_pvt *prev = NULL;
03595 struct dahdi_params par;
03596
03597 if (option_debug)
03598 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
03599 if (!ast->tech_pvt) {
03600 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03601 return 0;
03602 }
03603
03604 ast_mutex_lock(&p->lock);
03605
03606 index = dahdi_get_index(ast, p, 1);
03607
03608 if (p->sig == SIG_PRI) {
03609 x = 1;
03610 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03611 p->cid_num[0] = '\0';
03612 p->cid_name[0] = '\0';
03613 }
03614
03615 x = 0;
03616 dahdi_confmute(p, 0);
03617 restore_gains(p);
03618 if (p->origcid_num) {
03619 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03620 free(p->origcid_num);
03621 p->origcid_num = NULL;
03622 }
03623 if (p->origcid_name) {
03624 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03625 free(p->origcid_name);
03626 p->origcid_name = NULL;
03627 }
03628 if (p->dsp)
03629 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03630 p->exten[0] = '\0';
03631
03632 if (option_debug)
03633 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03634 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03635 p->ignoredtmf = 0;
03636
03637 if (index > -1) {
03638
03639 p->subs[index].owner = NULL;
03640 p->subs[index].needanswer = 0;
03641 p->subs[index].needflash = 0;
03642 p->subs[index].needringing = 0;
03643 p->subs[index].needbusy = 0;
03644 p->subs[index].needcongestion = 0;
03645 p->subs[index].linear = 0;
03646 p->subs[index].needcallerid = 0;
03647 p->polarity = POLARITY_IDLE;
03648 dahdi_setlinear(p->subs[index].dfd, 0);
03649 if (index == SUB_REAL) {
03650 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03651 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
03652 if (p->subs[SUB_CALLWAIT].inthreeway) {
03653
03654 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
03655
03656 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03657 unalloc_sub(p, SUB_CALLWAIT);
03658 p->owner = NULL;
03659 } else {
03660
03661 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03662 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03663 unalloc_sub(p, SUB_THREEWAY);
03664 if (p->subs[SUB_REAL].inthreeway) {
03665
03666
03667 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03668 p->owner = p->subs[SUB_REAL].owner;
03669 } else {
03670
03671 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03672 p->owner = NULL;
03673 }
03674 p->subs[SUB_REAL].inthreeway = 0;
03675 }
03676 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03677
03678 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03679 unalloc_sub(p, SUB_CALLWAIT);
03680 p->owner = p->subs[SUB_REAL].owner;
03681 if (p->owner->_state != AST_STATE_UP)
03682 p->subs[SUB_REAL].needanswer = 1;
03683 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03684 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03685 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03686 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03687 unalloc_sub(p, SUB_THREEWAY);
03688 if (p->subs[SUB_REAL].inthreeway) {
03689
03690
03691 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03692 p->owner = p->subs[SUB_REAL].owner;
03693 } else {
03694
03695 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03696 p->owner = NULL;
03697 }
03698 p->subs[SUB_REAL].inthreeway = 0;
03699 }
03700 } else if (index == SUB_CALLWAIT) {
03701
03702 if (p->subs[SUB_CALLWAIT].inthreeway) {
03703
03704
03705 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03706 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03707 S_OR(p->mohsuggest, NULL),
03708 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03709 }
03710 p->subs[SUB_THREEWAY].inthreeway = 0;
03711
03712 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03713 unalloc_sub(p, SUB_THREEWAY);
03714 } else
03715 unalloc_sub(p, SUB_CALLWAIT);
03716 } else if (index == SUB_THREEWAY) {
03717 if (p->subs[SUB_CALLWAIT].inthreeway) {
03718
03719
03720 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03721 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03722 S_OR(p->mohsuggest, NULL),
03723 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03724 }
03725 p->subs[SUB_CALLWAIT].inthreeway = 0;
03726 }
03727 p->subs[SUB_REAL].inthreeway = 0;
03728
03729
03730 unalloc_sub(p, SUB_THREEWAY);
03731 } else {
03732
03733 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03734 }
03735 }
03736
03737 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03738 p->owner = NULL;
03739 p->ringt = 0;
03740 p->distinctivering = 0;
03741 p->confirmanswer = 0;
03742 p->cidrings = 1;
03743 p->outgoing = 0;
03744 p->digital = 0;
03745 p->faxhandled = 0;
03746 p->pulsedial = 0;
03747 p->onhooktime = time(NULL);
03748 #ifdef HAVE_PRI
03749 p->proceeding = 0;
03750 p->dialing = 0;
03751 p->progress = 0;
03752 p->alerting = 0;
03753 p->setup_ack = 0;
03754 #endif
03755 if (p->dsp) {
03756 ast_dsp_free(p->dsp);
03757 p->dsp = NULL;
03758 }
03759
03760 law = DAHDI_LAW_DEFAULT;
03761 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03762 if (res < 0)
03763 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03764
03765 #ifdef HAVE_OPENR2
03766 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
03767 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
03768 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
03769 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
03770 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
03771 } else {
03772 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
03773 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
03774 openr2_call_disconnect_cause_t r2cause = r2cause_user
03775 ? dahdi_ast_cause_to_r2_cause(r2cause_user)
03776 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
03777 dahdi_r2_disconnect_call(p, r2cause);
03778 }
03779 } else if (p->mfcr2call) {
03780 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
03781 p->mfcr2call = 0;
03782 }
03783 #endif
03784 #ifdef HAVE_PRI
03785 if (p->pri) {
03786 #ifdef SUPPORT_USERUSER
03787 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03788 #endif
03789
03790
03791 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03792 if (!pri_grab(p, p->pri)) {
03793 if (p->alreadyhungup) {
03794 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
03795
03796 #ifdef SUPPORT_USERUSER
03797 pri_call_set_useruser(p->call, useruser);
03798 #endif
03799
03800 pri_hangup(p->pri->pri, p->call, -1);
03801 p->call = NULL;
03802 if (p->bearer)
03803 p->bearer->call = NULL;
03804 } else {
03805 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03806 int icause = ast->hangupcause ? ast->hangupcause : -1;
03807 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03808
03809 #ifdef SUPPORT_USERUSER
03810 pri_call_set_useruser(p->call, useruser);
03811 #endif
03812
03813 p->alreadyhungup = 1;
03814 if (p->bearer)
03815 p->bearer->alreadyhungup = 1;
03816 if (cause) {
03817 if (atoi(cause))
03818 icause = atoi(cause);
03819 }
03820 pri_hangup(p->pri->pri, p->call, icause);
03821 }
03822 if (res < 0)
03823 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03824 pri_rel(p->pri);
03825 } else {
03826 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03827 res = -1;
03828 }
03829 } else {
03830 if (p->bearer)
03831 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03832 p->call = NULL;
03833 res = 0;
03834 }
03835 }
03836 #endif
03837 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
03838 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03839 if (res < 0) {
03840 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03841 }
03842 switch (p->sig) {
03843 case SIG_FXOGS:
03844 case SIG_FXOLS:
03845 case SIG_FXOKS:
03846 memset(&par, 0, sizeof(par));
03847 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03848 if (!res) {
03849 #if 0
03850 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03851 #endif
03852
03853 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03854 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03855 else
03856 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03857 }
03858 break;
03859 case SIG_FXSGS:
03860 case SIG_FXSLS:
03861 case SIG_FXSKS:
03862
03863
03864 if (ast->_state != AST_STATE_RESERVED) {
03865 time(&p->guardtime);
03866 p->guardtime += 2;
03867 }
03868 break;
03869 default:
03870 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03871 }
03872 if (p->cidspill)
03873 free(p->cidspill);
03874 if (p->sig)
03875 dahdi_disable_ec(p);
03876 x = 0;
03877 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03878 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03879 p->didtdd = 0;
03880 p->cidspill = NULL;
03881 p->callwaitcas = 0;
03882 p->callwaiting = p->permcallwaiting;
03883 p->hidecallerid = p->permhidecallerid;
03884 p->dialing = 0;
03885 p->rdnis[0] = '\0';
03886 update_conf(p);
03887 reset_conf(p);
03888
03889 if (p->sig == SIG_PRI) {
03890 x = 0;
03891 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03892 }
03893 #ifdef HAVE_PRI
03894 if (p->bearer) {
03895 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03896
03897
03898 update_conf(p->bearer);
03899 reset_conf(p->bearer);
03900 p->bearer->owner = NULL;
03901 p->bearer->realcall = NULL;
03902 p->bearer = NULL;
03903 p->subs[SUB_REAL].dfd = -1;
03904 p->pri = NULL;
03905 }
03906 #endif
03907 if (num_restart_pending == 0)
03908 restart_monitor();
03909 }
03910
03911 p->callwaitingrepeat = 0;
03912 p->cidcwexpire = 0;
03913 p->oprmode = 0;
03914 ast->tech_pvt = NULL;
03915 ast_mutex_unlock(&p->lock);
03916 ast_module_unref(ast_module_info->self);
03917 if (option_verbose > 2)
03918 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03919
03920 ast_mutex_lock(&iflock);
03921
03922 if (p->restartpending) {
03923 num_restart_pending--;
03924 }
03925
03926 tmp = iflist;
03927 prev = NULL;
03928 if (p->destroy) {
03929 while (tmp) {
03930 if (tmp == p) {
03931 destroy_channel(prev, tmp, 0);
03932 break;
03933 } else {
03934 prev = tmp;
03935 tmp = tmp->next;
03936 }
03937 }
03938 }
03939 ast_mutex_unlock(&iflock);
03940 return 0;
03941 }
03942
03943 static int dahdi_answer(struct ast_channel *ast)
03944 {
03945 struct dahdi_pvt *p = ast->tech_pvt;
03946 int res = 0;
03947 int index;
03948 int oldstate = ast->_state;
03949 ast_setstate(ast, AST_STATE_UP);
03950 ast_mutex_lock(&p->lock);
03951 index = dahdi_get_index(ast, p, 0);
03952 if (index < 0)
03953 index = SUB_REAL;
03954
03955 if ((p->radio || (p->oprmode < 0))) {
03956 ast_mutex_unlock(&p->lock);
03957 return 0;
03958 }
03959 switch (p->sig) {
03960 case SIG_FXSLS:
03961 case SIG_FXSGS:
03962 case SIG_FXSKS:
03963 p->ringt = 0;
03964
03965 case SIG_EM:
03966 case SIG_EM_E1:
03967 case SIG_EMWINK:
03968 case SIG_FEATD:
03969 case SIG_FEATDMF:
03970 case SIG_FEATDMF_TA:
03971 case SIG_E911:
03972 case SIG_FGC_CAMA:
03973 case SIG_FGC_CAMAMF:
03974 case SIG_FEATB:
03975 case SIG_SF:
03976 case SIG_SFWINK:
03977 case SIG_SF_FEATD:
03978 case SIG_SF_FEATDMF:
03979 case SIG_SF_FEATB:
03980 case SIG_FXOLS:
03981 case SIG_FXOGS:
03982 case SIG_FXOKS:
03983
03984 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03985 if (p->hanguponpolarityswitch) {
03986 gettimeofday(&p->polaritydelaytv, NULL);
03987 }
03988 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03989 tone_zone_play_tone(p->subs[index].dfd, -1);
03990 p->dialing = 0;
03991 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03992 if (oldstate == AST_STATE_RINGING) {
03993 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03994 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03995 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03996 p->owner = p->subs[SUB_REAL].owner;
03997 }
03998 }
03999 if (p->sig & __DAHDI_SIG_FXS) {
04000 dahdi_enable_ec(p);
04001 dahdi_train_ec(p);
04002 }
04003 break;
04004 #ifdef HAVE_PRI
04005 case SIG_PRI:
04006
04007 if (!pri_grab(p, p->pri)) {
04008 p->proceeding = 1;
04009 p->dialing = 0;
04010 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04011 pri_rel(p->pri);
04012 } else {
04013 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04014 res = -1;
04015 }
04016 break;
04017 #endif
04018 #ifdef HAVE_OPENR2
04019 case SIG_MFCR2:
04020 if (!p->mfcr2_accept_on_offer) {
04021
04022
04023 if (p->mfcr2_charge_calls) {
04024 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
04025 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04026 } else {
04027 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
04028 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04029 }
04030 } else {
04031 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04032 res = dahdi_r2_answer(p);
04033 }
04034 break;
04035 #endif
04036 case 0:
04037 ast_mutex_unlock(&p->lock);
04038 return 0;
04039 default:
04040 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04041 res = -1;
04042 }
04043 ast_mutex_unlock(&p->lock);
04044 return res;
04045 }
04046
04047 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04048 {
04049 char *cp;
04050 signed char *scp;
04051 int x;
04052 int index;
04053 struct dahdi_pvt *p = chan->tech_pvt, *pp;
04054 struct oprmode *oprmode;
04055
04056
04057
04058 if (!data || (datalen < 1)) {
04059 errno = EINVAL;
04060 return -1;
04061 }
04062
04063 switch (option) {
04064 case AST_OPTION_TXGAIN:
04065 scp = (signed char *) data;
04066 index = dahdi_get_index(chan, p, 0);
04067 if (index < 0) {
04068 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04069 return -1;
04070 }
04071 if (option_debug)
04072 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04073 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
04074 case AST_OPTION_RXGAIN:
04075 scp = (signed char *) data;
04076 index = dahdi_get_index(chan, p, 0);
04077 if (index < 0) {
04078 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04079 return -1;
04080 }
04081 if (option_debug)
04082 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04083 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
04084 case AST_OPTION_TONE_VERIFY:
04085 if (!p->dsp)
04086 break;
04087 cp = (char *) data;
04088 switch (*cp) {
04089 case 1:
04090 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04091 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
04092 break;
04093 case 2:
04094 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04095 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
04096 break;
04097 default:
04098 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04099 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
04100 break;
04101 }
04102 break;
04103 case AST_OPTION_TDD:
04104
04105 cp = (char *) data;
04106 p->mate = 0;
04107 if (!*cp) {
04108 if (option_debug)
04109 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04110 if (p->tdd)
04111 tdd_free(p->tdd);
04112 p->tdd = 0;
04113 break;
04114 }
04115 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
04116 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04117 dahdi_disable_ec(p);
04118
04119 if (!p->didtdd) {
04120 unsigned char mybuf[41000];
04121 unsigned char *buf;
04122 int size, res, fd, len;
04123 struct pollfd fds[1];
04124
04125 buf = mybuf;
04126 memset(buf, 0x7f, sizeof(mybuf));
04127 ast_tdd_gen_ecdisa(buf + 16000, 16000);
04128 len = 40000;
04129 index = dahdi_get_index(chan, p, 0);
04130 if (index < 0) {
04131 ast_log(LOG_WARNING, "No index in TDD?\n");
04132 return -1;
04133 }
04134 fd = p->subs[index].dfd;
04135 while (len) {
04136 if (ast_check_hangup(chan))
04137 return -1;
04138 size = len;
04139 if (size > READ_SIZE)
04140 size = READ_SIZE;
04141 fds[0].fd = fd;
04142 fds[0].events = POLLPRI | POLLOUT;
04143 fds[0].revents = 0;
04144 res = poll(fds, 1, -1);
04145 if (!res) {
04146 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
04147 continue;
04148 }
04149
04150 if (fds[0].revents & POLLPRI)
04151 return -1;
04152 if (!(fds[0].revents & POLLOUT)) {
04153 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
04154 continue;
04155 }
04156 res = write(fd, buf, size);
04157 if (res != size) {
04158 if (res == -1) return -1;
04159 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04160 break;
04161 }
04162 len -= size;
04163 buf += size;
04164 }
04165 p->didtdd = 1;
04166 }
04167 if (*cp == 2) {
04168 if (p->tdd)
04169 tdd_free(p->tdd);
04170 p->tdd = 0;
04171 p->mate = 1;
04172 break;
04173 }
04174 if (!p->tdd) {
04175 p->tdd = tdd_new();
04176 }
04177 break;
04178 case AST_OPTION_RELAXDTMF:
04179 if (!p->dsp)
04180 break;
04181 cp = (char *) data;
04182 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04183 *cp ? "ON" : "OFF", (int) *cp, chan->name);
04184 p->dtmfrelax = 0;
04185 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
04186 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04187 break;
04188 case AST_OPTION_AUDIO_MODE:
04189 cp = (char *) data;
04190 if (!*cp) {
04191 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04192 x = 0;
04193 dahdi_disable_ec(p);
04194 } else {
04195 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04196 x = 1;
04197 }
04198 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04199 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04200 break;
04201 case AST_OPTION_OPRMODE:
04202 oprmode = (struct oprmode *) data;
04203 pp = oprmode->peer->tech_pvt;
04204 p->oprmode = pp->oprmode = 0;
04205
04206 p->oprpeer = pp;
04207 pp->oprpeer = p;
04208
04209 if (oprmode->mode)
04210 {
04211 pp->oprmode = oprmode->mode;
04212 p->oprmode = -oprmode->mode;
04213 }
04214 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
04215 oprmode->mode, chan->name,oprmode->peer->name);;
04216 break;
04217 case AST_OPTION_ECHOCAN:
04218 cp = (char *) data;
04219 if (*cp) {
04220 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
04221 dahdi_enable_ec(p);
04222 } else {
04223 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
04224 dahdi_disable_ec(p);
04225 }
04226 break;
04227 }
04228 errno = 0;
04229
04230 return 0;
04231 }
04232
04233 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
04234 {
04235 struct dahdi_pvt *p = chan->tech_pvt;
04236
04237 if (!strcasecmp(data, "rxgain")) {
04238 ast_mutex_lock(&p->lock);
04239 snprintf(buf, len, "%f", p->rxgain);
04240 ast_mutex_unlock(&p->lock);
04241 } else if (!strcasecmp(data, "txgain")) {
04242 ast_mutex_lock(&p->lock);
04243 snprintf(buf, len, "%f", p->txgain);
04244 ast_mutex_unlock(&p->lock);
04245 } else {
04246 ast_copy_string(buf, "", len);
04247 }
04248 return 0;
04249 }
04250
04251
04252 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04253 {
04254
04255 int x;
04256 int hasslaves;
04257 if (!master)
04258 return;
04259 if (needlock) {
04260 ast_mutex_lock(&master->lock);
04261 if (slave) {
04262 while (ast_mutex_trylock(&slave->lock)) {
04263 DEADLOCK_AVOIDANCE(&master->lock);
04264 }
04265 }
04266 }
04267 hasslaves = 0;
04268 for (x = 0; x < MAX_SLAVES; x++) {
04269 if (master->slaves[x]) {
04270 if (!slave || (master->slaves[x] == slave)) {
04271
04272 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04273 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04274 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04275 master->slaves[x]->master = NULL;
04276 master->slaves[x] = NULL;
04277 } else
04278 hasslaves = 1;
04279 }
04280 if (!hasslaves)
04281 master->inconference = 0;
04282 }
04283 if (!slave) {
04284 if (master->master) {
04285
04286 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04287 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04288 hasslaves = 0;
04289 for (x = 0; x < MAX_SLAVES; x++) {
04290 if (master->master->slaves[x] == master)
04291 master->master->slaves[x] = NULL;
04292 else if (master->master->slaves[x])
04293 hasslaves = 1;
04294 }
04295 if (!hasslaves)
04296 master->master->inconference = 0;
04297 }
04298 master->master = NULL;
04299 }
04300 update_conf(master);
04301 if (needlock) {
04302 if (slave)
04303 ast_mutex_unlock(&slave->lock);
04304 ast_mutex_unlock(&master->lock);
04305 }
04306 }
04307
04308 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04309 int x;
04310 if (!slave || !master) {
04311 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04312 return;
04313 }
04314 for (x = 0; x < MAX_SLAVES; x++) {
04315 if (!master->slaves[x]) {
04316 master->slaves[x] = slave;
04317 break;
04318 }
04319 }
04320 if (x >= MAX_SLAVES) {
04321 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04322 master->slaves[MAX_SLAVES - 1] = slave;
04323 }
04324 if (slave->master)
04325 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04326 slave->master = master;
04327
04328 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04329 }
04330
04331 static void disable_dtmf_detect(struct dahdi_pvt *p)
04332 {
04333 #ifdef DAHDI_TONEDETECT
04334 int val;
04335 #endif
04336
04337 p->ignoredtmf = 1;
04338
04339 #ifdef DAHDI_TONEDETECT
04340 val = 0;
04341 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04342 #endif
04343 if (!p->hardwaredtmf && p->dsp) {
04344 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04345 ast_dsp_set_features(p->dsp, p->dsp_features);
04346 }
04347 }
04348
04349 static void enable_dtmf_detect(struct dahdi_pvt *p)
04350 {
04351 #ifdef DAHDI_TONEDETECT
04352 int val;
04353 #endif
04354
04355 if (p->channel == CHAN_PSEUDO)
04356 return;
04357
04358 p->ignoredtmf = 0;
04359
04360 #ifdef DAHDI_TONEDETECT
04361 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04362 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04363 #endif
04364 if (!p->hardwaredtmf && p->dsp) {
04365 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04366 ast_dsp_set_features(p->dsp, p->dsp_features);
04367 }
04368 }
04369
04370 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)
04371 {
04372 struct ast_channel *who;
04373 struct dahdi_pvt *p0, *p1, *op0, *op1;
04374 struct dahdi_pvt *master = NULL, *slave = NULL;
04375 struct ast_frame *f;
04376 int inconf = 0;
04377 int nothingok = 1;
04378 int ofd0, ofd1;
04379 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04380 int os0 = -1, os1 = -1;
04381 int priority = 0;
04382 struct ast_channel *oc0, *oc1;
04383 enum ast_bridge_result res;
04384
04385 #ifdef PRI_2BCT
04386 int triedtopribridge = 0;
04387 q931_call *q931c0 = NULL, *q931c1 = NULL;
04388 #endif
04389
04390
04391
04392
04393
04394
04395 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04396 return AST_BRIDGE_FAILED_NOWARN;
04397
04398 ast_mutex_lock(&c0->lock);
04399 while (ast_mutex_trylock(&c1->lock)) {
04400 DEADLOCK_AVOIDANCE(&c0->lock);
04401 }
04402
04403 p0 = c0->tech_pvt;
04404 p1 = c1->tech_pvt;
04405
04406 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04407 ast_mutex_unlock(&c0->lock);
04408 ast_mutex_unlock(&c1->lock);
04409 return AST_BRIDGE_FAILED_NOWARN;
04410 }
04411
04412 oi0 = dahdi_get_index(c0, p0, 0);
04413 oi1 = dahdi_get_index(c1, p1, 0);
04414 if ((oi0 < 0) || (oi1 < 0)) {
04415 ast_mutex_unlock(&c0->lock);
04416 ast_mutex_unlock(&c1->lock);
04417 return AST_BRIDGE_FAILED;
04418 }
04419
04420 op0 = p0 = c0->tech_pvt;
04421 op1 = p1 = c1->tech_pvt;
04422 ofd0 = c0->fds[0];
04423 ofd1 = c1->fds[0];
04424 oc0 = p0->owner;
04425 oc1 = p1->owner;
04426
04427 if (ast_mutex_trylock(&p0->lock)) {
04428
04429 ast_mutex_unlock(&c0->lock);
04430 ast_mutex_unlock(&c1->lock);
04431 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04432 return AST_BRIDGE_RETRY;
04433 }
04434 if (ast_mutex_trylock(&p1->lock)) {
04435
04436 ast_mutex_unlock(&p0->lock);
04437 ast_mutex_unlock(&c0->lock);
04438 ast_mutex_unlock(&c1->lock);
04439 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04440 return AST_BRIDGE_RETRY;
04441 }
04442
04443 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04444 if (p0->owner && p1->owner) {
04445
04446 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04447 master = p0;
04448 slave = p1;
04449 inconf = 1;
04450 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04451 master = p1;
04452 slave = p0;
04453 inconf = 1;
04454 } else {
04455 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04456 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04457 p0->channel,
04458 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04459 p0->subs[SUB_REAL].inthreeway, p0->channel,
04460 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04461 p1->subs[SUB_REAL].inthreeway);
04462 }
04463 nothingok = 0;
04464 }
04465 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04466 if (p1->subs[SUB_THREEWAY].inthreeway) {
04467 master = p1;
04468 slave = p0;
04469 nothingok = 0;
04470 }
04471 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04472 if (p0->subs[SUB_THREEWAY].inthreeway) {
04473 master = p0;
04474 slave = p1;
04475 nothingok = 0;
04476 }
04477 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04478
04479
04480 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04481 master = p1;
04482 slave = p0;
04483 nothingok = 0;
04484 }
04485 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04486
04487 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04488 master = p0;
04489 slave = p1;
04490 nothingok = 0;
04491 }
04492 }
04493 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
04494 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04495 if (master && slave) {
04496
04497
04498
04499 if ((oi1 == SUB_THREEWAY) &&
04500 p1->subs[SUB_THREEWAY].inthreeway &&
04501 p1->subs[SUB_REAL].owner &&
04502 p1->subs[SUB_REAL].inthreeway &&
04503 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04504 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04505 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04506 os1 = p1->subs[SUB_REAL].owner->_state;
04507 } else {
04508 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04509 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04510 }
04511 if ((oi0 == SUB_THREEWAY) &&
04512 p0->subs[SUB_THREEWAY].inthreeway &&
04513 p0->subs[SUB_REAL].owner &&
04514 p0->subs[SUB_REAL].inthreeway &&
04515 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04516 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04517 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04518 os0 = p0->subs[SUB_REAL].owner->_state;
04519 } else {
04520 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04521 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04522 }
04523 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04524 if (!p0->echocanbridged || !p1->echocanbridged) {
04525
04526 dahdi_disable_ec(p0);
04527 dahdi_disable_ec(p1);
04528 }
04529 }
04530 dahdi_link(slave, master);
04531 master->inconference = inconf;
04532 } else if (!nothingok)
04533 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04534
04535 update_conf(p0);
04536 update_conf(p1);
04537 t0 = p0->subs[SUB_REAL].inthreeway;
04538 t1 = p1->subs[SUB_REAL].inthreeway;
04539
04540 ast_mutex_unlock(&p0->lock);
04541 ast_mutex_unlock(&p1->lock);
04542
04543 ast_mutex_unlock(&c0->lock);
04544 ast_mutex_unlock(&c1->lock);
04545
04546
04547 if ((!master || !slave) && !nothingok) {
04548 dahdi_enable_ec(p0);
04549 dahdi_enable_ec(p1);
04550 return AST_BRIDGE_FAILED;
04551 }
04552
04553 if (option_verbose > 2)
04554 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
04555
04556 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04557 disable_dtmf_detect(op0);
04558
04559 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04560 disable_dtmf_detect(op1);
04561
04562 for (;;) {
04563 struct ast_channel *c0_priority[2] = {c0, c1};
04564 struct ast_channel *c1_priority[2] = {c1, c0};
04565
04566
04567
04568 ast_mutex_lock(&c0->lock);
04569 while (ast_mutex_trylock(&c1->lock)) {
04570 DEADLOCK_AVOIDANCE(&c0->lock);
04571 }
04572
04573 p0 = c0->tech_pvt;
04574 p1 = c1->tech_pvt;
04575
04576 if (op0 == p0)
04577 i0 = dahdi_get_index(c0, p0, 1);
04578 if (op1 == p1)
04579 i1 = dahdi_get_index(c1, p1, 1);
04580 ast_mutex_unlock(&c0->lock);
04581 ast_mutex_unlock(&c1->lock);
04582
04583 if (!timeoutms ||
04584 (op0 != p0) ||
04585 (op1 != p1) ||
04586 (ofd0 != c0->fds[0]) ||
04587 (ofd1 != c1->fds[0]) ||
04588 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04589 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04590 (oc0 != p0->owner) ||
04591 (oc1 != p1->owner) ||
04592 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04593 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04594 (oi0 != i0) ||
04595 (oi1 != i1)) {
04596 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04597 op0->channel, oi0, op1->channel, oi1);
04598 res = AST_BRIDGE_RETRY;
04599 goto return_from_bridge;
04600 }
04601
04602 #ifdef PRI_2BCT
04603 q931c0 = p0->call;
04604 q931c1 = p1->call;
04605 if (p0->transfer && p1->transfer
04606 && q931c0 && q931c1
04607 && !triedtopribridge) {
04608 pri_channel_bridge(q931c0, q931c1);
04609 triedtopribridge = 1;
04610 }
04611 #endif
04612
04613 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04614 if (!who) {
04615 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
04616 continue;
04617 }
04618 f = ast_read(who);
04619 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04620 *fo = f;
04621 *rc = who;
04622 res = AST_BRIDGE_COMPLETE;
04623 goto return_from_bridge;
04624 }
04625 if (f->frametype == AST_FRAME_DTMF) {
04626 if ((who == c0) && p0->pulsedial) {
04627 ast_write(c1, f);
04628 } else if ((who == c1) && p1->pulsedial) {
04629 ast_write(c0, f);
04630 } else {
04631 *fo = f;
04632 *rc = who;
04633 res = AST_BRIDGE_COMPLETE;
04634 goto return_from_bridge;
04635 }
04636 }
04637 ast_frfree(f);
04638
04639
04640 priority = !priority;
04641 }
04642
04643 return_from_bridge:
04644 if (op0 == p0)
04645 dahdi_enable_ec(p0);
04646
04647 if (op1 == p1)
04648 dahdi_enable_ec(p1);
04649
04650 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04651 enable_dtmf_detect(op0);
04652
04653 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04654 enable_dtmf_detect(op1);
04655
04656 dahdi_unlink(slave, master, 1);
04657
04658 return res;
04659 }
04660
04661 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04662 {
04663 struct dahdi_pvt *p = newchan->tech_pvt;
04664 int x;
04665 ast_mutex_lock(&p->lock);
04666 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
04667 if (p->owner == oldchan) {
04668 p->owner = newchan;
04669 }
04670 for (x = 0; x < 3; x++)
04671 if (p->subs[x].owner == oldchan) {
04672 if (!x)
04673 dahdi_unlink(NULL, p, 0);
04674 p->subs[x].owner = newchan;
04675 }
04676 if (newchan->_state == AST_STATE_RINGING)
04677 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04678 update_conf(p);
04679 ast_mutex_unlock(&p->lock);
04680 return 0;
04681 }
04682
04683 static int dahdi_ring_phone(struct dahdi_pvt *p)
04684 {
04685 int x;
04686 int res;
04687
04688 x = 0;
04689 x = DAHDI_ONHOOK;
04690 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04691 do {
04692 x = DAHDI_RING;
04693 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04694 if (res) {
04695 switch (errno) {
04696 case EBUSY:
04697 case EINTR:
04698
04699 usleep(10000);
04700 continue;
04701 case EINPROGRESS:
04702 res = 0;
04703 break;
04704 default:
04705 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04706 res = 0;
04707 }
04708 }
04709 } while (res);
04710 return res;
04711 }
04712
04713 static void *ss_thread(void *data);
04714
04715 static int attempt_transfer(struct dahdi_pvt *p)
04716 {
04717
04718
04719
04720 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04721
04722
04723 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04724 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04725 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04726 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04727 }
04728 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04729 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04730 }
04731 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04732 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04733 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04734 return -1;
04735 }
04736
04737 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04738 unalloc_sub(p, SUB_THREEWAY);
04739 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04740 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04741 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04742 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04743 }
04744 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04745 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04746 }
04747 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04748 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04749 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04750 return -1;
04751 }
04752
04753 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04754 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
04755 unalloc_sub(p, SUB_THREEWAY);
04756
04757 return 1;
04758 } else {
04759 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04760 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04761 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04762 return -1;
04763 }
04764 return 0;
04765 }
04766
04767 static int check_for_conference(struct dahdi_pvt *p)
04768 {
04769 struct dahdi_confinfo ci;
04770
04771 if (p->master || (p->confno > -1))
04772 return 0;
04773 memset(&ci, 0, sizeof(ci));
04774 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04775 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04776 return 0;
04777 }
04778
04779
04780
04781 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04782 if (option_verbose > 2)
04783 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
04784 return 1;
04785 }
04786 return 0;
04787 }
04788
04789 static int get_alarms(struct dahdi_pvt *p)
04790 {
04791 int res;
04792 struct dahdi_spaninfo zi;
04793 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04794
04795
04796
04797
04798
04799 struct dahdi_params params;
04800 #endif
04801
04802 memset(&zi, 0, sizeof(zi));
04803 zi.spanno = p->span;
04804
04805
04806 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
04807 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04808 return 0;
04809 }
04810 if (zi.alarms != DAHDI_ALARM_NONE)
04811 return zi.alarms;
04812 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04813
04814 memset(¶ms, 0, sizeof(params));
04815 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04816 return params.chan_alarms;
04817
04818 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04819 #endif
04820 return DAHDI_ALARM_NONE;
04821 }
04822
04823 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04824 {
04825 struct dahdi_pvt *p = ast->tech_pvt;
04826 struct ast_frame *f = *dest;
04827
04828 if (option_debug)
04829 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04830
04831 if (p->confirmanswer) {
04832 if (option_debug)
04833 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04834
04835
04836 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04837 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04838 *dest = &p->subs[index].f;
04839
04840 p->confirmanswer = 0;
04841 } else if (p->callwaitcas) {
04842 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04843 if (option_debug)
04844 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04845 if (p->cidspill)
04846 free(p->cidspill);
04847 send_cwcidspill(p);
04848 }
04849 if ((f->subclass != 'm') && (f->subclass != 'u'))
04850 p->callwaitcas = 0;
04851 p->subs[index].f.frametype = AST_FRAME_NULL;
04852 p->subs[index].f.subclass = 0;
04853 *dest = &p->subs[index].f;
04854 } else if (f->subclass == 'f') {
04855
04856 if ((p->callprogress & 0x6) && !p->faxhandled) {
04857 p->faxhandled = 1;
04858 if (strcmp(ast->exten, "fax")) {
04859 const char *target_context = S_OR(ast->macrocontext, ast->context);
04860
04861
04862
04863
04864
04865 ast_mutex_unlock(&p->lock);
04866 ast_channel_unlock(ast);
04867 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04868 ast_channel_lock(ast);
04869 ast_mutex_lock(&p->lock);
04870 if (option_verbose > 2)
04871 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04872
04873 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04874 if (ast_async_goto(ast, target_context, "fax", 1))
04875 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04876 } else {
04877 ast_channel_lock(ast);
04878 ast_mutex_lock(&p->lock);
04879 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04880 }
04881 } else if (option_debug)
04882 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04883 } else if (option_debug)
04884 ast_log(LOG_DEBUG, "Fax already handled\n");
04885 dahdi_confmute(p, 0);
04886 p->subs[index].f.frametype = AST_FRAME_NULL;
04887 p->subs[index].f.subclass = 0;
04888 *dest = &p->subs[index].f;
04889 } else if (f->subclass == 'm') {
04890
04891 dahdi_confmute(p, 1);
04892 p->subs[index].f.frametype = AST_FRAME_NULL;
04893 p->subs[index].f.subclass = 0;
04894 *dest = &p->subs[index].f;
04895 } else if (f->subclass == 'u') {
04896
04897 dahdi_confmute(p, 0);
04898 p->subs[index].f.frametype = AST_FRAME_NULL;
04899 p->subs[index].f.subclass = 0;
04900 *dest = &p->subs[index].f;
04901 } else
04902 dahdi_confmute(p, 0);
04903 }
04904
04905 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04906 {
04907 const char *alarm_str = alarm2str(alarms);
04908
04909
04910
04911 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04912 p->unknown_alarm = 1;
04913 return;
04914 } else {
04915 p->unknown_alarm = 0;
04916 }
04917
04918 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04919 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04920 "Alarm: %s\r\n"
04921 "Channel: %d\r\n",
04922 alarm_str, p->channel);
04923 }
04924
04925 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04926 {
04927 int res, x;
04928 int index, mysig;
04929 char *c;
04930 struct dahdi_pvt *p = ast->tech_pvt;
04931 pthread_t threadid;
04932 pthread_attr_t attr;
04933 struct ast_channel *chan;
04934 struct ast_frame *f;
04935
04936 index = dahdi_get_index(ast, p, 0);
04937 mysig = p->sig;
04938 if (p->outsigmod > -1)
04939 mysig = p->outsigmod;
04940 p->subs[index].f.frametype = AST_FRAME_NULL;
04941 p->subs[index].f.subclass = 0;
04942 p->subs[index].f.datalen = 0;
04943 p->subs[index].f.samples = 0;
04944 p->subs[index].f.mallocd = 0;
04945 p->subs[index].f.offset = 0;
04946 p->subs[index].f.src = "dahdi_handle_event";
04947 p->subs[index].f.data = NULL;
04948 f = &p->subs[index].f;
04949
04950 if (index < 0)
04951 return &p->subs[index].f;
04952 if (p->fake_event) {
04953 res = p->fake_event;
04954 p->fake_event = 0;
04955 } else
04956 res = dahdi_get_event(p->subs[index].dfd);
04957
04958 if (option_debug)
04959 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04960
04961 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04962 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04963
04964 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04965 #ifdef HAVE_PRI
04966 if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04967
04968 } else {
04969 #endif
04970 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04971 p->subs[index].f.subclass = res & 0xff;
04972 #ifdef HAVE_PRI
04973 }
04974 #endif
04975 dahdi_handle_dtmfup(ast, index, &f);
04976 return f;
04977 }
04978
04979 if (res & DAHDI_EVENT_DTMFDOWN) {
04980 if (option_debug)
04981 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04982
04983 dahdi_confmute(p, 1);
04984 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04985 p->subs[index].f.subclass = res & 0xff;
04986 return &p->subs[index].f;
04987 }
04988
04989 switch (res) {
04990 #ifdef DAHDI_EVENT_EC_DISABLED
04991 case DAHDI_EVENT_EC_DISABLED:
04992 if (option_verbose > 2)
04993 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04994 p->echocanon = 0;
04995 break;
04996 #endif
04997 case DAHDI_EVENT_BITSCHANGED:
04998 #ifdef HAVE_OPENR2
04999 if (p->sig != SIG_MFCR2) {
05000 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05001 } else {
05002 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05003 openr2_chan_handle_cas(p->r2chan);
05004 }
05005 #else
05006 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05007 #endif
05008 case DAHDI_EVENT_PULSE_START:
05009
05010 if (!ast->pbx)
05011 tone_zone_play_tone(p->subs[index].dfd, -1);
05012 break;
05013 case DAHDI_EVENT_DIALCOMPLETE:
05014 #ifdef HAVE_OPENR2
05015 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05016
05017
05018 break;
05019 }
05020 #endif
05021 if (p->inalarm) break;
05022 if ((p->radio || (p->oprmode < 0))) break;
05023 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
05024 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05025 return NULL;
05026 }
05027 if (!x) {
05028 dahdi_enable_ec(p);
05029 if (p->echobreak) {
05030 dahdi_train_ec(p);
05031 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05032 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05033 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05034 p->echobreak = 0;
05035 } else {
05036 p->dialing = 0;
05037 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05038
05039 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05040 ast_setstate(ast, AST_STATE_UP);
05041 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05042 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05043 break;
05044 } else {
05045
05046 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05047 }
05048 }
05049 if (ast->_state == AST_STATE_DIALING) {
05050 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05051 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
05052 } 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)))) {
05053 ast_setstate(ast, AST_STATE_RINGING);
05054 } else if (!p->answeronpolarityswitch) {
05055 ast_setstate(ast, AST_STATE_UP);
05056 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05057 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05058
05059 p->polarity = POLARITY_REV;
05060 } else {
05061
05062 p->polarity = POLARITY_IDLE;
05063 }
05064 }
05065 }
05066 }
05067 break;
05068 case DAHDI_EVENT_ALARM:
05069 #ifdef HAVE_PRI
05070 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05071
05072 if (p->call) {
05073 if (p->pri && p->pri->pri) {
05074 if (!pri_grab(p, p->pri)) {
05075 pri_hangup(p->pri->pri, p->call, -1);
05076 pri_destroycall(p->pri->pri, p->call);
05077 p->call = NULL;
05078 pri_rel(p->pri);
05079 } else
05080 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05081 } else
05082 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05083 }
05084 if (p->owner)
05085 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05086 }
05087 if (p->bearer)
05088 p->bearer->inalarm = 1;
05089 else
05090 #endif
05091 p->inalarm = 1;
05092 res = get_alarms(p);
05093 handle_alarms(p, res);
05094 #ifdef HAVE_PRI
05095 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05096
05097 } else {
05098 break;
05099 }
05100 #endif
05101 #ifdef HAVE_OPENR2
05102 if (p->sig == SIG_MFCR2)
05103 break;
05104 #endif
05105 case DAHDI_EVENT_ONHOOK:
05106 if (p->radio) {
05107 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05108 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05109 break;
05110 }
05111 if (p->oprmode < 0)
05112 {
05113 if (p->oprmode != -1) break;
05114 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05115 {
05116
05117 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05118 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05119 save_conference(p->oprpeer);
05120 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05121 }
05122 break;
05123 }
05124 switch (p->sig) {
05125 case SIG_FXOLS:
05126 case SIG_FXOGS:
05127 case SIG_FXOKS:
05128 p->onhooktime = time(NULL);
05129 p->msgstate = -1;
05130
05131 if (index == SUB_REAL) {
05132
05133 if (p->subs[SUB_CALLWAIT].owner) {
05134
05135 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05136 if (option_verbose > 2)
05137 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05138 unalloc_sub(p, SUB_CALLWAIT);
05139 #if 0
05140 p->subs[index].needanswer = 0;
05141 p->subs[index].needringing = 0;
05142 #endif
05143 p->callwaitingrepeat = 0;
05144 p->cidcwexpire = 0;
05145 p->owner = NULL;
05146
05147 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05148 p->dialing = 1;
05149 dahdi_ring_phone(p);
05150 } else if (p->subs[SUB_THREEWAY].owner) {
05151 unsigned int mssinceflash;
05152
05153
05154 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
05155
05156 ast_mutex_unlock(&p->lock);
05157 DEADLOCK_AVOIDANCE(&ast->lock);
05158
05159
05160
05161 ast_mutex_lock(&p->lock);
05162 if (p->owner != ast) {
05163 ast_log(LOG_WARNING, "This isn't good...\n");
05164 return NULL;
05165 }
05166 }
05167 if (!p->subs[SUB_THREEWAY].owner) {
05168 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05169 return NULL;
05170 }
05171 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05172 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
05173 if (mssinceflash < MIN_MS_SINCE_FLASH) {
05174
05175
05176 if (p->subs[SUB_THREEWAY].owner)
05177 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
05178 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05179 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05180 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05181 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05182 if (p->transfer) {
05183
05184 p->subs[SUB_REAL].inthreeway = 0;
05185 p->subs[SUB_THREEWAY].inthreeway = 0;
05186
05187 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05188 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05189
05190 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05191 p->owner = NULL;
05192
05193 dahdi_ring_phone(p);
05194 } else {
05195 if ((res = attempt_transfer(p)) < 0) {
05196 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05197 if (p->subs[SUB_THREEWAY].owner)
05198 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05199 } else if (res) {
05200
05201 if (p->subs[SUB_THREEWAY].owner)
05202 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05203 break;
05204 }
05205 }
05206 } else {
05207 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05208 if (p->subs[SUB_THREEWAY].owner)
05209 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05210 }
05211 } else {
05212 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05213
05214 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05215 p->owner = NULL;
05216
05217 dahdi_ring_phone(p);
05218 }
05219 }
05220 } else {
05221 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
05222 }
05223
05224 default:
05225 dahdi_disable_ec(p);
05226 return NULL;
05227 }
05228 break;
05229 case DAHDI_EVENT_RINGOFFHOOK:
05230 if (p->inalarm) break;
05231 if (p->oprmode < 0)
05232 {
05233 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05234 {
05235
05236 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05237 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
05238 restore_conference(p->oprpeer);
05239 }
05240 break;
05241 }
05242 if (p->radio)
05243 {
05244 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05245 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05246 break;
05247 }
05248
05249
05250 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05251 c = strchr(p->dialdest, '/');
05252 if (c)
05253 c++;
05254 else
05255 c = p->dialdest;
05256 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05257 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05258 if (strlen(p->dop.dialstr) > 4) {
05259 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05260 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05261 p->echorest[sizeof(p->echorest) - 1] = '\0';
05262 p->echobreak = 1;
05263 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05264 } else
05265 p->echobreak = 0;
05266 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05267 int saveerr = errno;
05268
05269 x = DAHDI_ONHOOK;
05270 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05271 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05272 return NULL;
05273 }
05274 p->dialing = 1;
05275 return &p->subs[index].f;
05276 }
05277 switch (p->sig) {
05278 case SIG_FXOLS:
05279 case SIG_FXOGS:
05280 case SIG_FXOKS:
05281 switch (ast->_state) {
05282 case AST_STATE_RINGING:
05283 dahdi_enable_ec(p);
05284 dahdi_train_ec(p);
05285 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05286 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05287
05288 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05289 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
05290 if (p->cidspill) {
05291
05292 free(p->cidspill);
05293 p->cidspill = NULL;
05294 }
05295 p->dialing = 0;
05296 p->callwaitcas = 0;
05297 if (p->confirmanswer) {
05298
05299 p->subs[index].f.frametype = AST_FRAME_NULL;
05300 p->subs[index].f.subclass = 0;
05301 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05302
05303 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05304 if (res < 0) {
05305 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05306 p->dop.dialstr[0] = '\0';
05307 return NULL;
05308 } else {
05309 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05310 p->subs[index].f.frametype = AST_FRAME_NULL;
05311 p->subs[index].f.subclass = 0;
05312 p->dialing = 1;
05313 }
05314 p->dop.dialstr[0] = '\0';
05315 ast_setstate(ast, AST_STATE_DIALING);
05316 } else
05317 ast_setstate(ast, AST_STATE_UP);
05318 return &p->subs[index].f;
05319 case AST_STATE_DOWN:
05320 ast_setstate(ast, AST_STATE_RING);
05321 ast->rings = 1;
05322 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05323 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05324 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
05325 return &p->subs[index].f;
05326 case AST_STATE_UP:
05327
05328 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05329
05330 if (ast_bridged_channel(p->owner))
05331 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05332 p->subs[index].needunhold = 1;
05333 break;
05334 case AST_STATE_RESERVED:
05335
05336 if (has_voicemail(p))
05337 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05338 else
05339 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05340 break;
05341 default:
05342 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05343 }
05344 break;
05345 case SIG_FXSLS:
05346 case SIG_FXSGS:
05347 case SIG_FXSKS:
05348 if (ast->_state == AST_STATE_RING) {
05349 p->ringt = p->ringt_base;
05350 }
05351
05352
05353 case SIG_EM:
05354 case SIG_EM_E1:
05355 case SIG_EMWINK:
05356 case SIG_FEATD:
05357 case SIG_FEATDMF:
05358 case SIG_FEATDMF_TA:
05359 case SIG_E911:
05360 case SIG_FGC_CAMA:
05361 case SIG_FGC_CAMAMF:
05362 case SIG_FEATB:
05363 case SIG_SF:
05364 case SIG_SFWINK:
05365 case SIG_SF_FEATD:
05366 case SIG_SF_FEATDMF:
05367 case SIG_SF_FEATB:
05368 if (ast->_state == AST_STATE_PRERING)
05369 ast_setstate(ast, AST_STATE_RING);
05370 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05371 if (option_debug)
05372 ast_log(LOG_DEBUG, "Ring detected\n");
05373 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05374 p->subs[index].f.subclass = AST_CONTROL_RING;
05375 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05376 if (option_debug)
05377 ast_log(LOG_DEBUG, "Line answered\n");
05378 if (p->confirmanswer) {
05379 p->subs[index].f.frametype = AST_FRAME_NULL;
05380 p->subs[index].f.subclass = 0;
05381 } else {
05382 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05383 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05384 ast_setstate(ast, AST_STATE_UP);
05385 }
05386 } else if (ast->_state != AST_STATE_RING)
05387 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05388 break;
05389 default:
05390 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05391 }
05392 break;
05393 #ifdef DAHDI_EVENT_RINGBEGIN
05394 case DAHDI_EVENT_RINGBEGIN:
05395 switch (p->sig) {
05396 case SIG_FXSLS:
05397 case SIG_FXSGS:
05398 case SIG_FXSKS:
05399 if (ast->_state == AST_STATE_RING) {
05400 p->ringt = p->ringt_base;
05401 }
05402 break;
05403 }
05404 break;
05405 #endif
05406 case DAHDI_EVENT_RINGEROFF:
05407 if (p->inalarm) break;
05408 if ((p->radio || (p->oprmode < 0))) break;
05409 ast->rings++;
05410 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05411 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05412 free(p->cidspill);
05413 p->cidspill = NULL;
05414 p->callwaitcas = 0;
05415 }
05416 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05417 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05418 break;
05419 case DAHDI_EVENT_RINGERON:
05420 break;
05421 case DAHDI_EVENT_NOALARM:
05422 p->inalarm = 0;
05423 #ifdef HAVE_PRI
05424
05425 if (p->bearer)
05426 p->bearer->inalarm = 0;
05427 #endif
05428 if (!p->unknown_alarm) {
05429 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05430 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05431 "Channel: %d\r\n", p->channel);
05432 } else {
05433 p->unknown_alarm = 0;
05434 }
05435 break;
05436 case DAHDI_EVENT_WINKFLASH:
05437 if (p->inalarm) break;
05438 if (p->radio) break;
05439 if (p->oprmode < 0) break;
05440 if (p->oprmode > 1)
05441 {
05442 struct dahdi_params par;
05443
05444 memset(&par, 0, sizeof(par));
05445 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05446 {
05447 if (!par.rxisoffhook)
05448 {
05449
05450 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05451 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05452 save_conference(p);
05453 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05454 }
05455 }
05456 break;
05457 }
05458
05459 gettimeofday(&p->flashtime, NULL);
05460 switch (mysig) {
05461 case SIG_FXOLS:
05462 case SIG_FXOGS:
05463 case SIG_FXOKS:
05464 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05465 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05466 p->callwaitcas = 0;
05467
05468 if (index != SUB_REAL) {
05469 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05470 goto winkflashdone;
05471 }
05472
05473 if (p->subs[SUB_CALLWAIT].owner) {
05474
05475 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05476 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05477 p->owner = p->subs[SUB_REAL].owner;
05478 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
05479 if (p->owner->_state == AST_STATE_RINGING) {
05480 ast_setstate(p->owner, AST_STATE_UP);
05481 p->subs[SUB_REAL].needanswer = 1;
05482 }
05483 p->callwaitingrepeat = 0;
05484 p->cidcwexpire = 0;
05485
05486 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05487 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05488 S_OR(p->mohsuggest, NULL),
05489 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05490 }
05491 p->subs[SUB_CALLWAIT].needhold = 1;
05492 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05493 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05494 S_OR(p->mohsuggest, NULL),
05495 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05496 }
05497 p->subs[SUB_REAL].needunhold = 1;
05498 } else if (!p->subs[SUB_THREEWAY].owner) {
05499 if (!p->threewaycalling) {
05500
05501 p->subs[SUB_REAL].needflash = 1;
05502 goto winkflashdone;
05503 } else if (!check_for_conference(p)) {
05504 char cid_num[256];
05505 char cid_name[256];
05506
05507 cid_num[0] = 0;
05508 cid_name[0] = 0;
05509 if (p->dahditrcallerid && p->owner) {
05510 if (p->owner->cid.cid_num)
05511 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05512 if (p->owner->cid.cid_name)
05513 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05514 }
05515
05516
05517 if (!((ast->pbx) ||
05518 (ast->_state == AST_STATE_UP) ||
05519 (ast->_state == AST_STATE_RING))) {
05520 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
05521 goto winkflashdone;
05522 }
05523 if (alloc_sub(p, SUB_THREEWAY)) {
05524 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05525 goto winkflashdone;
05526 }
05527
05528 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05529 if (p->dahditrcallerid) {
05530 if (!p->origcid_num)
05531 p->origcid_num = ast_strdup(p->cid_num);
05532 if (!p->origcid_name)
05533 p->origcid_name = ast_strdup(p->cid_name);
05534 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05535 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05536 }
05537
05538 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05539
05540 dahdi_disable_ec(p);
05541 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05542 if (res)
05543 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05544 p->owner = chan;
05545 pthread_attr_init(&attr);
05546 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05547 if (!chan) {
05548 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05549 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
05550 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05551 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05552 dahdi_enable_ec(p);
05553 ast_hangup(chan);
05554 } else {
05555 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05556 int way3bridge = 0, cdr3way = 0;
05557
05558 if (!other) {
05559 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05560 } else
05561 way3bridge = 1;
05562
05563 if (p->subs[SUB_THREEWAY].owner->cdr)
05564 cdr3way = 1;
05565
05566 if (option_verbose > 2)
05567 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
05568
05569 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05570 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05571 S_OR(p->mohsuggest, NULL),
05572 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05573 }
05574 p->subs[SUB_THREEWAY].needhold = 1;
05575 }
05576 pthread_attr_destroy(&attr);
05577 }
05578 } else {
05579
05580 if (p->subs[SUB_THREEWAY].inthreeway) {
05581
05582 if (option_debug)
05583 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05584
05585 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05586
05587 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05588 p->owner = p->subs[SUB_REAL].owner;
05589 }
05590
05591 if (option_verbose > 2)
05592 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05593 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05594 p->subs[SUB_REAL].inthreeway = 0;
05595 p->subs[SUB_THREEWAY].inthreeway = 0;
05596 } else {
05597
05598 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05599 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05600 int otherindex = SUB_THREEWAY;
05601 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05602 int way3bridge = 0, cdr3way = 0;
05603
05604 if (!other) {
05605 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05606 } else
05607 way3bridge = 1;
05608
05609 if (p->subs[SUB_THREEWAY].owner->cdr)
05610 cdr3way = 1;
05611
05612 if (option_verbose > 2)
05613 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);
05614
05615 p->subs[SUB_THREEWAY].inthreeway = 1;
05616 p->subs[SUB_REAL].inthreeway = 1;
05617 if (ast->_state == AST_STATE_UP) {
05618 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05619 otherindex = SUB_REAL;
05620 }
05621 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05622 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05623 p->subs[otherindex].needunhold = 1;
05624 p->owner = p->subs[SUB_REAL].owner;
05625 if (ast->_state == AST_STATE_RINGING) {
05626 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
05627 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05628 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05629 }
05630 } else {
05631 if (option_verbose > 2)
05632 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05633 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05634 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05635 p->owner = p->subs[SUB_REAL].owner;
05636 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05637 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05638 p->subs[SUB_REAL].needunhold = 1;
05639 dahdi_enable_ec(p);
05640 }
05641
05642 }
05643 }
05644 winkflashdone:
05645 update_conf(p);
05646 break;
05647 case SIG_EM:
05648 case SIG_EM_E1:
05649 case SIG_FEATD:
05650 case SIG_SF:
05651 case SIG_SFWINK:
05652 case SIG_SF_FEATD:
05653 case SIG_FXSLS:
05654 case SIG_FXSGS:
05655 if (p->dialing)
05656 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
05657 else
05658 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05659 break;
05660 case SIG_FEATDMF_TA:
05661 switch (p->whichwink) {
05662 case 0:
05663 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05664 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05665 break;
05666 case 1:
05667 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05668 break;
05669 case 2:
05670 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05671 return NULL;
05672 }
05673 p->whichwink++;
05674
05675 case SIG_FEATDMF:
05676 case SIG_E911:
05677 case SIG_FGC_CAMAMF:
05678 case SIG_FGC_CAMA:
05679 case SIG_FEATB:
05680 case SIG_SF_FEATDMF:
05681 case SIG_SF_FEATB:
05682 case SIG_EMWINK:
05683
05684 if (!ast_strlen_zero(p->dop.dialstr)) {
05685 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05686 if (res < 0) {
05687 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05688 p->dop.dialstr[0] = '\0';
05689 return NULL;
05690 } else
05691 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05692 }
05693 p->dop.dialstr[0] = '\0';
05694 break;
05695 default:
05696 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
05697 }
05698 break;
05699 case DAHDI_EVENT_HOOKCOMPLETE:
05700 if (p->inalarm) break;
05701 if ((p->radio || (p->oprmode < 0))) break;
05702 switch (mysig) {
05703 case SIG_FXSLS:
05704 case SIG_FXSGS:
05705 case SIG_FXSKS:
05706 case SIG_EM:
05707 case SIG_EM_E1:
05708 case SIG_EMWINK:
05709 case SIG_FEATD:
05710 case SIG_SF:
05711 case SIG_SFWINK:
05712 case SIG_SF_FEATD:
05713 if (!ast_strlen_zero(p->dop.dialstr)) {
05714 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05715 if (res < 0) {
05716 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05717 p->dop.dialstr[0] = '\0';
05718 return NULL;
05719 } else
05720 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05721 }
05722 p->dop.dialstr[0] = '\0';
05723 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05724 break;
05725 case SIG_FEATDMF:
05726 case SIG_FEATDMF_TA:
05727 case SIG_E911:
05728 case SIG_FGC_CAMA:
05729 case SIG_FGC_CAMAMF:
05730 case SIG_FEATB:
05731 case SIG_SF_FEATDMF:
05732 case SIG_SF_FEATB:
05733 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05734 break;
05735 default:
05736 break;
05737 }
05738 break;
05739 case DAHDI_EVENT_POLARITY:
05740
05741
05742
05743
05744
05745
05746 if (p->polarity == POLARITY_IDLE) {
05747 p->polarity = POLARITY_REV;
05748 if (p->answeronpolarityswitch &&
05749 ((ast->_state == AST_STATE_DIALING) ||
05750 (ast->_state == AST_STATE_RINGING))) {
05751 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
05752 ast_setstate(p->owner, AST_STATE_UP);
05753 if (p->hanguponpolarityswitch) {
05754 gettimeofday(&p->polaritydelaytv, NULL);
05755 }
05756 } else
05757 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
05758 }
05759
05760
05761 if (p->hanguponpolarityswitch &&
05762 (p->polarityonanswerdelay > 0) &&
05763 (p->polarity == POLARITY_REV) &&
05764 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
05765
05766 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) );
05767
05768 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05769 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
05770 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05771 p->polarity = POLARITY_IDLE;
05772 } else {
05773 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);
05774 }
05775 } else {
05776 p->polarity = POLARITY_IDLE;
05777 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
05778 }
05779
05780 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) );
05781 break;
05782 default:
05783 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05784 }
05785 return &p->subs[index].f;
05786 }
05787
05788 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05789 {
05790 struct dahdi_pvt *p = ast->tech_pvt;
05791 int res;
05792 int usedindex=-1;
05793 int index;
05794 struct ast_frame *f;
05795
05796
05797 index = dahdi_get_index(ast, p, 1);
05798
05799 p->subs[index].f.frametype = AST_FRAME_NULL;
05800 p->subs[index].f.datalen = 0;
05801 p->subs[index].f.samples = 0;
05802 p->subs[index].f.mallocd = 0;
05803 p->subs[index].f.offset = 0;
05804 p->subs[index].f.subclass = 0;
05805 p->subs[index].f.delivery = ast_tv(0,0);
05806 p->subs[index].f.src = "dahdi_exception";
05807 p->subs[index].f.data = NULL;
05808
05809
05810 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05811
05812
05813
05814
05815
05816 if (p->fake_event) {
05817 res = p->fake_event;
05818 p->fake_event = 0;
05819 } else
05820 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05821
05822 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05823 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05824 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
05825 p->owner = p->subs[SUB_REAL].owner;
05826 if (p->owner && ast_bridged_channel(p->owner))
05827 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05828 p->subs[SUB_REAL].needunhold = 1;
05829 }
05830 switch (res) {
05831 case DAHDI_EVENT_ONHOOK:
05832 dahdi_disable_ec(p);
05833 if (p->owner) {
05834 if (option_verbose > 2)
05835 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
05836 dahdi_ring_phone(p);
05837 p->callwaitingrepeat = 0;
05838 p->cidcwexpire = 0;
05839 } else
05840 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05841 update_conf(p);
05842 break;
05843 case DAHDI_EVENT_RINGOFFHOOK:
05844 dahdi_enable_ec(p);
05845 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05846 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05847 p->subs[SUB_REAL].needanswer = 1;
05848 p->dialing = 0;
05849 }
05850 break;
05851 case DAHDI_EVENT_HOOKCOMPLETE:
05852 case DAHDI_EVENT_RINGERON:
05853 case DAHDI_EVENT_RINGEROFF:
05854
05855 break;
05856 case DAHDI_EVENT_WINKFLASH:
05857 gettimeofday(&p->flashtime, NULL);
05858 if (p->owner) {
05859 if (option_verbose > 2)
05860 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05861 if (p->owner->_state != AST_STATE_UP) {
05862
05863 usedindex = dahdi_get_index(p->owner, p, 0);
05864 if (usedindex > -1) {
05865 p->subs[usedindex].needanswer = 1;
05866 }
05867 ast_setstate(p->owner, AST_STATE_UP);
05868 }
05869 p->callwaitingrepeat = 0;
05870 p->cidcwexpire = 0;
05871 if (ast_bridged_channel(p->owner))
05872 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05873 p->subs[SUB_REAL].needunhold = 1;
05874 } else
05875 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05876 update_conf(p);
05877 break;
05878 default:
05879 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05880 }
05881 f = &p->subs[index].f;
05882 return f;
05883 }
05884 if (!(p->radio || (p->oprmode < 0)) && option_debug)
05885 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05886
05887 if (ast != p->owner) {
05888 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05889 f = &p->subs[index].f;
05890 return f;
05891 }
05892 f = dahdi_handle_event(ast);
05893 return f;
05894 }
05895
05896 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05897 {
05898 struct dahdi_pvt *p = ast->tech_pvt;
05899 struct ast_frame *f;
05900 ast_mutex_lock(&p->lock);
05901 f = __dahdi_exception(ast);
05902 ast_mutex_unlock(&p->lock);
05903 return f;
05904 }
05905
05906 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05907 {
05908 struct dahdi_pvt *p = ast->tech_pvt;
05909 int res;
05910 int index;
05911 void *readbuf;
05912 struct ast_frame *f;
05913
05914 while (ast_mutex_trylock(&p->lock)) {
05915 DEADLOCK_AVOIDANCE(&ast->lock);
05916 }
05917
05918 index = dahdi_get_index(ast, p, 0);
05919
05920
05921 if (index < 0) {
05922 ast_log(LOG_WARNING, "We dont exist?\n");
05923 ast_mutex_unlock(&p->lock);
05924 return NULL;
05925 }
05926
05927 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05928 ast_mutex_unlock(&p->lock);
05929 return NULL;
05930 }
05931
05932 p->subs[index].f.frametype = AST_FRAME_NULL;
05933 p->subs[index].f.datalen = 0;
05934 p->subs[index].f.samples = 0;
05935 p->subs[index].f.mallocd = 0;
05936 p->subs[index].f.offset = 0;
05937 p->subs[index].f.subclass = 0;
05938 p->subs[index].f.delivery = ast_tv(0,0);
05939 p->subs[index].f.src = "dahdi_read";
05940 p->subs[index].f.data = NULL;
05941
05942
05943 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05944 {
05945 struct dahdi_params ps;
05946
05947 memset(&ps, 0, sizeof(ps));
05948 ps.channo = p->channel;
05949 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05950 ast_mutex_unlock(&p->lock);
05951 return NULL;
05952 }
05953 p->firstradio = 1;
05954 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05955 if (ps.rxisoffhook)
05956 {
05957 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05958 }
05959 else
05960 {
05961 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05962 }
05963 ast_mutex_unlock(&p->lock);
05964 return &p->subs[index].f;
05965 }
05966 if (p->ringt == 1) {
05967 ast_mutex_unlock(&p->lock);
05968 return NULL;
05969 }
05970 else if (p->ringt > 0)
05971 p->ringt--;
05972
05973 #ifdef HAVE_OPENR2
05974 if (p->mfcr2) {
05975 openr2_chan_process_event(p->r2chan);
05976 }
05977 #endif
05978
05979 if (p->subs[index].needringing) {
05980
05981 p->subs[index].needringing = 0;
05982 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05983 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05984 ast_setstate(ast, AST_STATE_RINGING);
05985 ast_mutex_unlock(&p->lock);
05986 return &p->subs[index].f;
05987 }
05988
05989 if (p->subs[index].needbusy) {
05990
05991 p->subs[index].needbusy = 0;
05992 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05993 p->subs[index].f.subclass = AST_CONTROL_BUSY;
05994 ast_mutex_unlock(&p->lock);
05995 return &p->subs[index].f;
05996 }
05997
05998 if (p->subs[index].needcongestion) {
05999
06000 p->subs[index].needcongestion = 0;
06001 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06002 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
06003 ast_mutex_unlock(&p->lock);
06004 return &p->subs[index].f;
06005 }
06006
06007 if (p->subs[index].needcallerid) {
06008 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06009 S_OR(p->lastcid_name, NULL),
06010 S_OR(p->lastcid_num, NULL)
06011 );
06012 p->subs[index].needcallerid = 0;
06013 }
06014
06015 if (p->subs[index].needanswer) {
06016
06017 p->subs[index].needanswer = 0;
06018 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06019 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
06020 ast_mutex_unlock(&p->lock);
06021 return &p->subs[index].f;
06022 }
06023
06024 #ifdef HAVE_OPENR2
06025 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06026
06027
06028
06029
06030 p->subs[index].f.frametype = AST_FRAME_NULL;
06031 p->subs[index].f.subclass = 0;
06032 p->subs[index].f.samples = 0;
06033 p->subs[index].f.mallocd = 0;
06034 p->subs[index].f.offset = 0;
06035 p->subs[index].f.data = NULL;
06036 p->subs[index].f.datalen= 0;
06037 ast_mutex_unlock(&p->lock);
06038 return &p->subs[index].f;
06039 }
06040 #endif
06041
06042 if (p->subs[index].needflash) {
06043
06044 p->subs[index].needflash = 0;
06045 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06046 p->subs[index].f.subclass = AST_CONTROL_FLASH;
06047 ast_mutex_unlock(&p->lock);
06048 return &p->subs[index].f;
06049 }
06050
06051 if (p->subs[index].needhold) {
06052
06053 p->subs[index].needhold = 0;
06054 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06055 p->subs[index].f.subclass = AST_CONTROL_HOLD;
06056 ast_mutex_unlock(&p->lock);
06057 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
06058 return &p->subs[index].f;
06059 }
06060
06061 if (p->subs[index].needunhold) {
06062
06063 p->subs[index].needunhold = 0;
06064 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06065 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
06066 ast_mutex_unlock(&p->lock);
06067 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
06068 return &p->subs[index].f;
06069 }
06070
06071 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06072 if (!p->subs[index].linear) {
06073 p->subs[index].linear = 1;
06074 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06075 if (res)
06076 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
06077 }
06078 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06079 (ast->rawreadformat == AST_FORMAT_ALAW)) {
06080 if (p->subs[index].linear) {
06081 p->subs[index].linear = 0;
06082 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06083 if (res)
06084 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
06085 }
06086 } else {
06087 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06088 ast_mutex_unlock(&p->lock);
06089 return NULL;
06090 }
06091 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
06092 CHECK_BLOCKING(ast);
06093 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06094 ast_clear_flag(ast, AST_FLAG_BLOCKING);
06095
06096 if (res < 0) {
06097 f = NULL;
06098 if (res == -1) {
06099 if (errno == EAGAIN) {
06100
06101 ast_mutex_unlock(&p->lock);
06102 return &p->subs[index].f;
06103 } else if (errno == ELAST) {
06104 f = __dahdi_exception(ast);
06105 } else
06106 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06107 }
06108 ast_mutex_unlock(&p->lock);
06109 return f;
06110 }
06111 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06112 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06113 f = __dahdi_exception(ast);
06114 ast_mutex_unlock(&p->lock);
06115 return f;
06116 }
06117 if (p->tdd) {
06118 int c;
06119
06120 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06121 if (c < 0) {
06122 ast_log(LOG_DEBUG,"tdd_feed failed\n");
06123 ast_mutex_unlock(&p->lock);
06124 return NULL;
06125 }
06126 if (c) {
06127 p->subs[index].f.subclass = 0;
06128 p->subs[index].f.frametype = AST_FRAME_TEXT;
06129 p->subs[index].f.mallocd = 0;
06130 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06131 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06132 p->subs[index].f.datalen = 1;
06133 *((char *) p->subs[index].f.data) = c;
06134 ast_mutex_unlock(&p->lock);
06135 return &p->subs[index].f;
06136 }
06137 }
06138
06139 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06140 p->callwaitingrepeat--;
06141 }
06142 if (p->cidcwexpire)
06143 p->cidcwexpire--;
06144
06145 if (p->callwaitingrepeat == 1) {
06146 p->callwaitrings++;
06147 dahdi_callwait(ast);
06148 }
06149
06150 if (p->cidcwexpire == 1) {
06151 if (option_verbose > 2)
06152 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06153 restore_conference(p);
06154 }
06155 if (p->subs[index].linear) {
06156 p->subs[index].f.datalen = READ_SIZE * 2;
06157 } else
06158 p->subs[index].f.datalen = READ_SIZE;
06159
06160
06161 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06162 send_callerid(p);
06163 }
06164
06165 p->subs[index].f.frametype = AST_FRAME_VOICE;
06166 p->subs[index].f.subclass = ast->rawreadformat;
06167 p->subs[index].f.samples = READ_SIZE;
06168 p->subs[index].f.mallocd = 0;
06169 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06170 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06171 #if 0
06172 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06173 #endif
06174 if (p->dialing ||
06175 (index && (ast->_state != AST_STATE_UP)) ||
06176 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
06177 ) {
06178
06179
06180 p->subs[index].f.frametype = AST_FRAME_NULL;
06181 p->subs[index].f.subclass = 0;
06182 p->subs[index].f.samples = 0;
06183 p->subs[index].f.mallocd = 0;
06184 p->subs[index].f.offset = 0;
06185 p->subs[index].f.data = NULL;
06186 p->subs[index].f.datalen= 0;
06187 }
06188 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
06189
06190 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06191 if (f) {
06192 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06193 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06194
06195
06196 f = NULL;
06197 }
06198 } else if (f->frametype == AST_FRAME_DTMF) {
06199 #ifdef HAVE_PRI
06200 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial &&
06201 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
06202 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06203
06204 f->frametype = AST_FRAME_NULL;
06205 f->subclass = 0;
06206 }
06207 #endif
06208
06209 p->pulsedial = 0;
06210 }
06211 }
06212 } else
06213 f = &p->subs[index].f;
06214
06215 if (f && (f->frametype == AST_FRAME_DTMF))
06216 dahdi_handle_dtmfup(ast, index, &f);
06217
06218
06219 if (p->fake_event)
06220 ast_set_flag(ast, AST_FLAG_EXCEPTION);
06221
06222 ast_mutex_unlock(&p->lock);
06223 return f;
06224 }
06225
06226 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
06227 {
06228 int sent=0;
06229 int size;
06230 int res;
06231 int fd;
06232 fd = p->subs[index].dfd;
06233 while (len) {
06234 size = len;
06235 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06236 size = (linear ? READ_SIZE * 2 : READ_SIZE);
06237 res = write(fd, buf, size);
06238 if (res != size) {
06239 if (option_debug)
06240 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06241 return sent;
06242 }
06243 len -= size;
06244 buf += size;
06245 }
06246 return sent;
06247 }
06248
06249 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06250 {
06251 struct dahdi_pvt *p = ast->tech_pvt;
06252 int res;
06253 int index;
06254 index = dahdi_get_index(ast, p, 0);
06255 if (index < 0) {
06256 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06257 return -1;
06258 }
06259
06260 #if 0
06261 #ifdef HAVE_PRI
06262 ast_mutex_lock(&p->lock);
06263 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06264 if (p->pri->pri) {
06265 if (!pri_grab(p, p->pri)) {
06266 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06267 pri_rel(p->pri);
06268 } else
06269 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06270 }
06271 p->proceeding=1;
06272 }
06273 ast_mutex_unlock(&p->lock);
06274 #endif
06275 #endif
06276
06277 if (frame->frametype != AST_FRAME_VOICE) {
06278 if (frame->frametype != AST_FRAME_IMAGE)
06279 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06280 return 0;
06281 }
06282 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06283 (frame->subclass != AST_FORMAT_ULAW) &&
06284 (frame->subclass != AST_FORMAT_ALAW)) {
06285 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06286 return -1;
06287 }
06288 if (p->dialing) {
06289 if (option_debug)
06290 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06291 return 0;
06292 }
06293 if (!p->owner) {
06294 if (option_debug)
06295 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06296 return 0;
06297 }
06298 if (p->cidspill) {
06299 if (option_debug)
06300 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
06301 return 0;
06302 }
06303
06304 if (!frame->data || !frame->datalen)
06305 return 0;
06306
06307 if (frame->subclass == AST_FORMAT_SLINEAR) {
06308 if (!p->subs[index].linear) {
06309 p->subs[index].linear = 1;
06310 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06311 if (res)
06312 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06313 }
06314 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06315 } else {
06316
06317 if (p->subs[index].linear) {
06318 p->subs[index].linear = 0;
06319 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06320 if (res)
06321 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06322 }
06323 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06324 }
06325 if (res < 0) {
06326 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06327 return -1;
06328 }
06329 return 0;
06330 }
06331
06332 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06333 {
06334 struct dahdi_pvt *p = chan->tech_pvt;
06335 int res=-1;
06336 int index;
06337 int func = DAHDI_FLASH;
06338 ast_mutex_lock(&p->lock);
06339 index = dahdi_get_index(chan, p, 0);
06340 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06341 #ifdef HAVE_OPENR2
06342 if (p->mfcr2 && !p->mfcr2_call_accepted) {
06343 ast_mutex_unlock(&p->lock);
06344
06345
06346 return 0;
06347 }
06348 #endif
06349 if (index == SUB_REAL) {
06350 switch (condition) {
06351 case AST_CONTROL_BUSY:
06352 #ifdef HAVE_PRI
06353 if (p->priindication_oob && p->sig == SIG_PRI) {
06354 chan->hangupcause = AST_CAUSE_USER_BUSY;
06355 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06356 res = 0;
06357 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06358 if (p->pri->pri) {
06359 if (!pri_grab(p, p->pri)) {
06360 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06361 pri_rel(p->pri);
06362 }
06363 else
06364 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06365 }
06366 p->progress = 1;
06367 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06368 } else
06369 #endif
06370 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06371 break;
06372 case AST_CONTROL_RINGING:
06373 #ifdef HAVE_PRI
06374 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06375 if (p->pri->pri) {
06376 if (!pri_grab(p, p->pri)) {
06377 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06378 pri_rel(p->pri);
06379 }
06380 else
06381 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06382 }
06383 p->alerting = 1;
06384 }
06385 #endif
06386 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06387 if (chan->_state != AST_STATE_UP) {
06388 if ((chan->_state != AST_STATE_RING) ||
06389 ((p->sig != SIG_FXSKS) &&
06390 (p->sig != SIG_FXSLS) &&
06391 (p->sig != SIG_FXSGS)))
06392 ast_setstate(chan, AST_STATE_RINGING);
06393 }
06394 break;
06395 case AST_CONTROL_PROCEEDING:
06396 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06397 #ifdef HAVE_PRI
06398 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06399 if (p->pri->pri) {
06400 if (!pri_grab(p, p->pri)) {
06401 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06402 pri_rel(p->pri);
06403 }
06404 else
06405 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06406 }
06407 p->proceeding = 1;
06408 p->dialing = 0;
06409 }
06410 #endif
06411
06412 res = 0;
06413 break;
06414 case AST_CONTROL_PROGRESS:
06415 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06416 #ifdef HAVE_PRI
06417 p->digital = 0;
06418 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06419 if (p->pri->pri) {
06420 if (!pri_grab(p, p->pri)) {
06421 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06422 pri_rel(p->pri);
06423 }
06424 else
06425 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06426 }
06427 p->progress = 1;
06428 }
06429 #endif
06430
06431 res = 0;
06432 break;
06433 case AST_CONTROL_CONGESTION:
06434 chan->hangupcause = AST_CAUSE_CONGESTION;
06435 #ifdef HAVE_PRI
06436 if (p->priindication_oob && p->sig == SIG_PRI) {
06437 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06438 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06439 res = 0;
06440 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06441 if (p->pri) {
06442 if (!pri_grab(p, p->pri)) {
06443 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06444 pri_rel(p->pri);
06445 } else
06446 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06447 }
06448 p->progress = 1;
06449 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06450 } else
06451 #endif
06452 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06453 break;
06454 case AST_CONTROL_HOLD:
06455 #ifdef HAVE_PRI
06456 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06457 if (!pri_grab(p, p->pri)) {
06458 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06459 pri_rel(p->pri);
06460 } else
06461 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06462 } else
06463 #endif
06464 ast_moh_start(chan, data, p->mohinterpret);
06465 break;
06466 case AST_CONTROL_UNHOLD:
06467 #ifdef HAVE_PRI
06468 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06469 if (!pri_grab(p, p->pri)) {
06470 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06471 pri_rel(p->pri);
06472 } else
06473 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06474 } else
06475 #endif
06476 ast_moh_stop(chan);
06477 break;
06478 case AST_CONTROL_RADIO_KEY:
06479 if (p->radio)
06480 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06481 res = 0;
06482 break;
06483 case AST_CONTROL_RADIO_UNKEY:
06484 if (p->radio)
06485 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06486 res = 0;
06487 break;
06488 case AST_CONTROL_FLASH:
06489
06490 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06491
06492 p->dop.dialstr[0] = '\0';
06493 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06494 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06495 chan->name, strerror(errno));
06496 } else
06497 res = 0;
06498 } else
06499 res = 0;
06500 break;
06501 case AST_CONTROL_SRCUPDATE:
06502 res = 0;
06503 break;
06504 case -1:
06505 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06506 break;
06507 }
06508 } else
06509 res = 0;
06510 ast_mutex_unlock(&p->lock);
06511 return res;
06512 }
06513
06514 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
06515 {
06516 struct ast_channel *tmp;
06517 int deflaw;
06518 int res;
06519 int x,y;
06520 int features;
06521 char *b2 = NULL;
06522 struct dahdi_params ps;
06523 char chanprefix[*dahdi_chan_name_len + 4];
06524
06525 if (i->subs[index].owner) {
06526 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
06527 return NULL;
06528 }
06529 y = 1;
06530 do {
06531 if (b2)
06532 free(b2);
06533 #ifdef HAVE_PRI
06534 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06535 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06536 else
06537 #endif
06538 if (i->channel == CHAN_PSEUDO)
06539 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
06540 else
06541 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
06542 for (x = 0; x < 3; x++) {
06543 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
06544 break;
06545 }
06546 y++;
06547 } while (x < 3);
06548 strcpy(chanprefix, dahdi_chan_name);
06549 strcat(chanprefix, "/%s");
06550 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
06551 if (b2)
06552 free(b2);
06553 if (!tmp)
06554 return NULL;
06555 tmp->tech = chan_tech;
06556 memset(&ps, 0, sizeof(ps));
06557 ps.channo = i->channel;
06558 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06559 if (res) {
06560 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06561 ps.curlaw = DAHDI_LAW_MULAW;
06562 }
06563 if (ps.curlaw == DAHDI_LAW_ALAW)
06564 deflaw = AST_FORMAT_ALAW;
06565 else
06566 deflaw = AST_FORMAT_ULAW;
06567 if (law) {
06568 if (law == DAHDI_LAW_ALAW)
06569 deflaw = AST_FORMAT_ALAW;
06570 else
06571 deflaw = AST_FORMAT_ULAW;
06572 }
06573 tmp->fds[0] = i->subs[index].dfd;
06574 tmp->nativeformats = deflaw;
06575
06576 tmp->rawreadformat = deflaw;
06577 tmp->readformat = deflaw;
06578 tmp->rawwriteformat = deflaw;
06579 tmp->writeformat = deflaw;
06580 i->subs[index].linear = 0;
06581 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
06582 features = 0;
06583 if (index == SUB_REAL) {
06584 if (i->busydetect && CANBUSYDETECT(i))
06585 features |= DSP_FEATURE_BUSY_DETECT;
06586 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
06587 features |= DSP_FEATURE_CALL_PROGRESS;
06588 if ((!i->outgoing && (i->callprogress & 4)) ||
06589 (i->outgoing && (i->callprogress & 2))) {
06590 features |= DSP_FEATURE_FAX_DETECT;
06591 }
06592 #ifdef DAHDI_TONEDETECT
06593 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06594 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
06595 #endif
06596 i->hardwaredtmf = 0;
06597 features |= DSP_FEATURE_DTMF_DETECT;
06598 #ifdef DAHDI_TONEDETECT
06599 } else if (NEED_MFDETECT(i)) {
06600 i->hardwaredtmf = 1;
06601 features |= DSP_FEATURE_DTMF_DETECT;
06602 }
06603 #endif
06604 }
06605 if (features) {
06606 if (i->dsp) {
06607 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
06608 } else {
06609 if (i->channel != CHAN_PSEUDO)
06610 i->dsp = ast_dsp_new();
06611 else
06612 i->dsp = NULL;
06613 if (i->dsp) {
06614 i->dsp_features = features;
06615 #ifdef HAVE_PRI
06616
06617 if (i->outgoing && (i->sig == SIG_PRI)) {
06618
06619
06620 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06621 features = 0;
06622 }
06623 #endif
06624 ast_dsp_set_features(i->dsp, features);
06625 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06626 if (!ast_strlen_zero(progzone))
06627 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06628 if (i->busydetect && CANBUSYDETECT(i)) {
06629 if(i->silencethreshold > 0)
06630 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06631 ast_dsp_set_busy_count(i->dsp, i->busycount);
06632 if(i->busytonelength > 0)
06633 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06634 if((i->busytonelength == i->busyquietlength) && i->busycompare)
06635 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06636 }
06637 }
06638 }
06639 }
06640
06641 if (state == AST_STATE_RING)
06642 tmp->rings = 1;
06643 tmp->tech_pvt = i;
06644 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06645
06646 tmp->callgroup = i->callgroup;
06647 tmp->pickupgroup = i->pickupgroup;
06648 }
06649 if (!ast_strlen_zero(i->language))
06650 ast_string_field_set(tmp, language, i->language);
06651 if (!i->owner)
06652 i->owner = tmp;
06653 if (!ast_strlen_zero(i->accountcode))
06654 ast_string_field_set(tmp, accountcode, i->accountcode);
06655 if (i->amaflags)
06656 tmp->amaflags = i->amaflags;
06657 i->subs[index].owner = tmp;
06658 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06659 ast_string_field_set(tmp, call_forward, i->call_forward);
06660
06661 if (!i->adsi)
06662 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06663 if (!ast_strlen_zero(i->exten))
06664 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06665 if (!ast_strlen_zero(i->rdnis))
06666 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06667 if (!ast_strlen_zero(i->dnid))
06668 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06669
06670
06671
06672 #ifdef PRI_ANI
06673 if (!ast_strlen_zero(i->cid_ani))
06674 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06675 else
06676 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06677 #else
06678 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06679 #endif
06680 tmp->cid.cid_pres = i->callingpres;
06681 tmp->cid.cid_ton = i->cid_ton;
06682 #ifdef HAVE_PRI
06683 tmp->transfercapability = transfercapability;
06684 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06685 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
06686 i->digital = 1;
06687
06688 i->isidlecall = 0;
06689 i->alreadyhungup = 0;
06690 #endif
06691
06692 i->fake_event = 0;
06693
06694 dahdi_confmute(i, 0);
06695
06696 ast_jb_configure(tmp, &global_jbconf);
06697 if (startpbx) {
06698 #ifdef HAVE_OPENR2
06699 if (i->mfcr2call) {
06700 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
06701 }
06702 #endif
06703 if (ast_pbx_start(tmp)) {
06704 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06705 ast_hangup(tmp);
06706 i->owner = NULL;
06707 return NULL;
06708 }
06709 }
06710
06711 ast_module_ref(ast_module_info->self);
06712
06713 return tmp;
06714 }
06715
06716
06717 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06718 {
06719 char c;
06720
06721 *str = 0;
06722 for (;;)
06723 {
06724
06725 c = ast_waitfordigit(chan, ms);
06726
06727 if (c < 1)
06728 return c;
06729 *str++ = c;
06730 *str = 0;
06731 if (strchr(term, c))
06732 return 1;
06733 }
06734 }
06735
06736 static int dahdi_wink(struct dahdi_pvt *p, int index)
06737 {
06738 int j;
06739 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06740 for (;;)
06741 {
06742
06743 j = DAHDI_IOMUX_SIGEVENT;
06744
06745 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06746
06747 if (j & DAHDI_IOMUX_SIGEVENT) break;
06748 }
06749
06750 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06751 return 0;
06752 }
06753
06754 static void *ss_thread(void *data)
06755 {
06756 struct ast_channel *chan = data;
06757 struct dahdi_pvt *p = chan->tech_pvt;
06758 char exten[AST_MAX_EXTENSION] = "";
06759 char exten2[AST_MAX_EXTENSION] = "";
06760 unsigned char buf[256];
06761 char dtmfcid[300];
06762 char dtmfbuf[300];
06763 struct callerid_state *cs = NULL;
06764 char *name = NULL, *number = NULL;
06765 int distMatches;
06766 int curRingData[3];
06767 int receivedRingT;
06768 int counter1;
06769 int counter;
06770 int samples = 0;
06771 struct ast_smdi_md_message *smdi_msg = NULL;
06772 int flags = 0;
06773 int i;
06774 int timeout;
06775 int getforward = 0;
06776 char *s1, *s2;
06777 int len = 0;
06778 int res;
06779 int index;
06780
06781 ast_mutex_lock(&ss_thread_lock);
06782 ss_thread_count++;
06783 ast_mutex_unlock(&ss_thread_lock);
06784
06785
06786
06787 if (!p) {
06788 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06789 ast_hangup(chan);
06790 goto quit;
06791 }
06792 if (option_verbose > 2)
06793 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
06794 index = dahdi_get_index(chan, p, 1);
06795 if (index < 0) {
06796 ast_log(LOG_WARNING, "Huh?\n");
06797 ast_hangup(chan);
06798 goto quit;
06799 }
06800 if (p->dsp)
06801 ast_dsp_digitreset(p->dsp);
06802 switch (p->sig) {
06803 #ifdef HAVE_PRI
06804 case SIG_PRI:
06805
06806 ast_copy_string(exten, p->exten, sizeof(exten));
06807 len = strlen(exten);
06808 res = 0;
06809 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06810 if (len && !ast_ignore_pattern(chan->context, exten))
06811 tone_zone_play_tone(p->subs[index].dfd, -1);
06812 else
06813 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06814 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06815 timeout = matchdigittimeout;
06816 else
06817 timeout = gendigittimeout;
06818 res = ast_waitfordigit(chan, timeout);
06819 if (res < 0) {
06820 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06821 ast_hangup(chan);
06822 goto quit;
06823 } else if (res) {
06824 exten[len++] = res;
06825 exten[len] = '\0';
06826 } else
06827 break;
06828 }
06829
06830 if (ast_strlen_zero(exten)) {
06831 if (option_verbose > 2)
06832 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
06833 exten[0] = 's';
06834 exten[1] = '\0';
06835 }
06836 tone_zone_play_tone(p->subs[index].dfd, -1);
06837 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06838
06839 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06840 if (p->dsp) ast_dsp_digitreset(p->dsp);
06841 dahdi_enable_ec(p);
06842 ast_setstate(chan, AST_STATE_RING);
06843 res = ast_pbx_run(chan);
06844 if (res) {
06845 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06846 }
06847 } else {
06848 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06849 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06850 ast_hangup(chan);
06851 p->exten[0] = '\0';
06852
06853 p->call = NULL;
06854 }
06855 goto quit;
06856 break;
06857 #endif
06858 case SIG_FEATD:
06859 case SIG_FEATDMF:
06860 case SIG_FEATDMF_TA:
06861 case SIG_E911:
06862 case SIG_FGC_CAMAMF:
06863 case SIG_FEATB:
06864 case SIG_EMWINK:
06865 case SIG_SF_FEATD:
06866 case SIG_SF_FEATDMF:
06867 case SIG_SF_FEATB:
06868 case SIG_SFWINK:
06869 if (dahdi_wink(p, index))
06870 goto quit;
06871
06872 case SIG_EM:
06873 case SIG_EM_E1:
06874 case SIG_SF:
06875 case SIG_FGC_CAMA:
06876 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06877 if (p->dsp)
06878 ast_dsp_digitreset(p->dsp);
06879
06880 if (p->dsp) {
06881 if (NEED_MFDETECT(p))
06882 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06883 else
06884 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06885 }
06886 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06887
06888 if (!p->immediate)
06889
06890 res = ast_waitfordigit(chan, 5000);
06891 else
06892 res = 0;
06893 if (res > 0) {
06894
06895 dtmfbuf[0] = res;
06896 switch (p->sig) {
06897 case SIG_FEATD:
06898 case SIG_SF_FEATD:
06899 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06900 if (res > 0)
06901 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06902 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06903 break;
06904 case SIG_FEATDMF_TA:
06905 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06906 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06907 if (dahdi_wink(p, index)) goto quit;
06908 dtmfbuf[0] = 0;
06909
06910 res = ast_waitfordigit(chan, 5000);
06911 if (res <= 0) break;
06912 dtmfbuf[0] = res;
06913
06914 case SIG_FEATDMF:
06915 case SIG_E911:
06916 case SIG_FGC_CAMAMF:
06917 case SIG_SF_FEATDMF:
06918 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06919
06920 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06921 {
06922 if (dahdi_wink(p, index)) goto quit;
06923 dtmfbuf[0] = 0;
06924
06925 res = ast_waitfordigit(chan, 5000);
06926 if (res <= 0) break;
06927 dtmfbuf[0] = res;
06928 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06929 }
06930 if (res > 0) {
06931
06932 if (p->sig == SIG_E911)
06933 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06934 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06935 }
06936 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06937 break;
06938 case SIG_FEATB:
06939 case SIG_SF_FEATB:
06940 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06941 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06942 break;
06943 case SIG_EMWINK:
06944
06945
06946
06947
06948 if (res == '*') {
06949 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06950 if (res > 0)
06951 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06952 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06953 break;
06954 }
06955 default:
06956
06957 len = 1;
06958 dtmfbuf[len] = '\0';
06959 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06960 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06961 timeout = matchdigittimeout;
06962 } else {
06963 timeout = gendigittimeout;
06964 }
06965 res = ast_waitfordigit(chan, timeout);
06966 if (res < 0) {
06967 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06968 ast_hangup(chan);
06969 goto quit;
06970 } else if (res) {
06971 dtmfbuf[len++] = res;
06972 dtmfbuf[len] = '\0';
06973 } else {
06974 break;
06975 }
06976 }
06977 break;
06978 }
06979 }
06980 if (res == -1) {
06981 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06982 ast_hangup(chan);
06983 goto quit;
06984 } else if (res < 0) {
06985 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06986 ast_hangup(chan);
06987 goto quit;
06988 }
06989
06990 if (p->sig == SIG_FGC_CAMA) {
06991 char anibuf[100];
06992
06993 if (ast_safe_sleep(chan,1000) == -1) {
06994 ast_hangup(chan);
06995 goto quit;
06996 }
06997 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06998 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06999 res = my_getsigstr(chan, anibuf, "#", 10000);
07000 if ((res > 0) && (strlen(anibuf) > 2)) {
07001 if (anibuf[strlen(anibuf) - 1] == '#')
07002 anibuf[strlen(anibuf) - 1] = 0;
07003 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07004 }
07005 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07006 }
07007
07008 ast_copy_string(exten, dtmfbuf, sizeof(exten));
07009 if (ast_strlen_zero(exten))
07010 ast_copy_string(exten, "s", sizeof(exten));
07011 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07012
07013 if (exten[0] == '*') {
07014 char *stringp=NULL;
07015 ast_copy_string(exten2, exten, sizeof(exten2));
07016
07017 stringp=exten2 +1;
07018 s1 = strsep(&stringp, "*");
07019 s2 = strsep(&stringp, "*");
07020 if (s2) {
07021 if (!ast_strlen_zero(p->cid_num))
07022 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07023 else
07024 ast_set_callerid(chan, s1, NULL, s1);
07025 ast_copy_string(exten, s2, sizeof(exten));
07026 } else
07027 ast_copy_string(exten, s1, sizeof(exten));
07028 } else if (p->sig == SIG_FEATD)
07029 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07030 }
07031 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07032 if (exten[0] == '*') {
07033 char *stringp=NULL;
07034 ast_copy_string(exten2, exten, sizeof(exten2));
07035
07036 stringp=exten2 +1;
07037 s1 = strsep(&stringp, "#");
07038 s2 = strsep(&stringp, "#");
07039 if (s2) {
07040 if (!ast_strlen_zero(p->cid_num))
07041 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07042 else
07043 if (*(s1 + 2))
07044 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07045 ast_copy_string(exten, s2 + 1, sizeof(exten));
07046 } else
07047 ast_copy_string(exten, s1 + 2, sizeof(exten));
07048 } else
07049 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07050 }
07051 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07052 if (exten[0] == '*') {
07053 char *stringp=NULL;
07054 ast_copy_string(exten2, exten, sizeof(exten2));
07055
07056 stringp=exten2 +1;
07057 s1 = strsep(&stringp, "#");
07058 s2 = strsep(&stringp, "#");
07059 if (s2 && (*(s2 + 1) == '0')) {
07060 if (*(s2 + 2))
07061 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07062 }
07063 if (s1) ast_copy_string(exten, s1, sizeof(exten));
07064 else ast_copy_string(exten, "911", sizeof(exten));
07065 } else
07066 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
07067 }
07068 if (p->sig == SIG_FEATB) {
07069 if (exten[0] == '*') {
07070 char *stringp=NULL;
07071 ast_copy_string(exten2, exten, sizeof(exten2));
07072
07073 stringp=exten2 +1;
07074 s1 = strsep(&stringp, "#");
07075 ast_copy_string(exten, exten2 + 1, sizeof(exten));
07076 } else
07077 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
07078 }
07079 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07080 dahdi_wink(p, index);
07081
07082
07083
07084 if (ast_safe_sleep(chan,100)) goto quit;
07085 }
07086 dahdi_enable_ec(p);
07087 if (NEED_MFDETECT(p)) {
07088 if (p->dsp) {
07089 if (!p->hardwaredtmf)
07090 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07091 else {
07092 ast_dsp_free(p->dsp);
07093 p->dsp = NULL;
07094 }
07095 }
07096 }
07097
07098 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07099 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07100 if (p->dsp) ast_dsp_digitreset(p->dsp);
07101 res = ast_pbx_run(chan);
07102 if (res) {
07103 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07104 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07105 }
07106 goto quit;
07107 } else {
07108 if (option_verbose > 2)
07109 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07110 sleep(2);
07111 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07112 if (res < 0)
07113 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07114 else
07115 sleep(1);
07116 res = ast_streamfile(chan, "ss-noservice", chan->language);
07117 if (res >= 0)
07118 ast_waitstream(chan, "");
07119 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07120 ast_hangup(chan);
07121 goto quit;
07122 }
07123 break;
07124 case SIG_FXOLS:
07125 case SIG_FXOGS:
07126 case SIG_FXOKS:
07127
07128 timeout = firstdigittimeout;
07129
07130
07131 if (p->subs[SUB_THREEWAY].owner)
07132 timeout = 999999;
07133 while (len < AST_MAX_EXTENSION-1) {
07134
07135
07136 if (p->immediate)
07137 res = 's';
07138 else
07139 res = ast_waitfordigit(chan, timeout);
07140 timeout = 0;
07141 if (res < 0) {
07142 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07143 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07144 ast_hangup(chan);
07145 goto quit;
07146 } else if (res) {
07147 exten[len++]=res;
07148 exten[len] = '\0';
07149 }
07150 if (!ast_ignore_pattern(chan->context, exten))
07151 tone_zone_play_tone(p->subs[index].dfd, -1);
07152 else
07153 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07154 if (!strcmp(exten,ast_pickup_ext())) {
07155
07156
07157
07158
07159 if (index == SUB_REAL) {
07160
07161 if (p->subs[SUB_THREEWAY].owner) {
07162
07163
07164 alloc_sub(p, SUB_CALLWAIT);
07165 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07166 unalloc_sub(p, SUB_THREEWAY);
07167 }
07168 dahdi_enable_ec(p);
07169 if (ast_pickup_call(chan)) {
07170 ast_log(LOG_DEBUG, "No call pickup possible...\n");
07171 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07172 dahdi_wait_event(p->subs[index].dfd);
07173 }
07174 ast_hangup(chan);
07175 goto quit;
07176 } else {
07177 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07178 ast_hangup(chan);
07179 goto quit;
07180 }
07181
07182 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07183 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07184 if (getforward) {
07185
07186 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
07187 if (option_verbose > 2)
07188 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07189 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07190 if (res)
07191 break;
07192 usleep(500000);
07193 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07194 sleep(1);
07195 memset(exten, 0, sizeof(exten));
07196 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07197 len = 0;
07198 getforward = 0;
07199 } else {
07200 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07201 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07202 if (!ast_strlen_zero(p->cid_num)) {
07203 if (!p->hidecallerid)
07204 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07205 else
07206 ast_set_callerid(chan, NULL, NULL, p->cid_num);
07207 }
07208 if (!ast_strlen_zero(p->cid_name)) {
07209 if (!p->hidecallerid)
07210 ast_set_callerid(chan, NULL, p->cid_name, NULL);
07211 }
07212 ast_setstate(chan, AST_STATE_RING);
07213 dahdi_enable_ec(p);
07214 res = ast_pbx_run(chan);
07215 if (res) {
07216 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07217 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07218 }
07219 goto quit;
07220 }
07221 } else {
07222
07223
07224 timeout = matchdigittimeout;
07225 }
07226 } else if (res == 0) {
07227 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07228 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07229 dahdi_wait_event(p->subs[index].dfd);
07230 ast_hangup(chan);
07231 goto quit;
07232 } else if (p->callwaiting && !strcmp(exten, "*70")) {
07233 if (option_verbose > 2)
07234 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07235
07236 p->callwaiting = 0;
07237 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07238 if (res) {
07239 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07240 chan->name, strerror(errno));
07241 }
07242 len = 0;
07243 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07244 memset(exten, 0, sizeof(exten));
07245 timeout = firstdigittimeout;
07246
07247 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07248 if (option_verbose > 2)
07249 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07250
07251 p->hidecallerid = 1;
07252 if (chan->cid.cid_num)
07253 free(chan->cid.cid_num);
07254 chan->cid.cid_num = NULL;
07255 if (chan->cid.cid_name)
07256 free(chan->cid.cid_name);
07257 chan->cid.cid_name = NULL;
07258 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07259 if (res) {
07260 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07261 chan->name, strerror(errno));
07262 }
07263 len = 0;
07264 memset(exten, 0, sizeof(exten));
07265 timeout = firstdigittimeout;
07266 } else if (p->callreturn && !strcmp(exten, "*69")) {
07267 res = 0;
07268 if (!ast_strlen_zero(p->lastcid_num)) {
07269 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07270 }
07271 if (!res)
07272 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07273 break;
07274 } else if (!strcmp(exten, "*78")) {
07275
07276 if (option_verbose > 2)
07277 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07278 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07279 "Channel: %s/%d\r\n"
07280 "Status: enabled\r\n", dahdi_chan_name, p->channel);
07281 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07282 p->dnd = 1;
07283 getforward = 0;
07284 memset(exten, 0, sizeof(exten));
07285 len = 0;
07286 } else if (!strcmp(exten, "*79")) {
07287
07288 if (option_verbose > 2)
07289 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07290 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07291 "Channel: %s/%d\r\n"
07292 "Status: disabled\r\n", dahdi_chan_name, p->channel);
07293 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07294 p->dnd = 0;
07295 getforward = 0;
07296 memset(exten, 0, sizeof(exten));
07297 len = 0;
07298 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07299 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07300 getforward = 1;
07301 memset(exten, 0, sizeof(exten));
07302 len = 0;
07303 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07304 if (option_verbose > 2)
07305 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07306 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07307 memset(p->call_forward, 0, sizeof(p->call_forward));
07308 getforward = 0;
07309 memset(exten, 0, sizeof(exten));
07310 len = 0;
07311 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07312 p->subs[SUB_THREEWAY].owner &&
07313 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07314
07315
07316 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07317 if (option_verbose > 2)
07318 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07319 break;
07320 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07321 if (option_verbose > 2)
07322 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07323 res = ast_db_put("blacklist", p->lastcid_num, "1");
07324 if (!res) {
07325 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07326 memset(exten, 0, sizeof(exten));
07327 len = 0;
07328 }
07329 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07330 if (option_verbose > 2)
07331 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07332
07333 p->hidecallerid = 0;
07334 if (chan->cid.cid_num)
07335 free(chan->cid.cid_num);
07336 chan->cid.cid_num = NULL;
07337 if (chan->cid.cid_name)
07338 free(chan->cid.cid_name);
07339 chan->cid.cid_name = NULL;
07340 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07341 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07342 if (res) {
07343 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07344 chan->name, strerror(errno));
07345 }
07346 len = 0;
07347 memset(exten, 0, sizeof(exten));
07348 timeout = firstdigittimeout;
07349 } else if (!strcmp(exten, "*0")) {
07350 struct ast_channel *nbridge =
07351 p->subs[SUB_THREEWAY].owner;
07352 struct dahdi_pvt *pbridge = NULL;
07353
07354 if (nbridge && ast_bridged_channel(nbridge))
07355 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07356 if (nbridge && pbridge &&
07357 (nbridge->tech == chan_tech) &&
07358 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07359 ISTRUNK(pbridge)) {
07360 int func = DAHDI_FLASH;
07361
07362 p->dop.dialstr[0] = '\0';
07363
07364 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07365 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07366 nbridge->name, strerror(errno));
07367 }
07368 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07369 unalloc_sub(p, SUB_THREEWAY);
07370 p->owner = p->subs[SUB_REAL].owner;
07371 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07372 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07373 ast_hangup(chan);
07374 goto quit;
07375 } else {
07376 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07377 dahdi_wait_event(p->subs[index].dfd);
07378 tone_zone_play_tone(p->subs[index].dfd, -1);
07379 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07380 unalloc_sub(p, SUB_THREEWAY);
07381 p->owner = p->subs[SUB_REAL].owner;
07382 ast_hangup(chan);
07383 goto quit;
07384 }
07385 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07386 ((exten[0] != '*') || (strlen(exten) > 2))) {
07387 if (option_debug)
07388 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);
07389 break;
07390 }
07391 if (!timeout)
07392 timeout = gendigittimeout;
07393 if (len && !ast_ignore_pattern(chan->context, exten))
07394 tone_zone_play_tone(p->subs[index].dfd, -1);
07395 }
07396 break;
07397 case SIG_FXSLS:
07398 case SIG_FXSGS:
07399 case SIG_FXSKS:
07400 #ifdef HAVE_PRI
07401 if (p->pri) {
07402
07403 struct ast_frame *f;
07404 int res;
07405 time_t start;
07406
07407 time(&start);
07408 ast_setstate(chan, AST_STATE_RING);
07409 while (time(NULL) < start + 3) {
07410 res = ast_waitfor(chan, 1000);
07411 if (res) {
07412 f = ast_read(chan);
07413 if (!f) {
07414 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07415 ast_hangup(chan);
07416 goto quit;
07417 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07418 res = 1;
07419 } else
07420 res = 0;
07421 ast_frfree(f);
07422 if (res) {
07423 ast_log(LOG_DEBUG, "Got ring!\n");
07424 res = 0;
07425 break;
07426 }
07427 }
07428 }
07429 }
07430 #endif
07431
07432 if (p->use_smdi && p->smdi_iface) {
07433 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07434
07435 if (smdi_msg != NULL) {
07436 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07437
07438 if (smdi_msg->type == 'B')
07439 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07440 else if (smdi_msg->type == 'N')
07441 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07442
07443 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
07444 } else {
07445 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07446 }
07447 }
07448
07449 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07450 number = smdi_msg->calling_st;
07451
07452
07453
07454
07455 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
07456
07457 if (p->cid_signalling == CID_SIG_DTMF) {
07458 int i = 0;
07459 cs = NULL;
07460 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
07461 "channel %s\n", chan->name);
07462 dahdi_setlinear(p->subs[index].dfd, 0);
07463 res = 2000;
07464 for (;;) {
07465 struct ast_frame *f;
07466 res = ast_waitfor(chan, res);
07467 if (res <= 0) {
07468 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07469 "Exiting simple switch\n");
07470 ast_hangup(chan);
07471 goto quit;
07472 }
07473 f = ast_read(chan);
07474 if (!f)
07475 break;
07476 if (f->frametype == AST_FRAME_DTMF) {
07477 dtmfbuf[i++] = f->subclass;
07478 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07479 res = 2000;
07480 }
07481 ast_frfree(f);
07482 if (chan->_state == AST_STATE_RING ||
07483 chan->_state == AST_STATE_RINGING)
07484 break;
07485 }
07486 dtmfbuf[i] = '\0';
07487 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07488
07489 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
07490 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07491 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07492 dtmfcid, flags);
07493
07494 if (!ast_strlen_zero(dtmfcid))
07495 number = dtmfcid;
07496 else
07497 number = NULL;
07498
07499 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07500 cs = callerid_new(p->cid_signalling);
07501 if (cs) {
07502 samples = 0;
07503 #if 1
07504 bump_gains(p);
07505 #endif
07506
07507 dahdi_setlinear(p->subs[index].dfd, 0);
07508
07509
07510 for (;;) {
07511 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07512 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07513 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07514 callerid_free(cs);
07515 ast_hangup(chan);
07516 goto quit;
07517 }
07518 if (i & DAHDI_IOMUX_SIGEVENT) {
07519 res = dahdi_get_event(p->subs[index].dfd);
07520 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07521
07522 if (p->cid_signalling == CID_SIG_V23_JP) {
07523 #ifdef DAHDI_EVENT_RINGBEGIN
07524 if (res == DAHDI_EVENT_RINGBEGIN) {
07525 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07526 usleep(1);
07527 }
07528 #endif
07529 } else {
07530 res = 0;
07531 break;
07532 }
07533 } else if (i & DAHDI_IOMUX_READ) {
07534 res = read(p->subs[index].dfd, buf, sizeof(buf));
07535 if (res < 0) {
07536 if (errno != ELAST) {
07537 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07538 callerid_free(cs);
07539 ast_hangup(chan);
07540 goto quit;
07541 }
07542 break;
07543 }
07544 samples += res;
07545
07546 if (p->cid_signalling == CID_SIG_V23_JP) {
07547 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07548 } else {
07549 res = callerid_feed(cs, buf, res, AST_LAW(p));
07550 }
07551
07552 if (res < 0) {
07553 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07554 break;
07555 } else if (res)
07556 break;
07557 else if (samples > (8000 * 10))
07558 break;
07559 }
07560 }
07561 if (res == 1) {
07562 callerid_get(cs, &name, &number, &flags);
07563 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07564 }
07565
07566 if (p->cid_signalling == CID_SIG_V23_JP) {
07567 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07568 usleep(1);
07569 res = 4000;
07570 } else {
07571
07572
07573 res = 2000;
07574 }
07575
07576 for (;;) {
07577 struct ast_frame *f;
07578 res = ast_waitfor(chan, res);
07579 if (res <= 0) {
07580 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07581 "Exiting simple switch\n");
07582 ast_hangup(chan);
07583 goto quit;
07584 }
07585 if (!(f = ast_read(chan))) {
07586 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07587 ast_hangup(chan);
07588 goto quit;
07589 }
07590 ast_frfree(f);
07591 if (chan->_state == AST_STATE_RING ||
07592 chan->_state == AST_STATE_RINGING)
07593 break;
07594 }
07595
07596
07597
07598 if (p->usedistinctiveringdetection) {
07599 len = 0;
07600 distMatches = 0;
07601
07602 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07603 curRingData[receivedRingT] = 0;
07604 receivedRingT = 0;
07605 counter = 0;
07606 counter1 = 0;
07607
07608 if (strcmp(p->context,p->defcontext) != 0) {
07609 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07610 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07611 }
07612
07613 for (;;) {
07614 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07615 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07616 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07617 callerid_free(cs);
07618 ast_hangup(chan);
07619 goto quit;
07620 }
07621 if (i & DAHDI_IOMUX_SIGEVENT) {
07622 res = dahdi_get_event(p->subs[index].dfd);
07623 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07624 res = 0;
07625
07626
07627 curRingData[receivedRingT] = p->ringt;
07628
07629 if (p->ringt < p->ringt_base/2)
07630 break;
07631
07632
07633 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07634 break;
07635 } else if (i & DAHDI_IOMUX_READ) {
07636 res = read(p->subs[index].dfd, buf, sizeof(buf));
07637 if (res < 0) {
07638 if (errno != ELAST) {
07639 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07640 callerid_free(cs);
07641 ast_hangup(chan);
07642 goto quit;
07643 }
07644 break;
07645 }
07646 if (p->ringt)
07647 p->ringt--;
07648 if (p->ringt == 1) {
07649 res = -1;
07650 break;
07651 }
07652 }
07653 }
07654 if (option_verbose > 2)
07655
07656 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07657
07658 for (counter = 0; counter < 3; counter++) {
07659
07660
07661 distMatches = 0;
07662 for (counter1 = 0; counter1 < 3; counter1++) {
07663 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07664 (p->drings.ringnum[counter].ring[counter1]-10)) {
07665 distMatches++;
07666 }
07667 }
07668 if (distMatches == 3) {
07669
07670 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07671 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07672 if (option_verbose > 2)
07673 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07674 break;
07675 }
07676 }
07677 }
07678
07679 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07680 #if 1
07681 restore_gains(p);
07682 #endif
07683 } else
07684 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07685 } else {
07686 ast_log(LOG_WARNING, "Channel %s in prering "
07687 "state, but I have nothing to do. "
07688 "Terminating simple switch, should be "
07689 "restarted by the actual ring.\n",
07690 chan->name);
07691 ast_hangup(chan);
07692 goto quit;
07693 }
07694 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07695
07696 cs = callerid_new(p->cid_signalling);
07697 if (cs) {
07698 #if 1
07699 bump_gains(p);
07700 #endif
07701 samples = 0;
07702 len = 0;
07703 distMatches = 0;
07704
07705 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07706 curRingData[receivedRingT] = 0;
07707 receivedRingT = 0;
07708 counter = 0;
07709 counter1 = 0;
07710
07711 if (strcmp(p->context,p->defcontext) != 0) {
07712 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07713 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07714 }
07715
07716
07717 dahdi_setlinear(p->subs[index].dfd, 0);
07718 for (;;) {
07719 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07720 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07721 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07722 callerid_free(cs);
07723 ast_hangup(chan);
07724 goto quit;
07725 }
07726 if (i & DAHDI_IOMUX_SIGEVENT) {
07727 res = dahdi_get_event(p->subs[index].dfd);
07728 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07729
07730 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07731 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07732 p->polarity = POLARITY_IDLE;
07733 callerid_free(cs);
07734 ast_hangup(chan);
07735 goto quit;
07736 }
07737 res = 0;
07738
07739
07740 curRingData[receivedRingT] = p->ringt;
07741
07742 if (p->ringt < p->ringt_base/2)
07743 break;
07744
07745
07746 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07747 break;
07748 } else if (i & DAHDI_IOMUX_READ) {
07749 res = read(p->subs[index].dfd, buf, sizeof(buf));
07750 if (res < 0) {
07751 if (errno != ELAST) {
07752 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07753 callerid_free(cs);
07754 ast_hangup(chan);
07755 goto quit;
07756 }
07757 break;
07758 }
07759 if (p->ringt)
07760 p->ringt--;
07761 if (p->ringt == 1) {
07762 res = -1;
07763 break;
07764 }
07765 samples += res;
07766 res = callerid_feed(cs, buf, res, AST_LAW(p));
07767 if (res < 0) {
07768 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07769 break;
07770 } else if (res)
07771 break;
07772 else if (samples > (8000 * 10))
07773 break;
07774 }
07775 }
07776 if (res == 1) {
07777 callerid_get(cs, &name, &number, &flags);
07778 if (option_debug)
07779 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07780 }
07781 if (distinctiveringaftercid == 1) {
07782
07783 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07784 curRingData[receivedRingT] = 0;
07785 }
07786 receivedRingT = 0;
07787 if (option_verbose > 2)
07788 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
07789 for (;;) {
07790 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07791 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07792 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07793 callerid_free(cs);
07794 ast_hangup(chan);
07795 goto quit;
07796 }
07797 if (i & DAHDI_IOMUX_SIGEVENT) {
07798 res = dahdi_get_event(p->subs[index].dfd);
07799 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07800 res = 0;
07801
07802
07803 curRingData[receivedRingT] = p->ringt;
07804
07805 if (p->ringt < p->ringt_base/2)
07806 break;
07807
07808
07809 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07810 break;
07811 } else if (i & DAHDI_IOMUX_READ) {
07812 res = read(p->subs[index].dfd, buf, sizeof(buf));
07813 if (res < 0) {
07814 if (errno != ELAST) {
07815 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07816 callerid_free(cs);
07817 ast_hangup(chan);
07818 goto quit;
07819 }
07820 break;
07821 }
07822 if (p->ringt)
07823 p->ringt--;
07824 if (p->ringt == 1) {
07825 res = -1;
07826 break;
07827 }
07828 }
07829 }
07830 }
07831 if (p->usedistinctiveringdetection) {
07832 if (option_verbose > 2)
07833
07834 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07835
07836 for (counter = 0; counter < 3; counter++) {
07837
07838
07839 if (option_verbose > 2)
07840
07841 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
07842 p->drings.ringnum[counter].ring[0],
07843 p->drings.ringnum[counter].ring[1],
07844 p->drings.ringnum[counter].ring[2]);
07845 distMatches = 0;
07846 for (counter1 = 0; counter1 < 3; counter1++) {
07847 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07848 (p->drings.ringnum[counter].ring[counter1]-10)) {
07849 distMatches++;
07850 }
07851 }
07852 if (distMatches == 3) {
07853
07854 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07855 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07856 if (option_verbose > 2)
07857 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07858 break;
07859 }
07860 }
07861 }
07862
07863 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07864 #if 1
07865 restore_gains(p);
07866 #endif
07867 if (res < 0) {
07868 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07869 }
07870 } else
07871 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07872 }
07873 else
07874 cs = NULL;
07875
07876 if (number)
07877 ast_shrink_phone_number(number);
07878 ast_set_callerid(chan, number, name, number);
07879
07880 if (smdi_msg)
07881 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07882
07883 if (cs)
07884 callerid_free(cs);
07885
07886 ast_setstate(chan, AST_STATE_RING);
07887 chan->rings = 1;
07888 p->ringt = p->ringt_base;
07889 res = ast_pbx_run(chan);
07890 if (res) {
07891 ast_hangup(chan);
07892 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07893 }
07894 goto quit;
07895 default:
07896 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
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 }
07901 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07902 if (res < 0)
07903 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07904 ast_hangup(chan);
07905 quit:
07906 ast_mutex_lock(&ss_thread_lock);
07907 ss_thread_count--;
07908 ast_cond_signal(&ss_thread_complete);
07909 ast_mutex_unlock(&ss_thread_lock);
07910 return NULL;
07911 }
07912
07913
07914 static int dahdi_destroy_channel_bynum(int channel)
07915 {
07916 struct dahdi_pvt *tmp = NULL;
07917 struct dahdi_pvt *prev = NULL;
07918
07919 ast_mutex_lock(&iflock);
07920 tmp = iflist;
07921 while (tmp) {
07922 if (tmp->channel == channel) {
07923 int x = DAHDI_FLASH;
07924 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07925 destroy_channel(prev, tmp, 1);
07926 ast_mutex_unlock(&iflock);
07927 ast_module_unref(ast_module_info->self);
07928 return RESULT_SUCCESS;
07929 }
07930 prev = tmp;
07931 tmp = tmp->next;
07932 }
07933 ast_mutex_unlock(&iflock);
07934 return RESULT_FAILURE;
07935 }
07936
07937 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
07938 {
07939 int res;
07940 pthread_t threadid;
07941 pthread_attr_t attr;
07942 struct ast_channel *chan;
07943 pthread_attr_init(&attr);
07944 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07945
07946 switch (event) {
07947 case DAHDI_EVENT_NONE:
07948 case DAHDI_EVENT_BITSCHANGED:
07949 break;
07950 case DAHDI_EVENT_WINKFLASH:
07951 case DAHDI_EVENT_RINGOFFHOOK:
07952 if (i->inalarm) break;
07953 if (i->radio) break;
07954
07955 switch (i->sig) {
07956 case SIG_FXOLS:
07957 case SIG_FXOGS:
07958 case SIG_FXOKS:
07959 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07960 if (res && (errno == EBUSY))
07961 break;
07962 if (i->cidspill) {
07963
07964 free(i->cidspill);
07965 i->cidspill = NULL;
07966 }
07967 if (i->immediate) {
07968 dahdi_enable_ec(i);
07969
07970 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07971 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07972 if (!chan) {
07973 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07974 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07975 if (res < 0)
07976 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07977 }
07978 } else {
07979
07980 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07981 if (chan) {
07982 if (has_voicemail(i))
07983 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07984 else
07985 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07986 if (res < 0)
07987 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
07988 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07989 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07990 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07991 if (res < 0)
07992 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07993 ast_hangup(chan);
07994 }
07995 } else
07996 ast_log(LOG_WARNING, "Unable to create channel\n");
07997 }
07998 break;
07999 case SIG_FXSLS:
08000 case SIG_FXSGS:
08001 case SIG_FXSKS:
08002 i->ringt = i->ringt_base;
08003
08004 case SIG_EMWINK:
08005 case SIG_FEATD:
08006 case SIG_FEATDMF:
08007 case SIG_FEATDMF_TA:
08008 case SIG_E911:
08009 case SIG_FGC_CAMA:
08010 case SIG_FGC_CAMAMF:
08011 case SIG_FEATB:
08012 case SIG_EM:
08013 case SIG_EM_E1:
08014 case SIG_SFWINK:
08015 case SIG_SF_FEATD:
08016 case SIG_SF_FEATDMF:
08017 case SIG_SF_FEATB:
08018 case SIG_SF:
08019
08020 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08021 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08022 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08023 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08024 if (res < 0)
08025 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08026 ast_hangup(chan);
08027 } else if (!chan) {
08028 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08029 }
08030 break;
08031 default:
08032 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08033 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08034 if (res < 0)
08035 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08036 pthread_attr_destroy(&attr);
08037 return NULL;
08038 }
08039 break;
08040 case DAHDI_EVENT_NOALARM:
08041 i->inalarm = 0;
08042 if (!i->unknown_alarm) {
08043 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08044 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08045 "Channel: %d\r\n", i->channel);
08046 } else {
08047 i->unknown_alarm = 0;
08048 }
08049 break;
08050 case DAHDI_EVENT_ALARM:
08051 i->inalarm = 1;
08052 res = get_alarms(i);
08053 handle_alarms(i, res);
08054
08055 case DAHDI_EVENT_ONHOOK:
08056 if (i->radio)
08057 break;
08058
08059 switch (i->sig) {
08060 case SIG_FXOLS:
08061 case SIG_FXOGS:
08062 case SIG_FEATD:
08063 case SIG_FEATDMF:
08064 case SIG_FEATDMF_TA:
08065 case SIG_E911:
08066 case SIG_FGC_CAMA:
08067 case SIG_FGC_CAMAMF:
08068 case SIG_FEATB:
08069 case SIG_EM:
08070 case SIG_EM_E1:
08071 case SIG_EMWINK:
08072 case SIG_SF_FEATD:
08073 case SIG_SF_FEATDMF:
08074 case SIG_SF_FEATB:
08075 case SIG_SF:
08076 case SIG_SFWINK:
08077 case SIG_FXSLS:
08078 case SIG_FXSGS:
08079 case SIG_FXSKS:
08080 case SIG_GR303FXSKS:
08081 dahdi_disable_ec(i);
08082 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08083 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08084 break;
08085 case SIG_GR303FXOKS:
08086 case SIG_FXOKS:
08087 dahdi_disable_ec(i);
08088
08089 #ifdef ZHONE_HACK
08090 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08091 usleep(1);
08092 #endif
08093 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08094 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08095 break;
08096 case SIG_PRI:
08097 dahdi_disable_ec(i);
08098 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08099 break;
08100 default:
08101 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08102 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08103 pthread_attr_destroy(&attr);
08104 return NULL;
08105 }
08106 break;
08107 case DAHDI_EVENT_POLARITY:
08108 switch (i->sig) {
08109 case SIG_FXSLS:
08110 case SIG_FXSKS:
08111 case SIG_FXSGS:
08112
08113
08114
08115
08116 if (i->hanguponpolarityswitch)
08117 i->polarity = POLARITY_REV;
08118
08119 if (i->cid_start == CID_START_POLARITY) {
08120 i->polarity = POLARITY_REV;
08121 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08122 "CID detection on channel %d\n",
08123 i->channel);
08124 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08125 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08126 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08127 }
08128 }
08129 break;
08130 default:
08131 ast_log(LOG_WARNING, "handle_init_event detected "
08132 "polarity reversal on non-FXO (SIG_FXS) "
08133 "interface %d\n", i->channel);
08134 }
08135 break;
08136 case DAHDI_EVENT_REMOVED:
08137 ast_log(LOG_NOTICE,
08138 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08139 i->channel);
08140 pthread_attr_destroy(&attr);
08141 return i;
08142 }
08143 pthread_attr_destroy(&attr);
08144 return NULL;
08145 }
08146
08147 static void *do_monitor(void *data)
08148 {
08149 int count, res, res2, spoint, pollres=0;
08150 struct dahdi_pvt *i;
08151 struct dahdi_pvt *last = NULL;
08152 struct dahdi_pvt *doomed;
08153 time_t thispass = 0, lastpass = 0;
08154 int found;
08155 char buf[1024];
08156 struct pollfd *pfds=NULL;
08157 int lastalloc = -1;
08158
08159
08160
08161 #if 0
08162 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08163 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08164 return NULL;
08165 }
08166 ast_log(LOG_DEBUG, "Monitor starting...\n");
08167 #endif
08168 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08169
08170 for (;;) {
08171
08172 ast_mutex_lock(&iflock);
08173 if (!pfds || (lastalloc != ifcount)) {
08174 if (pfds) {
08175 free(pfds);
08176 pfds = NULL;
08177 }
08178 if (ifcount) {
08179 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08180 ast_mutex_unlock(&iflock);
08181 return NULL;
08182 }
08183 }
08184 lastalloc = ifcount;
08185 }
08186
08187
08188 count = 0;
08189 i = iflist;
08190 while (i) {
08191 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08192 if (!i->owner && !i->subs[SUB_REAL].owner) {
08193
08194 pfds[count].fd = i->subs[SUB_REAL].dfd;
08195 pfds[count].events = POLLPRI;
08196 pfds[count].revents = 0;
08197
08198 if (i->cidspill)
08199 pfds[count].events |= POLLIN;
08200 count++;
08201 }
08202 }
08203 i = i->next;
08204 }
08205
08206 ast_mutex_unlock(&iflock);
08207
08208 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08209 pthread_testcancel();
08210
08211 res = poll(pfds, count, 1000);
08212 pthread_testcancel();
08213 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08214
08215
08216 if (res < 0) {
08217 if ((errno != EAGAIN) && (errno != EINTR))
08218 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08219 continue;
08220 }
08221
08222
08223 ast_mutex_lock(&iflock);
08224 found = 0;
08225 spoint = 0;
08226 lastpass = thispass;
08227 thispass = time(NULL);
08228 doomed = NULL;
08229 for (i = iflist;; i = i->next) {
08230 if (doomed) {
08231 int res;
08232 res = dahdi_destroy_channel_bynum(doomed->channel);
08233 if (!res) {
08234 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08235 }
08236 doomed = NULL;
08237 }
08238 if (!i) {
08239 break;
08240 }
08241 if (thispass != lastpass) {
08242 if (!found && ((i == last) || ((i == iflist) && !last))) {
08243 last = i;
08244 if (last) {
08245 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08246 (last->sig & __DAHDI_SIG_FXO)) {
08247 res = ast_app_has_voicemail(last->mailbox, NULL);
08248 if (last->msgstate != res) {
08249 int x;
08250 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08251 x = DAHDI_FLUSH_BOTH;
08252 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08253 if (res2)
08254 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08255 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08256
08257 x = 4000;
08258 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08259 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08260 last->cidpos = 0;
08261 last->msgstate = res;
08262 last->onhooktime = thispass;
08263 }
08264 found ++;
08265 }
08266 }
08267 last = last->next;
08268 }
08269 }
08270 }
08271 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08272 if (i->radio && !i->owner)
08273 {
08274 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08275 if (res)
08276 {
08277 if (option_debug)
08278 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08279
08280 ast_mutex_unlock(&iflock);
08281 doomed = handle_init_event(i, res);
08282 ast_mutex_lock(&iflock);
08283 }
08284 continue;
08285 }
08286 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08287 if (pollres & POLLIN) {
08288 if (i->owner || i->subs[SUB_REAL].owner) {
08289 #ifdef HAVE_PRI
08290 if (!i->pri)
08291 #endif
08292 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08293 continue;
08294 }
08295 if (!i->cidspill) {
08296 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08297 continue;
08298 }
08299 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08300 if (res > 0) {
08301
08302 if (res > i->cidlen - i->cidpos)
08303 res = i->cidlen - i->cidpos;
08304 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
08305 if (res2 > 0) {
08306 i->cidpos += res2;
08307 if (i->cidpos >= i->cidlen) {
08308 free(i->cidspill);
08309 i->cidspill = 0;
08310 i->cidpos = 0;
08311 i->cidlen = 0;
08312 }
08313 } else {
08314 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
08315 i->msgstate = -1;
08316 }
08317 } else {
08318 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08319 }
08320 }
08321 if (pollres & POLLPRI) {
08322 if (i->owner || i->subs[SUB_REAL].owner) {
08323 #ifdef HAVE_PRI
08324 if (!i->pri)
08325 #endif
08326 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08327 continue;
08328 }
08329 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08330 if (option_debug)
08331 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08332
08333 ast_mutex_unlock(&iflock);
08334 doomed = handle_init_event(i, res);
08335 ast_mutex_lock(&iflock);
08336 }
08337 }
08338 }
08339 ast_mutex_unlock(&iflock);
08340 }
08341
08342 return NULL;
08343
08344 }
08345
08346 static int restart_monitor(void)
08347 {
08348 pthread_attr_t attr;
08349 pthread_attr_init(&attr);
08350 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08351
08352 if (monitor_thread == AST_PTHREADT_STOP)
08353 return 0;
08354 ast_mutex_lock(&monlock);
08355 if (monitor_thread == pthread_self()) {
08356 ast_mutex_unlock(&monlock);
08357 ast_log(LOG_WARNING, "Cannot kill myself\n");
08358 return -1;
08359 }
08360 if (monitor_thread != AST_PTHREADT_NULL) {
08361
08362 pthread_kill(monitor_thread, SIGURG);
08363 } else {
08364
08365 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08366 ast_mutex_unlock(&monlock);
08367 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08368 pthread_attr_destroy(&attr);
08369 return -1;
08370 }
08371 }
08372 ast_mutex_unlock(&monlock);
08373 pthread_attr_destroy(&attr);
08374 return 0;
08375 }
08376
08377 #ifdef HAVE_OPENR2
08378 static struct dahdi_mfcr2 *mfcr2_get_context(int id)
08379 {
08380 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08381 ast_log(LOG_ERROR, "No more R2 links available!.\n");
08382 return NULL;
08383 }
08384 return &r2links[id];
08385 }
08386 #endif
08387
08388 #ifdef HAVE_PRI
08389 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08390 {
08391 int x;
08392 int trunkgroup;
08393
08394 trunkgroup = pris[*span].mastertrunkgroup;
08395 if (trunkgroup) {
08396
08397 for (x = 0; x < NUM_SPANS; x++) {
08398 if (pris[x].trunkgroup == trunkgroup) {
08399 *span = x;
08400 return 0;
08401 }
08402 }
08403 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08404 *span = -1;
08405 } else {
08406 if (pris[*span].trunkgroup) {
08407 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08408 *span = -1;
08409 } else if (pris[*span].mastertrunkgroup) {
08410 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08411 *span = -1;
08412 } else {
08413 if (si->totalchans == 31) {
08414
08415 pris[*span].dchannels[0] = 16 + offset;
08416 } else if (si->totalchans == 24) {
08417
08418 pris[*span].dchannels[0] = 24 + offset;
08419 } else if (si->totalchans == 3) {
08420
08421 pris[*span].dchannels[0] = 3 + offset;
08422 } else {
08423 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);
08424 *span = -1;
08425 return 0;
08426 }
08427 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08428 pris[*span].offset = offset;
08429 pris[*span].span = *span + 1;
08430 }
08431 }
08432 return 0;
08433 }
08434
08435 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08436 {
08437 struct dahdi_spaninfo si;
08438 struct dahdi_params p;
08439 int fd;
08440 int span;
08441 int ospan=0;
08442 int x,y;
08443 for (x = 0; x < NUM_SPANS; x++) {
08444 if (pris[x].trunkgroup == trunkgroup) {
08445 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08446 return -1;
08447 }
08448 }
08449 for (y = 0; y < NUM_DCHANS; y++) {
08450 if (!channels[y])
08451 break;
08452 memset(&si, 0, sizeof(si));
08453 memset(&p, 0, sizeof(p));
08454 fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
08455 if (fd < 0) {
08456 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08457 return -1;
08458 }
08459 x = channels[y];
08460 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08461 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08462 close(fd);
08463 return -1;
08464 }
08465 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08466 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08467 return -1;
08468 }
08469 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08470 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08471 close(fd);
08472 return -1;
08473 }
08474 span = p.spanno - 1;
08475 if (pris[span].trunkgroup) {
08476 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08477 close(fd);
08478 return -1;
08479 }
08480 if (pris[span].pvts[0]) {
08481 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08482 close(fd);
08483 return -1;
08484 }
08485 if (!y) {
08486 pris[span].trunkgroup = trunkgroup;
08487 pris[span].offset = channels[y] - p.chanpos;
08488 ospan = span;
08489 }
08490 pris[ospan].dchannels[y] = channels[y];
08491 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08492 pris[span].span = span + 1;
08493 close(fd);
08494 }
08495 return 0;
08496 }
08497
08498 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08499 {
08500 if (pris[span].mastertrunkgroup) {
08501 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);
08502 return -1;
08503 }
08504 pris[span].mastertrunkgroup = trunkgroup;
08505 pris[span].prilogicalspan = logicalspan;
08506 return 0;
08507 }
08508
08509 #endif
08510
08511 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08512 {
08513
08514 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08515 char fn[80];
08516 #if 1
08517 struct dahdi_bufferinfo bi;
08518 #endif
08519 int res;
08520 int span=0;
08521 int here = 0;
08522 int x;
08523 struct dahdi_pvt **wlist;
08524 struct dahdi_pvt **wend;
08525 struct dahdi_params p;
08526
08527 wlist = &iflist;
08528 wend = &ifend;
08529
08530 #ifdef HAVE_PRI
08531 if (pri) {
08532 wlist = &pri->crvs;
08533 wend = &pri->crvend;
08534 }
08535 #endif
08536
08537 tmp2 = *wlist;
08538 prev = NULL;
08539
08540 while (tmp2) {
08541 if (!tmp2->destroy) {
08542 if (tmp2->channel == channel) {
08543 tmp = tmp2;
08544 here = 1;
08545 break;
08546 }
08547 if (tmp2->channel > channel) {
08548 break;
08549 }
08550 }
08551 prev = tmp2;
08552 tmp2 = tmp2->next;
08553 }
08554
08555 if (!here && reloading != 1) {
08556 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08557 if (tmp)
08558 free(tmp);
08559 return NULL;
08560 }
08561 ast_mutex_init(&tmp->lock);
08562 ifcount++;
08563 for (x = 0; x < 3; x++)
08564 tmp->subs[x].dfd = -1;
08565 tmp->channel = channel;
08566 tmp->priindication_oob = conf->chan.priindication_oob;
08567 }
08568
08569 if (tmp) {
08570 int chan_sig = conf->chan.sig;
08571 if (!here) {
08572 if ((channel != CHAN_PSEUDO) && !pri) {
08573 int count = 0;
08574 snprintf(fn, sizeof(fn), "%d", channel);
08575
08576 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08577 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08578 usleep(1);
08579 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08580 count++;
08581 }
08582
08583 if (tmp->subs[SUB_REAL].dfd < 0) {
08584 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);
08585 destroy_dahdi_pvt(&tmp);
08586 return NULL;
08587 }
08588 memset(&p, 0, sizeof(p));
08589 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08590 if (res < 0) {
08591 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08592 destroy_dahdi_pvt(&tmp);
08593 return NULL;
08594 }
08595 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
08596 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));
08597 destroy_dahdi_pvt(&tmp);
08598 return NULL;
08599 }
08600 tmp->law = p.curlaw;
08601 tmp->span = p.spanno;
08602 span = p.spanno - 1;
08603 } else {
08604 if (channel == CHAN_PSEUDO)
08605 chan_sig = 0;
08606 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08607 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08608 return NULL;
08609 }
08610 }
08611 #ifdef HAVE_PRI
08612 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08613 int offset;
08614 int myswitchtype;
08615 int matchesdchan;
08616 int x,y;
08617 offset = 0;
08618 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08619 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08620 destroy_dahdi_pvt(&tmp);
08621 return NULL;
08622 }
08623 if (span >= NUM_SPANS) {
08624 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08625 destroy_dahdi_pvt(&tmp);
08626 return NULL;
08627 } else {
08628 struct dahdi_spaninfo si;
08629 si.spanno = 0;
08630 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08631 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08632 destroy_dahdi_pvt(&tmp);
08633 return NULL;
08634 }
08635
08636 tmp->logicalspan = pris[span].prilogicalspan;
08637 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08638 if (span < 0) {
08639 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08640 destroy_dahdi_pvt(&tmp);
08641 return NULL;
08642 }
08643 if (chan_sig == SIG_PRI)
08644 myswitchtype = conf->pri.switchtype;
08645 else
08646 myswitchtype = PRI_SWITCH_GR303_TMC;
08647
08648 matchesdchan=0;
08649 for (x = 0; x < NUM_SPANS; x++) {
08650 for (y = 0; y < NUM_DCHANS; y++) {
08651 if (pris[x].dchannels[y] == tmp->channel) {
08652 matchesdchan = 1;
08653 break;
08654 }
08655 }
08656 }
08657 offset = p.chanpos;
08658 if (!matchesdchan) {
08659 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08660 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08661 destroy_dahdi_pvt(&tmp);
08662 return NULL;
08663 }
08664 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08665 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08666 destroy_dahdi_pvt(&tmp);
08667 return NULL;
08668 }
08669 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08670 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08671 destroy_dahdi_pvt(&tmp);
08672 return NULL;
08673 }
08674 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08675 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08676 destroy_dahdi_pvt(&tmp);
08677 return NULL;
08678 }
08679 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08680 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08681 destroy_dahdi_pvt(&tmp);
08682 return NULL;
08683 }
08684 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08685 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08686 destroy_dahdi_pvt(&tmp);
08687 return NULL;
08688 }
08689 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08690 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08691 destroy_dahdi_pvt(&tmp);
08692 return NULL;
08693 }
08694 if (pris[span].numchans >= MAX_CHANNELS) {
08695 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08696 pris[span].trunkgroup);
08697 destroy_dahdi_pvt(&tmp);
08698 return NULL;
08699 }
08700 pris[span].nodetype = conf->pri.nodetype;
08701 pris[span].switchtype = myswitchtype;
08702 pris[span].nsf = conf->pri.nsf;
08703 pris[span].dialplan = conf->pri.dialplan;
08704 pris[span].localdialplan = conf->pri.localdialplan;
08705 pris[span].pvts[pris[span].numchans++] = tmp;
08706 pris[span].minunused = conf->pri.minunused;
08707 pris[span].minidle = conf->pri.minidle;
08708 pris[span].overlapdial = conf->pri.overlapdial;
08709 #ifdef HAVE_PRI_INBANDDISCONNECT
08710 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08711 #endif
08712 pris[span].facilityenable = conf->pri.facilityenable;
08713 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08714 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08715 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08716 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08717 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08718 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08719 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08720 pris[span].resetinterval = conf->pri.resetinterval;
08721
08722 tmp->pri = &pris[span];
08723 tmp->prioffset = offset;
08724 tmp->call = NULL;
08725 } else {
08726 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08727 destroy_dahdi_pvt(&tmp);
08728 return NULL;
08729 }
08730 }
08731 } else {
08732 tmp->prioffset = 0;
08733 }
08734 #endif
08735 #ifdef HAVE_OPENR2
08736 if (chan_sig == SIG_MFCR2 && reloading != 1) {
08737 char logdir[OR2_MAX_PATH];
08738 struct dahdi_mfcr2 *dahdi_r2;
08739 int threshold = 0;
08740 int snres = 0;
08741 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
08742 if (!dahdi_r2) {
08743 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
08744 } else if (!dahdi_r2->protocol_context){
08745 char tmplogdir[] = "/tmp";
08746 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
08747 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
08748 if (!dahdi_r2->protocol_context) {
08749 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
08750 destroy_dahdi_pvt(&tmp);
08751 return NULL;
08752 }
08753 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
08754 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
08755 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
08756 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
08757 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
08758 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
08759 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
08760 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
08761 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
08762 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
08763 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
08764 #endif
08765 if (ast_strlen_zero(mfcr2_cur_logdir)) {
08766 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
08767 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08768 }
08769 } else {
08770 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
08771 if (snres >= sizeof(logdir)) {
08772 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
08773 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08774 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08775 }
08776 } else {
08777 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08778 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
08779 }
08780 }
08781 }
08782 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
08783 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
08784 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
08785 }
08786 }
08787 }
08788 if (dahdi_r2) {
08789
08790 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
08791 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
08792 tmp->subs[SUB_REAL].dfd, NULL, NULL);
08793 if (!tmp->r2chan) {
08794 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
08795 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
08796 destroy_dahdi_pvt(&tmp);
08797 return NULL;
08798 }
08799 openr2_chan_set_client_data(tmp->r2chan, tmp);
08800
08801 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
08802 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
08803 if (mfcr2_cur_call_files) {
08804 openr2_chan_enable_call_files(tmp->r2chan);
08805 }
08806 tmp->mfcr2_category = mfcr2_cur_category;
08807 tmp->mfcr2 = dahdi_r2;
08808 tmp->mfcr2call = 0;
08809 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
08810 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
08811 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
08812 tmp->mfcr2_ani_index = 0;
08813 tmp->mfcr2_dnis_index = 0;
08814 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
08815 tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
08816 }
08817 }
08818 #endif
08819 } else {
08820 chan_sig = tmp->sig;
08821 if (tmp->subs[SUB_REAL].dfd > -1) {
08822 memset(&p, 0, sizeof(p));
08823 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08824 }
08825 }
08826
08827 switch (chan_sig) {
08828 case SIG_FXSKS:
08829 case SIG_FXSLS:
08830 case SIG_EM:
08831 case SIG_EM_E1:
08832 case SIG_EMWINK:
08833 case SIG_FEATD:
08834 case SIG_FEATDMF:
08835 case SIG_FEATDMF_TA:
08836 case SIG_FEATB:
08837 case SIG_E911:
08838 case SIG_SF:
08839 case SIG_SFWINK:
08840 case SIG_FGC_CAMA:
08841 case SIG_FGC_CAMAMF:
08842 case SIG_SF_FEATD:
08843 case SIG_SF_FEATDMF:
08844 case SIG_SF_FEATB:
08845 p.starttime = 250;
08846 break;
08847 }
08848
08849 if (tmp->radio) {
08850
08851 p.channo = channel;
08852 p.rxwinktime = 1;
08853 p.rxflashtime = 1;
08854 p.starttime = 1;
08855 p.debouncetime = 5;
08856 }
08857 if (!tmp->radio) {
08858 p.channo = channel;
08859
08860 if (conf->timing.prewinktime >= 0)
08861 p.prewinktime = conf->timing.prewinktime;
08862 if (conf->timing.preflashtime >= 0)
08863 p.preflashtime = conf->timing.preflashtime;
08864 if (conf->timing.winktime >= 0)
08865 p.winktime = conf->timing.winktime;
08866 if (conf->timing.flashtime >= 0)
08867 p.flashtime = conf->timing.flashtime;
08868 if (conf->timing.starttime >= 0)
08869 p.starttime = conf->timing.starttime;
08870 if (conf->timing.rxwinktime >= 0)
08871 p.rxwinktime = conf->timing.rxwinktime;
08872 if (conf->timing.rxflashtime >= 0)
08873 p.rxflashtime = conf->timing.rxflashtime;
08874 if (conf->timing.debouncetime >= 0)
08875 p.debouncetime = conf->timing.debouncetime;
08876 }
08877
08878
08879 if (tmp->subs[SUB_REAL].dfd >= 0)
08880 {
08881 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
08882 if (res < 0) {
08883 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
08884 destroy_dahdi_pvt(&tmp);
08885 return NULL;
08886 }
08887 }
08888 #if 1
08889 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
08890 memset(&bi, 0, sizeof(bi));
08891 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08892 if (!res) {
08893 bi.txbufpolicy = conf->chan.buf_policy;
08894 bi.rxbufpolicy = conf->chan.buf_policy;
08895 bi.numbufs = conf->chan.buf_no;
08896 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08897 if (res < 0) {
08898 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
08899 }
08900 } else
08901 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
08902 }
08903 #endif
08904 tmp->immediate = conf->chan.immediate;
08905 tmp->transfertobusy = conf->chan.transfertobusy;
08906 tmp->sig = chan_sig;
08907 tmp->outsigmod = conf->chan.outsigmod;
08908 tmp->ringt_base = ringt_base;
08909 tmp->firstradio = 0;
08910 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
08911 tmp->permcallwaiting = conf->chan.callwaiting;
08912 else
08913 tmp->permcallwaiting = 0;
08914
08915 tmp->destroy = 0;
08916 tmp->drings = drings;
08917 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
08918 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
08919 tmp->threewaycalling = conf->chan.threewaycalling;
08920 tmp->adsi = conf->chan.adsi;
08921 tmp->use_smdi = conf->chan.use_smdi;
08922 tmp->permhidecallerid = conf->chan.hidecallerid;
08923 tmp->callreturn = conf->chan.callreturn;
08924 tmp->echocancel = conf->chan.echocancel;
08925 tmp->echotraining = conf->chan.echotraining;
08926 tmp->pulse = conf->chan.pulse;
08927 if (tmp->echocancel)
08928 tmp->echocanbridged = conf->chan.echocanbridged;
08929 else {
08930 if (conf->chan.echocanbridged)
08931 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
08932 tmp->echocanbridged = 0;
08933 }
08934 tmp->busydetect = conf->chan.busydetect;
08935 tmp->busycount = conf->chan.busycount;
08936 tmp->busycompare = conf->chan.busycompare;
08937 tmp->busytonelength = conf->chan.busytonelength;
08938 tmp->busyquietlength = conf->chan.busyquietlength;
08939 tmp->busyfuzziness = conf->chan.busyfuzziness;
08940 tmp->silencethreshold = conf->chan.silencethreshold;
08941 tmp->callprogress = conf->chan.callprogress;
08942 tmp->cancallforward = conf->chan.cancallforward;
08943 tmp->dtmfrelax = conf->chan.dtmfrelax;
08944 tmp->callwaiting = tmp->permcallwaiting;
08945 tmp->hidecallerid = tmp->permhidecallerid;
08946 tmp->channel = channel;
08947 tmp->stripmsd = conf->chan.stripmsd;
08948 tmp->use_callerid = conf->chan.use_callerid;
08949 tmp->cid_signalling = conf->chan.cid_signalling;
08950 tmp->cid_start = conf->chan.cid_start;
08951 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
08952 tmp->restrictcid = conf->chan.restrictcid;
08953 tmp->use_callingpres = conf->chan.use_callingpres;
08954 tmp->priexclusive = conf->chan.priexclusive;
08955 if (tmp->usedistinctiveringdetection) {
08956 if (!tmp->use_callerid) {
08957 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
08958 tmp->use_callerid = 1;
08959 }
08960 }
08961
08962 if (tmp->cid_signalling == CID_SIG_SMDI) {
08963 if (!tmp->use_smdi) {
08964 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
08965 tmp->use_smdi = 1;
08966 }
08967 }
08968 if (tmp->use_smdi) {
08969 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
08970 if (!(tmp->smdi_iface)) {
08971 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
08972 tmp->use_smdi = 0;
08973 }
08974 }
08975
08976 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
08977 tmp->amaflags = conf->chan.amaflags;
08978 if (!here) {
08979 tmp->confno = -1;
08980 tmp->propconfno = -1;
08981 }
08982 tmp->canpark = conf->chan.canpark;
08983 tmp->transfer = conf->chan.transfer;
08984 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
08985 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
08986 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
08987 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
08988 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
08989 tmp->cid_ton = 0;
08990 if (chan_sig != SIG_PRI) {
08991 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
08992 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
08993 } else {
08994 tmp->cid_num[0] = '\0';
08995 tmp->cid_name[0] = '\0';
08996 }
08997 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
08998 tmp->msgstate = -1;
08999 tmp->group = conf->chan.group;
09000 tmp->callgroup = conf->chan.callgroup;
09001 tmp->pickupgroup= conf->chan.pickupgroup;
09002 tmp->rxgain = conf->chan.rxgain;
09003 tmp->txgain = conf->chan.txgain;
09004 tmp->tonezone = conf->chan.tonezone;
09005 tmp->onhooktime = time(NULL);
09006 if (tmp->subs[SUB_REAL].dfd > -1) {
09007 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09008 if (tmp->dsp)
09009 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09010 update_conf(tmp);
09011 if (!here) {
09012 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09013
09014 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09015 }
09016 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09017 #ifdef HAVE_PRI
09018
09019 if (tmp->pri && !pri_is_up(tmp->pri)) {
09020 tmp->inalarm = 1;
09021 }
09022 #endif
09023 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09024 tmp->inalarm = 1;
09025 handle_alarms(tmp, res);
09026 } else {
09027
09028
09029
09030
09031
09032
09033
09034
09035
09036
09037 tmp->unknown_alarm = 1;
09038 }
09039 }
09040
09041 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09042 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09043 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09044 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09045
09046 }
09047 if (tmp && !here) {
09048
09049 if (!*wlist) {
09050 *wlist = tmp;
09051 tmp->prev = NULL;
09052 tmp->next = NULL;
09053 *wend = tmp;
09054 } else {
09055
09056 struct dahdi_pvt *working = *wlist;
09057
09058
09059 if (working->channel > tmp->channel) {
09060 tmp->next = *wlist;
09061 tmp->prev = NULL;
09062 (*wlist)->prev = tmp;
09063 *wlist = tmp;
09064 } else {
09065
09066 while (working) {
09067
09068 if (working->next) {
09069 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09070 tmp->next = working->next;
09071 tmp->prev = working;
09072 working->next->prev = tmp;
09073 working->next = tmp;
09074 break;
09075 }
09076 } else {
09077
09078 if (working->channel < tmp->channel) {
09079 working->next = tmp;
09080 tmp->next = NULL;
09081 tmp->prev = working;
09082 *wend = tmp;
09083 break;
09084 }
09085 }
09086 working = working->next;
09087 }
09088 }
09089 }
09090 }
09091 return tmp;
09092 }
09093
09094 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09095 {
09096 int res;
09097 struct dahdi_params par;
09098
09099
09100 if (groupmatch) {
09101 if ((p->group & groupmatch) != groupmatch)
09102 return 0;
09103 *groupmatched = 1;
09104 }
09105
09106 if (channelmatch != -1) {
09107 if (p->channel != channelmatch)
09108 return 0;
09109 *channelmatched = 1;
09110 }
09111
09112 if (busy) {
09113 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09114 *busy = 1;
09115 }
09116
09117 if (p->dnd)
09118 return 0;
09119
09120 if (p->guardtime && (time(NULL) < p->guardtime))
09121 return 0;
09122
09123
09124 if (!p->owner) {
09125 #ifdef HAVE_PRI
09126
09127 if (p->pri) {
09128 if (p->resetting || p->call)
09129 return 0;
09130 else
09131 return 1;
09132 }
09133 #endif
09134 #ifdef HAVE_OPENR2
09135
09136 if (p->mfcr2) {
09137 if (p->mfcr2call || p->mfcr2block)
09138 return 0;
09139 else
09140 return 1;
09141 }
09142 #endif
09143 if (!(p->radio || (p->oprmode < 0)))
09144 {
09145 if (!p->sig || (p->sig == SIG_FXSLS))
09146 return 1;
09147
09148 if (p->subs[SUB_REAL].dfd > -1) {
09149 memset(&par, 0, sizeof(par));
09150 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09151 } else {
09152
09153 res = 0;
09154 par.rxisoffhook = 0;
09155 }
09156 if (res) {
09157 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09158 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09159
09160
09161
09162 if (par.rxbits > -1)
09163 return 1;
09164 if (par.rxisoffhook)
09165 return 1;
09166 else
09167 #ifdef DAHDI_CHECK_HOOKSTATE
09168 return 0;
09169 #else
09170 return 1;
09171 #endif
09172 } else if (par.rxisoffhook) {
09173 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09174
09175 return 0;
09176 }
09177 }
09178 return 1;
09179 }
09180
09181
09182 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09183 return 0;
09184
09185 if (!p->callwaiting) {
09186
09187 return 0;
09188 }
09189
09190 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09191
09192 return 0;
09193 }
09194
09195 if ((p->owner->_state != AST_STATE_UP) &&
09196 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09197
09198 return 0;
09199 }
09200 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09201
09202 return 0;
09203 }
09204
09205 return 1;
09206 }
09207
09208 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09209 {
09210 struct dahdi_pvt *p;
09211 struct dahdi_bufferinfo bi;
09212 int res;
09213
09214 if ((p = ast_malloc(sizeof(*p)))) {
09215 memcpy(p, src, sizeof(struct dahdi_pvt));
09216 ast_mutex_init(&p->lock);
09217 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09218
09219 if (p->subs[SUB_REAL].dfd < 0) {
09220 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09221 destroy_dahdi_pvt(&p);
09222 return NULL;
09223 }
09224 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09225 if (!res) {
09226 bi.txbufpolicy = p->buf_policy;
09227 bi.rxbufpolicy = p->buf_policy;
09228 bi.numbufs = p->buf_no;
09229 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09230 if (res < 0) {
09231 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09232 }
09233 } else
09234 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09235 }
09236 p->destroy = 1;
09237 p->next = iflist;
09238 p->prev = NULL;
09239 iflist = p;
09240 if (iflist->next)
09241 iflist->next->prev = p;
09242 return p;
09243 }
09244
09245
09246 #ifdef HAVE_PRI
09247 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09248 {
09249 int x;
09250 if (backwards)
09251 x = pri->numchans;
09252 else
09253 x = 0;
09254 for (;;) {
09255 if (backwards && (x < 0))
09256 break;
09257 if (!backwards && (x >= pri->numchans))
09258 break;
09259 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09260 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
09261 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09262 return x;
09263 }
09264 if (backwards)
09265 x--;
09266 else
09267 x++;
09268 }
09269 return -1;
09270 }
09271 #endif
09272
09273 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09274 {
09275 ast_group_t groupmatch = 0;
09276 int channelmatch = -1;
09277 int roundrobin = 0;
09278 int callwait = 0;
09279 int busy = 0;
09280 struct dahdi_pvt *p;
09281 struct ast_channel *tmp = NULL;
09282 char *dest=NULL;
09283 int x;
09284 char *s;
09285 char opt=0;
09286 int res=0, y=0;
09287 int backwards = 0;
09288 #ifdef HAVE_PRI
09289 int crv;
09290 int bearer = -1;
09291 int trunkgroup;
09292 struct dahdi_pri *pri=NULL;
09293 #endif
09294 struct dahdi_pvt *exit, *start, *end;
09295 ast_mutex_t *lock;
09296 int channelmatched = 0;
09297 int groupmatched = 0;
09298
09299
09300
09301
09302
09303
09304
09305
09306
09307
09308
09309
09310
09311
09312
09313
09314
09315
09316
09317 lock = &iflock;
09318 start = iflist;
09319 end = ifend;
09320 if (data) {
09321 dest = ast_strdupa((char *)data);
09322 } else {
09323 ast_log(LOG_WARNING, "Channel requested with no data\n");
09324 return NULL;
09325 }
09326 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09327
09328 char *stringp;
09329
09330 stringp = dest + 1;
09331 s = strsep(&stringp, "/");
09332 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09333 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09334 return NULL;
09335 }
09336 groupmatch = ((ast_group_t) 1 << x);
09337 if (toupper(dest[0]) == 'G') {
09338 if (dest[0] == 'G') {
09339 backwards = 1;
09340 p = ifend;
09341 } else
09342 p = iflist;
09343 } else {
09344 if (dest[0] == 'R') {
09345 backwards = 1;
09346 p = round_robin[x]?round_robin[x]->prev:ifend;
09347 if (!p)
09348 p = ifend;
09349 } else {
09350 p = round_robin[x]?round_robin[x]->next:iflist;
09351 if (!p)
09352 p = iflist;
09353 }
09354 roundrobin = 1;
09355 }
09356 } else {
09357 char *stringp;
09358
09359 stringp = dest;
09360 s = strsep(&stringp, "/");
09361 p = iflist;
09362 if (!strcasecmp(s, "pseudo")) {
09363
09364 x = CHAN_PSEUDO;
09365 channelmatch = x;
09366 }
09367 #ifdef HAVE_PRI
09368 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09369 if ((trunkgroup < 1) || (crv < 1)) {
09370 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09371 return NULL;
09372 }
09373 res--;
09374 for (x = 0; x < NUM_SPANS; x++) {
09375 if (pris[x].trunkgroup == trunkgroup) {
09376 pri = pris + x;
09377 lock = &pri->lock;
09378 start = pri->crvs;
09379 end = pri->crvend;
09380 break;
09381 }
09382 }
09383 if (!pri) {
09384 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09385 return NULL;
09386 }
09387 channelmatch = crv;
09388 p = pris[x].crvs;
09389 }
09390 #endif
09391 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09392 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09393 return NULL;
09394 } else {
09395 channelmatch = x;
09396 }
09397 }
09398
09399 ast_mutex_lock(lock);
09400 exit = p;
09401 while (p && !tmp) {
09402 if (roundrobin)
09403 round_robin[x] = p;
09404 #if 0
09405 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09406 #endif
09407
09408 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09409 if (option_debug)
09410 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
09411 if (p->inalarm)
09412 goto next;
09413
09414 callwait = (p->owner != NULL);
09415 #ifdef HAVE_PRI
09416 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09417 if (p->sig != SIG_FXSKS) {
09418
09419
09420 bearer = pri_find_empty_chan(pri, 0);
09421 if (bearer < 0) {
09422 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09423 p = NULL;
09424 break;
09425 }
09426 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09427 } else {
09428 if (alloc_sub(p, 0)) {
09429 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09430 p = NULL;
09431 break;
09432 } else
09433 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
09434 p->pri = pri;
09435 }
09436 }
09437 #endif
09438 #ifdef HAVE_OPENR2
09439 if (p->mfcr2) {
09440 ast_mutex_lock(&p->lock);
09441 if (p->mfcr2call) {
09442 ast_mutex_unlock(&p->lock);
09443 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
09444 goto next;
09445 }
09446 if (p->mfcr2block) {
09447 ast_mutex_unlock(&p->lock);
09448 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
09449 goto next;
09450 }
09451 p->mfcr2call = 1;
09452 ast_mutex_unlock(&p->lock);
09453 }
09454 #endif
09455 if (p->channel == CHAN_PSEUDO) {
09456 p = chandup(p);
09457 if (!p) {
09458 break;
09459 }
09460 }
09461 if (p->owner) {
09462 if (alloc_sub(p, SUB_CALLWAIT)) {
09463 p = NULL;
09464 break;
09465 }
09466 }
09467 p->outgoing = 1;
09468 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09469 if (!tmp) {
09470 p->outgoing = 0;
09471 }
09472 #ifdef HAVE_PRI
09473 if (p->bearer) {
09474
09475 p->bearer->owner = tmp;
09476 }
09477 #endif
09478
09479 if (res > 1) {
09480 if (opt == 'c') {
09481
09482 p->confirmanswer = 1;
09483 } else if (opt == 'r') {
09484
09485 if (res < 3)
09486 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09487 else
09488 p->distinctivering = y;
09489 } else if (opt == 'd') {
09490
09491 p->digital = 1;
09492 if (tmp)
09493 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09494 } else {
09495 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09496 }
09497 }
09498
09499 if (tmp && callwait)
09500 tmp->cdrflags |= AST_CDR_CALLWAIT;
09501 break;
09502 }
09503 next:
09504 if (backwards) {
09505 p = p->prev;
09506 if (!p)
09507 p = end;
09508 } else {
09509 p = p->next;
09510 if (!p)
09511 p = start;
09512 }
09513
09514 if (p == exit)
09515 break;
09516 }
09517 ast_mutex_unlock(lock);
09518 restart_monitor();
09519 if (callwait)
09520 *cause = AST_CAUSE_BUSY;
09521 else if (!tmp) {
09522 if (channelmatched) {
09523 if (busy)
09524 *cause = AST_CAUSE_BUSY;
09525 } else if (groupmatched) {
09526 *cause = AST_CAUSE_CONGESTION;
09527 }
09528 }
09529
09530 return tmp;
09531 }
09532
09533 #ifdef HAVE_OPENR2
09534 static void *mfcr2_monitor(void *data)
09535 {
09536 struct dahdi_pvt *p;
09537 struct dahdi_mfcr2 *mfcr2 = data;
09538
09539
09540
09541
09542
09543 struct pollfd pollers[sizeof(mfcr2->pvts)];
09544 int maxsleep = 20;
09545 int res = 0;
09546 int i = 0;
09547 int pollsize = 0;
09548 int oldstate = 0;
09549 int was_idle = 0;
09550 int quit_loop = 0;
09551
09552
09553 for (i = 0; i < mfcr2->numchans; i++) {
09554 p = mfcr2->pvts[i];
09555 if (openr2_chan_set_idle(p->r2chan)) {
09556 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
09557 } else {
09558 ast_mutex_lock(&p->lock);
09559 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
09560 mfcr2->pvts[i]->mfcr2call = 0;
09561 ast_mutex_unlock(&p->lock);
09562 }
09563 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
09564 }
09565 while(1) {
09566
09567
09568 pollsize = 0;
09569 for (i = 0; i < mfcr2->numchans; i++) {
09570 pollers[i].revents = 0;
09571 pollers[i].events = 0;
09572 if (mfcr2->pvts[i]->owner) {
09573 continue;
09574 }
09575 if (!mfcr2->pvts[i]->r2chan) {
09576 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
09577 quit_loop = 1;
09578 break;
09579 }
09580 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
09581 pollers[i].events = POLLIN | POLLPRI;
09582 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
09583 pollsize++;
09584 }
09585 if (quit_loop) {
09586 break;
09587 }
09588
09589 if (pollsize == 0) {
09590 if (!was_idle) {
09591 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
09592 was_idle = 1;
09593 }
09594 poll(NULL, 0, maxsleep);
09595 continue;
09596 }
09597 was_idle = 0;
09598
09599
09600
09601 pthread_testcancel();
09602 res = poll(pollers, pollsize, maxsleep);
09603 pthread_testcancel();
09604 if ((res < 0) && (errno != EINTR)) {
09605 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
09606 break;
09607 }
09608
09609 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
09610 for (i = 0; i < mfcr2->numchans; i++) {
09611 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
09612 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
09613 }
09614 }
09615 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
09616 }
09617 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
09618 return 0;
09619 }
09620 #endif
09621
09622
09623 #ifdef HAVE_PRI
09624 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
09625 {
09626 struct dahdi_pvt *p;
09627 p = pri->crvs;
09628 while (p) {
09629 if (p->channel == crv)
09630 return p;
09631 p = p->next;
09632 }
09633 return NULL;
09634 }
09635
09636
09637 static int pri_find_principle(struct dahdi_pri *pri, int channel)
09638 {
09639 int x;
09640 int span = PRI_SPAN(channel);
09641 int spanfd;
09642 struct dahdi_params param;
09643 int principle = -1;
09644 int explicit = PRI_EXPLICIT(channel);
09645 channel = PRI_CHANNEL(channel);
09646
09647 if (!explicit) {
09648 spanfd = pri_active_dchan_fd(pri);
09649 memset(¶m, 0, sizeof(param));
09650 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
09651 return -1;
09652 span = pris[param.spanno - 1].prilogicalspan;
09653 }
09654
09655 for (x = 0; x < pri->numchans; x++) {
09656 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
09657 principle = x;
09658 break;
09659 }
09660 }
09661
09662 return principle;
09663 }
09664
09665 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
09666 {
09667 int x;
09668 struct dahdi_pvt *crv;
09669 if (!c) {
09670 if (principle < 0)
09671 return -1;
09672 return principle;
09673 }
09674 if ((principle > -1) &&
09675 (principle < pri->numchans) &&
09676 (pri->pvts[principle]) &&
09677 (pri->pvts[principle]->call == c))
09678 return principle;
09679
09680 for (x = 0; x < pri->numchans; x++) {
09681 if (!pri->pvts[x])
09682 continue;
09683 if (pri->pvts[x]->call == c) {
09684
09685 if (principle != x) {
09686 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
09687
09688 if (option_verbose > 2)
09689 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
09690 old->channel, new->channel);
09691 if (new->owner) {
09692 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
09693 old->channel, new->channel, new->channel);
09694 return -1;
09695 }
09696
09697 new->owner = old->owner;
09698 old->owner = NULL;
09699 if (new->owner) {
09700 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
09701 new->owner->tech_pvt = new;
09702 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
09703 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
09704 old->subs[SUB_REAL].owner = NULL;
09705 } else
09706 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);
09707 new->call = old->call;
09708 old->call = NULL;
09709
09710
09711 new->dsp = old->dsp;
09712 new->dsp_features = old->dsp_features;
09713 old->dsp = NULL;
09714 old->dsp_features = 0;
09715 }
09716 return principle;
09717 }
09718 }
09719
09720 crv = pri->crvs;
09721 while (crv) {
09722 if (crv->call == c) {
09723
09724 if (crv->bearer)
09725 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
09726 else if (pri->pvts[principle]->owner)
09727 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
09728 else {
09729
09730
09731 dahdi_close_sub(crv, SUB_REAL);
09732 pri->pvts[principle]->call = crv->call;
09733 pri_assign_bearer(crv, pri, pri->pvts[principle]);
09734 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
09735 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
09736 pri->trunkgroup, crv->channel);
09737 wakeup_sub(crv, SUB_REAL, pri);
09738 }
09739 return principle;
09740 }
09741 crv = crv->next;
09742 }
09743 ast_log(LOG_WARNING, "Call specified, but not found?\n");
09744 return -1;
09745 }
09746
09747 static void *do_idle_thread(void *vchan)
09748 {
09749 struct ast_channel *chan = vchan;
09750 struct dahdi_pvt *pvt = chan->tech_pvt;
09751 struct ast_frame *f;
09752 char ex[80];
09753
09754 int newms, ms = 30000;
09755 if (option_verbose > 2)
09756 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
09757 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
09758 if (ast_call(chan, ex, 0)) {
09759 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
09760 ast_hangup(chan);
09761 return NULL;
09762 }
09763 while ((newms = ast_waitfor(chan, ms)) > 0) {
09764 f = ast_read(chan);
09765 if (!f) {
09766
09767 break;
09768 }
09769 if (f->frametype == AST_FRAME_CONTROL) {
09770 switch (f->subclass) {
09771 case AST_CONTROL_ANSWER:
09772
09773 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
09774 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
09775 chan->priority = 1;
09776 if (option_verbose > 3)
09777 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
09778 ast_pbx_run(chan);
09779
09780 return NULL;
09781 case AST_CONTROL_BUSY:
09782 if (option_verbose > 3)
09783 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
09784 break;
09785 case AST_CONTROL_CONGESTION:
09786 if (option_verbose > 3)
09787 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
09788 break;
09789 };
09790 }
09791 ast_frfree(f);
09792 ms = newms;
09793 }
09794
09795 ast_hangup(chan);
09796 return NULL;
09797 }
09798
09799 #ifndef PRI_RESTART
09800 #error "Upgrade your libpri"
09801 #endif
09802 static void dahdi_pri_message(struct pri *pri, char *s)
09803 {
09804 int x, y;
09805 int dchan = -1, span = -1;
09806 int dchancount = 0;
09807
09808 if (pri) {
09809 for (x = 0; x < NUM_SPANS; x++) {
09810 for (y = 0; y < NUM_DCHANS; y++) {
09811 if (pris[x].dchans[y])
09812 dchancount++;
09813
09814 if (pris[x].dchans[y] == pri)
09815 dchan = y;
09816 }
09817 if (dchan >= 0) {
09818 span = x;
09819 break;
09820 }
09821 dchancount = 0;
09822 }
09823 if ((dchan >= 0) && (span >= 0)) {
09824 if (dchancount > 1)
09825 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
09826 else
09827 ast_verbose("%s", s);
09828 } else
09829 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09830 } else
09831 ast_verbose("%s", s);
09832
09833 ast_mutex_lock(&pridebugfdlock);
09834
09835 if (pridebugfd >= 0) {
09836 if (write(pridebugfd, s, strlen(s)) < 0) {
09837 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09838 }
09839 }
09840
09841 ast_mutex_unlock(&pridebugfdlock);
09842 }
09843
09844 static void dahdi_pri_error(struct pri *pri, char *s)
09845 {
09846 int x, y;
09847 int dchan = -1, span = -1;
09848 int dchancount = 0;
09849
09850 if (pri) {
09851 for (x = 0; x < NUM_SPANS; x++) {
09852 for (y = 0; y < NUM_DCHANS; y++) {
09853 if (pris[x].dchans[y])
09854 dchancount++;
09855
09856 if (pris[x].dchans[y] == pri)
09857 dchan = y;
09858 }
09859 if (dchan >= 0) {
09860 span = x;
09861 break;
09862 }
09863 dchancount = 0;
09864 }
09865 if ((dchan >= 0) && (span >= 0)) {
09866 if (dchancount > 1)
09867 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
09868 else
09869 ast_log(LOG_ERROR, "%s", s);
09870 } else
09871 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09872 } else
09873 ast_log(LOG_ERROR, "%s", s);
09874
09875 ast_mutex_lock(&pridebugfdlock);
09876
09877 if (pridebugfd >= 0) {
09878 if (write(pridebugfd, s, strlen(s)) < 0) {
09879 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09880 }
09881 }
09882
09883 ast_mutex_unlock(&pridebugfdlock);
09884 }
09885
09886 static int pri_check_restart(struct dahdi_pri *pri)
09887 {
09888 do {
09889 pri->resetpos++;
09890 } while ((pri->resetpos < pri->numchans) &&
09891 (!pri->pvts[pri->resetpos] ||
09892 pri->pvts[pri->resetpos]->call ||
09893 pri->pvts[pri->resetpos]->resetting));
09894 if (pri->resetpos < pri->numchans) {
09895
09896 pri->pvts[pri->resetpos]->resetting = 1;
09897 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
09898 } else {
09899 pri->resetting = 0;
09900 time(&pri->lastreset);
09901 }
09902 return 0;
09903 }
09904
09905 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
09906 {
09907 int x;
09908 int redo;
09909 ast_mutex_unlock(&pri->lock);
09910 ast_mutex_lock(&p->lock);
09911 do {
09912 redo = 0;
09913 for (x = 0; x < 3; x++) {
09914 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
09915 redo++;
09916 DEADLOCK_AVOIDANCE(&p->lock);
09917 }
09918 if (p->subs[x].owner) {
09919 ast_queue_hangup(p->subs[x].owner);
09920 ast_mutex_unlock(&p->subs[x].owner->lock);
09921 }
09922 }
09923 } while (redo);
09924 ast_mutex_unlock(&p->lock);
09925 ast_mutex_lock(&pri->lock);
09926 return 0;
09927 }
09928
09929 static char * redirectingreason2str(int redirectingreason)
09930 {
09931 switch (redirectingreason) {
09932 case 0:
09933 return "UNKNOWN";
09934 case 1:
09935 return "BUSY";
09936 case 2:
09937 return "NO_REPLY";
09938 case 0xF:
09939 return "UNCONDITIONAL";
09940 default:
09941 return "NOREDIRECT";
09942 }
09943 }
09944
09945 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
09946 {
09947 if (ast_strlen_zero(number)) {
09948 if (size) {
09949 *buf = '\0';
09950 }
09951 return;
09952 }
09953
09954 switch (plan) {
09955 case PRI_INTERNATIONAL_ISDN:
09956 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
09957 break;
09958 case PRI_NATIONAL_ISDN:
09959 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
09960 break;
09961 case PRI_LOCAL_ISDN:
09962 snprintf(buf, size, "%s%s", pri->localprefix, number);
09963 break;
09964 case PRI_PRIVATE:
09965 snprintf(buf, size, "%s%s", pri->privateprefix, number);
09966 break;
09967 case PRI_UNKNOWN:
09968 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
09969 break;
09970 default:
09971 snprintf(buf, size, "%s", number);
09972 break;
09973 }
09974 }
09975
09976 static int dahdi_setlaw(int dfd, int law)
09977 {
09978 int res;
09979 res = ioctl(dfd, DAHDI_SETLAW, &law);
09980 if (res)
09981 return res;
09982 return 0;
09983 }
09984
09985 static void *pri_dchannel(void *vpri)
09986 {
09987 struct dahdi_pri *pri = vpri;
09988 pri_event *e;
09989 struct pollfd fds[NUM_DCHANS];
09990 int res;
09991 int chanpos = 0;
09992 int x;
09993 int haveidles;
09994 int activeidles;
09995 int nextidle = -1;
09996 struct ast_channel *c;
09997 struct timeval tv, lowest, *next;
09998 struct timeval lastidle = { 0, 0 };
09999 int doidling=0;
10000 char *cc;
10001 char idlen[80];
10002 struct ast_channel *idle;
10003 pthread_t p;
10004 time_t t;
10005 int i, which=-1;
10006 int numdchans;
10007 int cause=0;
10008 struct dahdi_pvt *crv;
10009 pthread_t threadid;
10010 pthread_attr_t attr;
10011 char ani2str[6];
10012 char plancallingnum[256];
10013 char plancallingani[256];
10014 char calledtonstr[10];
10015
10016 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10017
10018 gettimeofday(&lastidle, NULL);
10019 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10020
10021 cc = strchr(pri->idleext, '@');
10022 if (cc) {
10023 *cc = '\0';
10024 cc++;
10025 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10026 #if 0
10027
10028 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10029 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10030 else
10031 #endif
10032 doidling = 1;
10033 } else
10034 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10035 }
10036 for (;;) {
10037 for (i = 0; i < NUM_DCHANS; i++) {
10038 if (!pri->dchannels[i])
10039 break;
10040 fds[i].fd = pri->fds[i];
10041 fds[i].events = POLLIN | POLLPRI;
10042 fds[i].revents = 0;
10043 }
10044 numdchans = i;
10045 time(&t);
10046 ast_mutex_lock(&pri->lock);
10047 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10048 if (pri->resetting && pri_is_up(pri)) {
10049 if (pri->resetpos < 0)
10050 pri_check_restart(pri);
10051 } else {
10052 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10053 pri->resetting = 1;
10054 pri->resetpos = -1;
10055 }
10056 }
10057 }
10058
10059 if (doidling && pri_is_up(pri)) {
10060 nextidle = -1;
10061 haveidles = 0;
10062 activeidles = 0;
10063 for (x = pri->numchans; x >= 0; x--) {
10064 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10065 !pri->pvts[x]->call) {
10066 if (haveidles < pri->minunused) {
10067 haveidles++;
10068 } else if (!pri->pvts[x]->resetting) {
10069 nextidle = x;
10070 break;
10071 }
10072 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10073 activeidles++;
10074 }
10075 if (nextidle > -1) {
10076 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10077
10078 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10079 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
10080 if (idle) {
10081 pri->pvts[nextidle]->isidlecall = 1;
10082 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10083 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10084 dahdi_hangup(idle);
10085 }
10086 } else
10087 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10088 gettimeofday(&lastidle, NULL);
10089 }
10090 } else if ((haveidles < pri->minunused) &&
10091 (activeidles > pri->minidle)) {
10092
10093
10094 for (x = pri->numchans; x >= 0; x--) {
10095
10096 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10097 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10098 haveidles++;
10099
10100
10101 if ((haveidles >= pri->minunused) ||
10102 (activeidles <= pri->minidle))
10103 break;
10104 }
10105 }
10106 }
10107 }
10108
10109 lowest = ast_tv(60, 0);
10110 for (i = 0; i < NUM_DCHANS; i++) {
10111
10112 if (!pri->dchannels[i])
10113 break;
10114 if ((next = pri_schedule_next(pri->dchans[i]))) {
10115
10116 tv = ast_tvsub(*next, ast_tvnow());
10117 if (tv.tv_sec < 0) {
10118 tv = ast_tv(0,0);
10119 }
10120 if (doidling || pri->resetting) {
10121 if (tv.tv_sec > 1) {
10122 tv = ast_tv(1, 0);
10123 }
10124 } else {
10125 if (tv.tv_sec > 60) {
10126 tv = ast_tv(60, 0);
10127 }
10128 }
10129 } else if (doidling || pri->resetting) {
10130
10131
10132 tv = ast_tv(1,0);
10133 } else {
10134
10135 tv = ast_tv(60, 0);
10136 }
10137 if (!i || ast_tvcmp(tv, lowest) < 0) {
10138 lowest = tv;
10139 }
10140 }
10141 ast_mutex_unlock(&pri->lock);
10142
10143 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10144 pthread_testcancel();
10145 e = NULL;
10146 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10147 pthread_testcancel();
10148 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10149
10150 ast_mutex_lock(&pri->lock);
10151 if (!res) {
10152 for (which = 0; which < NUM_DCHANS; which++) {
10153 if (!pri->dchans[which])
10154 break;
10155
10156 e = pri_schedule_run(pri->dchans[which]);
10157 if (e)
10158 break;
10159 }
10160 } else if (res > -1) {
10161 for (which = 0; which < NUM_DCHANS; which++) {
10162 if (!pri->dchans[which])
10163 break;
10164 if (fds[which].revents & POLLPRI) {
10165
10166 x = 0;
10167 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10168 if (x)
10169 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);
10170
10171 if (x == DAHDI_EVENT_ALARM) {
10172 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10173 pri_find_dchan(pri);
10174 } else if (x == DAHDI_EVENT_NOALARM) {
10175 pri->dchanavail[which] |= DCHAN_NOTINALARM;
10176 pri_restart(pri->dchans[which]);
10177 }
10178
10179 if (option_debug)
10180 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10181 } else if (fds[which].revents & POLLIN) {
10182 e = pri_check_event(pri->dchans[which]);
10183 }
10184 if (e)
10185 break;
10186 }
10187 } else if (errno != EINTR)
10188 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10189
10190 if (e) {
10191 if (pri->debug)
10192 pri_dump_event(pri->dchans[which], e);
10193
10194 if (e->e != PRI_EVENT_DCHAN_DOWN) {
10195 if (!(pri->dchanavail[which] & DCHAN_UP)) {
10196 if (option_verbose > 1)
10197 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10198 }
10199 pri->dchanavail[which] |= DCHAN_UP;
10200 } else {
10201 if (pri->dchanavail[which] & DCHAN_UP) {
10202 if (option_verbose > 1)
10203 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10204 }
10205 pri->dchanavail[which] &= ~DCHAN_UP;
10206 }
10207
10208 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10209
10210 pri->pri = pri->dchans[which];
10211
10212 switch (e->e) {
10213 case PRI_EVENT_DCHAN_UP:
10214 if (!pri->pri) pri_find_dchan(pri);
10215
10216
10217 time(&pri->lastreset);
10218
10219
10220 if (pri->resetinterval > -1) {
10221 pri->lastreset -= pri->resetinterval;
10222 pri->lastreset += 5;
10223 }
10224 pri->resetting = 0;
10225
10226 for (i = 0; i < pri->numchans; i++)
10227 if (pri->pvts[i]) {
10228 pri->pvts[i]->inalarm = 0;
10229 }
10230 break;
10231 case PRI_EVENT_DCHAN_DOWN:
10232 pri_find_dchan(pri);
10233 if (!pri_is_up(pri)) {
10234 pri->resetting = 0;
10235
10236 for (i = 0; i < pri->numchans; i++) {
10237 struct dahdi_pvt *p = pri->pvts[i];
10238 if (p) {
10239 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10240
10241 if (p->call) {
10242 if (p->pri && p->pri->pri) {
10243 pri_hangup(p->pri->pri, p->call, -1);
10244 pri_destroycall(p->pri->pri, p->call);
10245 p->call = NULL;
10246 } else
10247 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10248 }
10249 if (p->realcall) {
10250 pri_hangup_all(p->realcall, pri);
10251 } else if (p->owner)
10252 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10253 }
10254 p->inalarm = 1;
10255 }
10256 }
10257 }
10258 break;
10259 case PRI_EVENT_RESTART:
10260 if (e->restart.channel > -1) {
10261 chanpos = pri_find_principle(pri, e->restart.channel);
10262 if (chanpos < 0)
10263 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10264 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10265 else {
10266 if (option_verbose > 2)
10267 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
10268 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10269 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10270 if (pri->pvts[chanpos]->call) {
10271 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10272 pri->pvts[chanpos]->call = NULL;
10273 }
10274
10275 if (pri->pvts[chanpos]->realcall)
10276 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10277 else if (pri->pvts[chanpos]->owner)
10278 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10279 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10280 }
10281 } else {
10282 if (option_verbose > 2)
10283 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
10284 for (x = 0; x < pri->numchans; x++)
10285 if (pri->pvts[x]) {
10286 ast_mutex_lock(&pri->pvts[x]->lock);
10287 if (pri->pvts[x]->call) {
10288 pri_destroycall(pri->pri, pri->pvts[x]->call);
10289 pri->pvts[x]->call = NULL;
10290 }
10291 if (pri->pvts[x]->realcall)
10292 pri_hangup_all(pri->pvts[x]->realcall, pri);
10293 else if (pri->pvts[x]->owner)
10294 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10295 ast_mutex_unlock(&pri->pvts[x]->lock);
10296 }
10297 }
10298 break;
10299 case PRI_EVENT_KEYPAD_DIGIT:
10300 chanpos = pri_find_principle(pri, e->digit.channel);
10301 if (chanpos < 0) {
10302 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10303 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10304 } else {
10305 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10306 if (chanpos > -1) {
10307 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10308
10309 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
10310
10311 int digitlen = strlen(e->digit.digits);
10312 char digit;
10313 int i;
10314 for (i = 0; i < digitlen; i++) {
10315 digit = e->digit.digits[i];
10316 {
10317 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10318 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10319 }
10320 }
10321 }
10322 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10323 }
10324 }
10325 break;
10326
10327 case PRI_EVENT_INFO_RECEIVED:
10328 chanpos = pri_find_principle(pri, e->ring.channel);
10329 if (chanpos < 0) {
10330 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
10331 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10332 } else {
10333 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
10334 if (chanpos > -1) {
10335 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10336
10337 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
10338
10339 int digitlen = strlen(e->ring.callednum);
10340 char digit;
10341 int i;
10342 for (i = 0; i < digitlen; i++) {
10343 digit = e->ring.callednum[i];
10344 {
10345 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10346 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10347 }
10348 }
10349 }
10350 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10351 }
10352 }
10353 break;
10354 case PRI_EVENT_RING:
10355 crv = NULL;
10356 if (e->ring.channel == -1)
10357 chanpos = pri_find_empty_chan(pri, 1);
10358 else
10359 chanpos = pri_find_principle(pri, e->ring.channel);
10360
10361 if (chanpos < 0) {
10362 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
10363 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10364 } else {
10365 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10366 if (pri->pvts[chanpos]->owner) {
10367 if (pri->pvts[chanpos]->call == e->ring.call) {
10368 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
10369 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10370 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10371 break;
10372 } else {
10373
10374 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
10375 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10376 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10377 chanpos = -1;
10378 }
10379 }
10380 if (chanpos > -1)
10381 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10382 }
10383 if ((chanpos < 0) && (e->ring.flexible))
10384 chanpos = pri_find_empty_chan(pri, 1);
10385 if (chanpos > -1) {
10386 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10387 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
10388
10389 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
10390 if (crv)
10391 ast_mutex_lock(&crv->lock);
10392 if (!crv || crv->owner) {
10393 pri->pvts[chanpos]->call = NULL;
10394 if (crv) {
10395 if (crv->owner)
10396 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10397 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);
10398 } else
10399 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);
10400 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
10401 if (crv)
10402 ast_mutex_unlock(&crv->lock);
10403 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10404 break;
10405 }
10406 }
10407 pri->pvts[chanpos]->call = e->ring.call;
10408 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
10409 if (pri->pvts[chanpos]->use_callerid) {
10410 ast_shrink_phone_number(plancallingnum);
10411 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
10412 #ifdef PRI_ANI
10413 if (!ast_strlen_zero(e->ring.callingani)) {
10414 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
10415 ast_shrink_phone_number(plancallingani);
10416 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
10417 } else {
10418 pri->pvts[chanpos]->cid_ani[0] = '\0';
10419 }
10420 #endif
10421 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
10422 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
10423 } else {
10424 pri->pvts[chanpos]->cid_num[0] = '\0';
10425 pri->pvts[chanpos]->cid_ani[0] = '\0';
10426 pri->pvts[chanpos]->cid_name[0] = '\0';
10427 pri->pvts[chanpos]->cid_ton = 0;
10428 }
10429 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
10430 e->ring.redirectingnum, e->ring.callingplanrdnis);
10431
10432 if (pri->pvts[chanpos]->immediate) {
10433 if (option_verbose > 2)
10434 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
10435 pri->pvts[chanpos]->exten[0] = 's';
10436 pri->pvts[chanpos]->exten[1] = '\0';
10437 }
10438
10439 else if (!ast_strlen_zero(e->ring.callednum)) {
10440 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
10441 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10442 } else if (pri->overlapdial)
10443 pri->pvts[chanpos]->exten[0] = '\0';
10444 else {
10445
10446 pri->pvts[chanpos]->exten[0] = 's';
10447 pri->pvts[chanpos]->exten[1] = '\0';
10448 }
10449
10450 if (!ast_strlen_zero(e->ring.callednum))
10451 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10452
10453 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
10454 if (option_verbose > 2)
10455 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
10456 pri->pvts[chanpos]->exten[0] = 's';
10457 pri->pvts[chanpos]->exten[1] = '\0';
10458 }
10459
10460
10461 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
10462 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10463
10464 int law;
10465 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
10466
10467 law = 1;
10468 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
10469 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
10470 }
10471 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
10472 law = DAHDI_LAW_ALAW;
10473 else
10474 law = DAHDI_LAW_MULAW;
10475 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
10476 if (res < 0)
10477 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
10478 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10479 if (res < 0)
10480 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
10481 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
10482
10483 pri->pvts[chanpos]->proceeding = 1;
10484 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
10485 } else {
10486 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
10487 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10488 else
10489 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10490 }
10491
10492 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
10493
10494
10495 if (!e->ring.complete
10496 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
10497 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10498
10499
10500
10501
10502 ast_mutex_unlock(&pri->lock);
10503 if (crv) {
10504
10505 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
10506 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10507 pri->pvts[chanpos]->owner = &inuse;
10508 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
10509 } else {
10510 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10511 }
10512 ast_mutex_lock(&pri->lock);
10513 if (c) {
10514 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10515 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10516 }
10517 if (e->ring.ani2 >= 0) {
10518 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10519 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10520 }
10521
10522 #ifdef SUPPORT_USERUSER
10523 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10524 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10525 }
10526 #endif
10527
10528 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10529 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10530 if (e->ring.redirectingreason >= 0)
10531 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10532 }
10533
10534 pthread_attr_init(&attr);
10535 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10536 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
10537 if (option_verbose > 2)
10538 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10539 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
10540 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10541 } else {
10542 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10543 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10544 if (c)
10545 ast_hangup(c);
10546 else {
10547 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10548 pri->pvts[chanpos]->call = NULL;
10549 }
10550 }
10551 pthread_attr_destroy(&attr);
10552 } else {
10553
10554
10555
10556
10557 ast_mutex_unlock(&pri->lock);
10558 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
10559 ast_mutex_lock(&pri->lock);
10560 if (c) {
10561
10562
10563
10564
10565
10566
10567
10568
10569 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10570 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10571 }
10572 if (e->ring.ani2 >= 0) {
10573 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10574 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10575 }
10576
10577 #ifdef SUPPORT_USERUSER
10578 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10579 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10580 }
10581 #endif
10582
10583 if (e->ring.redirectingreason >= 0)
10584 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10585
10586 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10587 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10588 }
10589 if (c && !ast_pbx_start(c)) {
10590 if (option_verbose > 2)
10591 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10592 plancallingnum, pri->pvts[chanpos]->exten,
10593 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10594
10595 dahdi_enable_ec(pri->pvts[chanpos]);
10596 } else {
10597 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10598 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10599 if (c) {
10600 ast_hangup(c);
10601 } else {
10602 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10603 pri->pvts[chanpos]->call = NULL;
10604 }
10605 }
10606 }
10607 } else {
10608 if (option_verbose > 2)
10609 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
10610 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
10611 pri->pvts[chanpos]->prioffset, pri->span);
10612 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
10613 pri->pvts[chanpos]->call = NULL;
10614 pri->pvts[chanpos]->exten[0] = '\0';
10615 }
10616 if (crv)
10617 ast_mutex_unlock(&crv->lock);
10618 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10619 } else {
10620 if (e->ring.flexible)
10621 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
10622 else
10623 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
10624 }
10625 break;
10626 case PRI_EVENT_RINGING:
10627 chanpos = pri_find_principle(pri, e->ringing.channel);
10628 if (chanpos < 0) {
10629 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
10630 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10631 } else {
10632 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
10633 if (chanpos < 0) {
10634 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
10635 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10636 } else {
10637 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10638 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10639 dahdi_enable_ec(pri->pvts[chanpos]);
10640 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
10641 pri->pvts[chanpos]->alerting = 1;
10642 } else
10643 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
10644 #ifdef PRI_PROGRESS_MASK
10645 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10646 #else
10647 if (e->ringing.progress == 8) {
10648 #endif
10649
10650 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10651
10652 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
10653 pri->pvts[chanpos]->dsp_features = 0;
10654 }
10655 }
10656
10657 #ifdef SUPPORT_USERUSER
10658 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
10659 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10660 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10661 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
10662 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10663 }
10664 #endif
10665
10666 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10667 }
10668 }
10669 break;
10670 case PRI_EVENT_PROGRESS:
10671
10672 chanpos = pri_find_principle(pri, e->proceeding.channel);
10673 if (chanpos > -1) {
10674 #ifdef PRI_PROGRESS_MASK
10675 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
10676 #else
10677 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
10678 #endif
10679 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10680
10681 if (e->proceeding.cause > -1) {
10682 if (option_verbose > 2)
10683 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
10684
10685
10686 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
10687 if (pri->pvts[chanpos]->owner) {
10688 if (option_verbose > 2)
10689 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
10690
10691 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
10692 f.subclass = AST_CONTROL_BUSY;
10693 }
10694 }
10695 }
10696
10697 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10698 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
10699 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10700 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10701 #ifdef PRI_PROGRESS_MASK
10702 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10703 #else
10704 if (e->proceeding.progress == 8) {
10705 #endif
10706
10707 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10708 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10709 pri->pvts[chanpos]->dsp_features = 0;
10710 }
10711
10712 f.subclass = AST_CONTROL_PROGRESS;
10713 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10714 }
10715 pri->pvts[chanpos]->progress = 1;
10716 pri->pvts[chanpos]->dialing = 0;
10717 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10718 }
10719 }
10720 break;
10721 case PRI_EVENT_PROCEEDING:
10722 chanpos = pri_find_principle(pri, e->proceeding.channel);
10723 if (chanpos > -1) {
10724 if (!pri->pvts[chanpos]->proceeding) {
10725 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10726
10727 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10728 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
10729 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10730 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10731 #ifdef PRI_PROGRESS_MASK
10732 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10733 #else
10734 if (e->proceeding.progress == 8) {
10735 #endif
10736
10737 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10738 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10739 pri->pvts[chanpos]->dsp_features = 0;
10740 }
10741
10742 f.subclass = AST_CONTROL_PROGRESS;
10743 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10744 }
10745 pri->pvts[chanpos]->proceeding = 1;
10746 pri->pvts[chanpos]->dialing = 0;
10747 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10748 }
10749 }
10750 break;
10751 case PRI_EVENT_FACNAME:
10752 chanpos = pri_find_principle(pri, e->facname.channel);
10753 if (chanpos < 0) {
10754 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
10755 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10756 } else {
10757 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
10758 if (chanpos < 0) {
10759 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
10760 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10761 } else {
10762
10763 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10764 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
10765 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
10766 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
10767 dahdi_enable_ec(pri->pvts[chanpos]);
10768 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10769 }
10770 }
10771 break;
10772 case PRI_EVENT_ANSWER:
10773 chanpos = pri_find_principle(pri, e->answer.channel);
10774 if (chanpos < 0) {
10775 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
10776 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10777 } else {
10778 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
10779 if (chanpos < 0) {
10780 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
10781 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10782 } else {
10783 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10784
10785
10786
10787
10788
10789 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10790 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10791 pri->pvts[chanpos]->dsp_features = 0;
10792 }
10793 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
10794 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
10795 x = DAHDI_START;
10796 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10797 if (res < 0) {
10798 if (errno != EINPROGRESS) {
10799 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
10800 }
10801 }
10802 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10803 pri->pvts[chanpos]->dialing = 1;
10804
10805 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
10806 if (res < 0) {
10807 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
10808 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10809 } else
10810 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
10811 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10812 } else if (pri->pvts[chanpos]->confirmanswer) {
10813 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
10814 } else {
10815 pri->pvts[chanpos]->dialing = 0;
10816 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
10817
10818 dahdi_enable_ec(pri->pvts[chanpos]);
10819 }
10820
10821 #ifdef SUPPORT_USERUSER
10822 if (!ast_strlen_zero(e->answer.useruserinfo)) {
10823 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10824 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10825 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
10826 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10827 }
10828 #endif
10829
10830 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10831 }
10832 }
10833 break;
10834 case PRI_EVENT_HANGUP:
10835 chanpos = pri_find_principle(pri, e->hangup.channel);
10836 if (chanpos < 0) {
10837 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
10838 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10839 } else {
10840 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10841 if (chanpos > -1) {
10842 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10843 if (!pri->pvts[chanpos]->alreadyhungup) {
10844
10845 pri->pvts[chanpos]->alreadyhungup = 1;
10846 if (pri->pvts[chanpos]->realcall)
10847 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10848 else if (pri->pvts[chanpos]->owner) {
10849
10850 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10851 switch (pri->pvts[chanpos]->owner->_state) {
10852 case AST_STATE_BUSY:
10853 case AST_STATE_UP:
10854 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10855 break;
10856 default:
10857 switch (e->hangup.cause) {
10858 case PRI_CAUSE_USER_BUSY:
10859 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10860 break;
10861 case PRI_CAUSE_CALL_REJECTED:
10862 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10863 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10864 case PRI_CAUSE_SWITCH_CONGESTION:
10865 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10866 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10867 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10868 break;
10869 default:
10870 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10871 }
10872 break;
10873 }
10874 }
10875 if (option_verbose > 2)
10876 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
10877 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
10878 } else {
10879 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10880 pri->pvts[chanpos]->call = NULL;
10881 }
10882 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10883 if (option_verbose > 2)
10884 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
10885 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10886 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10887 pri->pvts[chanpos]->resetting = 1;
10888 }
10889 if (e->hangup.aoc_units > -1)
10890 if (option_verbose > 2)
10891 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10892 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10893
10894 #ifdef SUPPORT_USERUSER
10895 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
10896 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10897 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10898 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10899 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10900 }
10901 #endif
10902
10903 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10904 } else {
10905 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
10906 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10907 }
10908 }
10909 break;
10910 #ifndef PRI_EVENT_HANGUP_REQ
10911 #error please update libpri
10912 #endif
10913 case PRI_EVENT_HANGUP_REQ:
10914 chanpos = pri_find_principle(pri, e->hangup.channel);
10915 if (chanpos < 0) {
10916 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
10917 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10918 } else {
10919 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10920 if (chanpos > -1) {
10921 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10922 if (pri->pvts[chanpos]->realcall)
10923 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10924 else if (pri->pvts[chanpos]->owner) {
10925 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10926 switch (pri->pvts[chanpos]->owner->_state) {
10927 case AST_STATE_BUSY:
10928 case AST_STATE_UP:
10929 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10930 break;
10931 default:
10932 switch (e->hangup.cause) {
10933 case PRI_CAUSE_USER_BUSY:
10934 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10935 break;
10936 case PRI_CAUSE_CALL_REJECTED:
10937 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10938 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10939 case PRI_CAUSE_SWITCH_CONGESTION:
10940 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10941 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10942 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10943 break;
10944 default:
10945 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10946 }
10947 break;
10948 }
10949 if (option_verbose > 2)
10950 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);
10951 if (e->hangup.aoc_units > -1)
10952 if (option_verbose > 2)
10953 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10954 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10955 } else {
10956 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10957 pri->pvts[chanpos]->call = NULL;
10958 }
10959 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10960 if (option_verbose > 2)
10961 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
10962 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10963 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10964 pri->pvts[chanpos]->resetting = 1;
10965 }
10966
10967 #ifdef SUPPORT_USERUSER
10968 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
10969 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10970 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10971 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10972 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10973 }
10974 #endif
10975
10976 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10977 } else {
10978 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);
10979 }
10980 }
10981 break;
10982 case PRI_EVENT_HANGUP_ACK:
10983 chanpos = pri_find_principle(pri, e->hangup.channel);
10984 if (chanpos < 0) {
10985 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
10986 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10987 } else {
10988 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10989 if (chanpos > -1) {
10990 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10991 pri->pvts[chanpos]->call = NULL;
10992 pri->pvts[chanpos]->resetting = 0;
10993 if (pri->pvts[chanpos]->owner) {
10994 if (option_verbose > 2)
10995 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);
10996 }
10997
10998 #ifdef SUPPORT_USERUSER
10999 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11000 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11001 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11002 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11003 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11004 }
11005 #endif
11006
11007 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11008 }
11009 }
11010 break;
11011 case PRI_EVENT_CONFIG_ERR:
11012 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11013 break;
11014 case PRI_EVENT_RESTART_ACK:
11015 chanpos = pri_find_principle(pri, e->restartack.channel);
11016 if (chanpos < 0) {
11017
11018
11019
11020 for (x = 0; x < pri->numchans; x++) {
11021 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11022 chanpos = x;
11023 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11024 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11025 pri->pvts[chanpos]->prioffset, pri->span);
11026 if (pri->pvts[chanpos]->realcall)
11027 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11028 else if (pri->pvts[chanpos]->owner) {
11029 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11030 pri->pvts[chanpos]->prioffset, pri->span);
11031 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11032 }
11033 pri->pvts[chanpos]->resetting = 0;
11034 if (option_verbose > 2)
11035 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11036 pri->pvts[chanpos]->prioffset, pri->span);
11037 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11038 if (pri->resetting)
11039 pri_check_restart(pri);
11040 break;
11041 }
11042 }
11043 if (chanpos < 0) {
11044 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11045 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11046 }
11047 } else {
11048 if (pri->pvts[chanpos]) {
11049 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11050 if (pri->pvts[chanpos]->realcall)
11051 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11052 else if (pri->pvts[chanpos]->owner) {
11053 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11054 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11055 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11056 }
11057 pri->pvts[chanpos]->resetting = 0;
11058 if (option_verbose > 2)
11059 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11060 pri->pvts[chanpos]->prioffset, pri->span);
11061 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11062 if (pri->resetting)
11063 pri_check_restart(pri);
11064 }
11065 }
11066 break;
11067 case PRI_EVENT_SETUP_ACK:
11068 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11069 if (chanpos < 0) {
11070 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11071 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11072 } else {
11073 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11074 if (chanpos > -1) {
11075 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11076 pri->pvts[chanpos]->setup_ack = 1;
11077
11078 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11079 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11080 pri_information(pri->pri, pri->pvts[chanpos]->call,
11081 pri->pvts[chanpos]->dialdest[x]);
11082 }
11083 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11084 } else
11085 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11086 }
11087 break;
11088 case PRI_EVENT_NOTIFY:
11089 chanpos = pri_find_principle(pri, e->notify.channel);
11090 if (chanpos < 0) {
11091 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11092 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11093 } else {
11094 struct ast_frame f = { AST_FRAME_CONTROL, };
11095 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11096 switch (e->notify.info) {
11097 case PRI_NOTIFY_REMOTE_HOLD:
11098 f.subclass = AST_CONTROL_HOLD;
11099 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11100 break;
11101 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11102 f.subclass = AST_CONTROL_UNHOLD;
11103 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11104 break;
11105 }
11106 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11107 }
11108 break;
11109 default:
11110 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
11111 }
11112 }
11113 ast_mutex_unlock(&pri->lock);
11114 }
11115
11116 return NULL;
11117 }
11118
11119 static int start_pri(struct dahdi_pri *pri)
11120 {
11121 int res, x;
11122 struct dahdi_params p;
11123 struct dahdi_bufferinfo bi;
11124 struct dahdi_spaninfo si;
11125 int i;
11126
11127 for (i = 0; i < NUM_DCHANS; i++) {
11128 if (!pri->dchannels[i])
11129 break;
11130 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
11131 x = pri->dchannels[i];
11132 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11133 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11134 return -1;
11135 }
11136 memset(&p, 0, sizeof(p));
11137 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11138 if (res) {
11139 dahdi_close_pri_fd(pri, i);
11140 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11141 return -1;
11142 }
11143 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11144 dahdi_close_pri_fd(pri, i);
11145 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
11146 return -1;
11147 }
11148 memset(&si, 0, sizeof(si));
11149 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11150 if (res) {
11151 dahdi_close_pri_fd(pri, i);
11152 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11153 }
11154 if (!si.alarms)
11155 pri->dchanavail[i] |= DCHAN_NOTINALARM;
11156 else
11157 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11158 memset(&bi, 0, sizeof(bi));
11159 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11160 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11161 bi.numbufs = 32;
11162 bi.bufsize = 1024;
11163 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11164 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11165 dahdi_close_pri_fd(pri, i);
11166 return -1;
11167 }
11168 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11169
11170 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11171 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11172 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11173 #ifdef HAVE_PRI_INBANDDISCONNECT
11174 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11175 #endif
11176
11177 if (i)
11178 pri_enslave(pri->dchans[0], pri->dchans[i]);
11179 if (!pri->dchans[i]) {
11180 dahdi_close_pri_fd(pri, i);
11181 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11182 return -1;
11183 }
11184 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11185 pri_set_nsf(pri->dchans[i], pri->nsf);
11186 #ifdef PRI_GETSET_TIMERS
11187 for (x = 0; x < PRI_MAX_TIMERS; x++) {
11188 if (pritimers[x] != 0)
11189 pri_set_timer(pri->dchans[i], x, pritimers[x]);
11190 }
11191 #endif
11192 }
11193
11194 pri->pri = pri->dchans[0];
11195 pri->resetpos = -1;
11196 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11197 for (i = 0; i < NUM_DCHANS; i++) {
11198 if (!pri->dchannels[i])
11199 break;
11200 dahdi_close_pri_fd(pri, i);
11201 }
11202 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11203 return -1;
11204 }
11205 return 0;
11206 }
11207
11208 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
11209 {
11210 int which, span;
11211 char *ret = NULL;
11212
11213 if (pos != rpos)
11214 return ret;
11215
11216 for (which = span = 0; span < NUM_SPANS; span++) {
11217 if (pris[span].pri && ++which > state) {
11218 if (asprintf(&ret, "%d", span + 1) < 0) {
11219 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11220 }
11221 break;
11222 }
11223 }
11224 return ret;
11225 }
11226
11227 static char *complete_span_4(const char *line, const char *word, int pos, int state)
11228 {
11229 return complete_span_helper(line,word,pos,state,3);
11230 }
11231
11232 static char *complete_span_5(const char *line, const char *word, int pos, int state)
11233 {
11234 return complete_span_helper(line,word,pos,state,4);
11235 }
11236
11237 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
11238 {
11239 int myfd;
11240
11241 if (!strncasecmp(argv[1], "set", 3)) {
11242 if (argc < 5)
11243 return RESULT_SHOWUSAGE;
11244
11245 if (ast_strlen_zero(argv[4]))
11246 return RESULT_SHOWUSAGE;
11247
11248 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
11249 if (myfd < 0) {
11250 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
11251 return RESULT_SUCCESS;
11252 }
11253
11254 ast_mutex_lock(&pridebugfdlock);
11255
11256 if (pridebugfd >= 0)
11257 close(pridebugfd);
11258
11259 pridebugfd = myfd;
11260 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
11261
11262 ast_mutex_unlock(&pridebugfdlock);
11263
11264 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
11265 } else {
11266
11267 ast_mutex_lock(&pridebugfdlock);
11268 close(pridebugfd);
11269 pridebugfd = -1;
11270 ast_cli(fd, "PRI debug output to file disabled\n");
11271 ast_mutex_unlock(&pridebugfdlock);
11272 }
11273
11274 return RESULT_SUCCESS;
11275 }
11276
11277 #ifdef HAVE_PRI_VERSION
11278 static int handle_pri_version(int fd, int agc, char *argv[]) {
11279 ast_cli(fd, "libpri version: %s\n", pri_get_version());
11280 return RESULT_SUCCESS;
11281 }
11282 #endif
11283
11284 static int handle_pri_debug(int fd, int argc, char *argv[])
11285 {
11286 int span;
11287 int x;
11288 if (argc < 4) {
11289 return RESULT_SHOWUSAGE;
11290 }
11291 span = atoi(argv[3]);
11292 if ((span < 1) || (span > NUM_SPANS)) {
11293 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11294 return RESULT_SUCCESS;
11295 }
11296 if (!pris[span-1].pri) {
11297 ast_cli(fd, "No PRI running on span %d\n", span);
11298 return RESULT_SUCCESS;
11299 }
11300 for (x = 0; x < NUM_DCHANS; x++) {
11301 if (pris[span-1].dchans[x])
11302 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11303 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11304 PRI_DEBUG_Q921_STATE);
11305 }
11306 ast_cli(fd, "Enabled debugging on span %d\n", span);
11307 return RESULT_SUCCESS;
11308 }
11309
11310
11311
11312 static int handle_pri_no_debug(int fd, int argc, char *argv[])
11313 {
11314 int span;
11315 int x;
11316 if (argc < 5)
11317 return RESULT_SHOWUSAGE;
11318 span = atoi(argv[4]);
11319 if ((span < 1) || (span > NUM_SPANS)) {
11320 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11321 return RESULT_SUCCESS;
11322 }
11323 if (!pris[span-1].pri) {
11324 ast_cli(fd, "No PRI running on span %d\n", span);
11325 return RESULT_SUCCESS;
11326 }
11327 for (x = 0; x < NUM_DCHANS; x++) {
11328 if (pris[span-1].dchans[x])
11329 pri_set_debug(pris[span-1].dchans[x], 0);
11330 }
11331 ast_cli(fd, "Disabled debugging on span %d\n", span);
11332 return RESULT_SUCCESS;
11333 }
11334
11335 static int handle_pri_really_debug(int fd, int argc, char *argv[])
11336 {
11337 int span;
11338 int x;
11339 if (argc < 5)
11340 return RESULT_SHOWUSAGE;
11341 span = atoi(argv[4]);
11342 if ((span < 1) || (span > NUM_SPANS)) {
11343 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11344 return RESULT_SUCCESS;
11345 }
11346 if (!pris[span-1].pri) {
11347 ast_cli(fd, "No PRI running on span %d\n", span);
11348 return RESULT_SUCCESS;
11349 }
11350 for (x = 0; x < NUM_DCHANS; x++) {
11351 if (pris[span-1].dchans[x])
11352 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11353 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11354 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11355 }
11356 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11357 return RESULT_SUCCESS;
11358 }
11359
11360 static void build_status(char *s, size_t len, int status, int active)
11361 {
11362 if (!s || len < 1) {
11363 return;
11364 }
11365 s[0] = '\0';
11366 if (status & DCHAN_PROVISIONED)
11367 strncat(s, "Provisioned, ", len - strlen(s) - 1);
11368 if (!(status & DCHAN_NOTINALARM))
11369 strncat(s, "In Alarm, ", len - strlen(s) - 1);
11370 if (status & DCHAN_UP)
11371 strncat(s, "Up", len - strlen(s) - 1);
11372 else
11373 strncat(s, "Down", len - strlen(s) - 1);
11374 if (active)
11375 strncat(s, ", Active", len - strlen(s) - 1);
11376 else
11377 strncat(s, ", Standby", len - strlen(s) - 1);
11378 s[len - 1] = '\0';
11379 }
11380
11381 static int handle_pri_show_spans(int fd, int argc, char *argv[])
11382 {
11383 int span;
11384 int x;
11385 char status[256];
11386 if (argc != 3)
11387 return RESULT_SHOWUSAGE;
11388
11389 for (span = 0; span < NUM_SPANS; span++) {
11390 if (pris[span].pri) {
11391 for (x = 0; x < NUM_DCHANS; x++) {
11392 if (pris[span].dchannels[x]) {
11393 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11394 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11395 }
11396 }
11397 }
11398 }
11399 return RESULT_SUCCESS;
11400 }
11401
11402 static int handle_pri_show_span(int fd, int argc, char *argv[])
11403 {
11404 int span;
11405 int x;
11406 char status[256];
11407 if (argc < 4)
11408 return RESULT_SHOWUSAGE;
11409 span = atoi(argv[3]);
11410 if ((span < 1) || (span > NUM_SPANS)) {
11411 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11412 return RESULT_SUCCESS;
11413 }
11414 if (!pris[span-1].pri) {
11415 ast_cli(fd, "No PRI running on span %d\n", span);
11416 return RESULT_SUCCESS;
11417 }
11418 for (x = 0; x < NUM_DCHANS; x++) {
11419 if (pris[span-1].dchannels[x]) {
11420 #ifdef PRI_DUMP_INFO_STR
11421 char *info_str = NULL;
11422 #endif
11423 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11424 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11425 ast_cli(fd, "Status: %s\n", status);
11426 #ifdef PRI_DUMP_INFO_STR
11427 info_str = pri_dump_info_str(pris[span-1].pri);
11428 if (info_str) {
11429 ast_cli(fd, "%s", info_str);
11430 free(info_str);
11431 }
11432 #else
11433 pri_dump_info(pris[span-1].pri);
11434 #endif
11435 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11436 }
11437 }
11438 return RESULT_SUCCESS;
11439 }
11440
11441 static int handle_pri_show_debug(int fd, int argc, char *argv[])
11442 {
11443 int x;
11444 int span;
11445 int count=0;
11446 int debug=0;
11447
11448 for (span = 0; span < NUM_SPANS; span++) {
11449 if (pris[span].pri) {
11450 for (x = 0; x < NUM_DCHANS; x++) {
11451 debug = 0;
11452 if (pris[span].dchans[x]) {
11453 debug = pri_get_debug(pris[span].dchans[x]);
11454 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" );
11455 count++;
11456 }
11457 }
11458 }
11459
11460 }
11461 ast_mutex_lock(&pridebugfdlock);
11462 if (pridebugfd >= 0)
11463 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
11464 ast_mutex_unlock(&pridebugfdlock);
11465
11466 if (!count)
11467 ast_cli(fd, "No debug set or no PRI running\n");
11468 return RESULT_SUCCESS;
11469 }
11470
11471 static const char pri_debug_help[] =
11472 "Usage: pri debug span <span>\n"
11473 " Enables debugging on a given PRI span\n";
11474
11475 static const char pri_no_debug_help[] =
11476 "Usage: pri no debug span <span>\n"
11477 " Disables debugging on a given PRI span\n";
11478
11479 static const char pri_really_debug_help[] =
11480 "Usage: pri intensive debug span <span>\n"
11481 " Enables debugging down to the Q.921 level\n";
11482
11483 static const char pri_show_span_help[] =
11484 "Usage: pri show span <span>\n"
11485 " Displays PRI Information on a given PRI span\n";
11486
11487 static const char pri_show_spans_help[] =
11488 "Usage: pri show spans\n"
11489 " Displays PRI Information\n";
11490
11491 static struct ast_cli_entry dahdi_pri_cli[] = {
11492 { { "pri", "debug", "span", NULL },
11493 handle_pri_debug, "Enables PRI debugging on a span",
11494 pri_debug_help, complete_span_4 },
11495
11496 { { "pri", "no", "debug", "span", NULL },
11497 handle_pri_no_debug, "Disables PRI debugging on a span",
11498 pri_no_debug_help, complete_span_5 },
11499
11500 { { "pri", "intense", "debug", "span", NULL },
11501 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
11502 pri_really_debug_help, complete_span_5 },
11503
11504 { { "pri", "show", "spans", NULL },
11505 handle_pri_show_spans, "Displays PRI Information",
11506 pri_show_spans_help },
11507
11508 { { "pri", "show", "span", NULL },
11509 handle_pri_show_span, "Displays PRI Information",
11510 pri_show_span_help, complete_span_4 },
11511
11512 { { "pri", "show", "debug", NULL },
11513 handle_pri_show_debug, "Displays current PRI debug settings" },
11514
11515 { { "pri", "set", "debug", "file", NULL },
11516 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
11517
11518 { { "pri", "unset", "debug", "file", NULL },
11519 handle_pri_set_debug_file, "Ends PRI debug output to file" },
11520
11521 #ifdef HAVE_PRI_VERSION
11522 { { "pri", "show", "version", NULL },
11523 handle_pri_version, "Displays version of libpri" },
11524 #endif
11525 };
11526
11527 #endif
11528
11529 #ifdef HAVE_OPENR2
11530
11531 static int handle_mfcr2_version(int fd, int argc, char *argv[])
11532 {
11533 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11534 return RESULT_SUCCESS;
11535 }
11536
11537 static int handle_mfcr2_show_variants(int fd, int argc, char *argv[])
11538 {
11539 #define FORMAT "%4s %40s\n"
11540 int numvariants = 0;
11541 int i;
11542 const openr2_variant_entry_t *variants;
11543 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
11544 ast_cli(fd, "Failed to get list of variants.\n");
11545 return RESULT_FAILURE;
11546 }
11547 ast_cli(fd, FORMAT, "Variant Code", "Country");
11548 for (i = 0; i < numvariants; i++) {
11549 ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
11550 }
11551 return RESULT_SUCCESS;
11552 #undef FORMAT
11553 }
11554
11555 static int handle_mfcr2_show_channels(int fd, int argc, char *argv[])
11556 {
11557 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
11558 int filtertype = 0;
11559 int targetnum = 0;
11560 char channo[5];
11561 char anino[5];
11562 char dnisno[5];
11563 struct dahdi_pvt *p;
11564 openr2_context_t *r2context;
11565 openr2_variant_t r2variant;
11566 if (!((argc == 3) || (argc == 5))) {
11567 return RESULT_SHOWUSAGE;
11568 }
11569 if (argc == 5) {
11570 if (!strcasecmp(argv[3], "group")) {
11571 targetnum = atoi(argv[4]);
11572 if ((targetnum < 0) || (targetnum > 63))
11573 return RESULT_SHOWUSAGE;
11574 targetnum = 1 << targetnum;
11575 filtertype = 1;
11576 } else if (!strcasecmp(argv[3], "context")) {
11577 filtertype = 2;
11578 } else {
11579 return RESULT_SHOWUSAGE;
11580 }
11581 }
11582 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
11583 ast_mutex_lock(&iflock);
11584 p = iflist;
11585 while (p) {
11586 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11587 p = p->next;
11588 continue;
11589 }
11590 if (filtertype) {
11591 switch(filtertype) {
11592 case 1:
11593 if (p->group != targetnum) {
11594 p = p->next;
11595 continue;
11596 }
11597 break;
11598 case 2:
11599 if (strcasecmp(p->context, argv[4])) {
11600 p= p->next;
11601 continue;
11602 }
11603 break;
11604 default:
11605 ;
11606 }
11607 }
11608 r2context = openr2_chan_get_context(p->r2chan);
11609 r2variant = openr2_context_get_variant(r2context);
11610 snprintf(channo, sizeof(channo), "%d", p->channel);
11611 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
11612 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
11613 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
11614 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
11615 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
11616 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
11617 p = p->next;
11618 }
11619 ast_mutex_unlock(&iflock);
11620 return RESULT_SUCCESS;
11621 #undef FORMAT
11622 }
11623
11624 static int handle_mfcr2_set_debug(int fd, int argc, char *argv[])
11625 {
11626 struct dahdi_pvt *p = NULL;
11627 int channo = 0;
11628 char *toklevel = NULL;
11629 char *saveptr = NULL;
11630 char *logval = NULL;
11631 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
11632 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
11633 if (argc < 4) {
11634 return RESULT_SHOWUSAGE;
11635 }
11636 channo = (argc == 5) ? atoi(argv[4]) : -1;
11637 logval = ast_strdupa(argv[3]);
11638 toklevel = strtok_r(logval, ",", &saveptr);
11639 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11640 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
11641 return RESULT_FAILURE;
11642 } else if (OR2_LOG_NOTHING == tmplevel) {
11643 loglevel = tmplevel;
11644 } else {
11645 loglevel |= tmplevel;
11646 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
11647 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11648 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
11649 continue;
11650 }
11651 loglevel |= tmplevel;
11652 }
11653 }
11654 ast_mutex_lock(&iflock);
11655 p = iflist;
11656 while (p) {
11657 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11658 p = p->next;
11659 continue;
11660 }
11661 if ((channo != -1) && (p->channel != channo )) {
11662 p = p->next;
11663 continue;
11664 }
11665 openr2_chan_set_log_level(p->r2chan, loglevel);
11666 if (channo != -1) {
11667 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
11668 break;
11669 } else {
11670 p = p->next;
11671 }
11672 }
11673 if ((channo != -1) && !p) {
11674 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11675 }
11676 if (channo == -1) {
11677 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
11678 }
11679 ast_mutex_unlock(&iflock);
11680 return RESULT_SUCCESS;
11681 }
11682
11683 static int handle_mfcr2_call_files(int fd, int argc, char *argv[])
11684 {
11685 struct dahdi_pvt *p = NULL;
11686 int channo = 0;
11687 if (argc < 4) {
11688 return RESULT_SHOWUSAGE;
11689 }
11690 channo = (argc == 5) ? atoi(argv[4]) : -1;
11691 ast_mutex_lock(&iflock);
11692 p = iflist;
11693 while (p) {
11694 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11695 p = p->next;
11696 continue;
11697 }
11698 if ((channo != -1) && (p->channel != channo )) {
11699 p = p->next;
11700 continue;
11701 }
11702 if (ast_true(argv[3])) {
11703 openr2_chan_enable_call_files(p->r2chan);
11704 } else {
11705 openr2_chan_disable_call_files(p->r2chan);
11706 }
11707 if (channo != -1) {
11708 if (ast_true(argv[3])) {
11709 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
11710 } else {
11711 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
11712 }
11713 break;
11714 } else {
11715 p = p->next;
11716 }
11717 }
11718 if ((channo != -1) && !p) {
11719 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11720 }
11721 if (channo == -1) {
11722 if (ast_true(argv[3])) {
11723 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
11724 } else {
11725 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
11726 }
11727 }
11728 ast_mutex_unlock(&iflock);
11729 return RESULT_SUCCESS;
11730 }
11731
11732 static int handle_mfcr2_set_idle(int fd, int argc, char *argv[])
11733 {
11734 struct dahdi_pvt *p = NULL;
11735 int channo = 0;
11736 channo = (argc == 4) ? atoi(argv[3]) : -1;
11737 ast_mutex_lock(&iflock);
11738 p = iflist;
11739 while (p) {
11740 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11741 p = p->next;
11742 continue;
11743 }
11744 if ((channo != -1) && (p->channel != channo )) {
11745 p = p->next;
11746 continue;
11747 }
11748 if (!openr2_chan_set_idle(p->r2chan)) {
11749 ast_mutex_lock(&p->lock);
11750 p->mfcr2call = 0;
11751 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
11752 ast_mutex_unlock(&p->lock);
11753 }
11754 if (channo != -1) {
11755 break;
11756 } else {
11757 p = p->next;
11758 }
11759 }
11760 if ((channo != -1) && !p) {
11761 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11762 }
11763 ast_mutex_unlock(&iflock);
11764 return RESULT_SUCCESS;
11765 }
11766
11767 static int handle_mfcr2_set_blocked(int fd, int argc, char *argv[])
11768 {
11769 struct dahdi_pvt *p = NULL;
11770 int channo = 0;
11771 channo = (argc == 4) ? atoi(argv[3]) : -1;
11772 ast_mutex_lock(&iflock);
11773 p = iflist;
11774 while (p) {
11775 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11776 p = p->next;
11777 continue;
11778 }
11779 if ((channo != -1) && (p->channel != channo )) {
11780 p = p->next;
11781 continue;
11782 }
11783 if (!openr2_chan_set_blocked(p->r2chan)) {
11784 ast_mutex_lock(&p->lock);
11785 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
11786 ast_mutex_unlock(&p->lock);
11787 } else {
11788 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
11789 }
11790 if (channo != -1) {
11791 break;
11792 } else {
11793 p = p->next;
11794 }
11795 }
11796 if ((channo != -1) && !p) {
11797 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11798 }
11799 ast_mutex_unlock(&iflock);
11800 return RESULT_SUCCESS;
11801 }
11802
11803 static const char dahdi_r2_version_help[] =
11804 "Usage: mfcr2 show version\n"
11805 " Shows the version of the OpenR2 library being used.\n";
11806 static const char dahdi_r2_variants_help[] =
11807 "Usage: mfcr2 show variants\n"
11808 " Show supported MFC/R2 variants.\n";
11809 static const char dahdi_r2_showchannels_help[] =
11810 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
11811 " Shows the zap channels configured with MFC/R2 signaling.\n";
11812 static const char dahdi_r2_setdebug_help[] =
11813 "Usage: mfcr2 set debug <loglevel> <channel>\n"
11814 " Set a new logging level for the specified channel.\n"
11815 " If no channel is specified the logging level will be applied to all channels.\n";
11816 static const char dahdi_r2_callfiles_help[] =
11817 "Usage: mfcr2 call files [on|off] <channel>\n"
11818 " Enable call files creation on the specified channel.\n"
11819 " If no channel is specified call files creation policy will be applied to all channels.\n";
11820 static const char dahdi_r2_setidle_help[] =
11821 "Usage: mfcr2 set idle <channel>\n"
11822 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11823 " Force the given channel into IDLE state.\n"
11824 " If no channel is specified, all channels will be set to IDLE.\n";
11825 static const char dahdi_r2_setblocked_help[] =
11826 "Usage: mfcr2 set blocked <channel>\n"
11827 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11828 " Force the given channel into BLOCKED state.\n"
11829 " If no channel is specified, all channels will be set to BLOCKED.\n";
11830
11831 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
11832 { { "mfcr2", "show", "version", NULL },
11833 handle_mfcr2_version, "Show OpenR2 library version",
11834 dahdi_r2_version_help },
11835
11836 { { "mfcr2", "show", "variants", NULL },
11837 handle_mfcr2_show_variants, "Show supported MFC/R2 variants",
11838 dahdi_r2_variants_help },
11839
11840 { { "mfcr2", "show", "channels", NULL },
11841 handle_mfcr2_show_channels, "Show MFC/R2 channels",
11842 dahdi_r2_showchannels_help },
11843
11844 { { "mfcr2", "set", "debug", NULL },
11845 handle_mfcr2_set_debug, "Set MFC/R2 channel logging level",
11846 dahdi_r2_setdebug_help },
11847
11848 { { "mfcr2", "call", "files", NULL },
11849 handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files",
11850 dahdi_r2_callfiles_help },
11851
11852 { { "mfcr2", "set", "idle", NULL },
11853 handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE",
11854 dahdi_r2_setidle_help },
11855
11856 { { "mfcr2", "set", "blocked", NULL },
11857 handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED",
11858 dahdi_r2_setblocked_help }
11859
11860 };
11861
11862 #endif
11863
11864 static int dahdi_destroy_channel(int fd, int argc, char **argv)
11865 {
11866 int channel;
11867
11868 if (argc != 4)
11869 return RESULT_SHOWUSAGE;
11870
11871 channel = atoi(argv[3]);
11872
11873 return dahdi_destroy_channel_bynum(channel);
11874 }
11875
11876 static void dahdi_softhangup_all(void)
11877 {
11878 struct dahdi_pvt *p;
11879 retry:
11880 ast_mutex_lock(&iflock);
11881 for (p = iflist; p; p = p->next) {
11882 ast_mutex_lock(&p->lock);
11883 if (p->owner && !p->restartpending) {
11884 if (ast_channel_trylock(p->owner)) {
11885 if (option_debug > 2)
11886 ast_verbose("Avoiding deadlock\n");
11887
11888 ast_mutex_unlock(&p->lock);
11889 ast_mutex_unlock(&iflock);
11890 goto retry;
11891 }
11892 if (option_debug > 2)
11893 ast_verbose("Softhanging up on %s\n", p->owner->name);
11894 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11895 p->restartpending = 1;
11896 num_restart_pending++;
11897 ast_channel_unlock(p->owner);
11898 }
11899 ast_mutex_unlock(&p->lock);
11900 }
11901 ast_mutex_unlock(&iflock);
11902 }
11903
11904 static int setup_dahdi(int reload);
11905 static int dahdi_restart(void)
11906 {
11907 #ifdef HAVE_OPENR2
11908 int r;
11909 #endif
11910 #if defined(HAVE_PRI)
11911 int i, j;
11912 #endif
11913 int cancel_code;
11914 struct dahdi_pvt *p;
11915
11916 ast_mutex_lock(&restart_lock);
11917
11918 if (option_verbose)
11919 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
11920 dahdi_softhangup_all();
11921 if (option_verbose > 3)
11922 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
11923
11924 #ifdef HAVE_OPENR2
11925 for (r = 0; r < NUM_SPANS; r++) {
11926 if (r2links[r].master != AST_PTHREADT_NULL) {
11927 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
11928 pthread_cancel(r2links[r].master);
11929 pthread_join(r2links[r].master, NULL);
11930 openr2_context_delete(r2links[r].protocol_context);
11931 }
11932 }
11933 init_mfcr2_globals();
11934 #endif
11935
11936 #if defined(HAVE_PRI)
11937 for (i = 0; i < NUM_SPANS; i++) {
11938 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
11939 cancel_code = pthread_cancel(pris[i].master);
11940 pthread_kill(pris[i].master, SIGURG);
11941 if (option_debug > 3)
11942 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
11943 pthread_join(pris[i].master, NULL);
11944 if (option_debug > 3)
11945 ast_verbose("Joined thread of span %d\n", i);
11946 }
11947 }
11948 #endif
11949
11950 ast_mutex_lock(&monlock);
11951 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11952 cancel_code = pthread_cancel(monitor_thread);
11953 pthread_kill(monitor_thread, SIGURG);
11954 if (option_debug > 3)
11955 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
11956 pthread_join(monitor_thread, NULL);
11957 if (option_debug > 3)
11958 ast_verbose("Joined monitor thread\n");
11959 }
11960 monitor_thread = AST_PTHREADT_NULL;
11961
11962 ast_mutex_lock(&ss_thread_lock);
11963 while (ss_thread_count > 0) {
11964 int x = DAHDI_FLASH;
11965 if (option_debug > 2)
11966 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
11967
11968 for (p = iflist; p; p = p->next) {
11969 if (p->owner)
11970 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11971 }
11972 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
11973 }
11974
11975
11976 dahdi_softhangup_all();
11977 if (option_verbose > 3)
11978 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
11979 destroy_all_channels();
11980 if (option_debug)
11981 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
11982
11983 ast_mutex_unlock(&monlock);
11984
11985 #ifdef HAVE_PRI
11986 for (i = 0; i < NUM_SPANS; i++) {
11987 for (j = 0; j < NUM_DCHANS; j++)
11988 dahdi_close_pri_fd(&(pris[i]), j);
11989 }
11990
11991 memset(pris, 0, sizeof(pris));
11992 for (i = 0; i < NUM_SPANS; i++) {
11993 ast_mutex_init(&pris[i].lock);
11994 pris[i].offset = -1;
11995 pris[i].master = AST_PTHREADT_NULL;
11996 for (j = 0; j < NUM_DCHANS; j++)
11997 pris[i].fds[j] = -1;
11998 }
11999 pri_set_error(dahdi_pri_error);
12000 pri_set_message(dahdi_pri_message);
12001 #endif
12002
12003 if (setup_dahdi(2) != 0) {
12004 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12005 ast_mutex_unlock(&ss_thread_lock);
12006 return 1;
12007 }
12008 ast_mutex_unlock(&ss_thread_lock);
12009 ast_mutex_unlock(&restart_lock);
12010 return 0;
12011 }
12012
12013 static int dahdi_restart_cmd(int fd, int argc, char **argv)
12014 {
12015 if (argc != 2) {
12016 return RESULT_SHOWUSAGE;
12017 }
12018
12019 if (dahdi_restart() != 0)
12020 return RESULT_FAILURE;
12021 return RESULT_SUCCESS;
12022 }
12023
12024 static int dahdi_show_channels(int fd, int argc, char **argv)
12025 {
12026 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12027 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12028 struct dahdi_pvt *tmp = NULL;
12029 char tmps[20] = "";
12030 ast_mutex_t *lock;
12031 struct dahdi_pvt *start;
12032 #ifdef HAVE_PRI
12033 int trunkgroup;
12034 struct dahdi_pri *pri = NULL;
12035 int x;
12036 #endif
12037
12038 lock = &iflock;
12039 start = iflist;
12040
12041 #ifdef HAVE_PRI
12042 if (argc == 4) {
12043 if ((trunkgroup = atoi(argv[3])) < 1)
12044 return RESULT_SHOWUSAGE;
12045 for (x = 0; x < NUM_SPANS; x++) {
12046 if (pris[x].trunkgroup == trunkgroup) {
12047 pri = pris + x;
12048 break;
12049 }
12050 }
12051 if (pri) {
12052 start = pri->crvs;
12053 lock = &pri->lock;
12054 } else {
12055 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12056 return RESULT_FAILURE;
12057 }
12058 } else
12059 #endif
12060 if (argc != 3)
12061 return RESULT_SHOWUSAGE;
12062
12063 ast_mutex_lock(lock);
12064 #ifdef HAVE_PRI
12065 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
12066 #else
12067 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
12068 #endif
12069
12070 tmp = start;
12071 while (tmp) {
12072 if (tmp->channel > 0) {
12073 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12074 } else
12075 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12076 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
12077 tmp = tmp->next;
12078 }
12079 ast_mutex_unlock(lock);
12080 return RESULT_SUCCESS;
12081 #undef FORMAT
12082 #undef FORMAT2
12083 }
12084
12085 static int dahdi_show_channel(int fd, int argc, char **argv)
12086 {
12087 int channel;
12088 struct dahdi_pvt *tmp = NULL;
12089 struct dahdi_confinfo ci;
12090 struct dahdi_params ps;
12091 int x;
12092 ast_mutex_t *lock;
12093 struct dahdi_pvt *start;
12094 #ifdef HAVE_PRI
12095 char *c;
12096 int trunkgroup;
12097 struct dahdi_pri *pri=NULL;
12098 #endif
12099
12100 lock = &iflock;
12101 start = iflist;
12102
12103 if (argc != 4)
12104 return RESULT_SHOWUSAGE;
12105 #ifdef HAVE_PRI
12106 if ((c = strchr(argv[3], ':'))) {
12107 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12108 return RESULT_SHOWUSAGE;
12109 if ((trunkgroup < 1) || (channel < 1))
12110 return RESULT_SHOWUSAGE;
12111 for (x = 0; x < NUM_SPANS; x++) {
12112 if (pris[x].trunkgroup == trunkgroup) {
12113 pri = pris + x;
12114 break;
12115 }
12116 }
12117 if (pri) {
12118 start = pri->crvs;
12119 lock = &pri->lock;
12120 } else {
12121 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12122 return RESULT_FAILURE;
12123 }
12124 } else
12125 #endif
12126 channel = atoi(argv[3]);
12127
12128 ast_mutex_lock(lock);
12129 tmp = start;
12130 while (tmp) {
12131 if (tmp->channel == channel) {
12132 #ifdef HAVE_PRI
12133 if (pri)
12134 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12135 else
12136 #endif
12137 ast_cli(fd, "Channel: %d\n", tmp->channel);
12138 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12139 ast_cli(fd, "Span: %d\n", tmp->span);
12140 ast_cli(fd, "Extension: %s\n", tmp->exten);
12141 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12142 ast_cli(fd, "Context: %s\n", tmp->context);
12143 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
12144 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
12145 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
12146 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
12147 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
12148 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12149 ast_cli(fd, "Radio: %d\n", tmp->radio);
12150 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12151 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)" : "");
12152 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)" : "");
12153 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)" : "");
12154 ast_cli(fd, "Confno: %d\n", tmp->confno);
12155 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
12156 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
12157 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12158 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12159 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12160 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12161 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12162 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12163 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
12164 if (tmp->master)
12165 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
12166 for (x = 0; x < MAX_SLAVES; x++) {
12167 if (tmp->slaves[x])
12168 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12169 }
12170 #ifdef HAVE_OPENR2
12171 if (tmp->mfcr2) {
12172 char calldir[OR2_MAX_PATH];
12173 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
12174 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
12175 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
12176 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
12177 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
12178 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
12179 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
12180 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
12181 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
12182 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
12183 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
12184 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
12185 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12186 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
12187 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
12188 #endif
12189 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
12190 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
12191 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
12192 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
12193 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
12194 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
12195 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
12196 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
12197 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
12198 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
12199 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
12200 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
12201 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
12202 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
12203 }
12204 #endif
12205 #ifdef HAVE_PRI
12206 if (tmp->pri) {
12207 ast_cli(fd, "PRI Flags: ");
12208 if (tmp->resetting)
12209 ast_cli(fd, "Resetting ");
12210 if (tmp->call)
12211 ast_cli(fd, "Call ");
12212 if (tmp->bearer)
12213 ast_cli(fd, "Bearer ");
12214 ast_cli(fd, "\n");
12215 if (tmp->logicalspan)
12216 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12217 else
12218 ast_cli(fd, "PRI Logical Span: Implicit\n");
12219 }
12220
12221 #endif
12222 memset(&ci, 0, sizeof(ci));
12223 ps.channo = tmp->channel;
12224 if (tmp->subs[SUB_REAL].dfd > -1) {
12225 memset(&ci, 0, sizeof(ci));
12226 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12227 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12228 }
12229 #ifdef DAHDI_GETCONFMUTE
12230 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12231 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12232 }
12233 #endif
12234 memset(&ps, 0, sizeof(ps));
12235 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12236 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12237 } else {
12238 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12239 }
12240 }
12241 if (ISTRUNK(tmp)) {
12242 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
12243 if (!ast_strlen_zero(progzone))
12244 ast_cli(fd, "Progress Zone: %s\n", progzone);
12245 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
12246 if(tmp->busydetect) {
12247 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
12248 if(tmp->busytonelength > 0) {
12249 ast_cli(fd, "Busy Pattern:\n");
12250 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12251 if (tmp->busyquietlength > 0)
12252 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12253 else
12254 ast_cli(fd, " -- Detect Tone Only\n");
12255 if(tmp->busyfuzziness > 0)
12256 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12257 }
12258 }
12259 }
12260 ast_mutex_unlock(lock);
12261 return RESULT_SUCCESS;
12262 }
12263 tmp = tmp->next;
12264 }
12265
12266 ast_cli(fd, "Unable to find given channel %d\n", channel);
12267 ast_mutex_unlock(lock);
12268 return RESULT_FAILURE;
12269 }
12270
12271 static char dahdi_show_cadences_usage[] =
12272 "Usage: dahdi show cadences\n"
12273 " Shows all cadences currently defined\n";
12274
12275 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
12276 {
12277 int i, j;
12278 for (i = 0; i < num_cadence; i++) {
12279 char output[1024];
12280 char tmp[16], tmp2[64];
12281 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12282 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12283
12284 for (j = 0; j < 16; j++) {
12285 if (cadences[i].ringcadence[j] == 0)
12286 break;
12287 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12288 if (cidrings[i] * 2 - 1 == j)
12289 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12290 else
12291 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12292 if (j != 0)
12293 strncat(output, ",", sizeof(output) - strlen(output) - 1);
12294 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12295 }
12296 ast_cli(fd,"%s\n",output);
12297 }
12298 return 0;
12299 }
12300
12301
12302 static int dahdi_show_status(int fd, int argc, char *argv[]) {
12303 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12304 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12305
12306 int span;
12307 int res;
12308 char alarms[50];
12309
12310 int ctl;
12311 struct dahdi_spaninfo s;
12312
12313 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
12314 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
12315 ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
12316 return RESULT_FAILURE;
12317 }
12318 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
12319
12320 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12321 s.spanno = span;
12322 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12323 if (res) {
12324 continue;
12325 }
12326 alarms[0] = '\0';
12327 if (s.alarms > 0) {
12328 if (s.alarms & DAHDI_ALARM_BLUE)
12329 strcat(alarms, "BLU/");
12330 if (s.alarms & DAHDI_ALARM_YELLOW)
12331 strcat(alarms, "YEL/");
12332 if (s.alarms & DAHDI_ALARM_RED)
12333 strcat(alarms, "RED/");
12334 if (s.alarms & DAHDI_ALARM_LOOPBACK)
12335 strcat(alarms, "LB/");
12336 if (s.alarms & DAHDI_ALARM_RECOVER)
12337 strcat(alarms, "REC/");
12338 if (s.alarms & DAHDI_ALARM_NOTOPEN)
12339 strcat(alarms, "NOP/");
12340 if (!strlen(alarms))
12341 strcat(alarms, "UUU/");
12342 if (strlen(alarms)) {
12343
12344 alarms[strlen(alarms) - 1] = '\0';
12345 }
12346 } else {
12347 if (s.numchans)
12348 strcpy(alarms, "OK");
12349 else
12350 strcpy(alarms, "UNCONFIGURED");
12351 }
12352
12353 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12354 }
12355 close(ctl);
12356
12357 return RESULT_SUCCESS;
12358 #undef FORMAT
12359 #undef FORMAT2
12360 }
12361
12362 static char show_channels_usage[] =
12363 "Usage: dahdi show channels\n"
12364 " Shows a list of available channels\n";
12365
12366 static char show_channel_usage[] =
12367 "Usage: dahdi show channel <chan num>\n"
12368 " Detailed information about a given channel\n";
12369
12370 static char dahdi_show_status_usage[] =
12371 "Usage: dahdi show status\n"
12372 " Shows a list of DAHDI cards with status\n";
12373
12374 static char destroy_channel_usage[] =
12375 "Usage: dahdi destroy channel <chan num>\n"
12376 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12377
12378 static char dahdi_restart_usage[] =
12379 "Usage: dahdi restart\n"
12380 " Restarts the DAHDI channels: destroys them all and then\n"
12381 " re-reads them from chan_dahdi.conf.\n"
12382 " Note that this will STOP any running CALL on DAHDI channels.\n"
12383 "";
12384
12385 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
12386 { "zap", "show", "cadences", NULL },
12387 handle_dahdi_show_cadences, NULL,
12388 NULL };
12389
12390 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
12391 { "zap", "show", "channels", NULL },
12392 dahdi_show_channels, NULL,
12393 NULL };
12394
12395 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
12396 { "zap", "show", "channel", NULL },
12397 dahdi_show_channel, NULL,
12398 NULL };
12399
12400 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
12401 { "zap", "destroy", "channel", NULL },
12402 dahdi_destroy_channel, NULL,
12403 NULL };
12404
12405 static struct ast_cli_entry cli_zap_restart_deprecated = {
12406 { "zap", "restart", NULL },
12407 dahdi_restart_cmd, NULL,
12408 NULL };
12409
12410 static struct ast_cli_entry cli_zap_show_status_deprecated = {
12411 { "zap", "show", "status", NULL },
12412 dahdi_show_status, NULL,
12413 NULL };
12414
12415 static struct ast_cli_entry dahdi_cli[] = {
12416 { { "dahdi", "show", "cadences", NULL },
12417 handle_dahdi_show_cadences, "List cadences",
12418 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
12419
12420 { { "dahdi", "show", "channels", NULL},
12421 dahdi_show_channels, "Show active DAHDI channels",
12422 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
12423
12424 { { "dahdi", "show", "channel", NULL},
12425 dahdi_show_channel, "Show information on a channel",
12426 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
12427
12428 { { "dahdi", "destroy", "channel", NULL},
12429 dahdi_destroy_channel, "Destroy a channel",
12430 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
12431
12432 { { "dahdi", "restart", NULL},
12433 dahdi_restart_cmd, "Fully restart DAHDI channels",
12434 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
12435
12436 { { "dahdi", "show", "status", NULL},
12437 dahdi_show_status, "Show all DAHDI cards status",
12438 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
12439 };
12440
12441 #define TRANSFER 0
12442 #define HANGUP 1
12443
12444 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
12445 {
12446 if (p) {
12447 switch (mode) {
12448 case TRANSFER:
12449 p->fake_event = DAHDI_EVENT_WINKFLASH;
12450 break;
12451 case HANGUP:
12452 p->fake_event = DAHDI_EVENT_ONHOOK;
12453 break;
12454 default:
12455 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
12456 }
12457 }
12458 return 0;
12459 }
12460 static struct dahdi_pvt *find_channel(int channel)
12461 {
12462 struct dahdi_pvt *p = iflist;
12463 while (p) {
12464 if (p->channel == channel) {
12465 break;
12466 }
12467 p = p->next;
12468 }
12469 return p;
12470 }
12471
12472 #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)
12473 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
12474
12475 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
12476 {
12477 struct dahdi_pvt *p = NULL;
12478 const char *channel = local_astman_header(m, "Channel", zap_mode);
12479
12480 if (ast_strlen_zero(channel)) {
12481 astman_send_error(s, m, "No channel specified");
12482 return 0;
12483 }
12484 if (!(p = find_channel(atoi(channel)))) {
12485 astman_send_error(s, m, "No such channel");
12486 return 0;
12487 }
12488 p->dnd = dnd;
12489 local_astman_ack(s, m, "DND", zap_mode);
12490
12491 return 0;
12492 }
12493
12494 static int zap_action_dndon(struct mansession *s, const struct message *m)
12495 {
12496 return __action_dnd(s, m, 1, 1);
12497 }
12498
12499 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
12500 {
12501 return __action_dnd(s, m, 0, 1);
12502 }
12503
12504 static int zap_action_dndoff(struct mansession *s, const struct message *m)
12505 {
12506 return __action_dnd(s, m, 1, 0);
12507 }
12508
12509 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
12510 {
12511 return __action_dnd(s, m, 0, 0);
12512 }
12513
12514 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
12515 {
12516 struct dahdi_pvt *p = NULL;
12517 const char *channel = local_astman_header(m, "Channel", zap_mode);
12518
12519 if (ast_strlen_zero(channel)) {
12520 astman_send_error(s, m, "No channel specified");
12521 return 0;
12522 }
12523 if (!(p = find_channel(atoi(channel)))) {
12524 astman_send_error(s, m, "No such channel");
12525 return 0;
12526 }
12527 dahdi_fake_event(p,TRANSFER);
12528 local_astman_ack(s, m, "Transfer", zap_mode);
12529
12530 return 0;
12531 }
12532
12533 static int zap_action_transfer(struct mansession *s, const struct message *m)
12534 {
12535 return __action_transfer(s, m, 1);
12536 }
12537
12538 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
12539 {
12540 return __action_transfer(s, m, 0);
12541 }
12542
12543 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
12544 {
12545 struct dahdi_pvt *p = NULL;
12546 const char *channel = local_astman_header(m, "Channel", zap_mode);
12547
12548 if (ast_strlen_zero(channel)) {
12549 astman_send_error(s, m, "No channel specified");
12550 return 0;
12551 }
12552 if (!(p = find_channel(atoi(channel)))) {
12553 astman_send_error(s, m, "No such channel");
12554 return 0;
12555 }
12556 dahdi_fake_event(p, HANGUP);
12557 local_astman_ack(s, m, "Hangup", zap_mode);
12558 return 0;
12559 }
12560
12561 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
12562 {
12563 return __action_transferhangup(s, m, 1);
12564 }
12565
12566 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
12567 {
12568 return __action_transferhangup(s, m, 0);
12569 }
12570
12571 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
12572 {
12573 struct dahdi_pvt *p = NULL;
12574 const char *channel = local_astman_header(m, "Channel", zap_mode);
12575 const char *number = astman_get_header(m, "Number");
12576 int i;
12577
12578 if (ast_strlen_zero(channel)) {
12579 astman_send_error(s, m, "No channel specified");
12580 return 0;
12581 }
12582 if (ast_strlen_zero(number)) {
12583 astman_send_error(s, m, "No number specified");
12584 return 0;
12585 }
12586 if (!(p = find_channel(atoi(channel)))) {
12587 astman_send_error(s, m, "No such channel");
12588 return 0;
12589 }
12590 if (!p->owner) {
12591 astman_send_error(s, m, "Channel does not have an owner");
12592 return 0;
12593 }
12594 for (i = 0; i < strlen(number); i++) {
12595 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12596
12597 dahdi_queue_frame(p, &f, NULL);
12598 }
12599 local_astman_ack(s, m, "DialOffHook", zap_mode);
12600
12601 return 0;
12602 }
12603
12604 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
12605 {
12606 return __action_dialoffhook(s, m, 1);
12607 }
12608
12609 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
12610 {
12611 return __action_dialoffhook(s, m, 0);
12612 }
12613
12614 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
12615 {
12616 struct dahdi_pvt *tmp = NULL;
12617 const char *id = astman_get_header(m, "ActionID");
12618 char idText[256] = "";
12619
12620 local_astman_ack(s, m, " channel status will follow", zap_mode);
12621 if (!ast_strlen_zero(id))
12622 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12623
12624 ast_mutex_lock(&iflock);
12625
12626 tmp = iflist;
12627 while (tmp) {
12628 if (tmp->channel > 0) {
12629 int alarm = get_alarms(tmp);
12630 astman_append(s,
12631 "Event: %sShowChannels\r\n"
12632 "Channel: %d\r\n"
12633 "Signalling: %s\r\n"
12634 "Context: %s\r\n"
12635 "DND: %s\r\n"
12636 "Alarm: %s\r\n"
12637 "%s"
12638 "\r\n",
12639 dahdi_chan_name,
12640 tmp->channel, sig2str(tmp->sig), tmp->context,
12641 tmp->dnd ? "Enabled" : "Disabled",
12642 alarm2str(alarm), idText);
12643 }
12644
12645 tmp = tmp->next;
12646 }
12647
12648 ast_mutex_unlock(&iflock);
12649
12650 astman_append(s,
12651 "Event: %sShowChannelsComplete\r\n"
12652 "%s"
12653 "\r\n",
12654 dahdi_chan_name,
12655 idText);
12656 return 0;
12657 }
12658
12659 static int zap_action_showchannels(struct mansession *s, const struct message *m)
12660 {
12661 return __action_showchannels(s, m, 1);
12662 }
12663
12664 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
12665 {
12666 return __action_showchannels(s, m, 0);
12667 }
12668
12669 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
12670 {
12671 if (dahdi_restart() != 0) {
12672 if (zap_mode) {
12673 astman_send_error(s, m, "Failed to restart Zap");
12674 } else {
12675 astman_send_error(s, m, "Failed to restart DAHDI");
12676 }
12677 return 1;
12678 }
12679 local_astman_ack(s, m, "Restart: Success", zap_mode);
12680 return 0;
12681 }
12682
12683 static int zap_action_restart(struct mansession *s, const struct message *m)
12684 {
12685 return __action_restart(s, m, 1);
12686 }
12687
12688 static int dahdi_action_restart(struct mansession *s, const struct message *m)
12689 {
12690 return __action_restart(s, m, 0);
12691 }
12692
12693 #define local_astman_unregister(a) do { \
12694 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12695 ast_manager_unregister("DAHDI" a); \
12696 } \
12697 ast_manager_unregister("Zap" a); \
12698 } while (0)
12699
12700 static int __unload_module(void)
12701 {
12702 struct dahdi_pvt *p;
12703 #ifdef HAVE_OPENR2
12704 int r;
12705 #endif
12706 #ifdef HAVE_PRI
12707 int i, j;
12708 for (i = 0; i < NUM_SPANS; i++) {
12709 if (pris[i].master != AST_PTHREADT_NULL)
12710 pthread_cancel(pris[i].master);
12711 }
12712 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12713
12714 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12715 ast_unregister_application(dahdi_send_keypad_facility_app);
12716 }
12717 ast_unregister_application(zap_send_keypad_facility_app);
12718 #endif
12719 #ifdef HAVE_OPENR2
12720 for (r = 0; r < NUM_SPANS; r++) {
12721 if (r2links[r].master != AST_PTHREADT_NULL) {
12722 pthread_cancel(r2links[r].master);
12723 pthread_join(r2links[r].master, NULL);
12724 }
12725 }
12726 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
12727 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12728 ast_unregister_application(dahdi_accept_r2_call_app);
12729 }
12730 ast_unregister_application(zap_accept_r2_call_app);
12731 #endif
12732 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12733 local_astman_unregister("DialOffHook");
12734 local_astman_unregister("Hangup");
12735 local_astman_unregister("Transfer");
12736 local_astman_unregister("DNDoff");
12737 local_astman_unregister("DNDon");
12738 local_astman_unregister("ShowChannels");
12739 local_astman_unregister("Restart");
12740 ast_channel_unregister(chan_tech);
12741 ast_mutex_lock(&iflock);
12742
12743 p = iflist;
12744 while (p) {
12745 if (p->owner)
12746 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12747 p = p->next;
12748 }
12749 ast_mutex_unlock(&iflock);
12750 ast_mutex_lock(&monlock);
12751 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12752 pthread_cancel(monitor_thread);
12753 pthread_kill(monitor_thread, SIGURG);
12754 pthread_join(monitor_thread, NULL);
12755 }
12756 monitor_thread = AST_PTHREADT_STOP;
12757 ast_mutex_unlock(&monlock);
12758
12759 destroy_all_channels();
12760 #ifdef HAVE_PRI
12761 for (i = 0; i < NUM_SPANS; i++) {
12762 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12763 pthread_join(pris[i].master, NULL);
12764 for (j = 0; j < NUM_DCHANS; j++) {
12765 dahdi_close_pri_fd(&(pris[i]), j);
12766 }
12767 }
12768 #endif
12769 #ifdef HAVE_OPENR2
12770 for (r = 0; r < NUM_SPANS; r++) {
12771 if (r2links[r].protocol_context) {
12772 openr2_context_delete(r2links[r].protocol_context);
12773 }
12774 }
12775 #endif
12776 ast_cond_destroy(&ss_thread_complete);
12777 return 0;
12778 }
12779
12780 static int unload_module(void)
12781 {
12782 #ifdef HAVE_PRI
12783 int y;
12784 for (y = 0; y < NUM_SPANS; y++)
12785 ast_mutex_destroy(&pris[y].lock);
12786 #endif
12787 return __unload_module();
12788 }
12789
12790 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
12791 {
12792 char *c, *chan;
12793 int x, start, finish;
12794 struct dahdi_pvt *tmp;
12795 #ifdef HAVE_PRI
12796 struct dahdi_pri *pri;
12797 int trunkgroup, y;
12798 #endif
12799
12800 if ((reload == 0) && (conf->chan.sig < 0)) {
12801 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12802 return -1;
12803 }
12804
12805 c = ast_strdupa(value);
12806
12807 #ifdef HAVE_PRI
12808 pri = NULL;
12809 if (iscrv) {
12810 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
12811 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12812 return -1;
12813 }
12814 if (trunkgroup < 1) {
12815 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12816 return -1;
12817 }
12818 c += y;
12819 for (y = 0; y < NUM_SPANS; y++) {
12820 if (pris[y].trunkgroup == trunkgroup) {
12821 pri = pris + y;
12822 break;
12823 }
12824 }
12825 if (!pri) {
12826 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12827 return -1;
12828 }
12829 }
12830 #endif
12831
12832 while ((chan = strsep(&c, ","))) {
12833 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
12834
12835 } else if (sscanf(chan, "%30d", &start)) {
12836
12837 finish = start;
12838 } else if (!strcasecmp(chan, "pseudo")) {
12839 finish = start = CHAN_PSEUDO;
12840 if (found_pseudo)
12841 *found_pseudo = 1;
12842 } else {
12843 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12844 return -1;
12845 }
12846 if (finish < start) {
12847 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12848 x = finish;
12849 finish = start;
12850 start = x;
12851 }
12852
12853 for (x = start; x <= finish; x++) {
12854 #ifdef HAVE_PRI
12855 tmp = mkintf(x, conf, pri, reload);
12856 #else
12857 tmp = mkintf(x, conf, NULL, reload);
12858 #endif
12859
12860 if (tmp) {
12861 if (option_verbose > 2) {
12862 #ifdef HAVE_PRI
12863 if (pri)
12864 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12865 else
12866 #endif
12867 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12868 }
12869 } else {
12870 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12871 (reload == 1) ? "reconfigure" : "register", value);
12872 return -1;
12873 }
12874 }
12875 #ifdef HAVE_OPENR2
12876 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
12877 mfcr2_cur_context_index++;
12878 }
12879 #endif
12880 }
12881
12882 return 0;
12883 }
12884
12885
12886
12887 #define MAX_CHANLIST_LEN 80
12888 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
12889 {
12890 struct dahdi_pvt *tmp;
12891 int y;
12892 int found_pseudo = 0;
12893 char dahdichan[MAX_CHANLIST_LEN] = {};
12894
12895 for (; v; v = v->next) {
12896 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
12897 continue;
12898
12899
12900 if (!strcasecmp(v->name, "channel")
12901 #ifdef HAVE_PRI
12902 || !strcasecmp(v->name, "crv")
12903 #endif
12904 ) {
12905 int iscrv;
12906 if (skipchannels)
12907 continue;
12908 iscrv = !strcasecmp(v->name, "crv");
12909 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
12910 return -1;
12911 } else if (!strcasecmp(v->name, "buffers")) {
12912 int res;
12913 char policy[21] = "";
12914
12915 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
12916 if (res != 2) {
12917 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
12918 confp->chan.buf_no = numbufs;
12919 continue;
12920 }
12921 if (confp->chan.buf_no < 0)
12922 confp->chan.buf_no = numbufs;
12923 if (!strcasecmp(policy, "full")) {
12924 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
12925 } else if (!strcasecmp(policy, "immediate")) {
12926 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
12927 } else {
12928 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
12929 }
12930 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
12931 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
12932 if (v->name[0] == 'z' || v->name[0] == 'Z') {
12933 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
12934 }
12935 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
12936 if (ast_true(v->value))
12937 confp->chan.usedistinctiveringdetection = 1;
12938 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
12939 if (ast_true(v->value))
12940 distinctiveringaftercid = 1;
12941 } else if (!strcasecmp(v->name, "dring1context")) {
12942 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
12943 } else if (!strcasecmp(v->name, "dring2context")) {
12944 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
12945 } else if (!strcasecmp(v->name, "dring3context")) {
12946 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
12947 } else if (!strcasecmp(v->name, "dring1")) {
12948 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
12949 } else if (!strcasecmp(v->name, "dring2")) {
12950 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
12951 } else if (!strcasecmp(v->name, "dring3")) {
12952 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
12953 } else if (!strcasecmp(v->name, "usecallerid")) {
12954 confp->chan.use_callerid = ast_true(v->value);
12955 } else if (!strcasecmp(v->name, "cidsignalling")) {
12956 if (!strcasecmp(v->value, "bell"))
12957 confp->chan.cid_signalling = CID_SIG_BELL;
12958 else if (!strcasecmp(v->value, "v23"))
12959 confp->chan.cid_signalling = CID_SIG_V23;
12960 else if (!strcasecmp(v->value, "dtmf"))
12961 confp->chan.cid_signalling = CID_SIG_DTMF;
12962 else if (!strcasecmp(v->value, "smdi"))
12963 confp->chan.cid_signalling = CID_SIG_SMDI;
12964 else if (!strcasecmp(v->value, "v23_jp"))
12965 confp->chan.cid_signalling = CID_SIG_V23_JP;
12966 else if (ast_true(v->value))
12967 confp->chan.cid_signalling = CID_SIG_BELL;
12968 } else if (!strcasecmp(v->name, "cidstart")) {
12969 if (!strcasecmp(v->value, "ring"))
12970 confp->chan.cid_start = CID_START_RING;
12971 else if (!strcasecmp(v->value, "polarity"))
12972 confp->chan.cid_start = CID_START_POLARITY;
12973 else if (ast_true(v->value))
12974 confp->chan.cid_start = CID_START_RING;
12975 } else if (!strcasecmp(v->name, "threewaycalling")) {
12976 confp->chan.threewaycalling = ast_true(v->value);
12977 } else if (!strcasecmp(v->name, "cancallforward")) {
12978 confp->chan.cancallforward = ast_true(v->value);
12979 } else if (!strcasecmp(v->name, "relaxdtmf")) {
12980 if (ast_true(v->value))
12981 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
12982 else
12983 confp->chan.dtmfrelax = 0;
12984 } else if (!strcasecmp(v->name, "mailbox")) {
12985 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
12986 } else if (!strcasecmp(v->name, "hasvoicemail")) {
12987 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
12988 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
12989 }
12990 } else if (!strcasecmp(v->name, "adsi")) {
12991 confp->chan.adsi = ast_true(v->value);
12992 } else if (!strcasecmp(v->name, "usesmdi")) {
12993 confp->chan.use_smdi = ast_true(v->value);
12994 } else if (!strcasecmp(v->name, "smdiport")) {
12995 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
12996 } else if (!strcasecmp(v->name, "transfer")) {
12997 confp->chan.transfer = ast_true(v->value);
12998 } else if (!strcasecmp(v->name, "canpark")) {
12999 confp->chan.canpark = ast_true(v->value);
13000 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
13001 confp->chan.echocanbridged = ast_true(v->value);
13002 } else if (!strcasecmp(v->name, "busydetect")) {
13003 confp->chan.busydetect = ast_true(v->value);
13004 } else if (!strcasecmp(v->name, "busycount")) {
13005 confp->chan.busycount = atoi(v->value);
13006 } else if (!strcasecmp(v->name, "silencethreshold")) {
13007 confp->chan.silencethreshold = atoi(v->value);
13008 } else if (!strcasecmp(v->name, "busycompare")) {
13009 confp->chan.busycompare = ast_true(v->value);
13010 } else if (!strcasecmp(v->name, "busypattern")) {
13011 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
13012 if (count == 1)
13013 confp->chan.busyquietlength = 0;
13014 else if (count < 1)
13015 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
13016 } else if (!strcasecmp(v->name, "busyfuzziness")) {
13017 confp->chan.busyfuzziness = atoi(v->value);
13018 } else if (!strcasecmp(v->name, "callprogress")) {
13019 if (ast_true(v->value))
13020 confp->chan.callprogress |= 1;
13021 else
13022 confp->chan.callprogress &= ~1;
13023 } else if (!strcasecmp(v->name, "faxdetect")) {
13024 if (!strcasecmp(v->value, "incoming")) {
13025 confp->chan.callprogress |= 4;
13026 confp->chan.callprogress &= ~2;
13027 } else if (!strcasecmp(v->value, "outgoing")) {
13028 confp->chan.callprogress &= ~4;
13029 confp->chan.callprogress |= 2;
13030 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
13031 confp->chan.callprogress |= 6;
13032 else
13033 confp->chan.callprogress &= ~6;
13034 } else if (!strcasecmp(v->name, "echocancel")) {
13035 if (!ast_strlen_zero(v->value)) {
13036 y = atoi(v->value);
13037 } else
13038 y = 0;
13039 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
13040 confp->chan.echocancel = y;
13041 else {
13042 confp->chan.echocancel = ast_true(v->value);
13043 if (confp->chan.echocancel)
13044 confp->chan.echocancel=128;
13045 }
13046 } else if (!strcasecmp(v->name, "echotraining")) {
13047 if (sscanf(v->value, "%30d", &y) == 1) {
13048 if ((y < 10) || (y > 4000)) {
13049 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
13050 } else {
13051 confp->chan.echotraining = y;
13052 }
13053 } else if (ast_true(v->value)) {
13054 confp->chan.echotraining = 400;
13055 } else
13056 confp->chan.echotraining = 0;
13057 } else if (!strcasecmp(v->name, "hidecallerid")) {
13058 confp->chan.hidecallerid = ast_true(v->value);
13059 } else if (!strcasecmp(v->name, "hidecalleridname")) {
13060 confp->chan.hidecalleridname = ast_true(v->value);
13061 } else if (!strcasecmp(v->name, "pulsedial")) {
13062 confp->chan.pulse = ast_true(v->value);
13063 } else if (!strcasecmp(v->name, "callreturn")) {
13064 confp->chan.callreturn = ast_true(v->value);
13065 } else if (!strcasecmp(v->name, "callwaiting")) {
13066 confp->chan.callwaiting = ast_true(v->value);
13067 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
13068 confp->chan.callwaitingcallerid = ast_true(v->value);
13069 } else if (!strcasecmp(v->name, "context")) {
13070 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
13071 } else if (!strcasecmp(v->name, "language")) {
13072 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
13073 } else if (!strcasecmp(v->name, "progzone")) {
13074 ast_copy_string(progzone, v->value, sizeof(progzone));
13075 } else if (!strcasecmp(v->name, "mohinterpret")
13076 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
13077 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
13078 } else if (!strcasecmp(v->name, "mohsuggest")) {
13079 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
13080 } else if (!strcasecmp(v->name, "stripmsd")) {
13081 confp->chan.stripmsd = atoi(v->value);
13082 } else if (!strcasecmp(v->name, "jitterbuffers")) {
13083 numbufs = atoi(v->value);
13084 } else if (!strcasecmp(v->name, "group")) {
13085 confp->chan.group = ast_get_group(v->value);
13086 } else if (!strcasecmp(v->name, "callgroup")) {
13087 confp->chan.callgroup = ast_get_group(v->value);
13088 } else if (!strcasecmp(v->name, "pickupgroup")) {
13089 confp->chan.pickupgroup = ast_get_group(v->value);
13090 } else if (!strcasecmp(v->name, "immediate")) {
13091 confp->chan.immediate = ast_true(v->value);
13092 } else if (!strcasecmp(v->name, "transfertobusy")) {
13093 confp->chan.transfertobusy = ast_true(v->value);
13094 } else if (!strcasecmp(v->name, "rxgain")) {
13095 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
13096 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
13097 }
13098 } else if (!strcasecmp(v->name, "txgain")) {
13099 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
13100 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
13101 }
13102 } else if (!strcasecmp(v->name, "tonezone")) {
13103 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
13104 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
13105 }
13106 } else if (!strcasecmp(v->name, "callerid")) {
13107 if (!strcasecmp(v->value, "asreceived")) {
13108 confp->chan.cid_num[0] = '\0';
13109 confp->chan.cid_name[0] = '\0';
13110 } else {
13111 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
13112 }
13113 } else if (!strcasecmp(v->name, "fullname")) {
13114 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
13115 } else if (!strcasecmp(v->name, "cid_number")) {
13116 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
13117 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
13118 confp->chan.dahditrcallerid = ast_true(v->value);
13119 if (strstr(v->name, "zap")) {
13120 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
13121 }
13122 } else if (!strcasecmp(v->name, "restrictcid")) {
13123 confp->chan.restrictcid = ast_true(v->value);
13124 } else if (!strcasecmp(v->name, "usecallingpres")) {
13125 confp->chan.use_callingpres = ast_true(v->value);
13126 } else if (!strcasecmp(v->name, "accountcode")) {
13127 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
13128 } else if (!strcasecmp(v->name, "amaflags")) {
13129 y = ast_cdr_amaflags2int(v->value);
13130 if (y < 0)
13131 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
13132 else
13133 confp->chan.amaflags = y;
13134 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
13135 confp->chan.polarityonanswerdelay = atoi(v->value);
13136 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
13137 confp->chan.answeronpolarityswitch = ast_true(v->value);
13138 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
13139 confp->chan.hanguponpolarityswitch = ast_true(v->value);
13140 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
13141 confp->chan.sendcalleridafter = atoi(v->value);
13142 } else if (reload != 1) {
13143 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
13144 confp->chan.outsigmod = -1;
13145 if (!strcasecmp(v->value, "em")) {
13146 confp->chan.sig = SIG_EM;
13147 } else if (!strcasecmp(v->value, "em_e1")) {
13148 confp->chan.sig = SIG_EM_E1;
13149 } else if (!strcasecmp(v->value, "em_w")) {
13150 confp->chan.sig = SIG_EMWINK;
13151 confp->chan.radio = 0;
13152 } else if (!strcasecmp(v->value, "fxs_ls")) {
13153 confp->chan.sig = SIG_FXSLS;
13154 confp->chan.radio = 0;
13155 } else if (!strcasecmp(v->value, "fxs_gs")) {
13156 confp->chan.sig = SIG_FXSGS;
13157 confp->chan.radio = 0;
13158 } else if (!strcasecmp(v->value, "fxs_ks")) {
13159 confp->chan.sig = SIG_FXSKS;
13160 confp->chan.radio = 0;
13161 } else if (!strcasecmp(v->value, "fxo_ls")) {
13162 confp->chan.sig = SIG_FXOLS;
13163 confp->chan.radio = 0;
13164 } else if (!strcasecmp(v->value, "fxo_gs")) {
13165 confp->chan.sig = SIG_FXOGS;
13166 confp->chan.radio = 0;
13167 } else if (!strcasecmp(v->value, "fxo_ks")) {
13168 confp->chan.sig = SIG_FXOKS;
13169 confp->chan.radio = 0;
13170 } else if (!strcasecmp(v->value, "fxs_rx")) {
13171 confp->chan.sig = SIG_FXSKS;
13172 confp->chan.radio = 1;
13173 } else if (!strcasecmp(v->value, "fxo_rx")) {
13174 confp->chan.sig = SIG_FXOLS;
13175 confp->chan.radio = 1;
13176 } else if (!strcasecmp(v->value, "fxs_tx")) {
13177 confp->chan.sig = SIG_FXSLS;
13178 confp->chan.radio = 1;
13179 } else if (!strcasecmp(v->value, "fxo_tx")) {
13180 confp->chan.sig = SIG_FXOGS;
13181 confp->chan.radio = 1;
13182 } else if (!strcasecmp(v->value, "em_rx")) {
13183 confp->chan.sig = SIG_EM;
13184 confp->chan.radio = 1;
13185 } else if (!strcasecmp(v->value, "em_tx")) {
13186 confp->chan.sig = SIG_EM;
13187 confp->chan.radio = 1;
13188 } else if (!strcasecmp(v->value, "em_rxtx")) {
13189 confp->chan.sig = SIG_EM;
13190 confp->chan.radio = 2;
13191 } else if (!strcasecmp(v->value, "em_txrx")) {
13192 confp->chan.sig = SIG_EM;
13193 confp->chan.radio = 2;
13194 } else if (!strcasecmp(v->value, "sf")) {
13195 confp->chan.sig = SIG_SF;
13196 confp->chan.radio = 0;
13197 } else if (!strcasecmp(v->value, "sf_w")) {
13198 confp->chan.sig = SIG_SFWINK;
13199 confp->chan.radio = 0;
13200 } else if (!strcasecmp(v->value, "sf_featd")) {
13201 confp->chan.sig = SIG_FEATD;
13202 confp->chan.radio = 0;
13203 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13204 confp->chan.sig = SIG_FEATDMF;
13205 confp->chan.radio = 0;
13206 } else if (!strcasecmp(v->value, "sf_featb")) {
13207 confp->chan.sig = SIG_SF_FEATB;
13208 confp->chan.radio = 0;
13209 } else if (!strcasecmp(v->value, "sf")) {
13210 confp->chan.sig = SIG_SF;
13211 confp->chan.radio = 0;
13212 } else if (!strcasecmp(v->value, "sf_rx")) {
13213 confp->chan.sig = SIG_SF;
13214 confp->chan.radio = 1;
13215 } else if (!strcasecmp(v->value, "sf_tx")) {
13216 confp->chan.sig = SIG_SF;
13217 confp->chan.radio = 1;
13218 } else if (!strcasecmp(v->value, "sf_rxtx")) {
13219 confp->chan.sig = SIG_SF;
13220 confp->chan.radio = 2;
13221 } else if (!strcasecmp(v->value, "sf_txrx")) {
13222 confp->chan.sig = SIG_SF;
13223 confp->chan.radio = 2;
13224 } else if (!strcasecmp(v->value, "featd")) {
13225 confp->chan.sig = SIG_FEATD;
13226 confp->chan.radio = 0;
13227 } else if (!strcasecmp(v->value, "featdmf")) {
13228 confp->chan.sig = SIG_FEATDMF;
13229 confp->chan.radio = 0;
13230 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13231 confp->chan.sig = SIG_FEATDMF_TA;
13232 confp->chan.radio = 0;
13233 } else if (!strcasecmp(v->value, "e911")) {
13234 confp->chan.sig = SIG_E911;
13235 confp->chan.radio = 0;
13236 } else if (!strcasecmp(v->value, "fgccama")) {
13237 confp->chan.sig = SIG_FGC_CAMA;
13238 confp->chan.radio = 0;
13239 } else if (!strcasecmp(v->value, "fgccamamf")) {
13240 confp->chan.sig = SIG_FGC_CAMAMF;
13241 confp->chan.radio = 0;
13242 } else if (!strcasecmp(v->value, "featb")) {
13243 confp->chan.sig = SIG_FEATB;
13244 confp->chan.radio = 0;
13245 #ifdef HAVE_OPENR2
13246 } else if (!strcasecmp(v->value, "mfcr2")) {
13247 confp->chan.sig = SIG_MFCR2;
13248 #endif
13249 #ifdef HAVE_PRI
13250 } else if (!strcasecmp(v->value, "pri_net")) {
13251 confp->chan.radio = 0;
13252 confp->chan.sig = SIG_PRI;
13253 confp->pri.nodetype = PRI_NETWORK;
13254 } else if (!strcasecmp(v->value, "pri_cpe")) {
13255 confp->chan.sig = SIG_PRI;
13256 confp->chan.radio = 0;
13257 confp->pri.nodetype = PRI_CPE;
13258 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
13259 confp->chan.sig = SIG_GR303FXOKS;
13260 confp->chan.radio = 0;
13261 confp->pri.nodetype = PRI_NETWORK;
13262 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
13263 confp->chan.sig = SIG_GR303FXSKS;
13264 confp->chan.radio = 0;
13265 confp->pri.nodetype = PRI_CPE;
13266 #endif
13267 } else {
13268 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13269 }
13270 } else if (!strcasecmp(v->name, "outsignalling")) {
13271 if (!strcasecmp(v->value, "em")) {
13272 confp->chan.outsigmod = SIG_EM;
13273 } else if (!strcasecmp(v->value, "em_e1")) {
13274 confp->chan.outsigmod = SIG_EM_E1;
13275 } else if (!strcasecmp(v->value, "em_w")) {
13276 confp->chan.outsigmod = SIG_EMWINK;
13277 } else if (!strcasecmp(v->value, "sf")) {
13278 confp->chan.outsigmod = SIG_SF;
13279 } else if (!strcasecmp(v->value, "sf_w")) {
13280 confp->chan.outsigmod = SIG_SFWINK;
13281 } else if (!strcasecmp(v->value, "sf_featd")) {
13282 confp->chan.outsigmod = SIG_FEATD;
13283 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13284 confp->chan.outsigmod = SIG_FEATDMF;
13285 } else if (!strcasecmp(v->value, "sf_featb")) {
13286 confp->chan.outsigmod = SIG_SF_FEATB;
13287 } else if (!strcasecmp(v->value, "sf")) {
13288 confp->chan.outsigmod = SIG_SF;
13289 } else if (!strcasecmp(v->value, "featd")) {
13290 confp->chan.outsigmod = SIG_FEATD;
13291 } else if (!strcasecmp(v->value, "featdmf")) {
13292 confp->chan.outsigmod = SIG_FEATDMF;
13293 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13294 confp->chan.outsigmod = SIG_FEATDMF_TA;
13295 } else if (!strcasecmp(v->value, "e911")) {
13296 confp->chan.outsigmod = SIG_E911;
13297 } else if (!strcasecmp(v->value, "fgccama")) {
13298 confp->chan.outsigmod = SIG_FGC_CAMA;
13299 } else if (!strcasecmp(v->value, "fgccamamf")) {
13300 confp->chan.outsigmod = SIG_FGC_CAMAMF;
13301 } else if (!strcasecmp(v->value, "featb")) {
13302 confp->chan.outsigmod = SIG_FEATB;
13303 } else {
13304 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13305 }
13306 #ifdef HAVE_PRI
13307 } else if (!strcasecmp(v->name, "pridialplan")) {
13308 if (!strcasecmp(v->value, "national")) {
13309 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
13310 } else if (!strcasecmp(v->value, "unknown")) {
13311 confp->pri.dialplan = PRI_UNKNOWN + 1;
13312 } else if (!strcasecmp(v->value, "private")) {
13313 confp->pri.dialplan = PRI_PRIVATE + 1;
13314 } else if (!strcasecmp(v->value, "international")) {
13315 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
13316 } else if (!strcasecmp(v->value, "local")) {
13317 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
13318 } else if (!strcasecmp(v->value, "dynamic")) {
13319 confp->pri.dialplan = -1;
13320 } else {
13321 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13322 }
13323 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
13324 if (!strcasecmp(v->value, "national")) {
13325 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
13326 } else if (!strcasecmp(v->value, "unknown")) {
13327 confp->pri.localdialplan = PRI_UNKNOWN + 1;
13328 } else if (!strcasecmp(v->value, "private")) {
13329 confp->pri.localdialplan = PRI_PRIVATE + 1;
13330 } else if (!strcasecmp(v->value, "international")) {
13331 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
13332 } else if (!strcasecmp(v->value, "local")) {
13333 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
13334 } else if (!strcasecmp(v->value, "dynamic")) {
13335 confp->pri.localdialplan = -1;
13336 } else {
13337 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13338 }
13339 } else if (!strcasecmp(v->name, "switchtype")) {
13340 if (!strcasecmp(v->value, "national"))
13341 confp->pri.switchtype = PRI_SWITCH_NI2;
13342 else if (!strcasecmp(v->value, "ni1"))
13343 confp->pri.switchtype = PRI_SWITCH_NI1;
13344 else if (!strcasecmp(v->value, "dms100"))
13345 confp->pri.switchtype = PRI_SWITCH_DMS100;
13346 else if (!strcasecmp(v->value, "4ess"))
13347 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
13348 else if (!strcasecmp(v->value, "5ess"))
13349 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
13350 else if (!strcasecmp(v->value, "euroisdn"))
13351 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
13352 else if (!strcasecmp(v->value, "qsig"))
13353 confp->pri.switchtype = PRI_SWITCH_QSIG;
13354 else {
13355 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
13356 return -1;
13357 }
13358 } else if (!strcasecmp(v->name, "nsf")) {
13359 if (!strcasecmp(v->value, "sdn"))
13360 confp->pri.nsf = PRI_NSF_SDN;
13361 else if (!strcasecmp(v->value, "megacom"))
13362 confp->pri.nsf = PRI_NSF_MEGACOM;
13363 else if (!strcasecmp(v->value, "tollfreemegacom"))
13364 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
13365 else if (!strcasecmp(v->value, "accunet"))
13366 confp->pri.nsf = PRI_NSF_ACCUNET;
13367 else if (!strcasecmp(v->value, "none"))
13368 confp->pri.nsf = PRI_NSF_NONE;
13369 else {
13370 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
13371 confp->pri.nsf = PRI_NSF_NONE;
13372 }
13373 } else if (!strcasecmp(v->name, "priindication")) {
13374 if (!strcasecmp(v->value, "outofband"))
13375 confp->chan.priindication_oob = 1;
13376 else if (!strcasecmp(v->value, "inband"))
13377 confp->chan.priindication_oob = 0;
13378 else
13379 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
13380 v->value, v->lineno);
13381 } else if (!strcasecmp(v->name, "priexclusive")) {
13382 confp->chan.priexclusive = ast_true(v->value);
13383 } else if (!strcasecmp(v->name, "internationalprefix")) {
13384 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
13385 } else if (!strcasecmp(v->name, "nationalprefix")) {
13386 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
13387 } else if (!strcasecmp(v->name, "localprefix")) {
13388 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
13389 } else if (!strcasecmp(v->name, "privateprefix")) {
13390 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
13391 } else if (!strcasecmp(v->name, "unknownprefix")) {
13392 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
13393 } else if (!strcasecmp(v->name, "resetinterval")) {
13394 if (!strcasecmp(v->value, "never"))
13395 confp->pri.resetinterval = -1;
13396 else if (atoi(v->value) >= 60)
13397 confp->pri.resetinterval = atoi(v->value);
13398 else
13399 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
13400 v->value, v->lineno);
13401 } else if (!strcasecmp(v->name, "minunused")) {
13402 confp->pri.minunused = atoi(v->value);
13403 } else if (!strcasecmp(v->name, "minidle")) {
13404 confp->pri.minidle = atoi(v->value);
13405 } else if (!strcasecmp(v->name, "idleext")) {
13406 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
13407 } else if (!strcasecmp(v->name, "idledial")) {
13408 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
13409 } else if (!strcasecmp(v->name, "overlapdial")) {
13410 if (ast_true(v->value)) {
13411 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13412 } else if (!strcasecmp(v->value, "incoming")) {
13413 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
13414 } else if (!strcasecmp(v->value, "outgoing")) {
13415 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
13416 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
13417 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13418 } else {
13419 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
13420 }
13421 #ifdef HAVE_PRI_INBANDDISCONNECT
13422 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
13423 confp->pri.inbanddisconnect = ast_true(v->value);
13424 #endif
13425 } else if (!strcasecmp(v->name, "pritimer")) {
13426 #ifdef PRI_GETSET_TIMERS
13427 char tmp[20];
13428 char *timerc;
13429 char *c;
13430 int timer;
13431 int timeridx;
13432
13433 ast_copy_string(tmp, v->value, sizeof(tmp));
13434 c = tmp;
13435 timerc = strsep(&c, ",");
13436 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
13437 timeridx = pri_timer2idx(timerc);
13438 timer = atoi(c);
13439 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
13440 ast_log(LOG_WARNING,
13441 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
13442 v->lineno);
13443 } else if (!timer) {
13444 ast_log(LOG_WARNING,
13445 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
13446 c, timerc, v->lineno);
13447 } else {
13448 pritimers[timeridx] = timer;
13449 }
13450 } else {
13451 ast_log(LOG_WARNING,
13452 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
13453 v->value, v->lineno);
13454 }
13455 #endif
13456 } else if (!strcasecmp(v->name, "facilityenable")) {
13457 confp->pri.facilityenable = ast_true(v->value);
13458 #endif
13459 #ifdef HAVE_OPENR2
13460 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
13461 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
13462 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);
13463 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
13464 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
13465 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
13466 mfcr2_cur_variant = openr2_proto_get_variant(v->value);
13467 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
13468 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
13469 }
13470 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
13471 mfcr2_cur_mfback_timeout = atoi(v->value);
13472 if (!mfcr2_cur_mfback_timeout) {
13473 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
13474 mfcr2_cur_mfback_timeout = -1;
13475 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
13476 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
13477 }
13478 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
13479 mfcr2_cur_metering_pulse_timeout = atoi(v->value);
13480 if (mfcr2_cur_metering_pulse_timeout > 500) {
13481 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
13482 }
13483 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13484 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
13485 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
13486 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
13487 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
13488 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
13489 mfcr2_cur_dtmf_time_on = atoi(v->value);
13490 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
13491 mfcr2_cur_dtmf_time_off = atoi(v->value);
13492 #endif
13493 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
13494 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
13495 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
13496 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
13497 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
13498 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
13499 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
13500 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
13501 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
13502 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
13503 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
13504 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
13505 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
13506 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
13507 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
13508 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
13509 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
13510 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
13511 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
13512 mfcr2_cur_max_ani = atoi(v->value);
13513 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
13514 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
13515 }
13516 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
13517 mfcr2_cur_max_dnis = atoi(v->value);
13518 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
13519 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
13520 }
13521 } else if (!strcasecmp(v->name, "mfcr2_category")) {
13522 mfcr2_cur_category = openr2_proto_get_category(v->value);
13523 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
13524 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
13525 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
13526 v->value, v->lineno);
13527 }
13528 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
13529 openr2_log_level_t tmplevel;
13530 char *toklevel = NULL;
13531 char *saveptr = NULL;
13532 char *logval = ast_strdupa(v->value);
13533 toklevel = strtok_r(logval, ",", &saveptr);
13534 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13535 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
13536 } else if (OR2_LOG_NOTHING == tmplevel) {
13537 mfcr2_cur_loglevel = tmplevel;
13538 } else {
13539 mfcr2_cur_loglevel |= tmplevel;
13540 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
13541 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13542 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
13543 continue;
13544 }
13545 mfcr2_cur_loglevel |= tmplevel;
13546 }
13547 }
13548 #endif
13549
13550 } else if (!strcasecmp(v->name, "cadence")) {
13551
13552 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
13553 int i;
13554 struct dahdi_ring_cadence new_cadence;
13555 int cid_location = -1;
13556 int firstcadencepos = 0;
13557 char original_args[80];
13558 int cadence_is_ok = 1;
13559
13560 ast_copy_string(original_args, v->value, sizeof(original_args));
13561
13562 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]);
13563
13564
13565 if (element_count % 2 == 1) {
13566 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
13567 cadence_is_ok = 0;
13568 }
13569
13570
13571 for (i = 0; i < element_count; i++) {
13572 if (c[i] == 0) {
13573 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
13574 cadence_is_ok = 0;
13575 break;
13576 } else if (c[i] < 0) {
13577 if (i % 2 == 1) {
13578
13579 if (cid_location == -1) {
13580 cid_location = i;
13581 c[i] *= -1;
13582 } else {
13583 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
13584 cadence_is_ok = 0;
13585 break;
13586 }
13587 } else {
13588 if (firstcadencepos == 0) {
13589 firstcadencepos = i;
13590
13591 } else {
13592 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
13593 cadence_is_ok = 0;
13594 break;
13595 }
13596 }
13597 }
13598 }
13599
13600
13601 for (i = 0; i < 16; i++) {
13602 new_cadence.ringcadence[i] = c[i];
13603 }
13604
13605 if (cadence_is_ok) {
13606
13607 if (element_count < 2) {
13608 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
13609 } else {
13610 if (cid_location == -1) {
13611
13612 cid_location = 1;
13613 } else {
13614
13615 cid_location = (cid_location + 1) / 2;
13616 }
13617
13618 if (!user_has_defined_cadences++)
13619
13620 num_cadence = 0;
13621 if ((num_cadence+1) >= NUM_CADENCE_MAX)
13622 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
13623 else {
13624 cadences[num_cadence] = new_cadence;
13625 cidrings[num_cadence++] = cid_location;
13626 if (option_verbose > 2)
13627 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
13628 }
13629 }
13630 }
13631 } else if (!strcasecmp(v->name, "ringtimeout")) {
13632 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
13633 } else if (!strcasecmp(v->name, "prewink")) {
13634 confp->timing.prewinktime = atoi(v->value);
13635 } else if (!strcasecmp(v->name, "preflash")) {
13636 confp->timing.preflashtime = atoi(v->value);
13637 } else if (!strcasecmp(v->name, "wink")) {
13638 confp->timing.winktime = atoi(v->value);
13639 } else if (!strcasecmp(v->name, "flash")) {
13640 confp->timing.flashtime = atoi(v->value);
13641 } else if (!strcasecmp(v->name, "start")) {
13642 confp->timing.starttime = atoi(v->value);
13643 } else if (!strcasecmp(v->name, "rxwink")) {
13644 confp->timing.rxwinktime = atoi(v->value);
13645 } else if (!strcasecmp(v->name, "rxflash")) {
13646 confp->timing.rxflashtime = atoi(v->value);
13647 } else if (!strcasecmp(v->name, "debounce")) {
13648 confp->timing.debouncetime = atoi(v->value);
13649 } else if (!strcasecmp(v->name, "toneduration")) {
13650 int toneduration;
13651 int ctlfd;
13652 int res;
13653 struct dahdi_dialparams dps;
13654
13655 ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
13656
13657 if (ctlfd == -1) {
13658 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
13659 return -1;
13660 }
13661
13662 toneduration = atoi(v->value);
13663 if (toneduration > -1) {
13664 memset(&dps, 0, sizeof(dps));
13665
13666 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
13667 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
13668 if (res < 0) {
13669 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
13670 return -1;
13671 }
13672 }
13673 close(ctlfd);
13674 } else if (!strcasecmp(v->name, "defaultcic")) {
13675 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
13676 } else if (!strcasecmp(v->name, "defaultozz")) {
13677 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
13678 }
13679 } else if (!skipchannels)
13680 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
13681 }
13682 if (dahdichan[0]) {
13683
13684
13685 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
13686 return -1;
13687 }
13688 }
13689
13690
13691 if (!found_pseudo && reload != 1) {
13692
13693
13694
13695
13696 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13697
13698 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
13699
13700 if (tmp) {
13701 if (option_verbose > 2)
13702 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
13703 } else {
13704 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
13705 }
13706 }
13707 return 0;
13708 }
13709
13710 static int setup_dahdi(int reload)
13711 {
13712 struct ast_config *cfg;
13713 struct ast_variable *v;
13714 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13715 int res;
13716
13717 #ifdef HAVE_PRI
13718 char *c;
13719 int spanno;
13720 int i, x;
13721 int logicalspan;
13722 int trunkgroup;
13723 int dchannels[NUM_DCHANS];
13724 #endif
13725
13726 #ifdef HAVE_ZAPTEL
13727 int load_from_zapata_conf = 1;
13728 #else
13729 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
13730 #endif
13731
13732 if (load_from_zapata_conf) {
13733 if (!(cfg = ast_config_load("zapata.conf"))) {
13734 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13735 return 0;
13736 }
13737 } else {
13738 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13739 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13740 return 0;
13741 }
13742 }
13743
13744
13745 ast_mutex_lock(&iflock);
13746 #ifdef HAVE_PRI
13747 if (reload != 1) {
13748
13749 v = ast_variable_browse(cfg, "trunkgroups");
13750 while (v) {
13751 if (!strcasecmp(v->name, "trunkgroup")) {
13752 trunkgroup = atoi(v->value);
13753 if (trunkgroup > 0) {
13754 if ((c = strchr(v->value, ','))) {
13755 i = 0;
13756 memset(dchannels, 0, sizeof(dchannels));
13757 while (c && (i < NUM_DCHANS)) {
13758 dchannels[i] = atoi(c + 1);
13759 if (dchannels[i] < 0) {
13760 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);
13761 } else
13762 i++;
13763 c = strchr(c + 1, ',');
13764 }
13765 if (i) {
13766 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13767 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);
13768 } else if (option_verbose > 1)
13769 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");
13770 } else
13771 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13772 } else
13773 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13774 } else
13775 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13776 } else if (!strcasecmp(v->name, "spanmap")) {
13777 spanno = atoi(v->value);
13778 if (spanno > 0) {
13779 if ((c = strchr(v->value, ','))) {
13780 trunkgroup = atoi(c + 1);
13781 if (trunkgroup > 0) {
13782 if ((c = strchr(c + 1, ',')))
13783 logicalspan = atoi(c + 1);
13784 else
13785 logicalspan = 0;
13786 if (logicalspan >= 0) {
13787 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13788 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13789 } else if (option_verbose > 1)
13790 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13791 } else
13792 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);
13793 } else
13794 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13795 } else
13796 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13797 } else
13798 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13799 } else {
13800 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13801 }
13802 v = v->next;
13803 }
13804 }
13805 #endif
13806
13807
13808 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13809
13810 v = ast_variable_browse(cfg, "channels");
13811 res = process_dahdi(&conf, "", v, reload, 0);
13812 ast_mutex_unlock(&iflock);
13813 ast_config_destroy(cfg);
13814 if (res)
13815 return res;
13816 cfg = ast_config_load("users.conf");
13817 if (cfg) {
13818 char *cat;
13819 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13820 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13821 if (!strcasecmp(cat, "general"))
13822 continue;
13823 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
13824 struct dahdi_chan_conf sect_conf;
13825 memcpy(§_conf, &conf, sizeof(sect_conf));
13826
13827 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13828 }
13829 }
13830 ast_config_destroy(cfg);
13831 }
13832 #ifdef HAVE_PRI
13833 if (reload != 1) {
13834 for (x = 0; x < NUM_SPANS; x++) {
13835 if (pris[x].pvts[0]) {
13836 if (start_pri(pris + x)) {
13837 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13838 return -1;
13839 } else if (option_verbose > 1)
13840 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13841 }
13842 }
13843 }
13844 #endif
13845 #ifdef HAVE_OPENR2
13846 if (reload != 1) {
13847 int x;
13848 for (x = 0; x < NUM_SPANS; x++) {
13849 if (r2links[x].protocol_context) {
13850 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
13851 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
13852 return -1;
13853 } else {
13854 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
13855 }
13856 }
13857 }
13858 }
13859 #endif
13860
13861 restart_monitor();
13862 return 0;
13863 }
13864
13865 #define local_astman_register(a, b, c, d) do { \
13866 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13867 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
13868 } \
13869 ast_manager_register("Zap" a, b, zap_ ## c, d); \
13870 } while (0)
13871
13872 static int load_module(void)
13873 {
13874 int res;
13875
13876 #ifdef HAVE_PRI
13877 int y,i;
13878 memset(pris, 0, sizeof(pris));
13879 for (y = 0; y < NUM_SPANS; y++) {
13880 ast_mutex_init(&pris[y].lock);
13881 pris[y].offset = -1;
13882 pris[y].master = AST_PTHREADT_NULL;
13883 for (i = 0; i < NUM_DCHANS; i++)
13884 pris[y].fds[i] = -1;
13885 }
13886 pri_set_error(dahdi_pri_error);
13887 pri_set_message(dahdi_pri_message);
13888 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13889 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13890 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13891 }
13892 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13893 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13894 #endif
13895 #ifdef HAVE_OPENR2
13896 init_mfcr2_globals();
13897 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13898 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
13899 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
13900 }
13901 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
13902 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
13903 #endif
13904 if ((res = setup_dahdi(0))) {
13905 return AST_MODULE_LOAD_DECLINE;
13906 }
13907 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13908 chan_tech = &dahdi_tech;
13909 } else {
13910 chan_tech = &zap_tech;
13911 }
13912 if (ast_channel_register(chan_tech)) {
13913 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
13914 __unload_module();
13915 return -1;
13916 }
13917 #ifdef HAVE_PRI
13918 ast_string_field_init(&inuse, 16);
13919 ast_string_field_set(&inuse, name, "GR-303InUse");
13920 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13921 #endif
13922 #ifdef HAVE_OPENR2
13923 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
13924 #endif
13925 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13926
13927 memset(round_robin, 0, sizeof(round_robin));
13928 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
13929 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
13930 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
13931 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
13932 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
13933 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
13934 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
13935
13936 ast_cond_init(&ss_thread_complete, NULL);
13937
13938 return res;
13939 }
13940
13941 static int dahdi_sendtext(struct ast_channel *c, const char *text)
13942 {
13943 #define END_SILENCE_LEN 400
13944 #define HEADER_MS 50
13945 #define TRAILER_MS 5
13946 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
13947 #define ASCII_BYTES_PER_CHAR 80
13948
13949 unsigned char *buf,*mybuf;
13950 struct dahdi_pvt *p = c->tech_pvt;
13951 struct pollfd fds[1];
13952 int size,res,fd,len,x;
13953 int bytes=0;
13954
13955 float cr = 1.0;
13956 float ci = 0.0;
13957 float scont = 0.0;
13958 int index;
13959
13960 index = dahdi_get_index(c, p, 0);
13961 if (index < 0) {
13962 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
13963 return -1;
13964 }
13965 if (!text[0]) return(0);
13966 if ((!p->tdd) && (!p->mate)) return(0);
13967 if (p->mate)
13968 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
13969 else
13970 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
13971 if (!buf)
13972 return -1;
13973 mybuf = buf;
13974 if (p->mate) {
13975 int codec = AST_LAW(p);
13976 for (x = 0; x < HEADER_MS; x++) {
13977 PUT_CLID_MARKMS;
13978 }
13979
13980 for (x = 0; text[x]; x++) {
13981 PUT_CLID(text[x]);
13982 }
13983 for (x = 0; x < TRAILER_MS; x++) {
13984 PUT_CLID_MARKMS;
13985 }
13986 len = bytes;
13987 buf = mybuf;
13988 } else {
13989 len = tdd_generate(p->tdd, buf, text);
13990 if (len < 1) {
13991 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
13992 free(mybuf);
13993 return -1;
13994 }
13995 }
13996 memset(buf + len, 0x7f, END_SILENCE_LEN);
13997 len += END_SILENCE_LEN;
13998 fd = p->subs[index].dfd;
13999 while (len) {
14000 if (ast_check_hangup(c)) {
14001 free(mybuf);
14002 return -1;
14003 }
14004 size = len;
14005 if (size > READ_SIZE)
14006 size = READ_SIZE;
14007 fds[0].fd = fd;
14008 fds[0].events = POLLOUT | POLLPRI;
14009 fds[0].revents = 0;
14010 res = poll(fds, 1, -1);
14011 if (!res) {
14012 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
14013 continue;
14014 }
14015
14016 if (fds[0].revents & POLLPRI) {
14017 ast_free(mybuf);
14018 return -1;
14019 }
14020 if (!(fds[0].revents & POLLOUT)) {
14021 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
14022 continue;
14023 }
14024 res = write(fd, buf, size);
14025 if (res != size) {
14026 if (res == -1) {
14027 free(mybuf);
14028 return -1;
14029 }
14030 if (option_debug)
14031 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14032 break;
14033 }
14034 len -= size;
14035 buf += size;
14036 }
14037 free(mybuf);
14038 return(0);
14039 }
14040
14041
14042 static int reload(void)
14043 {
14044 int res = 0;
14045
14046 res = setup_dahdi(1);
14047 if (res) {
14048 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14049 return -1;
14050 }
14051 return 0;
14052 }
14053
14054
14055
14056
14057
14058 #ifdef HAVE_PRI
14059 #define tdesc "DAHDI Telephony w/PRI"
14060 #else
14061 #define tdesc "DAHDI Telephony"
14062 #endif
14063
14064 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
14065 .load = load_module,
14066 .unload = unload_module,
14067 .reload = reload,
14068 );
14069
14070