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: 211569 $")
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 busy_tonelength;
00955
00956
00957
00958
00959 int busy_quietlength;
00960
00961
00962
00963
00964 int callprogress;
00965 struct timeval flashtime;
00966
00967 struct ast_dsp *dsp;
00968
00969
00970 struct dahdi_dialoperation dop;
00971 int whichwink;
00972
00973 char finaldial[64];
00974 char accountcode[AST_MAX_ACCOUNT_CODE];
00975 int amaflags;
00976 struct tdd_state *tdd;
00977
00978 char call_forward[AST_MAX_EXTENSION];
00979
00980
00981
00982
00983 char mailbox[AST_MAX_EXTENSION];
00984
00985 struct ast_event_sub *mwi_event_sub;
00986
00987 char dialdest[256];
00988
00989 int onhooktime;
00990
00991 int msgstate;
00992 int distinctivering;
00993 int cidrings;
00994 int dtmfrelax;
00995
00996 int fake_event;
00997
00998
00999
01000
01001 int polarityonanswerdelay;
01002
01003 struct timeval polaritydelaytv;
01004
01005
01006
01007
01008 int sendcalleridafter;
01009 #ifdef HAVE_PRI
01010
01011 struct dahdi_pri *pri;
01012
01013 struct dahdi_pvt *bearer;
01014
01015 struct dahdi_pvt *realcall;
01016
01017 q931_call *call;
01018
01019 int prioffset;
01020
01021 int logicalspan;
01022 #endif
01023
01024 int polarity;
01025
01026 int dsp_features;
01027 #ifdef HAVE_SS7
01028
01029 struct dahdi_ss7 *ss7;
01030
01031 struct isup_call *ss7call;
01032 char charge_number[50];
01033 char gen_add_number[50];
01034 char gen_dig_number[50];
01035 char orig_called_num[50];
01036 char redirecting_num[50];
01037 char generic_name[50];
01038 unsigned char gen_add_num_plan;
01039 unsigned char gen_add_nai;
01040 unsigned char gen_add_pres_ind;
01041 unsigned char gen_add_type;
01042 unsigned char gen_dig_type;
01043 unsigned char gen_dig_scheme;
01044 char jip_number[50];
01045 unsigned char lspi_type;
01046 unsigned char lspi_scheme;
01047 unsigned char lspi_context;
01048 char lspi_ident[50];
01049 unsigned int call_ref_ident;
01050 unsigned int call_ref_pc;
01051 unsigned char calling_party_cat;
01052 int transcap;
01053 int cic;
01054 unsigned int dpc;
01055 unsigned int loopedback:1;
01056 #endif
01057
01058 char begindigit;
01059
01060 int muting;
01061 } *iflist = NULL, *ifend = NULL;
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 struct dahdi_chan_conf {
01074 struct dahdi_pvt chan;
01075 #ifdef HAVE_PRI
01076 struct dahdi_pri pri;
01077 #endif
01078
01079 #ifdef HAVE_SS7
01080 struct dahdi_ss7 ss7;
01081 #endif
01082 struct dahdi_params timing;
01083 int is_sig_auto;
01084
01085
01086
01087
01088
01089 char smdi_port[SMDI_MAX_FILENAME_LEN];
01090 };
01091
01092
01093 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01094
01095
01096
01097 struct dahdi_chan_conf conf = {
01098 #ifdef HAVE_PRI
01099 .pri = {
01100 .nsf = PRI_NSF_NONE,
01101 .switchtype = PRI_SWITCH_NI2,
01102 .dialplan = PRI_UNKNOWN + 1,
01103 .localdialplan = PRI_NATIONAL_ISDN + 1,
01104 .nodetype = PRI_CPE,
01105
01106 .minunused = 2,
01107 .idleext = "",
01108 .idledial = "",
01109 .internationalprefix = "",
01110 .nationalprefix = "",
01111 .localprefix = "",
01112 .privateprefix = "",
01113 .unknownprefix = "",
01114 .resetinterval = -1,
01115 },
01116 #endif
01117 #ifdef HAVE_SS7
01118 .ss7 = {
01119 .called_nai = SS7_NAI_NATIONAL,
01120 .calling_nai = SS7_NAI_NATIONAL,
01121 .internationalprefix = "",
01122 .nationalprefix = "",
01123 .subscriberprefix = "",
01124 .unknownprefix = ""
01125 },
01126 #endif
01127 .chan = {
01128 .context = "default",
01129 .cid_num = "",
01130 .cid_name = "",
01131 .mohinterpret = "default",
01132 .mohsuggest = "",
01133 .parkinglot = "",
01134 .transfertobusy = 1,
01135
01136 .cid_signalling = CID_SIG_BELL,
01137 .cid_start = CID_START_RING,
01138 .dahditrcallerid = 0,
01139 .use_callerid = 1,
01140 .sig = -1,
01141 .outsigmod = -1,
01142
01143 .cid_rxgain = +5.0,
01144
01145 .tonezone = -1,
01146
01147 .echocancel.head.tap_length = 1,
01148
01149 .busycount = 3,
01150
01151 .accountcode = "",
01152
01153 .mailbox = "",
01154
01155
01156 .polarityonanswerdelay = 600,
01157
01158 .sendcalleridafter = DEFAULT_CIDRINGS,
01159
01160 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01161 .buf_no = numbufs
01162 },
01163 .timing = {
01164 .prewinktime = -1,
01165 .preflashtime = -1,
01166 .winktime = -1,
01167 .flashtime = -1,
01168 .starttime = -1,
01169 .rxwinktime = -1,
01170 .rxflashtime = -1,
01171 .debouncetime = -1
01172 },
01173 .is_sig_auto = 1,
01174 .smdi_port = "/dev/ttyS0",
01175 };
01176
01177 return conf;
01178 }
01179
01180
01181 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01182 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01183 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01184 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01185 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01186 static int dahdi_hangup(struct ast_channel *ast);
01187 static int dahdi_answer(struct ast_channel *ast);
01188 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01189 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01190 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01191 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01192 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01193 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01194 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01195 static int handle_init_event(struct dahdi_pvt *i, int event);
01196
01197 static const struct ast_channel_tech dahdi_tech = {
01198 .type = "DAHDI",
01199 .description = tdesc,
01200 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01201 .requester = dahdi_request,
01202 .send_digit_begin = dahdi_digit_begin,
01203 .send_digit_end = dahdi_digit_end,
01204 .send_text = dahdi_sendtext,
01205 .call = dahdi_call,
01206 .hangup = dahdi_hangup,
01207 .answer = dahdi_answer,
01208 .read = dahdi_read,
01209 .write = dahdi_write,
01210 .bridge = dahdi_bridge,
01211 .exception = dahdi_exception,
01212 .indicate = dahdi_indicate,
01213 .fixup = dahdi_fixup,
01214 .setoption = dahdi_setoption,
01215 .func_channel_read = dahdi_func_read,
01216 };
01217
01218 #ifdef HAVE_PRI
01219 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01220 #else
01221 #define GET_CHANNEL(p) ((p)->channel)
01222 #endif
01223
01224 struct dahdi_pvt *round_robin[32];
01225
01226 #ifdef HAVE_PRI
01227 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01228 {
01229 int res;
01230
01231 do {
01232 res = ast_mutex_trylock(&pri->lock);
01233 if (res) {
01234 DEADLOCK_AVOIDANCE(&pvt->lock);
01235 }
01236 } while (res);
01237
01238 if (pri->master != AST_PTHREADT_NULL)
01239 pthread_kill(pri->master, SIGURG);
01240 return 0;
01241 }
01242 #endif
01243
01244 #ifdef HAVE_SS7
01245 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01246 {
01247 ast_mutex_unlock(&ss7->lock);
01248 }
01249
01250 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01251 {
01252 int res;
01253
01254 do {
01255 res = ast_mutex_trylock(&pri->lock);
01256 if (res) {
01257 DEADLOCK_AVOIDANCE(&pvt->lock);
01258 }
01259 } while (res);
01260
01261 if (pri->master != AST_PTHREADT_NULL)
01262 pthread_kill(pri->master, SIGURG);
01263 return 0;
01264 }
01265 #endif
01266 #define NUM_CADENCE_MAX 25
01267 static int num_cadence = 4;
01268 static int user_has_defined_cadences = 0;
01269
01270 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01271 { { 125, 125, 2000, 4000 } },
01272 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01273 { { 125, 125, 125, 125, 125, 4000 } },
01274 { { 1000, 500, 2500, 5000 } },
01275 };
01276
01277
01278
01279
01280
01281 static int cidrings[NUM_CADENCE_MAX] = {
01282 2,
01283 4,
01284 3,
01285 2,
01286 };
01287
01288
01289 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01290
01291 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01292 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01293
01294 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01295 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01296
01297 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01298 {
01299 int res;
01300 if (p->subs[SUB_REAL].owner == ast)
01301 res = 0;
01302 else if (p->subs[SUB_CALLWAIT].owner == ast)
01303 res = 1;
01304 else if (p->subs[SUB_THREEWAY].owner == ast)
01305 res = 2;
01306 else {
01307 res = -1;
01308 if (!nullok)
01309 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01310 }
01311 return res;
01312 }
01313
01314 #ifdef HAVE_PRI
01315 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01316 #else
01317 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01318 #endif
01319 {
01320 #ifdef HAVE_PRI
01321 if (pri)
01322 ast_mutex_unlock(&pri->lock);
01323 #endif
01324 for (;;) {
01325 if (p->subs[a].owner) {
01326 if (ast_channel_trylock(p->subs[a].owner)) {
01327 DEADLOCK_AVOIDANCE(&p->lock);
01328 } else {
01329 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01330 ast_channel_unlock(p->subs[a].owner);
01331 break;
01332 }
01333 } else
01334 break;
01335 }
01336 #ifdef HAVE_PRI
01337 if (pri)
01338 ast_mutex_lock(&pri->lock);
01339 #endif
01340 }
01341
01342 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01343 {
01344 #ifdef HAVE_PRI
01345 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01346 #endif
01347 #ifdef HAVE_SS7
01348 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01349 #endif
01350
01351 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01352 if (data) {
01353 switch (p->sig) {
01354 #ifdef HAVE_PRI
01355 case SIG_BRI:
01356 case SIG_BRI_PTMP:
01357 case SIG_PRI:
01358 ast_mutex_unlock(&pri->lock);
01359 break;
01360 #endif
01361 #ifdef HAVE_SS7
01362 case SIG_SS7:
01363 ast_mutex_unlock(&ss7->lock);
01364 break;
01365 #endif
01366 default:
01367 break;
01368 }
01369 }
01370 #endif
01371 for (;;) {
01372 if (p->owner) {
01373 if (ast_channel_trylock(p->owner)) {
01374 DEADLOCK_AVOIDANCE(&p->lock);
01375 } else {
01376 ast_queue_frame(p->owner, f);
01377 ast_channel_unlock(p->owner);
01378 break;
01379 }
01380 } else
01381 break;
01382 }
01383 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01384 if (data) {
01385 switch (p->sig) {
01386 #ifdef HAVE_PRI
01387 case SIG_BRI:
01388 case SIG_BRI_PTMP:
01389 case SIG_PRI:
01390 ast_mutex_lock(&pri->lock);
01391 break;
01392 #endif
01393 #ifdef HAVE_SS7
01394 case SIG_SS7:
01395 ast_mutex_lock(&ss7->lock);
01396 break;
01397 #endif
01398 default:
01399 break;
01400 }
01401 }
01402
01403 #endif
01404 }
01405
01406 static int restore_gains(struct dahdi_pvt *p);
01407
01408 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01409 {
01410 int tchan;
01411 int tinthreeway;
01412 struct ast_channel *towner;
01413
01414 ast_debug(1, "Swapping %d and %d\n", a, b);
01415
01416 tchan = p->subs[a].chan;
01417 towner = p->subs[a].owner;
01418 tinthreeway = p->subs[a].inthreeway;
01419
01420 p->subs[a].chan = p->subs[b].chan;
01421 p->subs[a].owner = p->subs[b].owner;
01422 p->subs[a].inthreeway = p->subs[b].inthreeway;
01423
01424 p->subs[b].chan = tchan;
01425 p->subs[b].owner = towner;
01426 p->subs[b].inthreeway = tinthreeway;
01427
01428 if (p->subs[a].owner)
01429 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01430 if (p->subs[b].owner)
01431 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01432 wakeup_sub(p, a, NULL);
01433 wakeup_sub(p, b, NULL);
01434 }
01435
01436 static int dahdi_open(char *fn)
01437 {
01438 int fd;
01439 int isnum;
01440 int chan = 0;
01441 int bs;
01442 int x;
01443 isnum = 1;
01444 for (x = 0; x < strlen(fn); x++) {
01445 if (!isdigit(fn[x])) {
01446 isnum = 0;
01447 break;
01448 }
01449 }
01450 if (isnum) {
01451 chan = atoi(fn);
01452 if (chan < 1) {
01453 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01454 return -1;
01455 }
01456 fn = "/dev/dahdi/channel";
01457 }
01458 fd = open(fn, O_RDWR | O_NONBLOCK);
01459 if (fd < 0) {
01460 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01461 return -1;
01462 }
01463 if (chan) {
01464 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01465 x = errno;
01466 close(fd);
01467 errno = x;
01468 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01469 return -1;
01470 }
01471 }
01472 bs = READ_SIZE;
01473 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01474 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01475 x = errno;
01476 close(fd);
01477 errno = x;
01478 return -1;
01479 }
01480 return fd;
01481 }
01482
01483 static void dahdi_close(int fd)
01484 {
01485 if (fd > 0)
01486 close(fd);
01487 }
01488
01489 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01490 {
01491 dahdi_close(chan_pvt->subs[sub_num].dfd);
01492 chan_pvt->subs[sub_num].dfd = -1;
01493 }
01494
01495 #ifdef HAVE_PRI
01496 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01497 {
01498 dahdi_close(pri->fds[fd_num]);
01499 pri->fds[fd_num] = -1;
01500 }
01501 #endif
01502
01503 #ifdef HAVE_SS7
01504 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
01505 {
01506 dahdi_close(ss7->fds[fd_num]);
01507 ss7->fds[fd_num] = -1;
01508 }
01509 #endif
01510
01511 static int dahdi_setlinear(int dfd, int linear)
01512 {
01513 int res;
01514 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01515 if (res)
01516 return res;
01517 return 0;
01518 }
01519
01520
01521 static int alloc_sub(struct dahdi_pvt *p, int x)
01522 {
01523 struct dahdi_bufferinfo bi;
01524 int res;
01525 if (p->subs[x].dfd >= 0) {
01526 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01527 return -1;
01528 }
01529
01530 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01531 if (p->subs[x].dfd <= -1) {
01532 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01533 return -1;
01534 }
01535
01536 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01537 if (!res) {
01538 bi.txbufpolicy = p->buf_policy;
01539 bi.rxbufpolicy = p->buf_policy;
01540 bi.numbufs = p->buf_no;
01541 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01542 if (res < 0) {
01543 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01544 }
01545 } else
01546 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01547
01548 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01549 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01550 dahdi_close_sub(p, x);
01551 p->subs[x].dfd = -1;
01552 return -1;
01553 }
01554 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01555 return 0;
01556 }
01557
01558 static int unalloc_sub(struct dahdi_pvt *p, int x)
01559 {
01560 if (!x) {
01561 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01562 return -1;
01563 }
01564 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01565 dahdi_close_sub(p, x);
01566 p->subs[x].linear = 0;
01567 p->subs[x].chan = 0;
01568 p->subs[x].owner = NULL;
01569 p->subs[x].inthreeway = 0;
01570 p->polarity = POLARITY_IDLE;
01571 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01572 return 0;
01573 }
01574
01575 static int digit_to_dtmfindex(char digit)
01576 {
01577 if (isdigit(digit))
01578 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01579 else if (digit >= 'A' && digit <= 'D')
01580 return DAHDI_TONE_DTMF_A + (digit - 'A');
01581 else if (digit >= 'a' && digit <= 'd')
01582 return DAHDI_TONE_DTMF_A + (digit - 'a');
01583 else if (digit == '*')
01584 return DAHDI_TONE_DTMF_s;
01585 else if (digit == '#')
01586 return DAHDI_TONE_DTMF_p;
01587 else
01588 return -1;
01589 }
01590
01591 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01592 {
01593 struct dahdi_pvt *pvt;
01594 int idx;
01595 int dtmf = -1;
01596
01597 pvt = chan->tech_pvt;
01598
01599 ast_mutex_lock(&pvt->lock);
01600
01601 idx = dahdi_get_index(chan, pvt, 0);
01602
01603 if ((idx != SUB_REAL) || !pvt->owner)
01604 goto out;
01605
01606 #ifdef HAVE_PRI
01607 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01608 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01609 if (pvt->setup_ack) {
01610 if (!pri_grab(pvt, pvt->pri)) {
01611 pri_information(pvt->pri->pri, pvt->call, digit);
01612 pri_rel(pvt->pri);
01613 } else
01614 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01615 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01616 int res;
01617 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01618 res = strlen(pvt->dialdest);
01619 pvt->dialdest[res++] = digit;
01620 pvt->dialdest[res] = '\0';
01621 }
01622 goto out;
01623 }
01624 #endif
01625 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01626 goto out;
01627
01628 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01629 int res;
01630 struct dahdi_dialoperation zo = {
01631 .op = DAHDI_DIAL_OP_APPEND,
01632 };
01633
01634 zo.dialstr[0] = 'T';
01635 zo.dialstr[1] = digit;
01636 zo.dialstr[2] = '\0';
01637 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01638 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01639 else
01640 pvt->dialing = 1;
01641 } else {
01642 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01643 pvt->dialing = 1;
01644 pvt->begindigit = digit;
01645 }
01646
01647 out:
01648 ast_mutex_unlock(&pvt->lock);
01649
01650 return 0;
01651 }
01652
01653 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01654 {
01655 struct dahdi_pvt *pvt;
01656 int res = 0;
01657 int idx;
01658 int x;
01659
01660 pvt = chan->tech_pvt;
01661
01662 ast_mutex_lock(&pvt->lock);
01663
01664 idx = dahdi_get_index(chan, pvt, 0);
01665
01666 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
01667 goto out;
01668
01669 #ifdef HAVE_PRI
01670
01671 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01672 && !pvt->begindigit)
01673 goto out;
01674 #endif
01675
01676 if (pvt->begindigit) {
01677 x = -1;
01678 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01679 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01680 pvt->dialing = 0;
01681 pvt->begindigit = 0;
01682 }
01683
01684 out:
01685 ast_mutex_unlock(&pvt->lock);
01686
01687 return res;
01688 }
01689
01690 static char *events[] = {
01691 "No event",
01692 "On hook",
01693 "Ring/Answered",
01694 "Wink/Flash",
01695 "Alarm",
01696 "No more alarm",
01697 "HDLC Abort",
01698 "HDLC Overrun",
01699 "HDLC Bad FCS",
01700 "Dial Complete",
01701 "Ringer On",
01702 "Ringer Off",
01703 "Hook Transition Complete",
01704 "Bits Changed",
01705 "Pulse Start",
01706 "Timer Expired",
01707 "Timer Ping",
01708 "Polarity Reversal",
01709 "Ring Begin",
01710 };
01711
01712 static struct {
01713 int alarm;
01714 char *name;
01715 } alarms[] = {
01716 { DAHDI_ALARM_RED, "Red Alarm" },
01717 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01718 { DAHDI_ALARM_BLUE, "Blue Alarm" },
01719 { DAHDI_ALARM_RECOVER, "Recovering" },
01720 { DAHDI_ALARM_LOOPBACK, "Loopback" },
01721 { DAHDI_ALARM_NOTOPEN, "Not Open" },
01722 { DAHDI_ALARM_NONE, "None" },
01723 };
01724
01725 static char *alarm2str(int alm)
01726 {
01727 int x;
01728 for (x = 0; x < ARRAY_LEN(alarms); x++) {
01729 if (alarms[x].alarm & alm)
01730 return alarms[x].name;
01731 }
01732 return alm ? "Unknown Alarm" : "No Alarm";
01733 }
01734
01735 static char *event2str(int event)
01736 {
01737 static char buf[256];
01738 if ((event < (ARRAY_LEN(events))) && (event > -1))
01739 return events[event];
01740 sprintf(buf, "Event %d", event);
01741 return buf;
01742 }
01743
01744 #ifdef HAVE_PRI
01745 static char *dialplan2str(int dialplan)
01746 {
01747 if (dialplan == -1 || dialplan == -2) {
01748 return("Dynamically set dialplan in ISDN");
01749 }
01750 return (pri_plan2str(dialplan));
01751 }
01752 #endif
01753
01754 static char *dahdi_sig2str(int sig)
01755 {
01756 static char buf[256];
01757 switch (sig) {
01758 case SIG_EM:
01759 return "E & M Immediate";
01760 case SIG_EMWINK:
01761 return "E & M Wink";
01762 case SIG_EM_E1:
01763 return "E & M E1";
01764 case SIG_FEATD:
01765 return "Feature Group D (DTMF)";
01766 case SIG_FEATDMF:
01767 return "Feature Group D (MF)";
01768 case SIG_FEATDMF_TA:
01769 return "Feature Groud D (MF) Tandem Access";
01770 case SIG_FEATB:
01771 return "Feature Group B (MF)";
01772 case SIG_E911:
01773 return "E911 (MF)";
01774 case SIG_FGC_CAMA:
01775 return "FGC/CAMA (Dialpulse)";
01776 case SIG_FGC_CAMAMF:
01777 return "FGC/CAMA (MF)";
01778 case SIG_FXSLS:
01779 return "FXS Loopstart";
01780 case SIG_FXSGS:
01781 return "FXS Groundstart";
01782 case SIG_FXSKS:
01783 return "FXS Kewlstart";
01784 case SIG_FXOLS:
01785 return "FXO Loopstart";
01786 case SIG_FXOGS:
01787 return "FXO Groundstart";
01788 case SIG_FXOKS:
01789 return "FXO Kewlstart";
01790 case SIG_PRI:
01791 return "ISDN PRI";
01792 case SIG_BRI:
01793 return "ISDN BRI Point to Point";
01794 case SIG_BRI_PTMP:
01795 return "ISDN BRI Point to MultiPoint";
01796 case SIG_SS7:
01797 return "SS7";
01798 case SIG_SF:
01799 return "SF (Tone) Immediate";
01800 case SIG_SFWINK:
01801 return "SF (Tone) Wink";
01802 case SIG_SF_FEATD:
01803 return "SF (Tone) with Feature Group D (DTMF)";
01804 case SIG_SF_FEATDMF:
01805 return "SF (Tone) with Feature Group D (MF)";
01806 case SIG_SF_FEATB:
01807 return "SF (Tone) with Feature Group B (MF)";
01808 case SIG_GR303FXOKS:
01809 return "GR-303 with FXOKS";
01810 case SIG_GR303FXSKS:
01811 return "GR-303 with FXSKS";
01812 case 0:
01813 return "Pseudo";
01814 default:
01815 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01816 return buf;
01817 }
01818 }
01819
01820 #define sig2str dahdi_sig2str
01821
01822 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
01823 {
01824
01825
01826 struct dahdi_confinfo zi;
01827
01828 memset(&zi, 0, sizeof(zi));
01829 zi.chan = 0;
01830
01831 if (slavechannel > 0) {
01832
01833 zi.confmode = DAHDI_CONF_DIGITALMON;
01834 zi.confno = slavechannel;
01835 } else {
01836 if (!idx) {
01837
01838 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01839 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01840 } else
01841 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01842 zi.confno = p->confno;
01843 }
01844 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01845 return 0;
01846 if (c->dfd < 0)
01847 return 0;
01848 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01849 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01850 return -1;
01851 }
01852 if (slavechannel < 1) {
01853 p->confno = zi.confno;
01854 }
01855 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01856 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01857 return 0;
01858 }
01859
01860 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01861 {
01862
01863 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01864 return 1;
01865
01866 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01867 return 1;
01868 return 0;
01869 }
01870
01871 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
01872 {
01873 struct dahdi_confinfo zi;
01874 if (
01875 (c->dfd < 0) ||
01876
01877 !isourconf(p, c)
01878
01879 ) return 0;
01880 memset(&zi, 0, sizeof(zi));
01881 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01882 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01883 return -1;
01884 }
01885 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01886 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01887 return 0;
01888 }
01889
01890 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01891 {
01892 int x;
01893 int useslavenative;
01894 struct dahdi_pvt *slave = NULL;
01895
01896 useslavenative = 1;
01897
01898 for (x = 0; x < 3; x++) {
01899
01900
01901 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01902 useslavenative = 0;
01903 }
01904
01905
01906 if (useslavenative) {
01907 for (x = 0; x < MAX_SLAVES; x++) {
01908 if (p->slaves[x]) {
01909 if (slave) {
01910
01911
01912 slave = NULL;
01913 useslavenative = 0;
01914 break;
01915 } else {
01916
01917 slave = p->slaves[x];
01918 }
01919 }
01920 }
01921 }
01922
01923 if (!slave)
01924 useslavenative = 0;
01925 else if (slave->law != p->law) {
01926 useslavenative = 0;
01927 slave = NULL;
01928 }
01929 if (out)
01930 *out = slave;
01931 return useslavenative;
01932 }
01933
01934 static int reset_conf(struct dahdi_pvt *p)
01935 {
01936 p->confno = -1;
01937 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01938 if (p->subs[SUB_REAL].dfd > -1) {
01939 struct dahdi_confinfo zi;
01940
01941 memset(&zi, 0, sizeof(zi));
01942 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01943 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01944 }
01945 return 0;
01946 }
01947
01948 static int update_conf(struct dahdi_pvt *p)
01949 {
01950 int needconf = 0;
01951 int x;
01952 int useslavenative;
01953 struct dahdi_pvt *slave = NULL;
01954
01955 useslavenative = isslavenative(p, &slave);
01956
01957 for (x = 0; x < 3; x++) {
01958
01959 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01960 conf_add(p, &p->subs[x], x, 0);
01961 needconf++;
01962 } else {
01963 conf_del(p, &p->subs[x], x);
01964 }
01965 }
01966
01967
01968 for (x = 0; x < MAX_SLAVES; x++) {
01969 if (p->slaves[x]) {
01970 if (useslavenative)
01971 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01972 else {
01973 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01974 needconf++;
01975 }
01976 }
01977 }
01978
01979 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01980 if (useslavenative)
01981 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01982 else {
01983 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01984 needconf++;
01985 }
01986 }
01987
01988 if (p->master) {
01989 if (isslavenative(p->master, NULL)) {
01990 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01991 } else {
01992 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01993 }
01994 }
01995 if (!needconf) {
01996
01997
01998 p->confno = -1;
01999 }
02000 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02001 return 0;
02002 }
02003
02004 static void dahdi_enable_ec(struct dahdi_pvt *p)
02005 {
02006 int x;
02007 int res;
02008 if (!p)
02009 return;
02010 if (p->echocanon) {
02011 ast_debug(1, "Echo cancellation already on\n");
02012 return;
02013 }
02014 if (p->digital) {
02015 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02016 return;
02017 }
02018 if (p->echocancel.head.tap_length) {
02019 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02020 x = 1;
02021 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02022 if (res)
02023 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02024 }
02025 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02026 if (res) {
02027 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02028 } else {
02029 p->echocanon = 1;
02030 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02031 }
02032 } else
02033 ast_debug(1, "No echo cancellation requested\n");
02034 }
02035
02036 static void dahdi_train_ec(struct dahdi_pvt *p)
02037 {
02038 int x;
02039 int res;
02040
02041 if (p && p->echocanon && p->echotraining) {
02042 x = p->echotraining;
02043 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02044 if (res)
02045 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02046 else
02047 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02048 } else {
02049 ast_debug(1, "No echo training requested\n");
02050 }
02051 }
02052
02053 static void dahdi_disable_ec(struct dahdi_pvt *p)
02054 {
02055 int res;
02056
02057 if (p->echocanon) {
02058 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02059
02060 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02061
02062 if (res)
02063 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02064 else
02065 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02066 }
02067
02068 p->echocanon = 0;
02069 }
02070
02071 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02072 {
02073 int j;
02074 int k;
02075 float linear_gain = pow(10.0, gain / 20.0);
02076
02077 switch (law) {
02078 case DAHDI_LAW_ALAW:
02079 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02080 if (gain) {
02081 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02082 if (k > 32767) k = 32767;
02083 if (k < -32767) k = -32767;
02084 g->txgain[j] = AST_LIN2A(k);
02085 } else {
02086 g->txgain[j] = j;
02087 }
02088 }
02089 break;
02090 case DAHDI_LAW_MULAW:
02091 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02092 if (gain) {
02093 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02094 if (k > 32767) k = 32767;
02095 if (k < -32767) k = -32767;
02096 g->txgain[j] = AST_LIN2MU(k);
02097 } else {
02098 g->txgain[j] = j;
02099 }
02100 }
02101 break;
02102 }
02103 }
02104
02105 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02106 {
02107 int j;
02108 int k;
02109 float linear_gain = pow(10.0, gain / 20.0);
02110
02111 switch (law) {
02112 case DAHDI_LAW_ALAW:
02113 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02114 if (gain) {
02115 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02116 if (k > 32767) k = 32767;
02117 if (k < -32767) k = -32767;
02118 g->rxgain[j] = AST_LIN2A(k);
02119 } else {
02120 g->rxgain[j] = j;
02121 }
02122 }
02123 break;
02124 case DAHDI_LAW_MULAW:
02125 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02126 if (gain) {
02127 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02128 if (k > 32767) k = 32767;
02129 if (k < -32767) k = -32767;
02130 g->rxgain[j] = AST_LIN2MU(k);
02131 } else {
02132 g->rxgain[j] = j;
02133 }
02134 }
02135 break;
02136 }
02137 }
02138
02139 static int set_actual_txgain(int fd, int chan, float gain, int law)
02140 {
02141 struct dahdi_gains g;
02142 int res;
02143
02144 memset(&g, 0, sizeof(g));
02145 g.chan = chan;
02146 res = ioctl(fd, DAHDI_GETGAINS, &g);
02147 if (res) {
02148 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02149 return res;
02150 }
02151
02152 fill_txgain(&g, gain, law);
02153
02154 return ioctl(fd, DAHDI_SETGAINS, &g);
02155 }
02156
02157 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02158 {
02159 struct dahdi_gains g;
02160 int res;
02161
02162 memset(&g, 0, sizeof(g));
02163 g.chan = chan;
02164 res = ioctl(fd, DAHDI_GETGAINS, &g);
02165 if (res) {
02166 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02167 return res;
02168 }
02169
02170 fill_rxgain(&g, gain, law);
02171
02172 return ioctl(fd, DAHDI_SETGAINS, &g);
02173 }
02174
02175 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02176 {
02177 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02178 }
02179
02180 static int bump_gains(struct dahdi_pvt *p)
02181 {
02182 int res;
02183
02184
02185 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02186 if (res) {
02187 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02188 return -1;
02189 }
02190
02191 return 0;
02192 }
02193
02194 static int restore_gains(struct dahdi_pvt *p)
02195 {
02196 int res;
02197
02198 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02199 if (res) {
02200 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02201 return -1;
02202 }
02203
02204 return 0;
02205 }
02206
02207 static inline int dahdi_set_hook(int fd, int hs)
02208 {
02209 int x, res;
02210
02211 x = hs;
02212 res = ioctl(fd, DAHDI_HOOK, &x);
02213
02214 if (res < 0) {
02215 if (errno == EINPROGRESS)
02216 return 0;
02217 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02218
02219 }
02220
02221 return res;
02222 }
02223
02224 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02225 {
02226 int x, y, res;
02227 x = muted;
02228 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02229 y = 1;
02230 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02231 if (res)
02232 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02233 }
02234 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02235 if (res < 0)
02236 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02237 return res;
02238 }
02239
02240 static int save_conference(struct dahdi_pvt *p)
02241 {
02242 struct dahdi_confinfo c;
02243 int res;
02244 if (p->saveconf.confmode) {
02245 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02246 return -1;
02247 }
02248 p->saveconf.chan = 0;
02249 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02250 if (res) {
02251 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02252 p->saveconf.confmode = 0;
02253 return -1;
02254 }
02255 memset(&c, 0, sizeof(c));
02256 c.confmode = DAHDI_CONF_NORMAL;
02257 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02258 if (res) {
02259 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02260 return -1;
02261 }
02262 ast_debug(1, "Disabled conferencing\n");
02263 return 0;
02264 }
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284 static void notify_message(char *mailbox_full, int thereornot)
02285 {
02286 char s[sizeof(mwimonitornotify) + 80];
02287 struct ast_event *event;
02288 char *mailbox, *context;
02289
02290
02291 context = mailbox = ast_strdupa(mailbox_full);
02292 strsep(&context, "@");
02293 if (ast_strlen_zero(context))
02294 context = "default";
02295
02296 if (!(event = ast_event_new(AST_EVENT_MWI,
02297 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02298 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02299 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02300 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02301 AST_EVENT_IE_END))) {
02302 return;
02303 }
02304
02305 ast_event_queue_and_cache(event);
02306
02307 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02308 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02309 ast_safe_system(s);
02310 }
02311 }
02312
02313 static int restore_conference(struct dahdi_pvt *p)
02314 {
02315 int res;
02316 if (p->saveconf.confmode) {
02317 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02318 p->saveconf.confmode = 0;
02319 if (res) {
02320 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02321 return -1;
02322 }
02323 }
02324 ast_debug(1, "Restored conferencing\n");
02325 return 0;
02326 }
02327
02328 static int send_callerid(struct dahdi_pvt *p);
02329
02330 static int send_cwcidspill(struct dahdi_pvt *p)
02331 {
02332 p->callwaitcas = 0;
02333 p->cidcwexpire = 0;
02334 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02335 return -1;
02336 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02337
02338 p->cidlen += READ_SIZE * 4;
02339 p->cidpos = 0;
02340 send_callerid(p);
02341 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02342 return 0;
02343 }
02344
02345 static int has_voicemail(struct dahdi_pvt *p)
02346 {
02347 int new_msgs;
02348 struct ast_event *event;
02349 char *mailbox, *context;
02350
02351 mailbox = context = ast_strdupa(p->mailbox);
02352 strsep(&context, "@");
02353 if (ast_strlen_zero(context))
02354 context = "default";
02355
02356 event = ast_event_get_cached(AST_EVENT_MWI,
02357 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02358 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02359 AST_EVENT_IE_END);
02360
02361 if (event) {
02362 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02363 ast_event_destroy(event);
02364 } else
02365 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02366
02367 return new_msgs;
02368 }
02369
02370 static int send_callerid(struct dahdi_pvt *p)
02371 {
02372
02373 int res;
02374
02375 if (p->subs[SUB_REAL].linear) {
02376 p->subs[SUB_REAL].linear = 0;
02377 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02378 }
02379 while (p->cidpos < p->cidlen) {
02380 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02381 if (res < 0) {
02382 if (errno == EAGAIN)
02383 return 0;
02384 else {
02385 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02386 return -1;
02387 }
02388 }
02389 if (!res)
02390 return 0;
02391 p->cidpos += res;
02392 }
02393 ast_free(p->cidspill);
02394 p->cidspill = NULL;
02395 if (p->callwaitcas) {
02396
02397 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02398 } else
02399 restore_conference(p);
02400 return 0;
02401 }
02402
02403 static int dahdi_callwait(struct ast_channel *ast)
02404 {
02405 struct dahdi_pvt *p = ast->tech_pvt;
02406 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02407 if (p->cidspill) {
02408 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02409 ast_free(p->cidspill);
02410 }
02411 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02412 return -1;
02413 save_conference(p);
02414
02415 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02416 if (!p->callwaitrings && p->callwaitingcallerid) {
02417 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02418 p->callwaitcas = 1;
02419 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02420 } else {
02421 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02422 p->callwaitcas = 0;
02423 p->cidlen = 2400 + READ_SIZE * 4;
02424 }
02425 p->cidpos = 0;
02426 send_callerid(p);
02427
02428 return 0;
02429 }
02430
02431 #ifdef HAVE_SS7
02432 static unsigned char cid_pres2ss7pres(int cid_pres)
02433 {
02434 return (cid_pres >> 5) & 0x03;
02435 }
02436
02437 static unsigned char cid_pres2ss7screen(int cid_pres)
02438 {
02439 return cid_pres & 0x03;
02440 }
02441 #endif
02442
02443 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02444 {
02445 struct dahdi_pvt *p = ast->tech_pvt;
02446 int x, res, idx,mysig;
02447 char *c, *n, *l;
02448 #ifdef HAVE_PRI
02449 char *s = NULL;
02450 #endif
02451 char dest[256];
02452 ast_mutex_lock(&p->lock);
02453 ast_copy_string(dest, rdest, sizeof(dest));
02454 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02455 if ((ast->_state == AST_STATE_BUSY)) {
02456 p->subs[SUB_REAL].needbusy = 1;
02457 ast_mutex_unlock(&p->lock);
02458 return 0;
02459 }
02460 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02461 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02462 ast_mutex_unlock(&p->lock);
02463 return -1;
02464 }
02465 p->dialednone = 0;
02466 if ((p->radio || (p->oprmode < 0)))
02467 {
02468
02469 ast_setstate(ast, AST_STATE_UP);
02470 ast_mutex_unlock(&p->lock);
02471 return 0;
02472 }
02473 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02475 if (res)
02476 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02477 p->outgoing = 1;
02478
02479 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02480
02481 mysig = p->sig;
02482 if (p->outsigmod > -1)
02483 mysig = p->outsigmod;
02484
02485 switch (mysig) {
02486 case SIG_FXOLS:
02487 case SIG_FXOGS:
02488 case SIG_FXOKS:
02489 if (p->owner == ast) {
02490
02491
02492
02493 p->dialing = 1;
02494 if (p->use_callerid) {
02495
02496 if (p->cidspill) {
02497 ast_log(LOG_WARNING, "cidspill already exists??\n");
02498 ast_free(p->cidspill);
02499 }
02500 p->callwaitcas = 0;
02501 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02502 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02503 p->cidpos = 0;
02504 send_callerid(p);
02505 }
02506 }
02507
02508 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02509 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02510 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02511 p->cidrings = cidrings[p->distinctivering - 1];
02512 } else {
02513 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02514 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02515 p->cidrings = p->sendcalleridafter;
02516 }
02517
02518
02519 c = strchr(dest, '/');
02520 if (c)
02521 c++;
02522 if (c && (strlen(c) < p->stripmsd)) {
02523 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02524 c = NULL;
02525 }
02526 if (c) {
02527 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02528 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02529 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
02530 } else {
02531 p->dop.dialstr[0] = '\0';
02532 }
02533 x = DAHDI_RING;
02534 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02535 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02536 ast_mutex_unlock(&p->lock);
02537 return -1;
02538 }
02539 p->dialing = 1;
02540 } else {
02541
02542 p->callwaitrings = 0;
02543 if (ast->cid.cid_num)
02544 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02545 else
02546 p->callwait_num[0] = '\0';
02547 if (ast->cid.cid_name)
02548 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02549 else
02550 p->callwait_name[0] = '\0';
02551
02552 if (dahdi_callwait(ast)) {
02553 ast_mutex_unlock(&p->lock);
02554 return -1;
02555 }
02556
02557 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02558 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02559
02560 }
02561 n = ast->cid.cid_name;
02562 l = ast->cid.cid_num;
02563 if (l)
02564 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02565 else
02566 p->lastcid_num[0] = '\0';
02567 if (n)
02568 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02569 else
02570 p->lastcid_name[0] = '\0';
02571 ast_setstate(ast, AST_STATE_RINGING);
02572 idx = dahdi_get_index(ast, p, 0);
02573 if (idx > -1) {
02574 p->subs[idx].needringing = 1;
02575 }
02576 break;
02577 case SIG_FXSLS:
02578 case SIG_FXSGS:
02579 case SIG_FXSKS:
02580 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02581 ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
02582 p->polaritydelaytv = ast_tvnow();
02583 }
02584
02585 case SIG_EMWINK:
02586 case SIG_EM:
02587 case SIG_EM_E1:
02588 case SIG_FEATD:
02589 case SIG_FEATDMF:
02590 case SIG_E911:
02591 case SIG_FGC_CAMA:
02592 case SIG_FGC_CAMAMF:
02593 case SIG_FEATB:
02594 case SIG_SFWINK:
02595 case SIG_SF:
02596 case SIG_SF_FEATD:
02597 case SIG_SF_FEATDMF:
02598 case SIG_FEATDMF_TA:
02599 case SIG_SF_FEATB:
02600 c = strchr(dest, '/');
02601 if (c)
02602 c++;
02603 else
02604 c = "";
02605 if (strlen(c) < p->stripmsd) {
02606 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02607 ast_mutex_unlock(&p->lock);
02608 return -1;
02609 }
02610 #ifdef HAVE_PRI
02611
02612 if (!p->pri) {
02613 #endif
02614 x = DAHDI_START;
02615 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02616 if (res < 0) {
02617 if (errno != EINPROGRESS) {
02618 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02619 ast_mutex_unlock(&p->lock);
02620 return -1;
02621 }
02622 }
02623 #ifdef HAVE_PRI
02624 }
02625 #endif
02626 ast_debug(1, "Dialing '%s'\n", c);
02627 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02628
02629 c += p->stripmsd;
02630
02631 switch (mysig) {
02632 case SIG_FEATD:
02633 l = ast->cid.cid_num;
02634 if (l)
02635 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02636 else
02637 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02638 break;
02639 case SIG_FEATDMF:
02640 l = ast->cid.cid_num;
02641 if (l)
02642 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02643 else
02644 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02645 break;
02646 case SIG_FEATDMF_TA:
02647 {
02648 const char *cic, *ozz;
02649
02650
02651 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02652 if (!ozz)
02653 ozz = defaultozz;
02654 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02655 if (!cic)
02656 cic = defaultcic;
02657 if (!ozz || !cic) {
02658 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02659 ast_mutex_unlock(&p->lock);
02660 return -1;
02661 }
02662 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02663 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02664 p->whichwink = 0;
02665 }
02666 break;
02667 case SIG_E911:
02668 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02669 break;
02670 case SIG_FGC_CAMA:
02671 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02672 break;
02673 case SIG_FGC_CAMAMF:
02674 case SIG_FEATB:
02675 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02676 break;
02677 default:
02678 if (p->pulse)
02679 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02680 else
02681 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02682 break;
02683 }
02684
02685 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02686 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02687 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02688 p->echorest[sizeof(p->echorest) - 1] = '\0';
02689 p->echobreak = 1;
02690 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02691 } else
02692 p->echobreak = 0;
02693 if (!res) {
02694 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02695 int saveerr = errno;
02696
02697 x = DAHDI_ONHOOK;
02698 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02699 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02700 ast_mutex_unlock(&p->lock);
02701 return -1;
02702 }
02703 } else
02704 ast_debug(1, "Deferring dialing...\n");
02705
02706 p->dialing = 1;
02707 if (ast_strlen_zero(c))
02708 p->dialednone = 1;
02709 ast_setstate(ast, AST_STATE_DIALING);
02710 break;
02711 case 0:
02712
02713 ast_setstate(ast, AST_STATE_UP);
02714 break;
02715 case SIG_PRI:
02716 case SIG_BRI:
02717 case SIG_BRI_PTMP:
02718 case SIG_SS7:
02719
02720 p->dialdest[0] = '\0';
02721 p->dialing = 1;
02722 break;
02723 default:
02724 ast_debug(1, "not yet implemented\n");
02725 ast_mutex_unlock(&p->lock);
02726 return -1;
02727 }
02728 #ifdef HAVE_SS7
02729 if (p->ss7) {
02730 char ss7_called_nai;
02731 int called_nai_strip;
02732 char ss7_calling_nai;
02733 int calling_nai_strip;
02734 const char *charge_str = NULL;
02735 const char *gen_address = NULL;
02736 const char *gen_digits = NULL;
02737 const char *gen_dig_type = NULL;
02738 const char *gen_dig_scheme = NULL;
02739 const char *gen_name = NULL;
02740 const char *jip_digits = NULL;
02741 const char *lspi_ident = NULL;
02742 const char *rlt_flag = NULL;
02743 const char *call_ref_id = NULL;
02744 const char *call_ref_pc = NULL;
02745 const char *send_far = NULL;
02746
02747 c = strchr(dest, '/');
02748 if (c) {
02749 c++;
02750 } else {
02751 c = "";
02752 }
02753 if (strlen(c) < p->stripmsd) {
02754 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02755 ast_mutex_unlock(&p->lock);
02756 return -1;
02757 }
02758
02759 if (!p->hidecallerid) {
02760 l = ast->cid.cid_num;
02761 } else {
02762 l = NULL;
02763 }
02764
02765 if (ss7_grab(p, p->ss7)) {
02766 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02767 ast_mutex_unlock(&p->lock);
02768 return -1;
02769 }
02770 p->digital = IS_DIGITAL(ast->transfercapability);
02771 p->ss7call = isup_new_call(p->ss7->ss7);
02772
02773 if (!p->ss7call) {
02774 ss7_rel(p->ss7);
02775 ast_mutex_unlock(&p->lock);
02776 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02777 return -1;
02778 }
02779
02780 called_nai_strip = 0;
02781 ss7_called_nai = p->ss7->called_nai;
02782 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
02783 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02784 called_nai_strip = strlen(p->ss7->internationalprefix);
02785 ss7_called_nai = SS7_NAI_INTERNATIONAL;
02786 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02787 called_nai_strip = strlen(p->ss7->nationalprefix);
02788 ss7_called_nai = SS7_NAI_NATIONAL;
02789 } else {
02790 ss7_called_nai = SS7_NAI_SUBSCRIBER;
02791 }
02792 }
02793 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02794
02795 calling_nai_strip = 0;
02796 ss7_calling_nai = p->ss7->calling_nai;
02797 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
02798 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02799 calling_nai_strip = strlen(p->ss7->internationalprefix);
02800 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02801 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02802 calling_nai_strip = strlen(p->ss7->nationalprefix);
02803 ss7_calling_nai = SS7_NAI_NATIONAL;
02804 } else {
02805 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02806 }
02807 }
02808 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02809 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02810 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02811
02812 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02813 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02814
02815 ast_channel_lock(ast);
02816
02817 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02818 if (charge_str)
02819 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02820
02821 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02822 if (gen_address)
02823 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);
02824
02825 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02826 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02827 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02828 if (gen_digits)
02829 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
02830
02831 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02832 if (gen_name)
02833 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02834
02835 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02836 if (jip_digits)
02837 isup_set_jip_digits(p->ss7call, jip_digits);
02838
02839 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02840 if (lspi_ident)
02841 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
02842
02843 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02844 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02845 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
02846 }
02847
02848 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02849 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02850 if (call_ref_id && call_ref_pc) {
02851 isup_set_callref(p->ss7call, atoi(call_ref_id),
02852 call_ref_pc ? atoi(call_ref_pc) : 0);
02853 }
02854
02855 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02856 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02857 (isup_far(p->ss7->ss7, p->ss7call));
02858
02859 ast_channel_unlock(ast);
02860
02861 isup_iam(p->ss7->ss7, p->ss7call);
02862 ast_setstate(ast, AST_STATE_DIALING);
02863 ss7_rel(p->ss7);
02864 }
02865 #endif
02866 #ifdef HAVE_PRI
02867 if (p->pri) {
02868 struct pri_sr *sr;
02869 #ifdef SUPPORT_USERUSER
02870 const char *useruser;
02871 #endif
02872 int pridialplan;
02873 int dp_strip;
02874 int prilocaldialplan;
02875 int ldp_strip;
02876 int exclusive;
02877 const char *rr_str;
02878 int redirect_reason;
02879
02880 c = strchr(dest, '/');
02881 if (c) {
02882 c++;
02883 } else {
02884 c = "";
02885 }
02886
02887 l = NULL;
02888 n = NULL;
02889 if (!p->hidecallerid) {
02890 l = ast->cid.cid_num;
02891 if (!p->hidecalleridname) {
02892 n = ast->cid.cid_name;
02893 }
02894 }
02895
02896 if (strlen(c) < p->stripmsd) {
02897 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02898 ast_mutex_unlock(&p->lock);
02899 return -1;
02900 }
02901 if (mysig != SIG_FXSKS) {
02902 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02903 s = strchr(c + p->stripmsd, 'w');
02904 if (s) {
02905 if (strlen(s) > 1)
02906 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02907 else
02908 p->dop.dialstr[0] = '\0';
02909 *s = '\0';
02910 } else {
02911 p->dop.dialstr[0] = '\0';
02912 }
02913 }
02914 if (pri_grab(p, p->pri)) {
02915 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02916 ast_mutex_unlock(&p->lock);
02917 return -1;
02918 }
02919 if (!(p->call = pri_new_call(p->pri->pri))) {
02920 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02921 pri_rel(p->pri);
02922 ast_mutex_unlock(&p->lock);
02923 return -1;
02924 }
02925 if (!(sr = pri_sr_new())) {
02926 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02927 pri_rel(p->pri);
02928 ast_mutex_unlock(&p->lock);
02929 }
02930 if (p->bearer || (mysig == SIG_FXSKS)) {
02931 if (p->bearer) {
02932 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02933 p->bearer->call = p->call;
02934 } else
02935 ast_debug(1, "I'm being setup with no bearer right now...\n");
02936
02937 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02938 }
02939 p->digital = IS_DIGITAL(ast->transfercapability);
02940
02941
02942 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
02943 exclusive = 1;
02944 } else {
02945 exclusive = 0;
02946 }
02947
02948 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02949 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02950 (p->digital ? -1 :
02951 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02952 if (p->pri->facilityenable)
02953 pri_facility_enable(p->pri->pri);
02954
02955 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02956 dp_strip = 0;
02957 pridialplan = p->pri->dialplan - 1;
02958 if (pridialplan == -2 || pridialplan == -3) {
02959 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02960 if (pridialplan == -2) {
02961 dp_strip = strlen(p->pri->internationalprefix);
02962 }
02963 pridialplan = PRI_INTERNATIONAL_ISDN;
02964 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02965 if (pridialplan == -2) {
02966 dp_strip = strlen(p->pri->nationalprefix);
02967 }
02968 pridialplan = PRI_NATIONAL_ISDN;
02969 } else {
02970 pridialplan = PRI_LOCAL_ISDN;
02971 }
02972 }
02973 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02974 switch (c[p->stripmsd]) {
02975 case 'U':
02976 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02977 break;
02978 case 'I':
02979 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
02980 break;
02981 case 'N':
02982 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
02983 break;
02984 case 'L':
02985 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
02986 break;
02987 case 'S':
02988 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
02989 break;
02990 case 'V':
02991 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
02992 break;
02993 case 'R':
02994 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
02995 break;
02996 case 'u':
02997 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
02998 break;
02999 case 'e':
03000 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03001 break;
03002 case 'x':
03003 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03004 break;
03005 case 'f':
03006 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03007 break;
03008 case 'n':
03009 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03010 break;
03011 case 'p':
03012 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03013 break;
03014 case 'r':
03015 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03016 break;
03017 default:
03018 if (isalpha(c[p->stripmsd])) {
03019 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03020 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03021 }
03022 break;
03023 }
03024 c++;
03025 }
03026 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03027
03028 ldp_strip = 0;
03029 prilocaldialplan = p->pri->localdialplan - 1;
03030 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03031 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03032 if (prilocaldialplan == -2) {
03033 ldp_strip = strlen(p->pri->internationalprefix);
03034 }
03035 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03036 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03037 if (prilocaldialplan == -2) {
03038 ldp_strip = strlen(p->pri->nationalprefix);
03039 }
03040 prilocaldialplan = PRI_NATIONAL_ISDN;
03041 } else {
03042 prilocaldialplan = PRI_LOCAL_ISDN;
03043 }
03044 }
03045 if (l != NULL) {
03046 while (*l > '9' && *l != '*' && *l != '#') {
03047 switch (*l) {
03048 case 'U':
03049 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03050 break;
03051 case 'I':
03052 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03053 break;
03054 case 'N':
03055 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03056 break;
03057 case 'L':
03058 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03059 break;
03060 case 'S':
03061 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03062 break;
03063 case 'V':
03064 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03065 break;
03066 case 'R':
03067 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03068 break;
03069 case 'u':
03070 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03071 break;
03072 case 'e':
03073 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03074 break;
03075 case 'x':
03076 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03077 break;
03078 case 'f':
03079 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03080 break;
03081 case 'n':
03082 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03083 break;
03084 case 'p':
03085 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03086 break;
03087 case 'r':
03088 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03089 break;
03090 default:
03091 if (isalpha(*l)) {
03092 ast_log(LOG_WARNING,
03093 "Unrecognized prilocaldialplan %s modifier: %c\n",
03094 *l > 'Z' ? "NPI" : "TON", *l);
03095 }
03096 break;
03097 }
03098 l++;
03099 }
03100 }
03101 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03102 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03103 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03104 if (!strcasecmp(rr_str, "UNKNOWN"))
03105 redirect_reason = 0;
03106 else if (!strcasecmp(rr_str, "BUSY"))
03107 redirect_reason = 1;
03108 else if (!strcasecmp(rr_str, "NO_REPLY"))
03109 redirect_reason = 2;
03110 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03111 redirect_reason = 15;
03112 else
03113 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03114 } else
03115 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03116 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03117
03118 #ifdef SUPPORT_USERUSER
03119
03120 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03121
03122 if (useruser)
03123 pri_sr_set_useruser(sr, useruser);
03124 #endif
03125
03126 if (pri_setup(p->pri->pri, p->call, sr)) {
03127 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03128 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03129 pri_rel(p->pri);
03130 ast_mutex_unlock(&p->lock);
03131 pri_sr_free(sr);
03132 return -1;
03133 }
03134 pri_sr_free(sr);
03135 ast_setstate(ast, AST_STATE_DIALING);
03136 pri_rel(p->pri);
03137 }
03138 #endif
03139 ast_mutex_unlock(&p->lock);
03140 return 0;
03141 }
03142
03143 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03144 {
03145 struct dahdi_pvt *p = *pvt;
03146
03147 if (p->prev)
03148 p->prev->next = p->next;
03149 if (p->next)
03150 p->next->prev = p->prev;
03151 if (p->use_smdi)
03152 ast_smdi_interface_unref(p->smdi_iface);
03153 if (p->mwi_event_sub)
03154 ast_event_unsubscribe(p->mwi_event_sub);
03155 if (p->vars)
03156 ast_variables_destroy(p->vars);
03157 ast_mutex_destroy(&p->lock);
03158 dahdi_close_sub(p, SUB_REAL);
03159 if (p->owner)
03160 p->owner->tech_pvt = NULL;
03161 free(p);
03162 *pvt = NULL;
03163 }
03164
03165 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03166 {
03167 int owned = 0;
03168 int i = 0;
03169
03170 if (!now) {
03171 if (cur->owner) {
03172 owned = 1;
03173 }
03174
03175 for (i = 0; i < 3; i++) {
03176 if (cur->subs[i].owner) {
03177 owned = 1;
03178 }
03179 }
03180 if (!owned) {
03181 if (prev) {
03182 prev->next = cur->next;
03183 if (prev->next)
03184 prev->next->prev = prev;
03185 else
03186 ifend = prev;
03187 } else {
03188 iflist = cur->next;
03189 if (iflist)
03190 iflist->prev = NULL;
03191 else
03192 ifend = NULL;
03193 }
03194 destroy_dahdi_pvt(&cur);
03195 }
03196 } else {
03197 if (prev) {
03198 prev->next = cur->next;
03199 if (prev->next)
03200 prev->next->prev = prev;
03201 else
03202 ifend = prev;
03203 } else {
03204 iflist = cur->next;
03205 if (iflist)
03206 iflist->prev = NULL;
03207 else
03208 ifend = NULL;
03209 }
03210 destroy_dahdi_pvt(&cur);
03211 }
03212 return 0;
03213 }
03214
03215 static void destroy_all_channels(void)
03216 {
03217 int x;
03218 struct dahdi_pvt *p, *pl;
03219
03220 while (num_restart_pending) {
03221 usleep(1);
03222 }
03223
03224 ast_mutex_lock(&iflock);
03225
03226 p = iflist;
03227 while (p) {
03228
03229 if (p->cidspill)
03230 ast_free(p->cidspill);
03231 pl = p;
03232 p = p->next;
03233 x = pl->channel;
03234
03235 if (pl)
03236 destroy_dahdi_pvt(&pl);
03237 if (option_verbose > 2)
03238 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03239 }
03240 iflist = NULL;
03241 ifcount = 0;
03242 ast_mutex_unlock(&iflock);
03243 }
03244
03245 #ifdef HAVE_PRI
03246 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03247
03248 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03249
03250 static char *dahdi_send_keypad_facility_descrip =
03251 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03252 " IE over the current channel.\n";
03253
03254 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03255 {
03256
03257 struct dahdi_pvt *p;
03258 char *digits = (char *) data;
03259
03260 if (ast_strlen_zero(digits)) {
03261 ast_debug(1, "No digit string sent to application!\n");
03262 return -1;
03263 }
03264
03265 p = (struct dahdi_pvt *)chan->tech_pvt;
03266
03267 if (!p) {
03268 ast_debug(1, "Unable to find technology private\n");
03269 return -1;
03270 }
03271
03272 ast_mutex_lock(&p->lock);
03273
03274 if (!p->pri || !p->call) {
03275 ast_debug(1, "Unable to find pri or call on channel!\n");
03276 ast_mutex_unlock(&p->lock);
03277 return -1;
03278 }
03279
03280 if (!pri_grab(p, p->pri)) {
03281 pri_keypad_facility(p->pri->pri, p->call, digits);
03282 pri_rel(p->pri);
03283 } else {
03284 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03285 ast_mutex_unlock(&p->lock);
03286 return -1;
03287 }
03288
03289 ast_mutex_unlock(&p->lock);
03290
03291 return 0;
03292 }
03293
03294 static int pri_is_up(struct dahdi_pri *pri)
03295 {
03296 int x;
03297 for (x = 0; x < NUM_DCHANS; x++) {
03298 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03299 return 1;
03300 }
03301 return 0;
03302 }
03303
03304 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03305 {
03306 bearer->owner = &inuse;
03307 bearer->realcall = crv;
03308 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03309 if (crv->subs[SUB_REAL].owner)
03310 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03311 crv->bearer = bearer;
03312 crv->call = bearer->call;
03313 crv->pri = pri;
03314 return 0;
03315 }
03316
03317 static char *pri_order(int level)
03318 {
03319 switch (level) {
03320 case 0:
03321 return "Primary";
03322 case 1:
03323 return "Secondary";
03324 case 2:
03325 return "Tertiary";
03326 case 3:
03327 return "Quaternary";
03328 default:
03329 return "<Unknown>";
03330 }
03331 }
03332
03333
03334 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03335 {
03336 int x = -1;
03337
03338 for (x = 0; x < NUM_DCHANS; x++) {
03339 if ((pri->dchans[x] == pri->pri))
03340 break;
03341 }
03342
03343 return pri->fds[x];
03344 }
03345
03346 static int pri_find_dchan(struct dahdi_pri *pri)
03347 {
03348 int oldslot = -1;
03349 struct pri *old;
03350 int newslot = -1;
03351 int x;
03352 old = pri->pri;
03353 for (x = 0; x < NUM_DCHANS; x++) {
03354 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03355 newslot = x;
03356 if (pri->dchans[x] == old) {
03357 oldslot = x;
03358 }
03359 }
03360 if (newslot < 0) {
03361 newslot = 0;
03362 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03363 pri->dchannels[newslot]);
03364 }
03365 if (old && (oldslot != newslot))
03366 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03367 pri->dchannels[oldslot], pri->dchannels[newslot]);
03368 pri->pri = pri->dchans[newslot];
03369 return 0;
03370 }
03371 #endif
03372
03373 static int dahdi_hangup(struct ast_channel *ast)
03374 {
03375 int res;
03376 int idx,x, law;
03377
03378 struct dahdi_pvt *p = ast->tech_pvt;
03379 struct dahdi_pvt *tmp = NULL;
03380 struct dahdi_pvt *prev = NULL;
03381 struct dahdi_params par;
03382
03383 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03384 if (!ast->tech_pvt) {
03385 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03386 return 0;
03387 }
03388
03389 ast_mutex_lock(&p->lock);
03390
03391 idx = dahdi_get_index(ast, p, 1);
03392
03393 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03394 x = 1;
03395 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03396 }
03397
03398 x = 0;
03399 dahdi_confmute(p, 0);
03400 p->muting = 0;
03401 restore_gains(p);
03402 if (p->origcid_num) {
03403 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03404 ast_free(p->origcid_num);
03405 p->origcid_num = NULL;
03406 }
03407 if (p->origcid_name) {
03408 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03409 ast_free(p->origcid_name);
03410 p->origcid_name = NULL;
03411 }
03412 if (p->dsp)
03413 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03414 p->exten[0] = '\0';
03415
03416 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03417 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03418 p->ignoredtmf = 0;
03419
03420 if (idx > -1) {
03421
03422 p->subs[idx].owner = NULL;
03423 p->subs[idx].needanswer = 0;
03424 p->subs[idx].needflash = 0;
03425 p->subs[idx].needringing = 0;
03426 p->subs[idx].needbusy = 0;
03427 p->subs[idx].needcongestion = 0;
03428 p->subs[idx].linear = 0;
03429 p->subs[idx].needcallerid = 0;
03430 p->polarity = POLARITY_IDLE;
03431 dahdi_setlinear(p->subs[idx].dfd, 0);
03432 if (idx == SUB_REAL) {
03433 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03434 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03435 if (p->subs[SUB_CALLWAIT].inthreeway) {
03436
03437 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03438
03439 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03440 unalloc_sub(p, SUB_CALLWAIT);
03441 p->owner = NULL;
03442 } else {
03443
03444 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03445 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03446 unalloc_sub(p, SUB_THREEWAY);
03447 if (p->subs[SUB_REAL].inthreeway) {
03448
03449
03450 ast_debug(1, "Call was complete, setting owner to former third call\n");
03451 p->owner = p->subs[SUB_REAL].owner;
03452 } else {
03453
03454 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03455 p->owner = NULL;
03456 }
03457 p->subs[SUB_REAL].inthreeway = 0;
03458 }
03459 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03460
03461 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03462 unalloc_sub(p, SUB_CALLWAIT);
03463 p->owner = p->subs[SUB_REAL].owner;
03464 if (p->owner->_state != AST_STATE_UP)
03465 p->subs[SUB_REAL].needanswer = 1;
03466 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03467 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03468 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03469 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03470 unalloc_sub(p, SUB_THREEWAY);
03471 if (p->subs[SUB_REAL].inthreeway) {
03472
03473
03474 ast_debug(1, "Call was complete, setting owner to former third call\n");
03475 p->owner = p->subs[SUB_REAL].owner;
03476 } else {
03477
03478 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03479 p->owner = NULL;
03480 }
03481 p->subs[SUB_REAL].inthreeway = 0;
03482 }
03483 } else if (idx == SUB_CALLWAIT) {
03484
03485 if (p->subs[SUB_CALLWAIT].inthreeway) {
03486
03487
03488 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03489 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03490 S_OR(p->mohsuggest, NULL),
03491 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03492 }
03493 p->subs[SUB_THREEWAY].inthreeway = 0;
03494
03495 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03496 unalloc_sub(p, SUB_THREEWAY);
03497 } else
03498 unalloc_sub(p, SUB_CALLWAIT);
03499 } else if (idx == SUB_THREEWAY) {
03500 if (p->subs[SUB_CALLWAIT].inthreeway) {
03501
03502
03503 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03504 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03505 S_OR(p->mohsuggest, NULL),
03506 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03507 }
03508 p->subs[SUB_CALLWAIT].inthreeway = 0;
03509 }
03510 p->subs[SUB_REAL].inthreeway = 0;
03511
03512
03513 unalloc_sub(p, SUB_THREEWAY);
03514 } else {
03515
03516 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03517 }
03518 }
03519
03520 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03521 p->owner = NULL;
03522 p->ringt = 0;
03523 p->distinctivering = 0;
03524 p->confirmanswer = 0;
03525 p->cidrings = 1;
03526 p->outgoing = 0;
03527 p->digital = 0;
03528 p->faxhandled = 0;
03529 p->pulsedial = 0;
03530 p->onhooktime = time(NULL);
03531 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03532 p->proceeding = 0;
03533 p->dialing = 0;
03534 p->progress = 0;
03535 p->alerting = 0;
03536 p->setup_ack = 0;
03537 p->rlt = 0;
03538 #endif
03539 if (p->dsp) {
03540 ast_dsp_free(p->dsp);
03541 p->dsp = NULL;
03542 }
03543
03544 law = DAHDI_LAW_DEFAULT;
03545 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03546 if (res < 0)
03547 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03548
03549 #ifdef HAVE_SS7
03550 if (p->ss7) {
03551 if (p->ss7call) {
03552 if (!ss7_grab(p, p->ss7)) {
03553 if (!p->alreadyhungup) {
03554 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03555 int icause = ast->hangupcause ? ast->hangupcause : -1;
03556
03557 if (cause) {
03558 if (atoi(cause))
03559 icause = atoi(cause);
03560 }
03561 isup_rel(p->ss7->ss7, p->ss7call, icause);
03562 ss7_rel(p->ss7);
03563 p->alreadyhungup = 1;
03564 } else
03565 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03566 } else {
03567 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03568 res = -1;
03569 }
03570 }
03571 }
03572 #endif
03573 #ifdef HAVE_PRI
03574 if (p->pri) {
03575 #ifdef SUPPORT_USERUSER
03576 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03577 #endif
03578
03579
03580 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03581 if (!pri_grab(p, p->pri)) {
03582 if (p->alreadyhungup) {
03583 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
03584
03585 #ifdef SUPPORT_USERUSER
03586 pri_call_set_useruser(p->call, useruser);
03587 #endif
03588
03589 pri_hangup(p->pri->pri, p->call, -1);
03590 p->call = NULL;
03591 if (p->bearer)
03592 p->bearer->call = NULL;
03593 } else {
03594 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03595 int icause = ast->hangupcause ? ast->hangupcause : -1;
03596 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03597
03598 #ifdef SUPPORT_USERUSER
03599 pri_call_set_useruser(p->call, useruser);
03600 #endif
03601
03602 p->alreadyhungup = 1;
03603 if (p->bearer)
03604 p->bearer->alreadyhungup = 1;
03605 if (cause) {
03606 if (atoi(cause))
03607 icause = atoi(cause);
03608 }
03609 pri_hangup(p->pri->pri, p->call, icause);
03610 }
03611 if (res < 0)
03612 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03613 pri_rel(p->pri);
03614 } else {
03615 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03616 res = -1;
03617 }
03618 } else {
03619 if (p->bearer)
03620 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03621 p->call = NULL;
03622 res = 0;
03623 }
03624 }
03625 #endif
03626 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03627 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03628 if (res < 0) {
03629 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03630 }
03631 switch (p->sig) {
03632 case SIG_FXOGS:
03633 case SIG_FXOLS:
03634 case SIG_FXOKS:
03635 memset(&par, 0, sizeof(par));
03636 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03637 if (!res) {
03638 #if 0
03639 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03640 #endif
03641
03642 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03643 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03644 else
03645 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03646 }
03647 break;
03648 case SIG_FXSGS:
03649 case SIG_FXSLS:
03650 case SIG_FXSKS:
03651
03652
03653 if (ast->_state != AST_STATE_RESERVED) {
03654 time(&p->guardtime);
03655 p->guardtime += 2;
03656 }
03657 break;
03658 default:
03659 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03660 }
03661 if (p->cidspill)
03662 ast_free(p->cidspill);
03663 if (p->sig)
03664 dahdi_disable_ec(p);
03665 x = 0;
03666 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03667 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03668 p->didtdd = 0;
03669 p->cidspill = NULL;
03670 p->callwaitcas = 0;
03671 p->callwaiting = p->permcallwaiting;
03672 p->hidecallerid = p->permhidecallerid;
03673 p->dialing = 0;
03674 p->rdnis[0] = '\0';
03675 update_conf(p);
03676 reset_conf(p);
03677
03678 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03679 x = 0;
03680 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03681 }
03682 #ifdef HAVE_PRI
03683 if (p->bearer) {
03684 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03685
03686
03687 update_conf(p->bearer);
03688 reset_conf(p->bearer);
03689 p->bearer->owner = NULL;
03690 p->bearer->realcall = NULL;
03691 p->bearer = NULL;
03692 p->subs[SUB_REAL].dfd = -1;
03693 p->pri = NULL;
03694 }
03695 #endif
03696 if (num_restart_pending == 0)
03697 restart_monitor();
03698 }
03699
03700 p->callwaitingrepeat = 0;
03701 p->cidcwexpire = 0;
03702 p->oprmode = 0;
03703 ast->tech_pvt = NULL;
03704 ast_mutex_unlock(&p->lock);
03705 ast_module_unref(ast_module_info->self);
03706 ast_verb(3, "Hungup '%s'\n", ast->name);
03707
03708 ast_mutex_lock(&iflock);
03709
03710 if (p->restartpending) {
03711 num_restart_pending--;
03712 }
03713
03714 tmp = iflist;
03715 prev = NULL;
03716 if (p->destroy) {
03717 while (tmp) {
03718 if (tmp == p) {
03719 destroy_channel(prev, tmp, 0);
03720 break;
03721 } else {
03722 prev = tmp;
03723 tmp = tmp->next;
03724 }
03725 }
03726 }
03727 ast_mutex_unlock(&iflock);
03728 return 0;
03729 }
03730
03731 static int dahdi_answer(struct ast_channel *ast)
03732 {
03733 struct dahdi_pvt *p = ast->tech_pvt;
03734 int res = 0;
03735 int idx;
03736 int oldstate = ast->_state;
03737 ast_setstate(ast, AST_STATE_UP);
03738 ast_mutex_lock(&p->lock);
03739 idx = dahdi_get_index(ast, p, 0);
03740 if (idx < 0)
03741 idx = SUB_REAL;
03742
03743 if ((p->radio || (p->oprmode < 0))) {
03744 ast_mutex_unlock(&p->lock);
03745 return 0;
03746 }
03747 switch (p->sig) {
03748 case SIG_FXSLS:
03749 case SIG_FXSGS:
03750 case SIG_FXSKS:
03751 p->ringt = 0;
03752
03753 case SIG_EM:
03754 case SIG_EM_E1:
03755 case SIG_EMWINK:
03756 case SIG_FEATD:
03757 case SIG_FEATDMF:
03758 case SIG_FEATDMF_TA:
03759 case SIG_E911:
03760 case SIG_FGC_CAMA:
03761 case SIG_FGC_CAMAMF:
03762 case SIG_FEATB:
03763 case SIG_SF:
03764 case SIG_SFWINK:
03765 case SIG_SF_FEATD:
03766 case SIG_SF_FEATDMF:
03767 case SIG_SF_FEATB:
03768 case SIG_FXOLS:
03769 case SIG_FXOGS:
03770 case SIG_FXOKS:
03771
03772 ast_debug(1, "Took %s off hook\n", ast->name);
03773 if (p->hanguponpolarityswitch) {
03774 p->polaritydelaytv = ast_tvnow();
03775 }
03776 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03777 tone_zone_play_tone(p->subs[idx].dfd, -1);
03778 p->dialing = 0;
03779 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03780 if (oldstate == AST_STATE_RINGING) {
03781 ast_debug(1, "Finally swapping real and threeway\n");
03782 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03783 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03784 p->owner = p->subs[SUB_REAL].owner;
03785 }
03786 }
03787 if (p->sig & __DAHDI_SIG_FXS) {
03788 dahdi_enable_ec(p);
03789 dahdi_train_ec(p);
03790 }
03791 break;
03792 #ifdef HAVE_PRI
03793 case SIG_BRI:
03794 case SIG_BRI_PTMP:
03795 case SIG_PRI:
03796
03797 if (!pri_grab(p, p->pri)) {
03798 p->proceeding = 1;
03799 p->dialing = 0;
03800 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03801 pri_rel(p->pri);
03802 } else {
03803 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03804 res = -1;
03805 }
03806 break;
03807 #endif
03808 #ifdef HAVE_SS7
03809 case SIG_SS7:
03810 if (!ss7_grab(p, p->ss7)) {
03811 p->proceeding = 1;
03812 res = isup_anm(p->ss7->ss7, p->ss7call);
03813 ss7_rel(p->ss7);
03814 } else {
03815 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03816 res = -1;
03817 }
03818 break;
03819 #endif
03820 case 0:
03821 ast_mutex_unlock(&p->lock);
03822 return 0;
03823 default:
03824 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03825 res = -1;
03826 }
03827 ast_mutex_unlock(&p->lock);
03828 return res;
03829 }
03830
03831 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03832 {
03833 char *cp;
03834 signed char *scp;
03835 int x;
03836 int idx;
03837 struct dahdi_pvt *p = chan->tech_pvt, *pp;
03838 struct oprmode *oprmode;
03839
03840
03841
03842 if (!data || (datalen < 1)) {
03843 errno = EINVAL;
03844 return -1;
03845 }
03846
03847 switch (option) {
03848 case AST_OPTION_TXGAIN:
03849 scp = (signed char *) data;
03850 idx = dahdi_get_index(chan, p, 0);
03851 if (idx < 0) {
03852 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03853 return -1;
03854 }
03855 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03856 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
03857 case AST_OPTION_RXGAIN:
03858 scp = (signed char *) data;
03859 idx = dahdi_get_index(chan, p, 0);
03860 if (idx < 0) {
03861 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03862 return -1;
03863 }
03864 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03865 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
03866 case AST_OPTION_TONE_VERIFY:
03867 if (!p->dsp)
03868 break;
03869 cp = (char *) data;
03870 switch (*cp) {
03871 case 1:
03872 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03873 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
03874 break;
03875 case 2:
03876 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03877 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
03878 break;
03879 default:
03880 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03881 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03882 break;
03883 }
03884 break;
03885 case AST_OPTION_TDD:
03886
03887 cp = (char *) data;
03888 p->mate = 0;
03889 if (!*cp) {
03890 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03891 if (p->tdd)
03892 tdd_free(p->tdd);
03893 p->tdd = 0;
03894 break;
03895 }
03896 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03897 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03898 dahdi_disable_ec(p);
03899
03900 if (!p->didtdd) {
03901 unsigned char mybuf[41000];
03902 unsigned char *buf;
03903 int size, res, fd, len;
03904 struct pollfd fds[1];
03905
03906 buf = mybuf;
03907 memset(buf, 0x7f, sizeof(mybuf));
03908 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03909 len = 40000;
03910 idx = dahdi_get_index(chan, p, 0);
03911 if (idx < 0) {
03912 ast_log(LOG_WARNING, "No index in TDD?\n");
03913 return -1;
03914 }
03915 fd = p->subs[idx].dfd;
03916 while (len) {
03917 if (ast_check_hangup(chan))
03918 return -1;
03919 size = len;
03920 if (size > READ_SIZE)
03921 size = READ_SIZE;
03922 fds[0].fd = fd;
03923 fds[0].events = POLLPRI | POLLOUT;
03924 fds[0].revents = 0;
03925 res = poll(fds, 1, -1);
03926 if (!res) {
03927 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03928 continue;
03929 }
03930
03931 if (fds[0].revents & POLLPRI)
03932 return -1;
03933 if (!(fds[0].revents & POLLOUT)) {
03934 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03935 continue;
03936 }
03937 res = write(fd, buf, size);
03938 if (res != size) {
03939 if (res == -1) return -1;
03940 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03941 break;
03942 }
03943 len -= size;
03944 buf += size;
03945 }
03946 p->didtdd = 1;
03947 }
03948 if (*cp == 2) {
03949 if (p->tdd)
03950 tdd_free(p->tdd);
03951 p->tdd = 0;
03952 p->mate = 1;
03953 break;
03954 }
03955 if (!p->tdd) {
03956 p->tdd = tdd_new();
03957 }
03958 break;
03959 case AST_OPTION_RELAXDTMF:
03960 if (!p->dsp)
03961 break;
03962 cp = (char *) data;
03963 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03964 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03965 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03966 break;
03967 case AST_OPTION_AUDIO_MODE:
03968 cp = (char *) data;
03969 if (!*cp) {
03970 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03971 x = 0;
03972 dahdi_disable_ec(p);
03973 } else {
03974 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03975 x = 1;
03976 }
03977 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03978 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03979 break;
03980 case AST_OPTION_OPRMODE:
03981 oprmode = (struct oprmode *) data;
03982 pp = oprmode->peer->tech_pvt;
03983 p->oprmode = pp->oprmode = 0;
03984
03985 p->oprpeer = pp;
03986 pp->oprpeer = p;
03987
03988 if (oprmode->mode)
03989 {
03990 pp->oprmode = oprmode->mode;
03991 p->oprmode = -oprmode->mode;
03992 }
03993 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
03994 oprmode->mode, chan->name,oprmode->peer->name);
03995 break;
03996 case AST_OPTION_ECHOCAN:
03997 cp = (char *) data;
03998 if (*cp) {
03999 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
04000 dahdi_enable_ec(p);
04001 } else {
04002 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
04003 dahdi_disable_ec(p);
04004 }
04005 break;
04006 }
04007 errno = 0;
04008
04009 return 0;
04010 }
04011
04012 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
04013 {
04014 struct dahdi_pvt *p = chan->tech_pvt;
04015
04016 if (!strcasecmp(data, "rxgain")) {
04017 ast_mutex_lock(&p->lock);
04018 snprintf(buf, len, "%f", p->rxgain);
04019 ast_mutex_unlock(&p->lock);
04020 } else if (!strcasecmp(data, "txgain")) {
04021 ast_mutex_lock(&p->lock);
04022 snprintf(buf, len, "%f", p->txgain);
04023 ast_mutex_unlock(&p->lock);
04024 } else {
04025 ast_copy_string(buf, "", len);
04026 }
04027 return 0;
04028 }
04029
04030
04031 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04032 {
04033
04034 int x;
04035 int hasslaves;
04036 if (!master)
04037 return;
04038 if (needlock) {
04039 ast_mutex_lock(&master->lock);
04040 if (slave) {
04041 while (ast_mutex_trylock(&slave->lock)) {
04042 DEADLOCK_AVOIDANCE(&master->lock);
04043 }
04044 }
04045 }
04046 hasslaves = 0;
04047 for (x = 0; x < MAX_SLAVES; x++) {
04048 if (master->slaves[x]) {
04049 if (!slave || (master->slaves[x] == slave)) {
04050
04051 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04052 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04053 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04054 master->slaves[x]->master = NULL;
04055 master->slaves[x] = NULL;
04056 } else
04057 hasslaves = 1;
04058 }
04059 if (!hasslaves)
04060 master->inconference = 0;
04061 }
04062 if (!slave) {
04063 if (master->master) {
04064
04065 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04066 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04067 hasslaves = 0;
04068 for (x = 0; x < MAX_SLAVES; x++) {
04069 if (master->master->slaves[x] == master)
04070 master->master->slaves[x] = NULL;
04071 else if (master->master->slaves[x])
04072 hasslaves = 1;
04073 }
04074 if (!hasslaves)
04075 master->master->inconference = 0;
04076 }
04077 master->master = NULL;
04078 }
04079 update_conf(master);
04080 if (needlock) {
04081 if (slave)
04082 ast_mutex_unlock(&slave->lock);
04083 ast_mutex_unlock(&master->lock);
04084 }
04085 }
04086
04087 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04088 int x;
04089 if (!slave || !master) {
04090 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04091 return;
04092 }
04093 for (x = 0; x < MAX_SLAVES; x++) {
04094 if (!master->slaves[x]) {
04095 master->slaves[x] = slave;
04096 break;
04097 }
04098 }
04099 if (x >= MAX_SLAVES) {
04100 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04101 master->slaves[MAX_SLAVES - 1] = slave;
04102 }
04103 if (slave->master)
04104 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04105 slave->master = master;
04106
04107 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04108 }
04109
04110 static void disable_dtmf_detect(struct dahdi_pvt *p)
04111 {
04112 int val;
04113
04114 p->ignoredtmf = 1;
04115
04116 val = 0;
04117 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04118
04119 if (!p->hardwaredtmf && p->dsp) {
04120 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
04121 ast_dsp_set_features(p->dsp, p->dsp_features);
04122 }
04123 }
04124
04125 static void enable_dtmf_detect(struct dahdi_pvt *p)
04126 {
04127 int val;
04128
04129 if (p->channel == CHAN_PSEUDO)
04130 return;
04131
04132 p->ignoredtmf = 0;
04133
04134 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
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 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)
04144 {
04145 struct ast_channel *who;
04146 struct dahdi_pvt *p0, *p1, *op0, *op1;
04147 struct dahdi_pvt *master = NULL, *slave = NULL;
04148 struct ast_frame *f;
04149 int inconf = 0;
04150 int nothingok = 1;
04151 int ofd0, ofd1;
04152 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04153 int os0 = -1, os1 = -1;
04154 int priority = 0;
04155 struct ast_channel *oc0, *oc1;
04156 enum ast_bridge_result res;
04157
04158 #ifdef PRI_2BCT
04159 int triedtopribridge = 0;
04160 q931_call *q931c0 = NULL, *q931c1 = NULL;
04161 #endif
04162
04163
04164
04165
04166
04167
04168 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04169 return AST_BRIDGE_FAILED_NOWARN;
04170
04171 ast_channel_lock(c0);
04172 while (ast_channel_trylock(c1)) {
04173 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04174 }
04175
04176 p0 = c0->tech_pvt;
04177 p1 = c1->tech_pvt;
04178
04179 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04180 ast_channel_unlock(c0);
04181 ast_channel_unlock(c1);
04182 return AST_BRIDGE_FAILED_NOWARN;
04183 }
04184
04185 oi0 = dahdi_get_index(c0, p0, 0);
04186 oi1 = dahdi_get_index(c1, p1, 0);
04187 if ((oi0 < 0) || (oi1 < 0)) {
04188 ast_channel_unlock(c0);
04189 ast_channel_unlock(c1);
04190 return AST_BRIDGE_FAILED;
04191 }
04192
04193 op0 = p0 = c0->tech_pvt;
04194 op1 = p1 = c1->tech_pvt;
04195 ofd0 = c0->fds[0];
04196 ofd1 = c1->fds[0];
04197 oc0 = p0->owner;
04198 oc1 = p1->owner;
04199
04200 if (ast_mutex_trylock(&p0->lock)) {
04201
04202 ast_channel_unlock(c0);
04203 ast_channel_unlock(c1);
04204 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04205 return AST_BRIDGE_RETRY;
04206 }
04207 if (ast_mutex_trylock(&p1->lock)) {
04208
04209 ast_mutex_unlock(&p0->lock);
04210 ast_channel_unlock(c0);
04211 ast_channel_unlock(c1);
04212 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04213 return AST_BRIDGE_RETRY;
04214 }
04215
04216 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04217 if (p0->owner && p1->owner) {
04218
04219 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04220 master = p0;
04221 slave = p1;
04222 inconf = 1;
04223 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04224 master = p1;
04225 slave = p0;
04226 inconf = 1;
04227 } else {
04228 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04229 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04230 p0->channel,
04231 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04232 p0->subs[SUB_REAL].inthreeway, p0->channel,
04233 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04234 p1->subs[SUB_REAL].inthreeway);
04235 }
04236 nothingok = 0;
04237 }
04238 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04239 if (p1->subs[SUB_THREEWAY].inthreeway) {
04240 master = p1;
04241 slave = p0;
04242 nothingok = 0;
04243 }
04244 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04245 if (p0->subs[SUB_THREEWAY].inthreeway) {
04246 master = p0;
04247 slave = p1;
04248 nothingok = 0;
04249 }
04250 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04251
04252
04253 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04254 master = p1;
04255 slave = p0;
04256 nothingok = 0;
04257 }
04258 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04259
04260 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04261 master = p0;
04262 slave = p1;
04263 nothingok = 0;
04264 }
04265 }
04266 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04267 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04268 if (master && slave) {
04269
04270
04271
04272 if ((oi1 == SUB_THREEWAY) &&
04273 p1->subs[SUB_THREEWAY].inthreeway &&
04274 p1->subs[SUB_REAL].owner &&
04275 p1->subs[SUB_REAL].inthreeway &&
04276 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04277 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04278 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04279 os1 = p1->subs[SUB_REAL].owner->_state;
04280 } else {
04281 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04282 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04283 }
04284 if ((oi0 == SUB_THREEWAY) &&
04285 p0->subs[SUB_THREEWAY].inthreeway &&
04286 p0->subs[SUB_REAL].owner &&
04287 p0->subs[SUB_REAL].inthreeway &&
04288 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04289 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04290 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04291 os0 = p0->subs[SUB_REAL].owner->_state;
04292 } else {
04293 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04294 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04295 }
04296 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04297 if (!p0->echocanbridged || !p1->echocanbridged) {
04298
04299 dahdi_disable_ec(p0);
04300 dahdi_disable_ec(p1);
04301 }
04302 }
04303 dahdi_link(slave, master);
04304 master->inconference = inconf;
04305 } else if (!nothingok)
04306 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04307
04308 update_conf(p0);
04309 update_conf(p1);
04310 t0 = p0->subs[SUB_REAL].inthreeway;
04311 t1 = p1->subs[SUB_REAL].inthreeway;
04312
04313 ast_mutex_unlock(&p0->lock);
04314 ast_mutex_unlock(&p1->lock);
04315
04316 ast_channel_unlock(c0);
04317 ast_channel_unlock(c1);
04318
04319
04320 if ((!master || !slave) && !nothingok) {
04321 dahdi_enable_ec(p0);
04322 dahdi_enable_ec(p1);
04323 return AST_BRIDGE_FAILED;
04324 }
04325
04326 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04327
04328 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04329 disable_dtmf_detect(op0);
04330
04331 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04332 disable_dtmf_detect(op1);
04333
04334 for (;;) {
04335 struct ast_channel *c0_priority[2] = {c0, c1};
04336 struct ast_channel *c1_priority[2] = {c1, c0};
04337
04338
04339
04340
04341 ast_channel_lock(c0);
04342 while (ast_channel_trylock(c1)) {
04343 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04344 }
04345
04346 p0 = c0->tech_pvt;
04347 p1 = c1->tech_pvt;
04348
04349 if (op0 == p0)
04350 i0 = dahdi_get_index(c0, p0, 1);
04351 if (op1 == p1)
04352 i1 = dahdi_get_index(c1, p1, 1);
04353
04354 ast_channel_unlock(c0);
04355 ast_channel_unlock(c1);
04356
04357 if (!timeoutms ||
04358 (op0 != p0) ||
04359 (op1 != p1) ||
04360 (ofd0 != c0->fds[0]) ||
04361 (ofd1 != c1->fds[0]) ||
04362 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04363 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04364 (oc0 != p0->owner) ||
04365 (oc1 != p1->owner) ||
04366 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04367 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04368 (oi0 != i0) ||
04369 (oi1 != i1)) {
04370 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04371 op0->channel, oi0, op1->channel, oi1);
04372 res = AST_BRIDGE_RETRY;
04373 goto return_from_bridge;
04374 }
04375
04376 #ifdef PRI_2BCT
04377 q931c0 = p0->call;
04378 q931c1 = p1->call;
04379 if (p0->transfer && p1->transfer
04380 && q931c0 && q931c1
04381 && !triedtopribridge) {
04382 pri_channel_bridge(q931c0, q931c1);
04383 triedtopribridge = 1;
04384 }
04385 #endif
04386
04387 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04388 if (!who) {
04389 ast_debug(1, "Ooh, empty read...\n");
04390 continue;
04391 }
04392 f = ast_read(who);
04393 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04394 *fo = f;
04395 *rc = who;
04396 res = AST_BRIDGE_COMPLETE;
04397 goto return_from_bridge;
04398 }
04399 if (f->frametype == AST_FRAME_DTMF) {
04400 if ((who == c0) && p0->pulsedial) {
04401 ast_write(c1, f);
04402 } else if ((who == c1) && p1->pulsedial) {
04403 ast_write(c0, f);
04404 } else {
04405 *fo = f;
04406 *rc = who;
04407 res = AST_BRIDGE_COMPLETE;
04408 goto return_from_bridge;
04409 }
04410 }
04411 ast_frfree(f);
04412
04413
04414 priority = !priority;
04415 }
04416
04417 return_from_bridge:
04418 if (op0 == p0)
04419 dahdi_enable_ec(p0);
04420
04421 if (op1 == p1)
04422 dahdi_enable_ec(p1);
04423
04424 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04425 enable_dtmf_detect(op0);
04426
04427 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04428 enable_dtmf_detect(op1);
04429
04430 dahdi_unlink(slave, master, 1);
04431
04432 return res;
04433 }
04434
04435 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04436 {
04437 struct dahdi_pvt *p = newchan->tech_pvt;
04438 int x;
04439 ast_mutex_lock(&p->lock);
04440 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04441 if (p->owner == oldchan) {
04442 p->owner = newchan;
04443 }
04444 for (x = 0; x < 3; x++)
04445 if (p->subs[x].owner == oldchan) {
04446 if (!x)
04447 dahdi_unlink(NULL, p, 0);
04448 p->subs[x].owner = newchan;
04449 }
04450 if (newchan->_state == AST_STATE_RINGING)
04451 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04452 update_conf(p);
04453 ast_mutex_unlock(&p->lock);
04454 return 0;
04455 }
04456
04457 static int dahdi_ring_phone(struct dahdi_pvt *p)
04458 {
04459 int x;
04460 int res;
04461
04462 x = 0;
04463 x = DAHDI_ONHOOK;
04464 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04465 do {
04466 x = DAHDI_RING;
04467 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04468 if (res) {
04469 switch (errno) {
04470 case EBUSY:
04471 case EINTR:
04472
04473 usleep(10000);
04474 continue;
04475 case EINPROGRESS:
04476 res = 0;
04477 break;
04478 default:
04479 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04480 res = 0;
04481 }
04482 }
04483 } while (res);
04484 return res;
04485 }
04486
04487 static void *ss_thread(void *data);
04488
04489 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
04490
04491 static int attempt_transfer(struct dahdi_pvt *p)
04492 {
04493
04494
04495
04496 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04497
04498
04499 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04500 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04501 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04502 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04503 }
04504 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04505 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04506 }
04507 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04508 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04509 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04510 return -1;
04511 }
04512
04513 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04514 unalloc_sub(p, SUB_THREEWAY);
04515 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04516 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04517 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04518 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04519 }
04520 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04521 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04522 }
04523 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04524 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04525 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04526 return -1;
04527 }
04528
04529 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04530 ast_channel_unlock(p->subs[SUB_REAL].owner);
04531 unalloc_sub(p, SUB_THREEWAY);
04532
04533 return 1;
04534 } else {
04535 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04536 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04537 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04538 return -1;
04539 }
04540 return 0;
04541 }
04542
04543 static int check_for_conference(struct dahdi_pvt *p)
04544 {
04545 struct dahdi_confinfo ci;
04546
04547 if (p->master || (p->confno > -1))
04548 return 0;
04549 memset(&ci, 0, sizeof(ci));
04550 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04551 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04552 return 0;
04553 }
04554
04555
04556
04557 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04558 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04559 return 1;
04560 }
04561 return 0;
04562 }
04563
04564
04565
04566
04567
04568
04569 static int get_alarms(struct dahdi_pvt *p)
04570 {
04571 int res;
04572 struct dahdi_spaninfo zi;
04573 struct dahdi_params params;
04574
04575 memset(&zi, 0, sizeof(zi));
04576 zi.spanno = p->span;
04577
04578 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04579 if (zi.alarms != DAHDI_ALARM_NONE)
04580 return zi.alarms;
04581 } else {
04582 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04583 return 0;
04584 }
04585
04586
04587 memset(¶ms, 0, sizeof(params));
04588 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04589 return params.chan_alarms;
04590
04591 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04592
04593 return DAHDI_ALARM_NONE;
04594 }
04595
04596 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
04597 {
04598 struct dahdi_pvt *p = ast->tech_pvt;
04599 struct ast_frame *f = *dest;
04600
04601 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04602
04603 if (p->confirmanswer) {
04604 ast_debug(1, "Confirm answer on %s!\n", ast->name);
04605
04606
04607 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04608 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04609 *dest = &p->subs[idx].f;
04610
04611 p->confirmanswer = 0;
04612 } else if (p->callwaitcas) {
04613 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04614 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04615 if (p->cidspill)
04616 ast_free(p->cidspill);
04617 send_cwcidspill(p);
04618 }
04619 p->callwaitcas = 0;
04620 p->subs[idx].f.frametype = AST_FRAME_NULL;
04621 p->subs[idx].f.subclass = 0;
04622 *dest = &p->subs[idx].f;
04623 } else if (f->subclass == 'f') {
04624
04625 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04626 p->faxhandled = 1;
04627 if (strcmp(ast->exten, "fax")) {
04628 const char *target_context = S_OR(ast->macrocontext, ast->context);
04629
04630
04631
04632
04633
04634 ast_mutex_unlock(&p->lock);
04635 ast_channel_unlock(ast);
04636 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04637 ast_channel_lock(ast);
04638 ast_mutex_lock(&p->lock);
04639 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04640
04641 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04642 if (ast_async_goto(ast, target_context, "fax", 1))
04643 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04644 } else {
04645 ast_channel_lock(ast);
04646 ast_mutex_lock(&p->lock);
04647 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04648 }
04649 } else {
04650 ast_debug(1, "Already in a fax extension, not redirecting\n");
04651 }
04652 } else {
04653 ast_debug(1, "Fax already handled\n");
04654 }
04655 dahdi_confmute(p, 0);
04656 p->subs[idx].f.frametype = AST_FRAME_NULL;
04657 p->subs[idx].f.subclass = 0;
04658 *dest = &p->subs[idx].f;
04659 }
04660 }
04661
04662 static void handle_alarms(struct dahdi_pvt *p, int alms)
04663 {
04664 const char *alarm_str = alarm2str(alms);
04665
04666 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04667 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04668 "Alarm: %s\r\n"
04669 "Channel: %d\r\n",
04670 alarm_str, p->channel);
04671 }
04672
04673 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04674 {
04675 int res, x;
04676 int idx, mysig;
04677 char *c;
04678 struct dahdi_pvt *p = ast->tech_pvt;
04679 pthread_t threadid;
04680 struct ast_channel *chan;
04681 struct ast_frame *f;
04682
04683 idx = dahdi_get_index(ast, p, 0);
04684 mysig = p->sig;
04685 if (p->outsigmod > -1)
04686 mysig = p->outsigmod;
04687 p->subs[idx].f.frametype = AST_FRAME_NULL;
04688 p->subs[idx].f.subclass = 0;
04689 p->subs[idx].f.datalen = 0;
04690 p->subs[idx].f.samples = 0;
04691 p->subs[idx].f.mallocd = 0;
04692 p->subs[idx].f.offset = 0;
04693 p->subs[idx].f.src = "dahdi_handle_event";
04694 p->subs[idx].f.data.ptr = NULL;
04695 f = &p->subs[idx].f;
04696
04697 if (idx < 0)
04698 return &p->subs[idx].f;
04699 if (p->fake_event) {
04700 res = p->fake_event;
04701 p->fake_event = 0;
04702 } else
04703 res = dahdi_get_event(p->subs[idx].dfd);
04704
04705 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
04706
04707 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04708 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04709 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04710 #ifdef HAVE_PRI
04711 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04712
04713 } else {
04714 #endif
04715 dahdi_confmute(p, 0);
04716 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
04717 p->subs[idx].f.subclass = res & 0xff;
04718 #ifdef HAVE_PRI
04719 }
04720 #endif
04721 dahdi_handle_dtmfup(ast, idx, &f);
04722 return f;
04723 }
04724
04725 if (res & DAHDI_EVENT_DTMFDOWN) {
04726 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04727
04728 dahdi_confmute(p, 1);
04729 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
04730 p->subs[idx].f.subclass = res & 0xff;
04731 return &p->subs[idx].f;
04732 }
04733
04734 switch (res) {
04735 case DAHDI_EVENT_EC_DISABLED:
04736 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04737 p->echocanon = 0;
04738 break;
04739 case DAHDI_EVENT_BITSCHANGED:
04740 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
04741 case DAHDI_EVENT_PULSE_START:
04742
04743 if (!ast->pbx)
04744 tone_zone_play_tone(p->subs[idx].dfd, -1);
04745 break;
04746 case DAHDI_EVENT_DIALCOMPLETE:
04747 if (p->inalarm) break;
04748 if ((p->radio || (p->oprmode < 0))) break;
04749 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
04750 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04751 return NULL;
04752 }
04753 if (!x) {
04754 dahdi_enable_ec(p);
04755 if (p->echobreak) {
04756 dahdi_train_ec(p);
04757 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04758 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04759 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04760 p->echobreak = 0;
04761 } else {
04762 p->dialing = 0;
04763 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04764
04765 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04766 ast_setstate(ast, AST_STATE_UP);
04767 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04768 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04769 break;
04770 } else {
04771
04772 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04773 }
04774 }
04775 if (ast->_state == AST_STATE_DIALING) {
04776 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04777 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04778 } 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)))) {
04779 ast_setstate(ast, AST_STATE_RINGING);
04780 } else if (!p->answeronpolarityswitch) {
04781 ast_setstate(ast, AST_STATE_UP);
04782 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04783 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04784
04785 p->polarity = POLARITY_REV;
04786 } else {
04787
04788 p->polarity = POLARITY_IDLE;
04789 }
04790 }
04791 }
04792 }
04793 break;
04794 case DAHDI_EVENT_ALARM:
04795 #ifdef HAVE_PRI
04796 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04797 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04798
04799 if (p->call) {
04800 if (p->pri && p->pri->pri) {
04801 if (!pri_grab(p, p->pri)) {
04802 pri_hangup(p->pri->pri, p->call, -1);
04803 pri_destroycall(p->pri->pri, p->call);
04804 p->call = NULL;
04805 pri_rel(p->pri);
04806 } else
04807 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04808 } else
04809 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04810 }
04811 if (p->owner)
04812 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04813 }
04814 }
04815 if (p->bearer)
04816 p->bearer->inalarm = 1;
04817 else
04818 #endif
04819 p->inalarm = 1;
04820 res = get_alarms(p);
04821 handle_alarms(p, res);
04822 #ifdef HAVE_PRI
04823 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04824
04825 } else {
04826 break;
04827 }
04828 #endif
04829 #ifdef HAVE_SS7
04830 if (p->sig == SIG_SS7)
04831 break;
04832 #endif
04833 case DAHDI_EVENT_ONHOOK:
04834 if (p->radio) {
04835 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04836 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
04837 break;
04838 }
04839 if (p->oprmode < 0)
04840 {
04841 if (p->oprmode != -1) break;
04842 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04843 {
04844
04845 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04846 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04847 save_conference(p->oprpeer);
04848 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04849 }
04850 break;
04851 }
04852 switch (p->sig) {
04853 case SIG_FXOLS:
04854 case SIG_FXOGS:
04855 case SIG_FXOKS:
04856 p->onhooktime = time(NULL);
04857 p->msgstate = -1;
04858
04859 if (idx == SUB_REAL) {
04860
04861 if (p->subs[SUB_CALLWAIT].owner) {
04862
04863 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04864 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04865 unalloc_sub(p, SUB_CALLWAIT);
04866 #if 0
04867 p->subs[idx].needanswer = 0;
04868 p->subs[idx].needringing = 0;
04869 #endif
04870 p->callwaitingrepeat = 0;
04871 p->cidcwexpire = 0;
04872 p->owner = NULL;
04873
04874 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04875 p->dialing = 1;
04876 dahdi_ring_phone(p);
04877 } else if (p->subs[SUB_THREEWAY].owner) {
04878 unsigned int mssinceflash;
04879
04880
04881 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04882
04883 DLA_UNLOCK(&p->lock);
04884 CHANNEL_DEADLOCK_AVOIDANCE(ast);
04885
04886
04887
04888 DLA_LOCK(&p->lock);
04889 if (p->owner != ast) {
04890 ast_log(LOG_WARNING, "This isn't good...\n");
04891 return NULL;
04892 }
04893 }
04894 if (!p->subs[SUB_THREEWAY].owner) {
04895 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04896 return NULL;
04897 }
04898 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04899 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04900 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04901
04902
04903 if (p->subs[SUB_THREEWAY].owner)
04904 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
04905 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04906 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04907 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04908 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04909 if (p->transfer) {
04910
04911 p->subs[SUB_REAL].inthreeway = 0;
04912 p->subs[SUB_THREEWAY].inthreeway = 0;
04913
04914 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04915 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04916
04917 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04918 p->owner = NULL;
04919
04920 dahdi_ring_phone(p);
04921 } else {
04922 if ((res = attempt_transfer(p)) < 0) {
04923 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04924 if (p->subs[SUB_THREEWAY].owner)
04925 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04926 } else if (res) {
04927
04928 if (p->subs[SUB_THREEWAY].owner)
04929 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04930 break;
04931 }
04932 }
04933 } else {
04934 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04935 if (p->subs[SUB_THREEWAY].owner)
04936 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04937 }
04938 } else {
04939 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04940
04941 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04942 p->owner = NULL;
04943
04944 dahdi_ring_phone(p);
04945 }
04946 }
04947 } else {
04948 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
04949 }
04950
04951 default:
04952 dahdi_disable_ec(p);
04953 return NULL;
04954 }
04955 break;
04956 case DAHDI_EVENT_RINGOFFHOOK:
04957 if (p->inalarm) break;
04958 if (p->oprmode < 0)
04959 {
04960 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04961 {
04962
04963 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04964 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04965 restore_conference(p->oprpeer);
04966 }
04967 break;
04968 }
04969 if (p->radio)
04970 {
04971 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04972 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
04973 break;
04974 }
04975
04976
04977 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04978 c = strchr(p->dialdest, '/');
04979 if (c)
04980 c++;
04981 else
04982 c = p->dialdest;
04983 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04984 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04985 if (strlen(p->dop.dialstr) > 4) {
04986 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04987 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04988 p->echorest[sizeof(p->echorest) - 1] = '\0';
04989 p->echobreak = 1;
04990 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04991 } else
04992 p->echobreak = 0;
04993 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04994 int saveerr = errno;
04995
04996 x = DAHDI_ONHOOK;
04997 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04998 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04999 return NULL;
05000 }
05001 p->dialing = 1;
05002 return &p->subs[idx].f;
05003 }
05004 switch (p->sig) {
05005 case SIG_FXOLS:
05006 case SIG_FXOGS:
05007 case SIG_FXOKS:
05008 switch (ast->_state) {
05009 case AST_STATE_RINGING:
05010 dahdi_enable_ec(p);
05011 dahdi_train_ec(p);
05012 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05013 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05014
05015 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05016 ast_debug(1, "channel %d answered\n", p->channel);
05017 if (p->cidspill) {
05018
05019 ast_free(p->cidspill);
05020 p->cidspill = NULL;
05021 }
05022 p->dialing = 0;
05023 p->callwaitcas = 0;
05024 if (p->confirmanswer) {
05025
05026 p->subs[idx].f.frametype = AST_FRAME_NULL;
05027 p->subs[idx].f.subclass = 0;
05028 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05029
05030 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05031 if (res < 0) {
05032 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05033 p->dop.dialstr[0] = '\0';
05034 return NULL;
05035 } else {
05036 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05037 p->subs[idx].f.frametype = AST_FRAME_NULL;
05038 p->subs[idx].f.subclass = 0;
05039 p->dialing = 1;
05040 }
05041 p->dop.dialstr[0] = '\0';
05042 ast_setstate(ast, AST_STATE_DIALING);
05043 } else
05044 ast_setstate(ast, AST_STATE_UP);
05045 return &p->subs[idx].f;
05046 case AST_STATE_DOWN:
05047 ast_setstate(ast, AST_STATE_RING);
05048 ast->rings = 1;
05049 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05050 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
05051 ast_debug(1, "channel %d picked up\n", p->channel);
05052 return &p->subs[idx].f;
05053 case AST_STATE_UP:
05054
05055 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05056
05057 if (ast_bridged_channel(p->owner))
05058 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05059 p->subs[idx].needunhold = 1;
05060 break;
05061 case AST_STATE_RESERVED:
05062
05063 if (has_voicemail(p))
05064 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05065 else
05066 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05067 break;
05068 default:
05069 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05070 }
05071 break;
05072 case SIG_FXSLS:
05073 case SIG_FXSGS:
05074 case SIG_FXSKS:
05075 if (ast->_state == AST_STATE_RING) {
05076 p->ringt = p->ringt_base;
05077 }
05078
05079
05080
05081 ast_debug(1, "Setting IDLE polarity due "
05082 "to ring. Old polarity was %d\n",
05083 p->polarity);
05084 p->polarity = POLARITY_IDLE;
05085
05086
05087 case SIG_EM:
05088 case SIG_EM_E1:
05089 case SIG_EMWINK:
05090 case SIG_FEATD:
05091 case SIG_FEATDMF:
05092 case SIG_FEATDMF_TA:
05093 case SIG_E911:
05094 case SIG_FGC_CAMA:
05095 case SIG_FGC_CAMAMF:
05096 case SIG_FEATB:
05097 case SIG_SF:
05098 case SIG_SFWINK:
05099 case SIG_SF_FEATD:
05100 case SIG_SF_FEATDMF:
05101 case SIG_SF_FEATB:
05102 if (ast->_state == AST_STATE_PRERING)
05103 ast_setstate(ast, AST_STATE_RING);
05104 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05105 ast_debug(1, "Ring detected\n");
05106 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05107 p->subs[idx].f.subclass = AST_CONTROL_RING;
05108 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05109 ast_debug(1, "Line answered\n");
05110 if (p->confirmanswer) {
05111 p->subs[idx].f.frametype = AST_FRAME_NULL;
05112 p->subs[idx].f.subclass = 0;
05113 } else {
05114 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05115 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05116 ast_setstate(ast, AST_STATE_UP);
05117 }
05118 } else if (ast->_state != AST_STATE_RING)
05119 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05120 break;
05121 default:
05122 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05123 }
05124 break;
05125 case DAHDI_EVENT_RINGBEGIN:
05126 switch (p->sig) {
05127 case SIG_FXSLS:
05128 case SIG_FXSGS:
05129 case SIG_FXSKS:
05130 if (ast->_state == AST_STATE_RING) {
05131 p->ringt = p->ringt_base;
05132 }
05133 break;
05134 }
05135 break;
05136 case DAHDI_EVENT_RINGEROFF:
05137 if (p->inalarm) break;
05138 if ((p->radio || (p->oprmode < 0))) break;
05139 ast->rings++;
05140 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05141 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05142 ast_free(p->cidspill);
05143 p->cidspill = NULL;
05144 p->callwaitcas = 0;
05145 }
05146 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05147 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05148 break;
05149 case DAHDI_EVENT_RINGERON:
05150 break;
05151 case DAHDI_EVENT_NOALARM:
05152 p->inalarm = 0;
05153 #ifdef HAVE_PRI
05154
05155 if (p->bearer)
05156 p->bearer->inalarm = 0;
05157 #endif
05158 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05159 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05160 "Channel: %d\r\n", p->channel);
05161 break;
05162 case DAHDI_EVENT_WINKFLASH:
05163 if (p->inalarm) break;
05164 if (p->radio) break;
05165 if (p->oprmode < 0) break;
05166 if (p->oprmode > 1)
05167 {
05168 struct dahdi_params par;
05169
05170 memset(&par, 0, sizeof(par));
05171 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05172 {
05173 if (!par.rxisoffhook)
05174 {
05175
05176 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05177 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05178 save_conference(p);
05179 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05180 }
05181 }
05182 break;
05183 }
05184
05185 p->flashtime = ast_tvnow();
05186 switch (mysig) {
05187 case SIG_FXOLS:
05188 case SIG_FXOGS:
05189 case SIG_FXOKS:
05190 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05191 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05192 p->callwaitcas = 0;
05193
05194 if (idx != SUB_REAL) {
05195 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
05196 goto winkflashdone;
05197 }
05198
05199 if (p->subs[SUB_CALLWAIT].owner) {
05200
05201 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05202 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05203 p->owner = p->subs[SUB_REAL].owner;
05204 ast_debug(1, "Making %s the new owner\n", p->owner->name);
05205 if (p->owner->_state == AST_STATE_RINGING) {
05206 ast_setstate(p->owner, AST_STATE_UP);
05207 p->subs[SUB_REAL].needanswer = 1;
05208 }
05209 p->callwaitingrepeat = 0;
05210 p->cidcwexpire = 0;
05211
05212 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05213 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05214 S_OR(p->mohsuggest, NULL),
05215 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05216 }
05217 p->subs[SUB_CALLWAIT].needhold = 1;
05218 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05219 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05220 S_OR(p->mohsuggest, NULL),
05221 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05222 }
05223 p->subs[SUB_REAL].needunhold = 1;
05224 } else if (!p->subs[SUB_THREEWAY].owner) {
05225 if (!p->threewaycalling) {
05226
05227 p->subs[SUB_REAL].needflash = 1;
05228 goto winkflashdone;
05229 } else if (!check_for_conference(p)) {
05230 char cid_num[256];
05231 char cid_name[256];
05232
05233 cid_num[0] = 0;
05234 cid_name[0] = 0;
05235 if (p->dahditrcallerid && p->owner) {
05236 if (p->owner->cid.cid_num)
05237 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05238 if (p->owner->cid.cid_name)
05239 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05240 }
05241
05242
05243 if (!((ast->pbx) ||
05244 (ast->_state == AST_STATE_UP) ||
05245 (ast->_state == AST_STATE_RING))) {
05246 ast_debug(1, "Flash when call not up or ringing\n");
05247 goto winkflashdone;
05248 }
05249 if (alloc_sub(p, SUB_THREEWAY)) {
05250 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05251 goto winkflashdone;
05252 }
05253
05254 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05255 if (p->dahditrcallerid) {
05256 if (!p->origcid_num)
05257 p->origcid_num = ast_strdup(p->cid_num);
05258 if (!p->origcid_name)
05259 p->origcid_name = ast_strdup(p->cid_name);
05260 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05261 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05262 }
05263
05264 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05265
05266 dahdi_disable_ec(p);
05267 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05268 if (res)
05269 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05270 p->owner = chan;
05271 if (!chan) {
05272 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05273 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05274 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05275 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05276 dahdi_enable_ec(p);
05277 ast_hangup(chan);
05278 } else {
05279 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05280 int way3bridge = 0, cdr3way = 0;
05281
05282 if (!other) {
05283 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05284 } else
05285 way3bridge = 1;
05286
05287 if (p->subs[SUB_THREEWAY].owner->cdr)
05288 cdr3way = 1;
05289
05290 ast_verb(3, "Started three way call on channel %d\n", p->channel);
05291
05292
05293 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05294 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05295 S_OR(p->mohsuggest, NULL),
05296 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05297 }
05298 p->subs[SUB_THREEWAY].needhold = 1;
05299 }
05300 }
05301 } else {
05302
05303 if (p->subs[SUB_THREEWAY].inthreeway) {
05304
05305 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05306
05307 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05308
05309 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05310 p->owner = p->subs[SUB_REAL].owner;
05311 }
05312
05313 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05314 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05315 p->subs[SUB_REAL].inthreeway = 0;
05316 p->subs[SUB_THREEWAY].inthreeway = 0;
05317 } else {
05318
05319 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05320 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05321 int otherindex = SUB_THREEWAY;
05322 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05323 int way3bridge = 0, cdr3way = 0;
05324
05325 if (!other) {
05326 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05327 } else
05328 way3bridge = 1;
05329
05330 if (p->subs[SUB_THREEWAY].owner->cdr)
05331 cdr3way = 1;
05332
05333 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05334
05335 p->subs[SUB_THREEWAY].inthreeway = 1;
05336 p->subs[SUB_REAL].inthreeway = 1;
05337 if (ast->_state == AST_STATE_UP) {
05338 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05339 otherindex = SUB_REAL;
05340 }
05341 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05342 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05343 p->subs[otherindex].needunhold = 1;
05344 p->owner = p->subs[SUB_REAL].owner;
05345 if (ast->_state == AST_STATE_RINGING) {
05346 ast_debug(1, "Enabling ringtone on real and threeway\n");
05347 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05348 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05349 }
05350 } else {
05351 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05352 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05353 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05354 p->owner = p->subs[SUB_REAL].owner;
05355 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05356 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05357 p->subs[SUB_REAL].needunhold = 1;
05358 dahdi_enable_ec(p);
05359 }
05360
05361 }
05362 }
05363 winkflashdone:
05364 update_conf(p);
05365 break;
05366 case SIG_EM:
05367 case SIG_EM_E1:
05368 case SIG_FEATD:
05369 case SIG_SF:
05370 case SIG_SFWINK:
05371 case SIG_SF_FEATD:
05372 case SIG_FXSLS:
05373 case SIG_FXSGS:
05374 if (option_debug) {
05375 if (p->dialing)
05376 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05377 else
05378 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05379 }
05380 break;
05381 case SIG_FEATDMF_TA:
05382 switch (p->whichwink) {
05383 case 0:
05384 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05385 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05386 break;
05387 case 1:
05388 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05389 break;
05390 case 2:
05391 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05392 return NULL;
05393 }
05394 p->whichwink++;
05395
05396 case SIG_FEATDMF:
05397 case SIG_E911:
05398 case SIG_FGC_CAMAMF:
05399 case SIG_FGC_CAMA:
05400 case SIG_FEATB:
05401 case SIG_SF_FEATDMF:
05402 case SIG_SF_FEATB:
05403 case SIG_EMWINK:
05404
05405 if (!ast_strlen_zero(p->dop.dialstr)) {
05406 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05407 if (res < 0) {
05408 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05409 p->dop.dialstr[0] = '\0';
05410 return NULL;
05411 } else
05412 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05413 }
05414 p->dop.dialstr[0] = '\0';
05415 break;
05416 default:
05417 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05418 }
05419 break;
05420 case DAHDI_EVENT_HOOKCOMPLETE:
05421 if (p->inalarm) break;
05422 if ((p->radio || (p->oprmode < 0))) break;
05423 switch (mysig) {
05424 case SIG_FXSLS:
05425 case SIG_FXSGS:
05426 case SIG_FXSKS:
05427 case SIG_EM:
05428 case SIG_EM_E1:
05429 case SIG_EMWINK:
05430 case SIG_FEATD:
05431 case SIG_SF:
05432 case SIG_SFWINK:
05433 case SIG_SF_FEATD:
05434 if (!ast_strlen_zero(p->dop.dialstr)) {
05435 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05436 if (res < 0) {
05437 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05438 p->dop.dialstr[0] = '\0';
05439 return NULL;
05440 } else
05441 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05442 }
05443 p->dop.dialstr[0] = '\0';
05444 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05445 break;
05446 case SIG_FEATDMF:
05447 case SIG_FEATDMF_TA:
05448 case SIG_E911:
05449 case SIG_FGC_CAMA:
05450 case SIG_FGC_CAMAMF:
05451 case SIG_FEATB:
05452 case SIG_SF_FEATDMF:
05453 case SIG_SF_FEATB:
05454 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05455 break;
05456 default:
05457 break;
05458 }
05459 break;
05460 case DAHDI_EVENT_POLARITY:
05461
05462
05463
05464
05465
05466
05467
05468
05469
05470 if (p->polarityonanswerdelay > 0) {
05471
05472 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05473 switch (ast->_state) {
05474 case AST_STATE_DIALING:
05475 case AST_STATE_RINGING:
05476 if (p->answeronpolarityswitch) {
05477 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
05478 ast_setstate(p->owner, AST_STATE_UP);
05479 p->polarity = POLARITY_REV;
05480 if (p->hanguponpolarityswitch) {
05481 p->polaritydelaytv = ast_tvnow();
05482 }
05483 } else {
05484 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
05485 }
05486 break;
05487 case AST_STATE_UP:
05488 case AST_STATE_RING:
05489 if (p->hanguponpolarityswitch) {
05490 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
05491 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05492 p->polarity = POLARITY_IDLE;
05493 } else {
05494 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
05495 }
05496 break;
05497
05498 case AST_STATE_DOWN:
05499 case AST_STATE_RESERVED:
05500 case AST_STATE_OFFHOOK:
05501 case AST_STATE_BUSY:
05502 case AST_STATE_DIALING_OFFHOOK:
05503 case AST_STATE_PRERING:
05504 default:
05505 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05506 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
05507 }
05508
05509 }
05510
05511 } else {
05512
05513 switch (ast->_state) {
05514 case AST_STATE_DIALING:
05515 case AST_STATE_RINGING:
05516 if (p->answeronpolarityswitch) {
05517 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
05518 }
05519 break;
05520
05521 case AST_STATE_UP:
05522 case AST_STATE_RING:
05523 if (p->hanguponpolarityswitch) {
05524 ast_debug(1, "Polarity switch detected but NOT hanging up (too close to Answer event) on channel %d, state %d\n", p->channel, ast->_state);
05525 }
05526 break;
05527
05528 default:
05529 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05530 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
05531 }
05532 }
05533 }
05534 }
05535
05536 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) );
05537 break;
05538 default:
05539 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05540 }
05541 return &p->subs[idx].f;
05542 }
05543
05544 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05545 {
05546 struct dahdi_pvt *p = ast->tech_pvt;
05547 int res;
05548 int usedindex=-1;
05549 int idx;
05550 struct ast_frame *f;
05551
05552
05553 idx = dahdi_get_index(ast, p, 1);
05554
05555 p->subs[idx].f.frametype = AST_FRAME_NULL;
05556 p->subs[idx].f.datalen = 0;
05557 p->subs[idx].f.samples = 0;
05558 p->subs[idx].f.mallocd = 0;
05559 p->subs[idx].f.offset = 0;
05560 p->subs[idx].f.subclass = 0;
05561 p->subs[idx].f.delivery = ast_tv(0,0);
05562 p->subs[idx].f.src = "dahdi_exception";
05563 p->subs[idx].f.data.ptr = NULL;
05564
05565
05566 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05567
05568
05569
05570
05571
05572 if (p->fake_event) {
05573 res = p->fake_event;
05574 p->fake_event = 0;
05575 } else
05576 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05577
05578 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05579 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05580 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05581 p->owner = p->subs[SUB_REAL].owner;
05582 if (p->owner && ast_bridged_channel(p->owner))
05583 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05584 p->subs[SUB_REAL].needunhold = 1;
05585 }
05586 switch (res) {
05587 case DAHDI_EVENT_ONHOOK:
05588 dahdi_disable_ec(p);
05589 if (p->owner) {
05590 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05591 dahdi_ring_phone(p);
05592 p->callwaitingrepeat = 0;
05593 p->cidcwexpire = 0;
05594 } else
05595 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05596 update_conf(p);
05597 break;
05598 case DAHDI_EVENT_RINGOFFHOOK:
05599 dahdi_enable_ec(p);
05600 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05601 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05602 p->subs[SUB_REAL].needanswer = 1;
05603 p->dialing = 0;
05604 }
05605 break;
05606 case DAHDI_EVENT_HOOKCOMPLETE:
05607 case DAHDI_EVENT_RINGERON:
05608 case DAHDI_EVENT_RINGEROFF:
05609
05610 break;
05611 case DAHDI_EVENT_WINKFLASH:
05612 p->flashtime = ast_tvnow();
05613 if (p->owner) {
05614 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05615 if (p->owner->_state != AST_STATE_UP) {
05616
05617 usedindex = dahdi_get_index(p->owner, p, 0);
05618 if (usedindex > -1) {
05619 p->subs[usedindex].needanswer = 1;
05620 }
05621 ast_setstate(p->owner, AST_STATE_UP);
05622 }
05623 p->callwaitingrepeat = 0;
05624 p->cidcwexpire = 0;
05625 if (ast_bridged_channel(p->owner))
05626 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05627 p->subs[SUB_REAL].needunhold = 1;
05628 } else
05629 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05630 update_conf(p);
05631 break;
05632 default:
05633 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05634 }
05635 f = &p->subs[idx].f;
05636 return f;
05637 }
05638 if (!(p->radio || (p->oprmode < 0)))
05639 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05640
05641 if (ast != p->owner) {
05642 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05643 f = &p->subs[idx].f;
05644 return f;
05645 }
05646 f = dahdi_handle_event(ast);
05647 return f;
05648 }
05649
05650 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05651 {
05652 struct dahdi_pvt *p = ast->tech_pvt;
05653 struct ast_frame *f;
05654 ast_mutex_lock(&p->lock);
05655 f = __dahdi_exception(ast);
05656 ast_mutex_unlock(&p->lock);
05657 return f;
05658 }
05659
05660 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05661 {
05662 struct dahdi_pvt *p = ast->tech_pvt;
05663 int res;
05664 int idx;
05665 void *readbuf;
05666 struct ast_frame *f;
05667
05668 while (ast_mutex_trylock(&p->lock)) {
05669 CHANNEL_DEADLOCK_AVOIDANCE(ast);
05670 }
05671
05672 idx = dahdi_get_index(ast, p, 0);
05673
05674
05675 if (idx < 0) {
05676 ast_log(LOG_WARNING, "We dont exist?\n");
05677 ast_mutex_unlock(&p->lock);
05678 return NULL;
05679 }
05680
05681 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
05682
05683 p->subs[idx].f.frametype = AST_FRAME_NULL;
05684 p->subs[idx].f.datalen = 0;
05685 p->subs[idx].f.samples = 0;
05686 p->subs[idx].f.mallocd = 0;
05687 p->subs[idx].f.offset = 0;
05688 p->subs[idx].f.subclass = 0;
05689 p->subs[idx].f.delivery = ast_tv(0,0);
05690 p->subs[idx].f.src = "dahdi_read";
05691 p->subs[idx].f.data.ptr = NULL;
05692
05693
05694 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05695 {
05696 struct dahdi_params ps;
05697
05698 memset(&ps, 0, sizeof(ps));
05699 ps.channo = p->channel;
05700 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05701 ast_mutex_unlock(&p->lock);
05702 return NULL;
05703 }
05704 p->firstradio = 1;
05705 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05706 if (ps.rxisoffhook)
05707 {
05708 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
05709 }
05710 else
05711 {
05712 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05713 }
05714 ast_mutex_unlock(&p->lock);
05715 return &p->subs[idx].f;
05716 }
05717 if (p->ringt == 1) {
05718 ast_mutex_unlock(&p->lock);
05719 return NULL;
05720 }
05721 else if (p->ringt > 0)
05722 p->ringt--;
05723
05724 if (p->subs[idx].needringing) {
05725
05726 p->subs[idx].needringing = 0;
05727 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05728 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05729 ast_setstate(ast, AST_STATE_RINGING);
05730 ast_mutex_unlock(&p->lock);
05731 return &p->subs[idx].f;
05732 }
05733
05734 if (p->subs[idx].needbusy) {
05735
05736 p->subs[idx].needbusy = 0;
05737 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05738 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
05739 ast_mutex_unlock(&p->lock);
05740 return &p->subs[idx].f;
05741 }
05742
05743 if (p->subs[idx].needcongestion) {
05744
05745 p->subs[idx].needcongestion = 0;
05746 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05747 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
05748 ast_mutex_unlock(&p->lock);
05749 return &p->subs[idx].f;
05750 }
05751
05752 if (p->subs[idx].needcallerid) {
05753 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05754 S_OR(p->lastcid_name, NULL),
05755 S_OR(p->lastcid_num, NULL)
05756 );
05757 p->subs[idx].needcallerid = 0;
05758 }
05759
05760 if (p->subs[idx].needanswer) {
05761
05762 p->subs[idx].needanswer = 0;
05763 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05764 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05765 ast_mutex_unlock(&p->lock);
05766 return &p->subs[idx].f;
05767 }
05768
05769 if (p->subs[idx].needflash) {
05770
05771 p->subs[idx].needflash = 0;
05772 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05773 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
05774 ast_mutex_unlock(&p->lock);
05775 return &p->subs[idx].f;
05776 }
05777
05778 if (p->subs[idx].needhold) {
05779
05780 p->subs[idx].needhold = 0;
05781 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05782 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
05783 ast_mutex_unlock(&p->lock);
05784 ast_debug(1, "Sending hold on '%s'\n", ast->name);
05785 return &p->subs[idx].f;
05786 }
05787
05788 if (p->subs[idx].needunhold) {
05789
05790 p->subs[idx].needunhold = 0;
05791 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05792 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
05793 ast_mutex_unlock(&p->lock);
05794 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05795 return &p->subs[idx].f;
05796 }
05797
05798 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05799 if (!p->subs[idx].linear) {
05800 p->subs[idx].linear = 1;
05801 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05802 if (res)
05803 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
05804 }
05805 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05806 (ast->rawreadformat == AST_FORMAT_ALAW)) {
05807 if (p->subs[idx].linear) {
05808 p->subs[idx].linear = 0;
05809 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05810 if (res)
05811 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
05812 }
05813 } else {
05814 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05815 ast_mutex_unlock(&p->lock);
05816 return NULL;
05817 }
05818 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
05819 CHECK_BLOCKING(ast);
05820 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05821 ast_clear_flag(ast, AST_FLAG_BLOCKING);
05822
05823 if (res < 0) {
05824 f = NULL;
05825 if (res == -1) {
05826 if (errno == EAGAIN) {
05827
05828 ast_mutex_unlock(&p->lock);
05829 return &p->subs[idx].f;
05830 } else if (errno == ELAST) {
05831 f = __dahdi_exception(ast);
05832 } else
05833 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05834 }
05835 ast_mutex_unlock(&p->lock);
05836 return f;
05837 }
05838 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
05839 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05840 f = __dahdi_exception(ast);
05841 ast_mutex_unlock(&p->lock);
05842 return f;
05843 }
05844 if (p->tdd) {
05845 int c;
05846
05847 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05848 if (c < 0) {
05849 ast_debug(1,"tdd_feed failed\n");
05850 ast_mutex_unlock(&p->lock);
05851 return NULL;
05852 }
05853 if (c) {
05854 p->subs[idx].f.subclass = 0;
05855 p->subs[idx].f.frametype = AST_FRAME_TEXT;
05856 p->subs[idx].f.mallocd = 0;
05857 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05858 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
05859 p->subs[idx].f.datalen = 1;
05860 *((char *) p->subs[idx].f.data.ptr) = c;
05861 ast_mutex_unlock(&p->lock);
05862 return &p->subs[idx].f;
05863 }
05864 }
05865
05866 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05867 p->callwaitingrepeat--;
05868 }
05869 if (p->cidcwexpire)
05870 p->cidcwexpire--;
05871
05872 if (p->callwaitingrepeat == 1) {
05873 p->callwaitrings++;
05874 dahdi_callwait(ast);
05875 }
05876
05877 if (p->cidcwexpire == 1) {
05878 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05879 restore_conference(p);
05880 }
05881 if (p->subs[idx].linear) {
05882 p->subs[idx].f.datalen = READ_SIZE * 2;
05883 } else
05884 p->subs[idx].f.datalen = READ_SIZE;
05885
05886
05887 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05888 send_callerid(p);
05889 }
05890
05891 p->subs[idx].f.frametype = AST_FRAME_VOICE;
05892 p->subs[idx].f.subclass = ast->rawreadformat;
05893 p->subs[idx].f.samples = READ_SIZE;
05894 p->subs[idx].f.mallocd = 0;
05895 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05896 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
05897 #if 0
05898 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
05899 #endif
05900 if (p->dialing ||
05901 (idx && (ast->_state != AST_STATE_UP)) ||
05902 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05903 ) {
05904
05905
05906 p->subs[idx].f.frametype = AST_FRAME_NULL;
05907 p->subs[idx].f.subclass = 0;
05908 p->subs[idx].f.samples = 0;
05909 p->subs[idx].f.mallocd = 0;
05910 p->subs[idx].f.offset = 0;
05911 p->subs[idx].f.data.ptr = NULL;
05912 p->subs[idx].f.datalen= 0;
05913 }
05914 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) {
05915
05916 int mute;
05917
05918 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
05919
05920
05921 mute = ast_dsp_was_muted(p->dsp);
05922 if (p->muting != mute) {
05923 p->muting = mute;
05924 dahdi_confmute(p, mute);
05925 }
05926
05927 if (f) {
05928 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05929 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05930
05931
05932 f = NULL;
05933 }
05934 } else if (f->frametype == AST_FRAME_DTMF) {
05935 #ifdef HAVE_PRI
05936 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
05937 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05938 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05939
05940 f->frametype = AST_FRAME_NULL;
05941 f->subclass = 0;
05942 }
05943 #endif
05944
05945 p->pulsedial = 0;
05946 }
05947 }
05948 } else
05949 f = &p->subs[idx].f;
05950
05951 if (f && (f->frametype == AST_FRAME_DTMF))
05952 dahdi_handle_dtmfup(ast, idx, &f);
05953
05954
05955 if (p->fake_event)
05956 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05957
05958 ast_mutex_unlock(&p->lock);
05959 return f;
05960 }
05961
05962 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
05963 {
05964 int sent=0;
05965 int size;
05966 int res;
05967 int fd;
05968 fd = p->subs[idx].dfd;
05969 while (len) {
05970 size = len;
05971 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05972 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05973 res = write(fd, buf, size);
05974 if (res != size) {
05975 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05976 return sent;
05977 }
05978 len -= size;
05979 buf += size;
05980 }
05981 return sent;
05982 }
05983
05984 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05985 {
05986 struct dahdi_pvt *p = ast->tech_pvt;
05987 int res;
05988 int idx;
05989 idx = dahdi_get_index(ast, p, 0);
05990 if (idx < 0) {
05991 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05992 return -1;
05993 }
05994
05995 #if 0
05996 #ifdef HAVE_PRI
05997 ast_mutex_lock(&p->lock);
05998 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05999 if (p->pri->pri) {
06000 if (!pri_grab(p, p->pri)) {
06001 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06002 pri_rel(p->pri);
06003 } else
06004 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06005 }
06006 p->proceeding=1;
06007 }
06008 ast_mutex_unlock(&p->lock);
06009 #endif
06010 #endif
06011
06012 if (frame->frametype != AST_FRAME_VOICE) {
06013 if (frame->frametype != AST_FRAME_IMAGE)
06014 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06015 return 0;
06016 }
06017 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06018 (frame->subclass != AST_FORMAT_ULAW) &&
06019 (frame->subclass != AST_FORMAT_ALAW)) {
06020 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06021 return -1;
06022 }
06023 if (p->dialing) {
06024 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06025 return 0;
06026 }
06027 if (!p->owner) {
06028 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06029 return 0;
06030 }
06031 if (p->cidspill) {
06032 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06033 return 0;
06034 }
06035
06036 if (!frame->data.ptr || !frame->datalen)
06037 return 0;
06038
06039 if (frame->subclass == AST_FORMAT_SLINEAR) {
06040 if (!p->subs[idx].linear) {
06041 p->subs[idx].linear = 1;
06042 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06043 if (res)
06044 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06045 }
06046 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
06047 } else {
06048
06049 if (p->subs[idx].linear) {
06050 p->subs[idx].linear = 0;
06051 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06052 if (res)
06053 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06054 }
06055 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
06056 }
06057 if (res < 0) {
06058 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06059 return -1;
06060 }
06061 return 0;
06062 }
06063
06064 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06065 {
06066 struct dahdi_pvt *p = chan->tech_pvt;
06067 int res=-1;
06068 int idx;
06069 int func = DAHDI_FLASH;
06070 ast_mutex_lock(&p->lock);
06071 idx = dahdi_get_index(chan, p, 0);
06072 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06073 if (idx == SUB_REAL) {
06074 switch (condition) {
06075 case AST_CONTROL_BUSY:
06076 #ifdef HAVE_PRI
06077 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06078 chan->hangupcause = AST_CAUSE_USER_BUSY;
06079 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06080 res = 0;
06081 } else if (!p->progress &&
06082 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06083 && p->pri && !p->outgoing) {
06084 if (p->pri->pri) {
06085 if (!pri_grab(p, p->pri)) {
06086 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06087 pri_rel(p->pri);
06088 }
06089 else
06090 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06091 }
06092 p->progress = 1;
06093 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06094 } else
06095 #endif
06096 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06097 break;
06098 case AST_CONTROL_RINGING:
06099 #ifdef HAVE_PRI
06100 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06101 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06102 if (p->pri->pri) {
06103 if (!pri_grab(p, p->pri)) {
06104 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06105 pri_rel(p->pri);
06106 }
06107 else
06108 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06109 }
06110 p->alerting = 1;
06111 }
06112
06113 #endif
06114 #ifdef HAVE_SS7
06115 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06116 if (p->ss7->ss7) {
06117 ss7_grab(p, p->ss7);
06118
06119 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06120 p->rlt = 1;
06121 if (p->rlt != 1)
06122 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06123 p->alerting = 1;
06124 ss7_rel(p->ss7);
06125 }
06126 }
06127 #endif
06128
06129 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
06130
06131 if (chan->_state != AST_STATE_UP) {
06132 if ((chan->_state != AST_STATE_RING) ||
06133 ((p->sig != SIG_FXSKS) &&
06134 (p->sig != SIG_FXSLS) &&
06135 (p->sig != SIG_FXSGS)))
06136 ast_setstate(chan, AST_STATE_RINGING);
06137 }
06138 break;
06139 case AST_CONTROL_PROCEEDING:
06140 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06141 #ifdef HAVE_PRI
06142 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06143 && p->pri && !p->outgoing) {
06144 if (p->pri->pri) {
06145 if (!pri_grab(p, p->pri)) {
06146 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06147 pri_rel(p->pri);
06148 }
06149 else
06150 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06151 }
06152 p->proceeding = 1;
06153 p->dialing = 0;
06154 }
06155 #endif
06156 #ifdef HAVE_SS7
06157
06158 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
06159 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06160 p->rlt = 1;
06161 }
06162
06163 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
06164 if (p->ss7->ss7) {
06165 ss7_grab(p, p->ss7);
06166 isup_acm(p->ss7->ss7, p->ss7call);
06167 p->proceeding = 1;
06168 ss7_rel(p->ss7);
06169
06170 }
06171 }
06172 #endif
06173
06174 res = 0;
06175 break;
06176 case AST_CONTROL_PROGRESS:
06177 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06178 #ifdef HAVE_PRI
06179 p->digital = 0;
06180 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06181 && p->pri && !p->outgoing) {
06182 if (p->pri->pri) {
06183 if (!pri_grab(p, p->pri)) {
06184 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06185 pri_rel(p->pri);
06186 }
06187 else
06188 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06189 }
06190 p->progress = 1;
06191 }
06192 #endif
06193 #ifdef HAVE_SS7
06194 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
06195 if (p->ss7->ss7) {
06196 ss7_grab(p, p->ss7);
06197 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
06198 p->progress = 1;
06199 ss7_rel(p->ss7);
06200
06201 dahdi_enable_ec(p);
06202
06203 }
06204 }
06205 #endif
06206
06207 res = 0;
06208 break;
06209 case AST_CONTROL_CONGESTION:
06210 chan->hangupcause = AST_CAUSE_CONGESTION;
06211 #ifdef HAVE_PRI
06212 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06213 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06214 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06215 res = 0;
06216 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06217 && p->pri && !p->outgoing) {
06218 if (p->pri) {
06219 if (!pri_grab(p, p->pri)) {
06220 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06221 pri_rel(p->pri);
06222 } else
06223 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06224 }
06225 p->progress = 1;
06226 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06227 } else
06228 #endif
06229 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06230 break;
06231 case AST_CONTROL_HOLD:
06232 #ifdef HAVE_PRI
06233 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06234 if (!pri_grab(p, p->pri)) {
06235 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06236 pri_rel(p->pri);
06237 } else
06238 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06239 } else
06240 #endif
06241 ast_moh_start(chan, data, p->mohinterpret);
06242 break;
06243 case AST_CONTROL_UNHOLD:
06244 #ifdef HAVE_PRI
06245 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06246 if (!pri_grab(p, p->pri)) {
06247 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06248 pri_rel(p->pri);
06249 } else
06250 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06251 } else
06252 #endif
06253 ast_moh_stop(chan);
06254 break;
06255 case AST_CONTROL_RADIO_KEY:
06256 if (p->radio)
06257 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06258 res = 0;
06259 break;
06260 case AST_CONTROL_RADIO_UNKEY:
06261 if (p->radio)
06262 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
06263 res = 0;
06264 break;
06265 case AST_CONTROL_FLASH:
06266
06267 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06268
06269 p->dop.dialstr[0] = '\0';
06270 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06271 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06272 chan->name, strerror(errno));
06273 } else
06274 res = 0;
06275 } else
06276 res = 0;
06277 break;
06278 case AST_CONTROL_SRCUPDATE:
06279 res = 0;
06280 break;
06281 case -1:
06282 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06283 break;
06284 }
06285 } else
06286 res = 0;
06287 ast_mutex_unlock(&p->lock);
06288 return res;
06289 }
06290
06291 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
06292 {
06293 struct ast_channel *tmp;
06294 int deflaw;
06295 int res;
06296 int x,y;
06297 int features;
06298 struct ast_str *chan_name;
06299 struct ast_variable *v;
06300 struct dahdi_params ps;
06301 if (i->subs[idx].owner) {
06302 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
06303 return NULL;
06304 }
06305 y = 1;
06306 chan_name = ast_str_alloca(32);
06307 do {
06308 #ifdef HAVE_PRI
06309 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06310 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06311 else
06312 #endif
06313 if (i->channel == CHAN_PSEUDO)
06314 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
06315 else
06316 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
06317 for (x = 0; x < 3; x++) {
06318 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
06319 break;
06320 }
06321 y++;
06322 } while (x < 3);
06323 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);
06324 if (!tmp)
06325 return NULL;
06326 tmp->tech = &dahdi_tech;
06327 memset(&ps, 0, sizeof(ps));
06328 ps.channo = i->channel;
06329 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06330 if (res) {
06331 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06332 ps.curlaw = DAHDI_LAW_MULAW;
06333 }
06334 if (ps.curlaw == DAHDI_LAW_ALAW)
06335 deflaw = AST_FORMAT_ALAW;
06336 else
06337 deflaw = AST_FORMAT_ULAW;
06338 if (law) {
06339 if (law == DAHDI_LAW_ALAW)
06340 deflaw = AST_FORMAT_ALAW;
06341 else
06342 deflaw = AST_FORMAT_ULAW;
06343 }
06344 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
06345 tmp->nativeformats = deflaw;
06346
06347 tmp->rawreadformat = deflaw;
06348 tmp->readformat = deflaw;
06349 tmp->rawwriteformat = deflaw;
06350 tmp->writeformat = deflaw;
06351 i->subs[idx].linear = 0;
06352 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
06353 features = 0;
06354 if (idx == SUB_REAL) {
06355 if (i->busydetect && CANBUSYDETECT(i))
06356 features |= DSP_FEATURE_BUSY_DETECT;
06357 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
06358 features |= DSP_FEATURE_CALL_PROGRESS;
06359 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
06360 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
06361 features |= DSP_FEATURE_FAX_DETECT;
06362 }
06363 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06364 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
06365 i->hardwaredtmf = 0;
06366 features |= DSP_FEATURE_DIGIT_DETECT;
06367 } else if (NEED_MFDETECT(i)) {
06368 i->hardwaredtmf = 1;
06369 features |= DSP_FEATURE_DIGIT_DETECT;
06370 }
06371 }
06372 if (features) {
06373 if (i->dsp) {
06374 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
06375 } else {
06376 if (i->channel != CHAN_PSEUDO)
06377 i->dsp = ast_dsp_new();
06378 else
06379 i->dsp = NULL;
06380 if (i->dsp) {
06381 i->dsp_features = features;
06382 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06383
06384 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
06385
06386
06387 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06388 features = 0;
06389 }
06390 #endif
06391 ast_dsp_set_features(i->dsp, features);
06392 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06393 if (!ast_strlen_zero(progzone))
06394 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06395 if (i->busydetect && CANBUSYDETECT(i)) {
06396 ast_dsp_set_busy_count(i->dsp, i->busycount);
06397 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
06398 }
06399 }
06400 }
06401 }
06402
06403 if (state == AST_STATE_RING)
06404 tmp->rings = 1;
06405 tmp->tech_pvt = i;
06406 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06407
06408 tmp->callgroup = i->callgroup;
06409 tmp->pickupgroup = i->pickupgroup;
06410 }
06411 if (!ast_strlen_zero(i->parkinglot))
06412 ast_string_field_set(tmp, parkinglot, i->parkinglot);
06413 if (!ast_strlen_zero(i->language))
06414 ast_string_field_set(tmp, language, i->language);
06415 if (!i->owner)
06416 i->owner = tmp;
06417 if (!ast_strlen_zero(i->accountcode))
06418 ast_string_field_set(tmp, accountcode, i->accountcode);
06419 if (i->amaflags)
06420 tmp->amaflags = i->amaflags;
06421 i->subs[idx].owner = tmp;
06422 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06423 ast_string_field_set(tmp, call_forward, i->call_forward);
06424
06425 if (!i->adsi)
06426 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06427 if (!ast_strlen_zero(i->exten))
06428 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06429 if (!ast_strlen_zero(i->rdnis))
06430 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06431 if (!ast_strlen_zero(i->dnid))
06432 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06433
06434
06435
06436 #ifdef PRI_ANI
06437 if (!ast_strlen_zero(i->cid_ani))
06438 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06439 else
06440 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06441 #else
06442 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06443 #endif
06444 tmp->cid.cid_pres = i->callingpres;
06445 tmp->cid.cid_ton = i->cid_ton;
06446 tmp->cid.cid_ani2 = i->cid_ani2;
06447 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06448 tmp->transfercapability = transfercapability;
06449 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06450 if (transfercapability & AST_TRANS_CAP_DIGITAL)
06451 i->digital = 1;
06452
06453 i->isidlecall = 0;
06454 i->alreadyhungup = 0;
06455 #endif
06456
06457 i->fake_event = 0;
06458
06459 dahdi_confmute(i, 0);
06460 i->muting = 0;
06461
06462 ast_jb_configure(tmp, &global_jbconf);
06463
06464 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
06465
06466 for (v = i->vars ; v ; v = v->next)
06467 pbx_builtin_setvar_helper(tmp, v->name, v->value);
06468
06469 if (startpbx) {
06470 if (ast_pbx_start(tmp)) {
06471 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06472 ast_hangup(tmp);
06473 i->owner = NULL;
06474 return NULL;
06475 }
06476 }
06477
06478 ast_module_ref(ast_module_info->self);
06479 return tmp;
06480 }
06481
06482
06483 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06484 {
06485 char c;
06486
06487 *str = 0;
06488 for (;;)
06489 {
06490
06491 c = ast_waitfordigit(chan, ms);
06492
06493 if (c < 1)
06494 return c;
06495 *str++ = c;
06496 *str = 0;
06497 if (strchr(term, c))
06498 return 1;
06499 }
06500 }
06501
06502 static int dahdi_wink(struct dahdi_pvt *p, int idx)
06503 {
06504 int j;
06505 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
06506 for (;;)
06507 {
06508
06509 j = DAHDI_IOMUX_SIGEVENT;
06510
06511 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06512
06513 if (j & DAHDI_IOMUX_SIGEVENT) break;
06514 }
06515
06516 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06517 return 0;
06518 }
06519
06520
06521
06522
06523
06524
06525
06526
06527
06528
06529 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
06530 {
06531
06532 dahdichan->dnd = on;
06533 ast_verb(3, "%s DND on channel %d\n",
06534 on? "Enabled" : "Disabled",
06535 dahdichan->channel);
06536 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06537 "Channel: DAHDI/%d\r\n"
06538 "Status: %s\r\n", dahdichan->channel,
06539 on? "enabled" : "disabled");
06540 }
06541
06542 static void *ss_thread(void *data)
06543 {
06544 struct ast_channel *chan = data;
06545 struct dahdi_pvt *p = chan->tech_pvt;
06546 char exten[AST_MAX_EXTENSION] = "";
06547 char exten2[AST_MAX_EXTENSION] = "";
06548 unsigned char buf[256];
06549 char dtmfcid[300];
06550 char dtmfbuf[300];
06551 struct callerid_state *cs = NULL;
06552 char *name = NULL, *number = NULL;
06553 int distMatches;
06554 int curRingData[3];
06555 int receivedRingT;
06556 int counter1;
06557 int counter;
06558 int samples = 0;
06559 struct ast_smdi_md_message *smdi_msg = NULL;
06560 int flags;
06561 int i;
06562 int timeout;
06563 int getforward = 0;
06564 char *s1, *s2;
06565 int len = 0;
06566 int res;
06567 int idx;
06568
06569 ast_mutex_lock(&ss_thread_lock);
06570 ss_thread_count++;
06571 ast_mutex_unlock(&ss_thread_lock);
06572
06573
06574
06575 if (!p) {
06576 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06577 ast_hangup(chan);
06578 goto quit;
06579 }
06580 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
06581 idx = dahdi_get_index(chan, p, 1);
06582 if (idx < 0) {
06583 ast_log(LOG_WARNING, "Huh?\n");
06584 ast_hangup(chan);
06585 goto quit;
06586 }
06587 if (p->dsp)
06588 ast_dsp_digitreset(p->dsp);
06589 switch (p->sig) {
06590 #ifdef HAVE_PRI
06591 case SIG_PRI:
06592 case SIG_BRI:
06593 case SIG_BRI_PTMP:
06594
06595 ast_copy_string(exten, p->exten, sizeof(exten));
06596 len = strlen(exten);
06597 res = 0;
06598 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06599 if (len && !ast_ignore_pattern(chan->context, exten))
06600 tone_zone_play_tone(p->subs[idx].dfd, -1);
06601 else
06602 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06603 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06604 timeout = matchdigittimeout;
06605 else
06606 timeout = gendigittimeout;
06607 res = ast_waitfordigit(chan, timeout);
06608 if (res < 0) {
06609 ast_debug(1, "waitfordigit returned < 0...\n");
06610 ast_hangup(chan);
06611 goto quit;
06612 } else if (res) {
06613 exten[len++] = res;
06614 exten[len] = '\0';
06615 } else
06616 break;
06617 }
06618
06619 if (ast_strlen_zero(exten)) {
06620 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
06621 exten[0] = 's';
06622 exten[1] = '\0';
06623 }
06624 tone_zone_play_tone(p->subs[idx].dfd, -1);
06625 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06626
06627 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06628 if (p->dsp) ast_dsp_digitreset(p->dsp);
06629 dahdi_enable_ec(p);
06630 ast_setstate(chan, AST_STATE_RING);
06631 res = ast_pbx_run(chan);
06632 if (res) {
06633 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06634 }
06635 } else {
06636 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06637 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06638 ast_hangup(chan);
06639 p->exten[0] = '\0';
06640
06641 p->call = NULL;
06642 }
06643 goto quit;
06644 break;
06645 #endif
06646 case SIG_FEATD:
06647 case SIG_FEATDMF:
06648 case SIG_FEATDMF_TA:
06649 case SIG_E911:
06650 case SIG_FGC_CAMAMF:
06651 case SIG_FEATB:
06652 case SIG_EMWINK:
06653 case SIG_SF_FEATD:
06654 case SIG_SF_FEATDMF:
06655 case SIG_SF_FEATB:
06656 case SIG_SFWINK:
06657 if (dahdi_wink(p, idx))
06658 goto quit;
06659
06660 case SIG_EM:
06661 case SIG_EM_E1:
06662 case SIG_SF:
06663 case SIG_FGC_CAMA:
06664 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06665 if (p->dsp)
06666 ast_dsp_digitreset(p->dsp);
06667
06668 if (p->dsp) {
06669 if (NEED_MFDETECT(p))
06670 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06671 else
06672 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06673 }
06674 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06675
06676 if (!p->immediate)
06677
06678 res = ast_waitfordigit(chan, 5000);
06679 else
06680 res = 0;
06681 if (res > 0) {
06682
06683 dtmfbuf[0] = res;
06684 switch (p->sig) {
06685 case SIG_FEATD:
06686 case SIG_SF_FEATD:
06687 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06688 if (res > 0)
06689 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06690 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06691 break;
06692 case SIG_FEATDMF_TA:
06693 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06694 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06695 if (dahdi_wink(p, idx)) goto quit;
06696 dtmfbuf[0] = 0;
06697
06698 res = ast_waitfordigit(chan, 5000);
06699 if (res <= 0) break;
06700 dtmfbuf[0] = res;
06701
06702 case SIG_FEATDMF:
06703 case SIG_E911:
06704 case SIG_FGC_CAMAMF:
06705 case SIG_SF_FEATDMF:
06706 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06707
06708 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06709 {
06710 if (dahdi_wink(p, idx)) goto quit;
06711 dtmfbuf[0] = 0;
06712
06713 res = ast_waitfordigit(chan, 5000);
06714 if (res <= 0) break;
06715 dtmfbuf[0] = res;
06716 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06717 }
06718 if (res > 0) {
06719
06720 if (p->sig == SIG_E911)
06721 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06722 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06723 }
06724 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06725 break;
06726 case SIG_FEATB:
06727 case SIG_SF_FEATB:
06728 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06729 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06730 break;
06731 case SIG_EMWINK:
06732
06733
06734
06735
06736 if (res == '*') {
06737 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06738 if (res > 0)
06739 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06740 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06741 break;
06742 }
06743 default:
06744
06745 len = 1;
06746 dtmfbuf[len] = '\0';
06747 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06748 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06749 timeout = matchdigittimeout;
06750 } else {
06751 timeout = gendigittimeout;
06752 }
06753 res = ast_waitfordigit(chan, timeout);
06754 if (res < 0) {
06755 ast_debug(1, "waitfordigit returned < 0...\n");
06756 ast_hangup(chan);
06757 goto quit;
06758 } else if (res) {
06759 dtmfbuf[len++] = res;
06760 dtmfbuf[len] = '\0';
06761 } else {
06762 break;
06763 }
06764 }
06765 break;
06766 }
06767 }
06768 if (res == -1) {
06769 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06770 ast_hangup(chan);
06771 goto quit;
06772 } else if (res < 0) {
06773 ast_debug(1, "Got hung up before digits finished\n");
06774 ast_hangup(chan);
06775 goto quit;
06776 }
06777
06778 if (p->sig == SIG_FGC_CAMA) {
06779 char anibuf[100];
06780
06781 if (ast_safe_sleep(chan,1000) == -1) {
06782 ast_hangup(chan);
06783 goto quit;
06784 }
06785 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06786 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06787 res = my_getsigstr(chan, anibuf, "#", 10000);
06788 if ((res > 0) && (strlen(anibuf) > 2)) {
06789 if (anibuf[strlen(anibuf) - 1] == '#')
06790 anibuf[strlen(anibuf) - 1] = 0;
06791 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06792 }
06793 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06794 }
06795
06796 ast_copy_string(exten, dtmfbuf, sizeof(exten));
06797 if (ast_strlen_zero(exten))
06798 ast_copy_string(exten, "s", sizeof(exten));
06799 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06800
06801 if (exten[0] == '*') {
06802 char *stringp=NULL;
06803 ast_copy_string(exten2, exten, sizeof(exten2));
06804
06805 stringp=exten2 +1;
06806 s1 = strsep(&stringp, "*");
06807 s2 = strsep(&stringp, "*");
06808 if (s2) {
06809 if (!ast_strlen_zero(p->cid_num))
06810 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06811 else
06812 ast_set_callerid(chan, s1, NULL, s1);
06813 ast_copy_string(exten, s2, sizeof(exten));
06814 } else
06815 ast_copy_string(exten, s1, sizeof(exten));
06816 } else if (p->sig == SIG_FEATD)
06817 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06818 }
06819 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06820 if (exten[0] == '*') {
06821 char *stringp=NULL;
06822 ast_copy_string(exten2, exten, sizeof(exten2));
06823
06824 stringp=exten2 +1;
06825 s1 = strsep(&stringp, "#");
06826 s2 = strsep(&stringp, "#");
06827 if (s2) {
06828 if (!ast_strlen_zero(p->cid_num))
06829 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06830 else
06831 if (*(s1 + 2))
06832 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06833 ast_copy_string(exten, s2 + 1, sizeof(exten));
06834 } else
06835 ast_copy_string(exten, s1 + 2, sizeof(exten));
06836 } else
06837 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06838 }
06839 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06840 if (exten[0] == '*') {
06841 char *stringp=NULL;
06842 ast_copy_string(exten2, exten, sizeof(exten2));
06843
06844 stringp=exten2 +1;
06845 s1 = strsep(&stringp, "#");
06846 s2 = strsep(&stringp, "#");
06847 if (s2 && (*(s2 + 1) == '0')) {
06848 if (*(s2 + 2))
06849 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06850 }
06851 if (s1) ast_copy_string(exten, s1, sizeof(exten));
06852 else ast_copy_string(exten, "911", sizeof(exten));
06853 } else
06854 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
06855 }
06856 if (p->sig == SIG_FEATB) {
06857 if (exten[0] == '*') {
06858 char *stringp=NULL;
06859 ast_copy_string(exten2, exten, sizeof(exten2));
06860
06861 stringp=exten2 +1;
06862 s1 = strsep(&stringp, "#");
06863 ast_copy_string(exten, exten2 + 1, sizeof(exten));
06864 } else
06865 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
06866 }
06867 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06868 dahdi_wink(p, idx);
06869
06870
06871
06872 if (ast_safe_sleep(chan,100)) goto quit;
06873 }
06874 dahdi_enable_ec(p);
06875 if (NEED_MFDETECT(p)) {
06876 if (p->dsp) {
06877 if (!p->hardwaredtmf)
06878 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06879 else {
06880 ast_dsp_free(p->dsp);
06881 p->dsp = NULL;
06882 }
06883 }
06884 }
06885
06886 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06887 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06888 if (p->dsp) ast_dsp_digitreset(p->dsp);
06889 res = ast_pbx_run(chan);
06890 if (res) {
06891 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06892 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06893 }
06894 goto quit;
06895 } else {
06896 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06897 sleep(2);
06898 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
06899 if (res < 0)
06900 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06901 else
06902 sleep(1);
06903 res = ast_streamfile(chan, "ss-noservice", chan->language);
06904 if (res >= 0)
06905 ast_waitstream(chan, "");
06906 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06907 ast_hangup(chan);
06908 goto quit;
06909 }
06910 break;
06911 case SIG_FXOLS:
06912 case SIG_FXOGS:
06913 case SIG_FXOKS:
06914
06915 timeout = firstdigittimeout;
06916
06917
06918 if (p->subs[SUB_THREEWAY].owner)
06919 timeout = 999999;
06920 while (len < AST_MAX_EXTENSION-1) {
06921
06922
06923 if (p->immediate)
06924 res = 's';
06925 else
06926 res = ast_waitfordigit(chan, timeout);
06927 timeout = 0;
06928 if (res < 0) {
06929 ast_debug(1, "waitfordigit returned < 0...\n");
06930 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06931 ast_hangup(chan);
06932 goto quit;
06933 } else if (res) {
06934 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
06935 exten[len++]=res;
06936 exten[len] = '\0';
06937 }
06938 if (!ast_ignore_pattern(chan->context, exten))
06939 tone_zone_play_tone(p->subs[idx].dfd, -1);
06940 else
06941 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06942 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06943 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06944 if (getforward) {
06945
06946 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
06947 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06948 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06949 if (res)
06950 break;
06951 usleep(500000);
06952 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06953 sleep(1);
06954 memset(exten, 0, sizeof(exten));
06955 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06956 len = 0;
06957 getforward = 0;
06958 } else {
06959 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06960 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06961 if (!ast_strlen_zero(p->cid_num)) {
06962 if (!p->hidecallerid)
06963 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06964 else
06965 ast_set_callerid(chan, NULL, NULL, p->cid_num);
06966 }
06967 if (!ast_strlen_zero(p->cid_name)) {
06968 if (!p->hidecallerid)
06969 ast_set_callerid(chan, NULL, p->cid_name, NULL);
06970 }
06971 ast_setstate(chan, AST_STATE_RING);
06972 dahdi_enable_ec(p);
06973 res = ast_pbx_run(chan);
06974 if (res) {
06975 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06976 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06977 }
06978 goto quit;
06979 }
06980 } else {
06981
06982
06983 timeout = matchdigittimeout;
06984 }
06985 } else if (res == 0) {
06986 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
06987 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06988 dahdi_wait_event(p->subs[idx].dfd);
06989 ast_hangup(chan);
06990 goto quit;
06991 } else if (p->callwaiting && !strcmp(exten, "*70")) {
06992 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
06993
06994 p->callwaiting = 0;
06995 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06996 if (res) {
06997 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06998 chan->name, strerror(errno));
06999 }
07000 len = 0;
07001 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
07002 memset(exten, 0, sizeof(exten));
07003 timeout = firstdigittimeout;
07004
07005 } else if (!strcmp(exten,ast_pickup_ext())) {
07006
07007
07008
07009
07010 if (idx == SUB_REAL) {
07011
07012 if (p->subs[SUB_THREEWAY].owner) {
07013
07014
07015 alloc_sub(p, SUB_CALLWAIT);
07016 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07017 unalloc_sub(p, SUB_THREEWAY);
07018 }
07019 dahdi_enable_ec(p);
07020 if (ast_pickup_call(chan)) {
07021 ast_debug(1, "No call pickup possible...\n");
07022 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07023 dahdi_wait_event(p->subs[idx].dfd);
07024 }
07025 ast_hangup(chan);
07026 goto quit;
07027 } else {
07028 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07029 ast_hangup(chan);
07030 goto quit;
07031 }
07032
07033 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07034 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
07035
07036 p->hidecallerid = 1;
07037 if (chan->cid.cid_num)
07038 ast_free(chan->cid.cid_num);
07039 chan->cid.cid_num = NULL;
07040 if (chan->cid.cid_name)
07041 ast_free(chan->cid.cid_name);
07042 chan->cid.cid_name = NULL;
07043 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07044 if (res) {
07045 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07046 chan->name, strerror(errno));
07047 }
07048 len = 0;
07049 memset(exten, 0, sizeof(exten));
07050 timeout = firstdigittimeout;
07051 } else if (p->callreturn && !strcmp(exten, "*69")) {
07052 res = 0;
07053 if (!ast_strlen_zero(p->lastcid_num)) {
07054 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07055 }
07056 if (!res)
07057 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07058 break;
07059 } else if (!strcmp(exten, "*78")) {
07060 dahdi_dnd(p, 1);
07061
07062 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07063 getforward = 0;
07064 memset(exten, 0, sizeof(exten));
07065 len = 0;
07066 } else if (!strcmp(exten, "*79")) {
07067 dahdi_dnd(p, 0);
07068
07069 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07070 getforward = 0;
07071 memset(exten, 0, sizeof(exten));
07072 len = 0;
07073 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07074 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07075 getforward = 1;
07076 memset(exten, 0, sizeof(exten));
07077 len = 0;
07078 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07079 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
07080 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07081 memset(p->call_forward, 0, sizeof(p->call_forward));
07082 getforward = 0;
07083 memset(exten, 0, sizeof(exten));
07084 len = 0;
07085 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07086 p->subs[SUB_THREEWAY].owner &&
07087 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07088
07089
07090 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07091 ast_verb(3, "Parking call to '%s'\n", chan->name);
07092 break;
07093 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07094 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
07095 res = ast_db_put("blacklist", p->lastcid_num, "1");
07096 if (!res) {
07097 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07098 memset(exten, 0, sizeof(exten));
07099 len = 0;
07100 }
07101 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07102 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
07103
07104 p->hidecallerid = 0;
07105 if (chan->cid.cid_num)
07106 ast_free(chan->cid.cid_num);
07107 chan->cid.cid_num = NULL;
07108 if (chan->cid.cid_name)
07109 ast_free(chan->cid.cid_name);
07110 chan->cid.cid_name = NULL;
07111 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07112 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07113 if (res) {
07114 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07115 chan->name, strerror(errno));
07116 }
07117 len = 0;
07118 memset(exten, 0, sizeof(exten));
07119 timeout = firstdigittimeout;
07120 } else if (!strcmp(exten, "*0")) {
07121 struct ast_channel *nbridge =
07122 p->subs[SUB_THREEWAY].owner;
07123 struct dahdi_pvt *pbridge = NULL;
07124
07125 if (nbridge && ast_bridged_channel(nbridge))
07126 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07127 if (nbridge && pbridge &&
07128 (nbridge->tech == &dahdi_tech) &&
07129 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
07130 ISTRUNK(pbridge)) {
07131 int func = DAHDI_FLASH;
07132
07133 p->dop.dialstr[0] = '\0';
07134
07135 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07136 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07137 nbridge->name, strerror(errno));
07138 }
07139 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07140 unalloc_sub(p, SUB_THREEWAY);
07141 p->owner = p->subs[SUB_REAL].owner;
07142 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07143 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07144 ast_hangup(chan);
07145 goto quit;
07146 } else {
07147 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07148 dahdi_wait_event(p->subs[idx].dfd);
07149 tone_zone_play_tone(p->subs[idx].dfd, -1);
07150 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07151 unalloc_sub(p, SUB_THREEWAY);
07152 p->owner = p->subs[SUB_REAL].owner;
07153 ast_hangup(chan);
07154 goto quit;
07155 }
07156 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07157 ((exten[0] != '*') || (strlen(exten) > 2))) {
07158 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);
07159 break;
07160 }
07161 if (!timeout)
07162 timeout = gendigittimeout;
07163 if (len && !ast_ignore_pattern(chan->context, exten))
07164 tone_zone_play_tone(p->subs[idx].dfd, -1);
07165 }
07166 break;
07167 case SIG_FXSLS:
07168 case SIG_FXSGS:
07169 case SIG_FXSKS:
07170 #ifdef HAVE_PRI
07171 if (p->pri) {
07172
07173 struct ast_frame *f;
07174 int res;
07175 time_t start;
07176
07177 time(&start);
07178 ast_setstate(chan, AST_STATE_RING);
07179 while (time(NULL) < start + 3) {
07180 res = ast_waitfor(chan, 1000);
07181 if (res) {
07182 f = ast_read(chan);
07183 if (!f) {
07184 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07185 ast_hangup(chan);
07186 goto quit;
07187 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07188 res = 1;
07189 } else
07190 res = 0;
07191 ast_frfree(f);
07192 if (res) {
07193 ast_debug(1, "Got ring!\n");
07194 res = 0;
07195 break;
07196 }
07197 }
07198 }
07199 }
07200 #endif
07201
07202 if (p->use_smdi && p->smdi_iface) {
07203 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07204
07205 if (smdi_msg != NULL) {
07206 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07207
07208 if (smdi_msg->type == 'B')
07209 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07210 else if (smdi_msg->type == 'N')
07211 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07212
07213 ast_debug(1, "Received SMDI message on %s\n", chan->name);
07214 } else {
07215 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07216 }
07217 }
07218
07219 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07220 number = smdi_msg->calling_st;
07221
07222
07223
07224
07225 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
07226
07227 if (p->cid_signalling == CID_SIG_DTMF) {
07228 int k = 0;
07229 cs = NULL;
07230 ast_debug(1, "Receiving DTMF cid on "
07231 "channel %s\n", chan->name);
07232 dahdi_setlinear(p->subs[idx].dfd, 0);
07233 res = 2000;
07234 for (;;) {
07235 struct ast_frame *f;
07236 res = ast_waitfor(chan, res);
07237 if (res <= 0) {
07238 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07239 "Exiting simple switch\n");
07240 ast_hangup(chan);
07241 goto quit;
07242 }
07243 f = ast_read(chan);
07244 if (!f)
07245 break;
07246 if (f->frametype == AST_FRAME_DTMF) {
07247 dtmfbuf[k++] = f->subclass;
07248 ast_debug(1, "CID got digit '%c'\n", f->subclass);
07249 res = 2000;
07250 }
07251 ast_frfree(f);
07252 if (chan->_state == AST_STATE_RING ||
07253 chan->_state == AST_STATE_RINGING)
07254 break;
07255 }
07256 dtmfbuf[k] = '\0';
07257 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07258
07259 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
07260 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07261 ast_debug(1, "CID is '%s', flags %d\n",
07262 dtmfcid, flags);
07263
07264 if (!ast_strlen_zero(dtmfcid))
07265 number = dtmfcid;
07266 else
07267 number = NULL;
07268
07269 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07270 cs = callerid_new(p->cid_signalling);
07271 if (cs) {
07272 samples = 0;
07273 #if 1
07274 bump_gains(p);
07275 #endif
07276
07277 dahdi_setlinear(p->subs[idx].dfd, 0);
07278
07279
07280 for (;;) {
07281 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07282 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07283 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07284 callerid_free(cs);
07285 ast_hangup(chan);
07286 goto quit;
07287 }
07288 if (i & DAHDI_IOMUX_SIGEVENT) {
07289 res = dahdi_get_event(p->subs[idx].dfd);
07290 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07291
07292 if (p->cid_signalling == CID_SIG_V23_JP) {
07293 if (res == DAHDI_EVENT_RINGBEGIN) {
07294 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07295 usleep(1);
07296 }
07297 } else {
07298 res = 0;
07299 break;
07300 }
07301 } else if (i & DAHDI_IOMUX_READ) {
07302 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07303 if (res < 0) {
07304 if (errno != ELAST) {
07305 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07306 callerid_free(cs);
07307 ast_hangup(chan);
07308 goto quit;
07309 }
07310 break;
07311 }
07312 samples += res;
07313
07314 if (p->cid_signalling == CID_SIG_V23_JP) {
07315 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07316 } else {
07317 res = callerid_feed(cs, buf, res, AST_LAW(p));
07318 }
07319
07320 if (res < 0) {
07321 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07322 break;
07323 } else if (res)
07324 break;
07325 else if (samples > (8000 * 10))
07326 break;
07327 }
07328 }
07329 if (res == 1) {
07330 callerid_get(cs, &name, &number, &flags);
07331 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07332 }
07333
07334 if (p->cid_signalling == CID_SIG_V23_JP) {
07335 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07336 usleep(1);
07337 res = 4000;
07338 } else {
07339
07340
07341 res = 2000;
07342 }
07343
07344 for (;;) {
07345 struct ast_frame *f;
07346 res = ast_waitfor(chan, res);
07347 if (res <= 0) {
07348 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07349 "Exiting simple switch\n");
07350 ast_hangup(chan);
07351 goto quit;
07352 }
07353 if (!(f = ast_read(chan))) {
07354 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07355 ast_hangup(chan);
07356 goto quit;
07357 }
07358 ast_frfree(f);
07359 if (chan->_state == AST_STATE_RING ||
07360 chan->_state == AST_STATE_RINGING)
07361 break;
07362 }
07363
07364
07365
07366 if (p->usedistinctiveringdetection) {
07367 len = 0;
07368 distMatches = 0;
07369
07370 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07371 curRingData[receivedRingT] = 0;
07372 receivedRingT = 0;
07373 counter = 0;
07374 counter1 = 0;
07375
07376 if (strcmp(p->context,p->defcontext) != 0) {
07377 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07378 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07379 }
07380
07381 for (;;) {
07382 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07383 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07384 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07385 callerid_free(cs);
07386 ast_hangup(chan);
07387 goto quit;
07388 }
07389 if (i & DAHDI_IOMUX_SIGEVENT) {
07390 res = dahdi_get_event(p->subs[idx].dfd);
07391 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07392 res = 0;
07393
07394
07395 curRingData[receivedRingT] = p->ringt;
07396
07397 if (p->ringt < p->ringt_base/2)
07398 break;
07399
07400
07401 if (++receivedRingT == ARRAY_LEN(curRingData))
07402 break;
07403 } else if (i & DAHDI_IOMUX_READ) {
07404 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07405 if (res < 0) {
07406 if (errno != ELAST) {
07407 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07408 callerid_free(cs);
07409 ast_hangup(chan);
07410 goto quit;
07411 }
07412 break;
07413 }
07414 if (p->ringt)
07415 p->ringt--;
07416 if (p->ringt == 1) {
07417 res = -1;
07418 break;
07419 }
07420 }
07421 }
07422
07423 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07424 for (counter = 0; counter < 3; counter++) {
07425
07426
07427 distMatches = 0;
07428 for (counter1 = 0; counter1 < 3; counter1++) {
07429 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07430 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07431 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07432 curRingData[counter1]);
07433 distMatches++;
07434 }
07435 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07436 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07437 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07438 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07439 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07440 distMatches++;
07441 }
07442 }
07443
07444 if (distMatches == 3) {
07445
07446 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07447 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07448 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07449 break;
07450 }
07451 }
07452 }
07453
07454 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07455 #if 1
07456 restore_gains(p);
07457 #endif
07458 } else
07459 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07460 } else {
07461 ast_log(LOG_WARNING, "Channel %s in prering "
07462 "state, but I have nothing to do. "
07463 "Terminating simple switch, should be "
07464 "restarted by the actual ring.\n",
07465 chan->name);
07466 ast_hangup(chan);
07467 goto quit;
07468 }
07469 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07470 if (p->cid_signalling == CID_SIG_DTMF) {
07471 int k = 0;
07472 cs = NULL;
07473 dahdi_setlinear(p->subs[idx].dfd, 0);
07474 res = 2000;
07475 for (;;) {
07476 struct ast_frame *f;
07477 res = ast_waitfor(chan, res);
07478 if (res <= 0) {
07479 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07480 "Exiting simple switch\n");
07481 ast_hangup(chan);
07482 return NULL;
07483 }
07484 f = ast_read(chan);
07485 if (f->frametype == AST_FRAME_DTMF) {
07486 dtmfbuf[k++] = f->subclass;
07487 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07488 res = 2000;
07489 }
07490 ast_frfree(f);
07491
07492 if (p->ringt_base == p->ringt)
07493 break;
07494
07495 }
07496 dtmfbuf[k] = '\0';
07497 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07498
07499 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07500 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07501 dtmfcid, flags);
07502
07503 if (!ast_strlen_zero(dtmfcid))
07504 number = dtmfcid;
07505 else
07506 number = NULL;
07507
07508 } else {
07509
07510 cs = callerid_new(p->cid_signalling);
07511 if (cs) {
07512 #if 1
07513 bump_gains(p);
07514 #endif
07515 samples = 0;
07516 len = 0;
07517 distMatches = 0;
07518
07519 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07520 curRingData[receivedRingT] = 0;
07521 receivedRingT = 0;
07522 counter = 0;
07523 counter1 = 0;
07524
07525 if (strcmp(p->context,p->defcontext) != 0) {
07526 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07527 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07528 }
07529
07530
07531 dahdi_setlinear(p->subs[idx].dfd, 0);
07532 for (;;) {
07533 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07534 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07535 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07536 callerid_free(cs);
07537 ast_hangup(chan);
07538 goto quit;
07539 }
07540 if (i & DAHDI_IOMUX_SIGEVENT) {
07541 res = dahdi_get_event(p->subs[idx].dfd);
07542 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07543
07544 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07545 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07546 p->polarity = POLARITY_IDLE;
07547 callerid_free(cs);
07548 ast_hangup(chan);
07549 goto quit;
07550 }
07551 res = 0;
07552
07553
07554 curRingData[receivedRingT] = p->ringt;
07555
07556 if (p->ringt < p->ringt_base/2)
07557 break;
07558
07559
07560 if (++receivedRingT == ARRAY_LEN(curRingData))
07561 break;
07562 } else if (i & DAHDI_IOMUX_READ) {
07563 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07564 if (res < 0) {
07565 if (errno != ELAST) {
07566 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07567 callerid_free(cs);
07568 ast_hangup(chan);
07569 goto quit;
07570 }
07571 break;
07572 }
07573 if (p->ringt)
07574 p->ringt--;
07575 if (p->ringt == 1) {
07576 res = -1;
07577 break;
07578 }
07579 samples += res;
07580 res = callerid_feed(cs, buf, res, AST_LAW(p));
07581 if (res < 0) {
07582 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07583 break;
07584 } else if (res)
07585 break;
07586 else if (samples > (8000 * 10))
07587 break;
07588 }
07589 }
07590 if (res == 1) {
07591 callerid_get(cs, &name, &number, &flags);
07592 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07593 }
07594 if (distinctiveringaftercid == 1) {
07595
07596 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07597 curRingData[receivedRingT] = 0;
07598 }
07599 receivedRingT = 0;
07600 ast_verb(3, "Detecting post-CID distinctive ring\n");
07601 for (;;) {
07602 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07603 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07604 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07605 callerid_free(cs);
07606 ast_hangup(chan);
07607 goto quit;
07608 }
07609 if (i & DAHDI_IOMUX_SIGEVENT) {
07610 res = dahdi_get_event(p->subs[idx].dfd);
07611 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07612 res = 0;
07613
07614
07615 curRingData[receivedRingT] = p->ringt;
07616
07617 if (p->ringt < p->ringt_base/2)
07618 break;
07619
07620
07621 if (++receivedRingT == ARRAY_LEN(curRingData))
07622 break;
07623 } else if (i & DAHDI_IOMUX_READ) {
07624 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07625 if (res < 0) {
07626 if (errno != ELAST) {
07627 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07628 callerid_free(cs);
07629 ast_hangup(chan);
07630 goto quit;
07631 }
07632 break;
07633 }
07634 if (p->ringt)
07635 p->ringt--;
07636 if (p->ringt == 1) {
07637 res = -1;
07638 break;
07639 }
07640 }
07641 }
07642 }
07643 if (p->usedistinctiveringdetection) {
07644
07645 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07646
07647 for (counter = 0; counter < 3; counter++) {
07648
07649
07650
07651 ast_verb(3, "Checking %d,%d,%d\n",
07652 p->drings.ringnum[counter].ring[0],
07653 p->drings.ringnum[counter].ring[1],
07654 p->drings.ringnum[counter].ring[2]);
07655 distMatches = 0;
07656 for (counter1 = 0; counter1 < 3; counter1++) {
07657 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07658 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07659 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07660 curRingData[counter1]);
07661 distMatches++;
07662 }
07663 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07664 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07665 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07666 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07667 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07668 distMatches++;
07669 }
07670 }
07671 if (distMatches == 3) {
07672
07673 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07674 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07675 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07676 break;
07677 }
07678 }
07679 }
07680
07681 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07682 #if 1
07683 restore_gains(p);
07684 #endif
07685 if (res < 0) {
07686 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07687 }
07688 } else
07689 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07690 }
07691 }
07692 else
07693 cs = NULL;
07694
07695 if (number)
07696 ast_shrink_phone_number(number);
07697 ast_set_callerid(chan, number, name, number);
07698
07699 if (smdi_msg)
07700 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07701
07702 if (cs)
07703 callerid_free(cs);
07704
07705 if (flags & CID_MSGWAITING) {
07706 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
07707 notify_message(p->mailbox, 1);
07708
07709 if (p->mwimonitor_rpas) {
07710 ast_hangup(chan);
07711 return NULL;
07712 }
07713 } else if (flags & CID_NOMSGWAITING) {
07714 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
07715 notify_message(p->mailbox, 0);
07716
07717 if (p->mwimonitor_rpas) {
07718 ast_hangup(chan);
07719 return NULL;
07720 }
07721 }
07722
07723 ast_setstate(chan, AST_STATE_RING);
07724 chan->rings = 1;
07725 p->ringt = p->ringt_base;
07726 res = ast_pbx_run(chan);
07727 if (res) {
07728 ast_hangup(chan);
07729 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07730 }
07731 goto quit;
07732 default:
07733 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07734 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07735 if (res < 0)
07736 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07737 }
07738 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07739 if (res < 0)
07740 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07741 ast_hangup(chan);
07742 quit:
07743 ast_mutex_lock(&ss_thread_lock);
07744 ss_thread_count--;
07745 ast_cond_signal(&ss_thread_complete);
07746 ast_mutex_unlock(&ss_thread_lock);
07747 return NULL;
07748 }
07749
07750 struct mwi_thread_data {
07751 struct dahdi_pvt *pvt;
07752 unsigned char buf[READ_SIZE];
07753 size_t len;
07754 };
07755
07756 static int calc_energy(const unsigned char *buf, int len, int law)
07757 {
07758 int x;
07759 int sum = 0;
07760
07761 if (!len)
07762 return 0;
07763
07764 for (x = 0; x < len; x++)
07765 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07766
07767 return sum / len;
07768 }
07769
07770 static void *mwi_thread(void *data)
07771 {
07772 struct mwi_thread_data *mtd = data;
07773 struct callerid_state *cs;
07774 pthread_t threadid;
07775 int samples = 0;
07776 char *name, *number;
07777 int flags;
07778 int i, res;
07779 unsigned int spill_done = 0;
07780 int spill_result = -1;
07781
07782 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
07783 mtd->pvt->mwimonitoractive = 0;
07784
07785 return NULL;
07786 }
07787
07788 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
07789
07790 bump_gains(mtd->pvt);
07791
07792 for (;;) {
07793 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07794 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07795 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07796 goto quit;
07797 }
07798
07799 if (i & DAHDI_IOMUX_SIGEVENT) {
07800 struct ast_channel *chan;
07801
07802
07803
07804
07805 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07806
07807 switch (res) {
07808 case DAHDI_EVENT_NEONMWI_ACTIVE:
07809 case DAHDI_EVENT_NEONMWI_INACTIVE:
07810 case DAHDI_EVENT_NONE:
07811 case DAHDI_EVENT_BITSCHANGED:
07812 break;
07813 case DAHDI_EVENT_NOALARM:
07814 mtd->pvt->inalarm = 0;
07815 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
07816 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07817 "Channel: %d\r\n", mtd->pvt->channel);
07818 break;
07819 case DAHDI_EVENT_ALARM:
07820 mtd->pvt->inalarm = 1;
07821 res = get_alarms(mtd->pvt);
07822 handle_alarms(mtd->pvt, res);
07823 break;
07824 default:
07825 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
07826 callerid_free(cs);
07827
07828 restore_gains(mtd->pvt);
07829 mtd->pvt->ringt = mtd->pvt->ringt_base;
07830
07831 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
07832 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07833 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
07834 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07835 if (res < 0)
07836 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
07837 ast_hangup(chan);
07838 goto quit;
07839 }
07840 goto quit_no_clean;
07841
07842 } else {
07843 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
07844 }
07845 }
07846 } else if (i & DAHDI_IOMUX_READ) {
07847 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07848 if (errno != ELAST) {
07849 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07850 goto quit;
07851 }
07852 break;
07853 }
07854 samples += res;
07855 if (!spill_done) {
07856 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
07857 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07858 break;
07859 } else if (spill_result) {
07860 spill_done = 1;
07861 }
07862 } else {
07863
07864
07865
07866 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
07867 break;
07868 }
07869 if (samples > (8000 * 4))
07870 break;
07871 }
07872 }
07873
07874 if (spill_result == 1) {
07875 callerid_get(cs, &name, &number, &flags);
07876 if (flags & CID_MSGWAITING) {
07877 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
07878 notify_message(mtd->pvt->mailbox, 1);
07879 } else if (flags & CID_NOMSGWAITING) {
07880 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
07881 notify_message(mtd->pvt->mailbox, 0);
07882 } else {
07883 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
07884 }
07885 }
07886
07887
07888 quit:
07889 callerid_free(cs);
07890
07891 restore_gains(mtd->pvt);
07892
07893 quit_no_clean:
07894 mtd->pvt->mwimonitoractive = 0;
07895
07896 ast_free(mtd);
07897
07898 return NULL;
07899 }
07900
07901
07902
07903
07904 enum mwisend_states {
07905 MWI_SEND_SA,
07906 MWI_SEND_SA_WAIT,
07907 MWI_SEND_PAUSE,
07908 MWI_SEND_SPILL,
07909 MWI_SEND_CLEANUP,
07910 MWI_SEND_DONE
07911 };
07912
07913 static void *mwi_send_thread(void *data)
07914 {
07915 struct mwi_thread_data *mtd = data;
07916 struct timeval timeout_basis, suspend, now;
07917 int x, i, res;
07918 int num_read;
07919 enum mwisend_states mwi_send_state = MWI_SEND_SPILL;
07920
07921 ast_mutex_lock(&mwi_thread_lock);
07922 mwi_thread_count++;
07923 ast_mutex_unlock(&mwi_thread_lock);
07924
07925
07926 if(mwisend_rpas) {
07927 mwi_send_state = MWI_SEND_SA;
07928 }
07929
07930 gettimeofday(&timeout_basis, NULL);
07931
07932 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
07933 if (!mtd->pvt->cidspill) {
07934 mtd->pvt->mwisendactive = 0;
07935 ast_free(mtd);
07936 return NULL;
07937 }
07938 x = DAHDI_FLUSH_BOTH;
07939 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07940 x = 3000;
07941 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07942 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
07943 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
07944 mtd->pvt->cidpos = 0;
07945
07946 while (MWI_SEND_DONE != mwi_send_state) {
07947 num_read = 0;
07948 gettimeofday(&now, NULL);
07949 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
07950 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
07951 goto quit;
07952 }
07953
07954 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07955 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07956 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07957 goto quit;
07958 }
07959
07960 if (i & DAHDI_IOMUX_SIGEVENT) {
07961
07962
07963
07964 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07965 switch (res) {
07966 case DAHDI_EVENT_RINGEROFF:
07967 if(mwi_send_state == MWI_SEND_SA_WAIT) {
07968 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
07969 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
07970 goto quit;
07971 }
07972 mwi_send_state = MWI_SEND_PAUSE;
07973 gettimeofday(&suspend, NULL);
07974 }
07975 break;
07976 case DAHDI_EVENT_RINGERON:
07977 case DAHDI_EVENT_HOOKCOMPLETE:
07978 break;
07979 default:
07980
07981 if (0 < handle_init_event(mtd->pvt, res)) {
07982
07983 goto quit;
07984 }
07985 break;
07986 }
07987 } else if (i & DAHDI_IOMUX_READ) {
07988 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07989 if (errno != ELAST) {
07990 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07991 goto quit;
07992 }
07993 break;
07994 }
07995 }
07996
07997 switch ( mwi_send_state) {
07998 case MWI_SEND_SA:
07999
08000 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
08001 if (res) {
08002 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
08003 goto quit;
08004 }
08005 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING);
08006 mwi_send_state = MWI_SEND_SA_WAIT;
08007 break;
08008 case MWI_SEND_SA_WAIT:
08009 break;
08010 case MWI_SEND_PAUSE:
08011 gettimeofday(&now, NULL);
08012 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
08013 mwi_send_state = MWI_SEND_SPILL;
08014 }
08015 break;
08016 case MWI_SEND_SPILL:
08017
08018 if(0 < num_read) {
08019 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
08020 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
08021 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
08022 if (res > 0) {
08023 mtd->pvt->cidpos += res;
08024 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
08025 ast_free(mtd->pvt->cidspill);
08026 mtd->pvt->cidspill = NULL;
08027 mtd->pvt->cidpos = 0;
08028 mtd->pvt->cidlen = 0;
08029 mwi_send_state = MWI_SEND_CLEANUP;
08030 }
08031 } else {
08032 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
08033 goto quit;
08034 }
08035 }
08036 break;
08037 case MWI_SEND_CLEANUP:
08038
08039 mwi_send_state = MWI_SEND_DONE;
08040 break;
08041 default:
08042
08043 goto quit;
08044 break;
08045 }
08046 }
08047
08048 quit:
08049 if(mtd->pvt->cidspill) {
08050 ast_free(mtd->pvt->cidspill);
08051 mtd->pvt->cidspill = NULL;
08052 }
08053 mtd->pvt->mwisendactive = 0;
08054 ast_free(mtd);
08055
08056 ast_mutex_lock(&mwi_thread_lock);
08057 mwi_thread_count--;
08058 ast_cond_signal(&mwi_thread_complete);
08059 ast_mutex_unlock(&mwi_thread_lock);
08060
08061 return NULL;
08062 }
08063
08064
08065
08066 static int dahdi_destroy_channel_bynum(int channel)
08067 {
08068 struct dahdi_pvt *tmp = NULL;
08069 struct dahdi_pvt *prev = NULL;
08070
08071 tmp = iflist;
08072 while (tmp) {
08073 if (tmp->channel == channel) {
08074 int x = DAHDI_FLASH;
08075 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08076 destroy_channel(prev, tmp, 1);
08077 ast_module_unref(ast_module_info->self);
08078 return RESULT_SUCCESS;
08079 }
08080 prev = tmp;
08081 tmp = tmp->next;
08082 }
08083 return RESULT_FAILURE;
08084 }
08085
08086
08087 static int handle_init_event(struct dahdi_pvt *i, int event)
08088 {
08089 int res;
08090 int thread_spawned = 0;
08091 pthread_t threadid;
08092 struct ast_channel *chan;
08093
08094
08095
08096 switch (event) {
08097 case DAHDI_EVENT_NONE:
08098 case DAHDI_EVENT_BITSCHANGED:
08099 break;
08100 case DAHDI_EVENT_WINKFLASH:
08101 case DAHDI_EVENT_RINGOFFHOOK:
08102 if (i->inalarm) break;
08103 if (i->radio) break;
08104
08105 switch (i->sig) {
08106 case SIG_FXOLS:
08107 case SIG_FXOGS:
08108 case SIG_FXOKS:
08109 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08110 if (res && (errno == EBUSY))
08111 break;
08112 if (i->cidspill) {
08113
08114 ast_free(i->cidspill);
08115 i->cidspill = NULL;
08116 }
08117 if (i->immediate) {
08118 dahdi_enable_ec(i);
08119
08120 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08121 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08122 if (!chan) {
08123 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08124 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08125 if (res < 0)
08126 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08127 }
08128 } else {
08129
08130 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08131 if (chan) {
08132 if (has_voicemail(i))
08133 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08134 else
08135 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08136 if (res < 0)
08137 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08138 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08139 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08140 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08141 if (res < 0)
08142 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08143 ast_hangup(chan);
08144 } else {
08145 thread_spawned = 1;
08146 }
08147 } else
08148 ast_log(LOG_WARNING, "Unable to create channel\n");
08149 }
08150 break;
08151 case SIG_FXSLS:
08152 case SIG_FXSGS:
08153 case SIG_FXSKS:
08154 i->ringt = i->ringt_base;
08155
08156 case SIG_EMWINK:
08157 case SIG_FEATD:
08158 case SIG_FEATDMF:
08159 case SIG_FEATDMF_TA:
08160 case SIG_E911:
08161 case SIG_FGC_CAMA:
08162 case SIG_FGC_CAMAMF:
08163 case SIG_FEATB:
08164 case SIG_EM:
08165 case SIG_EM_E1:
08166 case SIG_SFWINK:
08167 case SIG_SF_FEATD:
08168 case SIG_SF_FEATDMF:
08169 case SIG_SF_FEATB:
08170 case SIG_SF:
08171
08172 if (i->cid_start == CID_START_POLARITY_IN) {
08173 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08174 } else {
08175 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08176 }
08177
08178 if (!chan) {
08179 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08180 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08181 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08182 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08183 if (res < 0) {
08184 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08185 }
08186 ast_hangup(chan);
08187 } else {
08188 thread_spawned = 1;
08189 }
08190 break;
08191 default:
08192 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08193 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08194 if (res < 0)
08195 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08196 return -1;
08197 }
08198 break;
08199 case DAHDI_EVENT_NOALARM:
08200 i->inalarm = 0;
08201 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08202 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08203 "Channel: %d\r\n", i->channel);
08204 break;
08205 case DAHDI_EVENT_ALARM:
08206 i->inalarm = 1;
08207 res = get_alarms(i);
08208 handle_alarms(i, res);
08209
08210 case DAHDI_EVENT_ONHOOK:
08211 if (i->radio)
08212 break;
08213
08214 switch (i->sig) {
08215 case SIG_FXOLS:
08216 case SIG_FXOGS:
08217 case SIG_FEATD:
08218 case SIG_FEATDMF:
08219 case SIG_FEATDMF_TA:
08220 case SIG_E911:
08221 case SIG_FGC_CAMA:
08222 case SIG_FGC_CAMAMF:
08223 case SIG_FEATB:
08224 case SIG_EM:
08225 case SIG_EM_E1:
08226 case SIG_EMWINK:
08227 case SIG_SF_FEATD:
08228 case SIG_SF_FEATDMF:
08229 case SIG_SF_FEATB:
08230 case SIG_SF:
08231 case SIG_SFWINK:
08232 case SIG_FXSLS:
08233 case SIG_FXSGS:
08234 case SIG_FXSKS:
08235 case SIG_GR303FXSKS:
08236 dahdi_disable_ec(i);
08237 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08238 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08239 break;
08240 case SIG_GR303FXOKS:
08241 case SIG_FXOKS:
08242 dahdi_disable_ec(i);
08243
08244 #ifdef ZHONE_HACK
08245 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08246 usleep(1);
08247 #endif
08248 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08249 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08250 break;
08251 case SIG_PRI:
08252 case SIG_SS7:
08253 case SIG_BRI:
08254 case SIG_BRI_PTMP:
08255 dahdi_disable_ec(i);
08256 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08257 break;
08258 default:
08259 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08260 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08261 return -1;
08262 }
08263 break;
08264 case DAHDI_EVENT_POLARITY:
08265 switch (i->sig) {
08266 case SIG_FXSLS:
08267 case SIG_FXSKS:
08268 case SIG_FXSGS:
08269
08270
08271
08272
08273 if (i->hanguponpolarityswitch)
08274 i->polarity = POLARITY_REV;
08275 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08276 i->polarity = POLARITY_REV;
08277 ast_verb(2, "Starting post polarity "
08278 "CID detection on channel %d\n",
08279 i->channel);
08280 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08281 if (!chan) {
08282 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08283 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08284 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08285 } else {
08286 thread_spawned = 1;
08287 }
08288 }
08289 break;
08290 default:
08291 ast_log(LOG_WARNING, "handle_init_event detected "
08292 "polarity reversal on non-FXO (SIG_FXS) "
08293 "interface %d\n", i->channel);
08294 }
08295 break;
08296 case DAHDI_EVENT_REMOVED:
08297 ast_log(LOG_NOTICE,
08298 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08299 i->channel);
08300 dahdi_destroy_channel_bynum(i->channel);
08301 break;
08302 case DAHDI_EVENT_NEONMWI_ACTIVE:
08303 if (i->mwimonitor_neon) {
08304 notify_message(i->mailbox, 1);
08305 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08306 }
08307 break;
08308 case DAHDI_EVENT_NEONMWI_INACTIVE:
08309 if (i->mwimonitor_neon) {
08310 notify_message(i->mailbox, 0);
08311 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08312 }
08313 break;
08314 }
08315 return thread_spawned;
08316 }
08317
08318 static void *do_monitor(void *data)
08319 {
08320 int count, res, res2, spoint, pollres=0;
08321 struct dahdi_pvt *i;
08322 struct dahdi_pvt *last = NULL;
08323 time_t thispass = 0, lastpass = 0;
08324 int found;
08325 char buf[1024];
08326 struct pollfd *pfds=NULL;
08327 int lastalloc = -1;
08328
08329
08330
08331 #if 0
08332 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08333 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08334 return NULL;
08335 }
08336 ast_debug(1, "Monitor starting...\n");
08337 #endif
08338 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08339
08340 for (;;) {
08341
08342 ast_mutex_lock(&iflock);
08343 if (!pfds || (lastalloc != ifcount)) {
08344 if (pfds) {
08345 ast_free(pfds);
08346 pfds = NULL;
08347 }
08348 if (ifcount) {
08349 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08350 ast_mutex_unlock(&iflock);
08351 return NULL;
08352 }
08353 }
08354 lastalloc = ifcount;
08355 }
08356
08357
08358 count = 0;
08359 i = iflist;
08360 while (i) {
08361 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08362 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
08363
08364 pfds[count].fd = i->subs[SUB_REAL].dfd;
08365 pfds[count].events = POLLPRI;
08366 pfds[count].revents = 0;
08367
08368
08369 if (i->cidspill || i->mwimonitor_fsk)
08370 pfds[count].events |= POLLIN;
08371 count++;
08372 }
08373 }
08374 i = i->next;
08375 }
08376
08377 ast_mutex_unlock(&iflock);
08378
08379 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08380 pthread_testcancel();
08381
08382 res = poll(pfds, count, 1000);
08383 pthread_testcancel();
08384 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08385
08386
08387 if (res < 0) {
08388 if ((errno != EAGAIN) && (errno != EINTR))
08389 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08390 continue;
08391 }
08392
08393
08394 ast_mutex_lock(&iflock);
08395 found = 0;
08396 spoint = 0;
08397 lastpass = thispass;
08398 thispass = time(NULL);
08399 i = iflist;
08400 while (i) {
08401 if (thispass != lastpass) {
08402 if (!found && ((i == last) || ((i == iflist) && !last))) {
08403 last = i;
08404 if (last) {
08405 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) {
08406 res = has_voicemail(last);
08407 if (last->msgstate != res) {
08408
08409
08410
08411
08412 pthread_attr_t attr;
08413 pthread_t threadid;
08414 struct mwi_thread_data *mtd;
08415 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08416 if (res2) {
08417
08418 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08419 }
08420 pthread_attr_init(&attr);
08421 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08422 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08423 last->msgstate = res;
08424 mtd->pvt = last;
08425 last->mwisendactive = 1;
08426 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
08427 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
08428 ast_free(mtd);
08429 last->mwisendactive = 0;
08430 }
08431 }
08432 found ++;
08433 }
08434 }
08435 last = last->next;
08436 }
08437 }
08438 }
08439 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08440 if (i->radio && !i->owner)
08441 {
08442 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08443 if (res)
08444 {
08445 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08446
08447 ast_mutex_unlock(&iflock);
08448 handle_init_event(i, res);
08449 ast_mutex_lock(&iflock);
08450 }
08451 i = i->next;
08452 continue;
08453 }
08454 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08455 if (pollres & POLLIN) {
08456 if (i->owner || i->subs[SUB_REAL].owner) {
08457 #ifdef HAVE_PRI
08458 if (!i->pri)
08459 #endif
08460 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08461 i = i->next;
08462 continue;
08463 }
08464 if (!i->cidspill && !i->mwimonitor_fsk) {
08465 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08466 i = i->next;
08467 continue;
08468 }
08469 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08470 if (res > 0) {
08471 if (i->mwimonitor_fsk) {
08472 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08473 pthread_attr_t attr;
08474 pthread_t threadid;
08475 struct mwi_thread_data *mtd;
08476
08477 pthread_attr_init(&attr);
08478 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08479
08480 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08481 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08482 mtd->pvt = i;
08483 memcpy(mtd->buf, buf, res);
08484 mtd->len = res;
08485 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08486 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08487 ast_free(mtd);
08488 }
08489 i->mwimonitoractive = 1;
08490 }
08491 }
08492 }
08493 } else {
08494 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08495 }
08496 }
08497 if (pollres & POLLPRI) {
08498 if (i->owner || i->subs[SUB_REAL].owner) {
08499 #ifdef HAVE_PRI
08500 if (!i->pri)
08501 #endif
08502 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08503 i = i->next;
08504 continue;
08505 }
08506 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08507 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08508
08509 ast_mutex_unlock(&iflock);
08510 handle_init_event(i, res);
08511 ast_mutex_lock(&iflock);
08512 }
08513 }
08514 i=i->next;
08515 }
08516 ast_mutex_unlock(&iflock);
08517 }
08518
08519 return NULL;
08520
08521 }
08522
08523 static int restart_monitor(void)
08524 {
08525
08526 if (monitor_thread == AST_PTHREADT_STOP)
08527 return 0;
08528 ast_mutex_lock(&monlock);
08529 if (monitor_thread == pthread_self()) {
08530 ast_mutex_unlock(&monlock);
08531 ast_log(LOG_WARNING, "Cannot kill myself\n");
08532 return -1;
08533 }
08534 if (monitor_thread != AST_PTHREADT_NULL) {
08535
08536 pthread_kill(monitor_thread, SIGURG);
08537 } else {
08538
08539 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08540 ast_mutex_unlock(&monlock);
08541 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08542 return -1;
08543 }
08544 }
08545 ast_mutex_unlock(&monlock);
08546 return 0;
08547 }
08548
08549 #ifdef HAVE_PRI
08550 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08551 {
08552 int x;
08553 int trunkgroup;
08554
08555 trunkgroup = pris[*span].mastertrunkgroup;
08556 if (trunkgroup) {
08557
08558 for (x = 0; x < NUM_SPANS; x++) {
08559 if (pris[x].trunkgroup == trunkgroup) {
08560 *span = x;
08561 return 0;
08562 }
08563 }
08564 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08565 *span = -1;
08566 } else {
08567 if (pris[*span].trunkgroup) {
08568 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08569 *span = -1;
08570 } else if (pris[*span].mastertrunkgroup) {
08571 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08572 *span = -1;
08573 } else {
08574 if (si->totalchans == 31) {
08575
08576 pris[*span].dchannels[0] = 16 + offset;
08577 } else if (si->totalchans == 24) {
08578
08579 pris[*span].dchannels[0] = 24 + offset;
08580 } else if (si->totalchans == 3) {
08581
08582 pris[*span].dchannels[0] = 3 + offset;
08583 } else {
08584 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);
08585 *span = -1;
08586 return 0;
08587 }
08588 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08589 pris[*span].offset = offset;
08590 pris[*span].span = *span + 1;
08591 }
08592 }
08593 return 0;
08594 }
08595
08596 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08597 {
08598 struct dahdi_spaninfo si;
08599 struct dahdi_params p;
08600 int fd;
08601 int span;
08602 int ospan=0;
08603 int x,y;
08604 for (x = 0; x < NUM_SPANS; x++) {
08605 if (pris[x].trunkgroup == trunkgroup) {
08606 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08607 return -1;
08608 }
08609 }
08610 for (y = 0; y < NUM_DCHANS; y++) {
08611 if (!channels[y])
08612 break;
08613 memset(&si, 0, sizeof(si));
08614 memset(&p, 0, sizeof(p));
08615 fd = open("/dev/dahdi/channel", O_RDWR);
08616 if (fd < 0) {
08617 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08618 return -1;
08619 }
08620 x = channels[y];
08621 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08622 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08623 close(fd);
08624 return -1;
08625 }
08626 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08627 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08628 return -1;
08629 }
08630 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08631 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08632 close(fd);
08633 return -1;
08634 }
08635 span = p.spanno - 1;
08636 if (pris[span].trunkgroup) {
08637 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08638 close(fd);
08639 return -1;
08640 }
08641 if (pris[span].pvts[0]) {
08642 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08643 close(fd);
08644 return -1;
08645 }
08646 if (!y) {
08647 pris[span].trunkgroup = trunkgroup;
08648 pris[span].offset = channels[y] - p.chanpos;
08649 ospan = span;
08650 }
08651 pris[ospan].dchannels[y] = channels[y];
08652 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08653 pris[span].span = span + 1;
08654 close(fd);
08655 }
08656 return 0;
08657 }
08658
08659 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08660 {
08661 if (pris[span].mastertrunkgroup) {
08662 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);
08663 return -1;
08664 }
08665 pris[span].mastertrunkgroup = trunkgroup;
08666 pris[span].prilogicalspan = logicalspan;
08667 return 0;
08668 }
08669
08670 #endif
08671
08672 #ifdef HAVE_SS7
08673
08674 static unsigned int parse_pointcode(const char *pcstring)
08675 {
08676 unsigned int code1, code2, code3;
08677 int numvals;
08678
08679 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
08680 if (numvals == 1)
08681 return code1;
08682 if (numvals == 3)
08683 return (code1 << 16) | (code2 << 8) | code3;
08684
08685 return 0;
08686 }
08687
08688 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
08689 {
08690 if ((linkset < 0) || (linkset >= NUM_SPANS))
08691 return NULL;
08692 else
08693 return &linksets[linkset - 1];
08694 }
08695 #endif
08696
08697
08698
08699
08700
08701
08702 static int sigtype_to_signalling(int sigtype)
08703 {
08704 return sigtype;
08705 }
08706
08707 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08708 {
08709
08710 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08711 char fn[80];
08712 struct dahdi_bufferinfo bi;
08713
08714 int res;
08715 int span = 0;
08716 int here = 0;
08717 int x;
08718 struct dahdi_pvt **wlist;
08719 struct dahdi_pvt **wend;
08720 struct dahdi_params p;
08721
08722 wlist = &iflist;
08723 wend = &ifend;
08724
08725 #ifdef HAVE_PRI
08726 if (pri) {
08727 wlist = &pri->crvs;
08728 wend = &pri->crvend;
08729 }
08730 #endif
08731
08732 tmp2 = *wlist;
08733 prev = NULL;
08734
08735 while (tmp2) {
08736 if (!tmp2->destroy) {
08737 if (tmp2->channel == channel) {
08738 tmp = tmp2;
08739 here = 1;
08740 break;
08741 }
08742 if (tmp2->channel > channel) {
08743 break;
08744 }
08745 }
08746 prev = tmp2;
08747 tmp2 = tmp2->next;
08748 }
08749
08750 if (!here && reloading != 1) {
08751 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08752 if (tmp)
08753 free(tmp);
08754 return NULL;
08755 }
08756 ast_mutex_init(&tmp->lock);
08757 ifcount++;
08758 for (x = 0; x < 3; x++)
08759 tmp->subs[x].dfd = -1;
08760 tmp->channel = channel;
08761 tmp->priindication_oob = conf->chan.priindication_oob;
08762 }
08763
08764 if (tmp) {
08765 int chan_sig = conf->chan.sig;
08766 if (!here) {
08767 if ((channel != CHAN_PSEUDO) && !pri) {
08768 int count = 0;
08769 snprintf(fn, sizeof(fn), "%d", channel);
08770
08771 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08772 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08773 usleep(1);
08774 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08775 count++;
08776 }
08777
08778 if (tmp->subs[SUB_REAL].dfd < 0) {
08779 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);
08780 destroy_dahdi_pvt(&tmp);
08781 return NULL;
08782 }
08783 memset(&p, 0, sizeof(p));
08784 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08785 if (res < 0) {
08786 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08787 destroy_dahdi_pvt(&tmp);
08788 return NULL;
08789 }
08790 if (conf->is_sig_auto)
08791 chan_sig = sigtype_to_signalling(p.sigtype);
08792 if (p.sigtype != (chan_sig & 0x3ffff)) {
08793 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));
08794 destroy_dahdi_pvt(&tmp);
08795 return NULL;
08796 }
08797 tmp->law = p.curlaw;
08798 tmp->span = p.spanno;
08799 span = p.spanno - 1;
08800 } else {
08801 if (channel == CHAN_PSEUDO)
08802 chan_sig = 0;
08803 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08804 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08805 return NULL;
08806 }
08807 }
08808 #ifdef HAVE_SS7
08809 if (chan_sig == SIG_SS7) {
08810 struct dahdi_ss7 *ss7;
08811 int clear = 0;
08812 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08813 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08814 destroy_dahdi_pvt(&tmp);
08815 return NULL;
08816 }
08817
08818 ss7 = ss7_resolve_linkset(cur_linkset);
08819 if (!ss7) {
08820 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08821 destroy_dahdi_pvt(&tmp);
08822 return NULL;
08823 }
08824 if (cur_cicbeginswith < 0) {
08825 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08826 destroy_dahdi_pvt(&tmp);
08827 return NULL;
08828 }
08829
08830 tmp->cic = cur_cicbeginswith++;
08831
08832
08833 tmp->dpc = cur_defaultdpc;
08834
08835 tmp->ss7 = ss7;
08836 tmp->ss7call = NULL;
08837 ss7->pvts[ss7->numchans++] = tmp;
08838
08839 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
08840 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
08841 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
08842 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
08843
08844 ss7->called_nai = conf->ss7.called_nai;
08845 ss7->calling_nai = conf->ss7.calling_nai;
08846 }
08847 #endif
08848 #ifdef HAVE_PRI
08849 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08850 int offset;
08851 int myswitchtype;
08852 int matchesdchan;
08853 int x,y;
08854 offset = 0;
08855 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
08856 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08857 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08858 destroy_dahdi_pvt(&tmp);
08859 return NULL;
08860 }
08861 if (span >= NUM_SPANS) {
08862 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08863 destroy_dahdi_pvt(&tmp);
08864 return NULL;
08865 } else {
08866 struct dahdi_spaninfo si;
08867 si.spanno = 0;
08868 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08869 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08870 destroy_dahdi_pvt(&tmp);
08871 return NULL;
08872 }
08873
08874 tmp->logicalspan = pris[span].prilogicalspan;
08875 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08876 if (span < 0) {
08877 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08878 destroy_dahdi_pvt(&tmp);
08879 return NULL;
08880 }
08881 if ((chan_sig == SIG_PRI) ||
08882 (chan_sig == SIG_BRI) ||
08883 (chan_sig == SIG_BRI_PTMP))
08884 myswitchtype = conf->pri.switchtype;
08885 else
08886 myswitchtype = PRI_SWITCH_GR303_TMC;
08887
08888 matchesdchan=0;
08889 for (x = 0; x < NUM_SPANS; x++) {
08890 for (y = 0; y < NUM_DCHANS; y++) {
08891 if (pris[x].dchannels[y] == tmp->channel) {
08892 matchesdchan = 1;
08893 break;
08894 }
08895 }
08896 }
08897 offset = p.chanpos;
08898 if (!matchesdchan) {
08899 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08900 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08901 destroy_dahdi_pvt(&tmp);
08902 return NULL;
08903 }
08904 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08905 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08906 destroy_dahdi_pvt(&tmp);
08907 return NULL;
08908 }
08909 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08910 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08911 destroy_dahdi_pvt(&tmp);
08912 return NULL;
08913 }
08914 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08915 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08916 destroy_dahdi_pvt(&tmp);
08917 return NULL;
08918 }
08919 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08920 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08921 destroy_dahdi_pvt(&tmp);
08922 return NULL;
08923 }
08924 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08925 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08926 destroy_dahdi_pvt(&tmp);
08927 return NULL;
08928 }
08929 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08930 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08931 destroy_dahdi_pvt(&tmp);
08932 return NULL;
08933 }
08934 if (pris[span].numchans >= MAX_CHANNELS) {
08935 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08936 pris[span].trunkgroup);
08937 destroy_dahdi_pvt(&tmp);
08938 return NULL;
08939 }
08940
08941 pris[span].sig = chan_sig;
08942 pris[span].nodetype = conf->pri.nodetype;
08943 pris[span].switchtype = myswitchtype;
08944 pris[span].nsf = conf->pri.nsf;
08945 pris[span].dialplan = conf->pri.dialplan;
08946 pris[span].localdialplan = conf->pri.localdialplan;
08947 pris[span].pvts[pris[span].numchans++] = tmp;
08948 pris[span].minunused = conf->pri.minunused;
08949 pris[span].minidle = conf->pri.minidle;
08950 pris[span].overlapdial = conf->pri.overlapdial;
08951 #ifdef HAVE_PRI_INBANDDISCONNECT
08952 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08953 #endif
08954 pris[span].facilityenable = conf->pri.facilityenable;
08955 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08956 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08957 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08958 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08959 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08960 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08961 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08962 pris[span].resetinterval = conf->pri.resetinterval;
08963
08964 tmp->pri = &pris[span];
08965 tmp->prioffset = offset;
08966 tmp->call = NULL;
08967 } else {
08968 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08969 destroy_dahdi_pvt(&tmp);
08970 return NULL;
08971 }
08972 }
08973 } else {
08974 tmp->prioffset = 0;
08975 }
08976 #endif
08977 } else {
08978 chan_sig = tmp->sig;
08979 if (tmp->subs[SUB_REAL].dfd > -1) {
08980 memset(&p, 0, sizeof(p));
08981 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08982 }
08983 }
08984
08985 switch (chan_sig) {
08986 case SIG_FXSKS:
08987 case SIG_FXSLS:
08988 case SIG_EM:
08989 case SIG_EM_E1:
08990 case SIG_EMWINK:
08991 case SIG_FEATD:
08992 case SIG_FEATDMF:
08993 case SIG_FEATDMF_TA:
08994 case SIG_FEATB:
08995 case SIG_E911:
08996 case SIG_SF:
08997 case SIG_SFWINK:
08998 case SIG_FGC_CAMA:
08999 case SIG_FGC_CAMAMF:
09000 case SIG_SF_FEATD:
09001 case SIG_SF_FEATDMF:
09002 case SIG_SF_FEATB:
09003 p.starttime = 250;
09004 break;
09005 }
09006
09007 if (tmp->radio) {
09008
09009 p.channo = channel;
09010 p.rxwinktime = 1;
09011 p.rxflashtime = 1;
09012 p.starttime = 1;
09013 p.debouncetime = 5;
09014 }
09015 if (!tmp->radio) {
09016 p.channo = channel;
09017
09018 if (conf->timing.prewinktime >= 0)
09019 p.prewinktime = conf->timing.prewinktime;
09020 if (conf->timing.preflashtime >= 0)
09021 p.preflashtime = conf->timing.preflashtime;
09022 if (conf->timing.winktime >= 0)
09023 p.winktime = conf->timing.winktime;
09024 if (conf->timing.flashtime >= 0)
09025 p.flashtime = conf->timing.flashtime;
09026 if (conf->timing.starttime >= 0)
09027 p.starttime = conf->timing.starttime;
09028 if (conf->timing.rxwinktime >= 0)
09029 p.rxwinktime = conf->timing.rxwinktime;
09030 if (conf->timing.rxflashtime >= 0)
09031 p.rxflashtime = conf->timing.rxflashtime;
09032 if (conf->timing.debouncetime >= 0)
09033 p.debouncetime = conf->timing.debouncetime;
09034 }
09035
09036
09037 if (tmp->subs[SUB_REAL].dfd >= 0)
09038 {
09039 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09040 if (res < 0) {
09041 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09042 destroy_dahdi_pvt(&tmp);
09043 return NULL;
09044 }
09045 }
09046 #if 1
09047 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09048 memset(&bi, 0, sizeof(bi));
09049 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09050 if (!res) {
09051 bi.txbufpolicy = conf->chan.buf_policy;
09052 bi.rxbufpolicy = conf->chan.buf_policy;
09053 bi.numbufs = conf->chan.buf_no;
09054 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09055 if (res < 0) {
09056 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09057 }
09058 } else
09059 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09060 }
09061 #endif
09062 tmp->immediate = conf->chan.immediate;
09063 tmp->transfertobusy = conf->chan.transfertobusy;
09064 if (chan_sig & __DAHDI_SIG_FXS) {
09065 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
09066 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
09067 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
09068 }
09069 tmp->sig = chan_sig;
09070 tmp->outsigmod = conf->chan.outsigmod;
09071 tmp->ringt_base = ringt_base;
09072 tmp->firstradio = 0;
09073 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09074 tmp->permcallwaiting = conf->chan.callwaiting;
09075 else
09076 tmp->permcallwaiting = 0;
09077
09078 tmp->destroy = 0;
09079 tmp->drings = conf->chan.drings;
09080
09081
09082 if (tmp->drings.ringnum[0].range == 0)
09083 tmp->drings.ringnum[0].range = 10;
09084 if (tmp->drings.ringnum[1].range == 0)
09085 tmp->drings.ringnum[1].range = 10;
09086 if (tmp->drings.ringnum[2].range == 0)
09087 tmp->drings.ringnum[2].range = 10;
09088
09089 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
09090 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09091 tmp->threewaycalling = conf->chan.threewaycalling;
09092 tmp->adsi = conf->chan.adsi;
09093 tmp->use_smdi = conf->chan.use_smdi;
09094 tmp->permhidecallerid = conf->chan.hidecallerid;
09095 tmp->callreturn = conf->chan.callreturn;
09096 tmp->echocancel = conf->chan.echocancel;
09097 tmp->echotraining = conf->chan.echotraining;
09098 tmp->pulse = conf->chan.pulse;
09099 if (tmp->echocancel.head.tap_length) {
09100 tmp->echocanbridged = conf->chan.echocanbridged;
09101 } else {
09102 if (conf->chan.echocanbridged)
09103 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09104 tmp->echocanbridged = 0;
09105 }
09106 tmp->busydetect = conf->chan.busydetect;
09107 tmp->busycount = conf->chan.busycount;
09108 tmp->busy_tonelength = conf->chan.busy_tonelength;
09109 tmp->busy_quietlength = conf->chan.busy_quietlength;
09110 tmp->callprogress = conf->chan.callprogress;
09111 tmp->cancallforward = conf->chan.cancallforward;
09112 tmp->dtmfrelax = conf->chan.dtmfrelax;
09113 tmp->callwaiting = tmp->permcallwaiting;
09114 tmp->hidecallerid = tmp->permhidecallerid;
09115 tmp->channel = channel;
09116 tmp->stripmsd = conf->chan.stripmsd;
09117 tmp->use_callerid = conf->chan.use_callerid;
09118 tmp->cid_signalling = conf->chan.cid_signalling;
09119 tmp->cid_start = conf->chan.cid_start;
09120 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09121 tmp->restrictcid = conf->chan.restrictcid;
09122 tmp->use_callingpres = conf->chan.use_callingpres;
09123 tmp->priexclusive = conf->chan.priexclusive;
09124 if (tmp->usedistinctiveringdetection) {
09125 if (!tmp->use_callerid) {
09126 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09127 tmp->use_callerid = 1;
09128 }
09129 }
09130
09131 if (tmp->cid_signalling == CID_SIG_SMDI) {
09132 if (!tmp->use_smdi) {
09133 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09134 tmp->use_smdi = 1;
09135 }
09136 }
09137 if (tmp->use_smdi) {
09138 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09139 if (!(tmp->smdi_iface)) {
09140 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09141 tmp->use_smdi = 0;
09142 }
09143 }
09144
09145 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09146 tmp->amaflags = conf->chan.amaflags;
09147 if (!here) {
09148 tmp->confno = -1;
09149 tmp->propconfno = -1;
09150 }
09151 tmp->canpark = conf->chan.canpark;
09152 tmp->transfer = conf->chan.transfer;
09153 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09154 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09155 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09156 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09157 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09158 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09159 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
09160 tmp->cid_ton = 0;
09161 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09162 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09163 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
09164 char *mailbox, *context;
09165 mailbox = context = ast_strdupa(tmp->mailbox);
09166 strsep(&context, "@");
09167 if (ast_strlen_zero(context))
09168 context = "default";
09169 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
09170 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
09171 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
09172 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
09173 AST_EVENT_IE_END);
09174 }
09175 tmp->msgstate = -1;
09176 tmp->group = conf->chan.group;
09177 tmp->callgroup = conf->chan.callgroup;
09178 tmp->pickupgroup= conf->chan.pickupgroup;
09179 if (conf->chan.vars) {
09180 tmp->vars = conf->chan.vars;
09181 }
09182 tmp->cid_rxgain = conf->chan.cid_rxgain;
09183 tmp->rxgain = conf->chan.rxgain;
09184 tmp->txgain = conf->chan.txgain;
09185 tmp->tonezone = conf->chan.tonezone;
09186 tmp->onhooktime = time(NULL);
09187 if (tmp->subs[SUB_REAL].dfd > -1) {
09188 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09189 if (tmp->dsp)
09190 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09191 update_conf(tmp);
09192 if (!here) {
09193 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
09194
09195 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09196 }
09197 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09198 #ifdef HAVE_PRI
09199
09200 if (tmp->pri && !pri_is_up(tmp->pri))
09201 tmp->inalarm = 1;
09202 #endif
09203 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09204 tmp->inalarm = 1;
09205 handle_alarms(tmp, res);
09206 }
09207 }
09208
09209 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09210 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09211 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09212 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09213 if (!here) {
09214 tmp->locallyblocked = tmp->remotelyblocked = 0;
09215 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09216 tmp->inservice = 0;
09217 else
09218 tmp->inservice = 1;
09219 }
09220 }
09221 if (tmp && !here) {
09222
09223 if (!*wlist) {
09224 *wlist = tmp;
09225 tmp->prev = NULL;
09226 tmp->next = NULL;
09227 *wend = tmp;
09228 } else {
09229
09230 struct dahdi_pvt *working = *wlist;
09231
09232
09233 if (working->channel > tmp->channel) {
09234 tmp->next = *wlist;
09235 tmp->prev = NULL;
09236 (*wlist)->prev = tmp;
09237 *wlist = tmp;
09238 } else {
09239
09240 while (working) {
09241
09242 if (working->next) {
09243 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09244 tmp->next = working->next;
09245 tmp->prev = working;
09246 working->next->prev = tmp;
09247 working->next = tmp;
09248 break;
09249 }
09250 } else {
09251
09252 if (working->channel < tmp->channel) {
09253 working->next = tmp;
09254 tmp->next = NULL;
09255 tmp->prev = working;
09256 *wend = tmp;
09257 break;
09258 }
09259 }
09260 working = working->next;
09261 }
09262 }
09263 }
09264 }
09265 return tmp;
09266 }
09267
09268 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09269 {
09270 int res;
09271 struct dahdi_params par;
09272
09273
09274 if (groupmatch) {
09275 if ((p->group & groupmatch) != groupmatch)
09276 return 0;
09277 *groupmatched = 1;
09278 }
09279
09280 if (channelmatch != -1) {
09281 if (p->channel != channelmatch)
09282 return 0;
09283 *channelmatched = 1;
09284 }
09285
09286 if (busy) {
09287 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09288 *busy = 1;
09289 }
09290
09291 if (p->dnd)
09292 return 0;
09293
09294 if (p->guardtime && (time(NULL) < p->guardtime))
09295 return 0;
09296
09297 if (p->locallyblocked || p->remotelyblocked)
09298 return 0;
09299
09300
09301 if (!p->owner) {
09302 #ifdef HAVE_PRI
09303
09304 if (p->pri) {
09305 if (p->resetting || p->call)
09306 return 0;
09307 else
09308 return 1;
09309 }
09310 #endif
09311 #ifdef HAVE_SS7
09312
09313 if (p->ss7) {
09314 if (p->ss7call)
09315 return 0;
09316 else
09317 return 1;
09318 }
09319 #endif
09320 if (!(p->radio || (p->oprmode < 0)))
09321 {
09322 if (!p->sig || (p->sig == SIG_FXSLS))
09323 return 1;
09324
09325 if (p->subs[SUB_REAL].dfd > -1) {
09326 memset(&par, 0, sizeof(par));
09327 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09328 } else {
09329
09330 res = 0;
09331 par.rxisoffhook = 0;
09332 }
09333 if (res) {
09334 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09335 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09336
09337
09338
09339 if (par.rxbits > -1)
09340 return 1;
09341 if (par.rxisoffhook)
09342 return 1;
09343 else
09344 return 0;
09345 } else if (par.rxisoffhook) {
09346 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09347
09348 #ifdef DAHDI_CHECK_HOOKSTATE
09349 return 0;
09350 #else
09351 return 1;
09352 #endif
09353 }
09354 }
09355 return 1;
09356 }
09357
09358
09359 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09360 return 0;
09361
09362 if (!p->callwaiting) {
09363
09364 return 0;
09365 }
09366
09367 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09368
09369 return 0;
09370 }
09371
09372 if ((p->owner->_state != AST_STATE_UP) &&
09373 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09374
09375 return 0;
09376 }
09377 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09378
09379 return 0;
09380 }
09381
09382 return 1;
09383 }
09384
09385 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09386 {
09387 struct dahdi_pvt *p;
09388 struct dahdi_bufferinfo bi;
09389 int res;
09390
09391 if ((p = ast_malloc(sizeof(*p)))) {
09392 memcpy(p, src, sizeof(struct dahdi_pvt));
09393 ast_mutex_init(&p->lock);
09394 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09395
09396 if (p->subs[SUB_REAL].dfd < 0) {
09397 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09398 destroy_dahdi_pvt(&p);
09399 return NULL;
09400 }
09401 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09402 if (!res) {
09403 bi.txbufpolicy = src->buf_policy;
09404 bi.rxbufpolicy = src->buf_policy;
09405 bi.numbufs = src->buf_no;
09406 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09407 if (res < 0) {
09408 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09409 }
09410 } else
09411 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09412 }
09413 p->destroy = 1;
09414 p->next = iflist;
09415 p->prev = NULL;
09416 iflist = p;
09417 if (iflist->next)
09418 iflist->next->prev = p;
09419 return p;
09420 }
09421
09422
09423 #ifdef HAVE_PRI
09424 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09425 {
09426 int x;
09427 if (backwards)
09428 x = pri->numchans;
09429 else
09430 x = 0;
09431 for (;;) {
09432 if (backwards && (x < 0))
09433 break;
09434 if (!backwards && (x >= pri->numchans))
09435 break;
09436 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09437 ast_debug(1, "Found empty available channel %d/%d\n",
09438 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09439 return x;
09440 }
09441 if (backwards)
09442 x--;
09443 else
09444 x++;
09445 }
09446 return -1;
09447 }
09448 #endif
09449
09450 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09451 {
09452 ast_group_t groupmatch = 0;
09453 int channelmatch = -1;
09454 int roundrobin = 0;
09455 int callwait = 0;
09456 int busy = 0;
09457 struct dahdi_pvt *p;
09458 struct ast_channel *tmp = NULL;
09459 char *dest=NULL;
09460 int x;
09461 char *s;
09462 char opt=0;
09463 int res=0, y=0;
09464 int backwards = 0;
09465 #ifdef HAVE_PRI
09466 int crv;
09467 int bearer = -1;
09468 int trunkgroup;
09469 struct dahdi_pri *pri=NULL;
09470 #endif
09471 struct dahdi_pvt *exitpvt, *start, *end;
09472 ast_mutex_t *lock;
09473 int channelmatched = 0;
09474 int groupmatched = 0;
09475
09476
09477
09478
09479
09480
09481
09482
09483
09484
09485
09486
09487
09488
09489
09490
09491
09492
09493
09494 lock = &iflock;
09495 start = iflist;
09496 end = ifend;
09497 if (data) {
09498 dest = ast_strdupa((char *)data);
09499 } else {
09500 ast_log(LOG_WARNING, "Channel requested with no data\n");
09501 return NULL;
09502 }
09503 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09504
09505 char *stringp;
09506
09507 stringp = dest + 1;
09508 s = strsep(&stringp, "/");
09509 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09510 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09511 return NULL;
09512 }
09513 groupmatch = ((ast_group_t) 1 << x);
09514 if (toupper(dest[0]) == 'G') {
09515 if (dest[0] == 'G') {
09516 backwards = 1;
09517 p = ifend;
09518 } else
09519 p = iflist;
09520 } else {
09521 if (dest[0] == 'R') {
09522 backwards = 1;
09523 p = round_robin[x]?round_robin[x]->prev:ifend;
09524 if (!p)
09525 p = ifend;
09526 } else {
09527 p = round_robin[x]?round_robin[x]->next:iflist;
09528 if (!p)
09529 p = iflist;
09530 }
09531 roundrobin = 1;
09532 }
09533 } else {
09534 char *stringp;
09535
09536 stringp = dest;
09537 s = strsep(&stringp, "/");
09538 p = iflist;
09539 if (!strcasecmp(s, "pseudo")) {
09540
09541 x = CHAN_PSEUDO;
09542 channelmatch = x;
09543 }
09544 #ifdef HAVE_PRI
09545 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09546 if ((trunkgroup < 1) || (crv < 1)) {
09547 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09548 return NULL;
09549 }
09550 res--;
09551 for (x = 0; x < NUM_SPANS; x++) {
09552 if (pris[x].trunkgroup == trunkgroup) {
09553 pri = pris + x;
09554 lock = &pri->lock;
09555 start = pri->crvs;
09556 end = pri->crvend;
09557 break;
09558 }
09559 }
09560 if (!pri) {
09561 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09562 return NULL;
09563 }
09564 channelmatch = crv;
09565 p = pris[x].crvs;
09566 }
09567 #endif
09568 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09569 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09570 return NULL;
09571 } else {
09572 channelmatch = x;
09573 }
09574 }
09575
09576 ast_mutex_lock(lock);
09577 exitpvt = p;
09578 while (p && !tmp) {
09579 if (roundrobin)
09580 round_robin[x] = p;
09581 #if 0
09582 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09583 #endif
09584
09585 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09586 ast_debug(1, "Using channel %d\n", p->channel);
09587 if (p->inalarm)
09588 goto next;
09589
09590 callwait = (p->owner != NULL);
09591 #ifdef HAVE_PRI
09592 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09593 if (p->sig != SIG_FXSKS) {
09594
09595
09596 bearer = pri_find_empty_chan(pri, 0);
09597 if (bearer < 0) {
09598 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09599 p = NULL;
09600 break;
09601 }
09602 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09603 } else {
09604 if (alloc_sub(p, 0)) {
09605 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09606 p = NULL;
09607 break;
09608 } else
09609 ast_debug(1, "Allocated placeholder pseudo channel\n");
09610
09611 p->pri = pri;
09612 }
09613 }
09614 #endif
09615 if (p->channel == CHAN_PSEUDO) {
09616 p = chandup(p);
09617 if (!p) {
09618 break;
09619 }
09620 }
09621 if (p->owner) {
09622 if (alloc_sub(p, SUB_CALLWAIT)) {
09623 p = NULL;
09624 break;
09625 }
09626 }
09627 p->outgoing = 1;
09628 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09629 #ifdef HAVE_PRI
09630 if (p->bearer) {
09631
09632 p->bearer->owner = tmp;
09633 }
09634 #endif
09635
09636 if (res > 1) {
09637 if (opt == 'c') {
09638
09639 p->confirmanswer = 1;
09640 } else if (opt == 'r') {
09641
09642 if (res < 3)
09643 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09644 else
09645 p->distinctivering = y;
09646 } else if (opt == 'd') {
09647
09648 p->digital = 1;
09649 if (tmp)
09650 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09651 } else {
09652 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09653 }
09654 }
09655
09656 if (tmp && callwait)
09657 tmp->cdrflags |= AST_CDR_CALLWAIT;
09658 break;
09659 }
09660 next:
09661 if (backwards) {
09662 p = p->prev;
09663 if (!p)
09664 p = end;
09665 } else {
09666 p = p->next;
09667 if (!p)
09668 p = start;
09669 }
09670
09671 if (p == exitpvt)
09672 break;
09673 }
09674 ast_mutex_unlock(lock);
09675 restart_monitor();
09676 if (callwait)
09677 *cause = AST_CAUSE_BUSY;
09678 else if (!tmp) {
09679 if (channelmatched) {
09680 if (busy)
09681 *cause = AST_CAUSE_BUSY;
09682 } else if (groupmatched) {
09683 *cause = AST_CAUSE_CONGESTION;
09684 }
09685 }
09686
09687 return tmp;
09688 }
09689
09690 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09691 static int dahdi_setlaw(int dfd, int law)
09692 {
09693 return ioctl(dfd, DAHDI_SETLAW, &law);
09694 }
09695 #endif
09696
09697 #ifdef HAVE_SS7
09698
09699 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
09700 {
09701 int i;
09702 int winner = -1;
09703 for (i = 0; i < linkset->numchans; i++) {
09704 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09705 winner = i;
09706 break;
09707 }
09708 }
09709 return winner;
09710 }
09711
09712 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09713 {
09714 unsigned char status[32];
09715 struct dahdi_pvt *p = NULL;
09716 int i, offset;
09717
09718 for (i = 0; i < linkset->numchans; i++) {
09719 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09720 p = linkset->pvts[i];
09721 offset = p->cic - startcic;
09722 status[offset] = 0;
09723 if (p->locallyblocked)
09724 status[offset] |= (1 << 0) | (1 << 4);
09725 if (p->remotelyblocked)
09726 status[offset] |= (1 << 1) | (1 << 5);
09727 if (p->ss7call) {
09728 if (p->outgoing)
09729 status[offset] |= (1 << 3);
09730 else
09731 status[offset] |= (1 << 2);
09732 } else
09733 status[offset] |= 0x3 << 2;
09734 }
09735 }
09736
09737 if (p)
09738 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09739 else
09740 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09741
09742 }
09743
09744 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
09745 {
09746 int i;
09747
09748 for (i = 0; i < linkset->numchans; i++) {
09749 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09750 if (state) {
09751 if (state[i])
09752 linkset->pvts[i]->remotelyblocked = block;
09753 } else
09754 linkset->pvts[i]->remotelyblocked = block;
09755 }
09756 }
09757 }
09758
09759 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09760 {
09761 int i;
09762
09763 for (i = 0; i < linkset->numchans; i++) {
09764 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09765 linkset->pvts[i]->inservice = 1;
09766 }
09767 }
09768
09769 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
09770 {
09771 int i, startcic = -1, endcic, dpc;
09772
09773 if (linkset->numchans <= 0)
09774 return;
09775
09776 startcic = linkset->pvts[0]->cic;
09777
09778 dpc = linkset->pvts[0]->dpc;
09779
09780 for (i = 0; i < linkset->numchans; i++) {
09781 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)) {
09782 continue;
09783 } else {
09784 endcic = linkset->pvts[i]->cic;
09785 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09786 isup_grs(linkset->ss7, startcic, endcic, dpc);
09787
09788
09789 if (linkset->pvts[i+1]) {
09790 startcic = linkset->pvts[i+1]->cic;
09791 dpc = linkset->pvts[i+1]->dpc;
09792 }
09793 }
09794 }
09795 }
09796
09797 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
09798 {
09799 if (p->loopedback != enable) {
09800 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09801 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09802 return;
09803 }
09804 p->loopedback = enable;
09805 }
09806 }
09807
09808
09809 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
09810 {
09811 struct ss7 *ss7 = linkset->ss7;
09812 int res;
09813 int law = 1;
09814 struct ast_channel *c;
09815 char tmp[256];
09816
09817 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09818 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09819
09820 if (linkset->type == SS7_ITU)
09821 law = DAHDI_LAW_ALAW;
09822 else
09823 law = DAHDI_LAW_MULAW;
09824
09825 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09826 if (res < 0)
09827 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09828
09829 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09830 p->proceeding = 1;
09831 isup_acm(ss7, p->ss7call);
09832 }
09833
09834 ast_mutex_unlock(&linkset->lock);
09835 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09836
09837 if (!c) {
09838 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09839
09840 ast_mutex_lock(&linkset->lock);
09841 return;
09842 } else
09843 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09844
09845 dahdi_enable_ec(p);
09846
09847
09848
09849
09850
09851 ast_mutex_unlock(&p->lock);
09852
09853 if (!ast_strlen_zero(p->charge_number)) {
09854 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09855
09856 p->charge_number[0] = 0;
09857 }
09858 if (!ast_strlen_zero(p->gen_add_number)) {
09859 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09860
09861 p->gen_add_number[0] = 0;
09862 }
09863 if (!ast_strlen_zero(p->jip_number)) {
09864 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09865
09866 p->jip_number[0] = 0;
09867 }
09868 if (!ast_strlen_zero(p->gen_dig_number)) {
09869 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09870
09871 p->gen_dig_number[0] = 0;
09872 }
09873 if (!ast_strlen_zero(p->orig_called_num)) {
09874 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09875
09876 p->orig_called_num[0] = 0;
09877 }
09878
09879 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09880 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09881
09882 p->gen_dig_type = 0;
09883
09884 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09885 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09886
09887 p->gen_dig_scheme = 0;
09888
09889 if (!ast_strlen_zero(p->lspi_ident)) {
09890 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
09891
09892 p->lspi_ident[0] = 0;
09893 }
09894
09895 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
09896 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
09897
09898 p->call_ref_ident = 0;
09899
09900 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
09901 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
09902
09903 p->call_ref_pc = 0;
09904
09905 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
09906 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
09907
09908 p->calling_party_cat = 0;
09909
09910 if (!ast_strlen_zero(p->redirecting_num)) {
09911 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
09912
09913 p->redirecting_num[0] = 0;
09914 }
09915 if (!ast_strlen_zero(p->generic_name)) {
09916 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
09917
09918 p->generic_name[0] = 0;
09919 }
09920
09921 ast_mutex_lock(&p->lock);
09922 ast_mutex_lock(&linkset->lock);
09923 }
09924
09925 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
09926 {
09927 if (ast_strlen_zero(number)) {
09928 if (size) {
09929 *buf = '\0';
09930 }
09931 return;
09932 }
09933 switch (nai) {
09934 case SS7_NAI_INTERNATIONAL:
09935 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
09936 break;
09937 case SS7_NAI_NATIONAL:
09938 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
09939 break;
09940 case SS7_NAI_SUBSCRIBER:
09941 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
09942 break;
09943 case SS7_NAI_UNKNOWN:
09944 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
09945 break;
09946 default:
09947 snprintf(buf, size, "%s", number);
09948 break;
09949 }
09950 }
09951 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
09952 {
09953 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
09954 }
09955
09956 static void *ss7_linkset(void *data)
09957 {
09958 int res, i;
09959 struct timeval *next = NULL, tv;
09960 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
09961 struct ss7 *ss7 = linkset->ss7;
09962 ss7_event *e = NULL;
09963 struct dahdi_pvt *p;
09964 int chanpos;
09965 struct pollfd pollers[NUM_DCHANS];
09966 int cic;
09967 unsigned int dpc;
09968 int nextms = 0;
09969
09970 ss7_start(ss7);
09971
09972 while(1) {
09973 ast_mutex_lock(&linkset->lock);
09974 if ((next = ss7_schedule_next(ss7))) {
09975 tv = ast_tvnow();
09976 tv.tv_sec = next->tv_sec - tv.tv_sec;
09977 tv.tv_usec = next->tv_usec - tv.tv_usec;
09978 if (tv.tv_usec < 0) {
09979 tv.tv_usec += 1000000;
09980 tv.tv_sec -= 1;
09981 }
09982 if (tv.tv_sec < 0) {
09983 tv.tv_sec = 0;
09984 tv.tv_usec = 0;
09985 }
09986 nextms = tv.tv_sec * 1000;
09987 nextms += tv.tv_usec / 1000;
09988 }
09989 ast_mutex_unlock(&linkset->lock);
09990
09991 for (i = 0; i < linkset->numsigchans; i++) {
09992 pollers[i].fd = linkset->fds[i];
09993 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
09994 pollers[i].revents = 0;
09995 }
09996
09997 res = poll(pollers, linkset->numsigchans, nextms);
09998 if ((res < 0) && (errno != EINTR)) {
09999 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
10000 } else if (!res) {
10001 ast_mutex_lock(&linkset->lock);
10002 ss7_schedule_run(ss7);
10003 ast_mutex_unlock(&linkset->lock);
10004 continue;
10005 }
10006
10007 ast_mutex_lock(&linkset->lock);
10008 for (i = 0; i < linkset->numsigchans; i++) {
10009 if (pollers[i].revents & POLLPRI) {
10010 int x;
10011 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
10012 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
10013 }
10014 switch (x) {
10015 case DAHDI_EVENT_OVERRUN:
10016 ast_debug(1, "Overrun detected!\n");
10017 break;
10018 case DAHDI_EVENT_BADFCS:
10019 ast_debug(1, "Bad FCS\n");
10020 break;
10021 case DAHDI_EVENT_ABORT:
10022 ast_debug(1, "HDLC Abort\n");
10023 break;
10024 case DAHDI_EVENT_ALARM:
10025 ast_log(LOG_ERROR, "Alarm on link!\n");
10026 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
10027 linkset->linkstate[i] &= ~LINKSTATE_UP;
10028 ss7_link_alarm(ss7, pollers[i].fd);
10029 break;
10030 case DAHDI_EVENT_NOALARM:
10031 ast_log(LOG_ERROR, "Alarm cleared on link\n");
10032 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
10033 linkset->linkstate[i] |= LINKSTATE_STARTING;
10034 ss7_link_noalarm(ss7, pollers[i].fd);
10035 break;
10036 default:
10037 ast_log(LOG_ERROR, "Got exception %d!\n", x);
10038 break;
10039 }
10040 }
10041
10042 if (pollers[i].revents & POLLIN) {
10043 ast_mutex_lock(&linkset->lock);
10044 res = ss7_read(ss7, pollers[i].fd);
10045 ast_mutex_unlock(&linkset->lock);
10046 }
10047
10048 if (pollers[i].revents & POLLOUT) {
10049 ast_mutex_lock(&linkset->lock);
10050 res = ss7_write(ss7, pollers[i].fd);
10051 ast_mutex_unlock(&linkset->lock);
10052 if (res < 0) {
10053 ast_debug(1, "Error in write %s\n", strerror(errno));
10054 }
10055 }
10056 }
10057
10058 while ((e = ss7_check_event(ss7))) {
10059 switch (e->e) {
10060 case SS7_EVENT_UP:
10061 if (linkset->state != LINKSET_STATE_UP) {
10062 ast_verbose("--- SS7 Up ---\n");
10063 ss7_reset_linkset(linkset);
10064 }
10065 linkset->state = LINKSET_STATE_UP;
10066 break;
10067 case SS7_EVENT_DOWN:
10068 ast_verbose("--- SS7 Down ---\n");
10069 linkset->state = LINKSET_STATE_DOWN;
10070 for (i = 0; i < linkset->numchans; i++) {
10071 struct dahdi_pvt *p = linkset->pvts[i];
10072 if (p)
10073 p->inalarm = 1;
10074 }
10075 break;
10076 case MTP2_LINK_UP:
10077 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
10078 break;
10079 case MTP2_LINK_DOWN:
10080 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
10081 break;
10082 case ISUP_EVENT_CPG:
10083 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
10084 if (chanpos < 0) {
10085 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
10086 break;
10087 }
10088 p = linkset->pvts[chanpos];
10089 ast_mutex_lock(&p->lock);
10090 switch (e->cpg.event) {
10091 case CPG_EVENT_ALERTING:
10092 p->alerting = 1;
10093 p->subs[SUB_REAL].needringing = 1;
10094 break;
10095 case CPG_EVENT_PROGRESS:
10096 case CPG_EVENT_INBANDINFO:
10097 {
10098 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10099 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
10100 dahdi_queue_frame(p, &f, linkset);
10101 p->progress = 1;
10102 p->dialing = 0;
10103 if (p->dsp && p->dsp_features) {
10104 ast_dsp_set_features(p->dsp, p->dsp_features);
10105 p->dsp_features = 0;
10106 }
10107 }
10108 break;
10109 default:
10110 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
10111 }
10112
10113 ast_mutex_unlock(&p->lock);
10114 break;
10115 case ISUP_EVENT_RSC:
10116 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
10117 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
10118 if (chanpos < 0) {
10119 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
10120 break;
10121 }
10122 p = linkset->pvts[chanpos];
10123 ast_mutex_lock(&p->lock);
10124 p->inservice = 1;
10125 p->remotelyblocked = 0;
10126 dpc = p->dpc;
10127 isup_set_call_dpc(e->rsc.call, dpc);
10128 if (p->ss7call)
10129 p->ss7call = NULL;
10130 if (p->owner)
10131 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10132 ast_mutex_unlock(&p->lock);
10133 isup_rlc(ss7, e->rsc.call);
10134 break;
10135 case ISUP_EVENT_GRS:
10136 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
10137 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
10138 if (chanpos < 0) {
10139 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
10140 break;
10141 }
10142 p = linkset->pvts[chanpos];
10143 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
10144 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
10145 break;
10146 case ISUP_EVENT_CQM:
10147 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
10148 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
10149 break;
10150 case ISUP_EVENT_GRA:
10151 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
10152 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
10153 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
10154 break;
10155 case ISUP_EVENT_IAM:
10156 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);
10157 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
10158 if (chanpos < 0) {
10159 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
10160 isup_rel(ss7, e->iam.call, -1);
10161 break;
10162 }
10163 p = linkset->pvts[chanpos];
10164 ast_mutex_lock(&p->lock);
10165 if (p->owner) {
10166 if (p->ss7call == e->iam.call) {
10167 ast_mutex_unlock(&p->lock);
10168 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
10169 break;
10170 } else {
10171 ast_mutex_unlock(&p->lock);
10172 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
10173 break;
10174 }
10175 }
10176
10177 dpc = p->dpc;
10178 p->ss7call = e->iam.call;
10179 isup_set_call_dpc(p->ss7call, dpc);
10180
10181 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
10182 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
10183 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
10184 } else
10185 p->cid_num[0] = 0;
10186
10187 if (p->immediate) {
10188 p->exten[0] = 's';
10189 p->exten[1] = '\0';
10190 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
10191 char *st;
10192 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
10193 st = strchr(p->exten, '#');
10194 if (st)
10195 *st = '\0';
10196 } else
10197 p->exten[0] = '\0';
10198
10199 p->cid_ani[0] = '\0';
10200 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
10201 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
10202 else
10203 p->cid_name[0] = '\0';
10204
10205 p->cid_ani2 = e->iam.oli_ani2;
10206 p->cid_ton = 0;
10207 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
10208 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
10209 p->gen_add_type = e->iam.gen_add_type;
10210 p->gen_add_nai = e->iam.gen_add_nai;
10211 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
10212 p->gen_add_num_plan = e->iam.gen_add_num_plan;
10213 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
10214 p->gen_dig_type = e->iam.gen_dig_type;
10215 p->gen_dig_scheme = e->iam.gen_dig_scheme;
10216 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
10217 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
10218 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
10219 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
10220 p->calling_party_cat = e->iam.calling_party_cat;
10221
10222
10223 if (!ast_strlen_zero(e->iam.called_party_num))
10224 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
10225
10226 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
10227
10228 if (e->iam.cot_check_required) {
10229 dahdi_loopback(p, 1);
10230 } else
10231 ss7_start_call(p, linkset);
10232 } else {
10233 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
10234 p->alreadyhungup = 1;
10235 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
10236 }
10237 ast_mutex_unlock(&p->lock);
10238 break;
10239 case ISUP_EVENT_COT:
10240 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
10241 if (chanpos < 0) {
10242 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
10243 isup_rel(ss7, e->cot.call, -1);
10244 break;
10245 }
10246 p = linkset->pvts[chanpos];
10247
10248 ast_mutex_lock(&p->lock);
10249
10250 if (p->loopedback) {
10251 dahdi_loopback(p, 0);
10252 ss7_start_call(p, linkset);
10253 }
10254
10255 ast_mutex_unlock(&p->lock);
10256
10257 break;
10258 case ISUP_EVENT_CCR:
10259 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
10260 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
10261 if (chanpos < 0) {
10262 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
10263 break;
10264 }
10265
10266 p = linkset->pvts[chanpos];
10267
10268 ast_mutex_lock(&p->lock);
10269 dahdi_loopback(p, 1);
10270 ast_mutex_unlock(&p->lock);
10271
10272 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
10273 break;
10274 case ISUP_EVENT_CVT:
10275 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
10276 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
10277 if (chanpos < 0) {
10278 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
10279 break;
10280 }
10281
10282 p = linkset->pvts[chanpos];
10283
10284 ast_mutex_lock(&p->lock);
10285 dahdi_loopback(p, 1);
10286 ast_mutex_unlock(&p->lock);
10287
10288 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
10289 break;
10290 case ISUP_EVENT_REL:
10291 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
10292 if (chanpos < 0) {
10293 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
10294 break;
10295 }
10296 p = linkset->pvts[chanpos];
10297 ast_mutex_lock(&p->lock);
10298 if (p->owner) {
10299 p->owner->hangupcause = e->rel.cause;
10300 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10301 } else if (!p->restartpending)
10302 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
10303
10304
10305 dahdi_loopback(p, 0);
10306
10307 isup_rlc(ss7, e->rel.call);
10308 p->ss7call = NULL;
10309
10310 ast_mutex_unlock(&p->lock);
10311 break;
10312 case ISUP_EVENT_ACM:
10313 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
10314 if (chanpos < 0) {
10315 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
10316 isup_rel(ss7, e->acm.call, -1);
10317 break;
10318 } else {
10319 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10320
10321 p = linkset->pvts[chanpos];
10322
10323 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
10324
10325 if (e->acm.call_ref_ident > 0) {
10326 p->rlt = 1;
10327 }
10328
10329 ast_mutex_lock(&p->lock);
10330 dahdi_queue_frame(p, &f, linkset);
10331 p->proceeding = 1;
10332 p->dialing = 0;
10333
10334 if (e->acm.called_party_status_ind == 1) {
10335 p->alerting = 1;
10336 p->subs[SUB_REAL].needringing = 1;
10337 }
10338 ast_mutex_unlock(&p->lock);
10339 }
10340 break;
10341 case ISUP_EVENT_CGB:
10342 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
10343 if (chanpos < 0) {
10344 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
10345 break;
10346 }
10347 p = linkset->pvts[chanpos];
10348 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
10349 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
10350 break;
10351 case ISUP_EVENT_CGU:
10352 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
10353 if (chanpos < 0) {
10354 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
10355 break;
10356 }
10357 p = linkset->pvts[chanpos];
10358 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
10359 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
10360 break;
10361 case ISUP_EVENT_UCIC:
10362 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
10363 if (chanpos < 0) {
10364 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
10365 break;
10366 }
10367 p = linkset->pvts[chanpos];
10368 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
10369 ast_mutex_lock(&p->lock);
10370 p->remotelyblocked = 1;
10371 p->inservice = 0;
10372 ast_mutex_unlock(&p->lock);
10373 break;
10374 case ISUP_EVENT_BLO:
10375 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
10376 if (chanpos < 0) {
10377 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
10378 break;
10379 }
10380 p = linkset->pvts[chanpos];
10381 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
10382 ast_mutex_lock(&p->lock);
10383 p->remotelyblocked = 1;
10384 ast_mutex_unlock(&p->lock);
10385 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
10386 break;
10387 case ISUP_EVENT_BLA:
10388 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
10389 if (chanpos < 0) {
10390 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
10391 break;
10392 }
10393 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
10394 p = linkset->pvts[chanpos];
10395 ast_mutex_lock(&p->lock);
10396 p->locallyblocked = 1;
10397 ast_mutex_unlock(&p->lock);
10398 break;
10399 case ISUP_EVENT_UBL:
10400 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
10401 if (chanpos < 0) {
10402 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
10403 break;
10404 }
10405 p = linkset->pvts[chanpos];
10406 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
10407 ast_mutex_lock(&p->lock);
10408 p->remotelyblocked = 0;
10409 ast_mutex_unlock(&p->lock);
10410 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
10411 break;
10412 case ISUP_EVENT_UBA:
10413 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
10414 if (chanpos < 0) {
10415 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
10416 break;
10417 }
10418 p = linkset->pvts[chanpos];
10419 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
10420 ast_mutex_lock(&p->lock);
10421 p->locallyblocked = 0;
10422 ast_mutex_unlock(&p->lock);
10423 break;
10424 case ISUP_EVENT_CON:
10425 case ISUP_EVENT_ANM:
10426 if (e->e == ISUP_EVENT_CON)
10427 cic = e->con.cic;
10428 else
10429 cic = e->anm.cic;
10430
10431 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
10432 if (chanpos < 0) {
10433 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
10434 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
10435 break;
10436 } else {
10437 p = linkset->pvts[chanpos];
10438 ast_mutex_lock(&p->lock);
10439 p->subs[SUB_REAL].needanswer = 1;
10440 if (p->dsp && p->dsp_features) {
10441 ast_dsp_set_features(p->dsp, p->dsp_features);
10442 p->dsp_features = 0;
10443 }
10444 dahdi_enable_ec(p);
10445 ast_mutex_unlock(&p->lock);
10446 }
10447 break;
10448 case ISUP_EVENT_RLC:
10449 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
10450 if (chanpos < 0) {
10451 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
10452 break;
10453 } else {
10454 p = linkset->pvts[chanpos];
10455 ast_mutex_lock(&p->lock);
10456 if (p->alreadyhungup)
10457 p->ss7call = NULL;
10458 else
10459 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
10460 ast_mutex_unlock(&p->lock);
10461 }
10462 break;
10463 case ISUP_EVENT_FAA:
10464 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
10465 if (chanpos < 0) {
10466 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
10467 break;
10468 } else {
10469 p = linkset->pvts[chanpos];
10470 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
10471 ast_mutex_lock(&p->lock);
10472 if (p->alreadyhungup){
10473 p->ss7call = NULL;
10474 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
10475 }
10476 ast_mutex_unlock(&p->lock);
10477 }
10478 break;
10479 default:
10480 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
10481 break;
10482 }
10483 }
10484 ast_mutex_unlock(&linkset->lock);
10485 }
10486
10487 return 0;
10488 }
10489
10490 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
10491 {
10492 #if 0
10493 int i;
10494
10495 for (i = 0; i < NUM_SPANS; i++)
10496 if (linksets[i].ss7 == ss7)
10497 break;
10498
10499 ast_verbose("[%d] %s", i+1, s);
10500 #else
10501 ast_verbose("%s", s);
10502 #endif
10503 }
10504
10505 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
10506 {
10507 #if 0
10508 int i;
10509
10510 for (i = 0; i < NUM_SPANS; i++)
10511 if (linksets[i].ss7 == ss7)
10512 break;
10513
10514 #else
10515 ast_log(LOG_ERROR, "%s", s);
10516 #endif
10517 }
10518
10519 #endif
10520
10521 #ifdef HAVE_PRI
10522 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10523 {
10524 struct dahdi_pvt *p;
10525 p = pri->crvs;
10526 while (p) {
10527 if (p->channel == crv)
10528 return p;
10529 p = p->next;
10530 }
10531 return NULL;
10532 }
10533
10534
10535 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10536 {
10537 int x;
10538 int span = PRI_SPAN(channel);
10539 int spanfd;
10540 struct dahdi_params param;
10541 int principle = -1;
10542 int explicit = PRI_EXPLICIT(channel);
10543 channel = PRI_CHANNEL(channel);
10544
10545 if (!explicit) {
10546 spanfd = pri_active_dchan_fd(pri);
10547 memset(¶m, 0, sizeof(param));
10548 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
10549 return -1;
10550 span = pris[param.spanno - 1].prilogicalspan;
10551 }
10552
10553 for (x = 0; x < pri->numchans; x++) {
10554 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10555 principle = x;
10556 break;
10557 }
10558 }
10559
10560 return principle;
10561 }
10562
10563 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10564 {
10565 int x;
10566 struct dahdi_pvt *crv;
10567 if (!c) {
10568 if (principle < 0)
10569 return -1;
10570 return principle;
10571 }
10572 if ((principle > -1) &&
10573 (principle < pri->numchans) &&
10574 (pri->pvts[principle]) &&
10575 (pri->pvts[principle]->call == c))
10576 return principle;
10577
10578 for (x = 0; x < pri->numchans; x++) {
10579 if (!pri->pvts[x])
10580 continue;
10581 if (pri->pvts[x]->call == c) {
10582
10583 if (principle != x) {
10584 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10585
10586 ast_verb(3, "Moving call from channel %d to channel %d\n",
10587 old->channel, new->channel);
10588 if (new->owner) {
10589 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10590 old->channel, new->channel, new->channel);
10591 return -1;
10592 }
10593
10594 new->owner = old->owner;
10595 old->owner = NULL;
10596 if (new->owner) {
10597 ast_string_field_build(new->owner, name,
10598 "DAHDI/%d:%d-%d", pri->trunkgroup,
10599 new->channel, 1);
10600 new->owner->tech_pvt = new;
10601 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10602 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10603 old->subs[SUB_REAL].owner = NULL;
10604 } else
10605 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);
10606 new->call = old->call;
10607 old->call = NULL;
10608
10609
10610 new->dsp = old->dsp;
10611 new->dsp_features = old->dsp_features;
10612 old->dsp = NULL;
10613 old->dsp_features = 0;
10614 }
10615 return principle;
10616 }
10617 }
10618
10619 crv = pri->crvs;
10620 while (crv) {
10621 if (crv->call == c) {
10622
10623 if (crv->bearer)
10624 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10625 else if (pri->pvts[principle]->owner)
10626 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10627 else {
10628
10629
10630 dahdi_close_sub(crv, SUB_REAL);
10631 pri->pvts[principle]->call = crv->call;
10632 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10633 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10634 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10635 pri->trunkgroup, crv->channel);
10636 wakeup_sub(crv, SUB_REAL, pri);
10637 }
10638 return principle;
10639 }
10640 crv = crv->next;
10641 }
10642 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10643 return -1;
10644 }
10645
10646 static void *do_idle_thread(void *vchan)
10647 {
10648 struct ast_channel *chan = vchan;
10649 struct dahdi_pvt *pvt = chan->tech_pvt;
10650 struct ast_frame *f;
10651 char ex[80];
10652
10653 int newms, ms = 30000;
10654 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10655 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10656 if (ast_call(chan, ex, 0)) {
10657 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10658 ast_hangup(chan);
10659 return NULL;
10660 }
10661 while ((newms = ast_waitfor(chan, ms)) > 0) {
10662 f = ast_read(chan);
10663 if (!f) {
10664
10665 break;
10666 }
10667 if (f->frametype == AST_FRAME_CONTROL) {
10668 switch (f->subclass) {
10669 case AST_CONTROL_ANSWER:
10670
10671 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10672 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10673 chan->priority = 1;
10674 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10675 ast_pbx_run(chan);
10676
10677 return NULL;
10678 case AST_CONTROL_BUSY:
10679 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10680 break;
10681 case AST_CONTROL_CONGESTION:
10682 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10683 break;
10684 };
10685 }
10686 ast_frfree(f);
10687 ms = newms;
10688 }
10689
10690 ast_hangup(chan);
10691 return NULL;
10692 }
10693
10694 #ifndef PRI_RESTART
10695 #error "Upgrade your libpri"
10696 #endif
10697 static void dahdi_pri_message(struct pri *pri, char *s)
10698 {
10699 int x, y;
10700 int dchan = -1, span = -1;
10701 int dchancount = 0;
10702
10703 if (pri) {
10704 for (x = 0; x < NUM_SPANS; x++) {
10705 for (y = 0; y < NUM_DCHANS; y++) {
10706 if (pris[x].dchans[y])
10707 dchancount++;
10708
10709 if (pris[x].dchans[y] == pri)
10710 dchan = y;
10711 }
10712 if (dchan >= 0) {
10713 span = x;
10714 break;
10715 }
10716 dchancount = 0;
10717 }
10718 if (dchancount > 1 && (span > -1))
10719 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10720 else
10721 ast_verbose("%s", s);
10722 } else
10723 ast_verbose("%s", s);
10724
10725 ast_mutex_lock(&pridebugfdlock);
10726
10727 if (pridebugfd >= 0) {
10728 if (write(pridebugfd, s, strlen(s)) < 0) {
10729 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10730 }
10731 }
10732
10733 ast_mutex_unlock(&pridebugfdlock);
10734 }
10735
10736 static void dahdi_pri_error(struct pri *pri, char *s)
10737 {
10738 int x, y;
10739 int dchan = -1, span = -1;
10740 int dchancount = 0;
10741
10742 if (pri) {
10743 for (x = 0; x < NUM_SPANS; x++) {
10744 for (y = 0; y < NUM_DCHANS; y++) {
10745 if (pris[x].dchans[y])
10746 dchancount++;
10747
10748 if (pris[x].dchans[y] == pri)
10749 dchan = y;
10750 }
10751 if (dchan >= 0) {
10752 span = x;
10753 break;
10754 }
10755 dchancount = 0;
10756 }
10757 if ((dchancount > 1) && (span > -1))
10758 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10759 else
10760 ast_log(LOG_ERROR, "%s", s);
10761 } else
10762 ast_log(LOG_ERROR, "%s", s);
10763
10764 ast_mutex_lock(&pridebugfdlock);
10765
10766 if (pridebugfd >= 0) {
10767 if (write(pridebugfd, s, strlen(s)) < 0) {
10768 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10769 }
10770 }
10771
10772 ast_mutex_unlock(&pridebugfdlock);
10773 }
10774
10775 static int pri_check_restart(struct dahdi_pri *pri)
10776 {
10777 do {
10778 pri->resetpos++;
10779 } while ((pri->resetpos < pri->numchans) &&
10780 (!pri->pvts[pri->resetpos] ||
10781 pri->pvts[pri->resetpos]->call ||
10782 pri->pvts[pri->resetpos]->resetting));
10783 if (pri->resetpos < pri->numchans) {
10784
10785 pri->pvts[pri->resetpos]->resetting = 1;
10786 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10787 } else {
10788 pri->resetting = 0;
10789 time(&pri->lastreset);
10790 }
10791 return 0;
10792 }
10793
10794 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10795 {
10796 int x;
10797 int redo;
10798 ast_mutex_unlock(&pri->lock);
10799 ast_mutex_lock(&p->lock);
10800 do {
10801 redo = 0;
10802 for (x = 0; x < 3; x++) {
10803 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10804 redo++;
10805 DEADLOCK_AVOIDANCE(&p->lock);
10806 }
10807 if (p->subs[x].owner) {
10808 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10809 ast_channel_unlock(p->subs[x].owner);
10810 }
10811 }
10812 } while (redo);
10813 ast_mutex_unlock(&p->lock);
10814 ast_mutex_lock(&pri->lock);
10815 return 0;
10816 }
10817
10818 static char * redirectingreason2str(int redirectingreason)
10819 {
10820 switch (redirectingreason) {
10821 case 0:
10822 return "UNKNOWN";
10823 case 1:
10824 return "BUSY";
10825 case 2:
10826 return "NO_REPLY";
10827 case 0xF:
10828 return "UNCONDITIONAL";
10829 default:
10830 return "NOREDIRECT";
10831 }
10832 }
10833
10834 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10835 {
10836 if (pri->dialplan == -2) {
10837 snprintf(buf, size, "%s", number);
10838 return;
10839 }
10840 if (ast_strlen_zero(number)) {
10841 if (size) {
10842 *buf = '\0';
10843 }
10844 return;
10845 }
10846 switch (plan) {
10847 case PRI_INTERNATIONAL_ISDN:
10848 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10849 break;
10850 case PRI_NATIONAL_ISDN:
10851 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10852 break;
10853 case PRI_LOCAL_ISDN:
10854 snprintf(buf, size, "%s%s", pri->localprefix, number);
10855 break;
10856 case PRI_PRIVATE:
10857 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10858 break;
10859 case PRI_UNKNOWN:
10860 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10861 break;
10862 default:
10863 snprintf(buf, size, "%s", number);
10864 break;
10865 }
10866 }
10867
10868
10869 static void *pri_dchannel(void *vpri)
10870 {
10871 struct dahdi_pri *pri = vpri;
10872 pri_event *e;
10873 struct pollfd fds[NUM_DCHANS];
10874 int res;
10875 int chanpos = 0;
10876 int x;
10877 int haveidles;
10878 int activeidles;
10879 int nextidle = -1;
10880 struct ast_channel *c;
10881 struct timeval tv, lowest, *next;
10882 struct timeval lastidle = ast_tvnow();
10883 int doidling=0;
10884 char *cc;
10885 char idlen[80];
10886 struct ast_channel *idle;
10887 pthread_t p;
10888 time_t t;
10889 int i, which=-1;
10890 int numdchans;
10891 int cause=0;
10892 struct dahdi_pvt *crv;
10893 pthread_t threadid;
10894 char ani2str[6];
10895 char plancallingnum[256];
10896 char plancallingani[256];
10897 char calledtonstr[10];
10898
10899 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10900
10901 gettimeofday(&lastidle, NULL);
10902 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10903
10904 cc = strchr(pri->idleext, '@');
10905 if (cc) {
10906 *cc = '\0';
10907 cc++;
10908 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10909 #if 0
10910
10911 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10912 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10913 else
10914 #endif
10915 doidling = 1;
10916 } else
10917 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10918 }
10919 for (;;) {
10920 for (i = 0; i < NUM_DCHANS; i++) {
10921 if (!pri->dchannels[i])
10922 break;
10923 fds[i].fd = pri->fds[i];
10924 fds[i].events = POLLIN | POLLPRI;
10925 fds[i].revents = 0;
10926 }
10927 numdchans = i;
10928 time(&t);
10929 ast_mutex_lock(&pri->lock);
10930 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10931 if (pri->resetting && pri_is_up(pri)) {
10932 if (pri->resetpos < 0)
10933 pri_check_restart(pri);
10934 } else {
10935 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10936 pri->resetting = 1;
10937 pri->resetpos = -1;
10938 }
10939 }
10940 }
10941
10942 if (doidling && pri_is_up(pri)) {
10943 nextidle = -1;
10944 haveidles = 0;
10945 activeidles = 0;
10946 for (x = pri->numchans; x >= 0; x--) {
10947 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10948 !pri->pvts[x]->call) {
10949 if (haveidles < pri->minunused) {
10950 haveidles++;
10951 } else if (!pri->pvts[x]->resetting) {
10952 nextidle = x;
10953 break;
10954 }
10955 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10956 activeidles++;
10957 }
10958 if (nextidle > -1) {
10959 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10960
10961 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10962 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
10963 if (idle) {
10964 pri->pvts[nextidle]->isidlecall = 1;
10965 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10966 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10967 dahdi_hangup(idle);
10968 }
10969 } else
10970 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10971 lastidle = ast_tvnow();
10972 }
10973 } else if ((haveidles < pri->minunused) &&
10974 (activeidles > pri->minidle)) {
10975
10976
10977 for (x = pri->numchans; x >= 0; x--) {
10978
10979 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10980 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10981 haveidles++;
10982
10983
10984 if ((haveidles >= pri->minunused) ||
10985 (activeidles <= pri->minidle))
10986 break;
10987 }
10988 }
10989 }
10990 }
10991
10992 lowest = ast_tv(60, 0);
10993 for (i = 0; i < NUM_DCHANS; i++) {
10994
10995 if (!pri->dchannels[i])
10996 break;
10997 if ((next = pri_schedule_next(pri->dchans[i]))) {
10998
10999 tv = ast_tvsub(*next, ast_tvnow());
11000 if (tv.tv_sec < 0) {
11001 tv = ast_tv(0,0);
11002 }
11003 if (doidling || pri->resetting) {
11004 if (tv.tv_sec > 1) {
11005 tv = ast_tv(1, 0);
11006 }
11007 } else {
11008 if (tv.tv_sec > 60) {
11009 tv = ast_tv(60, 0);
11010 }
11011 }
11012 } else if (doidling || pri->resetting) {
11013
11014
11015 tv = ast_tv(1,0);
11016 } else {
11017
11018 tv = ast_tv(60, 0);
11019 }
11020 if (!i || ast_tvcmp(tv, lowest) < 0) {
11021 lowest = tv;
11022 }
11023 }
11024 ast_mutex_unlock(&pri->lock);
11025
11026 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11027 pthread_testcancel();
11028 e = NULL;
11029 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11030 pthread_testcancel();
11031 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11032
11033 ast_mutex_lock(&pri->lock);
11034 if (!res) {
11035 for (which = 0; which < NUM_DCHANS; which++) {
11036 if (!pri->dchans[which])
11037 break;
11038
11039 e = pri_schedule_run(pri->dchans[which]);
11040 if (e)
11041 break;
11042 }
11043 } else if (res > -1) {
11044 for (which = 0; which < NUM_DCHANS; which++) {
11045 if (!pri->dchans[which])
11046 break;
11047 if (fds[which].revents & POLLPRI) {
11048
11049 x = 0;
11050 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11051 if (x) {
11052 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);
11053 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
11054 "PRIEvent: %s\r\n"
11055 "PRIEventCode: %d\r\n"
11056 "D-channel: %s\r\n"
11057 "Span: %d\r\n",
11058 event2str(x),
11059 x,
11060 pri_order(which),
11061 pri->span
11062 );
11063 }
11064
11065 if (x == DAHDI_EVENT_ALARM) {
11066 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11067 pri_find_dchan(pri);
11068 } else if (x == DAHDI_EVENT_NOALARM) {
11069 pri->dchanavail[which] |= DCHAN_NOTINALARM;
11070 pri_restart(pri->dchans[which]);
11071 }
11072
11073 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11074 } else if (fds[which].revents & POLLIN) {
11075 e = pri_check_event(pri->dchans[which]);
11076 }
11077 if (e)
11078 break;
11079 }
11080 } else if (errno != EINTR)
11081 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11082
11083 if (e) {
11084 if (pri->debug)
11085 pri_dump_event(pri->dchans[which], e);
11086
11087 if (e->e != PRI_EVENT_DCHAN_DOWN) {
11088 if (!(pri->dchanavail[which] & DCHAN_UP)) {
11089 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11090 }
11091 pri->dchanavail[which] |= DCHAN_UP;
11092 } else if (pri->sig != SIG_BRI_PTMP) {
11093 if (pri->dchanavail[which] & DCHAN_UP) {
11094 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11095 }
11096 pri->dchanavail[which] &= ~DCHAN_UP;
11097 }
11098
11099 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11100
11101 pri->pri = pri->dchans[which];
11102
11103 switch (e->e) {
11104 case PRI_EVENT_DCHAN_UP:
11105 if (!pri->pri) pri_find_dchan(pri);
11106
11107
11108 time(&pri->lastreset);
11109
11110
11111 if (pri->resetinterval > -1) {
11112 pri->lastreset -= pri->resetinterval;
11113 pri->lastreset += 5;
11114 }
11115 pri->resetting = 0;
11116
11117 for (i = 0; i < pri->numchans; i++)
11118 if (pri->pvts[i]) {
11119 pri->pvts[i]->inalarm = 0;
11120 }
11121 break;
11122 case PRI_EVENT_DCHAN_DOWN:
11123 pri_find_dchan(pri);
11124 if (!pri_is_up(pri)) {
11125 pri->resetting = 0;
11126
11127 for (i = 0; i < pri->numchans; i++) {
11128 struct dahdi_pvt *p = pri->pvts[i];
11129 if (p) {
11130 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11131
11132 if (p->call) {
11133 if (p->pri && p->pri->pri) {
11134 pri_hangup(p->pri->pri, p->call, -1);
11135 pri_destroycall(p->pri->pri, p->call);
11136 p->call = NULL;
11137 } else
11138 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
11139 }
11140 if (p->realcall) {
11141 pri_hangup_all(p->realcall, pri);
11142 } else if (p->owner)
11143 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11144 }
11145 p->inalarm = 1;
11146 }
11147 }
11148 }
11149 break;
11150 case PRI_EVENT_RESTART:
11151 if (e->restart.channel > -1) {
11152 chanpos = pri_find_principle(pri, e->restart.channel);
11153 if (chanpos < 0)
11154 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
11155 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11156 else {
11157 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
11158 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11159 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11160 if (pri->pvts[chanpos]->call) {
11161 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11162 pri->pvts[chanpos]->call = NULL;
11163 }
11164
11165 if (pri->pvts[chanpos]->realcall)
11166 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11167 else if (pri->pvts[chanpos]->owner)
11168 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11169 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11170 }
11171 } else {
11172 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
11173 for (x = 0; x < pri->numchans; x++)
11174 if (pri->pvts[x]) {
11175 ast_mutex_lock(&pri->pvts[x]->lock);
11176 if (pri->pvts[x]->call) {
11177 pri_destroycall(pri->pri, pri->pvts[x]->call);
11178 pri->pvts[x]->call = NULL;
11179 }
11180 if (pri->pvts[chanpos]->realcall)
11181 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11182 else if (pri->pvts[x]->owner)
11183 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11184 ast_mutex_unlock(&pri->pvts[x]->lock);
11185 }
11186 }
11187 break;
11188 case PRI_EVENT_KEYPAD_DIGIT:
11189 chanpos = pri_find_principle(pri, e->digit.channel);
11190 if (chanpos < 0) {
11191 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
11192 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
11193 } else {
11194 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
11195 if (chanpos > -1) {
11196 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11197
11198 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
11199
11200 int digitlen = strlen(e->digit.digits);
11201 char digit;
11202 int i;
11203 for (i = 0; i < digitlen; i++) {
11204 digit = e->digit.digits[i];
11205 {
11206 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11207 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11208 }
11209 }
11210 }
11211 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11212 }
11213 }
11214 break;
11215
11216 case PRI_EVENT_INFO_RECEIVED:
11217 chanpos = pri_find_principle(pri, e->ring.channel);
11218 if (chanpos < 0) {
11219 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
11220 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11221 } else {
11222 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
11223 if (chanpos > -1) {
11224 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11225
11226 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
11227
11228 int digitlen = strlen(e->ring.callednum);
11229 char digit;
11230 int i;
11231 for (i = 0; i < digitlen; i++) {
11232 digit = e->ring.callednum[i];
11233 {
11234 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11235 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11236 }
11237 }
11238 }
11239 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11240 }
11241 }
11242 break;
11243 case PRI_EVENT_RING:
11244 crv = NULL;
11245 if (e->ring.channel == -1)
11246 chanpos = pri_find_empty_chan(pri, 1);
11247 else
11248 chanpos = pri_find_principle(pri, e->ring.channel);
11249
11250 if (chanpos < 0) {
11251 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
11252 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11253 } else {
11254 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11255 if (pri->pvts[chanpos]->owner) {
11256 if (pri->pvts[chanpos]->call == e->ring.call) {
11257 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
11258 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11259 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11260 break;
11261 } else {
11262
11263 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
11264 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11265 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11266 chanpos = -1;
11267 }
11268 }
11269 if (chanpos > -1)
11270 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11271 }
11272 if ((chanpos < 0) && (e->ring.flexible))
11273 chanpos = pri_find_empty_chan(pri, 1);
11274 if (chanpos > -1) {
11275 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11276 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11277
11278 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11279 if (crv)
11280 ast_mutex_lock(&crv->lock);
11281 if (!crv || crv->owner) {
11282 pri->pvts[chanpos]->call = NULL;
11283 if (crv) {
11284 if (crv->owner)
11285 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11286 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);
11287 } else
11288 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);
11289 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11290 if (crv)
11291 ast_mutex_unlock(&crv->lock);
11292 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11293 break;
11294 }
11295 }
11296 pri->pvts[chanpos]->call = e->ring.call;
11297 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11298 if (pri->pvts[chanpos]->use_callerid) {
11299 ast_shrink_phone_number(plancallingnum);
11300 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11301 #ifdef PRI_ANI
11302 if (!ast_strlen_zero(e->ring.callingani)) {
11303 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11304 ast_shrink_phone_number(plancallingani);
11305 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11306 } else {
11307 pri->pvts[chanpos]->cid_ani[0] = '\0';
11308 }
11309 #endif
11310 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11311 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
11312 } else {
11313 pri->pvts[chanpos]->cid_num[0] = '\0';
11314 pri->pvts[chanpos]->cid_ani[0] = '\0';
11315 pri->pvts[chanpos]->cid_name[0] = '\0';
11316 pri->pvts[chanpos]->cid_ton = 0;
11317 }
11318 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11319 e->ring.redirectingnum, e->ring.callingplanrdnis);
11320
11321 if (pri->pvts[chanpos]->immediate) {
11322 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
11323 pri->pvts[chanpos]->exten[0] = 's';
11324 pri->pvts[chanpos]->exten[1] = '\0';
11325 }
11326
11327 else if (!ast_strlen_zero(e->ring.callednum)) {
11328 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11329 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11330 } else if (pri->overlapdial)
11331 pri->pvts[chanpos]->exten[0] = '\0';
11332 else {
11333
11334 pri->pvts[chanpos]->exten[0] = 's';
11335 pri->pvts[chanpos]->exten[1] = '\0';
11336 }
11337
11338 if (!ast_strlen_zero(e->ring.callednum))
11339 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11340
11341 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11342 ast_verb(3, "Going to extension s|1 because of Complete received\n");
11343 pri->pvts[chanpos]->exten[0] = 's';
11344 pri->pvts[chanpos]->exten[1] = '\0';
11345 }
11346
11347
11348 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11349 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11350
11351 int law;
11352 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11353
11354 law = 1;
11355 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11356 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11357 }
11358 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11359 law = DAHDI_LAW_ALAW;
11360 else
11361 law = DAHDI_LAW_MULAW;
11362 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11363 if (res < 0)
11364 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11365 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11366 if (res < 0)
11367 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11368 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11369
11370 pri->pvts[chanpos]->proceeding = 1;
11371 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11372 } else {
11373 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
11374 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11375 else
11376 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11377 }
11378
11379 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11380
11381
11382 if (!e->ring.complete
11383 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11384 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11385
11386
11387
11388
11389 ast_mutex_unlock(&pri->lock);
11390 if (crv) {
11391
11392 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11393 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11394 pri->pvts[chanpos]->owner = &inuse;
11395 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11396 } else {
11397 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11398 }
11399 ast_mutex_lock(&pri->lock);
11400 if (c) {
11401 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11402 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11403 }
11404 if (e->ring.ani2 >= 0) {
11405 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11406 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11407 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11408 }
11409
11410 #ifdef SUPPORT_USERUSER
11411 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11412 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11413 }
11414 #endif
11415
11416 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11417 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11418 if (e->ring.redirectingreason >= 0)
11419 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11420 }
11421 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
11422 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11423 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11424 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11425 } else {
11426 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11427 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11428 if (c)
11429 ast_hangup(c);
11430 else {
11431 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11432 pri->pvts[chanpos]->call = NULL;
11433 }
11434 }
11435 } else {
11436
11437
11438
11439
11440 ast_mutex_unlock(&pri->lock);
11441 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
11442 ast_mutex_lock(&pri->lock);
11443 if (c) {
11444
11445
11446
11447
11448
11449
11450
11451
11452 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11453 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11454 }
11455 if (e->ring.ani2 >= 0) {
11456 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11457 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11458 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11459 }
11460
11461 #ifdef SUPPORT_USERUSER
11462 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11463 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11464 }
11465 #endif
11466
11467 if (e->ring.redirectingreason >= 0)
11468 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11469
11470 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11471 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11472 }
11473 if (c && !ast_pbx_start(c)) {
11474 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11475 plancallingnum, pri->pvts[chanpos]->exten,
11476 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11477
11478 dahdi_enable_ec(pri->pvts[chanpos]);
11479 } else {
11480 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11481 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11482 if (c) {
11483 ast_hangup(c);
11484 } else {
11485 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11486 pri->pvts[chanpos]->call = NULL;
11487 }
11488 }
11489 }
11490 } else {
11491 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
11492 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
11493 pri->pvts[chanpos]->prioffset, pri->span);
11494 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11495 pri->pvts[chanpos]->call = NULL;
11496 pri->pvts[chanpos]->exten[0] = '\0';
11497 }
11498 if (crv)
11499 ast_mutex_unlock(&crv->lock);
11500 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11501 } else {
11502 if (e->ring.flexible)
11503 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11504 else
11505 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11506 }
11507 break;
11508 case PRI_EVENT_RINGING:
11509 chanpos = pri_find_principle(pri, e->ringing.channel);
11510 if (chanpos < 0) {
11511 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
11512 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11513 } else {
11514 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
11515 if (chanpos < 0) {
11516 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
11517 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11518 } else {
11519 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11520 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11521 dahdi_enable_ec(pri->pvts[chanpos]);
11522 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11523 pri->pvts[chanpos]->alerting = 1;
11524 } else
11525 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11526
11527 #ifdef PRI_PROGRESS_MASK
11528 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11529 #else
11530 if (e->ringing.progress == 8) {
11531 #endif
11532
11533 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11534
11535 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11536 pri->pvts[chanpos]->dsp_features = 0;
11537 }
11538 }
11539
11540 #ifdef SUPPORT_USERUSER
11541 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11542 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11543 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11544 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11545 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11546 }
11547 #endif
11548
11549 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11550 }
11551 }
11552 break;
11553 case PRI_EVENT_PROGRESS:
11554
11555 chanpos = pri_find_principle(pri, e->proceeding.channel);
11556 if (chanpos > -1) {
11557 #ifdef PRI_PROGRESS_MASK
11558 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11559 #else
11560 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11561 #endif
11562 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11563
11564 if (e->proceeding.cause > -1) {
11565 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11566
11567
11568 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11569 if (pri->pvts[chanpos]->owner) {
11570 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11571
11572 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11573 f.subclass = AST_CONTROL_BUSY;
11574 }
11575 }
11576 }
11577
11578 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11579 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11580 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11581 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11582 #ifdef PRI_PROGRESS_MASK
11583 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11584 #else
11585 if (e->proceeding.progress == 8) {
11586 #endif
11587
11588 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11589 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11590 pri->pvts[chanpos]->dsp_features = 0;
11591 }
11592
11593 f.subclass = AST_CONTROL_PROGRESS;
11594 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11595 }
11596 pri->pvts[chanpos]->progress = 1;
11597 pri->pvts[chanpos]->dialing = 0;
11598 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11599 }
11600 }
11601 break;
11602 case PRI_EVENT_PROCEEDING:
11603 chanpos = pri_find_principle(pri, e->proceeding.channel);
11604 if (chanpos > -1) {
11605 if (!pri->pvts[chanpos]->proceeding) {
11606 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11607
11608 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11609 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11610 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11611 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11612 #ifdef PRI_PROGRESS_MASK
11613 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11614 #else
11615 if (e->proceeding.progress == 8) {
11616 #endif
11617
11618 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11619 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11620 pri->pvts[chanpos]->dsp_features = 0;
11621 }
11622
11623 f.subclass = AST_CONTROL_PROGRESS;
11624 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11625 }
11626 pri->pvts[chanpos]->proceeding = 1;
11627 pri->pvts[chanpos]->dialing = 0;
11628 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11629 }
11630 }
11631 break;
11632 case PRI_EVENT_FACNAME:
11633 chanpos = pri_find_principle(pri, e->facname.channel);
11634 if (chanpos < 0) {
11635 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11636 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11637 } else {
11638 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11639 if (chanpos < 0) {
11640 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
11641 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11642 } else {
11643
11644 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11645 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11646 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11647 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11648 dahdi_enable_ec(pri->pvts[chanpos]);
11649 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11650 }
11651 }
11652 break;
11653 case PRI_EVENT_ANSWER:
11654 chanpos = pri_find_principle(pri, e->answer.channel);
11655 if (chanpos < 0) {
11656 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
11657 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11658 } else {
11659 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11660 if (chanpos < 0) {
11661 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
11662 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11663 } else {
11664 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11665
11666
11667
11668
11669
11670 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11671 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11672 pri->pvts[chanpos]->dsp_features = 0;
11673 }
11674 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11675 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11676 x = DAHDI_START;
11677 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11678 if (res < 0) {
11679 if (errno != EINPROGRESS) {
11680 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11681 }
11682 }
11683 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11684 pri->pvts[chanpos]->dialing = 1;
11685
11686 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11687 if (res < 0) {
11688 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11689 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11690 } else
11691 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11692
11693 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11694 } else if (pri->pvts[chanpos]->confirmanswer) {
11695 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11696 } else {
11697 pri->pvts[chanpos]->dialing = 0;
11698 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11699
11700 dahdi_enable_ec(pri->pvts[chanpos]);
11701 }
11702
11703 #ifdef SUPPORT_USERUSER
11704 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11705 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11706 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11707 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11708 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11709 }
11710 #endif
11711
11712 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11713 }
11714 }
11715 break;
11716 case PRI_EVENT_HANGUP:
11717 chanpos = pri_find_principle(pri, e->hangup.channel);
11718 if (chanpos < 0) {
11719 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
11720 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11721 } else {
11722 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11723 if (chanpos > -1) {
11724 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11725 if (!pri->pvts[chanpos]->alreadyhungup) {
11726
11727 pri->pvts[chanpos]->alreadyhungup = 1;
11728 if (pri->pvts[chanpos]->realcall)
11729 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11730 else if (pri->pvts[chanpos]->owner) {
11731
11732 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11733 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11734 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11735 else {
11736 switch (e->hangup.cause) {
11737 case PRI_CAUSE_USER_BUSY:
11738 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11739 break;
11740 case PRI_CAUSE_CALL_REJECTED:
11741 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11742 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11743 case PRI_CAUSE_SWITCH_CONGESTION:
11744 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11745 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11746 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11747 break;
11748 default:
11749 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11750 }
11751 }
11752 }
11753 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11754 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11755 } else {
11756 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11757 pri->pvts[chanpos]->call = NULL;
11758 }
11759 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11760 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11761 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11762 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11763 pri->pvts[chanpos]->resetting = 1;
11764 }
11765 if (e->hangup.aoc_units > -1)
11766 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11767 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11768
11769 #ifdef SUPPORT_USERUSER
11770 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11771 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11772 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11773 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11774 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11775 }
11776 #endif
11777
11778 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11779 } else {
11780 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
11781 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11782 }
11783 }
11784 break;
11785 #ifndef PRI_EVENT_HANGUP_REQ
11786 #error please update libpri
11787 #endif
11788 case PRI_EVENT_HANGUP_REQ:
11789 chanpos = pri_find_principle(pri, e->hangup.channel);
11790 if (chanpos < 0) {
11791 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11792 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11793 } else {
11794 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11795 if (chanpos > -1) {
11796 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11797 if (pri->pvts[chanpos]->realcall)
11798 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11799 else if (pri->pvts[chanpos]->owner) {
11800 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11801 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11802 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11803 else {
11804 switch (e->hangup.cause) {
11805 case PRI_CAUSE_USER_BUSY:
11806 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11807 break;
11808 case PRI_CAUSE_CALL_REJECTED:
11809 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11810 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11811 case PRI_CAUSE_SWITCH_CONGESTION:
11812 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11813 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11814 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11815 break;
11816 default:
11817 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11818 }
11819 }
11820 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);
11821 if (e->hangup.aoc_units > -1)
11822 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11823 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11824 } else {
11825 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11826 pri->pvts[chanpos]->call = NULL;
11827 }
11828 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11829 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11830 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11831 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11832 pri->pvts[chanpos]->resetting = 1;
11833 }
11834
11835 #ifdef SUPPORT_USERUSER
11836 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11837 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11838 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11839 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11840 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11841 }
11842 #endif
11843
11844 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11845 } else {
11846 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);
11847 }
11848 }
11849 break;
11850 case PRI_EVENT_HANGUP_ACK:
11851 chanpos = pri_find_principle(pri, e->hangup.channel);
11852 if (chanpos < 0) {
11853 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11854 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11855 } else {
11856 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11857 if (chanpos > -1) {
11858 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11859 pri->pvts[chanpos]->call = NULL;
11860 pri->pvts[chanpos]->resetting = 0;
11861 if (pri->pvts[chanpos]->owner) {
11862 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11863 }
11864
11865 #ifdef SUPPORT_USERUSER
11866 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11867 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11868 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11869 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11870 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11871 }
11872 #endif
11873
11874 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11875 }
11876 }
11877 break;
11878 case PRI_EVENT_CONFIG_ERR:
11879 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11880 break;
11881 case PRI_EVENT_RESTART_ACK:
11882 chanpos = pri_find_principle(pri, e->restartack.channel);
11883 if (chanpos < 0) {
11884
11885
11886
11887 for (x = 0; x < pri->numchans; x++) {
11888 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11889 chanpos = x;
11890 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11891 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11892 pri->pvts[chanpos]->prioffset, pri->span);
11893 if (pri->pvts[chanpos]->realcall)
11894 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11895 else if (pri->pvts[chanpos]->owner) {
11896 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11897 pri->pvts[chanpos]->prioffset, pri->span);
11898 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11899 }
11900 pri->pvts[chanpos]->resetting = 0;
11901 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11902 pri->pvts[chanpos]->prioffset, pri->span);
11903 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11904 if (pri->resetting)
11905 pri_check_restart(pri);
11906 break;
11907 }
11908 }
11909 if (chanpos < 0) {
11910 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11911 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11912 }
11913 } else {
11914 if (pri->pvts[chanpos]) {
11915 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11916 if (pri->pvts[chanpos]->realcall)
11917 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11918 else if (pri->pvts[chanpos]->owner) {
11919 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11920 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11921 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11922 }
11923 pri->pvts[chanpos]->resetting = 0;
11924 pri->pvts[chanpos]->inservice = 1;
11925 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11926 pri->pvts[chanpos]->prioffset, pri->span);
11927 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11928 if (pri->resetting)
11929 pri_check_restart(pri);
11930 }
11931 }
11932 break;
11933 case PRI_EVENT_SETUP_ACK:
11934 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11935 if (chanpos < 0) {
11936 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11937 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11938 } else {
11939 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11940 if (chanpos > -1) {
11941 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11942 pri->pvts[chanpos]->setup_ack = 1;
11943
11944 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11945 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11946 pri_information(pri->pri, pri->pvts[chanpos]->call,
11947 pri->pvts[chanpos]->dialdest[x]);
11948 }
11949 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11950 } else
11951 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11952 }
11953 break;
11954 case PRI_EVENT_NOTIFY:
11955 chanpos = pri_find_principle(pri, e->notify.channel);
11956 if (chanpos < 0) {
11957 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11958 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11959 } else {
11960 struct ast_frame f = { AST_FRAME_CONTROL, };
11961 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11962 switch (e->notify.info) {
11963 case PRI_NOTIFY_REMOTE_HOLD:
11964 f.subclass = AST_CONTROL_HOLD;
11965 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11966 break;
11967 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11968 f.subclass = AST_CONTROL_UNHOLD;
11969 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11970 break;
11971 }
11972 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11973 }
11974 break;
11975 default:
11976 ast_debug(1, "Event: %d\n", e->e);
11977 }
11978 }
11979 ast_mutex_unlock(&pri->lock);
11980 }
11981
11982 return NULL;
11983 }
11984
11985 static int start_pri(struct dahdi_pri *pri)
11986 {
11987 int res, x;
11988 struct dahdi_params p;
11989 struct dahdi_bufferinfo bi;
11990 struct dahdi_spaninfo si;
11991 int i;
11992
11993 for (i = 0; i < NUM_DCHANS; i++) {
11994 if (!pri->dchannels[i])
11995 break;
11996 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
11997 x = pri->dchannels[i];
11998 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11999 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12000 return -1;
12001 }
12002 memset(&p, 0, sizeof(p));
12003 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12004 if (res) {
12005 dahdi_close_pri_fd(pri, i);
12006 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12007 return -1;
12008 }
12009 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12010 dahdi_close_pri_fd(pri, i);
12011 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
12012 return -1;
12013 }
12014 memset(&si, 0, sizeof(si));
12015 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12016 if (res) {
12017 dahdi_close_pri_fd(pri, i);
12018 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12019 }
12020 if (!si.alarms)
12021 pri->dchanavail[i] |= DCHAN_NOTINALARM;
12022 else
12023 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12024 memset(&bi, 0, sizeof(bi));
12025 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12026 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12027 bi.numbufs = 32;
12028 bi.bufsize = 1024;
12029 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12030 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12031 dahdi_close_pri_fd(pri, i);
12032 return -1;
12033 }
12034 switch (pri->sig) {
12035 case SIG_BRI:
12036 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12037 break;
12038 case SIG_BRI_PTMP:
12039 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12040 break;
12041 default:
12042 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12043 }
12044
12045 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12046 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12047 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12048 #ifdef HAVE_PRI_INBANDDISCONNECT
12049 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12050 #endif
12051
12052 if (i)
12053 pri_enslave(pri->dchans[0], pri->dchans[i]);
12054 if (!pri->dchans[i]) {
12055 dahdi_close_pri_fd(pri, i);
12056 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12057 return -1;
12058 }
12059 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12060 pri_set_nsf(pri->dchans[i], pri->nsf);
12061 #ifdef PRI_GETSET_TIMERS
12062 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12063 if (pritimers[x] != 0)
12064 pri_set_timer(pri->dchans[i], x, pritimers[x]);
12065 }
12066 #endif
12067 }
12068
12069 pri->pri = pri->dchans[0];
12070 pri->resetpos = -1;
12071 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12072 for (i = 0; i < NUM_DCHANS; i++) {
12073 if (!pri->dchannels[i])
12074 break;
12075 dahdi_close_pri_fd(pri, i);
12076 }
12077 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12078 return -1;
12079 }
12080 return 0;
12081 }
12082
12083 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
12084 {
12085 int which, span;
12086 char *ret = NULL;
12087
12088 if (pos != rpos)
12089 return ret;
12090
12091 for (which = span = 0; span < NUM_SPANS; span++) {
12092 if (pris[span].pri && ++which > state) {
12093 if (asprintf(&ret, "%d", span + 1) < 0) {
12094 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12095 }
12096 break;
12097 }
12098 }
12099 return ret;
12100 }
12101
12102 static char *complete_span_4(const char *line, const char *word, int pos, int state)
12103 {
12104 return complete_span_helper(line,word,pos,state,3);
12105 }
12106
12107 static char *complete_span_5(const char *line, const char *word, int pos, int state)
12108 {
12109 return complete_span_helper(line,word,pos,state,4);
12110 }
12111
12112 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12113 {
12114 switch (cmd) {
12115 case CLI_INIT:
12116 e->command = "pri unset debug file";
12117 e->usage = "Usage: pri unset debug file\n"
12118 " Stop sending debug output to the previously \n"
12119 " specified file\n";
12120 return NULL;
12121 case CLI_GENERATE:
12122 return NULL;
12123 }
12124
12125 ast_mutex_lock(&pridebugfdlock);
12126 close(pridebugfd);
12127 pridebugfd = -1;
12128 ast_cli(a->fd, "PRI debug output to file disabled\n");
12129 ast_mutex_unlock(&pridebugfdlock);
12130 return CLI_SUCCESS;
12131 }
12132
12133 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12134 {
12135 int myfd;
12136 switch (cmd) {
12137 case CLI_INIT:
12138 e->command = "pri set debug file";
12139 e->usage = "Usage: pri set debug file [output-file]\n"
12140 " Sends PRI debug output to the specified output file\n";
12141 return NULL;
12142 case CLI_GENERATE:
12143 return NULL;
12144 }
12145 if (a->argc < 5)
12146 return CLI_SHOWUSAGE;
12147
12148 if (ast_strlen_zero(a->argv[4]))
12149 return CLI_SHOWUSAGE;
12150
12151 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12152 if (myfd < 0) {
12153 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12154 return CLI_SUCCESS;
12155 }
12156
12157 ast_mutex_lock(&pridebugfdlock);
12158
12159 if (pridebugfd >= 0)
12160 close(pridebugfd);
12161
12162 pridebugfd = myfd;
12163 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12164 ast_mutex_unlock(&pridebugfdlock);
12165 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12166 return CLI_SUCCESS;
12167 }
12168
12169 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12170 {
12171 int span;
12172 int x;
12173 switch (cmd) {
12174 case CLI_INIT:
12175 e->command = "pri debug span";
12176 e->usage =
12177 "Usage: pri debug span <span>\n"
12178 " Enables debugging on a given PRI span\n";
12179 return NULL;
12180 case CLI_GENERATE:
12181 return complete_span_4(a->line, a->word, a->pos, a->n);
12182 }
12183 if (a->argc < 4) {
12184 return CLI_SHOWUSAGE;
12185 }
12186 span = atoi(a->argv[3]);
12187 if ((span < 1) || (span > NUM_SPANS)) {
12188 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
12189 return CLI_SUCCESS;
12190 }
12191 if (!pris[span-1].pri) {
12192 ast_cli(a->fd, "No PRI running on span %d\n", span);
12193 return CLI_SUCCESS;
12194 }
12195 for (x = 0; x < NUM_DCHANS; x++) {
12196 if (pris[span-1].dchans[x])
12197 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12198 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12199 PRI_DEBUG_Q921_STATE);
12200 }
12201 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
12202 return CLI_SUCCESS;
12203 }
12204
12205
12206
12207 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12208 {
12209 int span;
12210 int x;
12211 switch (cmd) {
12212 case CLI_INIT:
12213 e->command = "pri no debug span";
12214 e->usage =
12215 "Usage: pri no debug span <span>\n"
12216 " Disables debugging on a given PRI span\n";
12217 return NULL;
12218 case CLI_GENERATE:
12219 return complete_span_5(a->line, a->word, a->pos, a->n);
12220 }
12221 if (a->argc < 5)
12222 return CLI_SHOWUSAGE;
12223
12224 span = atoi(a->argv[4]);
12225 if ((span < 1) || (span > NUM_SPANS)) {
12226 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12227 return CLI_SUCCESS;
12228 }
12229 if (!pris[span-1].pri) {
12230 ast_cli(a->fd, "No PRI running on span %d\n", span);
12231 return CLI_SUCCESS;
12232 }
12233 for (x = 0; x < NUM_DCHANS; x++) {
12234 if (pris[span-1].dchans[x])
12235 pri_set_debug(pris[span-1].dchans[x], 0);
12236 }
12237 ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12238 return CLI_SUCCESS;
12239 }
12240
12241 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12242 {
12243 int span;
12244 int x;
12245 switch (cmd) {
12246 case CLI_INIT:
12247 e->command = "pri intensive debug span";
12248 e->usage =
12249 "Usage: pri intensive debug span <span>\n"
12250 " Enables debugging down to the Q.921 level\n";
12251 return NULL;
12252 case CLI_GENERATE:
12253 return complete_span_5(a->line, a->word, a->pos, a->n);
12254 }
12255
12256 if (a->argc < 5)
12257 return CLI_SHOWUSAGE;
12258 span = atoi(a->argv[4]);
12259 if ((span < 1) || (span > NUM_SPANS)) {
12260 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12261 return CLI_SUCCESS;
12262 }
12263 if (!pris[span-1].pri) {
12264 ast_cli(a->fd, "No PRI running on span %d\n", span);
12265 return CLI_SUCCESS;
12266 }
12267 for (x = 0; x < NUM_DCHANS; x++) {
12268 if (pris[span-1].dchans[x])
12269 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12270 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12271 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12272 }
12273 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12274 return CLI_SUCCESS;
12275 }
12276
12277 static void build_status(char *s, size_t len, int status, int active)
12278 {
12279 if (!s || len < 1) {
12280 return;
12281 }
12282 s[0] = '\0';
12283 if (status & DCHAN_PROVISIONED)
12284 strncat(s, "Provisioned, ", len - strlen(s) - 1);
12285 if (!(status & DCHAN_NOTINALARM))
12286 strncat(s, "In Alarm, ", len - strlen(s) - 1);
12287 if (status & DCHAN_UP)
12288 strncat(s, "Up", len - strlen(s) - 1);
12289 else
12290 strncat(s, "Down", len - strlen(s) - 1);
12291 if (active)
12292 strncat(s, ", Active", len - strlen(s) - 1);
12293 else
12294 strncat(s, ", Standby", len - strlen(s) - 1);
12295 s[len - 1] = '\0';
12296 }
12297
12298 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12299 {
12300 int span;
12301 int x;
12302 char status[256];
12303
12304 switch (cmd) {
12305 case CLI_INIT:
12306 e->command = "pri show spans";
12307 e->usage =
12308 "Usage: pri show spans\n"
12309 " Displays PRI Information\n";
12310 return NULL;
12311 case CLI_GENERATE:
12312 return NULL;
12313 }
12314
12315 if (a->argc != 3)
12316 return CLI_SHOWUSAGE;
12317
12318 for (span = 0; span < NUM_SPANS; span++) {
12319 if (pris[span].pri) {
12320 for (x = 0; x < NUM_DCHANS; x++) {
12321 if (pris[span].dchannels[x]) {
12322 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12323 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12324 }
12325 }
12326 }
12327 }
12328 return CLI_SUCCESS;
12329 }
12330
12331 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12332 {
12333 int span;
12334 int x;
12335 char status[256];
12336 switch (cmd) {
12337 case CLI_INIT:
12338 e->command = "pri show span";
12339 e->usage =
12340 "Usage: pri show span <span>\n"
12341 " Displays PRI Information on a given PRI span\n";
12342 return NULL;
12343 case CLI_GENERATE:
12344 return complete_span_4(a->line, a->word, a->pos, a->n);
12345 }
12346
12347 if (a->argc < 4)
12348 return CLI_SHOWUSAGE;
12349 span = atoi(a->argv[3]);
12350 if ((span < 1) || (span > NUM_SPANS)) {
12351 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12352 return CLI_SUCCESS;
12353 }
12354 if (!pris[span-1].pri) {
12355 ast_cli(a->fd, "No PRI running on span %d\n", span);
12356 return CLI_SUCCESS;
12357 }
12358 for (x = 0; x < NUM_DCHANS; x++) {
12359 if (pris[span-1].dchannels[x]) {
12360 #ifdef PRI_DUMP_INFO_STR
12361 char *info_str = NULL;
12362 #endif
12363 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12364 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12365 ast_cli(a->fd, "Status: %s\n", status);
12366 #ifdef PRI_DUMP_INFO_STR
12367 info_str = pri_dump_info_str(pris[span-1].pri);
12368 if (info_str) {
12369 ast_cli(a->fd, "%s", info_str);
12370 ast_free(info_str);
12371 }
12372 #else
12373 pri_dump_info(pris[span-1].pri);
12374 #endif
12375 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12376 }
12377 }
12378 return CLI_SUCCESS;
12379 }
12380
12381 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12382 {
12383 int x;
12384 int span;
12385 int count=0;
12386 int debug=0;
12387
12388 switch (cmd) {
12389 case CLI_INIT:
12390 e->command = "pri show debug";
12391 e->usage =
12392 "Usage: pri show debug\n"
12393 " Show the debug state of pri spans\n";
12394 return NULL;
12395 case CLI_GENERATE:
12396 return NULL;
12397 }
12398
12399 for (span = 0; span < NUM_SPANS; span++) {
12400 if (pris[span].pri) {
12401 for (x = 0; x < NUM_DCHANS; x++) {
12402 debug = 0;
12403 if (pris[span].dchans[x]) {
12404 debug = pri_get_debug(pris[span].dchans[x]);
12405 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" );
12406 count++;
12407 }
12408 }
12409 }
12410
12411 }
12412 ast_mutex_lock(&pridebugfdlock);
12413 if (pridebugfd >= 0)
12414 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12415 ast_mutex_unlock(&pridebugfdlock);
12416
12417 if (!count)
12418 ast_cli(a->fd, "No debug set or no PRI running\n");
12419 return CLI_SUCCESS;
12420 }
12421
12422 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12423 {
12424 switch (cmd) {
12425 case CLI_INIT:
12426 e->command = "pri show version";
12427 e->usage =
12428 "Usage: pri show version\n"
12429 "Show libpri version information\n";
12430 return NULL;
12431 case CLI_GENERATE:
12432 return NULL;
12433 }
12434
12435 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12436
12437 return CLI_SUCCESS;
12438 }
12439
12440 static struct ast_cli_entry dahdi_pri_cli[] = {
12441 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
12442 AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
12443 AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
12444 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
12445 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
12446 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
12447 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
12448 AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
12449 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
12450 };
12451
12452 #endif
12453
12454 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12455 {
12456 int channel;
12457 int ret;
12458 switch (cmd) {
12459 case CLI_INIT:
12460 e->command = "dahdi destroy channel";
12461 e->usage =
12462 "Usage: dahdi destroy channel <chan num>\n"
12463 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12464 return NULL;
12465 case CLI_GENERATE:
12466 return NULL;
12467 }
12468 if (a->argc != 4)
12469 return CLI_SHOWUSAGE;
12470
12471 channel = atoi(a->argv[3]);
12472 ret = dahdi_destroy_channel_bynum(channel);
12473 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12474 }
12475
12476 static void dahdi_softhangup_all(void)
12477 {
12478 struct dahdi_pvt *p;
12479 retry:
12480 ast_mutex_lock(&iflock);
12481 for (p = iflist; p; p = p->next) {
12482 ast_mutex_lock(&p->lock);
12483 if (p->owner && !p->restartpending) {
12484 if (ast_channel_trylock(p->owner)) {
12485 if (option_debug > 2)
12486 ast_verbose("Avoiding deadlock\n");
12487
12488 ast_mutex_unlock(&p->lock);
12489 ast_mutex_unlock(&iflock);
12490 goto retry;
12491 }
12492 if (option_debug > 2)
12493 ast_verbose("Softhanging up on %s\n", p->owner->name);
12494 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12495 p->restartpending = 1;
12496 num_restart_pending++;
12497 ast_channel_unlock(p->owner);
12498 }
12499 ast_mutex_unlock(&p->lock);
12500 }
12501 ast_mutex_unlock(&iflock);
12502 }
12503
12504 static int setup_dahdi(int reload);
12505 static int dahdi_restart(void)
12506 {
12507 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12508 int i, j;
12509 #endif
12510 int cancel_code;
12511 struct dahdi_pvt *p;
12512
12513 ast_mutex_lock(&restart_lock);
12514
12515 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12516 dahdi_softhangup_all();
12517 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12518
12519 #if defined(HAVE_PRI)
12520 for (i = 0; i < NUM_SPANS; i++) {
12521 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12522 cancel_code = pthread_cancel(pris[i].master);
12523 pthread_kill(pris[i].master, SIGURG);
12524 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12525 pthread_join(pris[i].master, NULL);
12526 ast_debug(4, "Joined thread of span %d\n", i);
12527 }
12528 }
12529 #endif
12530
12531 #if defined(HAVE_SS7)
12532 for (i = 0; i < NUM_SPANS; i++) {
12533 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12534 cancel_code = pthread_cancel(linksets[i].master);
12535 pthread_kill(linksets[i].master, SIGURG);
12536 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12537 pthread_join(linksets[i].master, NULL);
12538 ast_debug(4, "Joined thread of span %d\n", i);
12539 }
12540 }
12541 #endif
12542
12543 ast_mutex_lock(&monlock);
12544 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12545 cancel_code = pthread_cancel(monitor_thread);
12546 pthread_kill(monitor_thread, SIGURG);
12547 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12548 pthread_join(monitor_thread, NULL);
12549 ast_debug(4, "Joined monitor thread\n");
12550 }
12551 monitor_thread = AST_PTHREADT_NULL;
12552
12553 ast_mutex_lock(&mwi_thread_lock);
12554 while (mwi_thread_count > 0) {
12555 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12556 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12557 }
12558 ast_mutex_unlock(&mwi_thread_lock);
12559 ast_mutex_lock(&ss_thread_lock);
12560 while (ss_thread_count > 0) {
12561 int x = DAHDI_FLASH;
12562 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12563
12564 for (p = iflist; p; p = p->next) {
12565 if (p->owner)
12566 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
12567 }
12568 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12569 }
12570
12571
12572 dahdi_softhangup_all();
12573 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12574 destroy_all_channels();
12575 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12576
12577 ast_mutex_unlock(&monlock);
12578
12579 #ifdef HAVE_PRI
12580 for (i = 0; i < NUM_SPANS; i++) {
12581 for (j = 0; j < NUM_DCHANS; j++)
12582 dahdi_close_pri_fd(&(pris[i]), j);
12583 }
12584
12585 memset(pris, 0, sizeof(pris));
12586 for (i = 0; i < NUM_SPANS; i++) {
12587 ast_mutex_init(&pris[i].lock);
12588 pris[i].offset = -1;
12589 pris[i].master = AST_PTHREADT_NULL;
12590 for (j = 0; j < NUM_DCHANS; j++)
12591 pris[i].fds[j] = -1;
12592 }
12593 pri_set_error(dahdi_pri_error);
12594 pri_set_message(dahdi_pri_message);
12595 #endif
12596 #ifdef HAVE_SS7
12597 for (i = 0; i < NUM_SPANS; i++) {
12598 for (j = 0; j < NUM_DCHANS; j++)
12599 dahdi_close_ss7_fd(&(linksets[i]), j);
12600 }
12601
12602 memset(linksets, 0, sizeof(linksets));
12603 for (i = 0; i < NUM_SPANS; i++) {
12604 ast_mutex_init(&linksets[i].lock);
12605 linksets[i].master = AST_PTHREADT_NULL;
12606 for (j = 0; j < NUM_DCHANS; j++)
12607 linksets[i].fds[j] = -1;
12608 }
12609 ss7_set_error(dahdi_ss7_error);
12610 ss7_set_message(dahdi_ss7_message);
12611 #endif
12612
12613 if (setup_dahdi(2) != 0) {
12614 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12615 ast_mutex_unlock(&ss_thread_lock);
12616 return 1;
12617 }
12618 ast_mutex_unlock(&ss_thread_lock);
12619 ast_mutex_unlock(&restart_lock);
12620 return 0;
12621 }
12622
12623 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12624 {
12625 switch (cmd) {
12626 case CLI_INIT:
12627 e->command = "dahdi restart";
12628 e->usage =
12629 "Usage: dahdi restart\n"
12630 " Restarts the DAHDI channels: destroys them all and then\n"
12631 " re-reads them from chan_dahdi.conf.\n"
12632 " Note that this will STOP any running CALL on DAHDI channels.\n"
12633 "";
12634 return NULL;
12635 case CLI_GENERATE:
12636 return NULL;
12637 }
12638 if (a->argc != 2)
12639 return CLI_SHOWUSAGE;
12640
12641 if (dahdi_restart() != 0)
12642 return CLI_FAILURE;
12643 return CLI_SUCCESS;
12644 }
12645
12646 static int action_dahdirestart(struct mansession *s, const struct message *m)
12647 {
12648 if (dahdi_restart() != 0) {
12649 astman_send_error(s, m, "Failed rereading DAHDI configuration");
12650 return 1;
12651 }
12652 astman_send_ack(s, m, "DAHDIRestart: Success");
12653 return 0;
12654 }
12655
12656 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12657 {
12658 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12659 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12660 unsigned int targetnum = 0;
12661 int filtertype = 0;
12662 struct dahdi_pvt *tmp = NULL;
12663 char tmps[20] = "";
12664 char statestr[20] = "";
12665 char blockstr[20] = "";
12666 ast_mutex_t *lock;
12667 struct dahdi_pvt *start;
12668 #ifdef HAVE_PRI
12669 int trunkgroup;
12670 struct dahdi_pri *pri = NULL;
12671 int x;
12672 #endif
12673 switch (cmd) {
12674 case CLI_INIT:
12675 e->command = "dahdi show channels [trunkgroup|group|context]";
12676 e->usage =
12677 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12678 " Shows a list of available channels with optional filtering\n"
12679 " <group> must be a number between 0 and 63\n";
12680 return NULL;
12681 case CLI_GENERATE:
12682 return NULL;
12683 }
12684
12685 lock = &iflock;
12686 start = iflist;
12687
12688
12689
12690 if (!((a->argc == 3) || (a->argc == 5)))
12691 return CLI_SHOWUSAGE;
12692
12693 if (a->argc == 5) {
12694 #ifdef HAVE_PRI
12695 if (!strcasecmp(a->argv[3], "trunkgroup")) {
12696
12697 if ((trunkgroup = atoi(a->argv[4])) < 1)
12698 return CLI_SHOWUSAGE;
12699 for (x = 0; x < NUM_SPANS; x++) {
12700 if (pris[x].trunkgroup == trunkgroup) {
12701 pri = pris + x;
12702 break;
12703 }
12704 }
12705 if (pri) {
12706 start = pri->crvs;
12707 lock = &pri->lock;
12708 } else {
12709 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12710 return CLI_FAILURE;
12711 }
12712 } else
12713 #endif
12714 if (!strcasecmp(a->argv[3], "group")) {
12715 targetnum = atoi(a->argv[4]);
12716 if ((targetnum < 0) || (targetnum > 63))
12717 return CLI_SHOWUSAGE;
12718 targetnum = 1 << targetnum;
12719 filtertype = 1;
12720 } else if (!strcasecmp(a->argv[3], "context")) {
12721 filtertype = 2;
12722 }
12723 }
12724
12725 ast_mutex_lock(lock);
12726 #ifdef HAVE_PRI
12727 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12728 #else
12729 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12730 #endif
12731
12732 tmp = start;
12733 while (tmp) {
12734 if (filtertype) {
12735 switch(filtertype) {
12736 case 1:
12737 if (!(tmp->group & targetnum)) {
12738 tmp = tmp->next;
12739 continue;
12740 }
12741 break;
12742 case 2:
12743 if (strcasecmp(tmp->context, a->argv[4])) {
12744 tmp = tmp->next;
12745 continue;
12746 }
12747 break;
12748 default:
12749 ;
12750 }
12751 }
12752 if (tmp->channel > 0) {
12753 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12754 } else
12755 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12756
12757 if (tmp->locallyblocked)
12758 blockstr[0] = 'L';
12759 else
12760 blockstr[0] = ' ';
12761
12762 if (tmp->remotelyblocked)
12763 blockstr[1] = 'R';
12764 else
12765 blockstr[1] = ' ';
12766
12767 blockstr[2] = '\0';
12768
12769 snprintf(statestr, sizeof(statestr), "%s", "In Service");
12770
12771 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12772 tmp = tmp->next;
12773 }
12774 ast_mutex_unlock(lock);
12775 return CLI_SUCCESS;
12776 #undef FORMAT
12777 #undef FORMAT2
12778 }
12779
12780 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12781 {
12782 int channel;
12783 struct dahdi_pvt *tmp = NULL;
12784 struct dahdi_confinfo ci;
12785 struct dahdi_params ps;
12786 int x;
12787 ast_mutex_t *lock;
12788 struct dahdi_pvt *start;
12789 #ifdef HAVE_PRI
12790 char *c;
12791 int trunkgroup;
12792 struct dahdi_pri *pri=NULL;
12793 #endif
12794 switch (cmd) {
12795 case CLI_INIT:
12796 e->command = "dahdi show channel";
12797 e->usage =
12798 "Usage: dahdi show channel <chan num>\n"
12799 " Detailed information about a given channel\n";
12800 return NULL;
12801 case CLI_GENERATE:
12802 return NULL;
12803 }
12804
12805 lock = &iflock;
12806 start = iflist;
12807
12808 if (a->argc != 4)
12809 return CLI_SHOWUSAGE;
12810 #ifdef HAVE_PRI
12811 if ((c = strchr(a->argv[3], ':'))) {
12812 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12813 return CLI_SHOWUSAGE;
12814 if ((trunkgroup < 1) || (channel < 1))
12815 return CLI_SHOWUSAGE;
12816 for (x = 0; x < NUM_SPANS; x++) {
12817 if (pris[x].trunkgroup == trunkgroup) {
12818 pri = pris + x;
12819 break;
12820 }
12821 }
12822 if (pri) {
12823 start = pri->crvs;
12824 lock = &pri->lock;
12825 } else {
12826 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12827 return CLI_FAILURE;
12828 }
12829 } else
12830 #endif
12831 channel = atoi(a->argv[3]);
12832
12833 ast_mutex_lock(lock);
12834 tmp = start;
12835 while (tmp) {
12836 if (tmp->channel == channel) {
12837 #ifdef HAVE_PRI
12838 if (pri)
12839 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12840 else
12841 #endif
12842 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12843 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12844 ast_cli(a->fd, "Span: %d\n", tmp->span);
12845 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12846 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12847 ast_cli(a->fd, "Context: %s\n", tmp->context);
12848 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12849 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12850 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12851 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12852 if (tmp->vars) {
12853 struct ast_variable *v;
12854 ast_cli(a->fd, "Variables:\n");
12855 for (v = tmp->vars ; v ; v = v->next)
12856 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
12857 }
12858 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12859 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12860 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12861 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12862 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12863 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)" : "");
12864 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)" : "");
12865 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)" : "");
12866 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12867 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12868 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12869 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12870 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12871 if (tmp->busydetect) {
12872 #if defined(BUSYDETECT_TONEONLY)
12873 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12874 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12875 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12876 #endif
12877 #ifdef BUSYDETECT_DEBUG
12878 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
12879 #endif
12880 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
12881 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
12882 }
12883 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12884 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12885 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12886 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12887 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12888 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12889 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12890 ast_cli(a->fd, "Echo Cancellation:\n");
12891
12892 if (tmp->echocancel.head.tap_length) {
12893 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12894 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12895 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12896 }
12897 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12898 } else {
12899 ast_cli(a->fd, "\tnone\n");
12900 }
12901 if (tmp->master)
12902 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12903 for (x = 0; x < MAX_SLAVES; x++) {
12904 if (tmp->slaves[x])
12905 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12906 }
12907 #ifdef HAVE_SS7
12908 if (tmp->ss7) {
12909 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12910 }
12911 #endif
12912 #ifdef HAVE_PRI
12913 if (tmp->pri) {
12914 ast_cli(a->fd, "PRI Flags: ");
12915 if (tmp->resetting)
12916 ast_cli(a->fd, "Resetting ");
12917 if (tmp->call)
12918 ast_cli(a->fd, "Call ");
12919 if (tmp->bearer)
12920 ast_cli(a->fd, "Bearer ");
12921 ast_cli(a->fd, "\n");
12922 if (tmp->logicalspan)
12923 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12924 else
12925 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12926 }
12927
12928 #endif
12929 memset(&ci, 0, sizeof(ci));
12930 ps.channo = tmp->channel;
12931 if (tmp->subs[SUB_REAL].dfd > -1) {
12932 memset(&ci, 0, sizeof(ci));
12933 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12934 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12935 }
12936 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12937 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12938 }
12939 memset(&ps, 0, sizeof(ps));
12940 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12941 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12942 } else {
12943 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12944 }
12945 }
12946 ast_mutex_unlock(lock);
12947 return CLI_SUCCESS;
12948 }
12949 tmp = tmp->next;
12950 }
12951
12952 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12953 ast_mutex_unlock(lock);
12954 return CLI_FAILURE;
12955 }
12956
12957 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12958 {
12959 int i, j;
12960 switch (cmd) {
12961 case CLI_INIT:
12962 e->command = "dahdi show cadences";
12963 e->usage =
12964 "Usage: dahdi show cadences\n"
12965 " Shows all cadences currently defined\n";
12966 return NULL;
12967 case CLI_GENERATE:
12968 return NULL;
12969 }
12970 for (i = 0; i < num_cadence; i++) {
12971 char output[1024];
12972 char tmp[16], tmp2[64];
12973 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12974 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12975
12976 for (j = 0; j < 16; j++) {
12977 if (cadences[i].ringcadence[j] == 0)
12978 break;
12979 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12980 if (cidrings[i] * 2 - 1 == j)
12981 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12982 else
12983 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12984 if (j != 0)
12985 strncat(output, ",", sizeof(output) - strlen(output) - 1);
12986 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12987 }
12988 ast_cli(a->fd,"%s\n",output);
12989 }
12990 return CLI_SUCCESS;
12991 }
12992
12993
12994 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12995 {
12996 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12997 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12998 int span;
12999 int res;
13000 char alarmstr[50];
13001
13002 int ctl;
13003 struct dahdi_spaninfo s;
13004
13005 switch (cmd) {
13006 case CLI_INIT:
13007 e->command = "dahdi show status";
13008 e->usage =
13009 "Usage: dahdi show status\n"
13010 " Shows a list of DAHDI cards with status\n";
13011 return NULL;
13012 case CLI_GENERATE:
13013 return NULL;
13014 }
13015 ctl = open("/dev/dahdi/ctl", O_RDWR);
13016 if (ctl < 0) {
13017 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13018 return CLI_FAILURE;
13019 }
13020 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13021
13022 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13023 s.spanno = span;
13024 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13025 if (res) {
13026 continue;
13027 }
13028 alarmstr[0] = '\0';
13029 if (s.alarms > 0) {
13030 if (s.alarms & DAHDI_ALARM_BLUE)
13031 strcat(alarmstr, "BLU/");
13032 if (s.alarms & DAHDI_ALARM_YELLOW)
13033 strcat(alarmstr, "YEL/");
13034 if (s.alarms & DAHDI_ALARM_RED)
13035 strcat(alarmstr, "RED/");
13036 if (s.alarms & DAHDI_ALARM_LOOPBACK)
13037 strcat(alarmstr, "LB/");
13038 if (s.alarms & DAHDI_ALARM_RECOVER)
13039 strcat(alarmstr, "REC/");
13040 if (s.alarms & DAHDI_ALARM_NOTOPEN)
13041 strcat(alarmstr, "NOP/");
13042 if (!strlen(alarmstr))
13043 strcat(alarmstr, "UUU/");
13044 if (strlen(alarmstr)) {
13045
13046 alarmstr[strlen(alarmstr) - 1] = '\0';
13047 }
13048 } else {
13049 if (s.numchans)
13050 strcpy(alarmstr, "OK");
13051 else
13052 strcpy(alarmstr, "UNCONFIGURED");
13053 }
13054
13055 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13056 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13057 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13058 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13059 "CAS"
13060 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13061 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13062 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13063 "Unk"
13064 , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13065 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13066 , lbostr[s.lbo]
13067 );
13068 }
13069 close(ctl);
13070
13071 return CLI_SUCCESS;
13072 #undef FORMAT
13073 #undef FORMAT2
13074 }
13075
13076 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13077 {
13078 int pseudo_fd = -1;
13079 struct dahdi_versioninfo vi;
13080
13081 switch (cmd) {
13082 case CLI_INIT:
13083 e->command = "dahdi show version";
13084 e->usage =
13085 "Usage: dahdi show version\n"
13086 " Shows the DAHDI version in use\n";
13087 return NULL;
13088 case CLI_GENERATE:
13089 return NULL;
13090 }
13091 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13092 ast_cli(a->fd, "Failed to open control file to get version.\n");
13093 return CLI_SUCCESS;
13094 }
13095
13096 strcpy(vi.version, "Unknown");
13097 strcpy(vi.echo_canceller, "Unknown");
13098
13099 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13100 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13101 else
13102 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13103
13104 close(pseudo_fd);
13105
13106 return CLI_SUCCESS;
13107 }
13108
13109 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13110 {
13111 int channel;
13112 int gain;
13113 int tx;
13114 struct dahdi_hwgain hwgain;
13115 struct dahdi_pvt *tmp = NULL;
13116
13117 switch (cmd) {
13118 case CLI_INIT:
13119 e->command = "dahdi set hwgain";
13120 e->usage =
13121 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
13122 " Sets the hardware gain on a a given channel, overriding the\n"
13123 " value provided at module loadtime, whether the channel is in\n"
13124 " use or not. Changes take effect immediately.\n"
13125 " <rx|tx> which direction do you want to change (relative to our module)\n"
13126 " <chan num> is the channel number relative to the device\n"
13127 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13128 return NULL;
13129 case CLI_GENERATE:
13130 return NULL;
13131 }
13132
13133 if (a->argc != 6)
13134 return CLI_SHOWUSAGE;
13135
13136 if (!strcasecmp("rx", a->argv[3]))
13137 tx = 0;
13138 else if (!strcasecmp("tx", a->argv[3]))
13139 tx = 1;
13140 else
13141 return CLI_SHOWUSAGE;
13142
13143 channel = atoi(a->argv[4]);
13144 gain = atof(a->argv[5])*10.0;
13145
13146 ast_mutex_lock(&iflock);
13147
13148 for (tmp = iflist; tmp; tmp = tmp->next) {
13149
13150 if (tmp->channel != channel)
13151 continue;
13152
13153 if (tmp->subs[SUB_REAL].dfd == -1)
13154 break;
13155
13156 hwgain.newgain = gain;
13157 hwgain.tx = tx;
13158 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
13159 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
13160 ast_mutex_unlock(&iflock);
13161 return CLI_FAILURE;
13162 }
13163 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
13164 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
13165 break;
13166 }
13167
13168 ast_mutex_unlock(&iflock);
13169
13170 if (tmp)
13171 return CLI_SUCCESS;
13172
13173 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13174 return CLI_FAILURE;
13175
13176 }
13177
13178 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13179 {
13180 int channel;
13181 float gain;
13182 int tx;
13183 int res;
13184 ast_mutex_t *lock;
13185 struct dahdi_pvt *tmp = NULL;
13186
13187 switch (cmd) {
13188 case CLI_INIT:
13189 e->command = "dahdi set swgain";
13190 e->usage =
13191 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13192 " Sets the software gain on a a given channel, overriding the\n"
13193 " value provided at module loadtime, whether the channel is in\n"
13194 " use or not. Changes take effect immediately.\n"
13195 " <rx|tx> which direction do you want to change (relative to our module)\n"
13196 " <chan num> is the channel number relative to the device\n"
13197 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13198 return NULL;
13199 case CLI_GENERATE:
13200 return NULL;
13201 }
13202
13203 lock = &iflock;
13204
13205 if (a->argc != 6)
13206 return CLI_SHOWUSAGE;
13207
13208 if (!strcasecmp("rx", a->argv[3]))
13209 tx = 0;
13210 else if (!strcasecmp("tx", a->argv[3]))
13211 tx = 1;
13212 else
13213 return CLI_SHOWUSAGE;
13214
13215 channel = atoi(a->argv[4]);
13216 gain = atof(a->argv[5]);
13217
13218 ast_mutex_lock(lock);
13219 for (tmp = iflist; tmp; tmp = tmp->next) {
13220
13221 if (tmp->channel != channel)
13222 continue;
13223
13224 if (tmp->subs[SUB_REAL].dfd == -1)
13225 break;
13226
13227 if (tx)
13228 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13229 else
13230 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13231
13232 if (res) {
13233 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13234 ast_mutex_unlock(lock);
13235 return CLI_FAILURE;
13236 }
13237
13238 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13239 tx ? "tx" : "rx", gain, channel);
13240 break;
13241 }
13242 ast_mutex_unlock(lock);
13243
13244 if (tmp)
13245 return CLI_SUCCESS;
13246
13247 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13248 return CLI_FAILURE;
13249
13250 }
13251
13252 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13253 {
13254 int channel;
13255 int on;
13256 struct dahdi_pvt *dahdi_chan = NULL;
13257
13258 switch (cmd) {
13259 case CLI_INIT:
13260 e->command = "dahdi set dnd";
13261 e->usage =
13262 "Usage: dahdi set dnd <chan#> <on|off>\n"
13263 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13264 " Changes take effect immediately.\n"
13265 " <chan num> is the channel number\n"
13266 " <on|off> Enable or disable DND mode?\n"
13267 ;
13268 return NULL;
13269 case CLI_GENERATE:
13270 return NULL;
13271 }
13272
13273 if (a->argc != 5)
13274 return CLI_SHOWUSAGE;
13275
13276 if ((channel = atoi(a->argv[3])) <= 0) {
13277 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13278 return CLI_SHOWUSAGE;
13279 }
13280
13281 if (ast_true(a->argv[4]))
13282 on = 1;
13283 else if (ast_false(a->argv[4]))
13284 on = 0;
13285 else {
13286 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13287 return CLI_SHOWUSAGE;
13288 }
13289
13290 ast_mutex_lock(&iflock);
13291 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13292 if (dahdi_chan->channel != channel)
13293 continue;
13294
13295
13296 dahdi_dnd(dahdi_chan, on);
13297 break;
13298 }
13299 ast_mutex_unlock(&iflock);
13300
13301 if (!dahdi_chan) {
13302 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13303 return CLI_FAILURE;
13304 }
13305
13306 return CLI_SUCCESS;
13307 }
13308
13309 static struct ast_cli_entry dahdi_cli[] = {
13310 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
13311 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
13312 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
13313 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
13314 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
13315 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
13316 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
13317 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
13318 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
13319 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
13320 };
13321
13322 #define TRANSFER 0
13323 #define HANGUP 1
13324
13325 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13326 {
13327 if (p) {
13328 switch (mode) {
13329 case TRANSFER:
13330 p->fake_event = DAHDI_EVENT_WINKFLASH;
13331 break;
13332 case HANGUP:
13333 p->fake_event = DAHDI_EVENT_ONHOOK;
13334 break;
13335 default:
13336 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
13337 }
13338 }
13339 return 0;
13340 }
13341 static struct dahdi_pvt *find_channel(int channel)
13342 {
13343 struct dahdi_pvt *p = iflist;
13344 while (p) {
13345 if (p->channel == channel) {
13346 break;
13347 }
13348 p = p->next;
13349 }
13350 return p;
13351 }
13352
13353 static int action_dahdidndon(struct mansession *s, const struct message *m)
13354 {
13355 struct dahdi_pvt *p = NULL;
13356 const char *channel = astman_get_header(m, "DAHDIChannel");
13357
13358 if (ast_strlen_zero(channel)) {
13359 astman_send_error(s, m, "No channel specified");
13360 return 0;
13361 }
13362 p = find_channel(atoi(channel));
13363 if (!p) {
13364 astman_send_error(s, m, "No such channel");
13365 return 0;
13366 }
13367 p->dnd = 1;
13368 astman_send_ack(s, m, "DND Enabled");
13369 return 0;
13370 }
13371
13372 static int action_dahdidndoff(struct mansession *s, const struct message *m)
13373 {
13374 struct dahdi_pvt *p = NULL;
13375 const char *channel = astman_get_header(m, "DAHDIChannel");
13376
13377 if (ast_strlen_zero(channel)) {
13378 astman_send_error(s, m, "No channel specified");
13379 return 0;
13380 }
13381 p = find_channel(atoi(channel));
13382 if (!p) {
13383 astman_send_error(s, m, "No such channel");
13384 return 0;
13385 }
13386 p->dnd = 0;
13387 astman_send_ack(s, m, "DND Disabled");
13388 return 0;
13389 }
13390
13391 static int action_transfer(struct mansession *s, const struct message *m)
13392 {
13393 struct dahdi_pvt *p = NULL;
13394 const char *channel = astman_get_header(m, "DAHDIChannel");
13395
13396 if (ast_strlen_zero(channel)) {
13397 astman_send_error(s, m, "No channel specified");
13398 return 0;
13399 }
13400 p = find_channel(atoi(channel));
13401 if (!p) {
13402 astman_send_error(s, m, "No such channel");
13403 return 0;
13404 }
13405 dahdi_fake_event(p,TRANSFER);
13406 astman_send_ack(s, m, "DAHDITransfer");
13407 return 0;
13408 }
13409
13410 static int action_transferhangup(struct mansession *s, const struct message *m)
13411 {
13412 struct dahdi_pvt *p = NULL;
13413 const char *channel = astman_get_header(m, "DAHDIChannel");
13414
13415 if (ast_strlen_zero(channel)) {
13416 astman_send_error(s, m, "No channel specified");
13417 return 0;
13418 }
13419 p = find_channel(atoi(channel));
13420 if (!p) {
13421 astman_send_error(s, m, "No such channel");
13422 return 0;
13423 }
13424 dahdi_fake_event(p,HANGUP);
13425 astman_send_ack(s, m, "DAHDIHangup");
13426 return 0;
13427 }
13428
13429 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
13430 {
13431 struct dahdi_pvt *p = NULL;
13432 const char *channel = astman_get_header(m, "DAHDIChannel");
13433 const char *number = astman_get_header(m, "Number");
13434 int i;
13435
13436 if (ast_strlen_zero(channel)) {
13437 astman_send_error(s, m, "No channel specified");
13438 return 0;
13439 }
13440 if (ast_strlen_zero(number)) {
13441 astman_send_error(s, m, "No number specified");
13442 return 0;
13443 }
13444 p = find_channel(atoi(channel));
13445 if (!p) {
13446 astman_send_error(s, m, "No such channel");
13447 return 0;
13448 }
13449 if (!p->owner) {
13450 astman_send_error(s, m, "Channel does not have it's owner");
13451 return 0;
13452 }
13453 for (i = 0; i < strlen(number); i++) {
13454 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13455 dahdi_queue_frame(p, &f, NULL);
13456 }
13457 astman_send_ack(s, m, "DAHDIDialOffhook");
13458 return 0;
13459 }
13460
13461 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
13462 {
13463 struct dahdi_pvt *tmp = NULL;
13464 const char *id = astman_get_header(m, "ActionID");
13465 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13466 char idText[256] = "";
13467 int channels = 0;
13468 int dahdichanquery = -1;
13469 if (!ast_strlen_zero(dahdichannel)) {
13470 dahdichanquery = atoi(dahdichannel);
13471 }
13472
13473 astman_send_ack(s, m, "DAHDI channel status will follow");
13474 if (!ast_strlen_zero(id))
13475 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13476
13477 ast_mutex_lock(&iflock);
13478
13479 tmp = iflist;
13480 while (tmp) {
13481 if (tmp->channel > 0) {
13482 int alm = get_alarms(tmp);
13483
13484
13485 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13486 continue;
13487
13488 channels++;
13489 if (tmp->owner) {
13490
13491 astman_append(s,
13492 "Event: DAHDIShowChannels\r\n"
13493 "DAHDIChannel: %d\r\n"
13494 "Channel: %s\r\n"
13495 "Uniqueid: %s\r\n"
13496 "AccountCode: %s\r\n"
13497 "Signalling: %s\r\n"
13498 "SignallingCode: %d\r\n"
13499 "Context: %s\r\n"
13500 "DND: %s\r\n"
13501 "Alarm: %s\r\n"
13502 "%s"
13503 "\r\n",
13504 tmp->channel,
13505 tmp->owner->name,
13506 tmp->owner->uniqueid,
13507 tmp->owner->accountcode,
13508 sig2str(tmp->sig),
13509 tmp->sig,
13510 tmp->context,
13511 tmp->dnd ? "Enabled" : "Disabled",
13512 alarm2str(alm), idText);
13513 } else {
13514 astman_append(s,
13515 "Event: DAHDIShowChannels\r\n"
13516 "DAHDIChannel: %d\r\n"
13517 "Signalling: %s\r\n"
13518 "SignallingCode: %d\r\n"
13519 "Context: %s\r\n"
13520 "DND: %s\r\n"
13521 "Alarm: %s\r\n"
13522 "%s"
13523 "\r\n",
13524 tmp->channel, sig2str(tmp->sig), tmp->sig,
13525 tmp->context,
13526 tmp->dnd ? "Enabled" : "Disabled",
13527 alarm2str(alm), idText);
13528 }
13529 }
13530
13531 tmp = tmp->next;
13532 }
13533
13534 ast_mutex_unlock(&iflock);
13535
13536 astman_append(s,
13537 "Event: DAHDIShowChannelsComplete\r\n"
13538 "%s"
13539 "Items: %d\r\n"
13540 "\r\n",
13541 idText,
13542 channels);
13543 return 0;
13544 }
13545
13546 #ifdef HAVE_SS7
13547 static int linkset_addsigchan(int sigchan)
13548 {
13549 struct dahdi_ss7 *link;
13550 int res;
13551 int curfd;
13552 struct dahdi_params p;
13553 struct dahdi_bufferinfo bi;
13554 struct dahdi_spaninfo si;
13555
13556
13557 link = ss7_resolve_linkset(cur_linkset);
13558 if (!link) {
13559 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
13560 return -1;
13561 }
13562
13563 if (cur_ss7type < 0) {
13564 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13565 return -1;
13566 }
13567
13568 if (!link->ss7)
13569 link->ss7 = ss7_new(cur_ss7type);
13570
13571 if (!link->ss7) {
13572 ast_log(LOG_ERROR, "Can't create new SS7!\n");
13573 return -1;
13574 }
13575
13576 link->type = cur_ss7type;
13577
13578 if (cur_pointcode < 0) {
13579 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13580 return -1;
13581 } else
13582 ss7_set_pc(link->ss7, cur_pointcode);
13583
13584 if (sigchan < 0) {
13585 ast_log(LOG_ERROR, "Invalid sigchan!\n");
13586 return -1;
13587 } else {
13588 if (link->numsigchans >= NUM_DCHANS) {
13589 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13590 return -1;
13591 }
13592 curfd = link->numsigchans;
13593
13594 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13595 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13596 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13597 return -1;
13598 }
13599 memset(&p, 0, sizeof(p));
13600 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13601 if (res) {
13602 dahdi_close_ss7_fd(link, curfd);
13603 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13604 return -1;
13605 }
13606 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13607 dahdi_close_ss7_fd(link, curfd);
13608 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13609 return -1;
13610 }
13611
13612 memset(&bi, 0, sizeof(bi));
13613 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13614 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13615 bi.numbufs = 32;
13616 bi.bufsize = 512;
13617
13618 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13619 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13620 dahdi_close_ss7_fd(link, curfd);
13621 return -1;
13622 }
13623
13624 if (p.sigtype == DAHDI_SIG_MTP2)
13625 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13626 else
13627 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13628
13629 link->numsigchans++;
13630
13631 memset(&si, 0, sizeof(si));
13632 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13633 if (res) {
13634 dahdi_close_ss7_fd(link, curfd);
13635 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13636 }
13637
13638 if (!si.alarms) {
13639 link->linkstate[curfd] = LINKSTATE_DOWN;
13640 ss7_link_noalarm(link->ss7, link->fds[curfd]);
13641 } else {
13642 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13643 ss7_link_alarm(link->ss7, link->fds[curfd]);
13644 }
13645 }
13646
13647 if (cur_adjpointcode < 0) {
13648 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13649 return -1;
13650 } else {
13651 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13652 }
13653
13654 if (cur_defaultdpc < 0) {
13655 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13656 return -1;
13657 }
13658
13659 if (cur_networkindicator < 0) {
13660 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13661 return -1;
13662 } else
13663 ss7_set_network_ind(link->ss7, cur_networkindicator);
13664
13665 return 0;
13666 }
13667
13668 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13669 {
13670 int span;
13671 switch (cmd) {
13672 case CLI_INIT:
13673 e->command = "ss7 no debug linkset";
13674 e->usage =
13675 "Usage: ss7 no debug linkset <span>\n"
13676 " Disables debugging on a given SS7 linkset\n";
13677 return NULL;
13678 case CLI_GENERATE:
13679 return NULL;
13680 }
13681 if (a->argc < 5)
13682 return CLI_SHOWUSAGE;
13683 span = atoi(a->argv[4]);
13684 if ((span < 1) || (span > NUM_SPANS)) {
13685 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13686 return CLI_SUCCESS;
13687 }
13688 if (!linksets[span-1].ss7) {
13689 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13690 return CLI_SUCCESS;
13691 }
13692 if (linksets[span-1].ss7)
13693 ss7_set_debug(linksets[span-1].ss7, 0);
13694
13695 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13696 return CLI_SUCCESS;
13697 }
13698
13699 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13700 {
13701 int span;
13702 switch (cmd) {
13703 case CLI_INIT:
13704 e->command = "ss7 debug linkset";
13705 e->usage =
13706 "Usage: ss7 debug linkset <linkset>\n"
13707 " Enables debugging on a given SS7 linkset\n";
13708 return NULL;
13709 case CLI_GENERATE:
13710 return NULL;
13711 }
13712 if (a->argc < 4)
13713 return CLI_SHOWUSAGE;
13714 span = atoi(a->argv[3]);
13715 if ((span < 1) || (span > NUM_SPANS)) {
13716 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13717 return CLI_SUCCESS;
13718 }
13719 if (!linksets[span-1].ss7) {
13720 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13721 return CLI_SUCCESS;
13722 }
13723 if (linksets[span-1].ss7)
13724 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13725
13726 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13727 return CLI_SUCCESS;
13728 }
13729
13730 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13731 {
13732 int linkset, cic;
13733 int blocked = -1, i;
13734 switch (cmd) {
13735 case CLI_INIT:
13736 e->command = "ss7 block cic";
13737 e->usage =
13738 "Usage: ss7 block cic <linkset> <CIC>\n"
13739 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13740 return NULL;
13741 case CLI_GENERATE:
13742 return NULL;
13743 }
13744 if (a->argc == 5)
13745 linkset = atoi(a->argv[3]);
13746 else
13747 return CLI_SHOWUSAGE;
13748
13749 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13750 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13751 return CLI_SUCCESS;
13752 }
13753
13754 if (!linksets[linkset-1].ss7) {
13755 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13756 return CLI_SUCCESS;
13757 }
13758
13759 cic = atoi(a->argv[4]);
13760
13761 if (cic < 1) {
13762 ast_cli(a->fd, "Invalid CIC specified!\n");
13763 return CLI_SUCCESS;
13764 }
13765
13766 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13767 if (linksets[linkset-1].pvts[i]->cic == cic) {
13768 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13769 if (!blocked) {
13770 ast_mutex_lock(&linksets[linkset-1].lock);
13771 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13772 ast_mutex_unlock(&linksets[linkset-1].lock);
13773 }
13774 }
13775 }
13776
13777 if (blocked < 0) {
13778 ast_cli(a->fd, "Invalid CIC specified!\n");
13779 return CLI_SUCCESS;
13780 }
13781
13782 if (!blocked)
13783 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13784 else
13785 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13786
13787
13788 pthread_kill(linksets[linkset-1].master, SIGURG);
13789
13790 return CLI_SUCCESS;
13791 }
13792
13793 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13794 {
13795 int linkset;
13796 int i;
13797 switch (cmd) {
13798 case CLI_INIT:
13799 e->command = "ss7 block linkset";
13800 e->usage =
13801 "Usage: ss7 block linkset <linkset number>\n"
13802 " Sends a remote blocking request for all CICs on the given linkset\n";
13803 return NULL;
13804 case CLI_GENERATE:
13805 return NULL;
13806 }
13807 if (a->argc == 4)
13808 linkset = atoi(a->argv[3]);
13809 else
13810 return CLI_SHOWUSAGE;
13811
13812 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13813 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13814 return CLI_SUCCESS;
13815 }
13816
13817 if (!linksets[linkset-1].ss7) {
13818 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13819 return CLI_SUCCESS;
13820 }
13821
13822 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13823 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13824 ast_mutex_lock(&linksets[linkset-1].lock);
13825 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13826 ast_mutex_unlock(&linksets[linkset-1].lock);
13827 }
13828
13829
13830 pthread_kill(linksets[linkset-1].master, SIGURG);
13831
13832 return CLI_SUCCESS;
13833 }
13834
13835 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13836 {
13837 int linkset, cic;
13838 int i, blocked = -1;
13839 switch (cmd) {
13840 case CLI_INIT:
13841 e->command = "ss7 unblock cic";
13842 e->usage =
13843 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13844 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13845 return NULL;
13846 case CLI_GENERATE:
13847 return NULL;
13848 }
13849
13850 if (a->argc == 5)
13851 linkset = atoi(a->argv[3]);
13852 else
13853 return CLI_SHOWUSAGE;
13854
13855 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13856 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13857 return CLI_SUCCESS;
13858 }
13859
13860 if (!linksets[linkset-1].ss7) {
13861 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13862 return CLI_SUCCESS;
13863 }
13864
13865 cic = atoi(a->argv[4]);
13866
13867 if (cic < 1) {
13868 ast_cli(a->fd, "Invalid CIC specified!\n");
13869 return CLI_SUCCESS;
13870 }
13871
13872 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13873 if (linksets[linkset-1].pvts[i]->cic == cic) {
13874 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13875 if (blocked) {
13876 ast_mutex_lock(&linksets[linkset-1].lock);
13877 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13878 ast_mutex_unlock(&linksets[linkset-1].lock);
13879 }
13880 }
13881 }
13882
13883 if (blocked > 0)
13884 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13885
13886
13887 pthread_kill(linksets[linkset-1].master, SIGURG);
13888
13889 return CLI_SUCCESS;
13890 }
13891
13892 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13893 {
13894 int linkset;
13895 int i;
13896 switch (cmd) {
13897 case CLI_INIT:
13898 e->command = "ss7 unblock linkset";
13899 e->usage =
13900 "Usage: ss7 unblock linkset <linkset number>\n"
13901 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13902 return NULL;
13903 case CLI_GENERATE:
13904 return NULL;
13905 }
13906
13907 if (a->argc == 4)
13908 linkset = atoi(a->argv[3]);
13909 else
13910 return CLI_SHOWUSAGE;
13911
13912 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13913 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13914 return CLI_SUCCESS;
13915 }
13916
13917 if (!linksets[linkset-1].ss7) {
13918 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13919 return CLI_SUCCESS;
13920 }
13921
13922 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13923 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13924 ast_mutex_lock(&linksets[linkset-1].lock);
13925 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13926 ast_mutex_unlock(&linksets[linkset-1].lock);
13927 }
13928
13929
13930 pthread_kill(linksets[linkset-1].master, SIGURG);
13931
13932 return CLI_SUCCESS;
13933 }
13934
13935 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13936 {
13937 int linkset;
13938 struct dahdi_ss7 *ss7;
13939 switch (cmd) {
13940 case CLI_INIT:
13941 e->command = "ss7 show linkset";
13942 e->usage =
13943 "Usage: ss7 show linkset <span>\n"
13944 " Shows the status of an SS7 linkset.\n";
13945 return NULL;
13946 case CLI_GENERATE:
13947 return NULL;
13948 }
13949
13950 if (a->argc < 4)
13951 return CLI_SHOWUSAGE;
13952 linkset = atoi(a->argv[3]);
13953 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13954 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13955 return CLI_SUCCESS;
13956 }
13957 if (!linksets[linkset-1].ss7) {
13958 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13959 return CLI_SUCCESS;
13960 }
13961 if (linksets[linkset-1].ss7)
13962 ss7 = &linksets[linkset-1];
13963
13964 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
13965
13966 return CLI_SUCCESS;
13967 }
13968
13969 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13970 {
13971 switch (cmd) {
13972 case CLI_INIT:
13973 e->command = "ss7 show version";
13974 e->usage =
13975 "Usage: ss7 show version\n"
13976 " Show the libss7 version\n";
13977 return NULL;
13978 case CLI_GENERATE:
13979 return NULL;
13980 }
13981
13982 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
13983
13984 return CLI_SUCCESS;
13985 }
13986
13987 static struct ast_cli_entry dahdi_ss7_cli[] = {
13988 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
13989 AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"),
13990 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
13991 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
13992 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
13993 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
13994 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
13995 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
13996 };
13997 #endif
13998
13999 static int __unload_module(void)
14000 {
14001 struct dahdi_pvt *p;
14002 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14003 int i, j;
14004 #endif
14005
14006 #ifdef HAVE_PRI
14007 for (i = 0; i < NUM_SPANS; i++) {
14008 if (pris[i].master != AST_PTHREADT_NULL)
14009 pthread_cancel(pris[i].master);
14010 }
14011 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14012 ast_unregister_application(dahdi_send_keypad_facility_app);
14013 #endif
14014 #if defined(HAVE_SS7)
14015 for (i = 0; i < NUM_SPANS; i++) {
14016 if (linksets[i].master != AST_PTHREADT_NULL)
14017 pthread_cancel(linksets[i].master);
14018 }
14019 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14020 #endif
14021
14022 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14023 ast_manager_unregister( "DAHDIDialOffhook" );
14024 ast_manager_unregister( "DAHDIHangup" );
14025 ast_manager_unregister( "DAHDITransfer" );
14026 ast_manager_unregister( "DAHDIDNDoff" );
14027 ast_manager_unregister( "DAHDIDNDon" );
14028 ast_manager_unregister("DAHDIShowChannels");
14029 ast_manager_unregister("DAHDIRestart");
14030 ast_channel_unregister(&dahdi_tech);
14031 ast_mutex_lock(&iflock);
14032
14033 p = iflist;
14034 while (p) {
14035 if (p->owner)
14036 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14037 p = p->next;
14038 }
14039 ast_mutex_unlock(&iflock);
14040 ast_mutex_lock(&monlock);
14041 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14042 pthread_cancel(monitor_thread);
14043 pthread_kill(monitor_thread, SIGURG);
14044 pthread_join(monitor_thread, NULL);
14045 }
14046 monitor_thread = AST_PTHREADT_STOP;
14047 ast_mutex_unlock(&monlock);
14048
14049 destroy_all_channels();
14050
14051 #if defined(HAVE_PRI)
14052 for (i = 0; i < NUM_SPANS; i++) {
14053 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14054 pthread_join(pris[i].master, NULL);
14055 for (j = 0; j < NUM_DCHANS; j++) {
14056 dahdi_close_pri_fd(&(pris[i]), j);
14057 }
14058 }
14059 #endif
14060
14061 #if defined(HAVE_SS7)
14062 for (i = 0; i < NUM_SPANS; i++) {
14063 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14064 pthread_join(linksets[i].master, NULL);
14065 for (j = 0; j < NUM_DCHANS; j++) {
14066 dahdi_close_ss7_fd(&(linksets[i]), j);
14067 }
14068 }
14069 #endif
14070
14071 ast_cond_destroy(&mwi_thread_complete);
14072 ast_cond_destroy(&ss_thread_complete);
14073 return 0;
14074 }
14075
14076 static int unload_module(void)
14077 {
14078 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14079 int y;
14080 #endif
14081 #ifdef HAVE_PRI
14082 for (y = 0; y < NUM_SPANS; y++)
14083 ast_mutex_destroy(&pris[y].lock);
14084 #endif
14085 #ifdef HAVE_SS7
14086 for (y = 0; y < NUM_SPANS; y++)
14087 ast_mutex_destroy(&linksets[y].lock);
14088 #endif
14089 return __unload_module();
14090 }
14091
14092 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
14093 {
14094 char *c, *chan;
14095 int x, start, finish;
14096 struct dahdi_pvt *tmp;
14097 #ifdef HAVE_PRI
14098 struct dahdi_pri *pri;
14099 int trunkgroup, y;
14100 #endif
14101
14102 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14103 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14104 return -1;
14105 }
14106
14107 c = ast_strdupa(value);
14108
14109 #ifdef HAVE_PRI
14110 pri = NULL;
14111 if (iscrv) {
14112 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14113 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14114 return -1;
14115 }
14116 if (trunkgroup < 1) {
14117 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14118 return -1;
14119 }
14120 c += y;
14121 for (y = 0; y < NUM_SPANS; y++) {
14122 if (pris[y].trunkgroup == trunkgroup) {
14123 pri = pris + y;
14124 break;
14125 }
14126 }
14127 if (!pri) {
14128 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14129 return -1;
14130 }
14131 }
14132 #endif
14133
14134 while ((chan = strsep(&c, ","))) {
14135 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14136
14137 } else if (sscanf(chan, "%30d", &start)) {
14138
14139 finish = start;
14140 } else if (!strcasecmp(chan, "pseudo")) {
14141 finish = start = CHAN_PSEUDO;
14142 if (found_pseudo)
14143 *found_pseudo = 1;
14144 } else {
14145 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14146 return -1;
14147 }
14148 if (finish < start) {
14149 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14150 x = finish;
14151 finish = start;
14152 start = x;
14153 }
14154
14155 for (x = start; x <= finish; x++) {
14156 #ifdef HAVE_PRI
14157 tmp = mkintf(x, conf, pri, reload);
14158 #else
14159 tmp = mkintf(x, conf, NULL, reload);
14160 #endif
14161
14162 if (tmp) {
14163 #ifdef HAVE_PRI
14164 if (pri)
14165 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14166 else
14167 #endif
14168 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14169 } else {
14170 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14171 (reload == 1) ? "reconfigure" : "register", value);
14172 return -1;
14173 }
14174 }
14175 }
14176
14177 return 0;
14178 }
14179
14180
14181
14182 #define MAX_CHANLIST_LEN 80
14183
14184 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
14185 {
14186 char *parse = ast_strdupa(data);
14187 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14188 unsigned int param_count;
14189 unsigned int x;
14190
14191 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14192 return;
14193
14194 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14195
14196
14197
14198 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14199
14200 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14201 confp->chan.echocancel.head.tap_length = x;
14202 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14203 confp->chan.echocancel.head.tap_length = 128;
14204
14205
14206
14207 for (x = 1; x < param_count; x++) {
14208 struct {
14209 char *name;
14210 char *value;
14211 } param;
14212
14213 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
14214 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14215 continue;
14216 }
14217
14218 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14219 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14220 continue;
14221 }
14222
14223 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14224
14225 if (param.value) {
14226 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14227 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14228 continue;
14229 }
14230 }
14231 confp->chan.echocancel.head.param_count++;
14232 }
14233 }
14234
14235
14236 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
14237
14238 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
14239
14240 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
14241 {
14242 struct dahdi_pvt *tmp;
14243 int y;
14244 int found_pseudo = 0;
14245 char dahdichan[MAX_CHANLIST_LEN] = {};
14246
14247 for (; v; v = v->next) {
14248 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14249 continue;
14250
14251
14252 if (!strcasecmp(v->name, "parkinglot")) {
14253 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
14254 }
14255
14256
14257 if (!strcasecmp(v->name, "channel")
14258 #ifdef HAVE_PRI
14259 || !strcasecmp(v->name, "crv")
14260 #endif
14261 ) {
14262 int iscrv;
14263 if (options & PROC_DAHDI_OPT_NOCHAN) {
14264 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
14265 continue;
14266 }
14267 iscrv = !strcasecmp(v->name, "crv");
14268 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14269 return -1;
14270 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
14271 } else if (!strcasecmp(v->name, "buffers")) {
14272 int res;
14273 char policy[21] = "";
14274
14275 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
14276 if (res != 2) {
14277 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14278 confp->chan.buf_no = numbufs;
14279 continue;
14280 }
14281 if (confp->chan.buf_no < 0)
14282 confp->chan.buf_no = numbufs;
14283 if (!strcasecmp(policy, "full")) {
14284 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14285 } else if (!strcasecmp(policy, "immediate")) {
14286 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14287 } else {
14288 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14289 }
14290 } else if (!strcasecmp(v->name, "dahdichan")) {
14291 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14292 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14293 usedistinctiveringdetection = ast_true(v->value);
14294 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14295 distinctiveringaftercid = ast_true(v->value);
14296 } else if (!strcasecmp(v->name, "dring1context")) {
14297 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14298 } else if (!strcasecmp(v->name, "dring2context")) {
14299 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14300 } else if (!strcasecmp(v->name, "dring3context")) {
14301 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14302 } else if (!strcasecmp(v->name, "dring1range")) {
14303 confp->chan.drings.ringnum[0].range = atoi(v->value);
14304 } else if (!strcasecmp(v->name, "dring2range")) {
14305 confp->chan.drings.ringnum[1].range = atoi(v->value);
14306 } else if (!strcasecmp(v->name, "dring3range")) {
14307 confp->chan.drings.ringnum[2].range = atoi(v->value);
14308 } else if (!strcasecmp(v->name, "dring1")) {
14309 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
14310 } else if (!strcasecmp(v->name, "dring2")) {
14311 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
14312 } else if (!strcasecmp(v->name, "dring3")) {
14313 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
14314 } else if (!strcasecmp(v->name, "usecallerid")) {
14315 confp->chan.use_callerid = ast_true(v->value);
14316 } else if (!strcasecmp(v->name, "cidsignalling")) {
14317 if (!strcasecmp(v->value, "bell"))
14318 confp->chan.cid_signalling = CID_SIG_BELL;
14319 else if (!strcasecmp(v->value, "v23"))
14320 confp->chan.cid_signalling = CID_SIG_V23;
14321 else if (!strcasecmp(v->value, "dtmf"))
14322 confp->chan.cid_signalling = CID_SIG_DTMF;
14323 else if (!strcasecmp(v->value, "smdi"))
14324 confp->chan.cid_signalling = CID_SIG_SMDI;
14325 else if (!strcasecmp(v->value, "v23_jp"))
14326 confp->chan.cid_signalling = CID_SIG_V23_JP;
14327 else if (ast_true(v->value))
14328 confp->chan.cid_signalling = CID_SIG_BELL;
14329 } else if (!strcasecmp(v->name, "cidstart")) {
14330 if (!strcasecmp(v->value, "ring"))
14331 confp->chan.cid_start = CID_START_RING;
14332 else if (!strcasecmp(v->value, "polarity_in"))
14333 confp->chan.cid_start = CID_START_POLARITY_IN;
14334 else if (!strcasecmp(v->value, "polarity"))
14335 confp->chan.cid_start = CID_START_POLARITY;
14336 else if (ast_true(v->value))
14337 confp->chan.cid_start = CID_START_RING;
14338 } else if (!strcasecmp(v->name, "threewaycalling")) {
14339 confp->chan.threewaycalling = ast_true(v->value);
14340 } else if (!strcasecmp(v->name, "cancallforward")) {
14341 confp->chan.cancallforward = ast_true(v->value);
14342 } else if (!strcasecmp(v->name, "relaxdtmf")) {
14343 if (ast_true(v->value))
14344 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14345 else
14346 confp->chan.dtmfrelax = 0;
14347 } else if (!strcasecmp(v->name, "mailbox")) {
14348 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14349 } else if (!strcasecmp(v->name, "hasvoicemail")) {
14350 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14351 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14352 }
14353 } else if (!strcasecmp(v->name, "adsi")) {
14354 confp->chan.adsi = ast_true(v->value);
14355 } else if (!strcasecmp(v->name, "usesmdi")) {
14356 confp->chan.use_smdi = ast_true(v->value);
14357 } else if (!strcasecmp(v->name, "smdiport")) {
14358 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14359 } else if (!strcasecmp(v->name, "transfer")) {
14360 confp->chan.transfer = ast_true(v->value);
14361 } else if (!strcasecmp(v->name, "canpark")) {
14362 confp->chan.canpark = ast_true(v->value);
14363 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14364 confp->chan.echocanbridged = ast_true(v->value);
14365 } else if (!strcasecmp(v->name, "busydetect")) {
14366 confp->chan.busydetect = ast_true(v->value);
14367 } else if (!strcasecmp(v->name, "busycount")) {
14368 confp->chan.busycount = atoi(v->value);
14369 } else if (!strcasecmp(v->name, "busypattern")) {
14370 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
14371 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14372 }
14373 } else if (!strcasecmp(v->name, "callprogress")) {
14374 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14375 if (ast_true(v->value))
14376 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14377 } else if (!strcasecmp(v->name, "faxdetect")) {
14378 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14379 if (!strcasecmp(v->value, "incoming")) {
14380 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14381 } else if (!strcasecmp(v->value, "outgoing")) {
14382 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14383 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14384 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14385 } else if (!strcasecmp(v->name, "echocancel")) {
14386 process_echocancel(confp, v->value, v->lineno);
14387 } else if (!strcasecmp(v->name, "echotraining")) {
14388 if (sscanf(v->value, "%30d", &y) == 1) {
14389 if ((y < 10) || (y > 4000)) {
14390 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
14391 } else {
14392 confp->chan.echotraining = y;
14393 }
14394 } else if (ast_true(v->value)) {
14395 confp->chan.echotraining = 400;
14396 } else
14397 confp->chan.echotraining = 0;
14398 } else if (!strcasecmp(v->name, "hidecallerid")) {
14399 confp->chan.hidecallerid = ast_true(v->value);
14400 } else if (!strcasecmp(v->name, "hidecalleridname")) {
14401 confp->chan.hidecalleridname = ast_true(v->value);
14402 } else if (!strcasecmp(v->name, "pulsedial")) {
14403 confp->chan.pulse = ast_true(v->value);
14404 } else if (!strcasecmp(v->name, "callreturn")) {
14405 confp->chan.callreturn = ast_true(v->value);
14406 } else if (!strcasecmp(v->name, "callwaiting")) {
14407 confp->chan.callwaiting = ast_true(v->value);
14408 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14409 confp->chan.callwaitingcallerid = ast_true(v->value);
14410 } else if (!strcasecmp(v->name, "context")) {
14411 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14412 } else if (!strcasecmp(v->name, "language")) {
14413 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14414 } else if (!strcasecmp(v->name, "progzone")) {
14415 ast_copy_string(progzone, v->value, sizeof(progzone));
14416 } else if (!strcasecmp(v->name, "mohinterpret")
14417 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14418 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14419 } else if (!strcasecmp(v->name, "mohsuggest")) {
14420 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14421 } else if (!strcasecmp(v->name, "parkinglot")) {
14422 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
14423 } else if (!strcasecmp(v->name, "stripmsd")) {
14424 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14425 confp->chan.stripmsd = atoi(v->value);
14426 } else if (!strcasecmp(v->name, "jitterbuffers")) {
14427 numbufs = atoi(v->value);
14428 } else if (!strcasecmp(v->name, "group")) {
14429 confp->chan.group = ast_get_group(v->value);
14430 } else if (!strcasecmp(v->name, "callgroup")) {
14431 if (!strcasecmp(v->value, "none"))
14432 confp->chan.callgroup = 0;
14433 else
14434 confp->chan.callgroup = ast_get_group(v->value);
14435 } else if (!strcasecmp(v->name, "pickupgroup")) {
14436 if (!strcasecmp(v->value, "none"))
14437 confp->chan.pickupgroup = 0;
14438 else
14439 confp->chan.pickupgroup = ast_get_group(v->value);
14440 } else if (!strcasecmp(v->name, "setvar")) {
14441 char *varname = ast_strdupa(v->value), *varval = NULL;
14442 struct ast_variable *tmpvar;
14443 if (varname && (varval = strchr(varname, '='))) {
14444 *varval++ = '\0';
14445 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14446 tmpvar->next = confp->chan.vars;
14447 confp->chan.vars = tmpvar;
14448 }
14449 }
14450 } else if (!strcasecmp(v->name, "immediate")) {
14451 confp->chan.immediate = ast_true(v->value);
14452 } else if (!strcasecmp(v->name, "transfertobusy")) {
14453 confp->chan.transfertobusy = ast_true(v->value);
14454 } else if (!strcasecmp(v->name, "mwimonitor")) {
14455 confp->chan.mwimonitor_neon = 0;
14456 confp->chan.mwimonitor_fsk = 0;
14457 confp->chan.mwimonitor_rpas = 0;
14458 if (strcasestr(v->value, "fsk")) {
14459 confp->chan.mwimonitor_fsk = 1;
14460 }
14461 if (strcasestr(v->value, "rpas")) {
14462 confp->chan.mwimonitor_rpas = 1;
14463 }
14464 if (strcasestr(v->value, "neon")) {
14465 confp->chan.mwimonitor_neon = 1;
14466 }
14467
14468 if (ast_true(v->value)) {
14469 confp->chan.mwimonitor_fsk = 1;
14470 }
14471 } else if (!strcasecmp(v->name, "cid_rxgain")) {
14472 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
14473 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14474 }
14475 } else if (!strcasecmp(v->name, "rxgain")) {
14476 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
14477 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14478 }
14479 } else if (!strcasecmp(v->name, "txgain")) {
14480 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
14481 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14482 }
14483 } else if (!strcasecmp(v->name, "tonezone")) {
14484 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
14485 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14486 }
14487 } else if (!strcasecmp(v->name, "callerid")) {
14488 if (!strcasecmp(v->value, "asreceived")) {
14489 confp->chan.cid_num[0] = '\0';
14490 confp->chan.cid_name[0] = '\0';
14491 } else {
14492 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14493 }
14494 } else if (!strcasecmp(v->name, "fullname")) {
14495 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14496 } else if (!strcasecmp(v->name, "cid_number")) {
14497 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14498 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14499 confp->chan.dahditrcallerid = ast_true(v->value);
14500 } else if (!strcasecmp(v->name, "restrictcid")) {
14501 confp->chan.restrictcid = ast_true(v->value);
14502 } else if (!strcasecmp(v->name, "usecallingpres")) {
14503 confp->chan.use_callingpres = ast_true(v->value);
14504 } else if (!strcasecmp(v->name, "accountcode")) {
14505 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14506 } else if (!strcasecmp(v->name, "amaflags")) {
14507 y = ast_cdr_amaflags2int(v->value);
14508 if (y < 0)
14509 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14510 else
14511 confp->chan.amaflags = y;
14512 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14513 confp->chan.polarityonanswerdelay = atoi(v->value);
14514 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14515 confp->chan.answeronpolarityswitch = ast_true(v->value);
14516 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14517 confp->chan.hanguponpolarityswitch = ast_true(v->value);
14518 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14519 confp->chan.sendcalleridafter = atoi(v->value);
14520 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14521 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14522 } else if (!strcasecmp(v->name, "mwisendtype")) {
14523 if (!strcasecmp(v->value, "rpas")) {
14524 mwisend_rpas = 1;
14525 } else {
14526 mwisend_rpas = 0;
14527 }
14528 } else if (reload != 1) {
14529 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14530 int orig_radio = confp->chan.radio;
14531 int orig_outsigmod = confp->chan.outsigmod;
14532 int orig_auto = confp->is_sig_auto;
14533
14534 confp->chan.radio = 0;
14535 confp->chan.outsigmod = -1;
14536 confp->is_sig_auto = 0;
14537 if (!strcasecmp(v->value, "em")) {
14538 confp->chan.sig = SIG_EM;
14539 } else if (!strcasecmp(v->value, "em_e1")) {
14540 confp->chan.sig = SIG_EM_E1;
14541 } else if (!strcasecmp(v->value, "em_w")) {
14542 confp->chan.sig = SIG_EMWINK;
14543 } else if (!strcasecmp(v->value, "fxs_ls")) {
14544 confp->chan.sig = SIG_FXSLS;
14545 } else if (!strcasecmp(v->value, "fxs_gs")) {
14546 confp->chan.sig = SIG_FXSGS;
14547 } else if (!strcasecmp(v->value, "fxs_ks")) {
14548 confp->chan.sig = SIG_FXSKS;
14549 } else if (!strcasecmp(v->value, "fxo_ls")) {
14550 confp->chan.sig = SIG_FXOLS;
14551 } else if (!strcasecmp(v->value, "fxo_gs")) {
14552 confp->chan.sig = SIG_FXOGS;
14553 } else if (!strcasecmp(v->value, "fxo_ks")) {
14554 confp->chan.sig = SIG_FXOKS;
14555 } else if (!strcasecmp(v->value, "fxs_rx")) {
14556 confp->chan.sig = SIG_FXSKS;
14557 confp->chan.radio = 1;
14558 } else if (!strcasecmp(v->value, "fxo_rx")) {
14559 confp->chan.sig = SIG_FXOLS;
14560 confp->chan.radio = 1;
14561 } else if (!strcasecmp(v->value, "fxs_tx")) {
14562 confp->chan.sig = SIG_FXSLS;
14563 confp->chan.radio = 1;
14564 } else if (!strcasecmp(v->value, "fxo_tx")) {
14565 confp->chan.sig = SIG_FXOGS;
14566 confp->chan.radio = 1;
14567 } else if (!strcasecmp(v->value, "em_rx")) {
14568 confp->chan.sig = SIG_EM;
14569 confp->chan.radio = 1;
14570 } else if (!strcasecmp(v->value, "em_tx")) {
14571 confp->chan.sig = SIG_EM;
14572 confp->chan.radio = 1;
14573 } else if (!strcasecmp(v->value, "em_rxtx")) {
14574 confp->chan.sig = SIG_EM;
14575 confp->chan.radio = 2;
14576 } else if (!strcasecmp(v->value, "em_txrx")) {
14577 confp->chan.sig = SIG_EM;
14578 confp->chan.radio = 2;
14579 } else if (!strcasecmp(v->value, "sf")) {
14580 confp->chan.sig = SIG_SF;
14581 } else if (!strcasecmp(v->value, "sf_w")) {
14582 confp->chan.sig = SIG_SFWINK;
14583 } else if (!strcasecmp(v->value, "sf_featd")) {
14584 confp->chan.sig = SIG_FEATD;
14585 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14586 confp->chan.sig = SIG_FEATDMF;
14587 } else if (!strcasecmp(v->value, "sf_featb")) {
14588 confp->chan.sig = SIG_SF_FEATB;
14589 } else if (!strcasecmp(v->value, "sf")) {
14590 confp->chan.sig = SIG_SF;
14591 } else if (!strcasecmp(v->value, "sf_rx")) {
14592 confp->chan.sig = SIG_SF;
14593 confp->chan.radio = 1;
14594 } else if (!strcasecmp(v->value, "sf_tx")) {
14595 confp->chan.sig = SIG_SF;
14596 confp->chan.radio = 1;
14597 } else if (!strcasecmp(v->value, "sf_rxtx")) {
14598 confp->chan.sig = SIG_SF;
14599 confp->chan.radio = 2;
14600 } else if (!strcasecmp(v->value, "sf_txrx")) {
14601 confp->chan.sig = SIG_SF;
14602 confp->chan.radio = 2;
14603 } else if (!strcasecmp(v->value, "featd")) {
14604 confp->chan.sig = SIG_FEATD;
14605 } else if (!strcasecmp(v->value, "featdmf")) {
14606 confp->chan.sig = SIG_FEATDMF;
14607 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14608 confp->chan.sig = SIG_FEATDMF_TA;
14609 } else if (!strcasecmp(v->value, "e911")) {
14610 confp->chan.sig = SIG_E911;
14611 } else if (!strcasecmp(v->value, "fgccama")) {
14612 confp->chan.sig = SIG_FGC_CAMA;
14613 } else if (!strcasecmp(v->value, "fgccamamf")) {
14614 confp->chan.sig = SIG_FGC_CAMAMF;
14615 } else if (!strcasecmp(v->value, "featb")) {
14616 confp->chan.sig = SIG_FEATB;
14617 #ifdef HAVE_PRI
14618 } else if (!strcasecmp(v->value, "pri_net")) {
14619 confp->chan.sig = SIG_PRI;
14620 confp->pri.nodetype = PRI_NETWORK;
14621 } else if (!strcasecmp(v->value, "pri_cpe")) {
14622 confp->chan.sig = SIG_PRI;
14623 confp->pri.nodetype = PRI_CPE;
14624 } else if (!strcasecmp(v->value, "bri_cpe")) {
14625 confp->chan.sig = SIG_BRI;
14626 confp->pri.nodetype = PRI_CPE;
14627 } else if (!strcasecmp(v->value, "bri_net")) {
14628 confp->chan.sig = SIG_BRI;
14629 confp->pri.nodetype = PRI_NETWORK;
14630 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14631 confp->chan.sig = SIG_BRI_PTMP;
14632 confp->pri.nodetype = PRI_CPE;
14633 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14634 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
14635 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14636 confp->chan.sig = SIG_GR303FXOKS;
14637 confp->pri.nodetype = PRI_NETWORK;
14638 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14639 confp->chan.sig = SIG_GR303FXSKS;
14640 confp->pri.nodetype = PRI_CPE;
14641 #endif
14642 #ifdef HAVE_SS7
14643 } else if (!strcasecmp(v->value, "ss7")) {
14644 confp->chan.sig = SIG_SS7;
14645 #endif
14646 } else if (!strcasecmp(v->value, "auto")) {
14647 confp->is_sig_auto = 1;
14648 } else {
14649 confp->chan.outsigmod = orig_outsigmod;
14650 confp->chan.radio = orig_radio;
14651 confp->is_sig_auto = orig_auto;
14652 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14653 }
14654 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14655 if (!strcasecmp(v->value, "em")) {
14656 confp->chan.outsigmod = SIG_EM;
14657 } else if (!strcasecmp(v->value, "em_e1")) {
14658 confp->chan.outsigmod = SIG_EM_E1;
14659 } else if (!strcasecmp(v->value, "em_w")) {
14660 confp->chan.outsigmod = SIG_EMWINK;
14661 } else if (!strcasecmp(v->value, "sf")) {
14662 confp->chan.outsigmod = SIG_SF;
14663 } else if (!strcasecmp(v->value, "sf_w")) {
14664 confp->chan.outsigmod = SIG_SFWINK;
14665 } else if (!strcasecmp(v->value, "sf_featd")) {
14666 confp->chan.outsigmod = SIG_FEATD;
14667 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14668 confp->chan.outsigmod = SIG_FEATDMF;
14669 } else if (!strcasecmp(v->value, "sf_featb")) {
14670 confp->chan.outsigmod = SIG_SF_FEATB;
14671 } else if (!strcasecmp(v->value, "sf")) {
14672 confp->chan.outsigmod = SIG_SF;
14673 } else if (!strcasecmp(v->value, "featd")) {
14674 confp->chan.outsigmod = SIG_FEATD;
14675 } else if (!strcasecmp(v->value, "featdmf")) {
14676 confp->chan.outsigmod = SIG_FEATDMF;
14677 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14678 confp->chan.outsigmod = SIG_FEATDMF_TA;
14679 } else if (!strcasecmp(v->value, "e911")) {
14680 confp->chan.outsigmod = SIG_E911;
14681 } else if (!strcasecmp(v->value, "fgccama")) {
14682 confp->chan.outsigmod = SIG_FGC_CAMA;
14683 } else if (!strcasecmp(v->value, "fgccamamf")) {
14684 confp->chan.outsigmod = SIG_FGC_CAMAMF;
14685 } else if (!strcasecmp(v->value, "featb")) {
14686 confp->chan.outsigmod = SIG_FEATB;
14687 } else {
14688 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14689 }
14690 #ifdef HAVE_PRI
14691 } else if (!strcasecmp(v->name, "pridialplan")) {
14692 if (!strcasecmp(v->value, "national")) {
14693 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14694 } else if (!strcasecmp(v->value, "unknown")) {
14695 confp->pri.dialplan = PRI_UNKNOWN + 1;
14696 } else if (!strcasecmp(v->value, "private")) {
14697 confp->pri.dialplan = PRI_PRIVATE + 1;
14698 } else if (!strcasecmp(v->value, "international")) {
14699 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14700 } else if (!strcasecmp(v->value, "local")) {
14701 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14702 } else if (!strcasecmp(v->value, "dynamic")) {
14703 confp->pri.dialplan = -1;
14704 } else if (!strcasecmp(v->value, "redundant")) {
14705 confp->pri.dialplan = -2;
14706 } else {
14707 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14708 }
14709 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14710 if (!strcasecmp(v->value, "national")) {
14711 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14712 } else if (!strcasecmp(v->value, "unknown")) {
14713 confp->pri.localdialplan = PRI_UNKNOWN + 1;
14714 } else if (!strcasecmp(v->value, "private")) {
14715 confp->pri.localdialplan = PRI_PRIVATE + 1;
14716 } else if (!strcasecmp(v->value, "international")) {
14717 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14718 } else if (!strcasecmp(v->value, "local")) {
14719 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14720 } else if (!strcasecmp(v->value, "dynamic")) {
14721 confp->pri.localdialplan = -1;
14722 } else if (!strcasecmp(v->value, "redundant")) {
14723 confp->pri.localdialplan = -2;
14724 } else {
14725 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14726 }
14727 } else if (!strcasecmp(v->name, "switchtype")) {
14728 if (!strcasecmp(v->value, "national"))
14729 confp->pri.switchtype = PRI_SWITCH_NI2;
14730 else if (!strcasecmp(v->value, "ni1"))
14731 confp->pri.switchtype = PRI_SWITCH_NI1;
14732 else if (!strcasecmp(v->value, "dms100"))
14733 confp->pri.switchtype = PRI_SWITCH_DMS100;
14734 else if (!strcasecmp(v->value, "4ess"))
14735 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14736 else if (!strcasecmp(v->value, "5ess"))
14737 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14738 else if (!strcasecmp(v->value, "euroisdn"))
14739 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14740 else if (!strcasecmp(v->value, "qsig"))
14741 confp->pri.switchtype = PRI_SWITCH_QSIG;
14742 else {
14743 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14744 return -1;
14745 }
14746 } else if (!strcasecmp(v->name, "nsf")) {
14747 if (!strcasecmp(v->value, "sdn"))
14748 confp->pri.nsf = PRI_NSF_SDN;
14749 else if (!strcasecmp(v->value, "megacom"))
14750 confp->pri.nsf = PRI_NSF_MEGACOM;
14751 else if (!strcasecmp(v->value, "tollfreemegacom"))
14752 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14753 else if (!strcasecmp(v->value, "accunet"))
14754 confp->pri.nsf = PRI_NSF_ACCUNET;
14755 else if (!strcasecmp(v->value, "none"))
14756 confp->pri.nsf = PRI_NSF_NONE;
14757 else {
14758 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14759 confp->pri.nsf = PRI_NSF_NONE;
14760 }
14761 } else if (!strcasecmp(v->name, "priindication")) {
14762 if (!strcasecmp(v->value, "outofband"))
14763 confp->chan.priindication_oob = 1;
14764 else if (!strcasecmp(v->value, "inband"))
14765 confp->chan.priindication_oob = 0;
14766 else
14767 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14768 v->value, v->lineno);
14769 } else if (!strcasecmp(v->name, "priexclusive")) {
14770 confp->chan.priexclusive = ast_true(v->value);
14771 } else if (!strcasecmp(v->name, "internationalprefix")) {
14772 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14773 } else if (!strcasecmp(v->name, "nationalprefix")) {
14774 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14775 } else if (!strcasecmp(v->name, "localprefix")) {
14776 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14777 } else if (!strcasecmp(v->name, "privateprefix")) {
14778 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14779 } else if (!strcasecmp(v->name, "unknownprefix")) {
14780 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14781 } else if (!strcasecmp(v->name, "resetinterval")) {
14782 if (!strcasecmp(v->value, "never"))
14783 confp->pri.resetinterval = -1;
14784 else if (atoi(v->value) >= 60)
14785 confp->pri.resetinterval = atoi(v->value);
14786 else
14787 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14788 v->value, v->lineno);
14789 } else if (!strcasecmp(v->name, "minunused")) {
14790 confp->pri.minunused = atoi(v->value);
14791 } else if (!strcasecmp(v->name, "minidle")) {
14792 confp->pri.minidle = atoi(v->value);
14793 } else if (!strcasecmp(v->name, "idleext")) {
14794 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14795 } else if (!strcasecmp(v->name, "idledial")) {
14796 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14797 } else if (!strcasecmp(v->name, "overlapdial")) {
14798 if (ast_true(v->value)) {
14799 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14800 } else if (!strcasecmp(v->value, "incoming")) {
14801 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14802 } else if (!strcasecmp(v->value, "outgoing")) {
14803 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14804 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14805 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14806 } else {
14807 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14808 }
14809 #ifdef HAVE_PRI_INBANDDISCONNECT
14810 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14811 confp->pri.inbanddisconnect = ast_true(v->value);
14812 #endif
14813 } else if (!strcasecmp(v->name, "pritimer")) {
14814 #ifdef PRI_GETSET_TIMERS
14815 char tmp[20];
14816 char *timerc;
14817 char *c;
14818 int timer;
14819 int timeridx;
14820
14821 ast_copy_string(tmp, v->value, sizeof(tmp));
14822 c = tmp;
14823 timerc = strsep(&c, ",");
14824 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
14825 timeridx = pri_timer2idx(timerc);
14826 timer = atoi(c);
14827 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
14828 ast_log(LOG_WARNING,
14829 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
14830 v->lineno);
14831 } else if (!timer) {
14832 ast_log(LOG_WARNING,
14833 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
14834 c, timerc, v->lineno);
14835 } else {
14836 pritimers[timeridx] = timer;
14837 }
14838 } else {
14839 ast_log(LOG_WARNING,
14840 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
14841 v->value, v->lineno);
14842 }
14843
14844 } else if (!strcasecmp(v->name, "facilityenable")) {
14845 confp->pri.facilityenable = ast_true(v->value);
14846 #endif
14847 #endif
14848 #ifdef HAVE_SS7
14849 } else if (!strcasecmp(v->name, "ss7type")) {
14850 if (!strcasecmp(v->value, "itu")) {
14851 cur_ss7type = SS7_ITU;
14852 } else if (!strcasecmp(v->value, "ansi")) {
14853 cur_ss7type = SS7_ANSI;
14854 } else
14855 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14856 } else if (!strcasecmp(v->name, "linkset")) {
14857 cur_linkset = atoi(v->value);
14858 } else if (!strcasecmp(v->name, "pointcode")) {
14859 cur_pointcode = parse_pointcode(v->value);
14860 } else if (!strcasecmp(v->name, "adjpointcode")) {
14861 cur_adjpointcode = parse_pointcode(v->value);
14862 } else if (!strcasecmp(v->name, "defaultdpc")) {
14863 cur_defaultdpc = parse_pointcode(v->value);
14864 } else if (!strcasecmp(v->name, "cicbeginswith")) {
14865 cur_cicbeginswith = atoi(v->value);
14866 } else if (!strcasecmp(v->name, "networkindicator")) {
14867 if (!strcasecmp(v->value, "national"))
14868 cur_networkindicator = SS7_NI_NAT;
14869 else if (!strcasecmp(v->value, "national_spare"))
14870 cur_networkindicator = SS7_NI_NAT_SPARE;
14871 else if (!strcasecmp(v->value, "international"))
14872 cur_networkindicator = SS7_NI_INT;
14873 else if (!strcasecmp(v->value, "international_spare"))
14874 cur_networkindicator = SS7_NI_INT_SPARE;
14875 else
14876 cur_networkindicator = -1;
14877 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14878 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14879 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14880 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14881 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14882 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14883 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14884 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14885 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14886 if (!strcasecmp(v->value, "national")) {
14887 confp->ss7.called_nai = SS7_NAI_NATIONAL;
14888 } else if (!strcasecmp(v->value, "international")) {
14889 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14890 } else if (!strcasecmp(v->value, "subscriber")) {
14891 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14892 } else if (!strcasecmp(v->value, "dynamic")) {
14893 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14894 } else {
14895 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14896 }
14897 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14898 if (!strcasecmp(v->value, "national")) {
14899 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14900 } else if (!strcasecmp(v->value, "international")) {
14901 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14902 } else if (!strcasecmp(v->value, "subscriber")) {
14903 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14904 } else if (!strcasecmp(v->value, "dynamic")) {
14905 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14906 } else {
14907 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14908 }
14909 } else if (!strcasecmp(v->name, "sigchan")) {
14910 int sigchan, res;
14911 sigchan = atoi(v->value);
14912 res = linkset_addsigchan(sigchan);
14913 if (res < 0)
14914 return -1;
14915
14916 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14917 struct dahdi_ss7 *link;
14918 link = ss7_resolve_linkset(cur_linkset);
14919 if (!link) {
14920 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
14921 return -1;
14922 }
14923 if (ast_true(v->value))
14924 link->flags |= LINKSET_FLAG_EXPLICITACM;
14925
14926 #endif
14927 } else if (!strcasecmp(v->name, "cadence")) {
14928
14929 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14930 int i;
14931 struct dahdi_ring_cadence new_cadence;
14932 int cid_location = -1;
14933 int firstcadencepos = 0;
14934 char original_args[80];
14935 int cadence_is_ok = 1;
14936
14937 ast_copy_string(original_args, v->value, sizeof(original_args));
14938
14939 element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
14940
14941
14942 if (element_count % 2 == 1) {
14943 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
14944 cadence_is_ok = 0;
14945 }
14946
14947
14948 for (i = 0; i < element_count; i++) {
14949 if (c[i] == 0) {
14950 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
14951 cadence_is_ok = 0;
14952 break;
14953 } else if (c[i] < 0) {
14954 if (i % 2 == 1) {
14955
14956 if (cid_location == -1) {
14957 cid_location = i;
14958 c[i] *= -1;
14959 } else {
14960 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
14961 cadence_is_ok = 0;
14962 break;
14963 }
14964 } else {
14965 if (firstcadencepos == 0) {
14966 firstcadencepos = i;
14967
14968 } else {
14969 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
14970 cadence_is_ok = 0;
14971 break;
14972 }
14973 }
14974 }
14975 }
14976
14977
14978 for (i = 0; i < 16; i++) {
14979 new_cadence.ringcadence[i] = c[i];
14980 }
14981
14982 if (cadence_is_ok) {
14983
14984 if (element_count < 2) {
14985 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
14986 } else {
14987 if (cid_location == -1) {
14988
14989 cid_location = 1;
14990 } else {
14991
14992 cid_location = (cid_location + 1) / 2;
14993 }
14994
14995 if (!user_has_defined_cadences++)
14996
14997 num_cadence = 0;
14998 if ((num_cadence+1) >= NUM_CADENCE_MAX)
14999 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
15000 else {
15001 cadences[num_cadence] = new_cadence;
15002 cidrings[num_cadence++] = cid_location;
15003 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
15004 }
15005 }
15006 }
15007 } else if (!strcasecmp(v->name, "ringtimeout")) {
15008 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
15009 } else if (!strcasecmp(v->name, "prewink")) {
15010 confp->timing.prewinktime = atoi(v->value);
15011 } else if (!strcasecmp(v->name, "preflash")) {
15012 confp->timing.preflashtime = atoi(v->value);
15013 } else if (!strcasecmp(v->name, "wink")) {
15014 confp->timing.winktime = atoi(v->value);
15015 } else if (!strcasecmp(v->name, "flash")) {
15016 confp->timing.flashtime = atoi(v->value);
15017 } else if (!strcasecmp(v->name, "start")) {
15018 confp->timing.starttime = atoi(v->value);
15019 } else if (!strcasecmp(v->name, "rxwink")) {
15020 confp->timing.rxwinktime = atoi(v->value);
15021 } else if (!strcasecmp(v->name, "rxflash")) {
15022 confp->timing.rxflashtime = atoi(v->value);
15023 } else if (!strcasecmp(v->name, "debounce")) {
15024 confp->timing.debouncetime = atoi(v->value);
15025 } else if (!strcasecmp(v->name, "toneduration")) {
15026 int toneduration;
15027 int ctlfd;
15028 int res;
15029 struct dahdi_dialparams dps;
15030
15031 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
15032 if (ctlfd == -1) {
15033 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
15034 return -1;
15035 }
15036
15037 toneduration = atoi(v->value);
15038 if (toneduration > -1) {
15039 memset(&dps, 0, sizeof(dps));
15040
15041 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
15042 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
15043 if (res < 0) {
15044 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
15045 return -1;
15046 }
15047 }
15048 close(ctlfd);
15049 } else if (!strcasecmp(v->name, "defaultcic")) {
15050 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
15051 } else if (!strcasecmp(v->name, "defaultozz")) {
15052 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
15053 } else if (!strcasecmp(v->name, "mwilevel")) {
15054 mwilevel = atoi(v->value);
15055 }
15056 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
15057 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
15058 }
15059 if (dahdichan[0]) {
15060
15061
15062 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
15063 return -1;
15064 }
15065 }
15066
15067
15068 if (!found_pseudo && reload != 1) {
15069
15070
15071
15072
15073 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
15074
15075 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
15076
15077 if (tmp) {
15078 ast_verb(3, "Automatically generated pseudo channel\n");
15079 } else {
15080 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
15081 }
15082 }
15083 return 0;
15084 }
15085
15086 static int setup_dahdi(int reload)
15087 {
15088 struct ast_config *cfg, *ucfg;
15089 struct ast_variable *v;
15090 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
15091 struct dahdi_chan_conf conf;
15092 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
15093 const char *cat;
15094 int res;
15095
15096 #ifdef HAVE_PRI
15097 char *c;
15098 int spanno;
15099 int i;
15100 int logicalspan;
15101 int trunkgroup;
15102 int dchannels[NUM_DCHANS];
15103 #endif
15104
15105 cfg = ast_config_load(config, config_flags);
15106
15107
15108 if (!cfg) {
15109 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
15110 return 0;
15111 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
15112 ucfg = ast_config_load("users.conf", config_flags);
15113 if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
15114 return 0;
15115 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15116 cfg = ast_config_load(config, config_flags);
15117 } else {
15118 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15119 ucfg = ast_config_load("users.conf", config_flags);
15120 }
15121
15122
15123 ast_mutex_lock(&iflock);
15124 #ifdef HAVE_PRI
15125 if (reload != 1) {
15126
15127 v = ast_variable_browse(cfg, "trunkgroups");
15128 while (v) {
15129 if (!strcasecmp(v->name, "trunkgroup")) {
15130 trunkgroup = atoi(v->value);
15131 if (trunkgroup > 0) {
15132 if ((c = strchr(v->value, ','))) {
15133 i = 0;
15134 memset(dchannels, 0, sizeof(dchannels));
15135 while (c && (i < NUM_DCHANS)) {
15136 dchannels[i] = atoi(c + 1);
15137 if (dchannels[i] < 0) {
15138 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);
15139 } else
15140 i++;
15141 c = strchr(c + 1, ',');
15142 }
15143 if (i) {
15144 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
15145 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);
15146 } else
15147 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");
15148 } else
15149 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15150 } else
15151 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15152 } else
15153 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
15154 } else if (!strcasecmp(v->name, "spanmap")) {
15155 spanno = atoi(v->value);
15156 if (spanno > 0) {
15157 if ((c = strchr(v->value, ','))) {
15158 trunkgroup = atoi(c + 1);
15159 if (trunkgroup > 0) {
15160 if ((c = strchr(c + 1, ',')))
15161 logicalspan = atoi(c + 1);
15162 else
15163 logicalspan = 0;
15164 if (logicalspan >= 0) {
15165 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15166 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15167 } else
15168 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15169 } else
15170 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);
15171 } else
15172 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15173 } else
15174 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15175 } else
15176 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15177 } else {
15178 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15179 }
15180 v = v->next;
15181 }
15182 }
15183 #endif
15184
15185
15186 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
15187
15188 mwimonitornotify[0] = '\0';
15189
15190 v = ast_variable_browse(cfg, "channels");
15191 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
15192 ast_mutex_unlock(&iflock);
15193 ast_config_destroy(cfg);
15194 if (ucfg) {
15195 ast_config_destroy(ucfg);
15196 }
15197 return res;
15198 }
15199
15200
15201 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15202
15203
15204
15205 if (!strcasecmp(cat, "general") ||
15206 !strcasecmp(cat, "trunkgroups") ||
15207 !strcasecmp(cat, "globals") ||
15208 !strcasecmp(cat, "channels")) {
15209 continue;
15210 }
15211
15212 memcpy(&conf, &base_conf, sizeof(conf));
15213
15214 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
15215 ast_mutex_unlock(&iflock);
15216 ast_config_destroy(cfg);
15217 if (ucfg) {
15218 ast_config_destroy(cfg);
15219 }
15220 return res;
15221 }
15222 }
15223
15224 ast_config_destroy(cfg);
15225
15226 if (ucfg) {
15227 const char *chans;
15228
15229 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
15230
15231 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15232 if (!strcasecmp(cat, "general")) {
15233 continue;
15234 }
15235
15236 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
15237
15238 if (ast_strlen_zero(chans)) {
15239 continue;
15240 }
15241
15242 memcpy(&conf, &base_conf, sizeof(conf));
15243
15244 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
15245 ast_config_destroy(ucfg);
15246 ast_mutex_unlock(&iflock);
15247 return res;
15248 }
15249 }
15250 ast_config_destroy(ucfg);
15251 }
15252 ast_mutex_unlock(&iflock);
15253
15254 #ifdef HAVE_PRI
15255 if (reload != 1) {
15256 int x;
15257 for (x = 0; x < NUM_SPANS; x++) {
15258 if (pris[x].pvts[0]) {
15259 if (start_pri(pris + x)) {
15260 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15261 return -1;
15262 } else
15263 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
15264 }
15265 }
15266 }
15267 #endif
15268 #ifdef HAVE_SS7
15269 if (reload != 1) {
15270 int x;
15271 for (x = 0; x < NUM_SPANS; x++) {
15272 if (linksets[x].ss7) {
15273 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
15274 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
15275 return -1;
15276 } else
15277 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
15278 }
15279 }
15280 }
15281 #endif
15282
15283 restart_monitor();
15284 return 0;
15285 }
15286
15287 static int load_module(void)
15288 {
15289 int res;
15290 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15291 int y, i;
15292 #endif
15293
15294 #ifdef HAVE_PRI
15295 memset(pris, 0, sizeof(pris));
15296 for (y = 0; y < NUM_SPANS; y++) {
15297 ast_mutex_init(&pris[y].lock);
15298 pris[y].offset = -1;
15299 pris[y].master = AST_PTHREADT_NULL;
15300 for (i = 0; i < NUM_DCHANS; i++)
15301 pris[y].fds[i] = -1;
15302 }
15303 pri_set_error(dahdi_pri_error);
15304 pri_set_message(dahdi_pri_message);
15305 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15306 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15307 #endif
15308 #ifdef HAVE_SS7
15309 memset(linksets, 0, sizeof(linksets));
15310 for (y = 0; y < NUM_SPANS; y++) {
15311 ast_mutex_init(&linksets[y].lock);
15312 linksets[y].master = AST_PTHREADT_NULL;
15313 for (i = 0; i < NUM_DCHANS; i++)
15314 linksets[y].fds[i] = -1;
15315 }
15316 ss7_set_error(dahdi_ss7_error);
15317 ss7_set_message(dahdi_ss7_message);
15318 #endif
15319 res = setup_dahdi(0);
15320
15321 if (res)
15322 return AST_MODULE_LOAD_DECLINE;
15323 if (ast_channel_register(&dahdi_tech)) {
15324 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15325 __unload_module();
15326 return AST_MODULE_LOAD_FAILURE;
15327 }
15328 #ifdef HAVE_PRI
15329 ast_string_field_init(&inuse, 16);
15330 ast_string_field_set(&inuse, name, "GR-303InUse");
15331 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15332 #endif
15333 #ifdef HAVE_SS7
15334 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15335 #endif
15336
15337 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15338
15339 memset(round_robin, 0, sizeof(round_robin));
15340 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15341 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15342 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15343 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15344 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15345 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15346 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15347
15348 ast_cond_init(&mwi_thread_complete, NULL);
15349 ast_cond_init(&ss_thread_complete, NULL);
15350
15351 return res;
15352 }
15353
15354 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15355 {
15356 #define END_SILENCE_LEN 400
15357 #define HEADER_MS 50
15358 #define TRAILER_MS 5
15359 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15360 #define ASCII_BYTES_PER_CHAR 80
15361
15362 unsigned char *buf,*mybuf;
15363 struct dahdi_pvt *p = c->tech_pvt;
15364 struct pollfd fds[1];
15365 int size,res,fd,len,x;
15366 int bytes=0;
15367
15368 float cr = 1.0;
15369 float ci = 0.0;
15370 float scont = 0.0;
15371 int idx;
15372
15373 idx = dahdi_get_index(c, p, 0);
15374 if (idx < 0) {
15375 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
15376 return -1;
15377 }
15378 if (!text[0]) return(0);
15379 if ((!p->tdd) && (!p->mate)) return(0);
15380 if (p->mate)
15381 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15382 else
15383 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15384 if (!buf)
15385 return -1;
15386 mybuf = buf;
15387 if (p->mate) {
15388 int codec = AST_LAW(p);
15389 for (x = 0; x < HEADER_MS; x++) {
15390 PUT_CLID_MARKMS;
15391 }
15392
15393 for (x = 0; text[x]; x++) {
15394 PUT_CLID(text[x]);
15395 }
15396 for (x = 0; x < TRAILER_MS; x++) {
15397 PUT_CLID_MARKMS;
15398 }
15399 len = bytes;
15400 buf = mybuf;
15401 } else {
15402 len = tdd_generate(p->tdd, buf, text);
15403 if (len < 1) {
15404 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15405 ast_free(mybuf);
15406 return -1;
15407 }
15408 }
15409 memset(buf + len, 0x7f, END_SILENCE_LEN);
15410 len += END_SILENCE_LEN;
15411 fd = p->subs[idx].dfd;
15412 while (len) {
15413 if (ast_check_hangup(c)) {
15414 ast_free(mybuf);
15415 return -1;
15416 }
15417 size = len;
15418 if (size > READ_SIZE)
15419 size = READ_SIZE;
15420 fds[0].fd = fd;
15421 fds[0].events = POLLOUT | POLLPRI;
15422 fds[0].revents = 0;
15423 res = poll(fds, 1, -1);
15424 if (!res) {
15425 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15426 continue;
15427 }
15428
15429 if (fds[0].revents & POLLPRI) {
15430 ast_free(mybuf);
15431 return -1;
15432 }
15433 if (!(fds[0].revents & POLLOUT)) {
15434 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15435 continue;
15436 }
15437 res = write(fd, buf, size);
15438 if (res != size) {
15439 if (res == -1) {
15440 ast_free(mybuf);
15441 return -1;
15442 }
15443 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15444 break;
15445 }
15446 len -= size;
15447 buf += size;
15448 }
15449 ast_free(mybuf);
15450 return(0);
15451 }
15452
15453
15454 static int reload(void)
15455 {
15456 int res = 0;
15457
15458 res = setup_dahdi(1);
15459 if (res) {
15460 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15461 return -1;
15462 }
15463 return 0;
15464 }
15465
15466
15467
15468
15469
15470 #ifdef HAVE_PRI
15471 #ifdef HAVE_SS7
15472 #define tdesc "DAHDI Telephony w/PRI & SS7"
15473 #else
15474 #define tdesc "DAHDI Telephony w/PRI"
15475 #endif
15476 #else
15477 #ifdef HAVE_SS7
15478 #define tdesc "DAHDI Telephony w/SS7"
15479 #else
15480 #define tdesc "DAHDI Telephony"
15481 #endif
15482 #endif
15483
15484 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15485 .load = load_module,
15486 .unload = unload_module,
15487 .reload = reload,
15488 );
15489
15490