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 #include "asterisk.h"
00049
00050 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 188940 $")
00051
00052 #ifdef __NetBSD__
00053 #include <pthread.h>
00054 #include <signal.h>
00055 #else
00056 #include <sys/signal.h>
00057 #endif
00058 #include <sys/ioctl.h>
00059 #include <math.h>
00060 #include <ctype.h>
00061
00062 #include <dahdi/user.h>
00063 #include <dahdi/tonezone.h>
00064
00065 #ifdef HAVE_PRI
00066 #include <libpri.h>
00067 #endif
00068
00069 #ifdef HAVE_SS7
00070 #include <libss7.h>
00071 #endif
00072
00073 #include "asterisk/lock.h"
00074 #include "asterisk/channel.h"
00075 #include "asterisk/config.h"
00076 #include "asterisk/module.h"
00077 #include "asterisk/pbx.h"
00078 #include "asterisk/file.h"
00079 #include "asterisk/ulaw.h"
00080 #include "asterisk/alaw.h"
00081 #include "asterisk/callerid.h"
00082 #include "asterisk/adsi.h"
00083 #include "asterisk/cli.h"
00084 #include "asterisk/cdr.h"
00085 #include "asterisk/features.h"
00086 #include "asterisk/musiconhold.h"
00087 #include "asterisk/say.h"
00088 #include "asterisk/tdd.h"
00089 #include "asterisk/app.h"
00090 #include "asterisk/dsp.h"
00091 #include "asterisk/astdb.h"
00092 #include "asterisk/manager.h"
00093 #include "asterisk/causes.h"
00094 #include "asterisk/term.h"
00095 #include "asterisk/utils.h"
00096 #include "asterisk/transcap.h"
00097 #include "asterisk/stringfields.h"
00098 #include "asterisk/abstract_jb.h"
00099 #include "asterisk/smdi.h"
00100 #include "asterisk/astobj.h"
00101 #include "asterisk/event.h"
00102 #include "asterisk/devicestate.h"
00103
00104 #define SMDI_MD_WAIT_TIMEOUT 1500
00105
00106 static const char *lbostr[] = {
00107 "0 db (CSU)/0-133 feet (DSX-1)",
00108 "133-266 feet (DSX-1)",
00109 "266-399 feet (DSX-1)",
00110 "399-533 feet (DSX-1)",
00111 "533-655 feet (DSX-1)",
00112 "-7.5db (CSU)",
00113 "-15db (CSU)",
00114 "-22.5db (CSU)"
00115 };
00116
00117
00118 static struct ast_jb_conf default_jbconf =
00119 {
00120 .flags = 0,
00121 .max_size = -1,
00122 .resync_threshold = -1,
00123 .impl = ""
00124 };
00125 static struct ast_jb_conf global_jbconf;
00126
00127
00128 #undef SUPPORT_USERUSER
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 #define DEFAULT_CIDRINGS 1
00150
00151 #define CHANNEL_PSEUDO -12
00152
00153 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00154
00155
00156
00157 #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))
00158
00159 static const char tdesc[] = "DAHDI Telephony Driver"
00160 #ifdef HAVE_PRI
00161 " w/PRI"
00162 #endif
00163 #ifdef HAVE_SS7
00164 " w/SS7"
00165 #endif
00166 ;
00167
00168 static const char config[] = "chan_dahdi.conf";
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_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00187 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00188 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00189 #define SIG_SF DAHDI_SIG_SF
00190 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00191 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00192 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00193 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00194 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00195 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00196 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00197
00198 #ifdef LOTS_OF_SPANS
00199 #define NUM_SPANS DAHDI_MAX_SPANS
00200 #else
00201 #define NUM_SPANS 32
00202 #endif
00203 #define NUM_DCHANS 4
00204 #define MAX_CHANNELS 672
00205
00206 #define CHAN_PSEUDO -2
00207
00208 #define DCHAN_PROVISIONED (1 << 0)
00209 #define DCHAN_NOTINALARM (1 << 1)
00210 #define DCHAN_UP (1 << 2)
00211
00212 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00213
00214
00215 #define DAHDI_OVERLAPDIAL_NONE 0
00216 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00217 #define DAHDI_OVERLAPDIAL_INCOMING 2
00218 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00219
00220
00221 #define CALLPROGRESS_PROGRESS 1
00222 #define CALLPROGRESS_FAX_OUTGOING 2
00223 #define CALLPROGRESS_FAX_INCOMING 4
00224 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00225
00226 static char defaultcic[64] = "";
00227 static char defaultozz[64] = "";
00228
00229 static char parkinglot[AST_MAX_EXTENSION] = "";
00230
00231
00232 static char mwimonitornotify[PATH_MAX] = "";
00233 static int mwisend_rpas = 0;
00234
00235 static char progzone[10] = "";
00236
00237 static int usedistinctiveringdetection = 0;
00238 static int distinctiveringaftercid = 0;
00239
00240 static int numbufs = 4;
00241
00242 static int mwilevel = 512;
00243
00244 #ifdef HAVE_PRI
00245 static struct ast_channel inuse;
00246 #ifdef PRI_GETSET_TIMERS
00247 static int pritimers[PRI_MAX_TIMERS];
00248 #endif
00249 static int pridebugfd = -1;
00250 static char pridebugfilename[1024] = "";
00251 #endif
00252
00253
00254 static int firstdigittimeout = 16000;
00255
00256
00257 static int gendigittimeout = 8000;
00258
00259
00260 static int matchdigittimeout = 3000;
00261
00262
00263 AST_MUTEX_DEFINE_STATIC(iflock);
00264
00265
00266 static int ifcount = 0;
00267
00268 #ifdef HAVE_PRI
00269 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00270 #endif
00271
00272
00273
00274 AST_MUTEX_DEFINE_STATIC(monlock);
00275
00276
00277
00278 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00279 static ast_cond_t mwi_thread_complete;
00280 static ast_cond_t ss_thread_complete;
00281 AST_MUTEX_DEFINE_STATIC(mwi_thread_lock);
00282 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00283 AST_MUTEX_DEFINE_STATIC(restart_lock);
00284 static int mwi_thread_count = 0;
00285 static int ss_thread_count = 0;
00286 static int num_restart_pending = 0;
00287
00288 static int restart_monitor(void);
00289
00290 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);
00291
00292 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00293
00294 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00295 {
00296
00297
00298
00299
00300 }
00301
00302
00303 static inline int dahdi_get_event(int fd)
00304 {
00305 int j;
00306 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00307 return -1;
00308 return j;
00309 }
00310
00311
00312 static inline int dahdi_wait_event(int fd)
00313 {
00314 int i, j = 0;
00315 i = DAHDI_IOMUX_SIGEVENT;
00316 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00317 return -1;
00318 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00319 return -1;
00320 return j;
00321 }
00322
00323
00324 #define READ_SIZE 160
00325
00326 #define MASK_AVAIL (1 << 0)
00327 #define MASK_INUSE (1 << 1)
00328
00329 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00330 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00331 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00332 #define MIN_MS_SINCE_FLASH ( (2000) )
00333 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00334
00335 struct dahdi_pvt;
00336
00337
00338
00339
00340
00341 static int ringt_base = DEFAULT_RINGT;
00342
00343 #ifdef HAVE_SS7
00344
00345 #define LINKSTATE_INALARM (1 << 0)
00346 #define LINKSTATE_STARTING (1 << 1)
00347 #define LINKSTATE_UP (1 << 2)
00348 #define LINKSTATE_DOWN (1 << 3)
00349
00350 #define SS7_NAI_DYNAMIC -1
00351
00352 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00353
00354 struct dahdi_ss7 {
00355 pthread_t master;
00356 ast_mutex_t lock;
00357 int fds[NUM_DCHANS];
00358 int numsigchans;
00359 int linkstate[NUM_DCHANS];
00360 int numchans;
00361 int type;
00362 enum {
00363 LINKSET_STATE_DOWN = 0,
00364 LINKSET_STATE_UP
00365 } state;
00366 char called_nai;
00367 char calling_nai;
00368 char internationalprefix[10];
00369 char nationalprefix[10];
00370 char subscriberprefix[20];
00371 char unknownprefix[20];
00372 struct ss7 *ss7;
00373 struct dahdi_pvt *pvts[MAX_CHANNELS];
00374 int flags;
00375 };
00376
00377 static struct dahdi_ss7 linksets[NUM_SPANS];
00378
00379 static int cur_ss7type = -1;
00380 static int cur_linkset = -1;
00381 static int cur_pointcode = -1;
00382 static int cur_cicbeginswith = -1;
00383 static int cur_adjpointcode = -1;
00384 static int cur_networkindicator = -1;
00385 static int cur_defaultdpc = -1;
00386 #endif
00387
00388 #ifdef HAVE_PRI
00389
00390 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00391 #define PRI_CHANNEL(p) ((p) & 0xff)
00392 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00393 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00394
00395 struct dahdi_pri {
00396 pthread_t master;
00397 ast_mutex_t lock;
00398 char idleext[AST_MAX_EXTENSION];
00399 char idlecontext[AST_MAX_CONTEXT];
00400 char idledial[AST_MAX_EXTENSION];
00401 int minunused;
00402 int minidle;
00403 int nodetype;
00404 int switchtype;
00405 int nsf;
00406 int dialplan;
00407 int localdialplan;
00408 char internationalprefix[10];
00409 char nationalprefix[10];
00410 char localprefix[20];
00411 char privateprefix[20];
00412 char unknownprefix[20];
00413 int dchannels[NUM_DCHANS];
00414 int trunkgroup;
00415 int mastertrunkgroup;
00416 int prilogicalspan;
00417 int numchans;
00418 int overlapdial;
00419 int facilityenable;
00420 struct pri *dchans[NUM_DCHANS];
00421 int dchanavail[NUM_DCHANS];
00422 struct pri *pri;
00423
00424 int debug;
00425 int fds[NUM_DCHANS];
00426
00427 int offset;
00428
00429 int span;
00430
00431 int resetting;
00432
00433 int resetpos;
00434 #ifdef HAVE_PRI_INBANDDISCONNECT
00435 unsigned int inbanddisconnect:1;
00436 #endif
00437 time_t lastreset;
00438 long resetinterval;
00439
00440 int sig;
00441 struct dahdi_pvt *pvts[MAX_CHANNELS];
00442 struct dahdi_pvt *crvs;
00443 struct dahdi_pvt *crvend;
00444 };
00445
00446
00447 static struct dahdi_pri pris[NUM_SPANS];
00448
00449 #if 0
00450 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00451 #else
00452 #define DEFAULT_PRI_DEBUG 0
00453 #endif
00454
00455 static inline void pri_rel(struct dahdi_pri *pri)
00456 {
00457 ast_mutex_unlock(&pri->lock);
00458 }
00459
00460 #else
00461
00462 struct dahdi_pri;
00463 #endif
00464
00465 #define SUB_REAL 0
00466 #define SUB_CALLWAIT 1
00467 #define SUB_THREEWAY 2
00468
00469
00470 #define POLARITY_IDLE 0
00471 #define POLARITY_REV 1
00472
00473
00474 struct distRingData {
00475 int ring[3];
00476 int range;
00477 };
00478 struct ringContextData {
00479 char contextData[AST_MAX_CONTEXT];
00480 };
00481 struct dahdi_distRings {
00482 struct distRingData ringnum[3];
00483 struct ringContextData ringContext[3];
00484 };
00485
00486 static char *subnames[] = {
00487 "Real",
00488 "Callwait",
00489 "Threeway"
00490 };
00491
00492 struct dahdi_subchannel {
00493 int dfd;
00494 struct ast_channel *owner;
00495 int chan;
00496 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00497 struct ast_frame f;
00498 unsigned int needringing:1;
00499 unsigned int needbusy:1;
00500 unsigned int needcongestion:1;
00501 unsigned int needcallerid:1;
00502 unsigned int needanswer:1;
00503 unsigned int needflash:1;
00504 unsigned int needhold:1;
00505 unsigned int needunhold:1;
00506 unsigned int linear:1;
00507 unsigned int inthreeway:1;
00508 struct dahdi_confinfo curconf;
00509 };
00510
00511 #define CONF_USER_REAL (1 << 0)
00512 #define CONF_USER_THIRDCALL (1 << 1)
00513
00514 #define MAX_SLAVES 4
00515
00516 static struct dahdi_pvt {
00517 ast_mutex_t lock;
00518 struct ast_channel *owner;
00519
00520
00521 struct dahdi_subchannel sub_unused;
00522 struct dahdi_subchannel subs[3];
00523 struct dahdi_confinfo saveconf;
00524
00525 struct dahdi_pvt *slaves[MAX_SLAVES];
00526 struct dahdi_pvt *master;
00527 int inconference;
00528
00529 int buf_no;
00530 int buf_policy;
00531 int sig;
00532
00533
00534
00535
00536 int radio;
00537 int outsigmod;
00538 int oprmode;
00539 struct dahdi_pvt *oprpeer;
00540
00541 float cid_rxgain;
00542
00543 float rxgain;
00544
00545 float txgain;
00546 int tonezone;
00547 struct dahdi_pvt *next;
00548 struct dahdi_pvt *prev;
00549
00550
00551
00552
00553
00554
00555
00556 unsigned int adsi:1;
00557
00558
00559
00560
00561
00562 unsigned int answeronpolarityswitch:1;
00563
00564
00565
00566
00567
00568 unsigned int busydetect:1;
00569
00570
00571
00572
00573
00574 unsigned int callreturn:1;
00575
00576
00577
00578
00579
00580
00581 unsigned int callwaiting:1;
00582
00583
00584
00585
00586 unsigned int callwaitingcallerid:1;
00587
00588
00589
00590
00591
00592
00593 unsigned int cancallforward:1;
00594
00595
00596
00597
00598 unsigned int canpark:1;
00599
00600 unsigned int confirmanswer:1;
00601
00602
00603
00604
00605 unsigned int destroy:1;
00606 unsigned int didtdd:1;
00607
00608 unsigned int dialednone:1;
00609
00610 unsigned int dialing:1;
00611
00612 unsigned int digital:1;
00613
00614 unsigned int dnd:1;
00615
00616 unsigned int echobreak:1;
00617
00618
00619
00620
00621
00622 unsigned int echocanbridged:1;
00623
00624 unsigned int echocanon:1;
00625
00626 unsigned int faxhandled:1;
00627
00628 unsigned int firstradio:1;
00629
00630
00631
00632
00633 unsigned int hanguponpolarityswitch:1;
00634
00635 unsigned int hardwaredtmf:1;
00636
00637
00638
00639
00640
00641
00642 unsigned int hidecallerid:1;
00643
00644
00645
00646
00647
00648 unsigned int hidecalleridname:1;
00649
00650 unsigned int ignoredtmf:1;
00651
00652
00653
00654
00655
00656 unsigned int immediate:1;
00657
00658 unsigned int inalarm:1;
00659
00660 unsigned int mate:1;
00661
00662 unsigned int outgoing:1;
00663
00664
00665
00666
00667
00668
00669 unsigned int permcallwaiting:1;
00670
00671
00672
00673
00674 unsigned int permhidecallerid:1;
00675
00676
00677
00678
00679 unsigned int priindication_oob:1;
00680
00681
00682
00683
00684 unsigned int priexclusive:1;
00685
00686
00687
00688
00689 unsigned int pulse:1;
00690
00691 unsigned int pulsedial:1;
00692 unsigned int restartpending:1;
00693
00694
00695
00696
00697
00698 unsigned int restrictcid:1;
00699
00700
00701
00702
00703 unsigned int threewaycalling:1;
00704
00705
00706
00707
00708
00709
00710
00711
00712 unsigned int transfer:1;
00713
00714
00715
00716
00717
00718
00719
00720 unsigned int use_callerid:1;
00721
00722
00723
00724
00725
00726
00727 unsigned int use_callingpres:1;
00728
00729
00730
00731
00732
00733 unsigned int usedistinctiveringdetection:1;
00734
00735
00736
00737
00738 unsigned int dahditrcallerid:1;
00739
00740
00741
00742
00743 unsigned int transfertobusy:1;
00744
00745
00746
00747
00748 unsigned int mwimonitor_neon:1;
00749
00750
00751
00752
00753 unsigned int mwimonitor_fsk:1;
00754
00755
00756
00757
00758
00759 unsigned int mwimonitor_rpas:1;
00760
00761 unsigned int mwimonitoractive:1;
00762
00763 unsigned int mwisendactive:1;
00764
00765
00766
00767
00768 unsigned int inservice:1;
00769
00770
00771
00772
00773 unsigned int locallyblocked:1;
00774
00775
00776
00777
00778 unsigned int remotelyblocked:1;
00779 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00780
00781
00782
00783
00784 unsigned int rlt:1;
00785
00786 unsigned int alerting:1;
00787
00788 unsigned int alreadyhungup:1;
00789
00790
00791
00792
00793 unsigned int isidlecall:1;
00794
00795
00796
00797
00798 unsigned int proceeding:1;
00799
00800 unsigned int progress:1;
00801
00802
00803
00804
00805 unsigned int resetting:1;
00806
00807
00808
00809
00810 unsigned int setup_ack:1;
00811 #endif
00812
00813
00814
00815
00816 unsigned int use_smdi:1;
00817
00818 struct ast_smdi_interface *smdi_iface;
00819
00820
00821 struct dahdi_distRings drings;
00822
00823
00824
00825
00826
00827 char context[AST_MAX_CONTEXT];
00828
00829
00830
00831 char defcontext[AST_MAX_CONTEXT];
00832
00833 char exten[AST_MAX_EXTENSION];
00834
00835
00836
00837
00838 char language[MAX_LANGUAGE];
00839
00840
00841
00842
00843 char mohinterpret[MAX_MUSICCLASS];
00844
00845
00846
00847
00848 char mohsuggest[MAX_MUSICCLASS];
00849 char parkinglot[AST_MAX_EXTENSION];
00850 #if defined(PRI_ANI) || defined(HAVE_SS7)
00851
00852 char cid_ani[AST_MAX_EXTENSION];
00853 #endif
00854
00855 int cid_ani2;
00856
00857 char cid_num[AST_MAX_EXTENSION];
00858
00859 int cid_ton;
00860
00861 char cid_name[AST_MAX_EXTENSION];
00862
00863 char lastcid_num[AST_MAX_EXTENSION];
00864
00865 char lastcid_name[AST_MAX_EXTENSION];
00866 char *origcid_num;
00867 char *origcid_name;
00868
00869 char callwait_num[AST_MAX_EXTENSION];
00870
00871 char callwait_name[AST_MAX_EXTENSION];
00872
00873 char rdnis[AST_MAX_EXTENSION];
00874
00875 char dnid[AST_MAX_EXTENSION];
00876
00877
00878
00879
00880 ast_group_t group;
00881
00882 int law;
00883 int confno;
00884 int confusers;
00885 int propconfno;
00886
00887
00888
00889
00890 ast_group_t callgroup;
00891
00892
00893
00894
00895 ast_group_t pickupgroup;
00896
00897
00898
00899
00900 struct ast_variable *vars;
00901 int channel;
00902 int span;
00903 time_t guardtime;
00904 int cid_signalling;
00905 int cid_start;
00906 int callingpres;
00907 int callwaitingrepeat;
00908 int cidcwexpire;
00909
00910 unsigned char *cidspill;
00911
00912 int cidpos;
00913
00914 int cidlen;
00915
00916 int ringt;
00917
00918
00919
00920
00921 int ringt_base;
00922
00923
00924
00925
00926
00927
00928 int stripmsd;
00929
00930 int callwaitcas;
00931
00932 int callwaitrings;
00933
00934 struct {
00935 struct dahdi_echocanparams head;
00936 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
00937 } echocancel;
00938
00939
00940
00941
00942 int echotraining;
00943
00944 char echorest[20];
00945
00946
00947
00948
00949 int busycount;
00950
00951
00952
00953
00954 int busycompare;
00955
00956
00957
00958
00959 int busytonelength;
00960
00961
00962
00963
00964 int busyquietlength;
00965
00966
00967
00968
00969 int busyfuzziness;
00970
00971
00972
00973
00974 int silencethreshold;
00975
00976
00977
00978
00979 int callprogress;
00980 struct timeval flashtime;
00981
00982 struct ast_dsp *dsp;
00983
00984
00985 struct dahdi_dialoperation dop;
00986 int whichwink;
00987
00988 char finaldial[64];
00989 char accountcode[AST_MAX_ACCOUNT_CODE];
00990 int amaflags;
00991 struct tdd_state *tdd;
00992
00993 char call_forward[AST_MAX_EXTENSION];
00994
00995
00996
00997
00998 char mailbox[AST_MAX_EXTENSION];
00999
01000 struct ast_event_sub *mwi_event_sub;
01001
01002 char dialdest[256];
01003
01004 int onhooktime;
01005
01006 int msgstate;
01007 int distinctivering;
01008 int cidrings;
01009 int dtmfrelax;
01010
01011 int fake_event;
01012
01013
01014
01015
01016 int polarityonanswerdelay;
01017
01018 struct timeval polaritydelaytv;
01019
01020
01021
01022
01023 int sendcalleridafter;
01024 #ifdef HAVE_PRI
01025
01026 struct dahdi_pri *pri;
01027
01028 struct dahdi_pvt *bearer;
01029
01030 struct dahdi_pvt *realcall;
01031
01032 q931_call *call;
01033
01034 int prioffset;
01035
01036 int logicalspan;
01037 #endif
01038
01039 int polarity;
01040
01041 int dsp_features;
01042 #ifdef HAVE_SS7
01043
01044 struct dahdi_ss7 *ss7;
01045
01046 struct isup_call *ss7call;
01047 char charge_number[50];
01048 char gen_add_number[50];
01049 char gen_dig_number[50];
01050 char orig_called_num[50];
01051 char redirecting_num[50];
01052 char generic_name[50];
01053 unsigned char gen_add_num_plan;
01054 unsigned char gen_add_nai;
01055 unsigned char gen_add_pres_ind;
01056 unsigned char gen_add_type;
01057 unsigned char gen_dig_type;
01058 unsigned char gen_dig_scheme;
01059 char jip_number[50];
01060 unsigned char lspi_type;
01061 unsigned char lspi_scheme;
01062 unsigned char lspi_context;
01063 char lspi_ident[50];
01064 unsigned int call_ref_ident;
01065 unsigned int call_ref_pc;
01066 unsigned char calling_party_cat;
01067 int transcap;
01068 int cic;
01069 unsigned int dpc;
01070 unsigned int loopedback:1;
01071 #endif
01072
01073 char begindigit;
01074
01075 int muting;
01076 } *iflist = NULL, *ifend = NULL;
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088 struct dahdi_chan_conf {
01089 struct dahdi_pvt chan;
01090 #ifdef HAVE_PRI
01091 struct dahdi_pri pri;
01092 #endif
01093
01094 #ifdef HAVE_SS7
01095 struct dahdi_ss7 ss7;
01096 #endif
01097 struct dahdi_params timing;
01098 int is_sig_auto;
01099
01100
01101
01102
01103
01104 char smdi_port[SMDI_MAX_FILENAME_LEN];
01105 };
01106
01107
01108 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01109
01110
01111
01112 struct dahdi_chan_conf conf = {
01113 #ifdef HAVE_PRI
01114 .pri = {
01115 .nsf = PRI_NSF_NONE,
01116 .switchtype = PRI_SWITCH_NI2,
01117 .dialplan = PRI_UNKNOWN + 1,
01118 .localdialplan = PRI_NATIONAL_ISDN + 1,
01119 .nodetype = PRI_CPE,
01120
01121 .minunused = 2,
01122 .idleext = "",
01123 .idledial = "",
01124 .internationalprefix = "",
01125 .nationalprefix = "",
01126 .localprefix = "",
01127 .privateprefix = "",
01128 .unknownprefix = "",
01129 .resetinterval = -1,
01130 },
01131 #endif
01132 #ifdef HAVE_SS7
01133 .ss7 = {
01134 .called_nai = SS7_NAI_NATIONAL,
01135 .calling_nai = SS7_NAI_NATIONAL,
01136 .internationalprefix = "",
01137 .nationalprefix = "",
01138 .subscriberprefix = "",
01139 .unknownprefix = ""
01140 },
01141 #endif
01142 .chan = {
01143 .context = "default",
01144 .cid_num = "",
01145 .cid_name = "",
01146 .mohinterpret = "default",
01147 .mohsuggest = "",
01148 .parkinglot = "",
01149 .transfertobusy = 1,
01150
01151 .cid_signalling = CID_SIG_BELL,
01152 .cid_start = CID_START_RING,
01153 .dahditrcallerid = 0,
01154 .use_callerid = 1,
01155 .sig = -1,
01156 .outsigmod = -1,
01157
01158 .cid_rxgain = +5.0,
01159
01160 .tonezone = -1,
01161
01162 .echocancel.head.tap_length = 1,
01163
01164 .busycount = 3,
01165 .busycompare = 0,
01166 .busytonelength = 0,
01167 .busyquietlength = 0,
01168 .busyfuzziness = 0,
01169 .silencethreshold = 0,
01170
01171 .accountcode = "",
01172
01173 .mailbox = "",
01174
01175
01176 .polarityonanswerdelay = 600,
01177
01178 .sendcalleridafter = DEFAULT_CIDRINGS,
01179
01180 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01181 .buf_no = numbufs
01182 },
01183 .timing = {
01184 .prewinktime = -1,
01185 .preflashtime = -1,
01186 .winktime = -1,
01187 .flashtime = -1,
01188 .starttime = -1,
01189 .rxwinktime = -1,
01190 .rxflashtime = -1,
01191 .debouncetime = -1
01192 },
01193 .is_sig_auto = 1,
01194 .smdi_port = "/dev/ttyS0",
01195 };
01196
01197 return conf;
01198 }
01199
01200
01201 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01202 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01203 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01204 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01205 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01206 static int dahdi_hangup(struct ast_channel *ast);
01207 static int dahdi_answer(struct ast_channel *ast);
01208 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01209 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01210 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01211 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01212 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01213 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01214 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01215 static int handle_init_event(struct dahdi_pvt *i, int event);
01216
01217 static const struct ast_channel_tech dahdi_tech = {
01218 .type = "DAHDI",
01219 .description = tdesc,
01220 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01221 .requester = dahdi_request,
01222 .send_digit_begin = dahdi_digit_begin,
01223 .send_digit_end = dahdi_digit_end,
01224 .send_text = dahdi_sendtext,
01225 .call = dahdi_call,
01226 .hangup = dahdi_hangup,
01227 .answer = dahdi_answer,
01228 .read = dahdi_read,
01229 .write = dahdi_write,
01230 .bridge = dahdi_bridge,
01231 .exception = dahdi_exception,
01232 .indicate = dahdi_indicate,
01233 .fixup = dahdi_fixup,
01234 .setoption = dahdi_setoption,
01235 .func_channel_read = dahdi_func_read,
01236 };
01237
01238 #ifdef HAVE_PRI
01239 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01240 #else
01241 #define GET_CHANNEL(p) ((p)->channel)
01242 #endif
01243
01244 struct dahdi_pvt *round_robin[32];
01245
01246 #ifdef HAVE_PRI
01247 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01248 {
01249 int res;
01250
01251 do {
01252 res = ast_mutex_trylock(&pri->lock);
01253 if (res) {
01254 DEADLOCK_AVOIDANCE(&pvt->lock);
01255 }
01256 } while (res);
01257
01258 if (pri->master != AST_PTHREADT_NULL)
01259 pthread_kill(pri->master, SIGURG);
01260 return 0;
01261 }
01262 #endif
01263
01264 #ifdef HAVE_SS7
01265 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01266 {
01267 ast_mutex_unlock(&ss7->lock);
01268 }
01269
01270 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01271 {
01272 int res;
01273
01274 do {
01275 res = ast_mutex_trylock(&pri->lock);
01276 if (res) {
01277 DEADLOCK_AVOIDANCE(&pvt->lock);
01278 }
01279 } while (res);
01280
01281 if (pri->master != AST_PTHREADT_NULL)
01282 pthread_kill(pri->master, SIGURG);
01283 return 0;
01284 }
01285 #endif
01286 #define NUM_CADENCE_MAX 25
01287 static int num_cadence = 4;
01288 static int user_has_defined_cadences = 0;
01289
01290 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01291 { { 125, 125, 2000, 4000 } },
01292 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01293 { { 125, 125, 125, 125, 125, 4000 } },
01294 { { 1000, 500, 2500, 5000 } },
01295 };
01296
01297
01298
01299
01300
01301 static int cidrings[NUM_CADENCE_MAX] = {
01302 2,
01303 4,
01304 3,
01305 2,
01306 };
01307
01308
01309 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01310
01311 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01312 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01313
01314 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01315 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01316
01317 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01318 {
01319 int res;
01320 if (p->subs[SUB_REAL].owner == ast)
01321 res = 0;
01322 else if (p->subs[SUB_CALLWAIT].owner == ast)
01323 res = 1;
01324 else if (p->subs[SUB_THREEWAY].owner == ast)
01325 res = 2;
01326 else {
01327 res = -1;
01328 if (!nullok)
01329 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01330 }
01331 return res;
01332 }
01333
01334 #ifdef HAVE_PRI
01335 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01336 #else
01337 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01338 #endif
01339 {
01340 #ifdef HAVE_PRI
01341 if (pri)
01342 ast_mutex_unlock(&pri->lock);
01343 #endif
01344 for (;;) {
01345 if (p->subs[a].owner) {
01346 if (ast_channel_trylock(p->subs[a].owner)) {
01347 DEADLOCK_AVOIDANCE(&p->lock);
01348 } else {
01349 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01350 ast_channel_unlock(p->subs[a].owner);
01351 break;
01352 }
01353 } else
01354 break;
01355 }
01356 #ifdef HAVE_PRI
01357 if (pri)
01358 ast_mutex_lock(&pri->lock);
01359 #endif
01360 }
01361
01362 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01363 {
01364 #ifdef HAVE_PRI
01365 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01366 #endif
01367 #ifdef HAVE_SS7
01368 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01369 #endif
01370
01371 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01372 if (data) {
01373 switch (p->sig) {
01374 #ifdef HAVE_PRI
01375 case SIG_BRI:
01376 case SIG_BRI_PTMP:
01377 case SIG_PRI:
01378 ast_mutex_unlock(&pri->lock);
01379 break;
01380 #endif
01381 #ifdef HAVE_SS7
01382 case SIG_SS7:
01383 ast_mutex_unlock(&ss7->lock);
01384 break;
01385 #endif
01386 default:
01387 break;
01388 }
01389 }
01390 #endif
01391 for (;;) {
01392 if (p->owner) {
01393 if (ast_channel_trylock(p->owner)) {
01394 DEADLOCK_AVOIDANCE(&p->lock);
01395 } else {
01396 ast_queue_frame(p->owner, f);
01397 ast_channel_unlock(p->owner);
01398 break;
01399 }
01400 } else
01401 break;
01402 }
01403 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01404 if (data) {
01405 switch (p->sig) {
01406 #ifdef HAVE_PRI
01407 case SIG_BRI:
01408 case SIG_BRI_PTMP:
01409 case SIG_PRI:
01410 ast_mutex_lock(&pri->lock);
01411 break;
01412 #endif
01413 #ifdef HAVE_SS7
01414 case SIG_SS7:
01415 ast_mutex_lock(&ss7->lock);
01416 break;
01417 #endif
01418 default:
01419 break;
01420 }
01421 }
01422
01423 #endif
01424 }
01425
01426 static int restore_gains(struct dahdi_pvt *p);
01427
01428 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01429 {
01430 int tchan;
01431 int tinthreeway;
01432 struct ast_channel *towner;
01433
01434 ast_debug(1, "Swapping %d and %d\n", a, b);
01435
01436 tchan = p->subs[a].chan;
01437 towner = p->subs[a].owner;
01438 tinthreeway = p->subs[a].inthreeway;
01439
01440 p->subs[a].chan = p->subs[b].chan;
01441 p->subs[a].owner = p->subs[b].owner;
01442 p->subs[a].inthreeway = p->subs[b].inthreeway;
01443
01444 p->subs[b].chan = tchan;
01445 p->subs[b].owner = towner;
01446 p->subs[b].inthreeway = tinthreeway;
01447
01448 if (p->subs[a].owner)
01449 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01450 if (p->subs[b].owner)
01451 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01452 wakeup_sub(p, a, NULL);
01453 wakeup_sub(p, b, NULL);
01454 }
01455
01456 static int dahdi_open(char *fn)
01457 {
01458 int fd;
01459 int isnum;
01460 int chan = 0;
01461 int bs;
01462 int x;
01463 isnum = 1;
01464 for (x = 0; x < strlen(fn); x++) {
01465 if (!isdigit(fn[x])) {
01466 isnum = 0;
01467 break;
01468 }
01469 }
01470 if (isnum) {
01471 chan = atoi(fn);
01472 if (chan < 1) {
01473 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01474 return -1;
01475 }
01476 fn = "/dev/dahdi/channel";
01477 }
01478 fd = open(fn, O_RDWR | O_NONBLOCK);
01479 if (fd < 0) {
01480 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01481 return -1;
01482 }
01483 if (chan) {
01484 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01485 x = errno;
01486 close(fd);
01487 errno = x;
01488 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01489 return -1;
01490 }
01491 }
01492 bs = READ_SIZE;
01493 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01494 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01495 x = errno;
01496 close(fd);
01497 errno = x;
01498 return -1;
01499 }
01500 return fd;
01501 }
01502
01503 static void dahdi_close(int fd)
01504 {
01505 if (fd > 0)
01506 close(fd);
01507 }
01508
01509 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01510 {
01511 dahdi_close(chan_pvt->subs[sub_num].dfd);
01512 chan_pvt->subs[sub_num].dfd = -1;
01513 }
01514
01515 #ifdef HAVE_PRI
01516 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01517 {
01518 dahdi_close(pri->fds[fd_num]);
01519 pri->fds[fd_num] = -1;
01520 }
01521 #endif
01522
01523 #ifdef HAVE_SS7
01524 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
01525 {
01526 dahdi_close(ss7->fds[fd_num]);
01527 ss7->fds[fd_num] = -1;
01528 }
01529 #endif
01530
01531 static int dahdi_setlinear(int dfd, int linear)
01532 {
01533 int res;
01534 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01535 if (res)
01536 return res;
01537 return 0;
01538 }
01539
01540
01541 static int alloc_sub(struct dahdi_pvt *p, int x)
01542 {
01543 struct dahdi_bufferinfo bi;
01544 int res;
01545 if (p->subs[x].dfd >= 0) {
01546 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01547 return -1;
01548 }
01549
01550 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01551 if (p->subs[x].dfd <= -1) {
01552 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01553 return -1;
01554 }
01555
01556 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01557 if (!res) {
01558 bi.txbufpolicy = p->buf_policy;
01559 bi.rxbufpolicy = p->buf_policy;
01560 bi.numbufs = p->buf_no;
01561 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01562 if (res < 0) {
01563 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01564 }
01565 } else
01566 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01567
01568 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01569 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01570 dahdi_close_sub(p, x);
01571 p->subs[x].dfd = -1;
01572 return -1;
01573 }
01574 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01575 return 0;
01576 }
01577
01578 static int unalloc_sub(struct dahdi_pvt *p, int x)
01579 {
01580 if (!x) {
01581 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01582 return -1;
01583 }
01584 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01585 dahdi_close_sub(p, x);
01586 p->subs[x].linear = 0;
01587 p->subs[x].chan = 0;
01588 p->subs[x].owner = NULL;
01589 p->subs[x].inthreeway = 0;
01590 p->polarity = POLARITY_IDLE;
01591 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01592 return 0;
01593 }
01594
01595 static int digit_to_dtmfindex(char digit)
01596 {
01597 if (isdigit(digit))
01598 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01599 else if (digit >= 'A' && digit <= 'D')
01600 return DAHDI_TONE_DTMF_A + (digit - 'A');
01601 else if (digit >= 'a' && digit <= 'd')
01602 return DAHDI_TONE_DTMF_A + (digit - 'a');
01603 else if (digit == '*')
01604 return DAHDI_TONE_DTMF_s;
01605 else if (digit == '#')
01606 return DAHDI_TONE_DTMF_p;
01607 else
01608 return -1;
01609 }
01610
01611 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01612 {
01613 struct dahdi_pvt *pvt;
01614 int idx;
01615 int dtmf = -1;
01616
01617 pvt = chan->tech_pvt;
01618
01619 ast_mutex_lock(&pvt->lock);
01620
01621 idx = dahdi_get_index(chan, pvt, 0);
01622
01623 if ((idx != SUB_REAL) || !pvt->owner)
01624 goto out;
01625
01626 #ifdef HAVE_PRI
01627 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01628 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01629 if (pvt->setup_ack) {
01630 if (!pri_grab(pvt, pvt->pri)) {
01631 pri_information(pvt->pri->pri, pvt->call, digit);
01632 pri_rel(pvt->pri);
01633 } else
01634 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01635 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01636 int res;
01637 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01638 res = strlen(pvt->dialdest);
01639 pvt->dialdest[res++] = digit;
01640 pvt->dialdest[res] = '\0';
01641 }
01642 goto out;
01643 }
01644 #endif
01645 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01646 goto out;
01647
01648 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01649 int res;
01650 struct dahdi_dialoperation zo = {
01651 .op = DAHDI_DIAL_OP_APPEND,
01652 };
01653
01654 zo.dialstr[0] = 'T';
01655 zo.dialstr[1] = digit;
01656 zo.dialstr[2] = '\0';
01657 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01658 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01659 else
01660 pvt->dialing = 1;
01661 } else {
01662 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01663 pvt->dialing = 1;
01664 pvt->begindigit = digit;
01665 }
01666
01667 out:
01668 ast_mutex_unlock(&pvt->lock);
01669
01670 return 0;
01671 }
01672
01673 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01674 {
01675 struct dahdi_pvt *pvt;
01676 int res = 0;
01677 int idx;
01678 int x;
01679
01680 pvt = chan->tech_pvt;
01681
01682 ast_mutex_lock(&pvt->lock);
01683
01684 idx = dahdi_get_index(chan, pvt, 0);
01685
01686 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
01687 goto out;
01688
01689 #ifdef HAVE_PRI
01690
01691 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01692 && !pvt->begindigit)
01693 goto out;
01694 #endif
01695
01696 if (pvt->begindigit) {
01697 x = -1;
01698 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01699 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01700 pvt->dialing = 0;
01701 pvt->begindigit = 0;
01702 }
01703
01704 out:
01705 ast_mutex_unlock(&pvt->lock);
01706
01707 return res;
01708 }
01709
01710 static char *events[] = {
01711 "No event",
01712 "On hook",
01713 "Ring/Answered",
01714 "Wink/Flash",
01715 "Alarm",
01716 "No more alarm",
01717 "HDLC Abort",
01718 "HDLC Overrun",
01719 "HDLC Bad FCS",
01720 "Dial Complete",
01721 "Ringer On",
01722 "Ringer Off",
01723 "Hook Transition Complete",
01724 "Bits Changed",
01725 "Pulse Start",
01726 "Timer Expired",
01727 "Timer Ping",
01728 "Polarity Reversal",
01729 "Ring Begin",
01730 };
01731
01732 static struct {
01733 int alarm;
01734 char *name;
01735 } alarms[] = {
01736 { DAHDI_ALARM_RED, "Red Alarm" },
01737 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01738 { DAHDI_ALARM_BLUE, "Blue Alarm" },
01739 { DAHDI_ALARM_RECOVER, "Recovering" },
01740 { DAHDI_ALARM_LOOPBACK, "Loopback" },
01741 { DAHDI_ALARM_NOTOPEN, "Not Open" },
01742 { DAHDI_ALARM_NONE, "None" },
01743 };
01744
01745 static char *alarm2str(int alm)
01746 {
01747 int x;
01748 for (x = 0; x < ARRAY_LEN(alarms); x++) {
01749 if (alarms[x].alarm & alm)
01750 return alarms[x].name;
01751 }
01752 return alm ? "Unknown Alarm" : "No Alarm";
01753 }
01754
01755 static char *event2str(int event)
01756 {
01757 static char buf[256];
01758 if ((event < (ARRAY_LEN(events))) && (event > -1))
01759 return events[event];
01760 sprintf(buf, "Event %d", event);
01761 return buf;
01762 }
01763
01764 #ifdef HAVE_PRI
01765 static char *dialplan2str(int dialplan)
01766 {
01767 if (dialplan == -1 || dialplan == -2) {
01768 return("Dynamically set dialplan in ISDN");
01769 }
01770 return (pri_plan2str(dialplan));
01771 }
01772 #endif
01773
01774 static char *dahdi_sig2str(int sig)
01775 {
01776 static char buf[256];
01777 switch (sig) {
01778 case SIG_EM:
01779 return "E & M Immediate";
01780 case SIG_EMWINK:
01781 return "E & M Wink";
01782 case SIG_EM_E1:
01783 return "E & M E1";
01784 case SIG_FEATD:
01785 return "Feature Group D (DTMF)";
01786 case SIG_FEATDMF:
01787 return "Feature Group D (MF)";
01788 case SIG_FEATDMF_TA:
01789 return "Feature Groud D (MF) Tandem Access";
01790 case SIG_FEATB:
01791 return "Feature Group B (MF)";
01792 case SIG_E911:
01793 return "E911 (MF)";
01794 case SIG_FGC_CAMA:
01795 return "FGC/CAMA (Dialpulse)";
01796 case SIG_FGC_CAMAMF:
01797 return "FGC/CAMA (MF)";
01798 case SIG_FXSLS:
01799 return "FXS Loopstart";
01800 case SIG_FXSGS:
01801 return "FXS Groundstart";
01802 case SIG_FXSKS:
01803 return "FXS Kewlstart";
01804 case SIG_FXOLS:
01805 return "FXO Loopstart";
01806 case SIG_FXOGS:
01807 return "FXO Groundstart";
01808 case SIG_FXOKS:
01809 return "FXO Kewlstart";
01810 case SIG_PRI:
01811 return "ISDN PRI";
01812 case SIG_BRI:
01813 return "ISDN BRI Point to Point";
01814 case SIG_BRI_PTMP:
01815 return "ISDN BRI Point to MultiPoint";
01816 case SIG_SS7:
01817 return "SS7";
01818 case SIG_SF:
01819 return "SF (Tone) Immediate";
01820 case SIG_SFWINK:
01821 return "SF (Tone) Wink";
01822 case SIG_SF_FEATD:
01823 return "SF (Tone) with Feature Group D (DTMF)";
01824 case SIG_SF_FEATDMF:
01825 return "SF (Tone) with Feature Group D (MF)";
01826 case SIG_SF_FEATB:
01827 return "SF (Tone) with Feature Group B (MF)";
01828 case SIG_GR303FXOKS:
01829 return "GR-303 with FXOKS";
01830 case SIG_GR303FXSKS:
01831 return "GR-303 with FXSKS";
01832 case 0:
01833 return "Pseudo";
01834 default:
01835 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01836 return buf;
01837 }
01838 }
01839
01840 #define sig2str dahdi_sig2str
01841
01842 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
01843 {
01844
01845
01846 struct dahdi_confinfo zi;
01847
01848 memset(&zi, 0, sizeof(zi));
01849 zi.chan = 0;
01850
01851 if (slavechannel > 0) {
01852
01853 zi.confmode = DAHDI_CONF_DIGITALMON;
01854 zi.confno = slavechannel;
01855 } else {
01856 if (!idx) {
01857
01858 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01859 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01860 } else
01861 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01862 zi.confno = p->confno;
01863 }
01864 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01865 return 0;
01866 if (c->dfd < 0)
01867 return 0;
01868 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01869 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01870 return -1;
01871 }
01872 if (slavechannel < 1) {
01873 p->confno = zi.confno;
01874 }
01875 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01876 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01877 return 0;
01878 }
01879
01880 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01881 {
01882
01883 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01884 return 1;
01885
01886 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01887 return 1;
01888 return 0;
01889 }
01890
01891 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
01892 {
01893 struct dahdi_confinfo zi;
01894 if (
01895 (c->dfd < 0) ||
01896
01897 !isourconf(p, c)
01898
01899 ) return 0;
01900 memset(&zi, 0, sizeof(zi));
01901 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01902 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01903 return -1;
01904 }
01905 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01906 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01907 return 0;
01908 }
01909
01910 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01911 {
01912 int x;
01913 int useslavenative;
01914 struct dahdi_pvt *slave = NULL;
01915
01916 useslavenative = 1;
01917
01918 for (x = 0; x < 3; x++) {
01919
01920
01921 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01922 useslavenative = 0;
01923 }
01924
01925
01926 if (useslavenative) {
01927 for (x = 0; x < MAX_SLAVES; x++) {
01928 if (p->slaves[x]) {
01929 if (slave) {
01930
01931
01932 slave = NULL;
01933 useslavenative = 0;
01934 break;
01935 } else {
01936
01937 slave = p->slaves[x];
01938 }
01939 }
01940 }
01941 }
01942
01943 if (!slave)
01944 useslavenative = 0;
01945 else if (slave->law != p->law) {
01946 useslavenative = 0;
01947 slave = NULL;
01948 }
01949 if (out)
01950 *out = slave;
01951 return useslavenative;
01952 }
01953
01954 static int reset_conf(struct dahdi_pvt *p)
01955 {
01956 p->confno = -1;
01957 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01958 if (p->subs[SUB_REAL].dfd > -1) {
01959 struct dahdi_confinfo zi;
01960
01961 memset(&zi, 0, sizeof(zi));
01962 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01963 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01964 }
01965 return 0;
01966 }
01967
01968 static int update_conf(struct dahdi_pvt *p)
01969 {
01970 int needconf = 0;
01971 int x;
01972 int useslavenative;
01973 struct dahdi_pvt *slave = NULL;
01974
01975 useslavenative = isslavenative(p, &slave);
01976
01977 for (x = 0; x < 3; x++) {
01978
01979 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01980 conf_add(p, &p->subs[x], x, 0);
01981 needconf++;
01982 } else {
01983 conf_del(p, &p->subs[x], x);
01984 }
01985 }
01986
01987
01988 for (x = 0; x < MAX_SLAVES; x++) {
01989 if (p->slaves[x]) {
01990 if (useslavenative)
01991 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01992 else {
01993 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01994 needconf++;
01995 }
01996 }
01997 }
01998
01999 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02000 if (useslavenative)
02001 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02002 else {
02003 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02004 needconf++;
02005 }
02006 }
02007
02008 if (p->master) {
02009 if (isslavenative(p->master, NULL)) {
02010 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02011 } else {
02012 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02013 }
02014 }
02015 if (!needconf) {
02016
02017
02018 p->confno = -1;
02019 }
02020 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02021 return 0;
02022 }
02023
02024 static void dahdi_enable_ec(struct dahdi_pvt *p)
02025 {
02026 int x;
02027 int res;
02028 if (!p)
02029 return;
02030 if (p->echocanon) {
02031 ast_debug(1, "Echo cancellation already on\n");
02032 return;
02033 }
02034 if (p->digital) {
02035 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02036 return;
02037 }
02038 if (p->echocancel.head.tap_length) {
02039 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02040 x = 1;
02041 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02042 if (res)
02043 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02044 }
02045 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02046 if (res) {
02047 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02048 } else {
02049 p->echocanon = 1;
02050 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02051 }
02052 } else
02053 ast_debug(1, "No echo cancellation requested\n");
02054 }
02055
02056 static void dahdi_train_ec(struct dahdi_pvt *p)
02057 {
02058 int x;
02059 int res;
02060
02061 if (p && p->echocanon && p->echotraining) {
02062 x = p->echotraining;
02063 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02064 if (res)
02065 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02066 else
02067 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02068 } else {
02069 ast_debug(1, "No echo training requested\n");
02070 }
02071 }
02072
02073 static void dahdi_disable_ec(struct dahdi_pvt *p)
02074 {
02075 int res;
02076
02077 if (p->echocanon) {
02078 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02079
02080 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02081
02082 if (res)
02083 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02084 else
02085 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02086 }
02087
02088 p->echocanon = 0;
02089 }
02090
02091 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02092 {
02093 int j;
02094 int k;
02095 float linear_gain = pow(10.0, gain / 20.0);
02096
02097 switch (law) {
02098 case DAHDI_LAW_ALAW:
02099 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02100 if (gain) {
02101 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02102 if (k > 32767) k = 32767;
02103 if (k < -32767) k = -32767;
02104 g->txgain[j] = AST_LIN2A(k);
02105 } else {
02106 g->txgain[j] = j;
02107 }
02108 }
02109 break;
02110 case DAHDI_LAW_MULAW:
02111 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02112 if (gain) {
02113 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02114 if (k > 32767) k = 32767;
02115 if (k < -32767) k = -32767;
02116 g->txgain[j] = AST_LIN2MU(k);
02117 } else {
02118 g->txgain[j] = j;
02119 }
02120 }
02121 break;
02122 }
02123 }
02124
02125 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02126 {
02127 int j;
02128 int k;
02129 float linear_gain = pow(10.0, gain / 20.0);
02130
02131 switch (law) {
02132 case DAHDI_LAW_ALAW:
02133 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02134 if (gain) {
02135 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02136 if (k > 32767) k = 32767;
02137 if (k < -32767) k = -32767;
02138 g->rxgain[j] = AST_LIN2A(k);
02139 } else {
02140 g->rxgain[j] = j;
02141 }
02142 }
02143 break;
02144 case DAHDI_LAW_MULAW:
02145 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02146 if (gain) {
02147 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02148 if (k > 32767) k = 32767;
02149 if (k < -32767) k = -32767;
02150 g->rxgain[j] = AST_LIN2MU(k);
02151 } else {
02152 g->rxgain[j] = j;
02153 }
02154 }
02155 break;
02156 }
02157 }
02158
02159 static int set_actual_txgain(int fd, int chan, float gain, int law)
02160 {
02161 struct dahdi_gains g;
02162 int res;
02163
02164 memset(&g, 0, sizeof(g));
02165 g.chan = chan;
02166 res = ioctl(fd, DAHDI_GETGAINS, &g);
02167 if (res) {
02168 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02169 return res;
02170 }
02171
02172 fill_txgain(&g, gain, law);
02173
02174 return ioctl(fd, DAHDI_SETGAINS, &g);
02175 }
02176
02177 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02178 {
02179 struct dahdi_gains g;
02180 int res;
02181
02182 memset(&g, 0, sizeof(g));
02183 g.chan = chan;
02184 res = ioctl(fd, DAHDI_GETGAINS, &g);
02185 if (res) {
02186 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02187 return res;
02188 }
02189
02190 fill_rxgain(&g, gain, law);
02191
02192 return ioctl(fd, DAHDI_SETGAINS, &g);
02193 }
02194
02195 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02196 {
02197 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02198 }
02199
02200 static int bump_gains(struct dahdi_pvt *p)
02201 {
02202 int res;
02203
02204
02205 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02206 if (res) {
02207 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02208 return -1;
02209 }
02210
02211 return 0;
02212 }
02213
02214 static int restore_gains(struct dahdi_pvt *p)
02215 {
02216 int res;
02217
02218 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02219 if (res) {
02220 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02221 return -1;
02222 }
02223
02224 return 0;
02225 }
02226
02227 static inline int dahdi_set_hook(int fd, int hs)
02228 {
02229 int x, res;
02230
02231 x = hs;
02232 res = ioctl(fd, DAHDI_HOOK, &x);
02233
02234 if (res < 0) {
02235 if (errno == EINPROGRESS)
02236 return 0;
02237 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02238
02239 }
02240
02241 return res;
02242 }
02243
02244 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02245 {
02246 int x, y, res;
02247 x = muted;
02248 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02249 y = 1;
02250 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02251 if (res)
02252 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02253 }
02254 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02255 if (res < 0)
02256 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02257 return res;
02258 }
02259
02260 static int save_conference(struct dahdi_pvt *p)
02261 {
02262 struct dahdi_confinfo c;
02263 int res;
02264 if (p->saveconf.confmode) {
02265 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02266 return -1;
02267 }
02268 p->saveconf.chan = 0;
02269 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02270 if (res) {
02271 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02272 p->saveconf.confmode = 0;
02273 return -1;
02274 }
02275 memset(&c, 0, sizeof(c));
02276 c.confmode = DAHDI_CONF_NORMAL;
02277 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02278 if (res) {
02279 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02280 return -1;
02281 }
02282 ast_debug(1, "Disabled conferencing\n");
02283 return 0;
02284 }
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304 static void notify_message(char *mailbox_full, int thereornot)
02305 {
02306 char s[sizeof(mwimonitornotify) + 80];
02307 struct ast_event *event;
02308 char *mailbox, *context;
02309
02310
02311 context = mailbox = ast_strdupa(mailbox_full);
02312 strsep(&context, "@");
02313 if (ast_strlen_zero(context))
02314 context = "default";
02315
02316 if (!(event = ast_event_new(AST_EVENT_MWI,
02317 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02318 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02319 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02320 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02321 AST_EVENT_IE_END))) {
02322 return;
02323 }
02324
02325 ast_event_queue_and_cache(event);
02326
02327 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02328 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02329 ast_safe_system(s);
02330 }
02331 }
02332
02333 static int restore_conference(struct dahdi_pvt *p)
02334 {
02335 int res;
02336 if (p->saveconf.confmode) {
02337 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02338 p->saveconf.confmode = 0;
02339 if (res) {
02340 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02341 return -1;
02342 }
02343 }
02344 ast_debug(1, "Restored conferencing\n");
02345 return 0;
02346 }
02347
02348 static int send_callerid(struct dahdi_pvt *p);
02349
02350 static int send_cwcidspill(struct dahdi_pvt *p)
02351 {
02352 p->callwaitcas = 0;
02353 p->cidcwexpire = 0;
02354 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02355 return -1;
02356 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02357
02358 p->cidlen += READ_SIZE * 4;
02359 p->cidpos = 0;
02360 send_callerid(p);
02361 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02362 return 0;
02363 }
02364
02365 static int has_voicemail(struct dahdi_pvt *p)
02366 {
02367 int new_msgs;
02368 struct ast_event *event;
02369 char *mailbox, *context;
02370
02371 mailbox = context = ast_strdupa(p->mailbox);
02372 strsep(&context, "@");
02373 if (ast_strlen_zero(context))
02374 context = "default";
02375
02376 event = ast_event_get_cached(AST_EVENT_MWI,
02377 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02378 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02379 AST_EVENT_IE_END);
02380
02381 if (event) {
02382 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02383 ast_event_destroy(event);
02384 } else
02385 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02386
02387 return new_msgs;
02388 }
02389
02390 static int send_callerid(struct dahdi_pvt *p)
02391 {
02392
02393 int res;
02394
02395 if (p->subs[SUB_REAL].linear) {
02396 p->subs[SUB_REAL].linear = 0;
02397 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02398 }
02399 while (p->cidpos < p->cidlen) {
02400 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02401 if (res < 0) {
02402 if (errno == EAGAIN)
02403 return 0;
02404 else {
02405 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02406 return -1;
02407 }
02408 }
02409 if (!res)
02410 return 0;
02411 p->cidpos += res;
02412 }
02413 ast_free(p->cidspill);
02414 p->cidspill = NULL;
02415 if (p->callwaitcas) {
02416
02417 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02418 } else
02419 restore_conference(p);
02420 return 0;
02421 }
02422
02423 static int dahdi_callwait(struct ast_channel *ast)
02424 {
02425 struct dahdi_pvt *p = ast->tech_pvt;
02426 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02427 if (p->cidspill) {
02428 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02429 ast_free(p->cidspill);
02430 }
02431 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02432 return -1;
02433 save_conference(p);
02434
02435 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02436 if (!p->callwaitrings && p->callwaitingcallerid) {
02437 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02438 p->callwaitcas = 1;
02439 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02440 } else {
02441 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02442 p->callwaitcas = 0;
02443 p->cidlen = 2400 + READ_SIZE * 4;
02444 }
02445 p->cidpos = 0;
02446 send_callerid(p);
02447
02448 return 0;
02449 }
02450
02451 #ifdef HAVE_SS7
02452 static unsigned char cid_pres2ss7pres(int cid_pres)
02453 {
02454 return (cid_pres >> 5) & 0x03;
02455 }
02456
02457 static unsigned char cid_pres2ss7screen(int cid_pres)
02458 {
02459 return cid_pres & 0x03;
02460 }
02461 #endif
02462
02463 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02464 {
02465 struct dahdi_pvt *p = ast->tech_pvt;
02466 int x, res, idx,mysig;
02467 char *c, *n, *l;
02468 #ifdef HAVE_PRI
02469 char *s = NULL;
02470 #endif
02471 char dest[256];
02472 ast_mutex_lock(&p->lock);
02473 ast_copy_string(dest, rdest, sizeof(dest));
02474 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02475 if ((ast->_state == AST_STATE_BUSY)) {
02476 p->subs[SUB_REAL].needbusy = 1;
02477 ast_mutex_unlock(&p->lock);
02478 return 0;
02479 }
02480 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02481 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02482 ast_mutex_unlock(&p->lock);
02483 return -1;
02484 }
02485 p->dialednone = 0;
02486 if ((p->radio || (p->oprmode < 0)))
02487 {
02488
02489 ast_setstate(ast, AST_STATE_UP);
02490 ast_mutex_unlock(&p->lock);
02491 return 0;
02492 }
02493 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02494 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02495 if (res)
02496 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02497 p->outgoing = 1;
02498
02499 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02500
02501 mysig = p->sig;
02502 if (p->outsigmod > -1)
02503 mysig = p->outsigmod;
02504
02505 switch (mysig) {
02506 case SIG_FXOLS:
02507 case SIG_FXOGS:
02508 case SIG_FXOKS:
02509 if (p->owner == ast) {
02510
02511
02512
02513 p->dialing = 1;
02514 if (p->use_callerid) {
02515
02516 if (p->cidspill) {
02517 ast_log(LOG_WARNING, "cidspill already exists??\n");
02518 ast_free(p->cidspill);
02519 }
02520 p->callwaitcas = 0;
02521 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02522 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02523 p->cidpos = 0;
02524 send_callerid(p);
02525 }
02526 }
02527
02528 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02529 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02530 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02531 p->cidrings = cidrings[p->distinctivering - 1];
02532 } else {
02533 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02534 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02535 p->cidrings = p->sendcalleridafter;
02536 }
02537
02538
02539 c = strchr(dest, '/');
02540 if (c)
02541 c++;
02542 if (c && (strlen(c) < p->stripmsd)) {
02543 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02544 c = NULL;
02545 }
02546 if (c) {
02547 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02548 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02549 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
02550 } else {
02551 p->dop.dialstr[0] = '\0';
02552 }
02553 x = DAHDI_RING;
02554 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02555 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02556 ast_mutex_unlock(&p->lock);
02557 return -1;
02558 }
02559 p->dialing = 1;
02560 } else {
02561
02562 p->callwaitrings = 0;
02563 if (ast->cid.cid_num)
02564 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02565 else
02566 p->callwait_num[0] = '\0';
02567 if (ast->cid.cid_name)
02568 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02569 else
02570 p->callwait_name[0] = '\0';
02571
02572 if (dahdi_callwait(ast)) {
02573 ast_mutex_unlock(&p->lock);
02574 return -1;
02575 }
02576
02577 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02578 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02579
02580 }
02581 n = ast->cid.cid_name;
02582 l = ast->cid.cid_num;
02583 if (l)
02584 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02585 else
02586 p->lastcid_num[0] = '\0';
02587 if (n)
02588 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02589 else
02590 p->lastcid_name[0] = '\0';
02591 ast_setstate(ast, AST_STATE_RINGING);
02592 idx = dahdi_get_index(ast, p, 0);
02593 if (idx > -1) {
02594 p->subs[idx].needringing = 1;
02595 }
02596 break;
02597 case SIG_FXSLS:
02598 case SIG_FXSGS:
02599 case SIG_FXSKS:
02600 case SIG_EMWINK:
02601 case SIG_EM:
02602 case SIG_EM_E1:
02603 case SIG_FEATD:
02604 case SIG_FEATDMF:
02605 case SIG_E911:
02606 case SIG_FGC_CAMA:
02607 case SIG_FGC_CAMAMF:
02608 case SIG_FEATB:
02609 case SIG_SFWINK:
02610 case SIG_SF:
02611 case SIG_SF_FEATD:
02612 case SIG_SF_FEATDMF:
02613 case SIG_FEATDMF_TA:
02614 case SIG_SF_FEATB:
02615 c = strchr(dest, '/');
02616 if (c)
02617 c++;
02618 else
02619 c = "";
02620 if (strlen(c) < p->stripmsd) {
02621 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02622 ast_mutex_unlock(&p->lock);
02623 return -1;
02624 }
02625 #ifdef HAVE_PRI
02626
02627 if (!p->pri) {
02628 #endif
02629 x = DAHDI_START;
02630 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02631 if (res < 0) {
02632 if (errno != EINPROGRESS) {
02633 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02634 ast_mutex_unlock(&p->lock);
02635 return -1;
02636 }
02637 }
02638 #ifdef HAVE_PRI
02639 }
02640 #endif
02641 ast_debug(1, "Dialing '%s'\n", c);
02642 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02643
02644 c += p->stripmsd;
02645
02646 switch (mysig) {
02647 case SIG_FEATD:
02648 l = ast->cid.cid_num;
02649 if (l)
02650 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02651 else
02652 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02653 break;
02654 case SIG_FEATDMF:
02655 l = ast->cid.cid_num;
02656 if (l)
02657 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02658 else
02659 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02660 break;
02661 case SIG_FEATDMF_TA:
02662 {
02663 const char *cic, *ozz;
02664
02665
02666 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02667 if (!ozz)
02668 ozz = defaultozz;
02669 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02670 if (!cic)
02671 cic = defaultcic;
02672 if (!ozz || !cic) {
02673 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02674 ast_mutex_unlock(&p->lock);
02675 return -1;
02676 }
02677 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02678 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02679 p->whichwink = 0;
02680 }
02681 break;
02682 case SIG_E911:
02683 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02684 break;
02685 case SIG_FGC_CAMA:
02686 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02687 break;
02688 case SIG_FGC_CAMAMF:
02689 case SIG_FEATB:
02690 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02691 break;
02692 default:
02693 if (p->pulse)
02694 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02695 else
02696 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02697 break;
02698 }
02699
02700 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02701 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02702 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02703 p->echorest[sizeof(p->echorest) - 1] = '\0';
02704 p->echobreak = 1;
02705 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02706 } else
02707 p->echobreak = 0;
02708 if (!res) {
02709 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02710 int saveerr = errno;
02711
02712 x = DAHDI_ONHOOK;
02713 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02714 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02715 ast_mutex_unlock(&p->lock);
02716 return -1;
02717 }
02718 } else
02719 ast_debug(1, "Deferring dialing...\n");
02720
02721 p->dialing = 1;
02722 if (ast_strlen_zero(c))
02723 p->dialednone = 1;
02724 ast_setstate(ast, AST_STATE_DIALING);
02725 break;
02726 case 0:
02727
02728 ast_setstate(ast, AST_STATE_UP);
02729 break;
02730 case SIG_PRI:
02731 case SIG_BRI:
02732 case SIG_BRI_PTMP:
02733 case SIG_SS7:
02734
02735 p->dialdest[0] = '\0';
02736 p->dialing = 1;
02737 break;
02738 default:
02739 ast_debug(1, "not yet implemented\n");
02740 ast_mutex_unlock(&p->lock);
02741 return -1;
02742 }
02743 #ifdef HAVE_SS7
02744 if (p->ss7) {
02745 char ss7_called_nai;
02746 int called_nai_strip;
02747 char ss7_calling_nai;
02748 int calling_nai_strip;
02749 const char *charge_str = NULL;
02750 const char *gen_address = NULL;
02751 const char *gen_digits = NULL;
02752 const char *gen_dig_type = NULL;
02753 const char *gen_dig_scheme = NULL;
02754 const char *gen_name = NULL;
02755 const char *jip_digits = NULL;
02756 const char *lspi_ident = NULL;
02757 const char *rlt_flag = NULL;
02758 const char *call_ref_id = NULL;
02759 const char *call_ref_pc = NULL;
02760 const char *send_far = NULL;
02761
02762 c = strchr(dest, '/');
02763 if (c) {
02764 c++;
02765 } else {
02766 c = "";
02767 }
02768 if (strlen(c) < p->stripmsd) {
02769 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02770 ast_mutex_unlock(&p->lock);
02771 return -1;
02772 }
02773
02774 if (!p->hidecallerid) {
02775 l = ast->cid.cid_num;
02776 } else {
02777 l = NULL;
02778 }
02779
02780 if (ss7_grab(p, p->ss7)) {
02781 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02782 ast_mutex_unlock(&p->lock);
02783 return -1;
02784 }
02785 p->digital = IS_DIGITAL(ast->transfercapability);
02786 p->ss7call = isup_new_call(p->ss7->ss7);
02787
02788 if (!p->ss7call) {
02789 ss7_rel(p->ss7);
02790 ast_mutex_unlock(&p->lock);
02791 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02792 return -1;
02793 }
02794
02795 called_nai_strip = 0;
02796 ss7_called_nai = p->ss7->called_nai;
02797 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
02798 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02799 called_nai_strip = strlen(p->ss7->internationalprefix);
02800 ss7_called_nai = SS7_NAI_INTERNATIONAL;
02801 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02802 called_nai_strip = strlen(p->ss7->nationalprefix);
02803 ss7_called_nai = SS7_NAI_NATIONAL;
02804 } else {
02805 ss7_called_nai = SS7_NAI_SUBSCRIBER;
02806 }
02807 }
02808 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02809
02810 calling_nai_strip = 0;
02811 ss7_calling_nai = p->ss7->calling_nai;
02812 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
02813 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02814 calling_nai_strip = strlen(p->ss7->internationalprefix);
02815 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02816 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02817 calling_nai_strip = strlen(p->ss7->nationalprefix);
02818 ss7_calling_nai = SS7_NAI_NATIONAL;
02819 } else {
02820 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02821 }
02822 }
02823 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02824 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02825 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02826
02827 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02828 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02829
02830 ast_channel_lock(ast);
02831
02832 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02833 if (charge_str)
02834 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02835
02836 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02837 if (gen_address)
02838 isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type);
02839
02840 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02841 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02842 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02843 if (gen_digits)
02844 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
02845
02846 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02847 if (gen_name)
02848 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02849
02850 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02851 if (jip_digits)
02852 isup_set_jip_digits(p->ss7call, jip_digits);
02853
02854 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02855 if (lspi_ident)
02856 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
02857
02858 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02859 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02860 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
02861 }
02862
02863 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02864 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02865 if (call_ref_id && call_ref_pc) {
02866 isup_set_callref(p->ss7call, atoi(call_ref_id),
02867 call_ref_pc ? atoi(call_ref_pc) : 0);
02868 }
02869
02870 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02871 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02872 (isup_far(p->ss7->ss7, p->ss7call));
02873
02874 ast_channel_unlock(ast);
02875
02876 isup_iam(p->ss7->ss7, p->ss7call);
02877 ast_setstate(ast, AST_STATE_DIALING);
02878 ss7_rel(p->ss7);
02879 }
02880 #endif
02881 #ifdef HAVE_PRI
02882 if (p->pri) {
02883 struct pri_sr *sr;
02884 #ifdef SUPPORT_USERUSER
02885 const char *useruser;
02886 #endif
02887 int pridialplan;
02888 int dp_strip;
02889 int prilocaldialplan;
02890 int ldp_strip;
02891 int exclusive;
02892 const char *rr_str;
02893 int redirect_reason;
02894
02895 c = strchr(dest, '/');
02896 if (c) {
02897 c++;
02898 } else {
02899 c = "";
02900 }
02901
02902 l = NULL;
02903 n = NULL;
02904 if (!p->hidecallerid) {
02905 l = ast->cid.cid_num;
02906 if (!p->hidecalleridname) {
02907 n = ast->cid.cid_name;
02908 }
02909 }
02910
02911 if (strlen(c) < p->stripmsd) {
02912 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02913 ast_mutex_unlock(&p->lock);
02914 return -1;
02915 }
02916 if (mysig != SIG_FXSKS) {
02917 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02918 s = strchr(c + p->stripmsd, 'w');
02919 if (s) {
02920 if (strlen(s) > 1)
02921 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02922 else
02923 p->dop.dialstr[0] = '\0';
02924 *s = '\0';
02925 } else {
02926 p->dop.dialstr[0] = '\0';
02927 }
02928 }
02929 if (pri_grab(p, p->pri)) {
02930 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02931 ast_mutex_unlock(&p->lock);
02932 return -1;
02933 }
02934 if (!(p->call = pri_new_call(p->pri->pri))) {
02935 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02936 pri_rel(p->pri);
02937 ast_mutex_unlock(&p->lock);
02938 return -1;
02939 }
02940 if (!(sr = pri_sr_new())) {
02941 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02942 pri_rel(p->pri);
02943 ast_mutex_unlock(&p->lock);
02944 }
02945 if (p->bearer || (mysig == SIG_FXSKS)) {
02946 if (p->bearer) {
02947 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02948 p->bearer->call = p->call;
02949 } else
02950 ast_debug(1, "I'm being setup with no bearer right now...\n");
02951
02952 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02953 }
02954 p->digital = IS_DIGITAL(ast->transfercapability);
02955
02956 if (p->priexclusive)
02957 exclusive = 1;
02958 else {
02959
02960 if (p->pri->nodetype == PRI_NETWORK)
02961 exclusive = 0;
02962 else
02963 exclusive = 1;
02964 }
02965
02966 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02967 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02968 (p->digital ? -1 :
02969 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02970 if (p->pri->facilityenable)
02971 pri_facility_enable(p->pri->pri);
02972
02973 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02974 dp_strip = 0;
02975 pridialplan = p->pri->dialplan - 1;
02976 if (pridialplan == -2 || pridialplan == -3) {
02977 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02978 if (pridialplan == -2) {
02979 dp_strip = strlen(p->pri->internationalprefix);
02980 }
02981 pridialplan = PRI_INTERNATIONAL_ISDN;
02982 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02983 if (pridialplan == -2) {
02984 dp_strip = strlen(p->pri->nationalprefix);
02985 }
02986 pridialplan = PRI_NATIONAL_ISDN;
02987 } else {
02988 pridialplan = PRI_LOCAL_ISDN;
02989 }
02990 }
02991 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02992 switch (c[p->stripmsd]) {
02993 case 'U':
02994 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02995 break;
02996 case 'I':
02997 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
02998 break;
02999 case 'N':
03000 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03001 break;
03002 case 'L':
03003 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03004 break;
03005 case 'S':
03006 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03007 break;
03008 case 'V':
03009 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03010 break;
03011 case 'R':
03012 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03013 break;
03014 case 'u':
03015 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03016 break;
03017 case 'e':
03018 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03019 break;
03020 case 'x':
03021 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03022 break;
03023 case 'f':
03024 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03025 break;
03026 case 'n':
03027 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03028 break;
03029 case 'p':
03030 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03031 break;
03032 case 'r':
03033 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03034 break;
03035 default:
03036 if (isalpha(c[p->stripmsd])) {
03037 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03038 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03039 }
03040 break;
03041 }
03042 c++;
03043 }
03044 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03045
03046 ldp_strip = 0;
03047 prilocaldialplan = p->pri->localdialplan - 1;
03048 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03049 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03050 if (prilocaldialplan == -2) {
03051 ldp_strip = strlen(p->pri->internationalprefix);
03052 }
03053 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03054 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03055 if (prilocaldialplan == -2) {
03056 ldp_strip = strlen(p->pri->nationalprefix);
03057 }
03058 prilocaldialplan = PRI_NATIONAL_ISDN;
03059 } else {
03060 prilocaldialplan = PRI_LOCAL_ISDN;
03061 }
03062 }
03063 if (l != NULL) {
03064 while (*l > '9' && *l != '*' && *l != '#') {
03065 switch (*l) {
03066 case 'U':
03067 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03068 break;
03069 case 'I':
03070 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03071 break;
03072 case 'N':
03073 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03074 break;
03075 case 'L':
03076 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03077 break;
03078 case 'S':
03079 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03080 break;
03081 case 'V':
03082 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03083 break;
03084 case 'R':
03085 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03086 break;
03087 case 'u':
03088 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03089 break;
03090 case 'e':
03091 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03092 break;
03093 case 'x':
03094 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03095 break;
03096 case 'f':
03097 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03098 break;
03099 case 'n':
03100 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03101 break;
03102 case 'p':
03103 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03104 break;
03105 case 'r':
03106 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03107 break;
03108 default:
03109 if (isalpha(*l)) {
03110 ast_log(LOG_WARNING,
03111 "Unrecognized prilocaldialplan %s modifier: %c\n",
03112 *l > 'Z' ? "NPI" : "TON", *l);
03113 }
03114 break;
03115 }
03116 l++;
03117 }
03118 }
03119 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03120 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03121 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03122 if (!strcasecmp(rr_str, "UNKNOWN"))
03123 redirect_reason = 0;
03124 else if (!strcasecmp(rr_str, "BUSY"))
03125 redirect_reason = 1;
03126 else if (!strcasecmp(rr_str, "NO_REPLY"))
03127 redirect_reason = 2;
03128 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03129 redirect_reason = 15;
03130 else
03131 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03132 } else
03133 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03134 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03135
03136 #ifdef SUPPORT_USERUSER
03137
03138 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03139
03140 if (useruser)
03141 pri_sr_set_useruser(sr, useruser);
03142 #endif
03143
03144 if (pri_setup(p->pri->pri, p->call, sr)) {
03145 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03146 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03147 pri_rel(p->pri);
03148 ast_mutex_unlock(&p->lock);
03149 pri_sr_free(sr);
03150 return -1;
03151 }
03152 pri_sr_free(sr);
03153 ast_setstate(ast, AST_STATE_DIALING);
03154 pri_rel(p->pri);
03155 }
03156 #endif
03157 ast_mutex_unlock(&p->lock);
03158 return 0;
03159 }
03160
03161 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03162 {
03163 struct dahdi_pvt *p = *pvt;
03164
03165 if (p->prev)
03166 p->prev->next = p->next;
03167 if (p->next)
03168 p->next->prev = p->prev;
03169 if (p->use_smdi)
03170 ast_smdi_interface_unref(p->smdi_iface);
03171 if (p->mwi_event_sub)
03172 ast_event_unsubscribe(p->mwi_event_sub);
03173 if (p->vars)
03174 ast_variables_destroy(p->vars);
03175 ast_mutex_destroy(&p->lock);
03176 dahdi_close_sub(p, SUB_REAL);
03177 if (p->owner)
03178 p->owner->tech_pvt = NULL;
03179 free(p);
03180 *pvt = NULL;
03181 }
03182
03183 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03184 {
03185 int owned = 0;
03186 int i = 0;
03187
03188 if (!now) {
03189 if (cur->owner) {
03190 owned = 1;
03191 }
03192
03193 for (i = 0; i < 3; i++) {
03194 if (cur->subs[i].owner) {
03195 owned = 1;
03196 }
03197 }
03198 if (!owned) {
03199 if (prev) {
03200 prev->next = cur->next;
03201 if (prev->next)
03202 prev->next->prev = prev;
03203 else
03204 ifend = prev;
03205 } else {
03206 iflist = cur->next;
03207 if (iflist)
03208 iflist->prev = NULL;
03209 else
03210 ifend = NULL;
03211 }
03212 destroy_dahdi_pvt(&cur);
03213 }
03214 } else {
03215 if (prev) {
03216 prev->next = cur->next;
03217 if (prev->next)
03218 prev->next->prev = prev;
03219 else
03220 ifend = prev;
03221 } else {
03222 iflist = cur->next;
03223 if (iflist)
03224 iflist->prev = NULL;
03225 else
03226 ifend = NULL;
03227 }
03228 destroy_dahdi_pvt(&cur);
03229 }
03230 return 0;
03231 }
03232
03233 static void destroy_all_channels(void)
03234 {
03235 int x;
03236 struct dahdi_pvt *p, *pl;
03237
03238 while (num_restart_pending) {
03239 usleep(1);
03240 }
03241
03242 ast_mutex_lock(&iflock);
03243
03244 p = iflist;
03245 while (p) {
03246
03247 if (p->cidspill)
03248 ast_free(p->cidspill);
03249 pl = p;
03250 p = p->next;
03251 x = pl->channel;
03252
03253 if (pl)
03254 destroy_dahdi_pvt(&pl);
03255 if (option_verbose > 2)
03256 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03257 }
03258 iflist = NULL;
03259 ifcount = 0;
03260 ast_mutex_unlock(&iflock);
03261 }
03262
03263 #ifdef HAVE_PRI
03264 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03265
03266 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03267
03268 static char *dahdi_send_keypad_facility_descrip =
03269 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03270 " IE over the current channel.\n";
03271
03272 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03273 {
03274
03275 struct dahdi_pvt *p;
03276 char *digits = (char *) data;
03277
03278 if (ast_strlen_zero(digits)) {
03279 ast_debug(1, "No digit string sent to application!\n");
03280 return -1;
03281 }
03282
03283 p = (struct dahdi_pvt *)chan->tech_pvt;
03284
03285 if (!p) {
03286 ast_debug(1, "Unable to find technology private\n");
03287 return -1;
03288 }
03289
03290 ast_mutex_lock(&p->lock);
03291
03292 if (!p->pri || !p->call) {
03293 ast_debug(1, "Unable to find pri or call on channel!\n");
03294 ast_mutex_unlock(&p->lock);
03295 return -1;
03296 }
03297
03298 if (!pri_grab(p, p->pri)) {
03299 pri_keypad_facility(p->pri->pri, p->call, digits);
03300 pri_rel(p->pri);
03301 } else {
03302 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03303 ast_mutex_unlock(&p->lock);
03304 return -1;
03305 }
03306
03307 ast_mutex_unlock(&p->lock);
03308
03309 return 0;
03310 }
03311
03312 static int pri_is_up(struct dahdi_pri *pri)
03313 {
03314 int x;
03315 for (x = 0; x < NUM_DCHANS; x++) {
03316 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03317 return 1;
03318 }
03319 return 0;
03320 }
03321
03322 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03323 {
03324 bearer->owner = &inuse;
03325 bearer->realcall = crv;
03326 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03327 if (crv->subs[SUB_REAL].owner)
03328 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03329 crv->bearer = bearer;
03330 crv->call = bearer->call;
03331 crv->pri = pri;
03332 return 0;
03333 }
03334
03335 static char *pri_order(int level)
03336 {
03337 switch (level) {
03338 case 0:
03339 return "Primary";
03340 case 1:
03341 return "Secondary";
03342 case 2:
03343 return "Tertiary";
03344 case 3:
03345 return "Quaternary";
03346 default:
03347 return "<Unknown>";
03348 }
03349 }
03350
03351
03352 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03353 {
03354 int x = -1;
03355
03356 for (x = 0; x < NUM_DCHANS; x++) {
03357 if ((pri->dchans[x] == pri->pri))
03358 break;
03359 }
03360
03361 return pri->fds[x];
03362 }
03363
03364 static int pri_find_dchan(struct dahdi_pri *pri)
03365 {
03366 int oldslot = -1;
03367 struct pri *old;
03368 int newslot = -1;
03369 int x;
03370 old = pri->pri;
03371 for (x = 0; x < NUM_DCHANS; x++) {
03372 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03373 newslot = x;
03374 if (pri->dchans[x] == old) {
03375 oldslot = x;
03376 }
03377 }
03378 if (newslot < 0) {
03379 newslot = 0;
03380 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03381 pri->dchannels[newslot]);
03382 }
03383 if (old && (oldslot != newslot))
03384 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03385 pri->dchannels[oldslot], pri->dchannels[newslot]);
03386 pri->pri = pri->dchans[newslot];
03387 return 0;
03388 }
03389 #endif
03390
03391 static int dahdi_hangup(struct ast_channel *ast)
03392 {
03393 int res;
03394 int idx,x, law;
03395
03396 struct dahdi_pvt *p = ast->tech_pvt;
03397 struct dahdi_pvt *tmp = NULL;
03398 struct dahdi_pvt *prev = NULL;
03399 struct dahdi_params par;
03400
03401 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03402 if (!ast->tech_pvt) {
03403 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03404 return 0;
03405 }
03406
03407 ast_mutex_lock(&p->lock);
03408
03409 idx = dahdi_get_index(ast, p, 1);
03410
03411 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03412 x = 1;
03413 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03414 }
03415
03416 x = 0;
03417 dahdi_confmute(p, 0);
03418 p->muting = 0;
03419 restore_gains(p);
03420 if (p->origcid_num) {
03421 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03422 ast_free(p->origcid_num);
03423 p->origcid_num = NULL;
03424 }
03425 if (p->origcid_name) {
03426 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03427 ast_free(p->origcid_name);
03428 p->origcid_name = NULL;
03429 }
03430 if (p->dsp)
03431 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03432 p->exten[0] = '\0';
03433
03434 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03435 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03436 p->ignoredtmf = 0;
03437
03438 if (idx > -1) {
03439
03440 p->subs[idx].owner = NULL;
03441 p->subs[idx].needanswer = 0;
03442 p->subs[idx].needflash = 0;
03443 p->subs[idx].needringing = 0;
03444 p->subs[idx].needbusy = 0;
03445 p->subs[idx].needcongestion = 0;
03446 p->subs[idx].linear = 0;
03447 p->subs[idx].needcallerid = 0;
03448 p->polarity = POLARITY_IDLE;
03449 dahdi_setlinear(p->subs[idx].dfd, 0);
03450 if (idx == SUB_REAL) {
03451 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03452 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03453 if (p->subs[SUB_CALLWAIT].inthreeway) {
03454
03455 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03456
03457 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03458 unalloc_sub(p, SUB_CALLWAIT);
03459 p->owner = NULL;
03460 } else {
03461
03462 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03463 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03464 unalloc_sub(p, SUB_THREEWAY);
03465 if (p->subs[SUB_REAL].inthreeway) {
03466
03467
03468 ast_debug(1, "Call was complete, setting owner to former third call\n");
03469 p->owner = p->subs[SUB_REAL].owner;
03470 } else {
03471
03472 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03473 p->owner = NULL;
03474 }
03475 p->subs[SUB_REAL].inthreeway = 0;
03476 }
03477 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03478
03479 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03480 unalloc_sub(p, SUB_CALLWAIT);
03481 p->owner = p->subs[SUB_REAL].owner;
03482 if (p->owner->_state != AST_STATE_UP)
03483 p->subs[SUB_REAL].needanswer = 1;
03484 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03485 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03486 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03487 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03488 unalloc_sub(p, SUB_THREEWAY);
03489 if (p->subs[SUB_REAL].inthreeway) {
03490
03491
03492 ast_debug(1, "Call was complete, setting owner to former third call\n");
03493 p->owner = p->subs[SUB_REAL].owner;
03494 } else {
03495
03496 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03497 p->owner = NULL;
03498 }
03499 p->subs[SUB_REAL].inthreeway = 0;
03500 }
03501 } else if (idx == SUB_CALLWAIT) {
03502
03503 if (p->subs[SUB_CALLWAIT].inthreeway) {
03504
03505
03506 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03507 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03508 S_OR(p->mohsuggest, NULL),
03509 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03510 }
03511 p->subs[SUB_THREEWAY].inthreeway = 0;
03512
03513 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03514 unalloc_sub(p, SUB_THREEWAY);
03515 } else
03516 unalloc_sub(p, SUB_CALLWAIT);
03517 } else if (idx == SUB_THREEWAY) {
03518 if (p->subs[SUB_CALLWAIT].inthreeway) {
03519
03520
03521 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03522 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03523 S_OR(p->mohsuggest, NULL),
03524 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03525 }
03526 p->subs[SUB_CALLWAIT].inthreeway = 0;
03527 }
03528 p->subs[SUB_REAL].inthreeway = 0;
03529
03530
03531 unalloc_sub(p, SUB_THREEWAY);
03532 } else {
03533
03534 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03535 }
03536 }
03537
03538 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03539 p->owner = NULL;
03540 p->ringt = 0;
03541 p->distinctivering = 0;
03542 p->confirmanswer = 0;
03543 p->cidrings = 1;
03544 p->outgoing = 0;
03545 p->digital = 0;
03546 p->faxhandled = 0;
03547 p->pulsedial = 0;
03548 p->onhooktime = time(NULL);
03549 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03550 p->proceeding = 0;
03551 p->dialing = 0;
03552 p->progress = 0;
03553 p->alerting = 0;
03554 p->setup_ack = 0;
03555 p->rlt = 0;
03556 #endif
03557 if (p->dsp) {
03558 ast_dsp_free(p->dsp);
03559 p->dsp = NULL;
03560 }
03561
03562 law = DAHDI_LAW_DEFAULT;
03563 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03564 if (res < 0)
03565 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03566
03567 #ifdef HAVE_SS7
03568 if (p->ss7) {
03569 if (p->ss7call) {
03570 if (!ss7_grab(p, p->ss7)) {
03571 if (!p->alreadyhungup) {
03572 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03573 int icause = ast->hangupcause ? ast->hangupcause : -1;
03574
03575 if (cause) {
03576 if (atoi(cause))
03577 icause = atoi(cause);
03578 }
03579 isup_rel(p->ss7->ss7, p->ss7call, icause);
03580 ss7_rel(p->ss7);
03581 p->alreadyhungup = 1;
03582 } else
03583 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03584 } else {
03585 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03586 res = -1;
03587 }
03588 }
03589 }
03590 #endif
03591 #ifdef HAVE_PRI
03592 if (p->pri) {
03593 #ifdef SUPPORT_USERUSER
03594 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03595 #endif
03596
03597
03598 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03599 if (!pri_grab(p, p->pri)) {
03600 if (p->alreadyhungup) {
03601 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
03602
03603 #ifdef SUPPORT_USERUSER
03604 pri_call_set_useruser(p->call, useruser);
03605 #endif
03606
03607 pri_hangup(p->pri->pri, p->call, -1);
03608 p->call = NULL;
03609 if (p->bearer)
03610 p->bearer->call = NULL;
03611 } else {
03612 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03613 int icause = ast->hangupcause ? ast->hangupcause : -1;
03614 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03615
03616 #ifdef SUPPORT_USERUSER
03617 pri_call_set_useruser(p->call, useruser);
03618 #endif
03619
03620 p->alreadyhungup = 1;
03621 if (p->bearer)
03622 p->bearer->alreadyhungup = 1;
03623 if (cause) {
03624 if (atoi(cause))
03625 icause = atoi(cause);
03626 }
03627 pri_hangup(p->pri->pri, p->call, icause);
03628 }
03629 if (res < 0)
03630 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03631 pri_rel(p->pri);
03632 } else {
03633 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03634 res = -1;
03635 }
03636 } else {
03637 if (p->bearer)
03638 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03639 p->call = NULL;
03640 res = 0;
03641 }
03642 }
03643 #endif
03644 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03645 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03646 if (res < 0) {
03647 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03648 }
03649 switch (p->sig) {
03650 case SIG_FXOGS:
03651 case SIG_FXOLS:
03652 case SIG_FXOKS:
03653 memset(&par, 0, sizeof(par));
03654 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03655 if (!res) {
03656 #if 0
03657 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03658 #endif
03659
03660 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03661 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03662 else
03663 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03664 }
03665 break;
03666 case SIG_FXSGS:
03667 case SIG_FXSLS:
03668 case SIG_FXSKS:
03669
03670
03671 if (ast->_state != AST_STATE_RESERVED) {
03672 time(&p->guardtime);
03673 p->guardtime += 2;
03674 }
03675 break;
03676 default:
03677 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03678 }
03679 if (p->cidspill)
03680 ast_free(p->cidspill);
03681 if (p->sig)
03682 dahdi_disable_ec(p);
03683 x = 0;
03684 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03685 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03686 p->didtdd = 0;
03687 p->cidspill = NULL;
03688 p->callwaitcas = 0;
03689 p->callwaiting = p->permcallwaiting;
03690 p->hidecallerid = p->permhidecallerid;
03691 p->dialing = 0;
03692 p->rdnis[0] = '\0';
03693 update_conf(p);
03694 reset_conf(p);
03695
03696 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03697 x = 0;
03698 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03699 }
03700 #ifdef HAVE_PRI
03701 if (p->bearer) {
03702 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03703
03704
03705 update_conf(p->bearer);
03706 reset_conf(p->bearer);
03707 p->bearer->owner = NULL;
03708 p->bearer->realcall = NULL;
03709 p->bearer = NULL;
03710 p->subs[SUB_REAL].dfd = -1;
03711 p->pri = NULL;
03712 }
03713 #endif
03714 if (num_restart_pending == 0)
03715 restart_monitor();
03716 }
03717
03718 p->callwaitingrepeat = 0;
03719 p->cidcwexpire = 0;
03720 p->oprmode = 0;
03721 ast->tech_pvt = NULL;
03722 ast_mutex_unlock(&p->lock);
03723 ast_module_unref(ast_module_info->self);
03724 ast_verb(3, "Hungup '%s'\n", ast->name);
03725
03726 ast_mutex_lock(&iflock);
03727
03728 if (p->restartpending) {
03729 num_restart_pending--;
03730 }
03731
03732 tmp = iflist;
03733 prev = NULL;
03734 if (p->destroy) {
03735 while (tmp) {
03736 if (tmp == p) {
03737 destroy_channel(prev, tmp, 0);
03738 break;
03739 } else {
03740 prev = tmp;
03741 tmp = tmp->next;
03742 }
03743 }
03744 }
03745 ast_mutex_unlock(&iflock);
03746 return 0;
03747 }
03748
03749 static int dahdi_answer(struct ast_channel *ast)
03750 {
03751 struct dahdi_pvt *p = ast->tech_pvt;
03752 int res = 0;
03753 int idx;
03754 int oldstate = ast->_state;
03755 ast_setstate(ast, AST_STATE_UP);
03756 ast_mutex_lock(&p->lock);
03757 idx = dahdi_get_index(ast, p, 0);
03758 if (idx < 0)
03759 idx = SUB_REAL;
03760
03761 if ((p->radio || (p->oprmode < 0))) {
03762 ast_mutex_unlock(&p->lock);
03763 return 0;
03764 }
03765 switch (p->sig) {
03766 case SIG_FXSLS:
03767 case SIG_FXSGS:
03768 case SIG_FXSKS:
03769 p->ringt = 0;
03770
03771 case SIG_EM:
03772 case SIG_EM_E1:
03773 case SIG_EMWINK:
03774 case SIG_FEATD:
03775 case SIG_FEATDMF:
03776 case SIG_FEATDMF_TA:
03777 case SIG_E911:
03778 case SIG_FGC_CAMA:
03779 case SIG_FGC_CAMAMF:
03780 case SIG_FEATB:
03781 case SIG_SF:
03782 case SIG_SFWINK:
03783 case SIG_SF_FEATD:
03784 case SIG_SF_FEATDMF:
03785 case SIG_SF_FEATB:
03786 case SIG_FXOLS:
03787 case SIG_FXOGS:
03788 case SIG_FXOKS:
03789
03790 ast_debug(1, "Took %s off hook\n", ast->name);
03791 if (p->hanguponpolarityswitch) {
03792 p->polaritydelaytv = ast_tvnow();
03793 }
03794 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03795 tone_zone_play_tone(p->subs[idx].dfd, -1);
03796 p->dialing = 0;
03797 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03798 if (oldstate == AST_STATE_RINGING) {
03799 ast_debug(1, "Finally swapping real and threeway\n");
03800 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03801 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03802 p->owner = p->subs[SUB_REAL].owner;
03803 }
03804 }
03805 if (p->sig & __DAHDI_SIG_FXS) {
03806 dahdi_enable_ec(p);
03807 dahdi_train_ec(p);
03808 }
03809 break;
03810 #ifdef HAVE_PRI
03811 case SIG_BRI:
03812 case SIG_BRI_PTMP:
03813 case SIG_PRI:
03814
03815 if (!pri_grab(p, p->pri)) {
03816 p->proceeding = 1;
03817 p->dialing = 0;
03818 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03819 pri_rel(p->pri);
03820 } else {
03821 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03822 res = -1;
03823 }
03824 break;
03825 #endif
03826 #ifdef HAVE_SS7
03827 case SIG_SS7:
03828 if (!ss7_grab(p, p->ss7)) {
03829 p->proceeding = 1;
03830 res = isup_anm(p->ss7->ss7, p->ss7call);
03831 ss7_rel(p->ss7);
03832 } else {
03833 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03834 res = -1;
03835 }
03836 break;
03837 #endif
03838 case 0:
03839 ast_mutex_unlock(&p->lock);
03840 return 0;
03841 default:
03842 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03843 res = -1;
03844 }
03845 ast_mutex_unlock(&p->lock);
03846 return res;
03847 }
03848
03849 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03850 {
03851 char *cp;
03852 signed char *scp;
03853 int x;
03854 int idx;
03855 struct dahdi_pvt *p = chan->tech_pvt, *pp;
03856 struct oprmode *oprmode;
03857
03858
03859
03860 if (!data || (datalen < 1)) {
03861 errno = EINVAL;
03862 return -1;
03863 }
03864
03865 switch (option) {
03866 case AST_OPTION_TXGAIN:
03867 scp = (signed char *) data;
03868 idx = dahdi_get_index(chan, p, 0);
03869 if (idx < 0) {
03870 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03871 return -1;
03872 }
03873 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03874 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
03875 case AST_OPTION_RXGAIN:
03876 scp = (signed char *) data;
03877 idx = dahdi_get_index(chan, p, 0);
03878 if (idx < 0) {
03879 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03880 return -1;
03881 }
03882 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03883 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
03884 case AST_OPTION_TONE_VERIFY:
03885 if (!p->dsp)
03886 break;
03887 cp = (char *) data;
03888 switch (*cp) {
03889 case 1:
03890 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03891 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
03892 break;
03893 case 2:
03894 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03895 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
03896 break;
03897 default:
03898 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03899 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03900 break;
03901 }
03902 break;
03903 case AST_OPTION_TDD:
03904
03905 cp = (char *) data;
03906 p->mate = 0;
03907 if (!*cp) {
03908 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03909 if (p->tdd)
03910 tdd_free(p->tdd);
03911 p->tdd = 0;
03912 break;
03913 }
03914 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03915 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03916 dahdi_disable_ec(p);
03917
03918 if (!p->didtdd) {
03919 unsigned char mybuf[41000];
03920 unsigned char *buf;
03921 int size, res, fd, len;
03922 struct pollfd fds[1];
03923
03924 buf = mybuf;
03925 memset(buf, 0x7f, sizeof(mybuf));
03926 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03927 len = 40000;
03928 idx = dahdi_get_index(chan, p, 0);
03929 if (idx < 0) {
03930 ast_log(LOG_WARNING, "No index in TDD?\n");
03931 return -1;
03932 }
03933 fd = p->subs[idx].dfd;
03934 while (len) {
03935 if (ast_check_hangup(chan))
03936 return -1;
03937 size = len;
03938 if (size > READ_SIZE)
03939 size = READ_SIZE;
03940 fds[0].fd = fd;
03941 fds[0].events = POLLPRI | POLLOUT;
03942 fds[0].revents = 0;
03943 res = poll(fds, 1, -1);
03944 if (!res) {
03945 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03946 continue;
03947 }
03948
03949 if (fds[0].revents & POLLPRI)
03950 return -1;
03951 if (!(fds[0].revents & POLLOUT)) {
03952 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03953 continue;
03954 }
03955 res = write(fd, buf, size);
03956 if (res != size) {
03957 if (res == -1) return -1;
03958 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03959 break;
03960 }
03961 len -= size;
03962 buf += size;
03963 }
03964 p->didtdd = 1;
03965 }
03966 if (*cp == 2) {
03967 if (p->tdd)
03968 tdd_free(p->tdd);
03969 p->tdd = 0;
03970 p->mate = 1;
03971 break;
03972 }
03973 if (!p->tdd) {
03974 p->tdd = tdd_new();
03975 }
03976 break;
03977 case AST_OPTION_RELAXDTMF:
03978 if (!p->dsp)
03979 break;
03980 cp = (char *) data;
03981 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03982 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03983 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03984 break;
03985 case AST_OPTION_AUDIO_MODE:
03986 cp = (char *) data;
03987 if (!*cp) {
03988 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03989 x = 0;
03990 dahdi_disable_ec(p);
03991 } else {
03992 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03993 x = 1;
03994 }
03995 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03996 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03997 break;
03998 case AST_OPTION_OPRMODE:
03999 oprmode = (struct oprmode *) data;
04000 pp = oprmode->peer->tech_pvt;
04001 p->oprmode = pp->oprmode = 0;
04002
04003 p->oprpeer = pp;
04004 pp->oprpeer = p;
04005
04006 if (oprmode->mode)
04007 {
04008 pp->oprmode = oprmode->mode;
04009 p->oprmode = -oprmode->mode;
04010 }
04011 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
04012 oprmode->mode, chan->name,oprmode->peer->name);
04013 break;
04014 case AST_OPTION_ECHOCAN:
04015 cp = (char *) data;
04016 if (*cp) {
04017 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
04018 dahdi_enable_ec(p);
04019 } else {
04020 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
04021 dahdi_disable_ec(p);
04022 }
04023 break;
04024 }
04025 errno = 0;
04026
04027 return 0;
04028 }
04029
04030 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
04031 {
04032 struct dahdi_pvt *p = chan->tech_pvt;
04033
04034 if (!strcasecmp(data, "rxgain")) {
04035 ast_mutex_lock(&p->lock);
04036 snprintf(buf, len, "%f", p->rxgain);
04037 ast_mutex_unlock(&p->lock);
04038 } else if (!strcasecmp(data, "txgain")) {
04039 ast_mutex_lock(&p->lock);
04040 snprintf(buf, len, "%f", p->txgain);
04041 ast_mutex_unlock(&p->lock);
04042 } else {
04043 ast_copy_string(buf, "", len);
04044 }
04045 return 0;
04046 }
04047
04048
04049 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04050 {
04051
04052 int x;
04053 int hasslaves;
04054 if (!master)
04055 return;
04056 if (needlock) {
04057 ast_mutex_lock(&master->lock);
04058 if (slave) {
04059 while (ast_mutex_trylock(&slave->lock)) {
04060 DEADLOCK_AVOIDANCE(&master->lock);
04061 }
04062 }
04063 }
04064 hasslaves = 0;
04065 for (x = 0; x < MAX_SLAVES; x++) {
04066 if (master->slaves[x]) {
04067 if (!slave || (master->slaves[x] == slave)) {
04068
04069 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04070 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04071 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04072 master->slaves[x]->master = NULL;
04073 master->slaves[x] = NULL;
04074 } else
04075 hasslaves = 1;
04076 }
04077 if (!hasslaves)
04078 master->inconference = 0;
04079 }
04080 if (!slave) {
04081 if (master->master) {
04082
04083 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04084 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04085 hasslaves = 0;
04086 for (x = 0; x < MAX_SLAVES; x++) {
04087 if (master->master->slaves[x] == master)
04088 master->master->slaves[x] = NULL;
04089 else if (master->master->slaves[x])
04090 hasslaves = 1;
04091 }
04092 if (!hasslaves)
04093 master->master->inconference = 0;
04094 }
04095 master->master = NULL;
04096 }
04097 update_conf(master);
04098 if (needlock) {
04099 if (slave)
04100 ast_mutex_unlock(&slave->lock);
04101 ast_mutex_unlock(&master->lock);
04102 }
04103 }
04104
04105 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04106 int x;
04107 if (!slave || !master) {
04108 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04109 return;
04110 }
04111 for (x = 0; x < MAX_SLAVES; x++) {
04112 if (!master->slaves[x]) {
04113 master->slaves[x] = slave;
04114 break;
04115 }
04116 }
04117 if (x >= MAX_SLAVES) {
04118 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04119 master->slaves[MAX_SLAVES - 1] = slave;
04120 }
04121 if (slave->master)
04122 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04123 slave->master = master;
04124
04125 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04126 }
04127
04128 static void disable_dtmf_detect(struct dahdi_pvt *p)
04129 {
04130 int val;
04131
04132 p->ignoredtmf = 1;
04133
04134 val = 0;
04135 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04136
04137 if (!p->hardwaredtmf && p->dsp) {
04138 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
04139 ast_dsp_set_features(p->dsp, p->dsp_features);
04140 }
04141 }
04142
04143 static void enable_dtmf_detect(struct dahdi_pvt *p)
04144 {
04145 int val;
04146
04147 if (p->channel == CHAN_PSEUDO)
04148 return;
04149
04150 p->ignoredtmf = 0;
04151
04152 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04153 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04154
04155 if (!p->hardwaredtmf && p->dsp) {
04156 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
04157 ast_dsp_set_features(p->dsp, p->dsp_features);
04158 }
04159 }
04160
04161 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)
04162 {
04163 struct ast_channel *who;
04164 struct dahdi_pvt *p0, *p1, *op0, *op1;
04165 struct dahdi_pvt *master = NULL, *slave = NULL;
04166 struct ast_frame *f;
04167 int inconf = 0;
04168 int nothingok = 1;
04169 int ofd0, ofd1;
04170 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04171 int os0 = -1, os1 = -1;
04172 int priority = 0;
04173 struct ast_channel *oc0, *oc1;
04174 enum ast_bridge_result res;
04175
04176 #ifdef PRI_2BCT
04177 int triedtopribridge = 0;
04178 q931_call *q931c0 = NULL, *q931c1 = NULL;
04179 #endif
04180
04181
04182
04183
04184
04185
04186 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04187 return AST_BRIDGE_FAILED_NOWARN;
04188
04189 ast_channel_lock(c0);
04190 while (ast_channel_trylock(c1)) {
04191 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04192 }
04193
04194 p0 = c0->tech_pvt;
04195 p1 = c1->tech_pvt;
04196
04197 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04198 ast_channel_unlock(c0);
04199 ast_channel_unlock(c1);
04200 return AST_BRIDGE_FAILED_NOWARN;
04201 }
04202
04203 oi0 = dahdi_get_index(c0, p0, 0);
04204 oi1 = dahdi_get_index(c1, p1, 0);
04205 if ((oi0 < 0) || (oi1 < 0)) {
04206 ast_channel_unlock(c0);
04207 ast_channel_unlock(c1);
04208 return AST_BRIDGE_FAILED;
04209 }
04210
04211 op0 = p0 = c0->tech_pvt;
04212 op1 = p1 = c1->tech_pvt;
04213 ofd0 = c0->fds[0];
04214 ofd1 = c1->fds[0];
04215 oc0 = p0->owner;
04216 oc1 = p1->owner;
04217
04218 if (ast_mutex_trylock(&p0->lock)) {
04219
04220 ast_channel_unlock(c0);
04221 ast_channel_unlock(c1);
04222 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04223 return AST_BRIDGE_RETRY;
04224 }
04225 if (ast_mutex_trylock(&p1->lock)) {
04226
04227 ast_mutex_unlock(&p0->lock);
04228 ast_channel_unlock(c0);
04229 ast_channel_unlock(c1);
04230 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04231 return AST_BRIDGE_RETRY;
04232 }
04233
04234 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04235 if (p0->owner && p1->owner) {
04236
04237 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04238 master = p0;
04239 slave = p1;
04240 inconf = 1;
04241 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04242 master = p1;
04243 slave = p0;
04244 inconf = 1;
04245 } else {
04246 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04247 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04248 p0->channel,
04249 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04250 p0->subs[SUB_REAL].inthreeway, p0->channel,
04251 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04252 p1->subs[SUB_REAL].inthreeway);
04253 }
04254 nothingok = 0;
04255 }
04256 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04257 if (p1->subs[SUB_THREEWAY].inthreeway) {
04258 master = p1;
04259 slave = p0;
04260 nothingok = 0;
04261 }
04262 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04263 if (p0->subs[SUB_THREEWAY].inthreeway) {
04264 master = p0;
04265 slave = p1;
04266 nothingok = 0;
04267 }
04268 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04269
04270
04271 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04272 master = p1;
04273 slave = p0;
04274 nothingok = 0;
04275 }
04276 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04277
04278 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04279 master = p0;
04280 slave = p1;
04281 nothingok = 0;
04282 }
04283 }
04284 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04285 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04286 if (master && slave) {
04287
04288
04289
04290 if ((oi1 == SUB_THREEWAY) &&
04291 p1->subs[SUB_THREEWAY].inthreeway &&
04292 p1->subs[SUB_REAL].owner &&
04293 p1->subs[SUB_REAL].inthreeway &&
04294 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04295 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04296 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04297 os1 = p1->subs[SUB_REAL].owner->_state;
04298 } else {
04299 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04300 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04301 }
04302 if ((oi0 == SUB_THREEWAY) &&
04303 p0->subs[SUB_THREEWAY].inthreeway &&
04304 p0->subs[SUB_REAL].owner &&
04305 p0->subs[SUB_REAL].inthreeway &&
04306 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04307 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04308 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04309 os0 = p0->subs[SUB_REAL].owner->_state;
04310 } else {
04311 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04312 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04313 }
04314 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04315 if (!p0->echocanbridged || !p1->echocanbridged) {
04316
04317 dahdi_disable_ec(p0);
04318 dahdi_disable_ec(p1);
04319 }
04320 }
04321 dahdi_link(slave, master);
04322 master->inconference = inconf;
04323 } else if (!nothingok)
04324 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04325
04326 update_conf(p0);
04327 update_conf(p1);
04328 t0 = p0->subs[SUB_REAL].inthreeway;
04329 t1 = p1->subs[SUB_REAL].inthreeway;
04330
04331 ast_mutex_unlock(&p0->lock);
04332 ast_mutex_unlock(&p1->lock);
04333
04334 ast_channel_unlock(c0);
04335 ast_channel_unlock(c1);
04336
04337
04338 if ((!master || !slave) && !nothingok) {
04339 dahdi_enable_ec(p0);
04340 dahdi_enable_ec(p1);
04341 return AST_BRIDGE_FAILED;
04342 }
04343
04344 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04345
04346 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04347 disable_dtmf_detect(op0);
04348
04349 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04350 disable_dtmf_detect(op1);
04351
04352 for (;;) {
04353 struct ast_channel *c0_priority[2] = {c0, c1};
04354 struct ast_channel *c1_priority[2] = {c1, c0};
04355
04356
04357
04358
04359 ast_channel_lock(c0);
04360 while (ast_channel_trylock(c1)) {
04361 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04362 }
04363
04364 p0 = c0->tech_pvt;
04365 p1 = c1->tech_pvt;
04366
04367 if (op0 == p0)
04368 i0 = dahdi_get_index(c0, p0, 1);
04369 if (op1 == p1)
04370 i1 = dahdi_get_index(c1, p1, 1);
04371
04372 ast_channel_unlock(c0);
04373 ast_channel_unlock(c1);
04374
04375 if (!timeoutms ||
04376 (op0 != p0) ||
04377 (op1 != p1) ||
04378 (ofd0 != c0->fds[0]) ||
04379 (ofd1 != c1->fds[0]) ||
04380 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04381 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04382 (oc0 != p0->owner) ||
04383 (oc1 != p1->owner) ||
04384 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04385 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04386 (oi0 != i0) ||
04387 (oi1 != i1)) {
04388 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04389 op0->channel, oi0, op1->channel, oi1);
04390 res = AST_BRIDGE_RETRY;
04391 goto return_from_bridge;
04392 }
04393
04394 #ifdef PRI_2BCT
04395 q931c0 = p0->call;
04396 q931c1 = p1->call;
04397 if (p0->transfer && p1->transfer
04398 && q931c0 && q931c1
04399 && !triedtopribridge) {
04400 pri_channel_bridge(q931c0, q931c1);
04401 triedtopribridge = 1;
04402 }
04403 #endif
04404
04405 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04406 if (!who) {
04407 ast_debug(1, "Ooh, empty read...\n");
04408 continue;
04409 }
04410 f = ast_read(who);
04411 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04412 *fo = f;
04413 *rc = who;
04414 res = AST_BRIDGE_COMPLETE;
04415 goto return_from_bridge;
04416 }
04417 if (f->frametype == AST_FRAME_DTMF) {
04418 if ((who == c0) && p0->pulsedial) {
04419 ast_write(c1, f);
04420 } else if ((who == c1) && p1->pulsedial) {
04421 ast_write(c0, f);
04422 } else {
04423 *fo = f;
04424 *rc = who;
04425 res = AST_BRIDGE_COMPLETE;
04426 goto return_from_bridge;
04427 }
04428 }
04429 ast_frfree(f);
04430
04431
04432 priority = !priority;
04433 }
04434
04435 return_from_bridge:
04436 if (op0 == p0)
04437 dahdi_enable_ec(p0);
04438
04439 if (op1 == p1)
04440 dahdi_enable_ec(p1);
04441
04442 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04443 enable_dtmf_detect(op0);
04444
04445 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04446 enable_dtmf_detect(op1);
04447
04448 dahdi_unlink(slave, master, 1);
04449
04450 return res;
04451 }
04452
04453 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04454 {
04455 struct dahdi_pvt *p = newchan->tech_pvt;
04456 int x;
04457 ast_mutex_lock(&p->lock);
04458 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04459 if (p->owner == oldchan) {
04460 p->owner = newchan;
04461 }
04462 for (x = 0; x < 3; x++)
04463 if (p->subs[x].owner == oldchan) {
04464 if (!x)
04465 dahdi_unlink(NULL, p, 0);
04466 p->subs[x].owner = newchan;
04467 }
04468 if (newchan->_state == AST_STATE_RINGING)
04469 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04470 update_conf(p);
04471 ast_mutex_unlock(&p->lock);
04472 return 0;
04473 }
04474
04475 static int dahdi_ring_phone(struct dahdi_pvt *p)
04476 {
04477 int x;
04478 int res;
04479
04480 x = 0;
04481 x = DAHDI_ONHOOK;
04482 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04483 do {
04484 x = DAHDI_RING;
04485 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04486 if (res) {
04487 switch (errno) {
04488 case EBUSY:
04489 case EINTR:
04490
04491 usleep(10000);
04492 continue;
04493 case EINPROGRESS:
04494 res = 0;
04495 break;
04496 default:
04497 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04498 res = 0;
04499 }
04500 }
04501 } while (res);
04502 return res;
04503 }
04504
04505 static void *ss_thread(void *data);
04506
04507 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
04508
04509 static int attempt_transfer(struct dahdi_pvt *p)
04510 {
04511
04512
04513
04514 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04515
04516
04517 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04518 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04519 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04520 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04521 }
04522 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04523 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04524 }
04525 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04526 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04527 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04528 return -1;
04529 }
04530
04531 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04532 unalloc_sub(p, SUB_THREEWAY);
04533 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04534 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04535 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04536 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04537 }
04538 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04539 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04540 }
04541 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04542 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04543 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04544 return -1;
04545 }
04546
04547 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04548 ast_channel_unlock(p->subs[SUB_REAL].owner);
04549 unalloc_sub(p, SUB_THREEWAY);
04550
04551 return 1;
04552 } else {
04553 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04554 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04555 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04556 return -1;
04557 }
04558 return 0;
04559 }
04560
04561 static int check_for_conference(struct dahdi_pvt *p)
04562 {
04563 struct dahdi_confinfo ci;
04564
04565 if (p->master || (p->confno > -1))
04566 return 0;
04567 memset(&ci, 0, sizeof(ci));
04568 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04569 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04570 return 0;
04571 }
04572
04573
04574
04575 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04576 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04577 return 1;
04578 }
04579 return 0;
04580 }
04581
04582
04583
04584
04585
04586
04587 static int get_alarms(struct dahdi_pvt *p)
04588 {
04589 int res;
04590 struct dahdi_spaninfo zi;
04591 struct dahdi_params params;
04592
04593 memset(&zi, 0, sizeof(zi));
04594 zi.spanno = p->span;
04595
04596 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04597 if (zi.alarms != DAHDI_ALARM_NONE)
04598 return zi.alarms;
04599 } else {
04600 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04601 return 0;
04602 }
04603
04604
04605 memset(¶ms, 0, sizeof(params));
04606 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04607 return params.chan_alarms;
04608
04609 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04610
04611 return DAHDI_ALARM_NONE;
04612 }
04613
04614 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
04615 {
04616 struct dahdi_pvt *p = ast->tech_pvt;
04617 struct ast_frame *f = *dest;
04618
04619 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04620
04621 if (p->confirmanswer) {
04622 ast_debug(1, "Confirm answer on %s!\n", ast->name);
04623
04624
04625 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04626 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04627 *dest = &p->subs[idx].f;
04628
04629 p->confirmanswer = 0;
04630 } else if (p->callwaitcas) {
04631 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04632 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04633 if (p->cidspill)
04634 ast_free(p->cidspill);
04635 send_cwcidspill(p);
04636 }
04637 p->callwaitcas = 0;
04638 p->subs[idx].f.frametype = AST_FRAME_NULL;
04639 p->subs[idx].f.subclass = 0;
04640 *dest = &p->subs[idx].f;
04641 } else if (f->subclass == 'f') {
04642
04643 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04644 p->faxhandled = 1;
04645 if (strcmp(ast->exten, "fax")) {
04646 const char *target_context = S_OR(ast->macrocontext, ast->context);
04647
04648
04649
04650
04651
04652 ast_mutex_unlock(&p->lock);
04653 ast_channel_unlock(ast);
04654 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04655 ast_channel_lock(ast);
04656 ast_mutex_lock(&p->lock);
04657 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04658
04659 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04660 if (ast_async_goto(ast, target_context, "fax", 1))
04661 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04662 } else {
04663 ast_channel_lock(ast);
04664 ast_mutex_lock(&p->lock);
04665 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04666 }
04667 } else {
04668 ast_debug(1, "Already in a fax extension, not redirecting\n");
04669 }
04670 } else {
04671 ast_debug(1, "Fax already handled\n");
04672 }
04673 dahdi_confmute(p, 0);
04674 p->subs[idx].f.frametype = AST_FRAME_NULL;
04675 p->subs[idx].f.subclass = 0;
04676 *dest = &p->subs[idx].f;
04677 }
04678 }
04679
04680 static void handle_alarms(struct dahdi_pvt *p, int alms)
04681 {
04682 const char *alarm_str = alarm2str(alms);
04683
04684 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04685 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04686 "Alarm: %s\r\n"
04687 "Channel: %d\r\n",
04688 alarm_str, p->channel);
04689 }
04690
04691 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04692 {
04693 int res, x;
04694 int idx, mysig;
04695 char *c;
04696 struct dahdi_pvt *p = ast->tech_pvt;
04697 pthread_t threadid;
04698 struct ast_channel *chan;
04699 struct ast_frame *f;
04700
04701 idx = dahdi_get_index(ast, p, 0);
04702 mysig = p->sig;
04703 if (p->outsigmod > -1)
04704 mysig = p->outsigmod;
04705 p->subs[idx].f.frametype = AST_FRAME_NULL;
04706 p->subs[idx].f.subclass = 0;
04707 p->subs[idx].f.datalen = 0;
04708 p->subs[idx].f.samples = 0;
04709 p->subs[idx].f.mallocd = 0;
04710 p->subs[idx].f.offset = 0;
04711 p->subs[idx].f.src = "dahdi_handle_event";
04712 p->subs[idx].f.data.ptr = NULL;
04713 f = &p->subs[idx].f;
04714
04715 if (idx < 0)
04716 return &p->subs[idx].f;
04717 if (p->fake_event) {
04718 res = p->fake_event;
04719 p->fake_event = 0;
04720 } else
04721 res = dahdi_get_event(p->subs[idx].dfd);
04722
04723 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
04724
04725 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04726 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04727 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04728 #ifdef HAVE_PRI
04729 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04730
04731 } else {
04732 #endif
04733 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
04734 p->subs[idx].f.subclass = res & 0xff;
04735 #ifdef HAVE_PRI
04736 }
04737 #endif
04738 dahdi_handle_dtmfup(ast, idx, &f);
04739 return f;
04740 }
04741
04742 if (res & DAHDI_EVENT_DTMFDOWN) {
04743 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04744
04745 dahdi_confmute(p, 1);
04746 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
04747 p->subs[idx].f.subclass = res & 0xff;
04748 return &p->subs[idx].f;
04749 }
04750
04751 switch (res) {
04752 case DAHDI_EVENT_EC_DISABLED:
04753 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04754 p->echocanon = 0;
04755 break;
04756 case DAHDI_EVENT_BITSCHANGED:
04757 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04758 case DAHDI_EVENT_PULSE_START:
04759
04760 if (!ast->pbx)
04761 tone_zone_play_tone(p->subs[idx].dfd, -1);
04762 break;
04763 case DAHDI_EVENT_DIALCOMPLETE:
04764 if (p->inalarm) break;
04765 if ((p->radio || (p->oprmode < 0))) break;
04766 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
04767 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04768 return NULL;
04769 }
04770 if (!x) {
04771 dahdi_enable_ec(p);
04772 if (p->echobreak) {
04773 dahdi_train_ec(p);
04774 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04775 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04776 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04777 p->echobreak = 0;
04778 } else {
04779 p->dialing = 0;
04780 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04781
04782 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04783 ast_setstate(ast, AST_STATE_UP);
04784 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04785 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04786 break;
04787 } else {
04788
04789 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04790 }
04791 }
04792 if (ast->_state == AST_STATE_DIALING) {
04793 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04794 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04795 } 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)))) {
04796 ast_setstate(ast, AST_STATE_RINGING);
04797 } else if (!p->answeronpolarityswitch) {
04798 ast_setstate(ast, AST_STATE_UP);
04799 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04800 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04801
04802 p->polarity = POLARITY_REV;
04803 } else {
04804
04805 p->polarity = POLARITY_IDLE;
04806 }
04807 }
04808 }
04809 }
04810 break;
04811 case DAHDI_EVENT_ALARM:
04812 #ifdef HAVE_PRI
04813 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04814 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04815
04816 if (p->call) {
04817 if (p->pri && p->pri->pri) {
04818 if (!pri_grab(p, p->pri)) {
04819 pri_hangup(p->pri->pri, p->call, -1);
04820 pri_destroycall(p->pri->pri, p->call);
04821 p->call = NULL;
04822 pri_rel(p->pri);
04823 } else
04824 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04825 } else
04826 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04827 }
04828 if (p->owner)
04829 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04830 }
04831 }
04832 if (p->bearer)
04833 p->bearer->inalarm = 1;
04834 else
04835 #endif
04836 p->inalarm = 1;
04837 res = get_alarms(p);
04838 handle_alarms(p, res);
04839 #ifdef HAVE_PRI
04840 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04841
04842 } else {
04843 break;
04844 }
04845 #endif
04846 #ifdef HAVE_SS7
04847 if (p->sig == SIG_SS7)
04848 break;
04849 #endif
04850 case DAHDI_EVENT_ONHOOK:
04851 if (p->radio) {
04852 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04853 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
04854 break;
04855 }
04856 if (p->oprmode < 0)
04857 {
04858 if (p->oprmode != -1) break;
04859 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04860 {
04861
04862 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04863 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04864 save_conference(p->oprpeer);
04865 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04866 }
04867 break;
04868 }
04869 switch (p->sig) {
04870 case SIG_FXOLS:
04871 case SIG_FXOGS:
04872 case SIG_FXOKS:
04873 p->onhooktime = time(NULL);
04874 p->msgstate = -1;
04875
04876 if (idx == SUB_REAL) {
04877
04878 if (p->subs[SUB_CALLWAIT].owner) {
04879
04880 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04881 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04882 unalloc_sub(p, SUB_CALLWAIT);
04883 #if 0
04884 p->subs[idx].needanswer = 0;
04885 p->subs[idx].needringing = 0;
04886 #endif
04887 p->callwaitingrepeat = 0;
04888 p->cidcwexpire = 0;
04889 p->owner = NULL;
04890
04891 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04892 p->dialing = 1;
04893 dahdi_ring_phone(p);
04894 } else if (p->subs[SUB_THREEWAY].owner) {
04895 unsigned int mssinceflash;
04896
04897
04898 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04899
04900 DLA_UNLOCK(&p->lock);
04901 CHANNEL_DEADLOCK_AVOIDANCE(ast);
04902
04903
04904
04905 DLA_LOCK(&p->lock);
04906 if (p->owner != ast) {
04907 ast_log(LOG_WARNING, "This isn't good...\n");
04908 return NULL;
04909 }
04910 }
04911 if (!p->subs[SUB_THREEWAY].owner) {
04912 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04913 return NULL;
04914 }
04915 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04916 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04917 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04918
04919
04920 if (p->subs[SUB_THREEWAY].owner)
04921 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
04922 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04923 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04924 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04925 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04926 if (p->transfer) {
04927
04928 p->subs[SUB_REAL].inthreeway = 0;
04929 p->subs[SUB_THREEWAY].inthreeway = 0;
04930
04931 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04932 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04933
04934 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04935 p->owner = NULL;
04936
04937 dahdi_ring_phone(p);
04938 } else {
04939 if ((res = attempt_transfer(p)) < 0) {
04940 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04941 if (p->subs[SUB_THREEWAY].owner)
04942 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04943 } else if (res) {
04944
04945 if (p->subs[SUB_THREEWAY].owner)
04946 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04947 break;
04948 }
04949 }
04950 } else {
04951 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04952 if (p->subs[SUB_THREEWAY].owner)
04953 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04954 }
04955 } else {
04956 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04957
04958 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04959 p->owner = NULL;
04960
04961 dahdi_ring_phone(p);
04962 }
04963 }
04964 } else {
04965 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
04966 }
04967
04968 default:
04969 dahdi_disable_ec(p);
04970 return NULL;
04971 }
04972 break;
04973 case DAHDI_EVENT_RINGOFFHOOK:
04974 if (p->inalarm) break;
04975 if (p->oprmode < 0)
04976 {
04977 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04978 {
04979
04980 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04981 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04982 restore_conference(p->oprpeer);
04983 }
04984 break;
04985 }
04986 if (p->radio)
04987 {
04988 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04989 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
04990 break;
04991 }
04992
04993
04994 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04995 c = strchr(p->dialdest, '/');
04996 if (c)
04997 c++;
04998 else
04999 c = p->dialdest;
05000 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05001 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05002 if (strlen(p->dop.dialstr) > 4) {
05003 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05004 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05005 p->echorest[sizeof(p->echorest) - 1] = '\0';
05006 p->echobreak = 1;
05007 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05008 } else
05009 p->echobreak = 0;
05010 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05011 int saveerr = errno;
05012
05013 x = DAHDI_ONHOOK;
05014 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05015 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05016 return NULL;
05017 }
05018 p->dialing = 1;
05019 return &p->subs[idx].f;
05020 }
05021 switch (p->sig) {
05022 case SIG_FXOLS:
05023 case SIG_FXOGS:
05024 case SIG_FXOKS:
05025 switch (ast->_state) {
05026 case AST_STATE_RINGING:
05027 dahdi_enable_ec(p);
05028 dahdi_train_ec(p);
05029 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05030 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05031
05032 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05033 ast_debug(1, "channel %d answered\n", p->channel);
05034 if (p->cidspill) {
05035
05036 ast_free(p->cidspill);
05037 p->cidspill = NULL;
05038 }
05039 p->dialing = 0;
05040 p->callwaitcas = 0;
05041 if (p->confirmanswer) {
05042
05043 p->subs[idx].f.frametype = AST_FRAME_NULL;
05044 p->subs[idx].f.subclass = 0;
05045 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05046
05047 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05048 if (res < 0) {
05049 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05050 p->dop.dialstr[0] = '\0';
05051 return NULL;
05052 } else {
05053 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05054 p->subs[idx].f.frametype = AST_FRAME_NULL;
05055 p->subs[idx].f.subclass = 0;
05056 p->dialing = 1;
05057 }
05058 p->dop.dialstr[0] = '\0';
05059 ast_setstate(ast, AST_STATE_DIALING);
05060 } else
05061 ast_setstate(ast, AST_STATE_UP);
05062 return &p->subs[idx].f;
05063 case AST_STATE_DOWN:
05064 ast_setstate(ast, AST_STATE_RING);
05065 ast->rings = 1;
05066 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05067 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
05068 ast_debug(1, "channel %d picked up\n", p->channel);
05069 return &p->subs[idx].f;
05070 case AST_STATE_UP:
05071
05072 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05073
05074 if (ast_bridged_channel(p->owner))
05075 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05076 p->subs[idx].needunhold = 1;
05077 break;
05078 case AST_STATE_RESERVED:
05079
05080 if (has_voicemail(p))
05081 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05082 else
05083 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05084 break;
05085 default:
05086 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05087 }
05088 break;
05089 case SIG_FXSLS:
05090 case SIG_FXSGS:
05091 case SIG_FXSKS:
05092 if (ast->_state == AST_STATE_RING) {
05093 p->ringt = p->ringt_base;
05094 }
05095
05096
05097
05098 ast_debug(1, "Setting IDLE polarity due "
05099 "to ring. Old polarity was %d\n",
05100 p->polarity);
05101 p->polarity = POLARITY_IDLE;
05102
05103
05104 case SIG_EM:
05105 case SIG_EM_E1:
05106 case SIG_EMWINK:
05107 case SIG_FEATD:
05108 case SIG_FEATDMF:
05109 case SIG_FEATDMF_TA:
05110 case SIG_E911:
05111 case SIG_FGC_CAMA:
05112 case SIG_FGC_CAMAMF:
05113 case SIG_FEATB:
05114 case SIG_SF:
05115 case SIG_SFWINK:
05116 case SIG_SF_FEATD:
05117 case SIG_SF_FEATDMF:
05118 case SIG_SF_FEATB:
05119 if (ast->_state == AST_STATE_PRERING)
05120 ast_setstate(ast, AST_STATE_RING);
05121 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05122 ast_debug(1, "Ring detected\n");
05123 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05124 p->subs[idx].f.subclass = AST_CONTROL_RING;
05125 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05126 ast_debug(1, "Line answered\n");
05127 if (p->confirmanswer) {
05128 p->subs[idx].f.frametype = AST_FRAME_NULL;
05129 p->subs[idx].f.subclass = 0;
05130 } else {
05131 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05132 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05133 ast_setstate(ast, AST_STATE_UP);
05134 }
05135 } else if (ast->_state != AST_STATE_RING)
05136 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05137 break;
05138 default:
05139 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05140 }
05141 break;
05142 case DAHDI_EVENT_RINGBEGIN:
05143 switch (p->sig) {
05144 case SIG_FXSLS:
05145 case SIG_FXSGS:
05146 case SIG_FXSKS:
05147 if (ast->_state == AST_STATE_RING) {
05148 p->ringt = p->ringt_base;
05149 }
05150 break;
05151 }
05152 break;
05153 case DAHDI_EVENT_RINGEROFF:
05154 if (p->inalarm) break;
05155 if ((p->radio || (p->oprmode < 0))) break;
05156 ast->rings++;
05157 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05158 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05159 ast_free(p->cidspill);
05160 p->cidspill = NULL;
05161 p->callwaitcas = 0;
05162 }
05163 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05164 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05165 break;
05166 case DAHDI_EVENT_RINGERON:
05167 break;
05168 case DAHDI_EVENT_NOALARM:
05169 p->inalarm = 0;
05170 #ifdef HAVE_PRI
05171
05172 if (p->bearer)
05173 p->bearer->inalarm = 0;
05174 #endif
05175 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05176 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05177 "Channel: %d\r\n", p->channel);
05178 break;
05179 case DAHDI_EVENT_WINKFLASH:
05180 if (p->inalarm) break;
05181 if (p->radio) break;
05182 if (p->oprmode < 0) break;
05183 if (p->oprmode > 1)
05184 {
05185 struct dahdi_params par;
05186
05187 memset(&par, 0, sizeof(par));
05188 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05189 {
05190 if (!par.rxisoffhook)
05191 {
05192
05193 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05194 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05195 save_conference(p);
05196 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05197 }
05198 }
05199 break;
05200 }
05201
05202 p->flashtime = ast_tvnow();
05203 switch (mysig) {
05204 case SIG_FXOLS:
05205 case SIG_FXOGS:
05206 case SIG_FXOKS:
05207 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05208 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05209 p->callwaitcas = 0;
05210
05211 if (idx != SUB_REAL) {
05212 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
05213 goto winkflashdone;
05214 }
05215
05216 if (p->subs[SUB_CALLWAIT].owner) {
05217
05218 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05219 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05220 p->owner = p->subs[SUB_REAL].owner;
05221 ast_debug(1, "Making %s the new owner\n", p->owner->name);
05222 if (p->owner->_state == AST_STATE_RINGING) {
05223 ast_setstate(p->owner, AST_STATE_UP);
05224 p->subs[SUB_REAL].needanswer = 1;
05225 }
05226 p->callwaitingrepeat = 0;
05227 p->cidcwexpire = 0;
05228
05229 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05230 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05231 S_OR(p->mohsuggest, NULL),
05232 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05233 }
05234 p->subs[SUB_CALLWAIT].needhold = 1;
05235 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05236 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05237 S_OR(p->mohsuggest, NULL),
05238 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05239 }
05240 p->subs[SUB_REAL].needunhold = 1;
05241 } else if (!p->subs[SUB_THREEWAY].owner) {
05242 if (!p->threewaycalling) {
05243
05244 p->subs[SUB_REAL].needflash = 1;
05245 goto winkflashdone;
05246 } else if (!check_for_conference(p)) {
05247 char cid_num[256];
05248 char cid_name[256];
05249
05250 cid_num[0] = 0;
05251 cid_name[0] = 0;
05252 if (p->dahditrcallerid && p->owner) {
05253 if (p->owner->cid.cid_num)
05254 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05255 if (p->owner->cid.cid_name)
05256 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05257 }
05258
05259
05260 if (!((ast->pbx) ||
05261 (ast->_state == AST_STATE_UP) ||
05262 (ast->_state == AST_STATE_RING))) {
05263 ast_debug(1, "Flash when call not up or ringing\n");
05264 goto winkflashdone;
05265 }
05266 if (alloc_sub(p, SUB_THREEWAY)) {
05267 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05268 goto winkflashdone;
05269 }
05270
05271 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05272 if (p->dahditrcallerid) {
05273 if (!p->origcid_num)
05274 p->origcid_num = ast_strdup(p->cid_num);
05275 if (!p->origcid_name)
05276 p->origcid_name = ast_strdup(p->cid_name);
05277 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05278 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05279 }
05280
05281 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05282
05283 dahdi_disable_ec(p);
05284 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05285 if (res)
05286 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05287 p->owner = chan;
05288 if (!chan) {
05289 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05290 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05291 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05292 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05293 dahdi_enable_ec(p);
05294 ast_hangup(chan);
05295 } else {
05296 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05297 int way3bridge = 0, cdr3way = 0;
05298
05299 if (!other) {
05300 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05301 } else
05302 way3bridge = 1;
05303
05304 if (p->subs[SUB_THREEWAY].owner->cdr)
05305 cdr3way = 1;
05306
05307 ast_verb(3, "Started three way call on channel %d\n", p->channel);
05308
05309
05310 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05311 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05312 S_OR(p->mohsuggest, NULL),
05313 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05314 }
05315 p->subs[SUB_THREEWAY].needhold = 1;
05316 }
05317 }
05318 } else {
05319
05320 if (p->subs[SUB_THREEWAY].inthreeway) {
05321
05322 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05323
05324 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05325
05326 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05327 p->owner = p->subs[SUB_REAL].owner;
05328 }
05329
05330 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05331 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05332 p->subs[SUB_REAL].inthreeway = 0;
05333 p->subs[SUB_THREEWAY].inthreeway = 0;
05334 } else {
05335
05336 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05337 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05338 int otherindex = SUB_THREEWAY;
05339 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05340 int way3bridge = 0, cdr3way = 0;
05341
05342 if (!other) {
05343 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05344 } else
05345 way3bridge = 1;
05346
05347 if (p->subs[SUB_THREEWAY].owner->cdr)
05348 cdr3way = 1;
05349
05350 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05351
05352 p->subs[SUB_THREEWAY].inthreeway = 1;
05353 p->subs[SUB_REAL].inthreeway = 1;
05354 if (ast->_state == AST_STATE_UP) {
05355 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05356 otherindex = SUB_REAL;
05357 }
05358 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05359 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05360 p->subs[otherindex].needunhold = 1;
05361 p->owner = p->subs[SUB_REAL].owner;
05362 if (ast->_state == AST_STATE_RINGING) {
05363 ast_debug(1, "Enabling ringtone on real and threeway\n");
05364 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05365 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05366 }
05367 } else {
05368 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05369 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05370 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05371 p->owner = p->subs[SUB_REAL].owner;
05372 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05373 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05374 p->subs[SUB_REAL].needunhold = 1;
05375 dahdi_enable_ec(p);
05376 }
05377
05378 }
05379 }
05380 winkflashdone:
05381 update_conf(p);
05382 break;
05383 case SIG_EM:
05384 case SIG_EM_E1:
05385 case SIG_EMWINK:
05386 case SIG_FEATD:
05387 case SIG_SF:
05388 case SIG_SFWINK:
05389 case SIG_SF_FEATD:
05390 case SIG_FXSLS:
05391 case SIG_FXSGS:
05392 if (option_debug) {
05393 if (p->dialing)
05394 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05395 else
05396 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05397 }
05398 break;
05399 case SIG_FEATDMF_TA:
05400 switch (p->whichwink) {
05401 case 0:
05402 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05403 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05404 break;
05405 case 1:
05406 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05407 break;
05408 case 2:
05409 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05410 return NULL;
05411 }
05412 p->whichwink++;
05413
05414 case SIG_FEATDMF:
05415 case SIG_E911:
05416 case SIG_FGC_CAMAMF:
05417 case SIG_FGC_CAMA:
05418 case SIG_FEATB:
05419 case SIG_SF_FEATDMF:
05420 case SIG_SF_FEATB:
05421
05422 if (!ast_strlen_zero(p->dop.dialstr)) {
05423 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05424 if (res < 0) {
05425 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05426 p->dop.dialstr[0] = '\0';
05427 return NULL;
05428 } else
05429 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05430 }
05431 p->dop.dialstr[0] = '\0';
05432 break;
05433 default:
05434 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
05435 }
05436 break;
05437 case DAHDI_EVENT_HOOKCOMPLETE:
05438 if (p->inalarm) break;
05439 if ((p->radio || (p->oprmode < 0))) break;
05440 switch (mysig) {
05441 case SIG_FXSLS:
05442 case SIG_FXSGS:
05443 case SIG_FXSKS:
05444 case SIG_EM:
05445 case SIG_EM_E1:
05446 case SIG_EMWINK:
05447 case SIG_FEATD:
05448 case SIG_SF:
05449 case SIG_SFWINK:
05450 case SIG_SF_FEATD:
05451 if (!ast_strlen_zero(p->dop.dialstr)) {
05452 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05453 if (res < 0) {
05454 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05455 p->dop.dialstr[0] = '\0';
05456 return NULL;
05457 } else
05458 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05459 }
05460 p->dop.dialstr[0] = '\0';
05461 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05462 break;
05463 case SIG_FEATDMF:
05464 case SIG_FEATDMF_TA:
05465 case SIG_E911:
05466 case SIG_FGC_CAMA:
05467 case SIG_FGC_CAMAMF:
05468 case SIG_FEATB:
05469 case SIG_SF_FEATDMF:
05470 case SIG_SF_FEATB:
05471 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05472 break;
05473 default:
05474 break;
05475 }
05476 break;
05477 case DAHDI_EVENT_POLARITY:
05478
05479
05480
05481
05482
05483
05484 if (p->polarity == POLARITY_IDLE) {
05485 p->polarity = POLARITY_REV;
05486 if (p->answeronpolarityswitch &&
05487 ((ast->_state == AST_STATE_DIALING) ||
05488 (ast->_state == AST_STATE_RINGING))) {
05489 ast_debug(1, "Answering on polarity switch!\n");
05490 ast_setstate(p->owner, AST_STATE_UP);
05491 if (p->hanguponpolarityswitch) {
05492 p->polaritydelaytv = ast_tvnow();
05493 }
05494 } else
05495 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
05496
05497 }
05498
05499
05500 if (p->hanguponpolarityswitch &&
05501 (p->polarityonanswerdelay > 0) &&
05502 (p->polarity == POLARITY_REV) &&
05503 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
05504
05505 ast_debug(1, "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) );
05506
05507 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05508 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
05509 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05510 p->polarity = POLARITY_IDLE;
05511 } else
05512 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
05513
05514 } else {
05515 p->polarity = POLARITY_IDLE;
05516 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
05517 }
05518
05519 ast_debug(1, "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) );
05520 break;
05521 default:
05522 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05523 }
05524 return &p->subs[idx].f;
05525 }
05526
05527 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05528 {
05529 struct dahdi_pvt *p = ast->tech_pvt;
05530 int res;
05531 int usedindex=-1;
05532 int idx;
05533 struct ast_frame *f;
05534
05535
05536 idx = dahdi_get_index(ast, p, 1);
05537
05538 p->subs[idx].f.frametype = AST_FRAME_NULL;
05539 p->subs[idx].f.datalen = 0;
05540 p->subs[idx].f.samples = 0;
05541 p->subs[idx].f.mallocd = 0;
05542 p->subs[idx].f.offset = 0;
05543 p->subs[idx].f.subclass = 0;
05544 p->subs[idx].f.delivery = ast_tv(0,0);
05545 p->subs[idx].f.src = "dahdi_exception";
05546 p->subs[idx].f.data.ptr = NULL;
05547
05548
05549 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05550
05551
05552
05553
05554
05555 if (p->fake_event) {
05556 res = p->fake_event;
05557 p->fake_event = 0;
05558 } else
05559 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05560
05561 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05562 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05563 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05564 p->owner = p->subs[SUB_REAL].owner;
05565 if (p->owner && ast_bridged_channel(p->owner))
05566 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05567 p->subs[SUB_REAL].needunhold = 1;
05568 }
05569 switch (res) {
05570 case DAHDI_EVENT_ONHOOK:
05571 dahdi_disable_ec(p);
05572 if (p->owner) {
05573 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05574 dahdi_ring_phone(p);
05575 p->callwaitingrepeat = 0;
05576 p->cidcwexpire = 0;
05577 } else
05578 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05579 update_conf(p);
05580 break;
05581 case DAHDI_EVENT_RINGOFFHOOK:
05582 dahdi_enable_ec(p);
05583 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05584 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05585 p->subs[SUB_REAL].needanswer = 1;
05586 p->dialing = 0;
05587 }
05588 break;
05589 case DAHDI_EVENT_HOOKCOMPLETE:
05590 case DAHDI_EVENT_RINGERON:
05591 case DAHDI_EVENT_RINGEROFF:
05592
05593 break;
05594 case DAHDI_EVENT_WINKFLASH:
05595 p->flashtime = ast_tvnow();
05596 if (p->owner) {
05597 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05598 if (p->owner->_state != AST_STATE_UP) {
05599
05600 usedindex = dahdi_get_index(p->owner, p, 0);
05601 if (usedindex > -1) {
05602 p->subs[usedindex].needanswer = 1;
05603 }
05604 ast_setstate(p->owner, AST_STATE_UP);
05605 }
05606 p->callwaitingrepeat = 0;
05607 p->cidcwexpire = 0;
05608 if (ast_bridged_channel(p->owner))
05609 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05610 p->subs[SUB_REAL].needunhold = 1;
05611 } else
05612 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05613 update_conf(p);
05614 break;
05615 default:
05616 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05617 }
05618 f = &p->subs[idx].f;
05619 return f;
05620 }
05621 if (!(p->radio || (p->oprmode < 0)))
05622 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05623
05624 if (ast != p->owner) {
05625 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05626 f = &p->subs[idx].f;
05627 return f;
05628 }
05629 f = dahdi_handle_event(ast);
05630 return f;
05631 }
05632
05633 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05634 {
05635 struct dahdi_pvt *p = ast->tech_pvt;
05636 struct ast_frame *f;
05637 ast_mutex_lock(&p->lock);
05638 f = __dahdi_exception(ast);
05639 ast_mutex_unlock(&p->lock);
05640 return f;
05641 }
05642
05643 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05644 {
05645 struct dahdi_pvt *p = ast->tech_pvt;
05646 int res;
05647 int idx;
05648 void *readbuf;
05649 struct ast_frame *f;
05650
05651 while (ast_mutex_trylock(&p->lock)) {
05652 CHANNEL_DEADLOCK_AVOIDANCE(ast);
05653 }
05654
05655 idx = dahdi_get_index(ast, p, 0);
05656
05657
05658 if (idx < 0) {
05659 ast_log(LOG_WARNING, "We dont exist?\n");
05660 ast_mutex_unlock(&p->lock);
05661 return NULL;
05662 }
05663
05664 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
05665
05666 p->subs[idx].f.frametype = AST_FRAME_NULL;
05667 p->subs[idx].f.datalen = 0;
05668 p->subs[idx].f.samples = 0;
05669 p->subs[idx].f.mallocd = 0;
05670 p->subs[idx].f.offset = 0;
05671 p->subs[idx].f.subclass = 0;
05672 p->subs[idx].f.delivery = ast_tv(0,0);
05673 p->subs[idx].f.src = "dahdi_read";
05674 p->subs[idx].f.data.ptr = NULL;
05675
05676
05677 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05678 {
05679 struct dahdi_params ps;
05680
05681 memset(&ps, 0, sizeof(ps));
05682 ps.channo = p->channel;
05683 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05684 ast_mutex_unlock(&p->lock);
05685 return NULL;
05686 }
05687 p->firstradio = 1;
05688 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05689 if (ps.rxisoffhook)
05690 {
05691 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
05692 }
05693 else
05694 {
05695 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05696 }
05697 ast_mutex_unlock(&p->lock);
05698 return &p->subs[idx].f;
05699 }
05700 if (p->ringt == 1) {
05701 ast_mutex_unlock(&p->lock);
05702 return NULL;
05703 }
05704 else if (p->ringt > 0)
05705 p->ringt--;
05706
05707 if (p->subs[idx].needringing) {
05708
05709 p->subs[idx].needringing = 0;
05710 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05711 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05712 ast_setstate(ast, AST_STATE_RINGING);
05713 ast_mutex_unlock(&p->lock);
05714 return &p->subs[idx].f;
05715 }
05716
05717 if (p->subs[idx].needbusy) {
05718
05719 p->subs[idx].needbusy = 0;
05720 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05721 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
05722 ast_mutex_unlock(&p->lock);
05723 return &p->subs[idx].f;
05724 }
05725
05726 if (p->subs[idx].needcongestion) {
05727
05728 p->subs[idx].needcongestion = 0;
05729 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05730 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
05731 ast_mutex_unlock(&p->lock);
05732 return &p->subs[idx].f;
05733 }
05734
05735 if (p->subs[idx].needcallerid) {
05736 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05737 S_OR(p->lastcid_name, NULL),
05738 S_OR(p->lastcid_num, NULL)
05739 );
05740 p->subs[idx].needcallerid = 0;
05741 }
05742
05743 if (p->subs[idx].needanswer) {
05744
05745 p->subs[idx].needanswer = 0;
05746 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05747 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05748 ast_mutex_unlock(&p->lock);
05749 return &p->subs[idx].f;
05750 }
05751
05752 if (p->subs[idx].needflash) {
05753
05754 p->subs[idx].needflash = 0;
05755 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05756 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
05757 ast_mutex_unlock(&p->lock);
05758 return &p->subs[idx].f;
05759 }
05760
05761 if (p->subs[idx].needhold) {
05762
05763 p->subs[idx].needhold = 0;
05764 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05765 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
05766 ast_mutex_unlock(&p->lock);
05767 ast_debug(1, "Sending hold on '%s'\n", ast->name);
05768 return &p->subs[idx].f;
05769 }
05770
05771 if (p->subs[idx].needunhold) {
05772
05773 p->subs[idx].needunhold = 0;
05774 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05775 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
05776 ast_mutex_unlock(&p->lock);
05777 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05778 return &p->subs[idx].f;
05779 }
05780
05781 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05782 if (!p->subs[idx].linear) {
05783 p->subs[idx].linear = 1;
05784 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05785 if (res)
05786 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
05787 }
05788 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05789 (ast->rawreadformat == AST_FORMAT_ALAW)) {
05790 if (p->subs[idx].linear) {
05791 p->subs[idx].linear = 0;
05792 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05793 if (res)
05794 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
05795 }
05796 } else {
05797 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05798 ast_mutex_unlock(&p->lock);
05799 return NULL;
05800 }
05801 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
05802 CHECK_BLOCKING(ast);
05803 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05804 ast_clear_flag(ast, AST_FLAG_BLOCKING);
05805
05806 if (res < 0) {
05807 f = NULL;
05808 if (res == -1) {
05809 if (errno == EAGAIN) {
05810
05811 ast_mutex_unlock(&p->lock);
05812 return &p->subs[idx].f;
05813 } else if (errno == ELAST) {
05814 f = __dahdi_exception(ast);
05815 } else
05816 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05817 }
05818 ast_mutex_unlock(&p->lock);
05819 return f;
05820 }
05821 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
05822 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05823 f = __dahdi_exception(ast);
05824 ast_mutex_unlock(&p->lock);
05825 return f;
05826 }
05827 if (p->tdd) {
05828 int c;
05829
05830 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05831 if (c < 0) {
05832 ast_debug(1,"tdd_feed failed\n");
05833 ast_mutex_unlock(&p->lock);
05834 return NULL;
05835 }
05836 if (c) {
05837 p->subs[idx].f.subclass = 0;
05838 p->subs[idx].f.frametype = AST_FRAME_TEXT;
05839 p->subs[idx].f.mallocd = 0;
05840 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05841 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
05842 p->subs[idx].f.datalen = 1;
05843 *((char *) p->subs[idx].f.data.ptr) = c;
05844 ast_mutex_unlock(&p->lock);
05845 return &p->subs[idx].f;
05846 }
05847 }
05848
05849 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05850 p->callwaitingrepeat--;
05851 }
05852 if (p->cidcwexpire)
05853 p->cidcwexpire--;
05854
05855 if (p->callwaitingrepeat == 1) {
05856 p->callwaitrings++;
05857 dahdi_callwait(ast);
05858 }
05859
05860 if (p->cidcwexpire == 1) {
05861 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05862 restore_conference(p);
05863 }
05864 if (p->subs[idx].linear) {
05865 p->subs[idx].f.datalen = READ_SIZE * 2;
05866 } else
05867 p->subs[idx].f.datalen = READ_SIZE;
05868
05869
05870 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05871 send_callerid(p);
05872 }
05873
05874 p->subs[idx].f.frametype = AST_FRAME_VOICE;
05875 p->subs[idx].f.subclass = ast->rawreadformat;
05876 p->subs[idx].f.samples = READ_SIZE;
05877 p->subs[idx].f.mallocd = 0;
05878 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05879 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
05880 #if 0
05881 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
05882 #endif
05883 if (p->dialing ||
05884 (idx && (ast->_state != AST_STATE_UP)) ||
05885 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05886 ) {
05887
05888
05889 p->subs[idx].f.frametype = AST_FRAME_NULL;
05890 p->subs[idx].f.subclass = 0;
05891 p->subs[idx].f.samples = 0;
05892 p->subs[idx].f.mallocd = 0;
05893 p->subs[idx].f.offset = 0;
05894 p->subs[idx].f.data.ptr = NULL;
05895 p->subs[idx].f.datalen= 0;
05896 }
05897 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) {
05898
05899 int mute;
05900
05901 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
05902
05903
05904 mute = ast_dsp_was_muted(p->dsp);
05905 if (p->muting != mute) {
05906 p->muting = mute;
05907 dahdi_confmute(p, mute);
05908 }
05909
05910 if (f) {
05911 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05912 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05913
05914
05915 f = NULL;
05916 }
05917 } else if (f->frametype == AST_FRAME_DTMF) {
05918 #ifdef HAVE_PRI
05919 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
05920 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05921 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05922
05923 f->frametype = AST_FRAME_NULL;
05924 f->subclass = 0;
05925 }
05926 #endif
05927
05928 p->pulsedial = 0;
05929 }
05930 }
05931 } else
05932 f = &p->subs[idx].f;
05933
05934 if (f && (f->frametype == AST_FRAME_DTMF))
05935 dahdi_handle_dtmfup(ast, idx, &f);
05936
05937
05938 if (p->fake_event)
05939 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05940
05941 ast_mutex_unlock(&p->lock);
05942 return f;
05943 }
05944
05945 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
05946 {
05947 int sent=0;
05948 int size;
05949 int res;
05950 int fd;
05951 fd = p->subs[idx].dfd;
05952 while (len) {
05953 size = len;
05954 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05955 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05956 res = write(fd, buf, size);
05957 if (res != size) {
05958 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05959 return sent;
05960 }
05961 len -= size;
05962 buf += size;
05963 }
05964 return sent;
05965 }
05966
05967 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05968 {
05969 struct dahdi_pvt *p = ast->tech_pvt;
05970 int res;
05971 int idx;
05972 idx = dahdi_get_index(ast, p, 0);
05973 if (idx < 0) {
05974 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05975 return -1;
05976 }
05977
05978 #if 0
05979 #ifdef HAVE_PRI
05980 ast_mutex_lock(&p->lock);
05981 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05982 if (p->pri->pri) {
05983 if (!pri_grab(p, p->pri)) {
05984 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05985 pri_rel(p->pri);
05986 } else
05987 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05988 }
05989 p->proceeding=1;
05990 }
05991 ast_mutex_unlock(&p->lock);
05992 #endif
05993 #endif
05994
05995 if (frame->frametype != AST_FRAME_VOICE) {
05996 if (frame->frametype != AST_FRAME_IMAGE)
05997 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05998 return 0;
05999 }
06000 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06001 (frame->subclass != AST_FORMAT_ULAW) &&
06002 (frame->subclass != AST_FORMAT_ALAW)) {
06003 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06004 return -1;
06005 }
06006 if (p->dialing) {
06007 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06008 return 0;
06009 }
06010 if (!p->owner) {
06011 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06012 return 0;
06013 }
06014 if (p->cidspill) {
06015 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06016 return 0;
06017 }
06018
06019 if (!frame->data.ptr || !frame->datalen)
06020 return 0;
06021
06022 if (frame->subclass == AST_FORMAT_SLINEAR) {
06023 if (!p->subs[idx].linear) {
06024 p->subs[idx].linear = 1;
06025 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06026 if (res)
06027 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06028 }
06029 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
06030 } else {
06031
06032 if (p->subs[idx].linear) {
06033 p->subs[idx].linear = 0;
06034 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06035 if (res)
06036 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06037 }
06038 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
06039 }
06040 if (res < 0) {
06041 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06042 return -1;
06043 }
06044 return 0;
06045 }
06046
06047 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06048 {
06049 struct dahdi_pvt *p = chan->tech_pvt;
06050 int res=-1;
06051 int idx;
06052 int func = DAHDI_FLASH;
06053 ast_mutex_lock(&p->lock);
06054 idx = dahdi_get_index(chan, p, 0);
06055 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06056 if (idx == SUB_REAL) {
06057 switch (condition) {
06058 case AST_CONTROL_BUSY:
06059 #ifdef HAVE_PRI
06060 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06061 chan->hangupcause = AST_CAUSE_USER_BUSY;
06062 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06063 res = 0;
06064 } else if (!p->progress &&
06065 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06066 && p->pri && !p->outgoing) {
06067 if (p->pri->pri) {
06068 if (!pri_grab(p, p->pri)) {
06069 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06070 pri_rel(p->pri);
06071 }
06072 else
06073 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06074 }
06075 p->progress = 1;
06076 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06077 } else
06078 #endif
06079 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06080 break;
06081 case AST_CONTROL_RINGING:
06082 #ifdef HAVE_PRI
06083 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06084 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06085 if (p->pri->pri) {
06086 if (!pri_grab(p, p->pri)) {
06087 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06088 pri_rel(p->pri);
06089 }
06090 else
06091 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06092 }
06093 p->alerting = 1;
06094 }
06095
06096 #endif
06097 #ifdef HAVE_SS7
06098 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06099 if (p->ss7->ss7) {
06100 ss7_grab(p, p->ss7);
06101
06102 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06103 p->rlt = 1;
06104 if (p->rlt != 1)
06105 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06106 p->alerting = 1;
06107 ss7_rel(p->ss7);
06108 }
06109 }
06110 #endif
06111
06112 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
06113
06114 if (chan->_state != AST_STATE_UP) {
06115 if ((chan->_state != AST_STATE_RING) ||
06116 ((p->sig != SIG_FXSKS) &&
06117 (p->sig != SIG_FXSLS) &&
06118 (p->sig != SIG_FXSGS)))
06119 ast_setstate(chan, AST_STATE_RINGING);
06120 }
06121 break;
06122 case AST_CONTROL_PROCEEDING:
06123 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06124 #ifdef HAVE_PRI
06125 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06126 && p->pri && !p->outgoing) {
06127 if (p->pri->pri) {
06128 if (!pri_grab(p, p->pri)) {
06129 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06130 pri_rel(p->pri);
06131 }
06132 else
06133 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06134 }
06135 p->proceeding = 1;
06136 p->dialing = 0;
06137 }
06138 #endif
06139 #ifdef HAVE_SS7
06140
06141 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
06142 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06143 p->rlt = 1;
06144 }
06145
06146 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
06147 if (p->ss7->ss7) {
06148 ss7_grab(p, p->ss7);
06149 isup_acm(p->ss7->ss7, p->ss7call);
06150 p->proceeding = 1;
06151 ss7_rel(p->ss7);
06152
06153 }
06154 }
06155 #endif
06156
06157 res = 0;
06158 break;
06159 case AST_CONTROL_PROGRESS:
06160 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06161 #ifdef HAVE_PRI
06162 p->digital = 0;
06163 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06164 && p->pri && !p->outgoing) {
06165 if (p->pri->pri) {
06166 if (!pri_grab(p, p->pri)) {
06167 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06168 pri_rel(p->pri);
06169 }
06170 else
06171 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06172 }
06173 p->progress = 1;
06174 }
06175 #endif
06176 #ifdef HAVE_SS7
06177 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
06178 if (p->ss7->ss7) {
06179 ss7_grab(p, p->ss7);
06180 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
06181 p->progress = 1;
06182 ss7_rel(p->ss7);
06183
06184 dahdi_enable_ec(p);
06185
06186 }
06187 }
06188 #endif
06189
06190 res = 0;
06191 break;
06192 case AST_CONTROL_CONGESTION:
06193 chan->hangupcause = AST_CAUSE_CONGESTION;
06194 #ifdef HAVE_PRI
06195 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06196 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06197 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06198 res = 0;
06199 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06200 && p->pri && !p->outgoing) {
06201 if (p->pri) {
06202 if (!pri_grab(p, p->pri)) {
06203 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06204 pri_rel(p->pri);
06205 } else
06206 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06207 }
06208 p->progress = 1;
06209 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06210 } else
06211 #endif
06212 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06213 break;
06214 case AST_CONTROL_HOLD:
06215 #ifdef HAVE_PRI
06216 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06217 if (!pri_grab(p, p->pri)) {
06218 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06219 pri_rel(p->pri);
06220 } else
06221 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06222 } else
06223 #endif
06224 ast_moh_start(chan, data, p->mohinterpret);
06225 break;
06226 case AST_CONTROL_UNHOLD:
06227 #ifdef HAVE_PRI
06228 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06229 if (!pri_grab(p, p->pri)) {
06230 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06231 pri_rel(p->pri);
06232 } else
06233 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06234 } else
06235 #endif
06236 ast_moh_stop(chan);
06237 break;
06238 case AST_CONTROL_RADIO_KEY:
06239 if (p->radio)
06240 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06241 res = 0;
06242 break;
06243 case AST_CONTROL_RADIO_UNKEY:
06244 if (p->radio)
06245 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
06246 res = 0;
06247 break;
06248 case AST_CONTROL_FLASH:
06249
06250 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06251
06252 p->dop.dialstr[0] = '\0';
06253 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06254 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06255 chan->name, strerror(errno));
06256 } else
06257 res = 0;
06258 } else
06259 res = 0;
06260 break;
06261 case AST_CONTROL_SRCUPDATE:
06262 res = 0;
06263 break;
06264 case -1:
06265 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06266 break;
06267 }
06268 } else
06269 res = 0;
06270 ast_mutex_unlock(&p->lock);
06271 return res;
06272 }
06273
06274 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
06275 {
06276 struct ast_channel *tmp;
06277 int deflaw;
06278 int res;
06279 int x,y;
06280 int features;
06281 struct ast_str *chan_name;
06282 struct ast_variable *v;
06283 struct dahdi_params ps;
06284 if (i->subs[idx].owner) {
06285 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
06286 return NULL;
06287 }
06288 y = 1;
06289 chan_name = ast_str_alloca(32);
06290 do {
06291 #ifdef HAVE_PRI
06292 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06293 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06294 else
06295 #endif
06296 if (i->channel == CHAN_PSEUDO)
06297 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
06298 else
06299 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
06300 for (x = 0; x < 3; x++) {
06301 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
06302 break;
06303 }
06304 y++;
06305 } while (x < 3);
06306 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", chan_name->str);
06307 if (!tmp)
06308 return NULL;
06309 tmp->tech = &dahdi_tech;
06310 memset(&ps, 0, sizeof(ps));
06311 ps.channo = i->channel;
06312 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06313 if (res) {
06314 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06315 ps.curlaw = DAHDI_LAW_MULAW;
06316 }
06317 if (ps.curlaw == DAHDI_LAW_ALAW)
06318 deflaw = AST_FORMAT_ALAW;
06319 else
06320 deflaw = AST_FORMAT_ULAW;
06321 if (law) {
06322 if (law == DAHDI_LAW_ALAW)
06323 deflaw = AST_FORMAT_ALAW;
06324 else
06325 deflaw = AST_FORMAT_ULAW;
06326 }
06327 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
06328 tmp->nativeformats = deflaw;
06329
06330 tmp->rawreadformat = deflaw;
06331 tmp->readformat = deflaw;
06332 tmp->rawwriteformat = deflaw;
06333 tmp->writeformat = deflaw;
06334 i->subs[idx].linear = 0;
06335 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
06336 features = 0;
06337 if (idx == SUB_REAL) {
06338 if (i->busydetect && CANBUSYDETECT(i))
06339 features |= DSP_FEATURE_BUSY_DETECT;
06340 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
06341 features |= DSP_FEATURE_CALL_PROGRESS;
06342 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
06343 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
06344 features |= DSP_FEATURE_FAX_DETECT;
06345 }
06346 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06347 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
06348 i->hardwaredtmf = 0;
06349 features |= DSP_FEATURE_DIGIT_DETECT;
06350 } else if (NEED_MFDETECT(i)) {
06351 i->hardwaredtmf = 1;
06352 features |= DSP_FEATURE_DIGIT_DETECT;
06353 }
06354 }
06355 if (features) {
06356 if (i->dsp) {
06357 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
06358 } else {
06359 if (i->channel != CHAN_PSEUDO)
06360 i->dsp = ast_dsp_new();
06361 else
06362 i->dsp = NULL;
06363 if (i->dsp) {
06364 i->dsp_features = features;
06365 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06366
06367 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
06368
06369
06370 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06371 features = 0;
06372 }
06373 #endif
06374 ast_dsp_set_features(i->dsp, features);
06375 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06376 if (!ast_strlen_zero(progzone))
06377 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06378 if (i->busydetect && CANBUSYDETECT(i)) {
06379 if(i->silencethreshold > 0)
06380 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06381 ast_dsp_set_busy_count(i->dsp, i->busycount);
06382 if(i->busytonelength > 0)
06383 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06384 if((i->busytonelength == i->busyquietlength) && i->busycompare)
06385 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06386 }
06387 }
06388 }
06389 }
06390
06391 if (state == AST_STATE_RING)
06392 tmp->rings = 1;
06393 tmp->tech_pvt = i;
06394 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06395
06396 tmp->callgroup = i->callgroup;
06397 tmp->pickupgroup = i->pickupgroup;
06398 }
06399 if (!ast_strlen_zero(i->parkinglot))
06400 ast_string_field_set(tmp, parkinglot, i->parkinglot);
06401 if (!ast_strlen_zero(i->language))
06402 ast_string_field_set(tmp, language, i->language);
06403 if (!i->owner)
06404 i->owner = tmp;
06405 if (!ast_strlen_zero(i->accountcode))
06406 ast_string_field_set(tmp, accountcode, i->accountcode);
06407 if (i->amaflags)
06408 tmp->amaflags = i->amaflags;
06409 i->subs[idx].owner = tmp;
06410 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06411 ast_string_field_set(tmp, call_forward, i->call_forward);
06412
06413 if (!i->adsi)
06414 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06415 if (!ast_strlen_zero(i->exten))
06416 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06417 if (!ast_strlen_zero(i->rdnis))
06418 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06419 if (!ast_strlen_zero(i->dnid))
06420 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06421
06422
06423
06424 #ifdef PRI_ANI
06425 if (!ast_strlen_zero(i->cid_ani))
06426 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06427 else
06428 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06429 #else
06430 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06431 #endif
06432 tmp->cid.cid_pres = i->callingpres;
06433 tmp->cid.cid_ton = i->cid_ton;
06434 tmp->cid.cid_ani2 = i->cid_ani2;
06435 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06436 tmp->transfercapability = transfercapability;
06437 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06438 if (transfercapability & AST_TRANS_CAP_DIGITAL)
06439 i->digital = 1;
06440
06441 i->isidlecall = 0;
06442 i->alreadyhungup = 0;
06443 #endif
06444
06445 i->fake_event = 0;
06446
06447 dahdi_confmute(i, 0);
06448 i->muting = 0;
06449
06450 ast_jb_configure(tmp, &global_jbconf);
06451
06452 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
06453
06454 for (v = i->vars ; v ; v = v->next)
06455 pbx_builtin_setvar_helper(tmp, v->name, v->value);
06456
06457 if (startpbx) {
06458 if (ast_pbx_start(tmp)) {
06459 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06460 ast_hangup(tmp);
06461 i->owner = NULL;
06462 return NULL;
06463 }
06464 }
06465
06466 ast_module_ref(ast_module_info->self);
06467 return tmp;
06468 }
06469
06470
06471 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06472 {
06473 char c;
06474
06475 *str = 0;
06476 for (;;)
06477 {
06478
06479 c = ast_waitfordigit(chan, ms);
06480
06481 if (c < 1)
06482 return c;
06483 *str++ = c;
06484 *str = 0;
06485 if (strchr(term, c))
06486 return 1;
06487 }
06488 }
06489
06490 static int dahdi_wink(struct dahdi_pvt *p, int idx)
06491 {
06492 int j;
06493 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
06494 for (;;)
06495 {
06496
06497 j = DAHDI_IOMUX_SIGEVENT;
06498
06499 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06500
06501 if (j & DAHDI_IOMUX_SIGEVENT) break;
06502 }
06503
06504 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06505 return 0;
06506 }
06507
06508
06509
06510
06511
06512
06513
06514
06515
06516
06517 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
06518 {
06519
06520 dahdichan->dnd = on;
06521 ast_verb(3, "%s DND on channel %d\n",
06522 on? "Enabled" : "Disabled",
06523 dahdichan->channel);
06524 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06525 "Channel: DAHDI/%d\r\n"
06526 "Status: %s\r\n", dahdichan->channel,
06527 on? "enabled" : "disabled");
06528 }
06529
06530 static void *ss_thread(void *data)
06531 {
06532 struct ast_channel *chan = data;
06533 struct dahdi_pvt *p = chan->tech_pvt;
06534 char exten[AST_MAX_EXTENSION] = "";
06535 char exten2[AST_MAX_EXTENSION] = "";
06536 unsigned char buf[256];
06537 char dtmfcid[300];
06538 char dtmfbuf[300];
06539 struct callerid_state *cs = NULL;
06540 char *name = NULL, *number = NULL;
06541 int distMatches;
06542 int curRingData[3];
06543 int receivedRingT;
06544 int counter1;
06545 int counter;
06546 int samples = 0;
06547 struct ast_smdi_md_message *smdi_msg = NULL;
06548 int flags;
06549 int i;
06550 int timeout;
06551 int getforward = 0;
06552 char *s1, *s2;
06553 int len = 0;
06554 int res;
06555 int idx;
06556
06557 ast_mutex_lock(&ss_thread_lock);
06558 ss_thread_count++;
06559 ast_mutex_unlock(&ss_thread_lock);
06560
06561
06562
06563 if (!p) {
06564 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06565 ast_hangup(chan);
06566 goto quit;
06567 }
06568 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
06569 idx = dahdi_get_index(chan, p, 1);
06570 if (idx < 0) {
06571 ast_log(LOG_WARNING, "Huh?\n");
06572 ast_hangup(chan);
06573 goto quit;
06574 }
06575 if (p->dsp)
06576 ast_dsp_digitreset(p->dsp);
06577 switch (p->sig) {
06578 #ifdef HAVE_PRI
06579 case SIG_PRI:
06580 case SIG_BRI:
06581 case SIG_BRI_PTMP:
06582
06583 ast_copy_string(exten, p->exten, sizeof(exten));
06584 len = strlen(exten);
06585 res = 0;
06586 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06587 if (len && !ast_ignore_pattern(chan->context, exten))
06588 tone_zone_play_tone(p->subs[idx].dfd, -1);
06589 else
06590 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06591 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06592 timeout = matchdigittimeout;
06593 else
06594 timeout = gendigittimeout;
06595 res = ast_waitfordigit(chan, timeout);
06596 if (res < 0) {
06597 ast_debug(1, "waitfordigit returned < 0...\n");
06598 ast_hangup(chan);
06599 goto quit;
06600 } else if (res) {
06601 exten[len++] = res;
06602 exten[len] = '\0';
06603 } else
06604 break;
06605 }
06606
06607 if (ast_strlen_zero(exten)) {
06608 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
06609 exten[0] = 's';
06610 exten[1] = '\0';
06611 }
06612 tone_zone_play_tone(p->subs[idx].dfd, -1);
06613 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06614
06615 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06616 if (p->dsp) ast_dsp_digitreset(p->dsp);
06617 dahdi_enable_ec(p);
06618 ast_setstate(chan, AST_STATE_RING);
06619 res = ast_pbx_run(chan);
06620 if (res) {
06621 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06622 }
06623 } else {
06624 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06625 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06626 ast_hangup(chan);
06627 p->exten[0] = '\0';
06628
06629 p->call = NULL;
06630 }
06631 goto quit;
06632 break;
06633 #endif
06634 case SIG_FEATD:
06635 case SIG_FEATDMF:
06636 case SIG_FEATDMF_TA:
06637 case SIG_E911:
06638 case SIG_FGC_CAMAMF:
06639 case SIG_FEATB:
06640 case SIG_EMWINK:
06641 case SIG_SF_FEATD:
06642 case SIG_SF_FEATDMF:
06643 case SIG_SF_FEATB:
06644 case SIG_SFWINK:
06645 if (dahdi_wink(p, idx))
06646 goto quit;
06647
06648 case SIG_EM:
06649 case SIG_EM_E1:
06650 case SIG_SF:
06651 case SIG_FGC_CAMA:
06652 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06653 if (p->dsp)
06654 ast_dsp_digitreset(p->dsp);
06655
06656 if (p->dsp) {
06657 if (NEED_MFDETECT(p))
06658 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06659 else
06660 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06661 }
06662 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06663
06664 if (!p->immediate)
06665
06666 res = ast_waitfordigit(chan, 5000);
06667 else
06668 res = 0;
06669 if (res > 0) {
06670
06671 dtmfbuf[0] = res;
06672 switch (p->sig) {
06673 case SIG_FEATD:
06674 case SIG_SF_FEATD:
06675 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06676 if (res > 0)
06677 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06678 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06679 break;
06680 case SIG_FEATDMF_TA:
06681 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06682 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06683 if (dahdi_wink(p, idx)) goto quit;
06684 dtmfbuf[0] = 0;
06685
06686 res = ast_waitfordigit(chan, 5000);
06687 if (res <= 0) break;
06688 dtmfbuf[0] = res;
06689
06690 case SIG_FEATDMF:
06691 case SIG_E911:
06692 case SIG_FGC_CAMAMF:
06693 case SIG_SF_FEATDMF:
06694 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06695
06696 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06697 {
06698 if (dahdi_wink(p, idx)) goto quit;
06699 dtmfbuf[0] = 0;
06700
06701 res = ast_waitfordigit(chan, 5000);
06702 if (res <= 0) break;
06703 dtmfbuf[0] = res;
06704 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06705 }
06706 if (res > 0) {
06707
06708 if (p->sig == SIG_E911)
06709 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06710 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06711 }
06712 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06713 break;
06714 case SIG_FEATB:
06715 case SIG_SF_FEATB:
06716 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06717 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06718 break;
06719 case SIG_EMWINK:
06720
06721
06722
06723
06724 if (res == '*') {
06725 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06726 if (res > 0)
06727 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06728 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06729 break;
06730 }
06731 default:
06732
06733 len = 1;
06734 dtmfbuf[len] = '\0';
06735 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06736 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06737 timeout = matchdigittimeout;
06738 } else {
06739 timeout = gendigittimeout;
06740 }
06741 res = ast_waitfordigit(chan, timeout);
06742 if (res < 0) {
06743 ast_debug(1, "waitfordigit returned < 0...\n");
06744 ast_hangup(chan);
06745 goto quit;
06746 } else if (res) {
06747 dtmfbuf[len++] = res;
06748 dtmfbuf[len] = '\0';
06749 } else {
06750 break;
06751 }
06752 }
06753 break;
06754 }
06755 }
06756 if (res == -1) {
06757 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06758 ast_hangup(chan);
06759 goto quit;
06760 } else if (res < 0) {
06761 ast_debug(1, "Got hung up before digits finished\n");
06762 ast_hangup(chan);
06763 goto quit;
06764 }
06765
06766 if (p->sig == SIG_FGC_CAMA) {
06767 char anibuf[100];
06768
06769 if (ast_safe_sleep(chan,1000) == -1) {
06770 ast_hangup(chan);
06771 goto quit;
06772 }
06773 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06774 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06775 res = my_getsigstr(chan, anibuf, "#", 10000);
06776 if ((res > 0) && (strlen(anibuf) > 2)) {
06777 if (anibuf[strlen(anibuf) - 1] == '#')
06778 anibuf[strlen(anibuf) - 1] = 0;
06779 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06780 }
06781 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06782 }
06783
06784 ast_copy_string(exten, dtmfbuf, sizeof(exten));
06785 if (ast_strlen_zero(exten))
06786 ast_copy_string(exten, "s", sizeof(exten));
06787 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06788
06789 if (exten[0] == '*') {
06790 char *stringp=NULL;
06791 ast_copy_string(exten2, exten, sizeof(exten2));
06792
06793 stringp=exten2 +1;
06794 s1 = strsep(&stringp, "*");
06795 s2 = strsep(&stringp, "*");
06796 if (s2) {
06797 if (!ast_strlen_zero(p->cid_num))
06798 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06799 else
06800 ast_set_callerid(chan, s1, NULL, s1);
06801 ast_copy_string(exten, s2, sizeof(exten));
06802 } else
06803 ast_copy_string(exten, s1, sizeof(exten));
06804 } else if (p->sig == SIG_FEATD)
06805 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06806 }
06807 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06808 if (exten[0] == '*') {
06809 char *stringp=NULL;
06810 ast_copy_string(exten2, exten, sizeof(exten2));
06811
06812 stringp=exten2 +1;
06813 s1 = strsep(&stringp, "#");
06814 s2 = strsep(&stringp, "#");
06815 if (s2) {
06816 if (!ast_strlen_zero(p->cid_num))
06817 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06818 else
06819 if (*(s1 + 2))
06820 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06821 ast_copy_string(exten, s2 + 1, sizeof(exten));
06822 } else
06823 ast_copy_string(exten, s1 + 2, sizeof(exten));
06824 } else
06825 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06826 }
06827 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06828 if (exten[0] == '*') {
06829 char *stringp=NULL;
06830 ast_copy_string(exten2, exten, sizeof(exten2));
06831
06832 stringp=exten2 +1;
06833 s1 = strsep(&stringp, "#");
06834 s2 = strsep(&stringp, "#");
06835 if (s2 && (*(s2 + 1) == '0')) {
06836 if (*(s2 + 2))
06837 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06838 }
06839 if (s1) ast_copy_string(exten, s1, sizeof(exten));
06840 else ast_copy_string(exten, "911", sizeof(exten));
06841 } else
06842 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
06843 }
06844 if (p->sig == SIG_FEATB) {
06845 if (exten[0] == '*') {
06846 char *stringp=NULL;
06847 ast_copy_string(exten2, exten, sizeof(exten2));
06848
06849 stringp=exten2 +1;
06850 s1 = strsep(&stringp, "#");
06851 ast_copy_string(exten, exten2 + 1, sizeof(exten));
06852 } else
06853 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
06854 }
06855 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06856 dahdi_wink(p, idx);
06857
06858
06859
06860 if (ast_safe_sleep(chan,100)) goto quit;
06861 }
06862 dahdi_enable_ec(p);
06863 if (NEED_MFDETECT(p)) {
06864 if (p->dsp) {
06865 if (!p->hardwaredtmf)
06866 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06867 else {
06868 ast_dsp_free(p->dsp);
06869 p->dsp = NULL;
06870 }
06871 }
06872 }
06873
06874 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06875 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06876 if (p->dsp) ast_dsp_digitreset(p->dsp);
06877 res = ast_pbx_run(chan);
06878 if (res) {
06879 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06880 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06881 }
06882 goto quit;
06883 } else {
06884 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06885 sleep(2);
06886 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
06887 if (res < 0)
06888 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06889 else
06890 sleep(1);
06891 res = ast_streamfile(chan, "ss-noservice", chan->language);
06892 if (res >= 0)
06893 ast_waitstream(chan, "");
06894 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06895 ast_hangup(chan);
06896 goto quit;
06897 }
06898 break;
06899 case SIG_FXOLS:
06900 case SIG_FXOGS:
06901 case SIG_FXOKS:
06902
06903 timeout = firstdigittimeout;
06904
06905
06906 if (p->subs[SUB_THREEWAY].owner)
06907 timeout = 999999;
06908 while (len < AST_MAX_EXTENSION-1) {
06909
06910
06911 if (p->immediate)
06912 res = 's';
06913 else
06914 res = ast_waitfordigit(chan, timeout);
06915 timeout = 0;
06916 if (res < 0) {
06917 ast_debug(1, "waitfordigit returned < 0...\n");
06918 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06919 ast_hangup(chan);
06920 goto quit;
06921 } else if (res) {
06922 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
06923 exten[len++]=res;
06924 exten[len] = '\0';
06925 }
06926 if (!ast_ignore_pattern(chan->context, exten))
06927 tone_zone_play_tone(p->subs[idx].dfd, -1);
06928 else
06929 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06930 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06931 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06932 if (getforward) {
06933
06934 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
06935 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06936 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06937 if (res)
06938 break;
06939 usleep(500000);
06940 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06941 sleep(1);
06942 memset(exten, 0, sizeof(exten));
06943 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06944 len = 0;
06945 getforward = 0;
06946 } else {
06947 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06948 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06949 if (!ast_strlen_zero(p->cid_num)) {
06950 if (!p->hidecallerid)
06951 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06952 else
06953 ast_set_callerid(chan, NULL, NULL, p->cid_num);
06954 }
06955 if (!ast_strlen_zero(p->cid_name)) {
06956 if (!p->hidecallerid)
06957 ast_set_callerid(chan, NULL, p->cid_name, NULL);
06958 }
06959 ast_setstate(chan, AST_STATE_RING);
06960 dahdi_enable_ec(p);
06961 res = ast_pbx_run(chan);
06962 if (res) {
06963 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06964 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06965 }
06966 goto quit;
06967 }
06968 } else {
06969
06970
06971 timeout = matchdigittimeout;
06972 }
06973 } else if (res == 0) {
06974 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
06975 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06976 dahdi_wait_event(p->subs[idx].dfd);
06977 ast_hangup(chan);
06978 goto quit;
06979 } else if (p->callwaiting && !strcmp(exten, "*70")) {
06980 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
06981
06982 p->callwaiting = 0;
06983 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06984 if (res) {
06985 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06986 chan->name, strerror(errno));
06987 }
06988 len = 0;
06989 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
06990 memset(exten, 0, sizeof(exten));
06991 timeout = firstdigittimeout;
06992
06993 } else if (!strcmp(exten,ast_pickup_ext())) {
06994
06995
06996
06997
06998 if (idx == SUB_REAL) {
06999
07000 if (p->subs[SUB_THREEWAY].owner) {
07001
07002
07003 alloc_sub(p, SUB_CALLWAIT);
07004 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07005 unalloc_sub(p, SUB_THREEWAY);
07006 }
07007 dahdi_enable_ec(p);
07008 if (ast_pickup_call(chan)) {
07009 ast_debug(1, "No call pickup possible...\n");
07010 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07011 dahdi_wait_event(p->subs[idx].dfd);
07012 }
07013 ast_hangup(chan);
07014 goto quit;
07015 } else {
07016 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07017 ast_hangup(chan);
07018 goto quit;
07019 }
07020
07021 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07022 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
07023
07024 p->hidecallerid = 1;
07025 if (chan->cid.cid_num)
07026 ast_free(chan->cid.cid_num);
07027 chan->cid.cid_num = NULL;
07028 if (chan->cid.cid_name)
07029 ast_free(chan->cid.cid_name);
07030 chan->cid.cid_name = NULL;
07031 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07032 if (res) {
07033 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07034 chan->name, strerror(errno));
07035 }
07036 len = 0;
07037 memset(exten, 0, sizeof(exten));
07038 timeout = firstdigittimeout;
07039 } else if (p->callreturn && !strcmp(exten, "*69")) {
07040 res = 0;
07041 if (!ast_strlen_zero(p->lastcid_num)) {
07042 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07043 }
07044 if (!res)
07045 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07046 break;
07047 } else if (!strcmp(exten, "*78")) {
07048 dahdi_dnd(p, 1);
07049
07050 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07051 getforward = 0;
07052 memset(exten, 0, sizeof(exten));
07053 len = 0;
07054 } else if (!strcmp(exten, "*79")) {
07055 dahdi_dnd(p, 0);
07056
07057 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07058 getforward = 0;
07059 memset(exten, 0, sizeof(exten));
07060 len = 0;
07061 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07062 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07063 getforward = 1;
07064 memset(exten, 0, sizeof(exten));
07065 len = 0;
07066 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07067 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
07068 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07069 memset(p->call_forward, 0, sizeof(p->call_forward));
07070 getforward = 0;
07071 memset(exten, 0, sizeof(exten));
07072 len = 0;
07073 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07074 p->subs[SUB_THREEWAY].owner &&
07075 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07076
07077
07078 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07079 ast_verb(3, "Parking call to '%s'\n", chan->name);
07080 break;
07081 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07082 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
07083 res = ast_db_put("blacklist", p->lastcid_num, "1");
07084 if (!res) {
07085 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07086 memset(exten, 0, sizeof(exten));
07087 len = 0;
07088 }
07089 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07090 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
07091
07092 p->hidecallerid = 0;
07093 if (chan->cid.cid_num)
07094 ast_free(chan->cid.cid_num);
07095 chan->cid.cid_num = NULL;
07096 if (chan->cid.cid_name)
07097 ast_free(chan->cid.cid_name);
07098 chan->cid.cid_name = NULL;
07099 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07100 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07101 if (res) {
07102 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07103 chan->name, strerror(errno));
07104 }
07105 len = 0;
07106 memset(exten, 0, sizeof(exten));
07107 timeout = firstdigittimeout;
07108 } else if (!strcmp(exten, "*0")) {
07109 struct ast_channel *nbridge =
07110 p->subs[SUB_THREEWAY].owner;
07111 struct dahdi_pvt *pbridge = NULL;
07112
07113 if (nbridge && ast_bridged_channel(nbridge))
07114 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07115 if (nbridge && pbridge &&
07116 (nbridge->tech == &dahdi_tech) &&
07117 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
07118 ISTRUNK(pbridge)) {
07119 int func = DAHDI_FLASH;
07120
07121 p->dop.dialstr[0] = '\0';
07122
07123 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07124 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07125 nbridge->name, strerror(errno));
07126 }
07127 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07128 unalloc_sub(p, SUB_THREEWAY);
07129 p->owner = p->subs[SUB_REAL].owner;
07130 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07131 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07132 ast_hangup(chan);
07133 goto quit;
07134 } else {
07135 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07136 dahdi_wait_event(p->subs[idx].dfd);
07137 tone_zone_play_tone(p->subs[idx].dfd, -1);
07138 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07139 unalloc_sub(p, SUB_THREEWAY);
07140 p->owner = p->subs[SUB_REAL].owner;
07141 ast_hangup(chan);
07142 goto quit;
07143 }
07144 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07145 ((exten[0] != '*') || (strlen(exten) > 2))) {
07146 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
07147 break;
07148 }
07149 if (!timeout)
07150 timeout = gendigittimeout;
07151 if (len && !ast_ignore_pattern(chan->context, exten))
07152 tone_zone_play_tone(p->subs[idx].dfd, -1);
07153 }
07154 break;
07155 case SIG_FXSLS:
07156 case SIG_FXSGS:
07157 case SIG_FXSKS:
07158 #ifdef HAVE_PRI
07159 if (p->pri) {
07160
07161 struct ast_frame *f;
07162 int res;
07163 time_t start;
07164
07165 time(&start);
07166 ast_setstate(chan, AST_STATE_RING);
07167 while (time(NULL) < start + 3) {
07168 res = ast_waitfor(chan, 1000);
07169 if (res) {
07170 f = ast_read(chan);
07171 if (!f) {
07172 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07173 ast_hangup(chan);
07174 goto quit;
07175 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07176 res = 1;
07177 } else
07178 res = 0;
07179 ast_frfree(f);
07180 if (res) {
07181 ast_debug(1, "Got ring!\n");
07182 res = 0;
07183 break;
07184 }
07185 }
07186 }
07187 }
07188 #endif
07189
07190 if (p->use_smdi && p->smdi_iface) {
07191 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07192
07193 if (smdi_msg != NULL) {
07194 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07195
07196 if (smdi_msg->type == 'B')
07197 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07198 else if (smdi_msg->type == 'N')
07199 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07200
07201 ast_debug(1, "Recieved SMDI message on %s\n", chan->name);
07202 } else {
07203 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07204 }
07205 }
07206
07207 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07208 number = smdi_msg->calling_st;
07209
07210
07211
07212
07213 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
07214
07215 if (p->cid_signalling == CID_SIG_DTMF) {
07216 int k = 0;
07217 cs = NULL;
07218 ast_debug(1, "Receiving DTMF cid on "
07219 "channel %s\n", chan->name);
07220 dahdi_setlinear(p->subs[idx].dfd, 0);
07221 res = 2000;
07222 for (;;) {
07223 struct ast_frame *f;
07224 res = ast_waitfor(chan, res);
07225 if (res <= 0) {
07226 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07227 "Exiting simple switch\n");
07228 ast_hangup(chan);
07229 goto quit;
07230 }
07231 f = ast_read(chan);
07232 if (!f)
07233 break;
07234 if (f->frametype == AST_FRAME_DTMF) {
07235 dtmfbuf[k++] = f->subclass;
07236 ast_debug(1, "CID got digit '%c'\n", f->subclass);
07237 res = 2000;
07238 }
07239 ast_frfree(f);
07240 if (chan->_state == AST_STATE_RING ||
07241 chan->_state == AST_STATE_RINGING)
07242 break;
07243 }
07244 dtmfbuf[k] = '\0';
07245 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07246
07247 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
07248 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07249 ast_debug(1, "CID is '%s', flags %d\n",
07250 dtmfcid, flags);
07251
07252 if (!ast_strlen_zero(dtmfcid))
07253 number = dtmfcid;
07254 else
07255 number = NULL;
07256
07257 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07258 cs = callerid_new(p->cid_signalling);
07259 if (cs) {
07260 samples = 0;
07261 #if 1
07262 bump_gains(p);
07263 #endif
07264
07265 dahdi_setlinear(p->subs[idx].dfd, 0);
07266
07267
07268 for (;;) {
07269 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07270 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07271 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07272 callerid_free(cs);
07273 ast_hangup(chan);
07274 goto quit;
07275 }
07276 if (i & DAHDI_IOMUX_SIGEVENT) {
07277 res = dahdi_get_event(p->subs[idx].dfd);
07278 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07279
07280 if (p->cid_signalling == CID_SIG_V23_JP) {
07281 if (res == DAHDI_EVENT_RINGBEGIN) {
07282 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07283 usleep(1);
07284 }
07285 } else {
07286 res = 0;
07287 break;
07288 }
07289 } else if (i & DAHDI_IOMUX_READ) {
07290 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07291 if (res < 0) {
07292 if (errno != ELAST) {
07293 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07294 callerid_free(cs);
07295 ast_hangup(chan);
07296 goto quit;
07297 }
07298 break;
07299 }
07300 samples += res;
07301
07302 if (p->cid_signalling == CID_SIG_V23_JP) {
07303 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07304 } else {
07305 res = callerid_feed(cs, buf, res, AST_LAW(p));
07306 }
07307
07308 if (res < 0) {
07309 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07310 break;
07311 } else if (res)
07312 break;
07313 else if (samples > (8000 * 10))
07314 break;
07315 }
07316 }
07317 if (res == 1) {
07318 callerid_get(cs, &name, &number, &flags);
07319 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07320 }
07321
07322 if (p->cid_signalling == CID_SIG_V23_JP) {
07323 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07324 usleep(1);
07325 res = 4000;
07326 } else {
07327
07328
07329 res = 2000;
07330 }
07331
07332 for (;;) {
07333 struct ast_frame *f;
07334 res = ast_waitfor(chan, res);
07335 if (res <= 0) {
07336 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07337 "Exiting simple switch\n");
07338 ast_hangup(chan);
07339 goto quit;
07340 }
07341 if (!(f = ast_read(chan))) {
07342 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07343 ast_hangup(chan);
07344 goto quit;
07345 }
07346 ast_frfree(f);
07347 if (chan->_state == AST_STATE_RING ||
07348 chan->_state == AST_STATE_RINGING)
07349 break;
07350 }
07351
07352
07353
07354 if (p->usedistinctiveringdetection) {
07355 len = 0;
07356 distMatches = 0;
07357
07358 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07359 curRingData[receivedRingT] = 0;
07360 receivedRingT = 0;
07361 counter = 0;
07362 counter1 = 0;
07363
07364 if (strcmp(p->context,p->defcontext) != 0) {
07365 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07366 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07367 }
07368
07369 for (;;) {
07370 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07371 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07372 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07373 callerid_free(cs);
07374 ast_hangup(chan);
07375 goto quit;
07376 }
07377 if (i & DAHDI_IOMUX_SIGEVENT) {
07378 res = dahdi_get_event(p->subs[idx].dfd);
07379 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07380 res = 0;
07381
07382
07383 curRingData[receivedRingT] = p->ringt;
07384
07385 if (p->ringt < p->ringt_base/2)
07386 break;
07387
07388
07389 if (++receivedRingT == ARRAY_LEN(curRingData))
07390 break;
07391 } else if (i & DAHDI_IOMUX_READ) {
07392 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07393 if (res < 0) {
07394 if (errno != ELAST) {
07395 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07396 callerid_free(cs);
07397 ast_hangup(chan);
07398 goto quit;
07399 }
07400 break;
07401 }
07402 if (p->ringt)
07403 p->ringt--;
07404 if (p->ringt == 1) {
07405 res = -1;
07406 break;
07407 }
07408 }
07409 }
07410
07411 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07412 for (counter = 0; counter < 3; counter++) {
07413
07414
07415 distMatches = 0;
07416 for (counter1 = 0; counter1 < 3; counter1++) {
07417 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07418 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07419 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07420 curRingData[counter1]);
07421 distMatches++;
07422 }
07423 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07424 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07425 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07426 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07427 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07428 distMatches++;
07429 }
07430 }
07431
07432 if (distMatches == 3) {
07433
07434 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07435 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07436 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07437 break;
07438 }
07439 }
07440 }
07441
07442 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07443 #if 1
07444 restore_gains(p);
07445 #endif
07446 } else
07447 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07448 } else {
07449 ast_log(LOG_WARNING, "Channel %s in prering "
07450 "state, but I have nothing to do. "
07451 "Terminating simple switch, should be "
07452 "restarted by the actual ring.\n",
07453 chan->name);
07454 ast_hangup(chan);
07455 goto quit;
07456 }
07457 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07458 if (p->cid_signalling == CID_SIG_DTMF) {
07459 int k = 0;
07460 cs = NULL;
07461 dahdi_setlinear(p->subs[idx].dfd, 0);
07462 res = 2000;
07463 for (;;) {
07464 struct ast_frame *f;
07465 res = ast_waitfor(chan, res);
07466 if (res <= 0) {
07467 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07468 "Exiting simple switch\n");
07469 ast_hangup(chan);
07470 return NULL;
07471 }
07472 f = ast_read(chan);
07473 if (f->frametype == AST_FRAME_DTMF) {
07474 dtmfbuf[k++] = f->subclass;
07475 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07476 res = 2000;
07477 }
07478 ast_frfree(f);
07479
07480 if (p->ringt_base == p->ringt)
07481 break;
07482
07483 }
07484 dtmfbuf[k] = '\0';
07485 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07486
07487 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07488 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07489 dtmfcid, flags);
07490
07491 if (!ast_strlen_zero(dtmfcid))
07492 number = dtmfcid;
07493 else
07494 number = NULL;
07495
07496 } else {
07497
07498 cs = callerid_new(p->cid_signalling);
07499 if (cs) {
07500 #if 1
07501 bump_gains(p);
07502 #endif
07503 samples = 0;
07504 len = 0;
07505 distMatches = 0;
07506
07507 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07508 curRingData[receivedRingT] = 0;
07509 receivedRingT = 0;
07510 counter = 0;
07511 counter1 = 0;
07512
07513 if (strcmp(p->context,p->defcontext) != 0) {
07514 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07515 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07516 }
07517
07518
07519 dahdi_setlinear(p->subs[idx].dfd, 0);
07520 for (;;) {
07521 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07522 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07523 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07524 callerid_free(cs);
07525 ast_hangup(chan);
07526 goto quit;
07527 }
07528 if (i & DAHDI_IOMUX_SIGEVENT) {
07529 res = dahdi_get_event(p->subs[idx].dfd);
07530 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07531
07532 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07533 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07534 p->polarity = POLARITY_IDLE;
07535 callerid_free(cs);
07536 ast_hangup(chan);
07537 goto quit;
07538 }
07539 res = 0;
07540
07541
07542 curRingData[receivedRingT] = p->ringt;
07543
07544 if (p->ringt < p->ringt_base/2)
07545 break;
07546
07547
07548 if (++receivedRingT == ARRAY_LEN(curRingData))
07549 break;
07550 } else if (i & DAHDI_IOMUX_READ) {
07551 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07552 if (res < 0) {
07553 if (errno != ELAST) {
07554 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07555 callerid_free(cs);
07556 ast_hangup(chan);
07557 goto quit;
07558 }
07559 break;
07560 }
07561 if (p->ringt)
07562 p->ringt--;
07563 if (p->ringt == 1) {
07564 res = -1;
07565 break;
07566 }
07567 samples += res;
07568 res = callerid_feed(cs, buf, res, AST_LAW(p));
07569 if (res < 0) {
07570 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07571 break;
07572 } else if (res)
07573 break;
07574 else if (samples > (8000 * 10))
07575 break;
07576 }
07577 }
07578 if (res == 1) {
07579 callerid_get(cs, &name, &number, &flags);
07580 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07581 }
07582 if (distinctiveringaftercid == 1) {
07583
07584 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07585 curRingData[receivedRingT] = 0;
07586 }
07587 receivedRingT = 0;
07588 ast_verb(3, "Detecting post-CID distinctive ring\n");
07589 for (;;) {
07590 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07591 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07592 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07593 callerid_free(cs);
07594 ast_hangup(chan);
07595 goto quit;
07596 }
07597 if (i & DAHDI_IOMUX_SIGEVENT) {
07598 res = dahdi_get_event(p->subs[idx].dfd);
07599 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07600 res = 0;
07601
07602
07603 curRingData[receivedRingT] = p->ringt;
07604
07605 if (p->ringt < p->ringt_base/2)
07606 break;
07607
07608
07609 if (++receivedRingT == ARRAY_LEN(curRingData))
07610 break;
07611 } else if (i & DAHDI_IOMUX_READ) {
07612 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07613 if (res < 0) {
07614 if (errno != ELAST) {
07615 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07616 callerid_free(cs);
07617 ast_hangup(chan);
07618 goto quit;
07619 }
07620 break;
07621 }
07622 if (p->ringt)
07623 p->ringt--;
07624 if (p->ringt == 1) {
07625 res = -1;
07626 break;
07627 }
07628 }
07629 }
07630 }
07631 if (p->usedistinctiveringdetection) {
07632
07633 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07634
07635 for (counter = 0; counter < 3; counter++) {
07636
07637
07638
07639 ast_verb(3, "Checking %d,%d,%d\n",
07640 p->drings.ringnum[counter].ring[0],
07641 p->drings.ringnum[counter].ring[1],
07642 p->drings.ringnum[counter].ring[2]);
07643 distMatches = 0;
07644 for (counter1 = 0; counter1 < 3; counter1++) {
07645 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07646 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07647 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07648 curRingData[counter1]);
07649 distMatches++;
07650 }
07651 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07652 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07653 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07654 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07655 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07656 distMatches++;
07657 }
07658 }
07659 if (distMatches == 3) {
07660
07661 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07662 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07663 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07664 break;
07665 }
07666 }
07667 }
07668
07669 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07670 #if 1
07671 restore_gains(p);
07672 #endif
07673 if (res < 0) {
07674 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07675 }
07676 } else
07677 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07678 }
07679 }
07680 else
07681 cs = NULL;
07682
07683 if (number)
07684 ast_shrink_phone_number(number);
07685 ast_set_callerid(chan, number, name, number);
07686
07687 if (smdi_msg)
07688 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07689
07690 if (cs)
07691 callerid_free(cs);
07692
07693 if (flags & CID_MSGWAITING) {
07694 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
07695 notify_message(p->mailbox, 1);
07696
07697 if (p->mwimonitor_rpas) {
07698 ast_hangup(chan);
07699 return NULL;
07700 }
07701 } else if (flags & CID_NOMSGWAITING) {
07702 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
07703 notify_message(p->mailbox, 0);
07704
07705 if (p->mwimonitor_rpas) {
07706 ast_hangup(chan);
07707 return NULL;
07708 }
07709 }
07710
07711 ast_setstate(chan, AST_STATE_RING);
07712 chan->rings = 1;
07713 p->ringt = p->ringt_base;
07714 res = ast_pbx_run(chan);
07715 if (res) {
07716 ast_hangup(chan);
07717 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07718 }
07719 goto quit;
07720 default:
07721 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07722 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07723 if (res < 0)
07724 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07725 }
07726 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07727 if (res < 0)
07728 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07729 ast_hangup(chan);
07730 quit:
07731 ast_mutex_lock(&ss_thread_lock);
07732 ss_thread_count--;
07733 ast_cond_signal(&ss_thread_complete);
07734 ast_mutex_unlock(&ss_thread_lock);
07735 return NULL;
07736 }
07737
07738 struct mwi_thread_data {
07739 struct dahdi_pvt *pvt;
07740 unsigned char buf[READ_SIZE];
07741 size_t len;
07742 };
07743
07744 static int calc_energy(const unsigned char *buf, int len, int law)
07745 {
07746 int x;
07747 int sum = 0;
07748
07749 if (!len)
07750 return 0;
07751
07752 for (x = 0; x < len; x++)
07753 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07754
07755 return sum / len;
07756 }
07757
07758 static void *mwi_thread(void *data)
07759 {
07760 struct mwi_thread_data *mtd = data;
07761 struct callerid_state *cs;
07762 pthread_t threadid;
07763 int samples = 0;
07764 char *name, *number;
07765 int flags;
07766 int i, res;
07767 unsigned int spill_done = 0;
07768 int spill_result = -1;
07769
07770 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
07771 mtd->pvt->mwimonitoractive = 0;
07772
07773 return NULL;
07774 }
07775
07776 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
07777
07778 bump_gains(mtd->pvt);
07779
07780 for (;;) {
07781 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07782 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07783 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07784 goto quit;
07785 }
07786
07787 if (i & DAHDI_IOMUX_SIGEVENT) {
07788 struct ast_channel *chan;
07789
07790
07791
07792
07793 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07794
07795 switch (res) {
07796 case DAHDI_EVENT_NEONMWI_ACTIVE:
07797 case DAHDI_EVENT_NEONMWI_INACTIVE:
07798 case DAHDI_EVENT_NONE:
07799 case DAHDI_EVENT_BITSCHANGED:
07800 break;
07801 case DAHDI_EVENT_NOALARM:
07802 mtd->pvt->inalarm = 0;
07803 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
07804 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07805 "Channel: %d\r\n", mtd->pvt->channel);
07806 break;
07807 case DAHDI_EVENT_ALARM:
07808 mtd->pvt->inalarm = 1;
07809 res = get_alarms(mtd->pvt);
07810 handle_alarms(mtd->pvt, res);
07811 break;
07812 default:
07813 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
07814 callerid_free(cs);
07815
07816 restore_gains(mtd->pvt);
07817 mtd->pvt->ringt = mtd->pvt->ringt_base;
07818
07819 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
07820 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07821 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
07822 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07823 if (res < 0)
07824 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
07825 ast_hangup(chan);
07826 goto quit;
07827 }
07828 goto quit_no_clean;
07829
07830 } else {
07831 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
07832 }
07833 }
07834 } else if (i & DAHDI_IOMUX_READ) {
07835 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07836 if (errno != ELAST) {
07837 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07838 goto quit;
07839 }
07840 break;
07841 }
07842 samples += res;
07843 if (!spill_done) {
07844 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
07845 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07846 break;
07847 } else if (spill_result) {
07848 spill_done = 1;
07849 }
07850 } else {
07851
07852
07853
07854 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
07855 break;
07856 }
07857 if (samples > (8000 * 4))
07858 break;
07859 }
07860 }
07861
07862 if (spill_result == 1) {
07863 callerid_get(cs, &name, &number, &flags);
07864 if (flags & CID_MSGWAITING) {
07865 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
07866 notify_message(mtd->pvt->mailbox, 1);
07867 } else if (flags & CID_NOMSGWAITING) {
07868 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
07869 notify_message(mtd->pvt->mailbox, 0);
07870 } else {
07871 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
07872 }
07873 }
07874
07875
07876 quit:
07877 callerid_free(cs);
07878
07879 restore_gains(mtd->pvt);
07880
07881 quit_no_clean:
07882 mtd->pvt->mwimonitoractive = 0;
07883
07884 ast_free(mtd);
07885
07886 return NULL;
07887 }
07888
07889
07890
07891
07892 enum mwisend_states {
07893 MWI_SEND_SA,
07894 MWI_SEND_SA_WAIT,
07895 MWI_SEND_PAUSE,
07896 MWI_SEND_SPILL,
07897 MWI_SEND_CLEANUP,
07898 MWI_SEND_DONE
07899 };
07900
07901 static void *mwi_send_thread(void *data)
07902 {
07903 struct mwi_thread_data *mtd = data;
07904 struct timeval timeout_basis, suspend, now;
07905 int x, i, res;
07906 int num_read;
07907 enum mwisend_states mwi_send_state = MWI_SEND_SPILL;
07908
07909 ast_mutex_lock(&mwi_thread_lock);
07910 mwi_thread_count++;
07911 ast_mutex_unlock(&mwi_thread_lock);
07912
07913
07914 if(mwisend_rpas) {
07915 mwi_send_state = MWI_SEND_SA;
07916 }
07917
07918 gettimeofday(&timeout_basis, NULL);
07919
07920 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
07921 if (!mtd->pvt->cidspill) {
07922 mtd->pvt->mwisendactive = 0;
07923 ast_free(mtd);
07924 return NULL;
07925 }
07926 x = DAHDI_FLUSH_BOTH;
07927 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07928 x = 3000;
07929 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07930 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
07931 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
07932 mtd->pvt->cidpos = 0;
07933
07934 while (MWI_SEND_DONE != mwi_send_state) {
07935 num_read = 0;
07936 gettimeofday(&now, NULL);
07937 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
07938 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
07939 goto quit;
07940 }
07941
07942 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07943 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07944 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07945 goto quit;
07946 }
07947
07948 if (i & DAHDI_IOMUX_SIGEVENT) {
07949
07950
07951
07952 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07953 switch (res) {
07954 case DAHDI_EVENT_RINGEROFF:
07955 if(mwi_send_state == MWI_SEND_SA_WAIT) {
07956 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
07957 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
07958 goto quit;
07959 }
07960 mwi_send_state = MWI_SEND_PAUSE;
07961 gettimeofday(&suspend, NULL);
07962 }
07963 break;
07964 case DAHDI_EVENT_RINGERON:
07965 case DAHDI_EVENT_HOOKCOMPLETE:
07966 break;
07967 default:
07968
07969 if (0 < handle_init_event(mtd->pvt, res)) {
07970
07971 goto quit;
07972 }
07973 break;
07974 }
07975 } else if (i & DAHDI_IOMUX_READ) {
07976 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07977 if (errno != ELAST) {
07978 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07979 goto quit;
07980 }
07981 break;
07982 }
07983 }
07984
07985 switch ( mwi_send_state) {
07986 case MWI_SEND_SA:
07987
07988 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
07989 if (res) {
07990 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
07991 goto quit;
07992 }
07993 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING);
07994 mwi_send_state = MWI_SEND_SA_WAIT;
07995 break;
07996 case MWI_SEND_SA_WAIT:
07997 break;
07998 case MWI_SEND_PAUSE:
07999 gettimeofday(&now, NULL);
08000 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
08001 mwi_send_state = MWI_SEND_SPILL;
08002 }
08003 break;
08004 case MWI_SEND_SPILL:
08005
08006 if(0 < num_read) {
08007 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
08008 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
08009 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
08010 if (res > 0) {
08011 mtd->pvt->cidpos += res;
08012 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
08013 ast_free(mtd->pvt->cidspill);
08014 mtd->pvt->cidspill = NULL;
08015 mtd->pvt->cidpos = 0;
08016 mtd->pvt->cidlen = 0;
08017 mwi_send_state = MWI_SEND_CLEANUP;
08018 }
08019 } else {
08020 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
08021 goto quit;
08022 }
08023 }
08024 break;
08025 case MWI_SEND_CLEANUP:
08026
08027 mwi_send_state = MWI_SEND_DONE;
08028 break;
08029 default:
08030
08031 goto quit;
08032 break;
08033 }
08034 }
08035
08036 quit:
08037 if(mtd->pvt->cidspill) {
08038 ast_free(mtd->pvt->cidspill);
08039 mtd->pvt->cidspill = NULL;
08040 }
08041 mtd->pvt->mwisendactive = 0;
08042 ast_free(mtd);
08043
08044 ast_mutex_lock(&mwi_thread_lock);
08045 mwi_thread_count--;
08046 ast_cond_signal(&mwi_thread_complete);
08047 ast_mutex_unlock(&mwi_thread_lock);
08048
08049 return NULL;
08050 }
08051
08052
08053
08054 static int dahdi_destroy_channel_bynum(int channel)
08055 {
08056 struct dahdi_pvt *tmp = NULL;
08057 struct dahdi_pvt *prev = NULL;
08058
08059 tmp = iflist;
08060 while (tmp) {
08061 if (tmp->channel == channel) {
08062 int x = DAHDI_FLASH;
08063 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08064 destroy_channel(prev, tmp, 1);
08065 ast_module_unref(ast_module_info->self);
08066 return RESULT_SUCCESS;
08067 }
08068 prev = tmp;
08069 tmp = tmp->next;
08070 }
08071 return RESULT_FAILURE;
08072 }
08073
08074
08075 static int handle_init_event(struct dahdi_pvt *i, int event)
08076 {
08077 int res;
08078 int thread_spawned = 0;
08079 pthread_t threadid;
08080 struct ast_channel *chan;
08081
08082
08083
08084 switch (event) {
08085 case DAHDI_EVENT_NONE:
08086 case DAHDI_EVENT_BITSCHANGED:
08087 break;
08088 case DAHDI_EVENT_WINKFLASH:
08089 case DAHDI_EVENT_RINGOFFHOOK:
08090 if (i->inalarm) break;
08091 if (i->radio) break;
08092
08093 switch (i->sig) {
08094 case SIG_FXOLS:
08095 case SIG_FXOGS:
08096 case SIG_FXOKS:
08097 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08098 if (res && (errno == EBUSY))
08099 break;
08100 if (i->cidspill) {
08101
08102 ast_free(i->cidspill);
08103 i->cidspill = NULL;
08104 }
08105 if (i->immediate) {
08106 dahdi_enable_ec(i);
08107
08108 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08109 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08110 if (!chan) {
08111 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08112 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08113 if (res < 0)
08114 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08115 }
08116 } else {
08117
08118 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08119 if (chan) {
08120 if (has_voicemail(i))
08121 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08122 else
08123 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08124 if (res < 0)
08125 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08126 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08127 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08128 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08129 if (res < 0)
08130 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08131 ast_hangup(chan);
08132 } else {
08133 thread_spawned = 1;
08134 }
08135 } else
08136 ast_log(LOG_WARNING, "Unable to create channel\n");
08137 }
08138 break;
08139 case SIG_FXSLS:
08140 case SIG_FXSGS:
08141 case SIG_FXSKS:
08142 i->ringt = i->ringt_base;
08143
08144 case SIG_EMWINK:
08145 case SIG_FEATD:
08146 case SIG_FEATDMF:
08147 case SIG_FEATDMF_TA:
08148 case SIG_E911:
08149 case SIG_FGC_CAMA:
08150 case SIG_FGC_CAMAMF:
08151 case SIG_FEATB:
08152 case SIG_EM:
08153 case SIG_EM_E1:
08154 case SIG_SFWINK:
08155 case SIG_SF_FEATD:
08156 case SIG_SF_FEATDMF:
08157 case SIG_SF_FEATB:
08158 case SIG_SF:
08159
08160 if (i->cid_start == CID_START_POLARITY_IN) {
08161 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08162 } else {
08163 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08164 }
08165
08166 if (!chan) {
08167 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08168 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08169 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08170 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08171 if (res < 0) {
08172 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08173 }
08174 ast_hangup(chan);
08175 } else {
08176 thread_spawned = 1;
08177 }
08178 break;
08179 default:
08180 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08181 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08182 if (res < 0)
08183 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08184 return -1;
08185 }
08186 break;
08187 case DAHDI_EVENT_NOALARM:
08188 i->inalarm = 0;
08189 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08190 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08191 "Channel: %d\r\n", i->channel);
08192 break;
08193 case DAHDI_EVENT_ALARM:
08194 i->inalarm = 1;
08195 res = get_alarms(i);
08196 handle_alarms(i, res);
08197
08198 case DAHDI_EVENT_ONHOOK:
08199 if (i->radio)
08200 break;
08201
08202 switch (i->sig) {
08203 case SIG_FXOLS:
08204 case SIG_FXOGS:
08205 case SIG_FEATD:
08206 case SIG_FEATDMF:
08207 case SIG_FEATDMF_TA:
08208 case SIG_E911:
08209 case SIG_FGC_CAMA:
08210 case SIG_FGC_CAMAMF:
08211 case SIG_FEATB:
08212 case SIG_EM:
08213 case SIG_EM_E1:
08214 case SIG_EMWINK:
08215 case SIG_SF_FEATD:
08216 case SIG_SF_FEATDMF:
08217 case SIG_SF_FEATB:
08218 case SIG_SF:
08219 case SIG_SFWINK:
08220 case SIG_FXSLS:
08221 case SIG_FXSGS:
08222 case SIG_FXSKS:
08223 case SIG_GR303FXSKS:
08224 dahdi_disable_ec(i);
08225 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08226 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08227 break;
08228 case SIG_GR303FXOKS:
08229 case SIG_FXOKS:
08230 dahdi_disable_ec(i);
08231
08232 #ifdef ZHONE_HACK
08233 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08234 usleep(1);
08235 #endif
08236 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08237 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08238 break;
08239 case SIG_PRI:
08240 case SIG_SS7:
08241 case SIG_BRI:
08242 case SIG_BRI_PTMP:
08243 dahdi_disable_ec(i);
08244 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08245 break;
08246 default:
08247 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08248 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08249 return -1;
08250 }
08251 break;
08252 case DAHDI_EVENT_POLARITY:
08253 switch (i->sig) {
08254 case SIG_FXSLS:
08255 case SIG_FXSKS:
08256 case SIG_FXSGS:
08257
08258
08259
08260
08261 if (i->hanguponpolarityswitch)
08262 i->polarity = POLARITY_REV;
08263 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08264 i->polarity = POLARITY_REV;
08265 ast_verb(2, "Starting post polarity "
08266 "CID detection on channel %d\n",
08267 i->channel);
08268 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08269 if (!chan) {
08270 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08271 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08272 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08273 } else {
08274 thread_spawned = 1;
08275 }
08276 }
08277 break;
08278 default:
08279 ast_log(LOG_WARNING, "handle_init_event detected "
08280 "polarity reversal on non-FXO (SIG_FXS) "
08281 "interface %d\n", i->channel);
08282 }
08283 break;
08284 case DAHDI_EVENT_REMOVED:
08285 ast_log(LOG_NOTICE,
08286 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08287 i->channel);
08288 dahdi_destroy_channel_bynum(i->channel);
08289 break;
08290 case DAHDI_EVENT_NEONMWI_ACTIVE:
08291 if (i->mwimonitor_neon) {
08292 notify_message(i->mailbox, 1);
08293 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08294 }
08295 break;
08296 case DAHDI_EVENT_NEONMWI_INACTIVE:
08297 if (i->mwimonitor_neon) {
08298 notify_message(i->mailbox, 0);
08299 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08300 }
08301 break;
08302 }
08303 return thread_spawned;
08304 }
08305
08306 static void *do_monitor(void *data)
08307 {
08308 int count, res, res2, spoint, pollres=0;
08309 struct dahdi_pvt *i;
08310 struct dahdi_pvt *last = NULL;
08311 time_t thispass = 0, lastpass = 0;
08312 int found;
08313 char buf[1024];
08314 struct pollfd *pfds=NULL;
08315 int lastalloc = -1;
08316
08317
08318
08319 #if 0
08320 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08321 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08322 return NULL;
08323 }
08324 ast_debug(1, "Monitor starting...\n");
08325 #endif
08326 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08327
08328 for (;;) {
08329
08330 ast_mutex_lock(&iflock);
08331 if (!pfds || (lastalloc != ifcount)) {
08332 if (pfds) {
08333 ast_free(pfds);
08334 pfds = NULL;
08335 }
08336 if (ifcount) {
08337 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08338 ast_mutex_unlock(&iflock);
08339 return NULL;
08340 }
08341 }
08342 lastalloc = ifcount;
08343 }
08344
08345
08346 count = 0;
08347 i = iflist;
08348 while (i) {
08349 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08350 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
08351
08352 pfds[count].fd = i->subs[SUB_REAL].dfd;
08353 pfds[count].events = POLLPRI;
08354 pfds[count].revents = 0;
08355
08356
08357 if (i->cidspill || i->mwimonitor_fsk)
08358 pfds[count].events |= POLLIN;
08359 count++;
08360 }
08361 }
08362 i = i->next;
08363 }
08364
08365 ast_mutex_unlock(&iflock);
08366
08367 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08368 pthread_testcancel();
08369
08370 res = poll(pfds, count, 1000);
08371 pthread_testcancel();
08372 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08373
08374
08375 if (res < 0) {
08376 if ((errno != EAGAIN) && (errno != EINTR))
08377 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08378 continue;
08379 }
08380
08381
08382 ast_mutex_lock(&iflock);
08383 found = 0;
08384 spoint = 0;
08385 lastpass = thispass;
08386 thispass = time(NULL);
08387 i = iflist;
08388 while (i) {
08389 if (thispass != lastpass) {
08390 if (!found && ((i == last) || ((i == iflist) && !last))) {
08391 last = i;
08392 if (last) {
08393 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) {
08394 res = has_voicemail(last);
08395 if (last->msgstate != res) {
08396
08397
08398
08399
08400 pthread_attr_t attr;
08401 pthread_t threadid;
08402 struct mwi_thread_data *mtd;
08403 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08404 if (res2) {
08405
08406 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08407 }
08408 pthread_attr_init(&attr);
08409 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08410 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08411 last->msgstate = res;
08412 mtd->pvt = last;
08413 last->mwisendactive = 1;
08414 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
08415 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
08416 ast_free(mtd);
08417 last->mwisendactive = 0;
08418 }
08419 }
08420 found ++;
08421 }
08422 }
08423 last = last->next;
08424 }
08425 }
08426 }
08427 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08428 if (i->radio && !i->owner)
08429 {
08430 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08431 if (res)
08432 {
08433 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08434
08435 ast_mutex_unlock(&iflock);
08436 handle_init_event(i, res);
08437 ast_mutex_lock(&iflock);
08438 }
08439 i = i->next;
08440 continue;
08441 }
08442 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08443 if (pollres & POLLIN) {
08444 if (i->owner || i->subs[SUB_REAL].owner) {
08445 #ifdef HAVE_PRI
08446 if (!i->pri)
08447 #endif
08448 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08449 i = i->next;
08450 continue;
08451 }
08452 if (!i->cidspill && !i->mwimonitor_fsk) {
08453 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08454 i = i->next;
08455 continue;
08456 }
08457 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08458 if (res > 0) {
08459 if (i->mwimonitor_fsk) {
08460 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08461 pthread_attr_t attr;
08462 pthread_t threadid;
08463 struct mwi_thread_data *mtd;
08464
08465 pthread_attr_init(&attr);
08466 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08467
08468 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08469 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08470 mtd->pvt = i;
08471 memcpy(mtd->buf, buf, res);
08472 mtd->len = res;
08473 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08474 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08475 ast_free(mtd);
08476 }
08477 i->mwimonitoractive = 1;
08478 }
08479 }
08480 }
08481 } else {
08482 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08483 }
08484 }
08485 if (pollres & POLLPRI) {
08486 if (i->owner || i->subs[SUB_REAL].owner) {
08487 #ifdef HAVE_PRI
08488 if (!i->pri)
08489 #endif
08490 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08491 i = i->next;
08492 continue;
08493 }
08494 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08495 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08496
08497 ast_mutex_unlock(&iflock);
08498 handle_init_event(i, res);
08499 ast_mutex_lock(&iflock);
08500 }
08501 }
08502 i=i->next;
08503 }
08504 ast_mutex_unlock(&iflock);
08505 }
08506
08507 return NULL;
08508
08509 }
08510
08511 static int restart_monitor(void)
08512 {
08513
08514 if (monitor_thread == AST_PTHREADT_STOP)
08515 return 0;
08516 ast_mutex_lock(&monlock);
08517 if (monitor_thread == pthread_self()) {
08518 ast_mutex_unlock(&monlock);
08519 ast_log(LOG_WARNING, "Cannot kill myself\n");
08520 return -1;
08521 }
08522 if (monitor_thread != AST_PTHREADT_NULL) {
08523
08524 pthread_kill(monitor_thread, SIGURG);
08525 } else {
08526
08527 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08528 ast_mutex_unlock(&monlock);
08529 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08530 return -1;
08531 }
08532 }
08533 ast_mutex_unlock(&monlock);
08534 return 0;
08535 }
08536
08537 #ifdef HAVE_PRI
08538 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08539 {
08540 int x;
08541 int trunkgroup;
08542
08543 trunkgroup = pris[*span].mastertrunkgroup;
08544 if (trunkgroup) {
08545
08546 for (x = 0; x < NUM_SPANS; x++) {
08547 if (pris[x].trunkgroup == trunkgroup) {
08548 *span = x;
08549 return 0;
08550 }
08551 }
08552 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08553 *span = -1;
08554 } else {
08555 if (pris[*span].trunkgroup) {
08556 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08557 *span = -1;
08558 } else if (pris[*span].mastertrunkgroup) {
08559 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08560 *span = -1;
08561 } else {
08562 if (si->totalchans == 31) {
08563
08564 pris[*span].dchannels[0] = 16 + offset;
08565 } else if (si->totalchans == 24) {
08566
08567 pris[*span].dchannels[0] = 24 + offset;
08568 } else if (si->totalchans == 3) {
08569
08570 pris[*span].dchannels[0] = 3 + offset;
08571 } else {
08572 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);
08573 *span = -1;
08574 return 0;
08575 }
08576 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08577 pris[*span].offset = offset;
08578 pris[*span].span = *span + 1;
08579 }
08580 }
08581 return 0;
08582 }
08583
08584 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08585 {
08586 struct dahdi_spaninfo si;
08587 struct dahdi_params p;
08588 int fd;
08589 int span;
08590 int ospan=0;
08591 int x,y;
08592 for (x = 0; x < NUM_SPANS; x++) {
08593 if (pris[x].trunkgroup == trunkgroup) {
08594 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08595 return -1;
08596 }
08597 }
08598 for (y = 0; y < NUM_DCHANS; y++) {
08599 if (!channels[y])
08600 break;
08601 memset(&si, 0, sizeof(si));
08602 memset(&p, 0, sizeof(p));
08603 fd = open("/dev/dahdi/channel", O_RDWR);
08604 if (fd < 0) {
08605 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08606 return -1;
08607 }
08608 x = channels[y];
08609 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08610 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08611 close(fd);
08612 return -1;
08613 }
08614 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08615 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08616 return -1;
08617 }
08618 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08619 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08620 close(fd);
08621 return -1;
08622 }
08623 span = p.spanno - 1;
08624 if (pris[span].trunkgroup) {
08625 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08626 close(fd);
08627 return -1;
08628 }
08629 if (pris[span].pvts[0]) {
08630 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08631 close(fd);
08632 return -1;
08633 }
08634 if (!y) {
08635 pris[span].trunkgroup = trunkgroup;
08636 pris[span].offset = channels[y] - p.chanpos;
08637 ospan = span;
08638 }
08639 pris[ospan].dchannels[y] = channels[y];
08640 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08641 pris[span].span = span + 1;
08642 close(fd);
08643 }
08644 return 0;
08645 }
08646
08647 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08648 {
08649 if (pris[span].mastertrunkgroup) {
08650 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);
08651 return -1;
08652 }
08653 pris[span].mastertrunkgroup = trunkgroup;
08654 pris[span].prilogicalspan = logicalspan;
08655 return 0;
08656 }
08657
08658 #endif
08659
08660 #ifdef HAVE_SS7
08661
08662 static unsigned int parse_pointcode(const char *pcstring)
08663 {
08664 unsigned int code1, code2, code3;
08665 int numvals;
08666
08667 numvals = sscanf(pcstring, "%d-%d-%d", &code1, &code2, &code3);
08668 if (numvals == 1)
08669 return code1;
08670 if (numvals == 3)
08671 return (code1 << 16) | (code2 << 8) | code3;
08672
08673 return 0;
08674 }
08675
08676 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
08677 {
08678 if ((linkset < 0) || (linkset >= NUM_SPANS))
08679 return NULL;
08680 else
08681 return &linksets[linkset - 1];
08682 }
08683 #endif
08684
08685
08686
08687
08688
08689
08690 static int sigtype_to_signalling(int sigtype)
08691 {
08692 return sigtype;
08693 }
08694
08695 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08696 {
08697
08698 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08699 char fn[80];
08700 struct dahdi_bufferinfo bi;
08701
08702 int res;
08703 int span = 0;
08704 int here = 0;
08705 int x;
08706 struct dahdi_pvt **wlist;
08707 struct dahdi_pvt **wend;
08708 struct dahdi_params p;
08709
08710 wlist = &iflist;
08711 wend = &ifend;
08712
08713 #ifdef HAVE_PRI
08714 if (pri) {
08715 wlist = &pri->crvs;
08716 wend = &pri->crvend;
08717 }
08718 #endif
08719
08720 tmp2 = *wlist;
08721 prev = NULL;
08722
08723 while (tmp2) {
08724 if (!tmp2->destroy) {
08725 if (tmp2->channel == channel) {
08726 tmp = tmp2;
08727 here = 1;
08728 break;
08729 }
08730 if (tmp2->channel > channel) {
08731 break;
08732 }
08733 }
08734 prev = tmp2;
08735 tmp2 = tmp2->next;
08736 }
08737
08738 if (!here && reloading != 1) {
08739 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08740 if (tmp)
08741 free(tmp);
08742 return NULL;
08743 }
08744 ast_mutex_init(&tmp->lock);
08745 ifcount++;
08746 for (x = 0; x < 3; x++)
08747 tmp->subs[x].dfd = -1;
08748 tmp->channel = channel;
08749 }
08750
08751 if (tmp) {
08752 int chan_sig = conf->chan.sig;
08753 if (!here) {
08754 if ((channel != CHAN_PSEUDO) && !pri) {
08755 int count = 0;
08756 snprintf(fn, sizeof(fn), "%d", channel);
08757
08758 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08759 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08760 usleep(1);
08761 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08762 count++;
08763 }
08764
08765 if (tmp->subs[SUB_REAL].dfd < 0) {
08766 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);
08767 destroy_dahdi_pvt(&tmp);
08768 return NULL;
08769 }
08770 memset(&p, 0, sizeof(p));
08771 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08772 if (res < 0) {
08773 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08774 destroy_dahdi_pvt(&tmp);
08775 return NULL;
08776 }
08777 if (conf->is_sig_auto)
08778 chan_sig = sigtype_to_signalling(p.sigtype);
08779 if (p.sigtype != (chan_sig & 0x3ffff)) {
08780 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
08781 destroy_dahdi_pvt(&tmp);
08782 return NULL;
08783 }
08784 tmp->law = p.curlaw;
08785 tmp->span = p.spanno;
08786 span = p.spanno - 1;
08787 } else {
08788 if (channel == CHAN_PSEUDO)
08789 chan_sig = 0;
08790 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08791 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08792 return NULL;
08793 }
08794 }
08795 #ifdef HAVE_SS7
08796 if (chan_sig == SIG_SS7) {
08797 struct dahdi_ss7 *ss7;
08798 int clear = 0;
08799 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08800 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08801 destroy_dahdi_pvt(&tmp);
08802 return NULL;
08803 }
08804
08805 ss7 = ss7_resolve_linkset(cur_linkset);
08806 if (!ss7) {
08807 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08808 destroy_dahdi_pvt(&tmp);
08809 return NULL;
08810 }
08811 if (cur_cicbeginswith < 0) {
08812 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08813 destroy_dahdi_pvt(&tmp);
08814 return NULL;
08815 }
08816
08817 tmp->cic = cur_cicbeginswith++;
08818
08819
08820 tmp->dpc = cur_defaultdpc;
08821
08822 tmp->ss7 = ss7;
08823 tmp->ss7call = NULL;
08824 ss7->pvts[ss7->numchans++] = tmp;
08825
08826 ast_copy_string(linksets[span].internationalprefix, conf->ss7.internationalprefix, sizeof(linksets[span].internationalprefix));
08827 ast_copy_string(linksets[span].nationalprefix, conf->ss7.nationalprefix, sizeof(linksets[span].nationalprefix));
08828 ast_copy_string(linksets[span].subscriberprefix, conf->ss7.subscriberprefix, sizeof(linksets[span].subscriberprefix));
08829 ast_copy_string(linksets[span].unknownprefix, conf->ss7.unknownprefix, sizeof(linksets[span].unknownprefix));
08830
08831 linksets[span].called_nai = conf->ss7.called_nai;
08832 linksets[span].calling_nai = conf->ss7.calling_nai;
08833 }
08834 #endif
08835 #ifdef HAVE_PRI
08836 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08837 int offset;
08838 int myswitchtype;
08839 int matchesdchan;
08840 int x,y;
08841 offset = 0;
08842 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
08843 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08844 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08845 destroy_dahdi_pvt(&tmp);
08846 return NULL;
08847 }
08848 if (span >= NUM_SPANS) {
08849 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08850 destroy_dahdi_pvt(&tmp);
08851 return NULL;
08852 } else {
08853 struct dahdi_spaninfo si;
08854 si.spanno = 0;
08855 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08856 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08857 destroy_dahdi_pvt(&tmp);
08858 return NULL;
08859 }
08860
08861 tmp->logicalspan = pris[span].prilogicalspan;
08862 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08863 if (span < 0) {
08864 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08865 destroy_dahdi_pvt(&tmp);
08866 return NULL;
08867 }
08868 if ((chan_sig == SIG_PRI) ||
08869 (chan_sig == SIG_BRI) ||
08870 (chan_sig == SIG_BRI_PTMP))
08871 myswitchtype = conf->pri.switchtype;
08872 else
08873 myswitchtype = PRI_SWITCH_GR303_TMC;
08874
08875 matchesdchan=0;
08876 for (x = 0; x < NUM_SPANS; x++) {
08877 for (y = 0; y < NUM_DCHANS; y++) {
08878 if (pris[x].dchannels[y] == tmp->channel) {
08879 matchesdchan = 1;
08880 break;
08881 }
08882 }
08883 }
08884 offset = p.chanpos;
08885 if (!matchesdchan) {
08886 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08887 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08888 destroy_dahdi_pvt(&tmp);
08889 return NULL;
08890 }
08891 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08892 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08893 destroy_dahdi_pvt(&tmp);
08894 return NULL;
08895 }
08896 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08897 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08898 destroy_dahdi_pvt(&tmp);
08899 return NULL;
08900 }
08901 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08902 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08903 destroy_dahdi_pvt(&tmp);
08904 return NULL;
08905 }
08906 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08907 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08908 destroy_dahdi_pvt(&tmp);
08909 return NULL;
08910 }
08911 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08912 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08913 destroy_dahdi_pvt(&tmp);
08914 return NULL;
08915 }
08916 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08917 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08918 destroy_dahdi_pvt(&tmp);
08919 return NULL;
08920 }
08921 if (pris[span].numchans >= MAX_CHANNELS) {
08922 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08923 pris[span].trunkgroup);
08924 destroy_dahdi_pvt(&tmp);
08925 return NULL;
08926 }
08927
08928 pris[span].sig = chan_sig;
08929 pris[span].nodetype = conf->pri.nodetype;
08930 pris[span].switchtype = myswitchtype;
08931 pris[span].nsf = conf->pri.nsf;
08932 pris[span].dialplan = conf->pri.dialplan;
08933 pris[span].localdialplan = conf->pri.localdialplan;
08934 pris[span].pvts[pris[span].numchans++] = tmp;
08935 pris[span].minunused = conf->pri.minunused;
08936 pris[span].minidle = conf->pri.minidle;
08937 pris[span].overlapdial = conf->pri.overlapdial;
08938 #ifdef HAVE_PRI_INBANDDISCONNECT
08939 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08940 #endif
08941 pris[span].facilityenable = conf->pri.facilityenable;
08942 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08943 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08944 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08945 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08946 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08947 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08948 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08949 pris[span].resetinterval = conf->pri.resetinterval;
08950
08951 tmp->pri = &pris[span];
08952 tmp->prioffset = offset;
08953 tmp->call = NULL;
08954 } else {
08955 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08956 destroy_dahdi_pvt(&tmp);
08957 return NULL;
08958 }
08959 }
08960 } else {
08961 tmp->prioffset = 0;
08962 }
08963 #endif
08964 } else {
08965 chan_sig = tmp->sig;
08966 if (tmp->subs[SUB_REAL].dfd > -1) {
08967 memset(&p, 0, sizeof(p));
08968 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08969 }
08970 }
08971
08972 switch (chan_sig) {
08973 case SIG_FXSKS:
08974 case SIG_FXSLS:
08975 case SIG_EM:
08976 case SIG_EM_E1:
08977 case SIG_EMWINK:
08978 case SIG_FEATD:
08979 case SIG_FEATDMF:
08980 case SIG_FEATDMF_TA:
08981 case SIG_FEATB:
08982 case SIG_E911:
08983 case SIG_SF:
08984 case SIG_SFWINK:
08985 case SIG_FGC_CAMA:
08986 case SIG_FGC_CAMAMF:
08987 case SIG_SF_FEATD:
08988 case SIG_SF_FEATDMF:
08989 case SIG_SF_FEATB:
08990 p.starttime = 250;
08991 break;
08992 }
08993
08994 if (tmp->radio) {
08995
08996 p.channo = channel;
08997 p.rxwinktime = 1;
08998 p.rxflashtime = 1;
08999 p.starttime = 1;
09000 p.debouncetime = 5;
09001 }
09002 if (!tmp->radio) {
09003 p.channo = channel;
09004
09005 if (conf->timing.prewinktime >= 0)
09006 p.prewinktime = conf->timing.prewinktime;
09007 if (conf->timing.preflashtime >= 0)
09008 p.preflashtime = conf->timing.preflashtime;
09009 if (conf->timing.winktime >= 0)
09010 p.winktime = conf->timing.winktime;
09011 if (conf->timing.flashtime >= 0)
09012 p.flashtime = conf->timing.flashtime;
09013 if (conf->timing.starttime >= 0)
09014 p.starttime = conf->timing.starttime;
09015 if (conf->timing.rxwinktime >= 0)
09016 p.rxwinktime = conf->timing.rxwinktime;
09017 if (conf->timing.rxflashtime >= 0)
09018 p.rxflashtime = conf->timing.rxflashtime;
09019 if (conf->timing.debouncetime >= 0)
09020 p.debouncetime = conf->timing.debouncetime;
09021 }
09022
09023
09024 if (tmp->subs[SUB_REAL].dfd >= 0)
09025 {
09026 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09027 if (res < 0) {
09028 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09029 destroy_dahdi_pvt(&tmp);
09030 return NULL;
09031 }
09032 }
09033 #if 1
09034 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09035 memset(&bi, 0, sizeof(bi));
09036 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09037 if (!res) {
09038 bi.txbufpolicy = conf->chan.buf_policy;
09039 bi.rxbufpolicy = conf->chan.buf_policy;
09040 bi.numbufs = conf->chan.buf_no;
09041 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09042 if (res < 0) {
09043 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09044 }
09045 } else
09046 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09047 }
09048 #endif
09049 tmp->immediate = conf->chan.immediate;
09050 tmp->transfertobusy = conf->chan.transfertobusy;
09051 if (chan_sig & __DAHDI_SIG_FXS) {
09052 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
09053 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
09054 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
09055 }
09056 tmp->sig = chan_sig;
09057 tmp->outsigmod = conf->chan.outsigmod;
09058 tmp->ringt_base = ringt_base;
09059 tmp->firstradio = 0;
09060 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09061 tmp->permcallwaiting = conf->chan.callwaiting;
09062 else
09063 tmp->permcallwaiting = 0;
09064
09065 tmp->destroy = 0;
09066 tmp->drings = conf->chan.drings;
09067
09068
09069 if (tmp->drings.ringnum[0].range == 0)
09070 tmp->drings.ringnum[0].range = 10;
09071 if (tmp->drings.ringnum[1].range == 0)
09072 tmp->drings.ringnum[1].range = 10;
09073 if (tmp->drings.ringnum[2].range == 0)
09074 tmp->drings.ringnum[2].range = 10;
09075
09076 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
09077 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09078 tmp->threewaycalling = conf->chan.threewaycalling;
09079 tmp->adsi = conf->chan.adsi;
09080 tmp->use_smdi = conf->chan.use_smdi;
09081 tmp->permhidecallerid = conf->chan.hidecallerid;
09082 tmp->callreturn = conf->chan.callreturn;
09083 tmp->echocancel = conf->chan.echocancel;
09084 tmp->echotraining = conf->chan.echotraining;
09085 tmp->pulse = conf->chan.pulse;
09086 if (tmp->echocancel.head.tap_length) {
09087 tmp->echocanbridged = conf->chan.echocanbridged;
09088 } else {
09089 if (conf->chan.echocanbridged)
09090 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09091 tmp->echocanbridged = 0;
09092 }
09093 tmp->busydetect = conf->chan.busydetect;
09094 tmp->busycount = conf->chan.busycount;
09095 tmp->busycompare = conf->chan.busycompare;
09096 tmp->busytonelength = conf->chan.busytonelength;
09097 tmp->busyquietlength = conf->chan.busyquietlength;
09098 tmp->busyfuzziness = conf->chan.busyfuzziness;
09099 tmp->silencethreshold = conf->chan.silencethreshold;
09100 tmp->callprogress = conf->chan.callprogress;
09101 tmp->cancallforward = conf->chan.cancallforward;
09102 tmp->dtmfrelax = conf->chan.dtmfrelax;
09103 tmp->callwaiting = tmp->permcallwaiting;
09104 tmp->hidecallerid = tmp->permhidecallerid;
09105 tmp->channel = channel;
09106 tmp->stripmsd = conf->chan.stripmsd;
09107 tmp->use_callerid = conf->chan.use_callerid;
09108 tmp->cid_signalling = conf->chan.cid_signalling;
09109 tmp->cid_start = conf->chan.cid_start;
09110 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09111 tmp->restrictcid = conf->chan.restrictcid;
09112 tmp->use_callingpres = conf->chan.use_callingpres;
09113 tmp->priindication_oob = conf->chan.priindication_oob;
09114 tmp->priexclusive = conf->chan.priexclusive;
09115 if (tmp->usedistinctiveringdetection) {
09116 if (!tmp->use_callerid) {
09117 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09118 tmp->use_callerid = 1;
09119 }
09120 }
09121
09122 if (tmp->cid_signalling == CID_SIG_SMDI) {
09123 if (!tmp->use_smdi) {
09124 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09125 tmp->use_smdi = 1;
09126 }
09127 }
09128 if (tmp->use_smdi) {
09129 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09130 if (!(tmp->smdi_iface)) {
09131 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09132 tmp->use_smdi = 0;
09133 }
09134 }
09135
09136 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09137 tmp->amaflags = conf->chan.amaflags;
09138 if (!here) {
09139 tmp->confno = -1;
09140 tmp->propconfno = -1;
09141 }
09142 tmp->canpark = conf->chan.canpark;
09143 tmp->transfer = conf->chan.transfer;
09144 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09145 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09146 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09147 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09148 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09149 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09150 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
09151 tmp->cid_ton = 0;
09152 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09153 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09154 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
09155 char *mailbox, *context;
09156 mailbox = context = ast_strdupa(tmp->mailbox);
09157 strsep(&context, "@");
09158 if (ast_strlen_zero(context))
09159 context = "default";
09160 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
09161 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
09162 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
09163 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
09164 AST_EVENT_IE_END);
09165 }
09166 tmp->msgstate = -1;
09167 tmp->group = conf->chan.group;
09168 tmp->callgroup = conf->chan.callgroup;
09169 tmp->pickupgroup= conf->chan.pickupgroup;
09170 if (conf->chan.vars) {
09171 tmp->vars = conf->chan.vars;
09172 }
09173 tmp->cid_rxgain = conf->chan.cid_rxgain;
09174 tmp->rxgain = conf->chan.rxgain;
09175 tmp->txgain = conf->chan.txgain;
09176 tmp->tonezone = conf->chan.tonezone;
09177 tmp->onhooktime = time(NULL);
09178 if (tmp->subs[SUB_REAL].dfd > -1) {
09179 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09180 if (tmp->dsp)
09181 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09182 update_conf(tmp);
09183 if (!here) {
09184 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
09185
09186 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09187 }
09188 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09189 #ifdef HAVE_PRI
09190
09191 if (tmp->pri && !pri_is_up(tmp->pri))
09192 tmp->inalarm = 1;
09193 #endif
09194 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09195 tmp->inalarm = 1;
09196 handle_alarms(tmp, res);
09197 }
09198 }
09199
09200 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09201 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09202 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09203 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09204 if (!here) {
09205 tmp->locallyblocked = tmp->remotelyblocked = 0;
09206 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09207 tmp->inservice = 0;
09208 else
09209 tmp->inservice = 1;
09210 }
09211 }
09212 if (tmp && !here) {
09213
09214 if (!*wlist) {
09215 *wlist = tmp;
09216 tmp->prev = NULL;
09217 tmp->next = NULL;
09218 *wend = tmp;
09219 } else {
09220
09221 struct dahdi_pvt *working = *wlist;
09222
09223
09224 if (working->channel > tmp->channel) {
09225 tmp->next = *wlist;
09226 tmp->prev = NULL;
09227 (*wlist)->prev = tmp;
09228 *wlist = tmp;
09229 } else {
09230
09231 while (working) {
09232
09233 if (working->next) {
09234 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09235 tmp->next = working->next;
09236 tmp->prev = working;
09237 working->next->prev = tmp;
09238 working->next = tmp;
09239 break;
09240 }
09241 } else {
09242
09243 if (working->channel < tmp->channel) {
09244 working->next = tmp;
09245 tmp->next = NULL;
09246 tmp->prev = working;
09247 *wend = tmp;
09248 break;
09249 }
09250 }
09251 working = working->next;
09252 }
09253 }
09254 }
09255 }
09256 return tmp;
09257 }
09258
09259 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09260 {
09261 int res;
09262 struct dahdi_params par;
09263
09264
09265 if (groupmatch) {
09266 if ((p->group & groupmatch) != groupmatch)
09267 return 0;
09268 *groupmatched = 1;
09269 }
09270
09271 if (channelmatch != -1) {
09272 if (p->channel != channelmatch)
09273 return 0;
09274 *channelmatched = 1;
09275 }
09276
09277 if (busy) {
09278 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09279 *busy = 1;
09280 }
09281
09282 if (p->dnd)
09283 return 0;
09284
09285 if (p->guardtime && (time(NULL) < p->guardtime))
09286 return 0;
09287
09288 if (p->locallyblocked || p->remotelyblocked)
09289 return 0;
09290
09291
09292 if (!p->owner) {
09293 #ifdef HAVE_PRI
09294
09295 if (p->pri) {
09296 if (p->resetting || p->call)
09297 return 0;
09298 else
09299 return 1;
09300 }
09301 #endif
09302 #ifdef HAVE_SS7
09303
09304 if (p->ss7) {
09305 if (p->ss7call)
09306 return 0;
09307 else
09308 return 1;
09309 }
09310 #endif
09311 if (!(p->radio || (p->oprmode < 0)))
09312 {
09313 if (!p->sig || (p->sig == SIG_FXSLS))
09314 return 1;
09315
09316 if (p->subs[SUB_REAL].dfd > -1) {
09317 memset(&par, 0, sizeof(par));
09318 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09319 } else {
09320
09321 res = 0;
09322 par.rxisoffhook = 0;
09323 }
09324 if (res) {
09325 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09326 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09327
09328
09329
09330 if (par.rxbits > -1)
09331 return 1;
09332 if (par.rxisoffhook)
09333 return 1;
09334 else
09335 return 0;
09336 } else if (par.rxisoffhook) {
09337 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09338
09339 #ifdef DAHDI_CHECK_HOOKSTATE
09340 return 0;
09341 #else
09342 return 1;
09343 #endif
09344 }
09345 }
09346 return 1;
09347 }
09348
09349
09350 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09351 return 0;
09352
09353 if (!p->callwaiting) {
09354
09355 return 0;
09356 }
09357
09358 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09359
09360 return 0;
09361 }
09362
09363 if ((p->owner->_state != AST_STATE_UP) &&
09364 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09365
09366 return 0;
09367 }
09368 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09369
09370 return 0;
09371 }
09372
09373 return 1;
09374 }
09375
09376 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09377 {
09378 struct dahdi_pvt *p;
09379 struct dahdi_bufferinfo bi;
09380 int res;
09381
09382 if ((p = ast_malloc(sizeof(*p)))) {
09383 memcpy(p, src, sizeof(struct dahdi_pvt));
09384 ast_mutex_init(&p->lock);
09385 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09386
09387 if (p->subs[SUB_REAL].dfd < 0) {
09388 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09389 destroy_dahdi_pvt(&p);
09390 return NULL;
09391 }
09392 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09393 if (!res) {
09394 bi.txbufpolicy = src->buf_policy;
09395 bi.rxbufpolicy = src->buf_policy;
09396 bi.numbufs = src->buf_no;
09397 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09398 if (res < 0) {
09399 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09400 }
09401 } else
09402 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09403 }
09404 p->destroy = 1;
09405 p->next = iflist;
09406 p->prev = NULL;
09407 iflist = p;
09408 if (iflist->next)
09409 iflist->next->prev = p;
09410 return p;
09411 }
09412
09413
09414 #ifdef HAVE_PRI
09415 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09416 {
09417 int x;
09418 if (backwards)
09419 x = pri->numchans;
09420 else
09421 x = 0;
09422 for (;;) {
09423 if (backwards && (x < 0))
09424 break;
09425 if (!backwards && (x >= pri->numchans))
09426 break;
09427 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09428 ast_debug(1, "Found empty available channel %d/%d\n",
09429 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09430 return x;
09431 }
09432 if (backwards)
09433 x--;
09434 else
09435 x++;
09436 }
09437 return -1;
09438 }
09439 #endif
09440
09441 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09442 {
09443 ast_group_t groupmatch = 0;
09444 int channelmatch = -1;
09445 int roundrobin = 0;
09446 int callwait = 0;
09447 int busy = 0;
09448 struct dahdi_pvt *p;
09449 struct ast_channel *tmp = NULL;
09450 char *dest=NULL;
09451 int x;
09452 char *s;
09453 char opt=0;
09454 int res=0, y=0;
09455 int backwards = 0;
09456 #ifdef HAVE_PRI
09457 int crv;
09458 int bearer = -1;
09459 int trunkgroup;
09460 struct dahdi_pri *pri=NULL;
09461 #endif
09462 struct dahdi_pvt *exitpvt, *start, *end;
09463 ast_mutex_t *lock;
09464 int channelmatched = 0;
09465 int groupmatched = 0;
09466
09467
09468
09469
09470
09471
09472
09473
09474
09475
09476
09477
09478
09479
09480
09481
09482
09483
09484
09485 lock = &iflock;
09486 start = iflist;
09487 end = ifend;
09488 if (data) {
09489 dest = ast_strdupa((char *)data);
09490 } else {
09491 ast_log(LOG_WARNING, "Channel requested with no data\n");
09492 return NULL;
09493 }
09494 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09495
09496 char *stringp;
09497
09498 stringp = dest + 1;
09499 s = strsep(&stringp, "/");
09500 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
09501 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09502 return NULL;
09503 }
09504 groupmatch = ((ast_group_t) 1 << x);
09505 if (toupper(dest[0]) == 'G') {
09506 if (dest[0] == 'G') {
09507 backwards = 1;
09508 p = ifend;
09509 } else
09510 p = iflist;
09511 } else {
09512 if (dest[0] == 'R') {
09513 backwards = 1;
09514 p = round_robin[x]?round_robin[x]->prev:ifend;
09515 if (!p)
09516 p = ifend;
09517 } else {
09518 p = round_robin[x]?round_robin[x]->next:iflist;
09519 if (!p)
09520 p = iflist;
09521 }
09522 roundrobin = 1;
09523 }
09524 } else {
09525 char *stringp;
09526
09527 stringp = dest;
09528 s = strsep(&stringp, "/");
09529 p = iflist;
09530 if (!strcasecmp(s, "pseudo")) {
09531
09532 x = CHAN_PSEUDO;
09533 channelmatch = x;
09534 }
09535 #ifdef HAVE_PRI
09536 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
09537 if ((trunkgroup < 1) || (crv < 1)) {
09538 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09539 return NULL;
09540 }
09541 res--;
09542 for (x = 0; x < NUM_SPANS; x++) {
09543 if (pris[x].trunkgroup == trunkgroup) {
09544 pri = pris + x;
09545 lock = &pri->lock;
09546 start = pri->crvs;
09547 end = pri->crvend;
09548 break;
09549 }
09550 }
09551 if (!pri) {
09552 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09553 return NULL;
09554 }
09555 channelmatch = crv;
09556 p = pris[x].crvs;
09557 }
09558 #endif
09559 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
09560 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09561 return NULL;
09562 } else {
09563 channelmatch = x;
09564 }
09565 }
09566
09567 ast_mutex_lock(lock);
09568 exitpvt = p;
09569 while (p && !tmp) {
09570 if (roundrobin)
09571 round_robin[x] = p;
09572 #if 0
09573 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09574 #endif
09575
09576 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09577 ast_debug(1, "Using channel %d\n", p->channel);
09578 if (p->inalarm)
09579 goto next;
09580
09581 callwait = (p->owner != NULL);
09582 #ifdef HAVE_PRI
09583 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09584 if (p->sig != SIG_FXSKS) {
09585
09586
09587 bearer = pri_find_empty_chan(pri, 0);
09588 if (bearer < 0) {
09589 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09590 p = NULL;
09591 break;
09592 }
09593 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09594 } else {
09595 if (alloc_sub(p, 0)) {
09596 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09597 p = NULL;
09598 break;
09599 } else
09600 ast_debug(1, "Allocated placeholder pseudo channel\n");
09601
09602 p->pri = pri;
09603 }
09604 }
09605 #endif
09606 if (p->channel == CHAN_PSEUDO) {
09607 p = chandup(p);
09608 if (!p) {
09609 break;
09610 }
09611 }
09612 if (p->owner) {
09613 if (alloc_sub(p, SUB_CALLWAIT)) {
09614 p = NULL;
09615 break;
09616 }
09617 }
09618 p->outgoing = 1;
09619 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09620 #ifdef HAVE_PRI
09621 if (p->bearer) {
09622
09623 p->bearer->owner = tmp;
09624 }
09625 #endif
09626
09627 if (res > 1) {
09628 if (opt == 'c') {
09629
09630 p->confirmanswer = 1;
09631 } else if (opt == 'r') {
09632
09633 if (res < 3)
09634 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09635 else
09636 p->distinctivering = y;
09637 } else if (opt == 'd') {
09638
09639 p->digital = 1;
09640 if (tmp)
09641 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09642 } else {
09643 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09644 }
09645 }
09646
09647 if (tmp && callwait)
09648 tmp->cdrflags |= AST_CDR_CALLWAIT;
09649 break;
09650 }
09651 next:
09652 if (backwards) {
09653 p = p->prev;
09654 if (!p)
09655 p = end;
09656 } else {
09657 p = p->next;
09658 if (!p)
09659 p = start;
09660 }
09661
09662 if (p == exitpvt)
09663 break;
09664 }
09665 ast_mutex_unlock(lock);
09666 restart_monitor();
09667 if (callwait)
09668 *cause = AST_CAUSE_BUSY;
09669 else if (!tmp) {
09670 if (channelmatched) {
09671 if (busy)
09672 *cause = AST_CAUSE_BUSY;
09673 } else if (groupmatched) {
09674 *cause = AST_CAUSE_CONGESTION;
09675 }
09676 }
09677
09678 return tmp;
09679 }
09680
09681 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09682 static int dahdi_setlaw(int dfd, int law)
09683 {
09684 return ioctl(dfd, DAHDI_SETLAW, &law);
09685 }
09686 #endif
09687
09688 #ifdef HAVE_SS7
09689
09690 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
09691 {
09692 int i;
09693 int winner = -1;
09694 for (i = 0; i < linkset->numchans; i++) {
09695 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09696 winner = i;
09697 break;
09698 }
09699 }
09700 return winner;
09701 }
09702
09703 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09704 {
09705 unsigned char status[32];
09706 struct dahdi_pvt *p = NULL;
09707 int i, offset;
09708
09709 for (i = 0; i < linkset->numchans; i++) {
09710 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09711 p = linkset->pvts[i];
09712 offset = p->cic - startcic;
09713 status[offset] = 0;
09714 if (p->locallyblocked)
09715 status[offset] |= (1 << 0) | (1 << 4);
09716 if (p->remotelyblocked)
09717 status[offset] |= (1 << 1) | (1 << 5);
09718 if (p->ss7call) {
09719 if (p->outgoing)
09720 status[offset] |= (1 << 3);
09721 else
09722 status[offset] |= (1 << 2);
09723 } else
09724 status[offset] |= 0x3 << 2;
09725 }
09726 }
09727
09728 if (p)
09729 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09730 else
09731 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09732
09733 }
09734
09735 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
09736 {
09737 int i;
09738
09739 for (i = 0; i < linkset->numchans; i++) {
09740 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09741 if (state) {
09742 if (state[i])
09743 linkset->pvts[i]->remotelyblocked = block;
09744 } else
09745 linkset->pvts[i]->remotelyblocked = block;
09746 }
09747 }
09748 }
09749
09750 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09751 {
09752 int i;
09753
09754 for (i = 0; i < linkset->numchans; i++) {
09755 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09756 linkset->pvts[i]->inservice = 1;
09757 }
09758 }
09759
09760 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
09761 {
09762 int i, startcic = -1, endcic, dpc;
09763
09764 if (linkset->numchans <= 0)
09765 return;
09766
09767 startcic = linkset->pvts[0]->cic;
09768
09769 dpc = linkset->pvts[0]->dpc;
09770
09771 for (i = 0; i < linkset->numchans; i++) {
09772 if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
09773 continue;
09774 } else {
09775 endcic = linkset->pvts[i]->cic;
09776 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09777 isup_grs(linkset->ss7, startcic, endcic, dpc);
09778
09779
09780 if (linkset->pvts[i+1]) {
09781 startcic = linkset->pvts[i+1]->cic;
09782 dpc = linkset->pvts[i+1]->dpc;
09783 }
09784 }
09785 }
09786 }
09787
09788 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
09789 {
09790 if (p->loopedback != enable) {
09791 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09792 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09793 return;
09794 }
09795 p->loopedback = enable;
09796 }
09797 }
09798
09799
09800 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
09801 {
09802 struct ss7 *ss7 = linkset->ss7;
09803 int res;
09804 int law = 1;
09805 struct ast_channel *c;
09806 char tmp[256];
09807
09808 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09809 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09810
09811 if (linkset->type == SS7_ITU)
09812 law = DAHDI_LAW_ALAW;
09813 else
09814 law = DAHDI_LAW_MULAW;
09815
09816 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09817 if (res < 0)
09818 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09819
09820 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09821 p->proceeding = 1;
09822 isup_acm(ss7, p->ss7call);
09823 }
09824
09825 ast_mutex_unlock(&linkset->lock);
09826 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09827
09828 if (!c) {
09829 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09830
09831 ast_mutex_lock(&linkset->lock);
09832 return;
09833 } else
09834 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09835
09836 dahdi_enable_ec(p);
09837
09838
09839
09840
09841
09842 ast_mutex_unlock(&p->lock);
09843
09844 if (!ast_strlen_zero(p->charge_number)) {
09845 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09846
09847 p->charge_number[0] = 0;
09848 }
09849 if (!ast_strlen_zero(p->gen_add_number)) {
09850 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09851
09852 p->gen_add_number[0] = 0;
09853 }
09854 if (!ast_strlen_zero(p->jip_number)) {
09855 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09856
09857 p->jip_number[0] = 0;
09858 }
09859 if (!ast_strlen_zero(p->gen_dig_number)) {
09860 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09861
09862 p->gen_dig_number[0] = 0;
09863 }
09864 if (!ast_strlen_zero(p->orig_called_num)) {
09865 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09866
09867 p->orig_called_num[0] = 0;
09868 }
09869
09870 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09871 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09872
09873 p->gen_dig_type = 0;
09874
09875 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09876 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09877
09878 p->gen_dig_scheme = 0;
09879
09880 if (!ast_strlen_zero(p->lspi_ident)) {
09881 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
09882
09883 p->lspi_ident[0] = 0;
09884 }
09885
09886 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
09887 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
09888
09889 p->call_ref_ident = 0;
09890
09891 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
09892 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
09893
09894 p->call_ref_pc = 0;
09895
09896 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
09897 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
09898
09899 p->calling_party_cat = 0;
09900
09901 if (!ast_strlen_zero(p->redirecting_num)) {
09902 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
09903
09904 p->redirecting_num[0] = 0;
09905 }
09906 if (!ast_strlen_zero(p->generic_name)) {
09907 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
09908
09909 p->generic_name[0] = 0;
09910 }
09911
09912 ast_mutex_lock(&p->lock);
09913 ast_mutex_lock(&linkset->lock);
09914 }
09915
09916 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
09917 {
09918 if (ast_strlen_zero(number)) {
09919 if (size) {
09920 *buf = '\0';
09921 }
09922 return;
09923 }
09924 switch (nai) {
09925 case SS7_NAI_INTERNATIONAL:
09926 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
09927 break;
09928 case SS7_NAI_NATIONAL:
09929 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
09930 break;
09931 case SS7_NAI_SUBSCRIBER:
09932 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
09933 break;
09934 case SS7_NAI_UNKNOWN:
09935 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
09936 break;
09937 default:
09938 snprintf(buf, size, "%s", number);
09939 break;
09940 }
09941 }
09942 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
09943 {
09944 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
09945 }
09946
09947 static void *ss7_linkset(void *data)
09948 {
09949 int res, i;
09950 struct timeval *next = NULL, tv;
09951 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
09952 struct ss7 *ss7 = linkset->ss7;
09953 ss7_event *e = NULL;
09954 struct dahdi_pvt *p;
09955 int chanpos;
09956 struct pollfd pollers[NUM_DCHANS];
09957 int cic;
09958 unsigned int dpc;
09959 int nextms = 0;
09960
09961 ss7_start(ss7);
09962
09963 while(1) {
09964 ast_mutex_lock(&linkset->lock);
09965 if ((next = ss7_schedule_next(ss7))) {
09966 tv = ast_tvnow();
09967 tv.tv_sec = next->tv_sec - tv.tv_sec;
09968 tv.tv_usec = next->tv_usec - tv.tv_usec;
09969 if (tv.tv_usec < 0) {
09970 tv.tv_usec += 1000000;
09971 tv.tv_sec -= 1;
09972 }
09973 if (tv.tv_sec < 0) {
09974 tv.tv_sec = 0;
09975 tv.tv_usec = 0;
09976 }
09977 nextms = tv.tv_sec * 1000;
09978 nextms += tv.tv_usec / 1000;
09979 }
09980 ast_mutex_unlock(&linkset->lock);
09981
09982 for (i = 0; i < linkset->numsigchans; i++) {
09983 pollers[i].fd = linkset->fds[i];
09984 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
09985 pollers[i].revents = 0;
09986 }
09987
09988 res = poll(pollers, linkset->numsigchans, nextms);
09989 if ((res < 0) && (errno != EINTR)) {
09990 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
09991 } else if (!res) {
09992 ast_mutex_lock(&linkset->lock);
09993 ss7_schedule_run(ss7);
09994 ast_mutex_unlock(&linkset->lock);
09995 continue;
09996 }
09997
09998 ast_mutex_lock(&linkset->lock);
09999 for (i = 0; i < linkset->numsigchans; i++) {
10000 if (pollers[i].revents & POLLPRI) {
10001 int x;
10002 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
10003 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
10004 }
10005 switch (x) {
10006 case DAHDI_EVENT_OVERRUN:
10007 ast_debug(1, "Overrun detected!\n");
10008 break;
10009 case DAHDI_EVENT_BADFCS:
10010 ast_debug(1, "Bad FCS\n");
10011 break;
10012 case DAHDI_EVENT_ABORT:
10013 ast_debug(1, "HDLC Abort\n");
10014 break;
10015 case DAHDI_EVENT_ALARM:
10016 ast_log(LOG_ERROR, "Alarm on link!\n");
10017 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
10018 linkset->linkstate[i] &= ~LINKSTATE_UP;
10019 ss7_link_alarm(ss7, pollers[i].fd);
10020 break;
10021 case DAHDI_EVENT_NOALARM:
10022 ast_log(LOG_ERROR, "Alarm cleared on link\n");
10023 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
10024 linkset->linkstate[i] |= LINKSTATE_STARTING;
10025 ss7_link_noalarm(ss7, pollers[i].fd);
10026 break;
10027 default:
10028 ast_log(LOG_ERROR, "Got exception %d!\n", x);
10029 break;
10030 }
10031 }
10032
10033 if (pollers[i].revents & POLLIN) {
10034 ast_mutex_lock(&linkset->lock);
10035 res = ss7_read(ss7, pollers[i].fd);
10036 ast_mutex_unlock(&linkset->lock);
10037 }
10038
10039 if (pollers[i].revents & POLLOUT) {
10040 ast_mutex_lock(&linkset->lock);
10041 res = ss7_write(ss7, pollers[i].fd);
10042 ast_mutex_unlock(&linkset->lock);
10043 if (res < 0) {
10044 ast_debug(1, "Error in write %s\n", strerror(errno));
10045 }
10046 }
10047 }
10048
10049 while ((e = ss7_check_event(ss7))) {
10050 switch (e->e) {
10051 case SS7_EVENT_UP:
10052 if (linkset->state != LINKSET_STATE_UP) {
10053 ast_verbose("--- SS7 Up ---\n");
10054 ss7_reset_linkset(linkset);
10055 }
10056 linkset->state = LINKSET_STATE_UP;
10057 break;
10058 case SS7_EVENT_DOWN:
10059 ast_verbose("--- SS7 Down ---\n");
10060 linkset->state = LINKSET_STATE_DOWN;
10061 for (i = 0; i < linkset->numchans; i++) {
10062 struct dahdi_pvt *p = linkset->pvts[i];
10063 if (p)
10064 p->inalarm = 1;
10065 }
10066 break;
10067 case MTP2_LINK_UP:
10068 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
10069 break;
10070 case MTP2_LINK_DOWN:
10071 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
10072 break;
10073 case ISUP_EVENT_CPG:
10074 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
10075 if (chanpos < 0) {
10076 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
10077 break;
10078 }
10079 p = linkset->pvts[chanpos];
10080 ast_mutex_lock(&p->lock);
10081 switch (e->cpg.event) {
10082 case CPG_EVENT_ALERTING:
10083 p->alerting = 1;
10084 p->subs[SUB_REAL].needringing = 1;
10085 break;
10086 case CPG_EVENT_PROGRESS:
10087 case CPG_EVENT_INBANDINFO:
10088 {
10089 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10090 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
10091 dahdi_queue_frame(p, &f, linkset);
10092 p->progress = 1;
10093 if (p->dsp && p->dsp_features) {
10094 ast_dsp_set_features(p->dsp, p->dsp_features);
10095 p->dsp_features = 0;
10096 }
10097 }
10098 break;
10099 default:
10100 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
10101 }
10102
10103 ast_mutex_unlock(&p->lock);
10104 break;
10105 case ISUP_EVENT_RSC:
10106 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
10107 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
10108 if (chanpos < 0) {
10109 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
10110 break;
10111 }
10112 p = linkset->pvts[chanpos];
10113 ast_mutex_lock(&p->lock);
10114 p->inservice = 1;
10115 p->remotelyblocked = 0;
10116 dpc = p->dpc;
10117 isup_set_call_dpc(e->rsc.call, dpc);
10118 if (p->ss7call)
10119 p->ss7call = NULL;
10120 if (p->owner)
10121 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10122 ast_mutex_unlock(&p->lock);
10123 isup_rlc(ss7, e->rsc.call);
10124 break;
10125 case ISUP_EVENT_GRS:
10126 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
10127 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
10128 if (chanpos < 0) {
10129 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
10130 break;
10131 }
10132 p = linkset->pvts[chanpos];
10133 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
10134 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
10135 break;
10136 case ISUP_EVENT_CQM:
10137 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
10138 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
10139 break;
10140 case ISUP_EVENT_GRA:
10141 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
10142 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
10143 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
10144 break;
10145 case ISUP_EVENT_IAM:
10146 ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
10147 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
10148 if (chanpos < 0) {
10149 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
10150 isup_rel(ss7, e->iam.call, -1);
10151 break;
10152 }
10153 p = linkset->pvts[chanpos];
10154 ast_mutex_lock(&p->lock);
10155 if (p->owner) {
10156 if (p->ss7call == e->iam.call) {
10157 ast_mutex_unlock(&p->lock);
10158 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
10159 break;
10160 } else {
10161 ast_mutex_unlock(&p->lock);
10162 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
10163 break;
10164 }
10165 }
10166
10167 dpc = p->dpc;
10168 p->ss7call = e->iam.call;
10169 isup_set_call_dpc(p->ss7call, dpc);
10170
10171 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
10172 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
10173 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
10174 } else
10175 p->cid_num[0] = 0;
10176
10177 if (p->immediate) {
10178 p->exten[0] = 's';
10179 p->exten[1] = '\0';
10180 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
10181 char *st;
10182 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
10183 st = strchr(p->exten, '#');
10184 if (st)
10185 *st = '\0';
10186 } else
10187 p->exten[0] = '\0';
10188
10189 p->cid_ani[0] = '\0';
10190 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
10191 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
10192 else
10193 p->cid_name[0] = '\0';
10194
10195 p->cid_ani2 = e->iam.oli_ani2;
10196 p->cid_ton = 0;
10197 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
10198 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
10199 p->gen_add_type = e->iam.gen_add_type;
10200 p->gen_add_nai = e->iam.gen_add_nai;
10201 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
10202 p->gen_add_num_plan = e->iam.gen_add_num_plan;
10203 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
10204 p->gen_dig_type = e->iam.gen_dig_type;
10205 p->gen_dig_scheme = e->iam.gen_dig_scheme;
10206 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
10207 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
10208 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
10209 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
10210 p->calling_party_cat = e->iam.calling_party_cat;
10211
10212
10213 if (!ast_strlen_zero(e->iam.called_party_num))
10214 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
10215
10216 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
10217
10218 if (e->iam.cot_check_required) {
10219 dahdi_loopback(p, 1);
10220 } else
10221 ss7_start_call(p, linkset);
10222 } else {
10223 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
10224 p->alreadyhungup = 1;
10225 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
10226 }
10227 ast_mutex_unlock(&p->lock);
10228 break;
10229 case ISUP_EVENT_COT:
10230 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
10231 if (chanpos < 0) {
10232 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
10233 isup_rel(ss7, e->cot.call, -1);
10234 break;
10235 }
10236 p = linkset->pvts[chanpos];
10237
10238 ast_mutex_lock(&p->lock);
10239
10240 if (p->loopedback) {
10241 dahdi_loopback(p, 0);
10242 ss7_start_call(p, linkset);
10243 }
10244
10245 ast_mutex_unlock(&p->lock);
10246
10247 break;
10248 case ISUP_EVENT_CCR:
10249 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
10250 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
10251 if (chanpos < 0) {
10252 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
10253 break;
10254 }
10255
10256 p = linkset->pvts[chanpos];
10257
10258 ast_mutex_lock(&p->lock);
10259 dahdi_loopback(p, 1);
10260 ast_mutex_unlock(&p->lock);
10261
10262 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
10263 break;
10264 case ISUP_EVENT_CVT:
10265 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
10266 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
10267 if (chanpos < 0) {
10268 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
10269 break;
10270 }
10271
10272 p = linkset->pvts[chanpos];
10273
10274 ast_mutex_lock(&p->lock);
10275 dahdi_loopback(p, 1);
10276 ast_mutex_unlock(&p->lock);
10277
10278 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
10279 break;
10280 case ISUP_EVENT_REL:
10281 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
10282 if (chanpos < 0) {
10283 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
10284 break;
10285 }
10286 p = linkset->pvts[chanpos];
10287 ast_mutex_lock(&p->lock);
10288 if (p->owner) {
10289 p->owner->hangupcause = e->rel.cause;
10290 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10291 } else if (!p->restartpending)
10292 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
10293
10294
10295 dahdi_loopback(p, 0);
10296
10297 isup_rlc(ss7, e->rel.call);
10298 p->ss7call = NULL;
10299
10300 ast_mutex_unlock(&p->lock);
10301 break;
10302 case ISUP_EVENT_ACM:
10303 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
10304 if (chanpos < 0) {
10305 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
10306 isup_rel(ss7, e->acm.call, -1);
10307 break;
10308 } else {
10309 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10310
10311 p = linkset->pvts[chanpos];
10312
10313 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
10314
10315 if (e->acm.call_ref_ident > 0) {
10316 p->rlt = 1;
10317 }
10318
10319 ast_mutex_lock(&p->lock);
10320 dahdi_queue_frame(p, &f, linkset);
10321 p->proceeding = 1;
10322
10323 if (e->acm.called_party_status_ind == 1) {
10324 p->alerting = 1;
10325 p->subs[SUB_REAL].needringing = 1;
10326 }
10327 ast_mutex_unlock(&p->lock);
10328 }
10329 break;
10330 case ISUP_EVENT_CGB:
10331 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
10332 if (chanpos < 0) {
10333 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
10334 break;
10335 }
10336 p = linkset->pvts[chanpos];
10337 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
10338 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
10339 break;
10340 case ISUP_EVENT_CGU:
10341 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
10342 if (chanpos < 0) {
10343 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
10344 break;
10345 }
10346 p = linkset->pvts[chanpos];
10347 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
10348 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
10349 break;
10350 case ISUP_EVENT_UCIC:
10351 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
10352 if (chanpos < 0) {
10353 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
10354 break;
10355 }
10356 p = linkset->pvts[chanpos];
10357 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
10358 ast_mutex_lock(&p->lock);
10359 p->remotelyblocked = 1;
10360 p->inservice = 0;
10361 ast_mutex_unlock(&p->lock);
10362 break;
10363 case ISUP_EVENT_BLO:
10364 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
10365 if (chanpos < 0) {
10366 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
10367 break;
10368 }
10369 p = linkset->pvts[chanpos];
10370 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
10371 ast_mutex_lock(&p->lock);
10372 p->remotelyblocked = 1;
10373 ast_mutex_unlock(&p->lock);
10374 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
10375 break;
10376 case ISUP_EVENT_BLA:
10377 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
10378 if (chanpos < 0) {
10379 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
10380 break;
10381 }
10382 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
10383 p = linkset->pvts[chanpos];
10384 ast_mutex_lock(&p->lock);
10385 p->locallyblocked = 1;
10386 ast_mutex_unlock(&p->lock);
10387 break;
10388 case ISUP_EVENT_UBL:
10389 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
10390 if (chanpos < 0) {
10391 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
10392 break;
10393 }
10394 p = linkset->pvts[chanpos];
10395 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
10396 ast_mutex_lock(&p->lock);
10397 p->remotelyblocked = 0;
10398 ast_mutex_unlock(&p->lock);
10399 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
10400 break;
10401 case ISUP_EVENT_UBA:
10402 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
10403 if (chanpos < 0) {
10404 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
10405 break;
10406 }
10407 p = linkset->pvts[chanpos];
10408 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
10409 ast_mutex_lock(&p->lock);
10410 p->locallyblocked = 0;
10411 ast_mutex_unlock(&p->lock);
10412 break;
10413 case ISUP_EVENT_CON:
10414 case ISUP_EVENT_ANM:
10415 if (e->e == ISUP_EVENT_CON)
10416 cic = e->con.cic;
10417 else
10418 cic = e->anm.cic;
10419
10420 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
10421 if (chanpos < 0) {
10422 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
10423 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
10424 break;
10425 } else {
10426 p = linkset->pvts[chanpos];
10427 ast_mutex_lock(&p->lock);
10428 p->subs[SUB_REAL].needanswer = 1;
10429 if (p->dsp && p->dsp_features) {
10430 ast_dsp_set_features(p->dsp, p->dsp_features);
10431 p->dsp_features = 0;
10432 }
10433 dahdi_enable_ec(p);
10434 ast_mutex_unlock(&p->lock);
10435 }
10436 break;
10437 case ISUP_EVENT_RLC:
10438 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
10439 if (chanpos < 0) {
10440 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
10441 break;
10442 } else {
10443 p = linkset->pvts[chanpos];
10444 ast_mutex_lock(&p->lock);
10445 if (p->alreadyhungup)
10446 p->ss7call = NULL;
10447 else
10448 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
10449 ast_mutex_unlock(&p->lock);
10450 }
10451 break;
10452 case ISUP_EVENT_FAA:
10453 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
10454 if (chanpos < 0) {
10455 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
10456 break;
10457 } else {
10458 p = linkset->pvts[chanpos];
10459 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
10460 ast_mutex_lock(&p->lock);
10461 if (p->alreadyhungup){
10462 p->ss7call = NULL;
10463 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
10464 }
10465 ast_mutex_unlock(&p->lock);
10466 }
10467 break;
10468 default:
10469 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
10470 break;
10471 }
10472 }
10473 ast_mutex_unlock(&linkset->lock);
10474 }
10475
10476 return 0;
10477 }
10478
10479 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
10480 {
10481 #if 0
10482 int i;
10483
10484 for (i = 0; i < NUM_SPANS; i++)
10485 if (linksets[i].ss7 == ss7)
10486 break;
10487
10488 ast_verbose("[%d] %s", i+1, s);
10489 #else
10490 ast_verbose("%s", s);
10491 #endif
10492 }
10493
10494 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
10495 {
10496 #if 0
10497 int i;
10498
10499 for (i = 0; i < NUM_SPANS; i++)
10500 if (linksets[i].ss7 == ss7)
10501 break;
10502
10503 #else
10504 ast_log(LOG_ERROR, "%s", s);
10505 #endif
10506 }
10507
10508 #endif
10509
10510 #ifdef HAVE_PRI
10511 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10512 {
10513 struct dahdi_pvt *p;
10514 p = pri->crvs;
10515 while (p) {
10516 if (p->channel == crv)
10517 return p;
10518 p = p->next;
10519 }
10520 return NULL;
10521 }
10522
10523
10524 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10525 {
10526 int x;
10527 int span = PRI_SPAN(channel);
10528 int spanfd;
10529 struct dahdi_params param;
10530 int principle = -1;
10531 int explicit = PRI_EXPLICIT(channel);
10532 channel = PRI_CHANNEL(channel);
10533
10534 if (!explicit) {
10535 spanfd = pri_active_dchan_fd(pri);
10536 memset(¶m, 0, sizeof(param));
10537 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
10538 return -1;
10539 span = pris[param.spanno - 1].prilogicalspan;
10540 }
10541
10542 for (x = 0; x < pri->numchans; x++) {
10543 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10544 principle = x;
10545 break;
10546 }
10547 }
10548
10549 return principle;
10550 }
10551
10552 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10553 {
10554 int x;
10555 struct dahdi_pvt *crv;
10556 if (!c) {
10557 if (principle < 0)
10558 return -1;
10559 return principle;
10560 }
10561 if ((principle > -1) &&
10562 (principle < pri->numchans) &&
10563 (pri->pvts[principle]) &&
10564 (pri->pvts[principle]->call == c))
10565 return principle;
10566
10567 for (x = 0; x < pri->numchans; x++) {
10568 if (!pri->pvts[x])
10569 continue;
10570 if (pri->pvts[x]->call == c) {
10571
10572 if (principle != x) {
10573 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10574
10575 ast_verb(3, "Moving call from channel %d to channel %d\n",
10576 old->channel, new->channel);
10577 if (new->owner) {
10578 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10579 old->channel, new->channel, new->channel);
10580 return -1;
10581 }
10582
10583 new->owner = old->owner;
10584 old->owner = NULL;
10585 if (new->owner) {
10586 ast_string_field_build(new->owner, name,
10587 "DAHDI/%d:%d-%d", pri->trunkgroup,
10588 new->channel, 1);
10589 new->owner->tech_pvt = new;
10590 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10591 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10592 old->subs[SUB_REAL].owner = NULL;
10593 } else
10594 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);
10595 new->call = old->call;
10596 old->call = NULL;
10597
10598
10599 new->dsp = old->dsp;
10600 new->dsp_features = old->dsp_features;
10601 old->dsp = NULL;
10602 old->dsp_features = 0;
10603 }
10604 return principle;
10605 }
10606 }
10607
10608 crv = pri->crvs;
10609 while (crv) {
10610 if (crv->call == c) {
10611
10612 if (crv->bearer)
10613 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10614 else if (pri->pvts[principle]->owner)
10615 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10616 else {
10617
10618
10619 dahdi_close_sub(crv, SUB_REAL);
10620 pri->pvts[principle]->call = crv->call;
10621 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10622 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10623 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10624 pri->trunkgroup, crv->channel);
10625 wakeup_sub(crv, SUB_REAL, pri);
10626 }
10627 return principle;
10628 }
10629 crv = crv->next;
10630 }
10631 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10632 return -1;
10633 }
10634
10635 static void *do_idle_thread(void *vchan)
10636 {
10637 struct ast_channel *chan = vchan;
10638 struct dahdi_pvt *pvt = chan->tech_pvt;
10639 struct ast_frame *f;
10640 char ex[80];
10641
10642 int newms, ms = 30000;
10643 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10644 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10645 if (ast_call(chan, ex, 0)) {
10646 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10647 ast_hangup(chan);
10648 return NULL;
10649 }
10650 while ((newms = ast_waitfor(chan, ms)) > 0) {
10651 f = ast_read(chan);
10652 if (!f) {
10653
10654 break;
10655 }
10656 if (f->frametype == AST_FRAME_CONTROL) {
10657 switch (f->subclass) {
10658 case AST_CONTROL_ANSWER:
10659
10660 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10661 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10662 chan->priority = 1;
10663 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10664 ast_pbx_run(chan);
10665
10666 return NULL;
10667 case AST_CONTROL_BUSY:
10668 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10669 break;
10670 case AST_CONTROL_CONGESTION:
10671 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10672 break;
10673 };
10674 }
10675 ast_frfree(f);
10676 ms = newms;
10677 }
10678
10679 ast_hangup(chan);
10680 return NULL;
10681 }
10682
10683 #ifndef PRI_RESTART
10684 #error "Upgrade your libpri"
10685 #endif
10686 static void dahdi_pri_message(struct pri *pri, char *s)
10687 {
10688 int x, y;
10689 int dchan = -1, span = -1;
10690 int dchancount = 0;
10691
10692 if (pri) {
10693 for (x = 0; x < NUM_SPANS; x++) {
10694 for (y = 0; y < NUM_DCHANS; y++) {
10695 if (pris[x].dchans[y])
10696 dchancount++;
10697
10698 if (pris[x].dchans[y] == pri)
10699 dchan = y;
10700 }
10701 if (dchan >= 0) {
10702 span = x;
10703 break;
10704 }
10705 dchancount = 0;
10706 }
10707 if (dchancount > 1 && (span > -1))
10708 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10709 else
10710 ast_verbose("%s", s);
10711 } else
10712 ast_verbose("%s", s);
10713
10714 ast_mutex_lock(&pridebugfdlock);
10715
10716 if (pridebugfd >= 0) {
10717 if (write(pridebugfd, s, strlen(s)) < 0) {
10718 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10719 }
10720 }
10721
10722 ast_mutex_unlock(&pridebugfdlock);
10723 }
10724
10725 static void dahdi_pri_error(struct pri *pri, char *s)
10726 {
10727 int x, y;
10728 int dchan = -1, span = -1;
10729 int dchancount = 0;
10730
10731 if (pri) {
10732 for (x = 0; x < NUM_SPANS; x++) {
10733 for (y = 0; y < NUM_DCHANS; y++) {
10734 if (pris[x].dchans[y])
10735 dchancount++;
10736
10737 if (pris[x].dchans[y] == pri)
10738 dchan = y;
10739 }
10740 if (dchan >= 0) {
10741 span = x;
10742 break;
10743 }
10744 dchancount = 0;
10745 }
10746 if ((dchancount > 1) && (span > -1))
10747 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10748 else
10749 ast_log(LOG_ERROR, "%s", s);
10750 } else
10751 ast_log(LOG_ERROR, "%s", s);
10752
10753 ast_mutex_lock(&pridebugfdlock);
10754
10755 if (pridebugfd >= 0) {
10756 if (write(pridebugfd, s, strlen(s)) < 0) {
10757 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10758 }
10759 }
10760
10761 ast_mutex_unlock(&pridebugfdlock);
10762 }
10763
10764 static int pri_check_restart(struct dahdi_pri *pri)
10765 {
10766 do {
10767 pri->resetpos++;
10768 } while ((pri->resetpos < pri->numchans) &&
10769 (!pri->pvts[pri->resetpos] ||
10770 pri->pvts[pri->resetpos]->call ||
10771 pri->pvts[pri->resetpos]->resetting));
10772 if (pri->resetpos < pri->numchans) {
10773
10774 pri->pvts[pri->resetpos]->resetting = 1;
10775 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10776 } else {
10777 pri->resetting = 0;
10778 time(&pri->lastreset);
10779 }
10780 return 0;
10781 }
10782
10783 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10784 {
10785 int x;
10786 int redo;
10787 ast_mutex_unlock(&pri->lock);
10788 ast_mutex_lock(&p->lock);
10789 do {
10790 redo = 0;
10791 for (x = 0; x < 3; x++) {
10792 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10793 redo++;
10794 DEADLOCK_AVOIDANCE(&p->lock);
10795 }
10796 if (p->subs[x].owner) {
10797 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10798 ast_channel_unlock(p->subs[x].owner);
10799 }
10800 }
10801 } while (redo);
10802 ast_mutex_unlock(&p->lock);
10803 ast_mutex_lock(&pri->lock);
10804 return 0;
10805 }
10806
10807 static char * redirectingreason2str(int redirectingreason)
10808 {
10809 switch (redirectingreason) {
10810 case 0:
10811 return "UNKNOWN";
10812 case 1:
10813 return "BUSY";
10814 case 2:
10815 return "NO_REPLY";
10816 case 0xF:
10817 return "UNCONDITIONAL";
10818 default:
10819 return "NOREDIRECT";
10820 }
10821 }
10822
10823 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10824 {
10825 if (pri->dialplan == -2) {
10826 snprintf(buf, size, "%s", number);
10827 return;
10828 }
10829 if (ast_strlen_zero(number)) {
10830 if (size) {
10831 *buf = '\0';
10832 }
10833 return;
10834 }
10835 switch (plan) {
10836 case PRI_INTERNATIONAL_ISDN:
10837 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10838 break;
10839 case PRI_NATIONAL_ISDN:
10840 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10841 break;
10842 case PRI_LOCAL_ISDN:
10843 snprintf(buf, size, "%s%s", pri->localprefix, number);
10844 break;
10845 case PRI_PRIVATE:
10846 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10847 break;
10848 case PRI_UNKNOWN:
10849 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10850 break;
10851 default:
10852 snprintf(buf, size, "%s", number);
10853 break;
10854 }
10855 }
10856
10857
10858 static void *pri_dchannel(void *vpri)
10859 {
10860 struct dahdi_pri *pri = vpri;
10861 pri_event *e;
10862 struct pollfd fds[NUM_DCHANS];
10863 int res;
10864 int chanpos = 0;
10865 int x;
10866 int haveidles;
10867 int activeidles;
10868 int nextidle = -1;
10869 struct ast_channel *c;
10870 struct timeval tv, lowest, *next;
10871 struct timeval lastidle = ast_tvnow();
10872 int doidling=0;
10873 char *cc;
10874 char idlen[80];
10875 struct ast_channel *idle;
10876 pthread_t p;
10877 time_t t;
10878 int i, which=-1;
10879 int numdchans;
10880 int cause=0;
10881 struct dahdi_pvt *crv;
10882 pthread_t threadid;
10883 char ani2str[6];
10884 char plancallingnum[256];
10885 char plancallingani[256];
10886 char calledtonstr[10];
10887
10888 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10889
10890 gettimeofday(&lastidle, NULL);
10891 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10892
10893 cc = strchr(pri->idleext, '@');
10894 if (cc) {
10895 *cc = '\0';
10896 cc++;
10897 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10898 #if 0
10899
10900 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10901 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10902 else
10903 #endif
10904 doidling = 1;
10905 } else
10906 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10907 }
10908 for (;;) {
10909 for (i = 0; i < NUM_DCHANS; i++) {
10910 if (!pri->dchannels[i])
10911 break;
10912 fds[i].fd = pri->fds[i];
10913 fds[i].events = POLLIN | POLLPRI;
10914 fds[i].revents = 0;
10915 }
10916 numdchans = i;
10917 time(&t);
10918 ast_mutex_lock(&pri->lock);
10919 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10920 if (pri->resetting && pri_is_up(pri)) {
10921 if (pri->resetpos < 0)
10922 pri_check_restart(pri);
10923 } else {
10924 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10925 pri->resetting = 1;
10926 pri->resetpos = -1;
10927 }
10928 }
10929 }
10930
10931 if (doidling && pri_is_up(pri)) {
10932 nextidle = -1;
10933 haveidles = 0;
10934 activeidles = 0;
10935 for (x = pri->numchans; x >= 0; x--) {
10936 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10937 !pri->pvts[x]->call) {
10938 if (haveidles < pri->minunused) {
10939 haveidles++;
10940 } else if (!pri->pvts[x]->resetting) {
10941 nextidle = x;
10942 break;
10943 }
10944 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10945 activeidles++;
10946 }
10947 if (nextidle > -1) {
10948 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10949
10950 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10951 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
10952 if (idle) {
10953 pri->pvts[nextidle]->isidlecall = 1;
10954 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10955 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10956 dahdi_hangup(idle);
10957 }
10958 } else
10959 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10960 lastidle = ast_tvnow();
10961 }
10962 } else if ((haveidles < pri->minunused) &&
10963 (activeidles > pri->minidle)) {
10964
10965
10966 for (x = pri->numchans; x >= 0; x--) {
10967
10968 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10969 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10970 haveidles++;
10971
10972
10973 if ((haveidles >= pri->minunused) ||
10974 (activeidles <= pri->minidle))
10975 break;
10976 }
10977 }
10978 }
10979 }
10980
10981 lowest = ast_tv(60, 0);
10982 for (i = 0; i < NUM_DCHANS; i++) {
10983
10984 if (!pri->dchannels[i])
10985 break;
10986 if ((next = pri_schedule_next(pri->dchans[i]))) {
10987
10988 tv = ast_tvsub(*next, ast_tvnow());
10989 if (tv.tv_sec < 0) {
10990 tv = ast_tv(0,0);
10991 }
10992 if (doidling || pri->resetting) {
10993 if (tv.tv_sec > 1) {
10994 tv = ast_tv(1, 0);
10995 }
10996 } else {
10997 if (tv.tv_sec > 60) {
10998 tv = ast_tv(60, 0);
10999 }
11000 }
11001 } else if (doidling || pri->resetting) {
11002
11003
11004 tv = ast_tv(1,0);
11005 } else {
11006
11007 tv = ast_tv(60, 0);
11008 }
11009 if (!i || ast_tvcmp(tv, lowest) < 0) {
11010 lowest = tv;
11011 }
11012 }
11013 ast_mutex_unlock(&pri->lock);
11014
11015 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11016 pthread_testcancel();
11017 e = NULL;
11018 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11019 pthread_testcancel();
11020 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11021
11022 ast_mutex_lock(&pri->lock);
11023 if (!res) {
11024 for (which = 0; which < NUM_DCHANS; which++) {
11025 if (!pri->dchans[which])
11026 break;
11027
11028 e = pri_schedule_run(pri->dchans[which]);
11029 if (e)
11030 break;
11031 }
11032 } else if (res > -1) {
11033 for (which = 0; which < NUM_DCHANS; which++) {
11034 if (!pri->dchans[which])
11035 break;
11036 if (fds[which].revents & POLLPRI) {
11037
11038 x = 0;
11039 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11040 if (x) {
11041 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);
11042 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
11043 "PRIEvent: %s\r\n"
11044 "PRIEventCode: %d\r\n"
11045 "D-channel: %s\r\n"
11046 "Span: %d\r\n",
11047 event2str(x),
11048 x,
11049 pri_order(which),
11050 pri->span
11051 );
11052 }
11053
11054 if (x == DAHDI_EVENT_ALARM) {
11055 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11056 pri_find_dchan(pri);
11057 } else if (x == DAHDI_EVENT_NOALARM) {
11058 pri->dchanavail[which] |= DCHAN_NOTINALARM;
11059 pri_restart(pri->dchans[which]);
11060 }
11061
11062 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11063 } else if (fds[which].revents & POLLIN) {
11064 e = pri_check_event(pri->dchans[which]);
11065 }
11066 if (e)
11067 break;
11068 }
11069 } else if (errno != EINTR)
11070 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11071
11072 if (e) {
11073 if (pri->debug)
11074 pri_dump_event(pri->dchans[which], e);
11075
11076 if (e->e != PRI_EVENT_DCHAN_DOWN) {
11077 if (!(pri->dchanavail[which] & DCHAN_UP)) {
11078 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11079 }
11080 pri->dchanavail[which] |= DCHAN_UP;
11081 } else {
11082 if (pri->dchanavail[which] & DCHAN_UP) {
11083 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11084 }
11085 pri->dchanavail[which] &= ~DCHAN_UP;
11086 }
11087
11088 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11089
11090 pri->pri = pri->dchans[which];
11091
11092 switch (e->e) {
11093 case PRI_EVENT_DCHAN_UP:
11094 if (!pri->pri) pri_find_dchan(pri);
11095
11096
11097 time(&pri->lastreset);
11098
11099
11100 if (pri->resetinterval > -1) {
11101 pri->lastreset -= pri->resetinterval;
11102 pri->lastreset += 5;
11103 }
11104 pri->resetting = 0;
11105
11106 for (i = 0; i < pri->numchans; i++)
11107 if (pri->pvts[i]) {
11108 pri->pvts[i]->inalarm = 0;
11109 }
11110 break;
11111 case PRI_EVENT_DCHAN_DOWN:
11112 pri_find_dchan(pri);
11113 if (!pri_is_up(pri)) {
11114 pri->resetting = 0;
11115
11116 for (i = 0; i < pri->numchans; i++) {
11117 struct dahdi_pvt *p = pri->pvts[i];
11118 if (p) {
11119 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11120
11121 if (p->call) {
11122 if (p->pri && p->pri->pri) {
11123 pri_hangup(p->pri->pri, p->call, -1);
11124 pri_destroycall(p->pri->pri, p->call);
11125 p->call = NULL;
11126 } else
11127 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
11128 }
11129 if (p->realcall) {
11130 pri_hangup_all(p->realcall, pri);
11131 } else if (p->owner)
11132 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11133 }
11134 p->inalarm = 1;
11135 }
11136 }
11137 }
11138 break;
11139 case PRI_EVENT_RESTART:
11140 if (e->restart.channel > -1) {
11141 chanpos = pri_find_principle(pri, e->restart.channel);
11142 if (chanpos < 0)
11143 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
11144 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11145 else {
11146 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
11147 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11148 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11149 if (pri->pvts[chanpos]->call) {
11150 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11151 pri->pvts[chanpos]->call = NULL;
11152 }
11153
11154 if (pri->pvts[chanpos]->realcall)
11155 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11156 else if (pri->pvts[chanpos]->owner)
11157 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11158 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11159 }
11160 } else {
11161 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
11162 for (x = 0; x < pri->numchans; x++)
11163 if (pri->pvts[x]) {
11164 ast_mutex_lock(&pri->pvts[x]->lock);
11165 if (pri->pvts[x]->call) {
11166 pri_destroycall(pri->pri, pri->pvts[x]->call);
11167 pri->pvts[x]->call = NULL;
11168 }
11169 if (pri->pvts[chanpos]->realcall)
11170 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11171 else if (pri->pvts[x]->owner)
11172 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11173 ast_mutex_unlock(&pri->pvts[x]->lock);
11174 }
11175 }
11176 break;
11177 case PRI_EVENT_KEYPAD_DIGIT:
11178 chanpos = pri_find_principle(pri, e->digit.channel);
11179 if (chanpos < 0) {
11180 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
11181 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
11182 } else {
11183 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
11184 if (chanpos > -1) {
11185 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11186
11187 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
11188
11189 int digitlen = strlen(e->digit.digits);
11190 char digit;
11191 int i;
11192 for (i = 0; i < digitlen; i++) {
11193 digit = e->digit.digits[i];
11194 {
11195 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11196 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11197 }
11198 }
11199 }
11200 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11201 }
11202 }
11203 break;
11204
11205 case PRI_EVENT_INFO_RECEIVED:
11206 chanpos = pri_find_principle(pri, e->ring.channel);
11207 if (chanpos < 0) {
11208 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
11209 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11210 } else {
11211 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
11212 if (chanpos > -1) {
11213 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11214
11215 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
11216
11217 int digitlen = strlen(e->ring.callednum);
11218 char digit;
11219 int i;
11220 for (i = 0; i < digitlen; i++) {
11221 digit = e->ring.callednum[i];
11222 {
11223 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11224 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11225 }
11226 }
11227 }
11228 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11229 }
11230 }
11231 break;
11232 case PRI_EVENT_RING:
11233 crv = NULL;
11234 if (e->ring.channel == -1)
11235 chanpos = pri_find_empty_chan(pri, 1);
11236 else
11237 chanpos = pri_find_principle(pri, e->ring.channel);
11238
11239 if (chanpos < 0) {
11240 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
11241 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11242 } else {
11243 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11244 if (pri->pvts[chanpos]->owner) {
11245 if (pri->pvts[chanpos]->call == e->ring.call) {
11246 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
11247 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11248 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11249 break;
11250 } else {
11251
11252 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
11253 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11254 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11255 chanpos = -1;
11256 }
11257 }
11258 if (chanpos > -1)
11259 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11260 }
11261 if ((chanpos < 0) && (e->ring.flexible))
11262 chanpos = pri_find_empty_chan(pri, 1);
11263 if (chanpos > -1) {
11264 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11265 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11266
11267 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11268 if (crv)
11269 ast_mutex_lock(&crv->lock);
11270 if (!crv || crv->owner) {
11271 pri->pvts[chanpos]->call = NULL;
11272 if (crv) {
11273 if (crv->owner)
11274 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11275 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);
11276 } else
11277 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);
11278 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11279 if (crv)
11280 ast_mutex_unlock(&crv->lock);
11281 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11282 break;
11283 }
11284 }
11285 pri->pvts[chanpos]->call = e->ring.call;
11286 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11287 if (pri->pvts[chanpos]->use_callerid) {
11288 ast_shrink_phone_number(plancallingnum);
11289 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11290 #ifdef PRI_ANI
11291 if (!ast_strlen_zero(e->ring.callingani)) {
11292 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11293 ast_shrink_phone_number(plancallingani);
11294 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11295 } else {
11296 pri->pvts[chanpos]->cid_ani[0] = '\0';
11297 }
11298 #endif
11299 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11300 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
11301 } else {
11302 pri->pvts[chanpos]->cid_num[0] = '\0';
11303 pri->pvts[chanpos]->cid_ani[0] = '\0';
11304 pri->pvts[chanpos]->cid_name[0] = '\0';
11305 pri->pvts[chanpos]->cid_ton = 0;
11306 }
11307 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11308 e->ring.redirectingnum, e->ring.callingplanrdnis);
11309
11310 if (pri->pvts[chanpos]->immediate) {
11311 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
11312 pri->pvts[chanpos]->exten[0] = 's';
11313 pri->pvts[chanpos]->exten[1] = '\0';
11314 }
11315
11316 else if (!ast_strlen_zero(e->ring.callednum)) {
11317 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11318 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11319 } else if (pri->overlapdial)
11320 pri->pvts[chanpos]->exten[0] = '\0';
11321 else {
11322
11323 pri->pvts[chanpos]->exten[0] = 's';
11324 pri->pvts[chanpos]->exten[1] = '\0';
11325 }
11326
11327 if (!ast_strlen_zero(e->ring.callednum))
11328 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11329
11330 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11331 ast_verb(3, "Going to extension s|1 because of Complete received\n");
11332 pri->pvts[chanpos]->exten[0] = 's';
11333 pri->pvts[chanpos]->exten[1] = '\0';
11334 }
11335
11336 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11337 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11338
11339 int law;
11340 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11341
11342 law = 1;
11343 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11344 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11345 }
11346 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11347 law = DAHDI_LAW_ALAW;
11348 else
11349 law = DAHDI_LAW_MULAW;
11350 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11351 if (res < 0)
11352 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11353 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11354 if (res < 0)
11355 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11356 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11357
11358 pri->pvts[chanpos]->proceeding = 1;
11359 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11360 } else {
11361 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
11362 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11363 else
11364 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11365 }
11366
11367 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11368
11369
11370 if (!e->ring.complete && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11371
11372 ast_mutex_unlock(&pri->lock);
11373 if (crv) {
11374
11375 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11376 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11377 pri->pvts[chanpos]->owner = &inuse;
11378 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11379 } else {
11380 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11381 }
11382
11383 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11384
11385 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11386 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11387 }
11388 if (e->ring.ani2 >= 0) {
11389 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
11390 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11391 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11392 }
11393
11394 #ifdef SUPPORT_USERUSER
11395 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11396 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11397 }
11398 #endif
11399
11400 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11401 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11402 if (e->ring.redirectingreason >= 0)
11403 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11404
11405 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11406 ast_mutex_lock(&pri->lock);
11407 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
11408 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11409 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11410 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11411 } else {
11412 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11413 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11414 if (c)
11415 ast_hangup(c);
11416 else {
11417 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11418 pri->pvts[chanpos]->call = NULL;
11419 }
11420 }
11421 } else {
11422 ast_mutex_unlock(&pri->lock);
11423
11424 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
11425 if (c) {
11426 char calledtonstr[10];
11427
11428 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11429
11430 if (e->ring.ani2 >= 0) {
11431 snprintf(ani2str, 5, "%d", e->ring.ani2);
11432 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11433 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11434 }
11435
11436 #ifdef SUPPORT_USERUSER
11437 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11438 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11439 }
11440 #endif
11441
11442 if (e->ring.redirectingreason >= 0)
11443 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11444
11445 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11446 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11447
11448 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11449 ast_mutex_lock(&pri->lock);
11450
11451 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11452 plancallingnum, pri->pvts[chanpos]->exten,
11453 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11454
11455 dahdi_enable_ec(pri->pvts[chanpos]);
11456 } else {
11457
11458 ast_mutex_lock(&pri->lock);
11459
11460 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11461 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11462 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11463 pri->pvts[chanpos]->call = NULL;
11464 }
11465 }
11466 } else {
11467 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
11468 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
11469 pri->pvts[chanpos]->prioffset, pri->span);
11470 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11471 pri->pvts[chanpos]->call = NULL;
11472 pri->pvts[chanpos]->exten[0] = '\0';
11473 }
11474 if (crv)
11475 ast_mutex_unlock(&crv->lock);
11476 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11477 } else {
11478 if (e->ring.flexible)
11479 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11480 else
11481 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11482 }
11483 break;
11484 case PRI_EVENT_RINGING:
11485 chanpos = pri_find_principle(pri, e->ringing.channel);
11486 if (chanpos < 0) {
11487 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
11488 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11489 } else {
11490 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
11491 if (chanpos < 0) {
11492 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
11493 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11494 } else {
11495 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11496 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11497 dahdi_enable_ec(pri->pvts[chanpos]);
11498 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11499 pri->pvts[chanpos]->alerting = 1;
11500 } else
11501 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11502
11503 #ifdef PRI_PROGRESS_MASK
11504 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11505 #else
11506 if (e->ringing.progress == 8) {
11507 #endif
11508
11509 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11510
11511 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11512 pri->pvts[chanpos]->dsp_features = 0;
11513 }
11514 }
11515
11516 #ifdef SUPPORT_USERUSER
11517 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11518 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11519 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11520 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11521 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11522 }
11523 #endif
11524
11525 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11526 }
11527 }
11528 break;
11529 case PRI_EVENT_PROGRESS:
11530
11531 chanpos = pri_find_principle(pri, e->proceeding.channel);
11532 if (chanpos > -1) {
11533 #ifdef PRI_PROGRESS_MASK
11534 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11535 #else
11536 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11537 #endif
11538 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11539
11540 if (e->proceeding.cause > -1) {
11541 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11542
11543
11544 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11545 if (pri->pvts[chanpos]->owner) {
11546 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11547
11548 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11549 f.subclass = AST_CONTROL_BUSY;
11550 }
11551 }
11552 }
11553
11554 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11555 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11556 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11557 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11558 #ifdef PRI_PROGRESS_MASK
11559 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11560 #else
11561 if (e->proceeding.progress == 8) {
11562 #endif
11563
11564 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11565 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11566 pri->pvts[chanpos]->dsp_features = 0;
11567 }
11568
11569 f.subclass = AST_CONTROL_PROGRESS;
11570 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11571 }
11572 pri->pvts[chanpos]->progress = 1;
11573 pri->pvts[chanpos]->dialing = 0;
11574 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11575 }
11576 }
11577 break;
11578 case PRI_EVENT_PROCEEDING:
11579 chanpos = pri_find_principle(pri, e->proceeding.channel);
11580 if (chanpos > -1) {
11581 if (!pri->pvts[chanpos]->proceeding) {
11582 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11583
11584 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11585 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11586 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11587 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11588 #ifdef PRI_PROGRESS_MASK
11589 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11590 #else
11591 if (e->proceeding.progress == 8) {
11592 #endif
11593
11594 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11595 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11596 pri->pvts[chanpos]->dsp_features = 0;
11597 }
11598
11599 f.subclass = AST_CONTROL_PROGRESS;
11600 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11601 }
11602 pri->pvts[chanpos]->proceeding = 1;
11603 pri->pvts[chanpos]->dialing = 0;
11604 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11605 }
11606 }
11607 break;
11608 case PRI_EVENT_FACNAME:
11609 chanpos = pri_find_principle(pri, e->facname.channel);
11610 if (chanpos < 0) {
11611 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11612 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11613 } else {
11614 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11615 if (chanpos < 0) {
11616 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
11617 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11618 } else {
11619
11620 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11621 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11622 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11623 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11624 dahdi_enable_ec(pri->pvts[chanpos]);
11625 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11626 }
11627 }
11628 break;
11629 case PRI_EVENT_ANSWER:
11630 chanpos = pri_find_principle(pri, e->answer.channel);
11631 if (chanpos < 0) {
11632 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
11633 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11634 } else {
11635 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11636 if (chanpos < 0) {
11637 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
11638 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11639 } else {
11640 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11641
11642
11643
11644
11645
11646 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11647 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11648 pri->pvts[chanpos]->dsp_features = 0;
11649 }
11650 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11651 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11652 x = DAHDI_START;
11653 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11654 if (res < 0) {
11655 if (errno != EINPROGRESS) {
11656 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11657 }
11658 }
11659 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11660 pri->pvts[chanpos]->dialing = 1;
11661
11662 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11663 if (res < 0) {
11664 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11665 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11666 } else
11667 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11668
11669 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11670 } else if (pri->pvts[chanpos]->confirmanswer) {
11671 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11672 } else {
11673 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11674
11675 dahdi_enable_ec(pri->pvts[chanpos]);
11676 }
11677
11678 #ifdef SUPPORT_USERUSER
11679 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11680 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11681 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11682 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11683 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11684 }
11685 #endif
11686
11687 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11688 }
11689 }
11690 break;
11691 case PRI_EVENT_HANGUP:
11692 chanpos = pri_find_principle(pri, e->hangup.channel);
11693 if (chanpos < 0) {
11694 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
11695 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11696 } else {
11697 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11698 if (chanpos > -1) {
11699 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11700 if (!pri->pvts[chanpos]->alreadyhungup) {
11701
11702 pri->pvts[chanpos]->alreadyhungup = 1;
11703 if (pri->pvts[chanpos]->realcall)
11704 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11705 else if (pri->pvts[chanpos]->owner) {
11706
11707 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11708 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11709 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11710 else {
11711 switch (e->hangup.cause) {
11712 case PRI_CAUSE_USER_BUSY:
11713 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11714 break;
11715 case PRI_CAUSE_CALL_REJECTED:
11716 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11717 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11718 case PRI_CAUSE_SWITCH_CONGESTION:
11719 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11720 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11721 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11722 break;
11723 default:
11724 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11725 }
11726 }
11727 }
11728 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11729 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11730 } else {
11731 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11732 pri->pvts[chanpos]->call = NULL;
11733 }
11734 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11735 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11736 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11737 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11738 pri->pvts[chanpos]->resetting = 1;
11739 }
11740 if (e->hangup.aoc_units > -1)
11741 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11742 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11743
11744 #ifdef SUPPORT_USERUSER
11745 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11746 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11747 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11748 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11749 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11750 }
11751 #endif
11752
11753 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11754 } else {
11755 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
11756 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11757 }
11758 }
11759 break;
11760 #ifndef PRI_EVENT_HANGUP_REQ
11761 #error please update libpri
11762 #endif
11763 case PRI_EVENT_HANGUP_REQ:
11764 chanpos = pri_find_principle(pri, e->hangup.channel);
11765 if (chanpos < 0) {
11766 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11767 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11768 } else {
11769 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11770 if (chanpos > -1) {
11771 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11772 if (pri->pvts[chanpos]->realcall)
11773 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11774 else if (pri->pvts[chanpos]->owner) {
11775 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11776 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11777 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11778 else {
11779 switch (e->hangup.cause) {
11780 case PRI_CAUSE_USER_BUSY:
11781 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11782 break;
11783 case PRI_CAUSE_CALL_REJECTED:
11784 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11785 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11786 case PRI_CAUSE_SWITCH_CONGESTION:
11787 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11788 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11789 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11790 break;
11791 default:
11792 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11793 }
11794 }
11795 ast_verb(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);
11796 if (e->hangup.aoc_units > -1)
11797 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11798 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11799 } else {
11800 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11801 pri->pvts[chanpos]->call = NULL;
11802 }
11803 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11804 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11805 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11806 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11807 pri->pvts[chanpos]->resetting = 1;
11808 }
11809
11810 #ifdef SUPPORT_USERUSER
11811 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11812 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11813 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11814 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11815 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11816 }
11817 #endif
11818
11819 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11820 } else {
11821 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);
11822 }
11823 }
11824 break;
11825 case PRI_EVENT_HANGUP_ACK:
11826 chanpos = pri_find_principle(pri, e->hangup.channel);
11827 if (chanpos < 0) {
11828 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11829 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11830 } else {
11831 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11832 if (chanpos > -1) {
11833 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11834 pri->pvts[chanpos]->call = NULL;
11835 pri->pvts[chanpos]->resetting = 0;
11836 if (pri->pvts[chanpos]->owner) {
11837 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11838 }
11839
11840 #ifdef SUPPORT_USERUSER
11841 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11842 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11843 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11844 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11845 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11846 }
11847 #endif
11848
11849 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11850 }
11851 }
11852 break;
11853 case PRI_EVENT_CONFIG_ERR:
11854 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11855 break;
11856 case PRI_EVENT_RESTART_ACK:
11857 chanpos = pri_find_principle(pri, e->restartack.channel);
11858 if (chanpos < 0) {
11859
11860
11861
11862 for (x = 0; x < pri->numchans; x++) {
11863 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11864 chanpos = x;
11865 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11866 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11867 pri->pvts[chanpos]->prioffset, pri->span);
11868 if (pri->pvts[chanpos]->realcall)
11869 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11870 else if (pri->pvts[chanpos]->owner) {
11871 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11872 pri->pvts[chanpos]->prioffset, pri->span);
11873 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11874 }
11875 pri->pvts[chanpos]->resetting = 0;
11876 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11877 pri->pvts[chanpos]->prioffset, pri->span);
11878 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11879 if (pri->resetting)
11880 pri_check_restart(pri);
11881 break;
11882 }
11883 }
11884 if (chanpos < 0) {
11885 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11886 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11887 }
11888 } else {
11889 if (pri->pvts[chanpos]) {
11890 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11891 if (pri->pvts[chanpos]->realcall)
11892 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11893 else if (pri->pvts[chanpos]->owner) {
11894 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11895 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11896 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11897 }
11898 pri->pvts[chanpos]->resetting = 0;
11899 pri->pvts[chanpos]->inservice = 1;
11900 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11901 pri->pvts[chanpos]->prioffset, pri->span);
11902 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11903 if (pri->resetting)
11904 pri_check_restart(pri);
11905 }
11906 }
11907 break;
11908 case PRI_EVENT_SETUP_ACK:
11909 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11910 if (chanpos < 0) {
11911 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11912 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11913 } else {
11914 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11915 if (chanpos > -1) {
11916 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11917 pri->pvts[chanpos]->setup_ack = 1;
11918
11919 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11920 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11921 pri_information(pri->pri, pri->pvts[chanpos]->call,
11922 pri->pvts[chanpos]->dialdest[x]);
11923 }
11924 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11925 } else
11926 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11927 }
11928 break;
11929 case PRI_EVENT_NOTIFY:
11930 chanpos = pri_find_principle(pri, e->notify.channel);
11931 if (chanpos < 0) {
11932 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11933 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11934 } else {
11935 struct ast_frame f = { AST_FRAME_CONTROL, };
11936 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11937 switch (e->notify.info) {
11938 case PRI_NOTIFY_REMOTE_HOLD:
11939 f.subclass = AST_CONTROL_HOLD;
11940 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11941 break;
11942 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11943 f.subclass = AST_CONTROL_UNHOLD;
11944 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11945 break;
11946 }
11947 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11948 }
11949 break;
11950 default:
11951 ast_debug(1, "Event: %d\n", e->e);
11952 }
11953 }
11954 ast_mutex_unlock(&pri->lock);
11955 }
11956
11957 return NULL;
11958 }
11959
11960 static int start_pri(struct dahdi_pri *pri)
11961 {
11962 int res, x;
11963 struct dahdi_params p;
11964 struct dahdi_bufferinfo bi;
11965 struct dahdi_spaninfo si;
11966 int i;
11967
11968 for (i = 0; i < NUM_DCHANS; i++) {
11969 if (!pri->dchannels[i])
11970 break;
11971 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
11972 x = pri->dchannels[i];
11973 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11974 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11975 return -1;
11976 }
11977 memset(&p, 0, sizeof(p));
11978 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11979 if (res) {
11980 dahdi_close_pri_fd(pri, i);
11981 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11982 return -1;
11983 }
11984 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11985 dahdi_close_pri_fd(pri, i);
11986 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
11987 return -1;
11988 }
11989 memset(&si, 0, sizeof(si));
11990 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11991 if (res) {
11992 dahdi_close_pri_fd(pri, i);
11993 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11994 }
11995 if (!si.alarms)
11996 pri->dchanavail[i] |= DCHAN_NOTINALARM;
11997 else
11998 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11999 memset(&bi, 0, sizeof(bi));
12000 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12001 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12002 bi.numbufs = 32;
12003 bi.bufsize = 1024;
12004 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12005 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12006 dahdi_close_pri_fd(pri, i);
12007 return -1;
12008 }
12009 switch (pri->sig) {
12010 case SIG_BRI:
12011 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12012 break;
12013 case SIG_BRI_PTMP:
12014 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12015 break;
12016 default:
12017 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12018 }
12019
12020 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12021 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12022 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12023 #ifdef HAVE_PRI_INBANDDISCONNECT
12024 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12025 #endif
12026
12027 if (i)
12028 pri_enslave(pri->dchans[0], pri->dchans[i]);
12029 if (!pri->dchans[i]) {
12030 dahdi_close_pri_fd(pri, i);
12031 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12032 return -1;
12033 }
12034 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12035 pri_set_nsf(pri->dchans[i], pri->nsf);
12036 #ifdef PRI_GETSET_TIMERS
12037 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12038 if (pritimers[x] != 0)
12039 pri_set_timer(pri->dchans[i], x, pritimers[x]);
12040 }
12041 #endif
12042 }
12043
12044 pri->pri = pri->dchans[0];
12045 pri->resetpos = -1;
12046 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12047 for (i = 0; i < NUM_DCHANS; i++) {
12048 if (!pri->dchannels[i])
12049 break;
12050 dahdi_close_pri_fd(pri, i);
12051 }
12052 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12053 return -1;
12054 }
12055 return 0;
12056 }
12057
12058 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
12059 {
12060 int which, span;
12061 char *ret = NULL;
12062
12063 if (pos != rpos)
12064 return ret;
12065
12066 for (which = span = 0; span < NUM_SPANS; span++) {
12067 if (pris[span].pri && ++which > state) {
12068 if (asprintf(&ret, "%d", span + 1) < 0) {
12069 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12070 }
12071 break;
12072 }
12073 }
12074 return ret;
12075 }
12076
12077 static char *complete_span_4(const char *line, const char *word, int pos, int state)
12078 {
12079 return complete_span_helper(line,word,pos,state,3);
12080 }
12081
12082 static char *complete_span_5(const char *line, const char *word, int pos, int state)
12083 {
12084 return complete_span_helper(line,word,pos,state,4);
12085 }
12086
12087 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12088 {
12089 switch (cmd) {
12090 case CLI_INIT:
12091 e->command = "pri unset debug file";
12092 e->usage = "Usage: pri unset debug file\n"
12093 " Stop sending debug output to the previously \n"
12094 " specified file\n";
12095 return NULL;
12096 case CLI_GENERATE:
12097 return NULL;
12098 }
12099
12100 ast_mutex_lock(&pridebugfdlock);
12101 close(pridebugfd);
12102 pridebugfd = -1;
12103 ast_cli(a->fd, "PRI debug output to file disabled\n");
12104 ast_mutex_unlock(&pridebugfdlock);
12105 return CLI_SUCCESS;
12106 }
12107
12108 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12109 {
12110 int myfd;
12111 switch (cmd) {
12112 case CLI_INIT:
12113 e->command = "pri set debug file";
12114 e->usage = "Usage: pri set debug file [output-file]\n"
12115 " Sends PRI debug output to the specified output file\n";
12116 return NULL;
12117 case CLI_GENERATE:
12118 return NULL;
12119 }
12120 if (a->argc < 5)
12121 return CLI_SHOWUSAGE;
12122
12123 if (ast_strlen_zero(a->argv[4]))
12124 return CLI_SHOWUSAGE;
12125
12126 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12127 if (myfd < 0) {
12128 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12129 return CLI_SUCCESS;
12130 }
12131
12132 ast_mutex_lock(&pridebugfdlock);
12133
12134 if (pridebugfd >= 0)
12135 close(pridebugfd);
12136
12137 pridebugfd = myfd;
12138 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12139 ast_mutex_unlock(&pridebugfdlock);
12140 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12141 return CLI_SUCCESS;
12142 }
12143
12144 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12145 {
12146 int span;
12147 int x;
12148 switch (cmd) {
12149 case CLI_INIT:
12150 e->command = "pri debug span";
12151 e->usage =
12152 "Usage: pri debug span <span>\n"
12153 " Enables debugging on a given PRI span\n";
12154 return NULL;
12155 case CLI_GENERATE:
12156 return complete_span_4(a->line, a->word, a->pos, a->n);
12157 }
12158 if (a->argc < 4) {
12159 return CLI_SHOWUSAGE;
12160 }
12161 span = atoi(a->argv[3]);
12162 if ((span < 1) || (span > NUM_SPANS)) {
12163 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
12164 return CLI_SUCCESS;
12165 }
12166 if (!pris[span-1].pri) {
12167 ast_cli(a->fd, "No PRI running on span %d\n", span);
12168 return CLI_SUCCESS;
12169 }
12170 for (x = 0; x < NUM_DCHANS; x++) {
12171 if (pris[span-1].dchans[x])
12172 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12173 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12174 PRI_DEBUG_Q921_STATE);
12175 }
12176 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
12177 return CLI_SUCCESS;
12178 }
12179
12180
12181
12182 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12183 {
12184 int span;
12185 int x;
12186 switch (cmd) {
12187 case CLI_INIT:
12188 e->command = "pri no debug span";
12189 e->usage =
12190 "Usage: pri no debug span <span>\n"
12191 " Disables debugging on a given PRI span\n";
12192 return NULL;
12193 case CLI_GENERATE:
12194 return complete_span_5(a->line, a->word, a->pos, a->n);
12195 }
12196 if (a->argc < 5)
12197 return CLI_SHOWUSAGE;
12198
12199 span = atoi(a->argv[4]);
12200 if ((span < 1) || (span > NUM_SPANS)) {
12201 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12202 return CLI_SUCCESS;
12203 }
12204 if (!pris[span-1].pri) {
12205 ast_cli(a->fd, "No PRI running on span %d\n", span);
12206 return CLI_SUCCESS;
12207 }
12208 for (x = 0; x < NUM_DCHANS; x++) {
12209 if (pris[span-1].dchans[x])
12210 pri_set_debug(pris[span-1].dchans[x], 0);
12211 }
12212 ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12213 return CLI_SUCCESS;
12214 }
12215
12216 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12217 {
12218 int span;
12219 int x;
12220 switch (cmd) {
12221 case CLI_INIT:
12222 e->command = "pri intensive debug span";
12223 e->usage =
12224 "Usage: pri intensive debug span <span>\n"
12225 " Enables debugging down to the Q.921 level\n";
12226 return NULL;
12227 case CLI_GENERATE:
12228 return complete_span_5(a->line, a->word, a->pos, a->n);
12229 }
12230
12231 if (a->argc < 5)
12232 return CLI_SHOWUSAGE;
12233 span = atoi(a->argv[4]);
12234 if ((span < 1) || (span > NUM_SPANS)) {
12235 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12236 return CLI_SUCCESS;
12237 }
12238 if (!pris[span-1].pri) {
12239 ast_cli(a->fd, "No PRI running on span %d\n", span);
12240 return CLI_SUCCESS;
12241 }
12242 for (x = 0; x < NUM_DCHANS; x++) {
12243 if (pris[span-1].dchans[x])
12244 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12245 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12246 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12247 }
12248 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12249 return CLI_SUCCESS;
12250 }
12251
12252 static void build_status(char *s, size_t len, int status, int active)
12253 {
12254 if (!s || len < 1) {
12255 return;
12256 }
12257 s[0] = '\0';
12258 if (status & DCHAN_PROVISIONED)
12259 strncat(s, "Provisioned, ", len - strlen(s) - 1);
12260 if (!(status & DCHAN_NOTINALARM))
12261 strncat(s, "In Alarm, ", len - strlen(s) - 1);
12262 if (status & DCHAN_UP)
12263 strncat(s, "Up", len - strlen(s) - 1);
12264 else
12265 strncat(s, "Down", len - strlen(s) - 1);
12266 if (active)
12267 strncat(s, ", Active", len - strlen(s) - 1);
12268 else
12269 strncat(s, ", Standby", len - strlen(s) - 1);
12270 s[len - 1] = '\0';
12271 }
12272
12273 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12274 {
12275 int span;
12276 int x;
12277 char status[256];
12278
12279 switch (cmd) {
12280 case CLI_INIT:
12281 e->command = "pri show spans";
12282 e->usage =
12283 "Usage: pri show spans\n"
12284 " Displays PRI Information\n";
12285 return NULL;
12286 case CLI_GENERATE:
12287 return NULL;
12288 }
12289
12290 if (a->argc != 3)
12291 return CLI_SHOWUSAGE;
12292
12293 for (span = 0; span < NUM_SPANS; span++) {
12294 if (pris[span].pri) {
12295 for (x = 0; x < NUM_DCHANS; x++) {
12296 if (pris[span].dchannels[x]) {
12297 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12298 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12299 }
12300 }
12301 }
12302 }
12303 return CLI_SUCCESS;
12304 }
12305
12306 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12307 {
12308 int span;
12309 int x;
12310 char status[256];
12311 switch (cmd) {
12312 case CLI_INIT:
12313 e->command = "pri show span";
12314 e->usage =
12315 "Usage: pri show span <span>\n"
12316 " Displays PRI Information on a given PRI span\n";
12317 return NULL;
12318 case CLI_GENERATE:
12319 return complete_span_4(a->line, a->word, a->pos, a->n);
12320 }
12321
12322 if (a->argc < 4)
12323 return CLI_SHOWUSAGE;
12324 span = atoi(a->argv[3]);
12325 if ((span < 1) || (span > NUM_SPANS)) {
12326 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12327 return CLI_SUCCESS;
12328 }
12329 if (!pris[span-1].pri) {
12330 ast_cli(a->fd, "No PRI running on span %d\n", span);
12331 return CLI_SUCCESS;
12332 }
12333 for (x = 0; x < NUM_DCHANS; x++) {
12334 if (pris[span-1].dchannels[x]) {
12335 #ifdef PRI_DUMP_INFO_STR
12336 char *info_str = NULL;
12337 #endif
12338 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12339 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12340 ast_cli(a->fd, "Status: %s\n", status);
12341 #ifdef PRI_DUMP_INFO_STR
12342 info_str = pri_dump_info_str(pris[span-1].pri);
12343 if (info_str) {
12344 ast_cli(a->fd, "%s", info_str);
12345 ast_free(info_str);
12346 }
12347 #else
12348 pri_dump_info(pris[span-1].pri);
12349 #endif
12350 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12351 }
12352 }
12353 return CLI_SUCCESS;
12354 }
12355
12356 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12357 {
12358 int x;
12359 int span;
12360 int count=0;
12361 int debug=0;
12362
12363 switch (cmd) {
12364 case CLI_INIT:
12365 e->command = "pri show debug";
12366 e->usage =
12367 "Usage: pri show debug\n"
12368 " Show the debug state of pri spans\n";
12369 return NULL;
12370 case CLI_GENERATE:
12371 return NULL;
12372 }
12373
12374 for (span = 0; span < NUM_SPANS; span++) {
12375 if (pris[span].pri) {
12376 for (x = 0; x < NUM_DCHANS; x++) {
12377 debug = 0;
12378 if (pris[span].dchans[x]) {
12379 debug = pri_get_debug(pris[span].dchans[x]);
12380 ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
12381 count++;
12382 }
12383 }
12384 }
12385
12386 }
12387 ast_mutex_lock(&pridebugfdlock);
12388 if (pridebugfd >= 0)
12389 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12390 ast_mutex_unlock(&pridebugfdlock);
12391
12392 if (!count)
12393 ast_cli(a->fd, "No debug set or no PRI running\n");
12394 return CLI_SUCCESS;
12395 }
12396
12397 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12398 {
12399 switch (cmd) {
12400 case CLI_INIT:
12401 e->command = "pri show version";
12402 e->usage =
12403 "Usage: pri show version\n"
12404 "Show libpri version information\n";
12405 return NULL;
12406 case CLI_GENERATE:
12407 return NULL;
12408 }
12409
12410 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12411
12412 return CLI_SUCCESS;
12413 }
12414
12415 static struct ast_cli_entry dahdi_pri_cli[] = {
12416 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
12417 AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
12418 AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
12419 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
12420 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
12421 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
12422 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
12423 AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
12424 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
12425 };
12426
12427 #endif
12428
12429 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12430 {
12431 int channel;
12432 int ret;
12433 switch (cmd) {
12434 case CLI_INIT:
12435 e->command = "dahdi destroy channel";
12436 e->usage =
12437 "Usage: dahdi destroy channel <chan num>\n"
12438 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12439 return NULL;
12440 case CLI_GENERATE:
12441 return NULL;
12442 }
12443 if (a->argc != 4)
12444 return CLI_SHOWUSAGE;
12445
12446 channel = atoi(a->argv[3]);
12447 ret = dahdi_destroy_channel_bynum(channel);
12448 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12449 }
12450
12451 static void dahdi_softhangup_all(void)
12452 {
12453 struct dahdi_pvt *p;
12454 retry:
12455 ast_mutex_lock(&iflock);
12456 for (p = iflist; p; p = p->next) {
12457 ast_mutex_lock(&p->lock);
12458 if (p->owner && !p->restartpending) {
12459 if (ast_channel_trylock(p->owner)) {
12460 if (option_debug > 2)
12461 ast_verbose("Avoiding deadlock\n");
12462
12463 ast_mutex_unlock(&p->lock);
12464 ast_mutex_unlock(&iflock);
12465 goto retry;
12466 }
12467 if (option_debug > 2)
12468 ast_verbose("Softhanging up on %s\n", p->owner->name);
12469 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12470 p->restartpending = 1;
12471 num_restart_pending++;
12472 ast_channel_unlock(p->owner);
12473 }
12474 ast_mutex_unlock(&p->lock);
12475 }
12476 ast_mutex_unlock(&iflock);
12477 }
12478
12479 static int setup_dahdi(int reload);
12480 static int dahdi_restart(void)
12481 {
12482 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12483 int i, j;
12484 #endif
12485 int cancel_code;
12486 struct dahdi_pvt *p;
12487
12488 ast_mutex_lock(&restart_lock);
12489
12490 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12491 dahdi_softhangup_all();
12492 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12493
12494 #if defined(HAVE_PRI)
12495 for (i = 0; i < NUM_SPANS; i++) {
12496 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12497 cancel_code = pthread_cancel(pris[i].master);
12498 pthread_kill(pris[i].master, SIGURG);
12499 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12500 pthread_join(pris[i].master, NULL);
12501 ast_debug(4, "Joined thread of span %d\n", i);
12502 }
12503 }
12504 #endif
12505
12506 #if defined(HAVE_SS7)
12507 for (i = 0; i < NUM_SPANS; i++) {
12508 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12509 cancel_code = pthread_cancel(linksets[i].master);
12510 pthread_kill(linksets[i].master, SIGURG);
12511 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12512 pthread_join(linksets[i].master, NULL);
12513 ast_debug(4, "Joined thread of span %d\n", i);
12514 }
12515 }
12516 #endif
12517
12518 ast_mutex_lock(&monlock);
12519 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12520 cancel_code = pthread_cancel(monitor_thread);
12521 pthread_kill(monitor_thread, SIGURG);
12522 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12523 pthread_join(monitor_thread, NULL);
12524 ast_debug(4, "Joined monitor thread\n");
12525 }
12526 monitor_thread = AST_PTHREADT_NULL;
12527
12528 ast_mutex_lock(&mwi_thread_lock);
12529 while (mwi_thread_count > 0) {
12530 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12531 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12532 }
12533 ast_mutex_unlock(&mwi_thread_lock);
12534 ast_mutex_lock(&ss_thread_lock);
12535 while (ss_thread_count > 0) {
12536 int x = DAHDI_FLASH;
12537 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12538
12539 for (p = iflist; p; p = p->next) {
12540 if (p->owner)
12541 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
12542 }
12543 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12544 }
12545
12546
12547 dahdi_softhangup_all();
12548 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12549 destroy_all_channels();
12550 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12551
12552 ast_mutex_unlock(&monlock);
12553
12554 #ifdef HAVE_PRI
12555 for (i = 0; i < NUM_SPANS; i++) {
12556 for (j = 0; j < NUM_DCHANS; j++)
12557 dahdi_close_pri_fd(&(pris[i]), j);
12558 }
12559
12560 memset(pris, 0, sizeof(pris));
12561 for (i = 0; i < NUM_SPANS; i++) {
12562 ast_mutex_init(&pris[i].lock);
12563 pris[i].offset = -1;
12564 pris[i].master = AST_PTHREADT_NULL;
12565 for (j = 0; j < NUM_DCHANS; j++)
12566 pris[i].fds[j] = -1;
12567 }
12568 pri_set_error(dahdi_pri_error);
12569 pri_set_message(dahdi_pri_message);
12570 #endif
12571 #ifdef HAVE_SS7
12572 for (i = 0; i < NUM_SPANS; i++) {
12573 for (j = 0; j < NUM_DCHANS; j++)
12574 dahdi_close_ss7_fd(&(linksets[i]), j);
12575 }
12576
12577 memset(linksets, 0, sizeof(linksets));
12578 for (i = 0; i < NUM_SPANS; i++) {
12579 ast_mutex_init(&linksets[i].lock);
12580 linksets[i].master = AST_PTHREADT_NULL;
12581 for (j = 0; j < NUM_DCHANS; j++)
12582 linksets[i].fds[j] = -1;
12583 }
12584 ss7_set_error(dahdi_ss7_error);
12585 ss7_set_message(dahdi_ss7_message);
12586 #endif
12587
12588 if (setup_dahdi(2) != 0) {
12589 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12590 ast_mutex_unlock(&ss_thread_lock);
12591 return 1;
12592 }
12593 ast_mutex_unlock(&ss_thread_lock);
12594 ast_mutex_unlock(&restart_lock);
12595 return 0;
12596 }
12597
12598 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12599 {
12600 switch (cmd) {
12601 case CLI_INIT:
12602 e->command = "dahdi restart";
12603 e->usage =
12604 "Usage: dahdi restart\n"
12605 " Restarts the DAHDI channels: destroys them all and then\n"
12606 " re-reads them from chan_dahdi.conf.\n"
12607 " Note that this will STOP any running CALL on DAHDI channels.\n"
12608 "";
12609 return NULL;
12610 case CLI_GENERATE:
12611 return NULL;
12612 }
12613 if (a->argc != 2)
12614 return CLI_SHOWUSAGE;
12615
12616 if (dahdi_restart() != 0)
12617 return CLI_FAILURE;
12618 return CLI_SUCCESS;
12619 }
12620
12621 static int action_dahdirestart(struct mansession *s, const struct message *m)
12622 {
12623 if (dahdi_restart() != 0) {
12624 astman_send_error(s, m, "Failed rereading DAHDI configuration");
12625 return 1;
12626 }
12627 astman_send_ack(s, m, "DAHDIRestart: Success");
12628 return 0;
12629 }
12630
12631 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12632 {
12633 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12634 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12635 unsigned int targetnum = 0;
12636 int filtertype = 0;
12637 struct dahdi_pvt *tmp = NULL;
12638 char tmps[20] = "";
12639 char statestr[20] = "";
12640 char blockstr[20] = "";
12641 ast_mutex_t *lock;
12642 struct dahdi_pvt *start;
12643 #ifdef HAVE_PRI
12644 int trunkgroup;
12645 struct dahdi_pri *pri = NULL;
12646 int x;
12647 #endif
12648 switch (cmd) {
12649 case CLI_INIT:
12650 e->command = "dahdi show channels [trunkgroup|group|context]";
12651 e->usage =
12652 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12653 " Shows a list of available channels with optional filtering\n"
12654 " <group> must be a number between 0 and 63\n";
12655 return NULL;
12656 case CLI_GENERATE:
12657 return NULL;
12658 }
12659
12660 lock = &iflock;
12661 start = iflist;
12662
12663
12664
12665 if (!((a->argc == 3) || (a->argc == 5)))
12666 return CLI_SHOWUSAGE;
12667
12668 if (a->argc == 5) {
12669 #ifdef HAVE_PRI
12670 if (!strcasecmp(a->argv[3], "trunkgroup")) {
12671
12672 if ((trunkgroup = atoi(a->argv[4])) < 1)
12673 return CLI_SHOWUSAGE;
12674 for (x = 0; x < NUM_SPANS; x++) {
12675 if (pris[x].trunkgroup == trunkgroup) {
12676 pri = pris + x;
12677 break;
12678 }
12679 }
12680 if (pri) {
12681 start = pri->crvs;
12682 lock = &pri->lock;
12683 } else {
12684 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12685 return CLI_FAILURE;
12686 }
12687 } else
12688 #endif
12689 if (!strcasecmp(a->argv[3], "group")) {
12690 targetnum = atoi(a->argv[4]);
12691 if ((targetnum < 0) || (targetnum > 63))
12692 return CLI_SHOWUSAGE;
12693 targetnum = 1 << targetnum;
12694 filtertype = 1;
12695 } else if (!strcasecmp(a->argv[3], "context")) {
12696 filtertype = 2;
12697 }
12698 }
12699
12700 ast_mutex_lock(lock);
12701 #ifdef HAVE_PRI
12702 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12703 #else
12704 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12705 #endif
12706
12707 tmp = start;
12708 while (tmp) {
12709 if (filtertype) {
12710 switch(filtertype) {
12711 case 1:
12712 if (tmp->group != targetnum) {
12713 tmp = tmp->next;
12714 continue;
12715 }
12716 break;
12717 case 2:
12718 if (strcasecmp(tmp->context, a->argv[4])) {
12719 tmp = tmp->next;
12720 continue;
12721 }
12722 break;
12723 default:
12724 ;
12725 }
12726 }
12727 if (tmp->channel > 0) {
12728 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12729 } else
12730 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12731
12732 if (tmp->locallyblocked)
12733 blockstr[0] = 'L';
12734 else
12735 blockstr[0] = ' ';
12736
12737 if (tmp->remotelyblocked)
12738 blockstr[1] = 'R';
12739 else
12740 blockstr[1] = ' ';
12741
12742 blockstr[2] = '\0';
12743
12744 snprintf(statestr, sizeof(statestr), "%s", "In Service");
12745
12746 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12747 tmp = tmp->next;
12748 }
12749 ast_mutex_unlock(lock);
12750 return CLI_SUCCESS;
12751 #undef FORMAT
12752 #undef FORMAT2
12753 }
12754
12755 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12756 {
12757 int channel;
12758 struct dahdi_pvt *tmp = NULL;
12759 struct dahdi_confinfo ci;
12760 struct dahdi_params ps;
12761 int x;
12762 ast_mutex_t *lock;
12763 struct dahdi_pvt *start;
12764 #ifdef HAVE_PRI
12765 char *c;
12766 int trunkgroup;
12767 struct dahdi_pri *pri=NULL;
12768 #endif
12769 switch (cmd) {
12770 case CLI_INIT:
12771 e->command = "dahdi show channel";
12772 e->usage =
12773 "Usage: dahdi show channel <chan num>\n"
12774 " Detailed information about a given channel\n";
12775 return NULL;
12776 case CLI_GENERATE:
12777 return NULL;
12778 }
12779
12780 lock = &iflock;
12781 start = iflist;
12782
12783 if (a->argc != 4)
12784 return CLI_SHOWUSAGE;
12785 #ifdef HAVE_PRI
12786 if ((c = strchr(a->argv[3], ':'))) {
12787 if (sscanf(a->argv[3], "%d:%d", &trunkgroup, &channel) != 2)
12788 return CLI_SHOWUSAGE;
12789 if ((trunkgroup < 1) || (channel < 1))
12790 return CLI_SHOWUSAGE;
12791 for (x = 0; x < NUM_SPANS; x++) {
12792 if (pris[x].trunkgroup == trunkgroup) {
12793 pri = pris + x;
12794 break;
12795 }
12796 }
12797 if (pri) {
12798 start = pri->crvs;
12799 lock = &pri->lock;
12800 } else {
12801 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12802 return CLI_FAILURE;
12803 }
12804 } else
12805 #endif
12806 channel = atoi(a->argv[3]);
12807
12808 ast_mutex_lock(lock);
12809 tmp = start;
12810 while (tmp) {
12811 if (tmp->channel == channel) {
12812 #ifdef HAVE_PRI
12813 if (pri)
12814 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12815 else
12816 #endif
12817 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12818 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12819 ast_cli(a->fd, "Span: %d\n", tmp->span);
12820 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12821 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12822 ast_cli(a->fd, "Context: %s\n", tmp->context);
12823 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12824 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12825 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12826 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12827 if (tmp->vars) {
12828 struct ast_variable *v;
12829 ast_cli(a->fd, "Variables:\n");
12830 for (v = tmp->vars ; v ; v = v->next)
12831 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
12832 }
12833 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12834 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12835 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12836 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12837 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12838 ast_cli(a->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)" : "");
12839 ast_cli(a->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)" : "");
12840 ast_cli(a->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)" : "");
12841 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12842 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12843 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12844 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12845 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12846 if (tmp->busydetect) {
12847 #if defined(BUSYDETECT_TONEONLY)
12848 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12849 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12850 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12851 #endif
12852 #ifdef BUSYDETECT_DEBUG
12853 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
12854 #endif
12855 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
12856 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
12857 }
12858 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12859 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12860 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12861 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12862 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12863 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12864 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12865 ast_cli(a->fd, "Echo Cancellation:\n");
12866
12867 if (tmp->echocancel.head.tap_length) {
12868 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12869 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12870 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12871 }
12872 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12873 } else {
12874 ast_cli(a->fd, "\tnone\n");
12875 }
12876 if (tmp->master)
12877 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12878 for (x = 0; x < MAX_SLAVES; x++) {
12879 if (tmp->slaves[x])
12880 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12881 }
12882 #ifdef HAVE_SS7
12883 if (tmp->ss7) {
12884 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12885 }
12886 #endif
12887 #ifdef HAVE_PRI
12888 if (tmp->pri) {
12889 ast_cli(a->fd, "PRI Flags: ");
12890 if (tmp->resetting)
12891 ast_cli(a->fd, "Resetting ");
12892 if (tmp->call)
12893 ast_cli(a->fd, "Call ");
12894 if (tmp->bearer)
12895 ast_cli(a->fd, "Bearer ");
12896 ast_cli(a->fd, "\n");
12897 if (tmp->logicalspan)
12898 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12899 else
12900 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12901 }
12902
12903 #endif
12904 memset(&ci, 0, sizeof(ci));
12905 ps.channo = tmp->channel;
12906 if (tmp->subs[SUB_REAL].dfd > -1) {
12907 memset(&ci, 0, sizeof(ci));
12908 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12909 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12910 }
12911 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12912 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12913 }
12914 memset(&ps, 0, sizeof(ps));
12915 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12916 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12917 } else {
12918 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12919 }
12920 }
12921 if (ISTRUNK(tmp)) {
12922 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
12923 if (!ast_strlen_zero(progzone))
12924 ast_cli(a->fd, "Progress Zone: %s\n", progzone);
12925 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
12926 if(tmp->busydetect) {
12927 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
12928 if(tmp->busytonelength > 0) {
12929 ast_cli(a->fd, "Busy Pattern:\n");
12930 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12931 if (tmp->busyquietlength > 0)
12932 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12933 else
12934 ast_cli(a->fd, " -- Detect Tone Only\n");
12935 if(tmp->busyfuzziness > 0)
12936 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12937 }
12938 }
12939 }
12940 ast_mutex_unlock(lock);
12941 return CLI_SUCCESS;
12942 }
12943 tmp = tmp->next;
12944 }
12945
12946 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12947 ast_mutex_unlock(lock);
12948 return CLI_FAILURE;
12949 }
12950
12951 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12952 {
12953 int i, j;
12954 switch (cmd) {
12955 case CLI_INIT:
12956 e->command = "dahdi show cadences";
12957 e->usage =
12958 "Usage: dahdi show cadences\n"
12959 " Shows all cadences currently defined\n";
12960 return NULL;
12961 case CLI_GENERATE:
12962 return NULL;
12963 }
12964 for (i = 0; i < num_cadence; i++) {
12965 char output[1024];
12966 char tmp[16], tmp2[64];
12967 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12968 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12969
12970 for (j = 0; j < 16; j++) {
12971 if (cadences[i].ringcadence[j] == 0)
12972 break;
12973 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12974 if (cidrings[i] * 2 - 1 == j)
12975 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12976 else
12977 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12978 if (j != 0)
12979 strncat(output, ",", sizeof(output) - strlen(output) - 1);
12980 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12981 }
12982 ast_cli(a->fd,"%s\n",output);
12983 }
12984 return CLI_SUCCESS;
12985 }
12986
12987
12988 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12989 {
12990 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12991 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12992 int span;
12993 int res;
12994 char alarmstr[50];
12995
12996 int ctl;
12997 struct dahdi_spaninfo s;
12998
12999 switch (cmd) {
13000 case CLI_INIT:
13001 e->command = "dahdi show status";
13002 e->usage =
13003 "Usage: dahdi show status\n"
13004 " Shows a list of DAHDI cards with status\n";
13005 return NULL;
13006 case CLI_GENERATE:
13007 return NULL;
13008 }
13009 ctl = open("/dev/dahdi/ctl", O_RDWR);
13010 if (ctl < 0) {
13011 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13012 return CLI_FAILURE;
13013 }
13014 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13015
13016 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13017 s.spanno = span;
13018 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13019 if (res) {
13020 continue;
13021 }
13022 alarmstr[0] = '\0';
13023 if (s.alarms > 0) {
13024 if (s.alarms & DAHDI_ALARM_BLUE)
13025 strcat(alarmstr, "BLU/");
13026 if (s.alarms & DAHDI_ALARM_YELLOW)
13027 strcat(alarmstr, "YEL/");
13028 if (s.alarms & DAHDI_ALARM_RED)
13029 strcat(alarmstr, "RED/");
13030 if (s.alarms & DAHDI_ALARM_LOOPBACK)
13031 strcat(alarmstr, "LB/");
13032 if (s.alarms & DAHDI_ALARM_RECOVER)
13033 strcat(alarmstr, "REC/");
13034 if (s.alarms & DAHDI_ALARM_NOTOPEN)
13035 strcat(alarmstr, "NOP/");
13036 if (!strlen(alarmstr))
13037 strcat(alarmstr, "UUU/");
13038 if (strlen(alarmstr)) {
13039
13040 alarmstr[strlen(alarmstr) - 1] = '\0';
13041 }
13042 } else {
13043 if (s.numchans)
13044 strcpy(alarmstr, "OK");
13045 else
13046 strcpy(alarmstr, "UNCONFIGURED");
13047 }
13048
13049 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13050 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13051 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13052 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13053 "CAS"
13054 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13055 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13056 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13057 "Unk"
13058 , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13059 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13060 , lbostr[s.lbo]
13061 );
13062 }
13063 close(ctl);
13064
13065 return CLI_SUCCESS;
13066 #undef FORMAT
13067 #undef FORMAT2
13068 }
13069
13070 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13071 {
13072 int pseudo_fd = -1;
13073 struct dahdi_versioninfo vi;
13074
13075 switch (cmd) {
13076 case CLI_INIT:
13077 e->command = "dahdi show version";
13078 e->usage =
13079 "Usage: dahdi show version\n"
13080 " Shows the DAHDI version in use\n";
13081 return NULL;
13082 case CLI_GENERATE:
13083 return NULL;
13084 }
13085 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13086 ast_cli(a->fd, "Failed to open control file to get version.\n");
13087 return CLI_SUCCESS;
13088 }
13089
13090 strcpy(vi.version, "Unknown");
13091 strcpy(vi.echo_canceller, "Unknown");
13092
13093 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13094 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13095 else
13096 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13097
13098 close(pseudo_fd);
13099
13100 return CLI_SUCCESS;
13101 }
13102
13103 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13104 {
13105 int channel;
13106 int gain;
13107 int tx;
13108 struct dahdi_hwgain hwgain;
13109 struct dahdi_pvt *tmp = NULL;
13110
13111 switch (cmd) {
13112 case CLI_INIT:
13113 e->command = "dahdi set hwgain";
13114 e->usage =
13115 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
13116 " Sets the hardware gain on a a given channel, overriding the\n"
13117 " value provided at module loadtime, whether the channel is in\n"
13118 " use or not. Changes take effect immediately.\n"
13119 " <rx|tx> which direction do you want to change (relative to our module)\n"
13120 " <chan num> is the channel number relative to the device\n"
13121 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13122 return NULL;
13123 case CLI_GENERATE:
13124 return NULL;
13125 }
13126
13127 if (a->argc != 6)
13128 return CLI_SHOWUSAGE;
13129
13130 if (!strcasecmp("rx", a->argv[3]))
13131 tx = 0;
13132 else if (!strcasecmp("tx", a->argv[3]))
13133 tx = 1;
13134 else
13135 return CLI_SHOWUSAGE;
13136
13137 channel = atoi(a->argv[4]);
13138 gain = atof(a->argv[5])*10.0;
13139
13140 ast_mutex_lock(&iflock);
13141
13142 for (tmp = iflist; tmp; tmp = tmp->next) {
13143
13144 if (tmp->channel != channel)
13145 continue;
13146
13147 if (tmp->subs[SUB_REAL].dfd == -1)
13148 break;
13149
13150 hwgain.newgain = gain;
13151 hwgain.tx = tx;
13152 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
13153 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
13154 ast_mutex_unlock(&iflock);
13155 return CLI_FAILURE;
13156 }
13157 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
13158 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
13159 break;
13160 }
13161
13162 ast_mutex_unlock(&iflock);
13163
13164 if (tmp)
13165 return CLI_SUCCESS;
13166
13167 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13168 return CLI_FAILURE;
13169
13170 }
13171
13172 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13173 {
13174 int channel;
13175 float gain;
13176 int tx;
13177 int res;
13178 ast_mutex_t *lock;
13179 struct dahdi_pvt *tmp = NULL;
13180
13181 switch (cmd) {
13182 case CLI_INIT:
13183 e->command = "dahdi set swgain";
13184 e->usage =
13185 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13186 " Sets the software gain on a a given channel, overriding the\n"
13187 " value provided at module loadtime, whether the channel is in\n"
13188 " use or not. Changes take effect immediately.\n"
13189 " <rx|tx> which direction do you want to change (relative to our module)\n"
13190 " <chan num> is the channel number relative to the device\n"
13191 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13192 return NULL;
13193 case CLI_GENERATE:
13194 return NULL;
13195 }
13196
13197 lock = &iflock;
13198
13199 if (a->argc != 6)
13200 return CLI_SHOWUSAGE;
13201
13202 if (!strcasecmp("rx", a->argv[3]))
13203 tx = 0;
13204 else if (!strcasecmp("tx", a->argv[3]))
13205 tx = 1;
13206 else
13207 return CLI_SHOWUSAGE;
13208
13209 channel = atoi(a->argv[4]);
13210 gain = atof(a->argv[5]);
13211
13212 ast_mutex_lock(lock);
13213 for (tmp = iflist; tmp; tmp = tmp->next) {
13214
13215 if (tmp->channel != channel)
13216 continue;
13217
13218 if (tmp->subs[SUB_REAL].dfd == -1)
13219 break;
13220
13221 if (tx)
13222 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13223 else
13224 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13225
13226 if (res) {
13227 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13228 ast_mutex_unlock(lock);
13229 return CLI_FAILURE;
13230 }
13231
13232 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13233 tx ? "tx" : "rx", gain, channel);
13234 break;
13235 }
13236 ast_mutex_unlock(lock);
13237
13238 if (tmp)
13239 return CLI_SUCCESS;
13240
13241 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13242 return CLI_FAILURE;
13243
13244 }
13245
13246 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13247 {
13248 int channel;
13249 int on;
13250 struct dahdi_pvt *dahdi_chan = NULL;
13251
13252 switch (cmd) {
13253 case CLI_INIT:
13254 e->command = "dahdi set dnd";
13255 e->usage =
13256 "Usage: dahdi set dnd <chan#> <on|off>\n"
13257 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13258 " Changes take effect immediately.\n"
13259 " <chan num> is the channel number\n"
13260 " <on|off> Enable or disable DND mode?\n"
13261 ;
13262 return NULL;
13263 case CLI_GENERATE:
13264 return NULL;
13265 }
13266
13267 if (a->argc != 5)
13268 return CLI_SHOWUSAGE;
13269
13270 if ((channel = atoi(a->argv[3])) <= 0) {
13271 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13272 return CLI_SHOWUSAGE;
13273 }
13274
13275 if (ast_true(a->argv[4]))
13276 on = 1;
13277 else if (ast_false(a->argv[4]))
13278 on = 0;
13279 else {
13280 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13281 return CLI_SHOWUSAGE;
13282 }
13283
13284 ast_mutex_lock(&iflock);
13285 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13286 if (dahdi_chan->channel != channel)
13287 continue;
13288
13289
13290 dahdi_dnd(dahdi_chan, on);
13291 break;
13292 }
13293 ast_mutex_unlock(&iflock);
13294
13295 if (!dahdi_chan) {
13296 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13297 return CLI_FAILURE;
13298 }
13299
13300 return CLI_SUCCESS;
13301 }
13302
13303 static struct ast_cli_entry dahdi_cli[] = {
13304 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
13305 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
13306 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
13307 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
13308 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
13309 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
13310 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
13311 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
13312 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
13313 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
13314 };
13315
13316 #define TRANSFER 0
13317 #define HANGUP 1
13318
13319 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13320 {
13321 if (p) {
13322 switch (mode) {
13323 case TRANSFER:
13324 p->fake_event = DAHDI_EVENT_WINKFLASH;
13325 break;
13326 case HANGUP:
13327 p->fake_event = DAHDI_EVENT_ONHOOK;
13328 break;
13329 default:
13330 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
13331 }
13332 }
13333 return 0;
13334 }
13335 static struct dahdi_pvt *find_channel(int channel)
13336 {
13337 struct dahdi_pvt *p = iflist;
13338 while (p) {
13339 if (p->channel == channel) {
13340 break;
13341 }
13342 p = p->next;
13343 }
13344 return p;
13345 }
13346
13347 static int action_dahdidndon(struct mansession *s, const struct message *m)
13348 {
13349 struct dahdi_pvt *p = NULL;
13350 const char *channel = astman_get_header(m, "DAHDIChannel");
13351
13352 if (ast_strlen_zero(channel)) {
13353 astman_send_error(s, m, "No channel specified");
13354 return 0;
13355 }
13356 p = find_channel(atoi(channel));
13357 if (!p) {
13358 astman_send_error(s, m, "No such channel");
13359 return 0;
13360 }
13361 p->dnd = 1;
13362 astman_send_ack(s, m, "DND Enabled");
13363 return 0;
13364 }
13365
13366 static int action_dahdidndoff(struct mansession *s, const struct message *m)
13367 {
13368 struct dahdi_pvt *p = NULL;
13369 const char *channel = astman_get_header(m, "DAHDIChannel");
13370
13371 if (ast_strlen_zero(channel)) {
13372 astman_send_error(s, m, "No channel specified");
13373 return 0;
13374 }
13375 p = find_channel(atoi(channel));
13376 if (!p) {
13377 astman_send_error(s, m, "No such channel");
13378 return 0;
13379 }
13380 p->dnd = 0;
13381 astman_send_ack(s, m, "DND Disabled");
13382 return 0;
13383 }
13384
13385 static int action_transfer(struct mansession *s, const struct message *m)
13386 {
13387 struct dahdi_pvt *p = NULL;
13388 const char *channel = astman_get_header(m, "DAHDIChannel");
13389
13390 if (ast_strlen_zero(channel)) {
13391 astman_send_error(s, m, "No channel specified");
13392 return 0;
13393 }
13394 p = find_channel(atoi(channel));
13395 if (!p) {
13396 astman_send_error(s, m, "No such channel");
13397 return 0;
13398 }
13399 dahdi_fake_event(p,TRANSFER);
13400 astman_send_ack(s, m, "DAHDITransfer");
13401 return 0;
13402 }
13403
13404 static int action_transferhangup(struct mansession *s, const struct message *m)
13405 {
13406 struct dahdi_pvt *p = NULL;
13407 const char *channel = astman_get_header(m, "DAHDIChannel");
13408
13409 if (ast_strlen_zero(channel)) {
13410 astman_send_error(s, m, "No channel specified");
13411 return 0;
13412 }
13413 p = find_channel(atoi(channel));
13414 if (!p) {
13415 astman_send_error(s, m, "No such channel");
13416 return 0;
13417 }
13418 dahdi_fake_event(p,HANGUP);
13419 astman_send_ack(s, m, "DAHDIHangup");
13420 return 0;
13421 }
13422
13423 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
13424 {
13425 struct dahdi_pvt *p = NULL;
13426 const char *channel = astman_get_header(m, "DAHDIChannel");
13427 const char *number = astman_get_header(m, "Number");
13428 int i;
13429
13430 if (ast_strlen_zero(channel)) {
13431 astman_send_error(s, m, "No channel specified");
13432 return 0;
13433 }
13434 if (ast_strlen_zero(number)) {
13435 astman_send_error(s, m, "No number specified");
13436 return 0;
13437 }
13438 p = find_channel(atoi(channel));
13439 if (!p) {
13440 astman_send_error(s, m, "No such channel");
13441 return 0;
13442 }
13443 if (!p->owner) {
13444 astman_send_error(s, m, "Channel does not have it's owner");
13445 return 0;
13446 }
13447 for (i = 0; i < strlen(number); i++) {
13448 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13449 dahdi_queue_frame(p, &f, NULL);
13450 }
13451 astman_send_ack(s, m, "DAHDIDialOffhook");
13452 return 0;
13453 }
13454
13455 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
13456 {
13457 struct dahdi_pvt *tmp = NULL;
13458 const char *id = astman_get_header(m, "ActionID");
13459 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13460 char idText[256] = "";
13461 int channels = 0;
13462 int dahdichanquery = -1;
13463 if (!ast_strlen_zero(dahdichannel)) {
13464 dahdichanquery = atoi(dahdichannel);
13465 }
13466
13467 astman_send_ack(s, m, "DAHDI channel status will follow");
13468 if (!ast_strlen_zero(id))
13469 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13470
13471 ast_mutex_lock(&iflock);
13472
13473 tmp = iflist;
13474 while (tmp) {
13475 if (tmp->channel > 0) {
13476 int alm = get_alarms(tmp);
13477
13478
13479 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13480 continue;
13481
13482 channels++;
13483 if (tmp->owner) {
13484
13485 astman_append(s,
13486 "Event: DAHDIShowChannels\r\n"
13487 "DAHDIChannel: %d\r\n"
13488 "Channel: %s\r\n"
13489 "Uniqueid: %s\r\n"
13490 "AccountCode: %s\r\n"
13491 "Signalling: %s\r\n"
13492 "SignallingCode: %d\r\n"
13493 "Context: %s\r\n"
13494 "DND: %s\r\n"
13495 "Alarm: %s\r\n"
13496 "%s"
13497 "\r\n",
13498 tmp->channel,
13499 tmp->owner->name,
13500 tmp->owner->uniqueid,
13501 tmp->owner->accountcode,
13502 sig2str(tmp->sig),
13503 tmp->sig,
13504 tmp->context,
13505 tmp->dnd ? "Enabled" : "Disabled",
13506 alarm2str(alm), idText);
13507 } else {
13508 astman_append(s,
13509 "Event: DAHDIShowChannels\r\n"
13510 "DAHDIChannel: %d\r\n"
13511 "Signalling: %s\r\n"
13512 "SignallingCode: %d\r\n"
13513 "Context: %s\r\n"
13514 "DND: %s\r\n"
13515 "Alarm: %s\r\n"
13516 "%s"
13517 "\r\n",
13518 tmp->channel, sig2str(tmp->sig), tmp->sig,
13519 tmp->context,
13520 tmp->dnd ? "Enabled" : "Disabled",
13521 alarm2str(alm), idText);
13522 }
13523 }
13524
13525 tmp = tmp->next;
13526 }
13527
13528 ast_mutex_unlock(&iflock);
13529
13530 astman_append(s,
13531 "Event: DAHDIShowChannelsComplete\r\n"
13532 "%s"
13533 "Items: %d\r\n"
13534 "\r\n",
13535 idText,
13536 channels);
13537 return 0;
13538 }
13539
13540 #ifdef HAVE_SS7
13541 static int linkset_addsigchan(int sigchan)
13542 {
13543 struct dahdi_ss7 *link;
13544 int res;
13545 int curfd;
13546 struct dahdi_params p;
13547 struct dahdi_bufferinfo bi;
13548 struct dahdi_spaninfo si;
13549
13550
13551 link = ss7_resolve_linkset(cur_linkset);
13552 if (!link) {
13553 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
13554 return -1;
13555 }
13556
13557 if (cur_ss7type < 0) {
13558 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13559 return -1;
13560 }
13561
13562 if (!link->ss7)
13563 link->ss7 = ss7_new(cur_ss7type);
13564
13565 if (!link->ss7) {
13566 ast_log(LOG_ERROR, "Can't create new SS7!\n");
13567 return -1;
13568 }
13569
13570 link->type = cur_ss7type;
13571
13572 if (cur_pointcode < 0) {
13573 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13574 return -1;
13575 } else
13576 ss7_set_pc(link->ss7, cur_pointcode);
13577
13578 if (sigchan < 0) {
13579 ast_log(LOG_ERROR, "Invalid sigchan!\n");
13580 return -1;
13581 } else {
13582 if (link->numsigchans >= NUM_DCHANS) {
13583 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13584 return -1;
13585 }
13586 curfd = link->numsigchans;
13587
13588 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13589 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13590 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13591 return -1;
13592 }
13593 memset(&p, 0, sizeof(p));
13594 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13595 if (res) {
13596 dahdi_close_ss7_fd(link, curfd);
13597 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13598 return -1;
13599 }
13600 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13601 dahdi_close_ss7_fd(link, curfd);
13602 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13603 return -1;
13604 }
13605
13606 memset(&bi, 0, sizeof(bi));
13607 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13608 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13609 bi.numbufs = 32;
13610 bi.bufsize = 512;
13611
13612 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13613 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13614 dahdi_close_ss7_fd(link, curfd);
13615 return -1;
13616 }
13617
13618 if (p.sigtype == DAHDI_SIG_MTP2)
13619 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13620 else
13621 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13622
13623 link->numsigchans++;
13624
13625 memset(&si, 0, sizeof(si));
13626 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13627 if (res) {
13628 dahdi_close_ss7_fd(link, curfd);
13629 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13630 }
13631
13632 if (!si.alarms) {
13633 link->linkstate[curfd] = LINKSTATE_DOWN;
13634 ss7_link_noalarm(link->ss7, link->fds[curfd]);
13635 } else {
13636 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13637 ss7_link_alarm(link->ss7, link->fds[curfd]);
13638 }
13639 }
13640
13641 if (cur_adjpointcode < 0) {
13642 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13643 return -1;
13644 } else {
13645 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13646 }
13647
13648 if (cur_defaultdpc < 0) {
13649 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13650 return -1;
13651 }
13652
13653 if (cur_networkindicator < 0) {
13654 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13655 return -1;
13656 } else
13657 ss7_set_network_ind(link->ss7, cur_networkindicator);
13658
13659 return 0;
13660 }
13661
13662 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13663 {
13664 int span;
13665 switch (cmd) {
13666 case CLI_INIT:
13667 e->command = "ss7 no debug linkset";
13668 e->usage =
13669 "Usage: ss7 no debug linkset <span>\n"
13670 " Disables debugging on a given SS7 linkset\n";
13671 return NULL;
13672 case CLI_GENERATE:
13673 return NULL;
13674 }
13675 if (a->argc < 5)
13676 return CLI_SHOWUSAGE;
13677 span = atoi(a->argv[4]);
13678 if ((span < 1) || (span > NUM_SPANS)) {
13679 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13680 return CLI_SUCCESS;
13681 }
13682 if (!linksets[span-1].ss7) {
13683 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13684 return CLI_SUCCESS;
13685 }
13686 if (linksets[span-1].ss7)
13687 ss7_set_debug(linksets[span-1].ss7, 0);
13688
13689 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13690 return CLI_SUCCESS;
13691 }
13692
13693 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13694 {
13695 int span;
13696 switch (cmd) {
13697 case CLI_INIT:
13698 e->command = "ss7 debug linkset";
13699 e->usage =
13700 "Usage: ss7 debug linkset <linkset>\n"
13701 " Enables debugging on a given SS7 linkset\n";
13702 return NULL;
13703 case CLI_GENERATE:
13704 return NULL;
13705 }
13706 if (a->argc < 4)
13707 return CLI_SHOWUSAGE;
13708 span = atoi(a->argv[3]);
13709 if ((span < 1) || (span > NUM_SPANS)) {
13710 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13711 return CLI_SUCCESS;
13712 }
13713 if (!linksets[span-1].ss7) {
13714 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13715 return CLI_SUCCESS;
13716 }
13717 if (linksets[span-1].ss7)
13718 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13719
13720 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13721 return CLI_SUCCESS;
13722 }
13723
13724 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13725 {
13726 int linkset, cic;
13727 int blocked = -1, i;
13728 switch (cmd) {
13729 case CLI_INIT:
13730 e->command = "ss7 block cic";
13731 e->usage =
13732 "Usage: ss7 block cic <linkset> <CIC>\n"
13733 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13734 return NULL;
13735 case CLI_GENERATE:
13736 return NULL;
13737 }
13738 if (a->argc == 5)
13739 linkset = atoi(a->argv[3]);
13740 else
13741 return CLI_SHOWUSAGE;
13742
13743 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13744 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13745 return CLI_SUCCESS;
13746 }
13747
13748 if (!linksets[linkset-1].ss7) {
13749 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13750 return CLI_SUCCESS;
13751 }
13752
13753 cic = atoi(a->argv[4]);
13754
13755 if (cic < 1) {
13756 ast_cli(a->fd, "Invalid CIC specified!\n");
13757 return CLI_SUCCESS;
13758 }
13759
13760 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13761 if (linksets[linkset-1].pvts[i]->cic == cic) {
13762 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13763 if (!blocked) {
13764 ast_mutex_lock(&linksets[linkset-1].lock);
13765 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13766 ast_mutex_unlock(&linksets[linkset-1].lock);
13767 }
13768 }
13769 }
13770
13771 if (blocked < 0) {
13772 ast_cli(a->fd, "Invalid CIC specified!\n");
13773 return CLI_SUCCESS;
13774 }
13775
13776 if (!blocked)
13777 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13778 else
13779 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13780
13781
13782 pthread_kill(linksets[linkset-1].master, SIGURG);
13783
13784 return CLI_SUCCESS;
13785 }
13786
13787 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13788 {
13789 int linkset;
13790 int i;
13791 switch (cmd) {
13792 case CLI_INIT:
13793 e->command = "ss7 block linkset";
13794 e->usage =
13795 "Usage: ss7 block linkset <linkset number>\n"
13796 " Sends a remote blocking request for all CICs on the given linkset\n";
13797 return NULL;
13798 case CLI_GENERATE:
13799 return NULL;
13800 }
13801 if (a->argc == 4)
13802 linkset = atoi(a->argv[3]);
13803 else
13804 return CLI_SHOWUSAGE;
13805
13806 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13807 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13808 return CLI_SUCCESS;
13809 }
13810
13811 if (!linksets[linkset-1].ss7) {
13812 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13813 return CLI_SUCCESS;
13814 }
13815
13816 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13817 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13818 ast_mutex_lock(&linksets[linkset-1].lock);
13819 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13820 ast_mutex_unlock(&linksets[linkset-1].lock);
13821 }
13822
13823
13824 pthread_kill(linksets[linkset-1].master, SIGURG);
13825
13826 return CLI_SUCCESS;
13827 }
13828
13829 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13830 {
13831 int linkset, cic;
13832 int i, blocked = -1;
13833 switch (cmd) {
13834 case CLI_INIT:
13835 e->command = "ss7 unblock cic";
13836 e->usage =
13837 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13838 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13839 return NULL;
13840 case CLI_GENERATE:
13841 return NULL;
13842 }
13843
13844 if (a->argc == 5)
13845 linkset = atoi(a->argv[3]);
13846 else
13847 return CLI_SHOWUSAGE;
13848
13849 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13850 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13851 return CLI_SUCCESS;
13852 }
13853
13854 if (!linksets[linkset-1].ss7) {
13855 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13856 return CLI_SUCCESS;
13857 }
13858
13859 cic = atoi(a->argv[4]);
13860
13861 if (cic < 1) {
13862 ast_cli(a->fd, "Invalid CIC specified!\n");
13863 return CLI_SUCCESS;
13864 }
13865
13866 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13867 if (linksets[linkset-1].pvts[i]->cic == cic) {
13868 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13869 if (blocked) {
13870 ast_mutex_lock(&linksets[linkset-1].lock);
13871 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13872 ast_mutex_unlock(&linksets[linkset-1].lock);
13873 }
13874 }
13875 }
13876
13877 if (blocked > 0)
13878 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13879
13880
13881 pthread_kill(linksets[linkset-1].master, SIGURG);
13882
13883 return CLI_SUCCESS;
13884 }
13885
13886 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13887 {
13888 int linkset;
13889 int i;
13890 switch (cmd) {
13891 case CLI_INIT:
13892 e->command = "ss7 unblock linkset";
13893 e->usage =
13894 "Usage: ss7 unblock linkset <linkset number>\n"
13895 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13896 return NULL;
13897 case CLI_GENERATE:
13898 return NULL;
13899 }
13900
13901 if (a->argc == 4)
13902 linkset = atoi(a->argv[3]);
13903 else
13904 return CLI_SHOWUSAGE;
13905
13906 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13907 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13908 return CLI_SUCCESS;
13909 }
13910
13911 if (!linksets[linkset-1].ss7) {
13912 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13913 return CLI_SUCCESS;
13914 }
13915
13916 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13917 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13918 ast_mutex_lock(&linksets[linkset-1].lock);
13919 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13920 ast_mutex_unlock(&linksets[linkset-1].lock);
13921 }
13922
13923
13924 pthread_kill(linksets[linkset-1].master, SIGURG);
13925
13926 return CLI_SUCCESS;
13927 }
13928
13929 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13930 {
13931 int linkset;
13932 struct dahdi_ss7 *ss7;
13933 switch (cmd) {
13934 case CLI_INIT:
13935 e->command = "ss7 show linkset";
13936 e->usage =
13937 "Usage: ss7 show linkset <span>\n"
13938 " Shows the status of an SS7 linkset.\n";
13939 return NULL;
13940 case CLI_GENERATE:
13941 return NULL;
13942 }
13943
13944 if (a->argc < 4)
13945 return CLI_SHOWUSAGE;
13946 linkset = atoi(a->argv[3]);
13947 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13948 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13949 return CLI_SUCCESS;
13950 }
13951 if (!linksets[linkset-1].ss7) {
13952 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13953 return CLI_SUCCESS;
13954 }
13955 if (linksets[linkset-1].ss7)
13956 ss7 = &linksets[linkset-1];
13957
13958 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
13959
13960 return CLI_SUCCESS;
13961 }
13962
13963 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13964 {
13965 switch (cmd) {
13966 case CLI_INIT:
13967 e->command = "ss7 show version";
13968 e->usage =
13969 "Usage: ss7 show version\n"
13970 " Show the libss7 version\n";
13971 return NULL;
13972 case CLI_GENERATE:
13973 return NULL;
13974 }
13975
13976 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
13977
13978 return CLI_SUCCESS;
13979 }
13980
13981 static struct ast_cli_entry dahdi_ss7_cli[] = {
13982 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
13983 AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"),
13984 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
13985 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
13986 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
13987 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
13988 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
13989 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
13990 };
13991 #endif
13992
13993 static int __unload_module(void)
13994 {
13995 struct dahdi_pvt *p;
13996 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13997 int i, j;
13998 #endif
13999
14000 #ifdef HAVE_PRI
14001 for (i = 0; i < NUM_SPANS; i++) {
14002 if (pris[i].master != AST_PTHREADT_NULL)
14003 pthread_cancel(pris[i].master);
14004 }
14005 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14006 ast_unregister_application(dahdi_send_keypad_facility_app);
14007 #endif
14008 #if defined(HAVE_SS7)
14009 for (i = 0; i < NUM_SPANS; i++) {
14010 if (linksets[i].master != AST_PTHREADT_NULL)
14011 pthread_cancel(linksets[i].master);
14012 }
14013 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14014 #endif
14015
14016 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14017 ast_manager_unregister( "DAHDIDialOffhook" );
14018 ast_manager_unregister( "DAHDIHangup" );
14019 ast_manager_unregister( "DAHDITransfer" );
14020 ast_manager_unregister( "DAHDIDNDoff" );
14021 ast_manager_unregister( "DAHDIDNDon" );
14022 ast_manager_unregister("DAHDIShowChannels");
14023 ast_manager_unregister("DAHDIRestart");
14024 ast_channel_unregister(&dahdi_tech);
14025 ast_mutex_lock(&iflock);
14026
14027 p = iflist;
14028 while (p) {
14029 if (p->owner)
14030 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14031 p = p->next;
14032 }
14033 ast_mutex_unlock(&iflock);
14034 ast_mutex_lock(&monlock);
14035 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14036 pthread_cancel(monitor_thread);
14037 pthread_kill(monitor_thread, SIGURG);
14038 pthread_join(monitor_thread, NULL);
14039 }
14040 monitor_thread = AST_PTHREADT_STOP;
14041 ast_mutex_unlock(&monlock);
14042
14043 destroy_all_channels();
14044
14045 #if defined(HAVE_PRI)
14046 for (i = 0; i < NUM_SPANS; i++) {
14047 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14048 pthread_join(pris[i].master, NULL);
14049 for (j = 0; j < NUM_DCHANS; j++) {
14050 dahdi_close_pri_fd(&(pris[i]), j);
14051 }
14052 }
14053 #endif
14054
14055 #if defined(HAVE_SS7)
14056 for (i = 0; i < NUM_SPANS; i++) {
14057 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14058 pthread_join(linksets[i].master, NULL);
14059 for (j = 0; j < NUM_DCHANS; j++) {
14060 dahdi_close_ss7_fd(&(linksets[i]), j);
14061 }
14062 }
14063 #endif
14064
14065 ast_cond_destroy(&mwi_thread_complete);
14066 ast_cond_destroy(&ss_thread_complete);
14067 return 0;
14068 }
14069
14070 static int unload_module(void)
14071 {
14072 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14073 int y;
14074 #endif
14075 #ifdef HAVE_PRI
14076 for (y = 0; y < NUM_SPANS; y++)
14077 ast_mutex_destroy(&pris[y].lock);
14078 #endif
14079 #ifdef HAVE_SS7
14080 for (y = 0; y < NUM_SPANS; y++)
14081 ast_mutex_destroy(&linksets[y].lock);
14082 #endif
14083 return __unload_module();
14084 }
14085
14086 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
14087 {
14088 char *c, *chan;
14089 int x, start, finish;
14090 struct dahdi_pvt *tmp;
14091 #ifdef HAVE_PRI
14092 struct dahdi_pri *pri;
14093 int trunkgroup, y;
14094 #endif
14095
14096 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14097 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14098 return -1;
14099 }
14100
14101 c = ast_strdupa(value);
14102
14103 #ifdef HAVE_PRI
14104 pri = NULL;
14105 if (iscrv) {
14106 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
14107 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14108 return -1;
14109 }
14110 if (trunkgroup < 1) {
14111 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14112 return -1;
14113 }
14114 c += y;
14115 for (y = 0; y < NUM_SPANS; y++) {
14116 if (pris[y].trunkgroup == trunkgroup) {
14117 pri = pris + y;
14118 break;
14119 }
14120 }
14121 if (!pri) {
14122 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14123 return -1;
14124 }
14125 }
14126 #endif
14127
14128 while ((chan = strsep(&c, ","))) {
14129 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
14130
14131 } else if (sscanf(chan, "%d", &start)) {
14132
14133 finish = start;
14134 } else if (!strcasecmp(chan, "pseudo")) {
14135 finish = start = CHAN_PSEUDO;
14136 if (found_pseudo)
14137 *found_pseudo = 1;
14138 } else {
14139 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14140 return -1;
14141 }
14142 if (finish < start) {
14143 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14144 x = finish;
14145 finish = start;
14146 start = x;
14147 }
14148
14149 for (x = start; x <= finish; x++) {
14150 #ifdef HAVE_PRI
14151 tmp = mkintf(x, conf, pri, reload);
14152 #else
14153 tmp = mkintf(x, conf, NULL, reload);
14154 #endif
14155
14156 if (tmp) {
14157 #ifdef HAVE_PRI
14158 if (pri)
14159 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14160 else
14161 #endif
14162 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14163 } else {
14164 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14165 (reload == 1) ? "reconfigure" : "register", value);
14166 return -1;
14167 }
14168 }
14169 }
14170
14171 return 0;
14172 }
14173
14174
14175
14176 #define MAX_CHANLIST_LEN 80
14177
14178 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
14179 {
14180 char *parse = ast_strdupa(data);
14181 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14182 unsigned int param_count;
14183 unsigned int x;
14184
14185 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14186 return;
14187
14188 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14189
14190
14191
14192 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14193
14194 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14195 confp->chan.echocancel.head.tap_length = x;
14196 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14197 confp->chan.echocancel.head.tap_length = 128;
14198
14199
14200
14201 for (x = 1; x < param_count; x++) {
14202 struct {
14203 char *name;
14204 char *value;
14205 } param;
14206
14207 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
14208 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14209 continue;
14210 }
14211
14212 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14213 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14214 continue;
14215 }
14216
14217 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14218
14219 if (param.value) {
14220 if (sscanf(param.value, "%d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14221 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14222 continue;
14223 }
14224 }
14225 confp->chan.echocancel.head.param_count++;
14226 }
14227 }
14228
14229
14230 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
14231
14232 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
14233
14234 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
14235 {
14236 struct dahdi_pvt *tmp;
14237 int y;
14238 int found_pseudo = 0;
14239 char dahdichan[MAX_CHANLIST_LEN] = {};
14240
14241 for (; v; v = v->next) {
14242 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14243 continue;
14244
14245
14246 if (!strcasecmp(v->name, "parkinglot")) {
14247 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
14248 }
14249
14250
14251 if (!strcasecmp(v->name, "channel")
14252 #ifdef HAVE_PRI
14253 || !strcasecmp(v->name, "crv")
14254 #endif
14255 ) {
14256 int iscrv;
14257 if (options & PROC_DAHDI_OPT_NOCHAN) {
14258 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
14259 continue;
14260 }
14261 iscrv = !strcasecmp(v->name, "crv");
14262 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14263 return -1;
14264 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
14265 } else if (!strcasecmp(v->name, "buffers")) {
14266 int res;
14267 char policy[21] = "";
14268
14269 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
14270 if (res != 2) {
14271 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14272 confp->chan.buf_no = numbufs;
14273 continue;
14274 }
14275 if (confp->chan.buf_no < 0)
14276 confp->chan.buf_no = numbufs;
14277 if (!strcasecmp(policy, "full")) {
14278 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14279 } else if (!strcasecmp(policy, "immediate")) {
14280 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14281 } else {
14282 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14283 }
14284 } else if (!strcasecmp(v->name, "dahdichan")) {
14285 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14286 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14287 usedistinctiveringdetection = ast_true(v->value);
14288 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14289 distinctiveringaftercid = ast_true(v->value);
14290 } else if (!strcasecmp(v->name, "dring1context")) {
14291 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14292 } else if (!strcasecmp(v->name, "dring2context")) {
14293 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14294 } else if (!strcasecmp(v->name, "dring3context")) {
14295 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14296 } else if (!strcasecmp(v->name, "dring1range")) {
14297 confp->chan.drings.ringnum[0].range = atoi(v->value);
14298 } else if (!strcasecmp(v->name, "dring2range")) {
14299 confp->chan.drings.ringnum[1].range = atoi(v->value);
14300 } else if (!strcasecmp(v->name, "dring3range")) {
14301 confp->chan.drings.ringnum[2].range = atoi(v->value);
14302 } else if (!strcasecmp(v->name, "dring1")) {
14303 sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
14304 } else if (!strcasecmp(v->name, "dring2")) {
14305 sscanf(v->value,"%d,%d,%d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
14306 } else if (!strcasecmp(v->name, "dring3")) {
14307 sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
14308 } else if (!strcasecmp(v->name, "usecallerid")) {
14309 confp->chan.use_callerid = ast_true(v->value);
14310 } else if (!strcasecmp(v->name, "cidsignalling")) {
14311 if (!strcasecmp(v->value, "bell"))
14312 confp->chan.cid_signalling = CID_SIG_BELL;
14313 else if (!strcasecmp(v->value, "v23"))
14314 confp->chan.cid_signalling = CID_SIG_V23;
14315 else if (!strcasecmp(v->value, "dtmf"))
14316 confp->chan.cid_signalling = CID_SIG_DTMF;
14317 else if (!strcasecmp(v->value, "smdi"))
14318 confp->chan.cid_signalling = CID_SIG_SMDI;
14319 else if (!strcasecmp(v->value, "v23_jp"))
14320 confp->chan.cid_signalling = CID_SIG_V23_JP;
14321 else if (ast_true(v->value))
14322 confp->chan.cid_signalling = CID_SIG_BELL;
14323 } else if (!strcasecmp(v->name, "cidstart")) {
14324 if (!strcasecmp(v->value, "ring"))
14325 confp->chan.cid_start = CID_START_RING;
14326 else if (!strcasecmp(v->value, "polarity_in"))
14327 confp->chan.cid_start = CID_START_POLARITY_IN;
14328 else if (!strcasecmp(v->value, "polarity"))
14329 confp->chan.cid_start = CID_START_POLARITY;
14330 else if (ast_true(v->value))
14331 confp->chan.cid_start = CID_START_RING;
14332 } else if (!strcasecmp(v->name, "threewaycalling")) {
14333 confp->chan.threewaycalling = ast_true(v->value);
14334 } else if (!strcasecmp(v->name, "cancallforward")) {
14335 confp->chan.cancallforward = ast_true(v->value);
14336 } else if (!strcasecmp(v->name, "relaxdtmf")) {
14337 if (ast_true(v->value))
14338 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14339 else
14340 confp->chan.dtmfrelax = 0;
14341 } else if (!strcasecmp(v->name, "mailbox")) {
14342 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14343 } else if (!strcasecmp(v->name, "hasvoicemail")) {
14344 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14345 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14346 }
14347 } else if (!strcasecmp(v->name, "adsi")) {
14348 confp->chan.adsi = ast_true(v->value);
14349 } else if (!strcasecmp(v->name, "usesmdi")) {
14350 confp->chan.use_smdi = ast_true(v->value);
14351 } else if (!strcasecmp(v->name, "smdiport")) {
14352 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14353 } else if (!strcasecmp(v->name, "transfer")) {
14354 confp->chan.transfer = ast_true(v->value);
14355 } else if (!strcasecmp(v->name, "canpark")) {
14356 confp->chan.canpark = ast_true(v->value);
14357 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14358 confp->chan.echocanbridged = ast_true(v->value);
14359 } else if (!strcasecmp(v->name, "busydetect")) {
14360 confp->chan.busydetect = ast_true(v->value);
14361 } else if (!strcasecmp(v->name, "busycount")) {
14362 confp->chan.busycount = atoi(v->value);
14363 } else if (!strcasecmp(v->name, "silencethreshold")) {
14364 confp->chan.silencethreshold = atoi(v->value);
14365 } else if (!strcasecmp(v->name, "busycompare")) {
14366 confp->chan.busycompare = ast_true(v->value);
14367 } else if (!strcasecmp(v->name, "busypattern")) {
14368 if (sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
14369 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14370 }
14371 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
14372 if (count == 1)
14373 confp->chan.busyquietlength = 0;
14374 else if (count < 1)
14375 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
14376 } else if (!strcasecmp(v->name, "busyfuzziness")) {
14377 confp->chan.busyfuzziness = atoi(v->value);
14378 } else if (!strcasecmp(v->name, "callprogress")) {
14379 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14380 if (ast_true(v->value))
14381 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14382 } else if (!strcasecmp(v->name, "faxdetect")) {
14383 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14384 if (!strcasecmp(v->value, "incoming")) {
14385 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14386 } else if (!strcasecmp(v->value, "outgoing")) {
14387 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14388 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14389 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14390 } else if (!strcasecmp(v->name, "echocancel")) {
14391 process_echocancel(confp, v->value, v->lineno);
14392 } else if (!strcasecmp(v->name, "echotraining")) {
14393 if (sscanf(v->value, "%d", &y) == 1) {
14394 if ((y < 10) || (y > 4000)) {
14395 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
14396 } else {
14397 confp->chan.echotraining = y;
14398 }
14399 } else if (ast_true(v->value)) {
14400 confp->chan.echotraining = 400;
14401 } else
14402 confp->chan.echotraining = 0;
14403 } else if (!strcasecmp(v->name, "hidecallerid")) {
14404 confp->chan.hidecallerid = ast_true(v->value);
14405 } else if (!strcasecmp(v->name, "hidecalleridname")) {
14406 confp->chan.hidecalleridname = ast_true(v->value);
14407 } else if (!strcasecmp(v->name, "pulsedial")) {
14408 confp->chan.pulse = ast_true(v->value);
14409 } else if (!strcasecmp(v->name, "callreturn")) {
14410 confp->chan.callreturn = ast_true(v->value);
14411 } else if (!strcasecmp(v->name, "callwaiting")) {
14412 confp->chan.callwaiting = ast_true(v->value);
14413 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14414 confp->chan.callwaitingcallerid = ast_true(v->value);
14415 } else if (!strcasecmp(v->name, "context")) {
14416 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14417 } else if (!strcasecmp(v->name, "language")) {
14418 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14419 } else if (!strcasecmp(v->name, "progzone")) {
14420 ast_copy_string(progzone, v->value, sizeof(progzone));
14421 } else if (!strcasecmp(v->name, "mohinterpret")
14422 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14423 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14424 } else if (!strcasecmp(v->name, "mohsuggest")) {
14425 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14426 } else if (!strcasecmp(v->name, "parkinglot")) {
14427 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
14428 } else if (!strcasecmp(v->name, "stripmsd")) {
14429 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14430 confp->chan.stripmsd = atoi(v->value);
14431 } else if (!strcasecmp(v->name, "jitterbuffers")) {
14432 numbufs = atoi(v->value);
14433 } else if (!strcasecmp(v->name, "group")) {
14434 confp->chan.group = ast_get_group(v->value);
14435 } else if (!strcasecmp(v->name, "callgroup")) {
14436 if (!strcasecmp(v->value, "none"))
14437 confp->chan.callgroup = 0;
14438 else
14439 confp->chan.callgroup = ast_get_group(v->value);
14440 } else if (!strcasecmp(v->name, "pickupgroup")) {
14441 if (!strcasecmp(v->value, "none"))
14442 confp->chan.pickupgroup = 0;
14443 else
14444 confp->chan.pickupgroup = ast_get_group(v->value);
14445 } else if (!strcasecmp(v->name, "setvar")) {
14446 char *varname = ast_strdupa(v->value), *varval = NULL;
14447 struct ast_variable *tmpvar;
14448 if (varname && (varval = strchr(varname, '='))) {
14449 *varval++ = '\0';
14450 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14451 tmpvar->next = confp->chan.vars;
14452 confp->chan.vars = tmpvar;
14453 }
14454 }
14455 } else if (!strcasecmp(v->name, "immediate")) {
14456 confp->chan.immediate = ast_true(v->value);
14457 } else if (!strcasecmp(v->name, "transfertobusy")) {
14458 confp->chan.transfertobusy = ast_true(v->value);
14459 } else if (!strcasecmp(v->name, "mwimonitor")) {
14460 confp->chan.mwimonitor_neon = 0;
14461 confp->chan.mwimonitor_fsk = 0;
14462 confp->chan.mwimonitor_rpas = 0;
14463 if (strcasestr(v->value, "fsk")) {
14464 confp->chan.mwimonitor_fsk = 1;
14465 }
14466 if (strcasestr(v->value, "rpas")) {
14467 confp->chan.mwimonitor_rpas = 1;
14468 }
14469 if (strcasestr(v->value, "neon")) {
14470 confp->chan.mwimonitor_neon = 1;
14471 }
14472
14473 if (ast_true(v->value)) {
14474 confp->chan.mwimonitor_fsk = 1;
14475 }
14476 } else if (!strcasecmp(v->name, "cid_rxgain")) {
14477 if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) {
14478 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14479 }
14480 } else if (!strcasecmp(v->name, "rxgain")) {
14481 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
14482 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14483 }
14484 } else if (!strcasecmp(v->name, "txgain")) {
14485 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
14486 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14487 }
14488 } else if (!strcasecmp(v->name, "tonezone")) {
14489 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
14490 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14491 }
14492 } else if (!strcasecmp(v->name, "callerid")) {
14493 if (!strcasecmp(v->value, "asreceived")) {
14494 confp->chan.cid_num[0] = '\0';
14495 confp->chan.cid_name[0] = '\0';
14496 } else {
14497 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14498 }
14499 } else if (!strcasecmp(v->name, "fullname")) {
14500 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14501 } else if (!strcasecmp(v->name, "cid_number")) {
14502 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14503 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14504 confp->chan.dahditrcallerid = ast_true(v->value);
14505 } else if (!strcasecmp(v->name, "restrictcid")) {
14506 confp->chan.restrictcid = ast_true(v->value);
14507 } else if (!strcasecmp(v->name, "usecallingpres")) {
14508 confp->chan.use_callingpres = ast_true(v->value);
14509 } else if (!strcasecmp(v->name, "accountcode")) {
14510 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14511 } else if (!strcasecmp(v->name, "amaflags")) {
14512 y = ast_cdr_amaflags2int(v->value);
14513 if (y < 0)
14514 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14515 else
14516 confp->chan.amaflags = y;
14517 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14518 confp->chan.polarityonanswerdelay = atoi(v->value);
14519 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14520 confp->chan.answeronpolarityswitch = ast_true(v->value);
14521 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14522 confp->chan.hanguponpolarityswitch = ast_true(v->value);
14523 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14524 confp->chan.sendcalleridafter = atoi(v->value);
14525 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14526 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14527 } else if (!strcasecmp(v->name, "mwisendtype")) {
14528 if (!strcasecmp(v->value, "rpas")) {
14529 mwisend_rpas = 1;
14530 } else {
14531 mwisend_rpas = 0;
14532 }
14533 } else if (reload != 1) {
14534 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14535 int orig_radio = confp->chan.radio;
14536 int orig_outsigmod = confp->chan.outsigmod;
14537 int orig_auto = confp->is_sig_auto;
14538
14539 confp->chan.radio = 0;
14540 confp->chan.outsigmod = -1;
14541 confp->is_sig_auto = 0;
14542 if (!strcasecmp(v->value, "em")) {
14543 confp->chan.sig = SIG_EM;
14544 } else if (!strcasecmp(v->value, "em_e1")) {
14545 confp->chan.sig = SIG_EM_E1;
14546 } else if (!strcasecmp(v->value, "em_w")) {
14547 confp->chan.sig = SIG_EMWINK;
14548 } else if (!strcasecmp(v->value, "fxs_ls")) {
14549 confp->chan.sig = SIG_FXSLS;
14550 } else if (!strcasecmp(v->value, "fxs_gs")) {
14551 confp->chan.sig = SIG_FXSGS;
14552 } else if (!strcasecmp(v->value, "fxs_ks")) {
14553 confp->chan.sig = SIG_FXSKS;
14554 } else if (!strcasecmp(v->value, "fxo_ls")) {
14555 confp->chan.sig = SIG_FXOLS;
14556 } else if (!strcasecmp(v->value, "fxo_gs")) {
14557 confp->chan.sig = SIG_FXOGS;
14558 } else if (!strcasecmp(v->value, "fxo_ks")) {
14559 confp->chan.sig = SIG_FXOKS;
14560 } else if (!strcasecmp(v->value, "fxs_rx")) {
14561 confp->chan.sig = SIG_FXSKS;
14562 confp->chan.radio = 1;
14563 } else if (!strcasecmp(v->value, "fxo_rx")) {
14564 confp->chan.sig = SIG_FXOLS;
14565 confp->chan.radio = 1;
14566 } else if (!strcasecmp(v->value, "fxs_tx")) {
14567 confp->chan.sig = SIG_FXSLS;
14568 confp->chan.radio = 1;
14569 } else if (!strcasecmp(v->value, "fxo_tx")) {
14570 confp->chan.sig = SIG_FXOGS;
14571 confp->chan.radio = 1;
14572 } else if (!strcasecmp(v->value, "em_rx")) {
14573 confp->chan.sig = SIG_EM;
14574 confp->chan.radio = 1;
14575 } else if (!strcasecmp(v->value, "em_tx")) {
14576 confp->chan.sig = SIG_EM;
14577 confp->chan.radio = 1;
14578 } else if (!strcasecmp(v->value, "em_rxtx")) {
14579 confp->chan.sig = SIG_EM;
14580 confp->chan.radio = 2;
14581 } else if (!strcasecmp(v->value, "em_txrx")) {
14582 confp->chan.sig = SIG_EM;
14583 confp->chan.radio = 2;
14584 } else if (!strcasecmp(v->value, "sf")) {
14585 confp->chan.sig = SIG_SF;
14586 } else if (!strcasecmp(v->value, "sf_w")) {
14587 confp->chan.sig = SIG_SFWINK;
14588 } else if (!strcasecmp(v->value, "sf_featd")) {
14589 confp->chan.sig = SIG_FEATD;
14590 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14591 confp->chan.sig = SIG_FEATDMF;
14592 } else if (!strcasecmp(v->value, "sf_featb")) {
14593 confp->chan.sig = SIG_SF_FEATB;
14594 } else if (!strcasecmp(v->value, "sf")) {
14595 confp->chan.sig = SIG_SF;
14596 } else if (!strcasecmp(v->value, "sf_rx")) {
14597 confp->chan.sig = SIG_SF;
14598 confp->chan.radio = 1;
14599 } else if (!strcasecmp(v->value, "sf_tx")) {
14600 confp->chan.sig = SIG_SF;
14601 confp->chan.radio = 1;
14602 } else if (!strcasecmp(v->value, "sf_rxtx")) {
14603 confp->chan.sig = SIG_SF;
14604 confp->chan.radio = 2;
14605 } else if (!strcasecmp(v->value, "sf_txrx")) {
14606 confp->chan.sig = SIG_SF;
14607 confp->chan.radio = 2;
14608 } else if (!strcasecmp(v->value, "featd")) {
14609 confp->chan.sig = SIG_FEATD;
14610 } else if (!strcasecmp(v->value, "featdmf")) {
14611 confp->chan.sig = SIG_FEATDMF;
14612 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14613 confp->chan.sig = SIG_FEATDMF_TA;
14614 } else if (!strcasecmp(v->value, "e911")) {
14615 confp->chan.sig = SIG_E911;
14616 } else if (!strcasecmp(v->value, "fgccama")) {
14617 confp->chan.sig = SIG_FGC_CAMA;
14618 } else if (!strcasecmp(v->value, "fgccamamf")) {
14619 confp->chan.sig = SIG_FGC_CAMAMF;
14620 } else if (!strcasecmp(v->value, "featb")) {
14621 confp->chan.sig = SIG_FEATB;
14622 #ifdef HAVE_PRI
14623 } else if (!strcasecmp(v->value, "pri_net")) {
14624 confp->chan.sig = SIG_PRI;
14625 confp->pri.nodetype = PRI_NETWORK;
14626 } else if (!strcasecmp(v->value, "pri_cpe")) {
14627 confp->chan.sig = SIG_PRI;
14628 confp->pri.nodetype = PRI_CPE;
14629 } else if (!strcasecmp(v->value, "bri_cpe")) {
14630 confp->chan.sig = SIG_BRI;
14631 confp->pri.nodetype = PRI_CPE;
14632 } else if (!strcasecmp(v->value, "bri_net")) {
14633 confp->chan.sig = SIG_BRI;
14634 confp->pri.nodetype = PRI_NETWORK;
14635 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14636 confp->chan.sig = SIG_BRI_PTMP;
14637 confp->pri.nodetype = PRI_CPE;
14638 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14639 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
14640 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14641 confp->chan.sig = SIG_GR303FXOKS;
14642 confp->pri.nodetype = PRI_NETWORK;
14643 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14644 confp->chan.sig = SIG_GR303FXSKS;
14645 confp->pri.nodetype = PRI_CPE;
14646 #endif
14647 #ifdef HAVE_SS7
14648 } else if (!strcasecmp(v->value, "ss7")) {
14649 confp->chan.sig = SIG_SS7;
14650 #endif
14651 } else if (!strcasecmp(v->value, "auto")) {
14652 confp->is_sig_auto = 1;
14653 } else {
14654 confp->chan.outsigmod = orig_outsigmod;
14655 confp->chan.radio = orig_radio;
14656 confp->is_sig_auto = orig_auto;
14657 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14658 }
14659 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14660 if (!strcasecmp(v->value, "em")) {
14661 confp->chan.outsigmod = SIG_EM;
14662 } else if (!strcasecmp(v->value, "em_e1")) {
14663 confp->chan.outsigmod = SIG_EM_E1;
14664 } else if (!strcasecmp(v->value, "em_w")) {
14665 confp->chan.outsigmod = SIG_EMWINK;
14666 } else if (!strcasecmp(v->value, "sf")) {
14667 confp->chan.outsigmod = SIG_SF;
14668 } else if (!strcasecmp(v->value, "sf_w")) {
14669 confp->chan.outsigmod = SIG_SFWINK;
14670 } else if (!strcasecmp(v->value, "sf_featd")) {
14671 confp->chan.outsigmod = SIG_FEATD;
14672 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14673 confp->chan.outsigmod = SIG_FEATDMF;
14674 } else if (!strcasecmp(v->value, "sf_featb")) {
14675 confp->chan.outsigmod = SIG_SF_FEATB;
14676 } else if (!strcasecmp(v->value, "sf")) {
14677 confp->chan.outsigmod = SIG_SF;
14678 } else if (!strcasecmp(v->value, "featd")) {
14679 confp->chan.outsigmod = SIG_FEATD;
14680 } else if (!strcasecmp(v->value, "featdmf")) {
14681 confp->chan.outsigmod = SIG_FEATDMF;
14682 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14683 confp->chan.outsigmod = SIG_FEATDMF_TA;
14684 } else if (!strcasecmp(v->value, "e911")) {
14685 confp->chan.outsigmod = SIG_E911;
14686 } else if (!strcasecmp(v->value, "fgccama")) {
14687 confp->chan.outsigmod = SIG_FGC_CAMA;
14688 } else if (!strcasecmp(v->value, "fgccamamf")) {
14689 confp->chan.outsigmod = SIG_FGC_CAMAMF;
14690 } else if (!strcasecmp(v->value, "featb")) {
14691 confp->chan.outsigmod = SIG_FEATB;
14692 } else {
14693 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14694 }
14695 #ifdef HAVE_PRI
14696 } else if (!strcasecmp(v->name, "pridialplan")) {
14697 if (!strcasecmp(v->value, "national")) {
14698 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14699 } else if (!strcasecmp(v->value, "unknown")) {
14700 confp->pri.dialplan = PRI_UNKNOWN + 1;
14701 } else if (!strcasecmp(v->value, "private")) {
14702 confp->pri.dialplan = PRI_PRIVATE + 1;
14703 } else if (!strcasecmp(v->value, "international")) {
14704 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14705 } else if (!strcasecmp(v->value, "local")) {
14706 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14707 } else if (!strcasecmp(v->value, "dynamic")) {
14708 confp->pri.dialplan = -1;
14709 } else if (!strcasecmp(v->value, "redundant")) {
14710 confp->pri.dialplan = -2;
14711 } else {
14712 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14713 }
14714 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14715 if (!strcasecmp(v->value, "national")) {
14716 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14717 } else if (!strcasecmp(v->value, "unknown")) {
14718 confp->pri.localdialplan = PRI_UNKNOWN + 1;
14719 } else if (!strcasecmp(v->value, "private")) {
14720 confp->pri.localdialplan = PRI_PRIVATE + 1;
14721 } else if (!strcasecmp(v->value, "international")) {
14722 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14723 } else if (!strcasecmp(v->value, "local")) {
14724 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14725 } else if (!strcasecmp(v->value, "dynamic")) {
14726 confp->pri.localdialplan = -1;
14727 } else if (!strcasecmp(v->value, "redundant")) {
14728 confp->pri.localdialplan = -2;
14729 } else {
14730 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14731 }
14732 } else if (!strcasecmp(v->name, "switchtype")) {
14733 if (!strcasecmp(v->value, "national"))
14734 confp->pri.switchtype = PRI_SWITCH_NI2;
14735 else if (!strcasecmp(v->value, "ni1"))
14736 confp->pri.switchtype = PRI_SWITCH_NI1;
14737 else if (!strcasecmp(v->value, "dms100"))
14738 confp->pri.switchtype = PRI_SWITCH_DMS100;
14739 else if (!strcasecmp(v->value, "4ess"))
14740 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14741 else if (!strcasecmp(v->value, "5ess"))
14742 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14743 else if (!strcasecmp(v->value, "euroisdn"))
14744 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14745 else if (!strcasecmp(v->value, "qsig"))
14746 confp->pri.switchtype = PRI_SWITCH_QSIG;
14747 else {
14748 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14749 return -1;
14750 }
14751 } else if (!strcasecmp(v->name, "nsf")) {
14752 if (!strcasecmp(v->value, "sdn"))
14753 confp->pri.nsf = PRI_NSF_SDN;
14754 else if (!strcasecmp(v->value, "megacom"))
14755 confp->pri.nsf = PRI_NSF_MEGACOM;
14756 else if (!strcasecmp(v->value, "tollfreemegacom"))
14757 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14758 else if (!strcasecmp(v->value, "accunet"))
14759 confp->pri.nsf = PRI_NSF_ACCUNET;
14760 else if (!strcasecmp(v->value, "none"))
14761 confp->pri.nsf = PRI_NSF_NONE;
14762 else {
14763 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14764 confp->pri.nsf = PRI_NSF_NONE;
14765 }
14766 } else if (!strcasecmp(v->name, "priindication")) {
14767 if (!strcasecmp(v->value, "outofband"))
14768 confp->chan.priindication_oob = 1;
14769 else if (!strcasecmp(v->value, "inband"))
14770 confp->chan.priindication_oob = 0;
14771 else
14772 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14773 v->value, v->lineno);
14774 } else if (!strcasecmp(v->name, "priexclusive")) {
14775 confp->chan.priexclusive = ast_true(v->value);
14776 } else if (!strcasecmp(v->name, "internationalprefix")) {
14777 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14778 } else if (!strcasecmp(v->name, "nationalprefix")) {
14779 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14780 } else if (!strcasecmp(v->name, "localprefix")) {
14781 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14782 } else if (!strcasecmp(v->name, "privateprefix")) {
14783 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14784 } else if (!strcasecmp(v->name, "unknownprefix")) {
14785 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14786 } else if (!strcasecmp(v->name, "resetinterval")) {
14787 if (!strcasecmp(v->value, "never"))
14788 confp->pri.resetinterval = -1;
14789 else if (atoi(v->value) >= 60)
14790 confp->pri.resetinterval = atoi(v->value);
14791 else
14792 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14793 v->value, v->lineno);
14794 } else if (!strcasecmp(v->name, "minunused")) {
14795 confp->pri.minunused = atoi(v->value);
14796 } else if (!strcasecmp(v->name, "minidle")) {
14797 confp->pri.minidle = atoi(v->value);
14798 } else if (!strcasecmp(v->name, "idleext")) {
14799 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14800 } else if (!strcasecmp(v->name, "idledial")) {
14801 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14802 } else if (!strcasecmp(v->name, "overlapdial")) {
14803 if (ast_true(v->value)) {
14804 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14805 } else if (!strcasecmp(v->value, "incoming")) {
14806 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14807 } else if (!strcasecmp(v->value, "outgoing")) {
14808 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14809 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14810 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14811 } else {
14812 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14813 }
14814 #ifdef HAVE_PRI_INBANDDISCONNECT
14815 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14816 confp->pri.inbanddisconnect = ast_true(v->value);
14817 #endif
14818 } else if (!strcasecmp(v->name, "pritimer")) {
14819 #ifdef PRI_GETSET_TIMERS
14820 char tmp[20], *timerc, *c = tmp;
14821 int timer, timeridx;
14822 ast_copy_string(tmp, v->value, sizeof(tmp));
14823 timerc = strsep(&c, ",");
14824 if (timerc) {
14825 timer = atoi(c);
14826 if (!timer)
14827 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc, v->lineno);
14828 else {
14829 if ((timeridx = pri_timer2idx(timerc)) >= 0)
14830 pritimers[timeridx] = timer;
14831 else
14832 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer at line %d.\n", timerc, v->lineno);
14833 }
14834 } else
14835 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v->value, v->lineno);
14836
14837 } else if (!strcasecmp(v->name, "facilityenable")) {
14838 confp->pri.facilityenable = ast_true(v->value);
14839 #endif
14840 #endif
14841 #ifdef HAVE_SS7
14842 } else if (!strcasecmp(v->name, "ss7type")) {
14843 if (!strcasecmp(v->value, "itu")) {
14844 cur_ss7type = SS7_ITU;
14845 } else if (!strcasecmp(v->value, "ansi")) {
14846 cur_ss7type = SS7_ANSI;
14847 } else
14848 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14849 } else if (!strcasecmp(v->name, "linkset")) {
14850 cur_linkset = atoi(v->value);
14851 } else if (!strcasecmp(v->name, "pointcode")) {
14852 cur_pointcode = parse_pointcode(v->value);
14853 } else if (!strcasecmp(v->name, "adjpointcode")) {
14854 cur_adjpointcode = parse_pointcode(v->value);
14855 } else if (!strcasecmp(v->name, "defaultdpc")) {
14856 cur_defaultdpc = parse_pointcode(v->value);
14857 } else if (!strcasecmp(v->name, "cicbeginswith")) {
14858 cur_cicbeginswith = atoi(v->value);
14859 } else if (!strcasecmp(v->name, "networkindicator")) {
14860 if (!strcasecmp(v->value, "national"))
14861 cur_networkindicator = SS7_NI_NAT;
14862 else if (!strcasecmp(v->value, "national_spare"))
14863 cur_networkindicator = SS7_NI_NAT_SPARE;
14864 else if (!strcasecmp(v->value, "international"))
14865 cur_networkindicator = SS7_NI_INT;
14866 else if (!strcasecmp(v->value, "international_spare"))
14867 cur_networkindicator = SS7_NI_INT_SPARE;
14868 else
14869 cur_networkindicator = -1;
14870 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14871 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14872 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14873 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14874 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14875 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14876 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14877 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14878 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14879 if (!strcasecmp(v->value, "national")) {
14880 confp->ss7.called_nai = SS7_NAI_NATIONAL;
14881 } else if (!strcasecmp(v->value, "international")) {
14882 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14883 } else if (!strcasecmp(v->value, "subscriber")) {
14884 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14885 } else if (!strcasecmp(v->value, "dynamic")) {
14886 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14887 } else {
14888 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14889 }
14890 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14891 if (!strcasecmp(v->value, "national")) {
14892 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14893 } else if (!strcasecmp(v->value, "international")) {
14894 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14895 } else if (!strcasecmp(v->value, "subscriber")) {
14896 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14897 } else if (!strcasecmp(v->value, "dynamic")) {
14898 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14899 } else {
14900 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14901 }
14902 } else if (!strcasecmp(v->name, "sigchan")) {
14903 int sigchan, res;
14904 sigchan = atoi(v->value);
14905 res = linkset_addsigchan(sigchan);
14906 if (res < 0)
14907 return -1;
14908
14909 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14910 struct dahdi_ss7 *link;
14911 link = ss7_resolve_linkset(cur_linkset);
14912 if (!link) {
14913 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
14914 return -1;
14915 }
14916 if (ast_true(v->value))
14917 link->flags |= LINKSET_FLAG_EXPLICITACM;
14918
14919 #endif
14920 } else if (!strcasecmp(v->name, "cadence")) {
14921
14922 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14923 int i;
14924 struct dahdi_ring_cadence new_cadence;
14925 int cid_location = -1;
14926 int firstcadencepos = 0;
14927 char original_args[80];
14928 int cadence_is_ok = 1;
14929
14930 ast_copy_string(original_args, v->value, sizeof(original_args));
14931
14932 element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &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]);
14933
14934
14935 if (element_count % 2 == 1) {
14936 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
14937 cadence_is_ok = 0;
14938 }
14939
14940
14941 for (i = 0; i < element_count; i++) {
14942 if (c[i] == 0) {
14943 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
14944 cadence_is_ok = 0;
14945 break;
14946 } else if (c[i] < 0) {
14947 if (i % 2 == 1) {
14948
14949 if (cid_location == -1) {
14950 cid_location = i;
14951 c[i] *= -1;
14952 } else {
14953 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
14954 cadence_is_ok = 0;
14955 break;
14956 }
14957 } else {
14958 if (firstcadencepos == 0) {
14959 firstcadencepos = i;
14960
14961 } else {
14962 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
14963 cadence_is_ok = 0;
14964 break;
14965 }
14966 }
14967 }
14968 }
14969
14970
14971 for (i = 0; i < 16; i++) {
14972 new_cadence.ringcadence[i] = c[i];
14973 }
14974
14975 if (cadence_is_ok) {
14976
14977 if (element_count < 2) {
14978 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
14979 } else {
14980 if (cid_location == -1) {
14981
14982 cid_location = 1;
14983 } else {
14984
14985 cid_location = (cid_location + 1) / 2;
14986 }
14987
14988 if (!user_has_defined_cadences++)
14989
14990 num_cadence = 0;
14991 if ((num_cadence+1) >= NUM_CADENCE_MAX)
14992 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
14993 else {
14994 cadences[num_cadence] = new_cadence;
14995 cidrings[num_cadence++] = cid_location;
14996 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
14997 }
14998 }
14999 }
15000 } else if (!strcasecmp(v->name, "ringtimeout")) {
15001 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
15002 } else if (!strcasecmp(v->name, "prewink")) {
15003 confp->timing.prewinktime = atoi(v->value);
15004 } else if (!strcasecmp(v->name, "preflash")) {
15005 confp->timing.preflashtime = atoi(v->value);
15006 } else if (!strcasecmp(v->name, "wink")) {
15007 confp->timing.winktime = atoi(v->value);
15008 } else if (!strcasecmp(v->name, "flash")) {
15009 confp->timing.flashtime = atoi(v->value);
15010 } else if (!strcasecmp(v->name, "start")) {
15011 confp->timing.starttime = atoi(v->value);
15012 } else if (!strcasecmp(v->name, "rxwink")) {
15013 confp->timing.rxwinktime = atoi(v->value);
15014 } else if (!strcasecmp(v->name, "rxflash")) {
15015 confp->timing.rxflashtime = atoi(v->value);
15016 } else if (!strcasecmp(v->name, "debounce")) {
15017 confp->timing.debouncetime = atoi(v->value);
15018 } else if (!strcasecmp(v->name, "toneduration")) {
15019 int toneduration;
15020 int ctlfd;
15021 int res;
15022 struct dahdi_dialparams dps;
15023
15024 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
15025 if (ctlfd == -1) {
15026 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
15027 return -1;
15028 }
15029
15030 toneduration = atoi(v->value);
15031 if (toneduration > -1) {
15032 memset(&dps, 0, sizeof(dps));
15033
15034 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
15035 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
15036 if (res < 0) {
15037 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
15038 return -1;
15039 }
15040 }
15041 close(ctlfd);
15042 } else if (!strcasecmp(v->name, "defaultcic")) {
15043 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
15044 } else if (!strcasecmp(v->name, "defaultozz")) {
15045 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
15046 } else if (!strcasecmp(v->name, "mwilevel")) {
15047 mwilevel = atoi(v->value);
15048 }
15049 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
15050 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
15051 }
15052 if (dahdichan[0]) {
15053
15054
15055 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
15056 return -1;
15057 }
15058 }
15059
15060
15061 if (!found_pseudo && reload == 0) {
15062
15063
15064
15065
15066 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
15067
15068 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
15069
15070 if (tmp) {
15071 ast_verb(3, "Automatically generated pseudo channel\n");
15072 } else {
15073 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
15074 }
15075 }
15076 return 0;
15077 }
15078
15079 static int setup_dahdi(int reload)
15080 {
15081 struct ast_config *cfg, *ucfg;
15082 struct ast_variable *v;
15083 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
15084 struct dahdi_chan_conf conf;
15085 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
15086 const char *cat;
15087 int res;
15088
15089 #ifdef HAVE_PRI
15090 char *c;
15091 int spanno;
15092 int i;
15093 int logicalspan;
15094 int trunkgroup;
15095 int dchannels[NUM_DCHANS];
15096 #endif
15097
15098 cfg = ast_config_load(config, config_flags);
15099
15100
15101 if (!cfg) {
15102 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
15103 return 0;
15104 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
15105 ucfg = ast_config_load("users.conf", config_flags);
15106 if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
15107 return 0;
15108 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15109 cfg = ast_config_load(config, config_flags);
15110 } else {
15111 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15112 ucfg = ast_config_load("users.conf", config_flags);
15113 }
15114
15115
15116 ast_mutex_lock(&iflock);
15117 #ifdef HAVE_PRI
15118 if (reload != 1) {
15119
15120 v = ast_variable_browse(cfg, "trunkgroups");
15121 while (v) {
15122 if (!strcasecmp(v->name, "trunkgroup")) {
15123 trunkgroup = atoi(v->value);
15124 if (trunkgroup > 0) {
15125 if ((c = strchr(v->value, ','))) {
15126 i = 0;
15127 memset(dchannels, 0, sizeof(dchannels));
15128 while (c && (i < NUM_DCHANS)) {
15129 dchannels[i] = atoi(c + 1);
15130 if (dchannels[i] < 0) {
15131 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);
15132 } else
15133 i++;
15134 c = strchr(c + 1, ',');
15135 }
15136 if (i) {
15137 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
15138 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);
15139 } else
15140 ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
15141 } else
15142 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15143 } else
15144 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15145 } else
15146 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
15147 } else if (!strcasecmp(v->name, "spanmap")) {
15148 spanno = atoi(v->value);
15149 if (spanno > 0) {
15150 if ((c = strchr(v->value, ','))) {
15151 trunkgroup = atoi(c + 1);
15152 if (trunkgroup > 0) {
15153 if ((c = strchr(c + 1, ',')))
15154 logicalspan = atoi(c + 1);
15155 else
15156 logicalspan = 0;
15157 if (logicalspan >= 0) {
15158 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15159 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15160 } else
15161 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15162 } else
15163 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);
15164 } else
15165 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15166 } else
15167 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15168 } else
15169 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15170 } else {
15171 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15172 }
15173 v = v->next;
15174 }
15175 }
15176 #endif
15177
15178
15179 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
15180
15181 mwimonitornotify[0] = '\0';
15182
15183 v = ast_variable_browse(cfg, "channels");
15184 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
15185 ast_mutex_unlock(&iflock);
15186 ast_config_destroy(cfg);
15187 if (ucfg) {
15188 ast_config_destroy(ucfg);
15189 }
15190 return res;
15191 }
15192
15193
15194 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15195
15196
15197
15198 if (!strcasecmp(cat, "general") ||
15199 !strcasecmp(cat, "trunkgroups") ||
15200 !strcasecmp(cat, "globals") ||
15201 !strcasecmp(cat, "channels")) {
15202 continue;
15203 }
15204
15205 memcpy(&conf, &base_conf, sizeof(conf));
15206
15207 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
15208 ast_mutex_unlock(&iflock);
15209 ast_config_destroy(cfg);
15210 if (ucfg) {
15211 ast_config_destroy(cfg);
15212 }
15213 return res;
15214 }
15215 }
15216
15217 ast_config_destroy(cfg);
15218
15219 if (ucfg) {
15220 const char *chans;
15221
15222 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
15223
15224 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15225 if (!strcasecmp(cat, "general")) {
15226 continue;
15227 }
15228
15229 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
15230
15231 if (ast_strlen_zero(chans)) {
15232 continue;
15233 }
15234
15235 memcpy(&conf, &base_conf, sizeof(conf));
15236
15237 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
15238 ast_config_destroy(ucfg);
15239 ast_mutex_unlock(&iflock);
15240 return res;
15241 }
15242 }
15243 ast_config_destroy(ucfg);
15244 }
15245 ast_mutex_unlock(&iflock);
15246
15247 #ifdef HAVE_PRI
15248 if (reload != 1) {
15249 int x;
15250 for (x = 0; x < NUM_SPANS; x++) {
15251 if (pris[x].pvts[0]) {
15252 if (start_pri(pris + x)) {
15253 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15254 return -1;
15255 } else
15256 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
15257 }
15258 }
15259 }
15260 #endif
15261 #ifdef HAVE_SS7
15262 if (reload != 1) {
15263 int x;
15264 for (x = 0; x < NUM_SPANS; x++) {
15265 if (linksets[x].ss7) {
15266 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
15267 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
15268 return -1;
15269 } else
15270 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
15271 }
15272 }
15273 }
15274 #endif
15275
15276 restart_monitor();
15277 return 0;
15278 }
15279
15280 static int load_module(void)
15281 {
15282 int res;
15283 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15284 int y, i;
15285 #endif
15286
15287 #ifdef HAVE_PRI
15288 memset(pris, 0, sizeof(pris));
15289 for (y = 0; y < NUM_SPANS; y++) {
15290 ast_mutex_init(&pris[y].lock);
15291 pris[y].offset = -1;
15292 pris[y].master = AST_PTHREADT_NULL;
15293 for (i = 0; i < NUM_DCHANS; i++)
15294 pris[y].fds[i] = -1;
15295 }
15296 pri_set_error(dahdi_pri_error);
15297 pri_set_message(dahdi_pri_message);
15298 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15299 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15300 #endif
15301 #ifdef HAVE_SS7
15302 memset(linksets, 0, sizeof(linksets));
15303 for (y = 0; y < NUM_SPANS; y++) {
15304 ast_mutex_init(&linksets[y].lock);
15305 linksets[y].master = AST_PTHREADT_NULL;
15306 for (i = 0; i < NUM_DCHANS; i++)
15307 linksets[y].fds[i] = -1;
15308 }
15309 ss7_set_error(dahdi_ss7_error);
15310 ss7_set_message(dahdi_ss7_message);
15311 #endif
15312 res = setup_dahdi(0);
15313
15314 if (res)
15315 return AST_MODULE_LOAD_DECLINE;
15316 if (ast_channel_register(&dahdi_tech)) {
15317 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15318 __unload_module();
15319 return AST_MODULE_LOAD_FAILURE;
15320 }
15321 #ifdef HAVE_PRI
15322 ast_string_field_init(&inuse, 16);
15323 ast_string_field_set(&inuse, name, "GR-303InUse");
15324 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15325 #endif
15326 #ifdef HAVE_SS7
15327 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15328 #endif
15329
15330 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15331
15332 memset(round_robin, 0, sizeof(round_robin));
15333 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15334 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15335 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15336 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15337 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15338 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15339 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15340
15341 ast_cond_init(&mwi_thread_complete, NULL);
15342 ast_cond_init(&ss_thread_complete, NULL);
15343
15344 return res;
15345 }
15346
15347 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15348 {
15349 #define END_SILENCE_LEN 400
15350 #define HEADER_MS 50
15351 #define TRAILER_MS 5
15352 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15353 #define ASCII_BYTES_PER_CHAR 80
15354
15355 unsigned char *buf,*mybuf;
15356 struct dahdi_pvt *p = c->tech_pvt;
15357 struct pollfd fds[1];
15358 int size,res,fd,len,x;
15359 int bytes=0;
15360
15361 float cr = 1.0;
15362 float ci = 0.0;
15363 float scont = 0.0;
15364 int idx;
15365
15366 idx = dahdi_get_index(c, p, 0);
15367 if (idx < 0) {
15368 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
15369 return -1;
15370 }
15371 if (!text[0]) return(0);
15372 if ((!p->tdd) && (!p->mate)) return(0);
15373 if (p->mate)
15374 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15375 else
15376 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15377 if (!buf)
15378 return -1;
15379 mybuf = buf;
15380 if (p->mate) {
15381 int codec = AST_LAW(p);
15382 for (x = 0; x < HEADER_MS; x++) {
15383 PUT_CLID_MARKMS;
15384 }
15385
15386 for (x = 0; text[x]; x++) {
15387 PUT_CLID(text[x]);
15388 }
15389 for (x = 0; x < TRAILER_MS; x++) {
15390 PUT_CLID_MARKMS;
15391 }
15392 len = bytes;
15393 buf = mybuf;
15394 } else {
15395 len = tdd_generate(p->tdd, buf, text);
15396 if (len < 1) {
15397 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15398 ast_free(mybuf);
15399 return -1;
15400 }
15401 }
15402 memset(buf + len, 0x7f, END_SILENCE_LEN);
15403 len += END_SILENCE_LEN;
15404 fd = p->subs[idx].dfd;
15405 while (len) {
15406 if (ast_check_hangup(c)) {
15407 ast_free(mybuf);
15408 return -1;
15409 }
15410 size = len;
15411 if (size > READ_SIZE)
15412 size = READ_SIZE;
15413 fds[0].fd = fd;
15414 fds[0].events = POLLOUT | POLLPRI;
15415 fds[0].revents = 0;
15416 res = poll(fds, 1, -1);
15417 if (!res) {
15418 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15419 continue;
15420 }
15421
15422 if (fds[0].revents & POLLPRI) {
15423 ast_free(mybuf);
15424 return -1;
15425 }
15426 if (!(fds[0].revents & POLLOUT)) {
15427 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15428 continue;
15429 }
15430 res = write(fd, buf, size);
15431 if (res != size) {
15432 if (res == -1) {
15433 ast_free(mybuf);
15434 return -1;
15435 }
15436 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15437 break;
15438 }
15439 len -= size;
15440 buf += size;
15441 }
15442 ast_free(mybuf);
15443 return(0);
15444 }
15445
15446
15447 static int reload(void)
15448 {
15449 int res = 0;
15450
15451 res = setup_dahdi(1);
15452 if (res) {
15453 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15454 return -1;
15455 }
15456 return 0;
15457 }
15458
15459
15460
15461
15462
15463 #ifdef HAVE_PRI
15464 #ifdef HAVE_SS7
15465 #define tdesc "DAHDI Telephony w/PRI & SS7"
15466 #else
15467 #define tdesc "DAHDI Telephony w/PRI"
15468 #endif
15469 #else
15470 #ifdef HAVE_SS7
15471 #define tdesc "DAHDI Telephony w/SS7"
15472 #else
15473 #define tdesc "DAHDI Telephony"
15474 #endif
15475 #endif
15476
15477 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15478 .load = load_module,
15479 .unload = unload_module,
15480 .reload = reload,
15481 );
15482
15483