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: 261452 $")
00051
00052 #if defined(__NetBSD__) || defined(__FreeBSD__)
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 .target_extra = -1,
00125 };
00126 static struct ast_jb_conf global_jbconf;
00127
00128
00129 #undef SUPPORT_USERUSER
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 #define DEFAULT_CIDRINGS 1
00151
00152 #define CHANNEL_PSEUDO -12
00153
00154 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00155
00156
00157
00158 #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))
00159
00160 static const char tdesc[] = "DAHDI Telephony Driver"
00161 #ifdef HAVE_PRI
00162 " w/PRI"
00163 #endif
00164 #ifdef HAVE_SS7
00165 " w/SS7"
00166 #endif
00167 ;
00168
00169 static const char config[] = "chan_dahdi.conf";
00170
00171 #define SIG_EM DAHDI_SIG_EM
00172 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00173 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00174 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00175 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00176 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00177 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00178 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00179 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00180 #define SIG_FXSLS DAHDI_SIG_FXSLS
00181 #define SIG_FXSGS DAHDI_SIG_FXSGS
00182 #define SIG_FXSKS DAHDI_SIG_FXSKS
00183 #define SIG_FXOLS DAHDI_SIG_FXOLS
00184 #define SIG_FXOGS DAHDI_SIG_FXOGS
00185 #define SIG_FXOKS DAHDI_SIG_FXOKS
00186 #define SIG_PRI DAHDI_SIG_CLEAR
00187 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00188 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00189 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00190 #define SIG_SF DAHDI_SIG_SF
00191 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00192 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00193 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00194 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00195 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00196 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00197 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00198
00199 #ifdef LOTS_OF_SPANS
00200 #define NUM_SPANS DAHDI_MAX_SPANS
00201 #else
00202 #define NUM_SPANS 32
00203 #endif
00204 #define NUM_DCHANS 4
00205 #define MAX_CHANNELS 672
00206
00207 #define CHAN_PSEUDO -2
00208
00209 #define DCHAN_PROVISIONED (1 << 0)
00210 #define DCHAN_NOTINALARM (1 << 1)
00211 #define DCHAN_UP (1 << 2)
00212
00213 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00214
00215
00216 #define DAHDI_OVERLAPDIAL_NONE 0
00217 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00218 #define DAHDI_OVERLAPDIAL_INCOMING 2
00219 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00220
00221
00222 #define CALLPROGRESS_PROGRESS 1
00223 #define CALLPROGRESS_FAX_OUTGOING 2
00224 #define CALLPROGRESS_FAX_INCOMING 4
00225 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00226
00227 static char defaultcic[64] = "";
00228 static char defaultozz[64] = "";
00229
00230 static char parkinglot[AST_MAX_EXTENSION] = "";
00231
00232
00233 static char mwimonitornotify[PATH_MAX] = "";
00234 static int mwisend_rpas = 0;
00235
00236 static char progzone[10] = "";
00237
00238 static int usedistinctiveringdetection = 0;
00239 static int distinctiveringaftercid = 0;
00240
00241 static int numbufs = 4;
00242
00243 static int mwilevel = 512;
00244
00245 #ifdef HAVE_PRI
00246 static struct ast_channel inuse;
00247 #ifdef PRI_GETSET_TIMERS
00248 static int pritimers[PRI_MAX_TIMERS];
00249 #endif
00250 static int pridebugfd = -1;
00251 static char pridebugfilename[1024] = "";
00252 #endif
00253
00254
00255 static int firstdigittimeout = 16000;
00256
00257
00258 static int gendigittimeout = 8000;
00259
00260
00261 static int matchdigittimeout = 3000;
00262
00263
00264 AST_MUTEX_DEFINE_STATIC(iflock);
00265
00266
00267 static int ifcount = 0;
00268
00269 #ifdef HAVE_PRI
00270 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00271 #endif
00272
00273
00274
00275 AST_MUTEX_DEFINE_STATIC(monlock);
00276
00277
00278
00279 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00280 static ast_cond_t mwi_thread_complete;
00281 static ast_cond_t ss_thread_complete;
00282 AST_MUTEX_DEFINE_STATIC(mwi_thread_lock);
00283 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00284 AST_MUTEX_DEFINE_STATIC(restart_lock);
00285 static int mwi_thread_count = 0;
00286 static int ss_thread_count = 0;
00287 static int num_restart_pending = 0;
00288
00289 static int restart_monitor(void);
00290
00291 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);
00292
00293 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00294
00295 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00296 {
00297
00298
00299
00300
00301 }
00302
00303
00304 static inline int dahdi_get_event(int fd)
00305 {
00306 int j;
00307 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00308 return -1;
00309 return j;
00310 }
00311
00312
00313 static inline int dahdi_wait_event(int fd)
00314 {
00315 int i, j = 0;
00316 i = DAHDI_IOMUX_SIGEVENT;
00317 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00318 return -1;
00319 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00320 return -1;
00321 return j;
00322 }
00323
00324
00325 #define READ_SIZE 160
00326
00327 #define MASK_AVAIL (1 << 0)
00328 #define MASK_INUSE (1 << 1)
00329
00330 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00331 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00332 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00333 #define MIN_MS_SINCE_FLASH ( (2000) )
00334 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00335
00336 struct dahdi_pvt;
00337
00338
00339
00340
00341
00342 static int ringt_base = DEFAULT_RINGT;
00343
00344 #ifdef HAVE_SS7
00345
00346 #define LINKSTATE_INALARM (1 << 0)
00347 #define LINKSTATE_STARTING (1 << 1)
00348 #define LINKSTATE_UP (1 << 2)
00349 #define LINKSTATE_DOWN (1 << 3)
00350
00351 #define SS7_NAI_DYNAMIC -1
00352
00353 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00354
00355 struct dahdi_ss7 {
00356 pthread_t master;
00357 ast_mutex_t lock;
00358 int fds[NUM_DCHANS];
00359 int numsigchans;
00360 int linkstate[NUM_DCHANS];
00361 int numchans;
00362 int type;
00363 enum {
00364 LINKSET_STATE_DOWN = 0,
00365 LINKSET_STATE_UP
00366 } state;
00367 char called_nai;
00368 char calling_nai;
00369 char internationalprefix[10];
00370 char nationalprefix[10];
00371 char subscriberprefix[20];
00372 char unknownprefix[20];
00373 struct ss7 *ss7;
00374 struct dahdi_pvt *pvts[MAX_CHANNELS];
00375 int flags;
00376 };
00377
00378 static struct dahdi_ss7 linksets[NUM_SPANS];
00379
00380 static int cur_ss7type = -1;
00381 static int cur_linkset = -1;
00382 static int cur_pointcode = -1;
00383 static int cur_cicbeginswith = -1;
00384 static int cur_adjpointcode = -1;
00385 static int cur_networkindicator = -1;
00386 static int cur_defaultdpc = -1;
00387 #endif
00388
00389 #ifdef HAVE_PRI
00390
00391 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00392 #define PRI_CHANNEL(p) ((p) & 0xff)
00393 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00394 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00395
00396 struct dahdi_pri {
00397 pthread_t master;
00398 ast_mutex_t lock;
00399 char idleext[AST_MAX_EXTENSION];
00400 char idlecontext[AST_MAX_CONTEXT];
00401 char idledial[AST_MAX_EXTENSION];
00402 int minunused;
00403 int minidle;
00404 int nodetype;
00405 int switchtype;
00406 int nsf;
00407 int dialplan;
00408 int localdialplan;
00409 char internationalprefix[10];
00410 char nationalprefix[10];
00411 char localprefix[20];
00412 char privateprefix[20];
00413 char unknownprefix[20];
00414 int dchannels[NUM_DCHANS];
00415 int trunkgroup;
00416 int mastertrunkgroup;
00417 int prilogicalspan;
00418 int numchans;
00419 int overlapdial;
00420 int facilityenable;
00421 struct pri *dchans[NUM_DCHANS];
00422 int dchanavail[NUM_DCHANS];
00423 struct pri *pri;
00424
00425 int debug;
00426 int fds[NUM_DCHANS];
00427
00428 int offset;
00429
00430 int span;
00431
00432 int resetting;
00433
00434 int resetpos;
00435 #ifdef HAVE_PRI_INBANDDISCONNECT
00436 unsigned int inbanddisconnect:1;
00437 #endif
00438 time_t lastreset;
00439 long resetinterval;
00440
00441 int sig;
00442 struct dahdi_pvt *pvts[MAX_CHANNELS];
00443 struct dahdi_pvt *crvs;
00444 struct dahdi_pvt *crvend;
00445 };
00446
00447
00448 static struct dahdi_pri pris[NUM_SPANS];
00449
00450 #if 0
00451 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00452 #else
00453 #define DEFAULT_PRI_DEBUG 0
00454 #endif
00455
00456 static inline void pri_rel(struct dahdi_pri *pri)
00457 {
00458 ast_mutex_unlock(&pri->lock);
00459 }
00460
00461 #else
00462
00463 struct dahdi_pri;
00464 #endif
00465
00466 #define SUB_REAL 0
00467 #define SUB_CALLWAIT 1
00468 #define SUB_THREEWAY 2
00469
00470
00471 #define POLARITY_IDLE 0
00472 #define POLARITY_REV 1
00473
00474
00475 struct distRingData {
00476 int ring[3];
00477 int range;
00478 };
00479 struct ringContextData {
00480 char contextData[AST_MAX_CONTEXT];
00481 };
00482 struct dahdi_distRings {
00483 struct distRingData ringnum[3];
00484 struct ringContextData ringContext[3];
00485 };
00486
00487 static char *subnames[] = {
00488 "Real",
00489 "Callwait",
00490 "Threeway"
00491 };
00492
00493 struct dahdi_subchannel {
00494 int dfd;
00495 struct ast_channel *owner;
00496 int chan;
00497 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00498 struct ast_frame f;
00499 unsigned int needringing:1;
00500 unsigned int needbusy:1;
00501 unsigned int needcongestion:1;
00502 unsigned int needcallerid:1;
00503 unsigned int needanswer:1;
00504 unsigned int needflash:1;
00505 unsigned int needhold:1;
00506 unsigned int needunhold:1;
00507 unsigned int linear:1;
00508 unsigned int inthreeway:1;
00509 struct dahdi_confinfo curconf;
00510 };
00511
00512 #define CONF_USER_REAL (1 << 0)
00513 #define CONF_USER_THIRDCALL (1 << 1)
00514
00515 #define MAX_SLAVES 4
00516
00517 static struct dahdi_pvt {
00518 ast_mutex_t lock;
00519 struct ast_channel *owner;
00520
00521
00522 struct dahdi_subchannel sub_unused;
00523 struct dahdi_subchannel subs[3];
00524 struct dahdi_confinfo saveconf;
00525
00526 struct dahdi_pvt *slaves[MAX_SLAVES];
00527 struct dahdi_pvt *master;
00528 int inconference;
00529
00530 int buf_no;
00531 int buf_policy;
00532 int sig;
00533
00534
00535
00536
00537 int radio;
00538 int outsigmod;
00539 int oprmode;
00540 struct dahdi_pvt *oprpeer;
00541
00542 float cid_rxgain;
00543
00544 float rxgain;
00545
00546 float txgain;
00547 int tonezone;
00548 struct dahdi_pvt *next;
00549 struct dahdi_pvt *prev;
00550
00551
00552
00553
00554
00555
00556
00557 unsigned int adsi:1;
00558
00559
00560
00561
00562
00563 unsigned int answeronpolarityswitch:1;
00564
00565
00566
00567
00568
00569 unsigned int busydetect:1;
00570
00571
00572
00573
00574
00575 unsigned int callreturn:1;
00576
00577
00578
00579
00580
00581
00582 unsigned int callwaiting:1;
00583
00584
00585
00586
00587 unsigned int callwaitingcallerid:1;
00588
00589
00590
00591
00592
00593
00594 unsigned int cancallforward:1;
00595
00596
00597
00598
00599 unsigned int canpark:1;
00600
00601 unsigned int confirmanswer:1;
00602
00603
00604
00605
00606 unsigned int destroy:1;
00607 unsigned int didtdd:1;
00608
00609 unsigned int dialednone:1;
00610
00611 unsigned int dialing:1;
00612
00613 unsigned int digital:1;
00614
00615 unsigned int dnd:1;
00616
00617 unsigned int echobreak:1;
00618
00619
00620
00621
00622
00623 unsigned int echocanbridged:1;
00624
00625 unsigned int echocanon:1;
00626
00627 unsigned int faxhandled:1;
00628
00629 unsigned int firstradio:1;
00630
00631
00632
00633
00634 unsigned int hanguponpolarityswitch:1;
00635
00636 unsigned int hardwaredtmf:1;
00637
00638
00639
00640
00641
00642
00643 unsigned int hidecallerid:1;
00644
00645
00646
00647
00648
00649 unsigned int hidecalleridname:1;
00650
00651 unsigned int ignoredtmf:1;
00652
00653
00654
00655
00656
00657 unsigned int immediate:1;
00658
00659 unsigned int inalarm:1;
00660
00661 unsigned int mate:1;
00662
00663 unsigned int outgoing:1;
00664
00665
00666
00667
00668
00669
00670 unsigned int permcallwaiting:1;
00671
00672
00673
00674
00675 unsigned int permhidecallerid:1;
00676
00677
00678
00679
00680 unsigned int priindication_oob:1;
00681
00682
00683
00684
00685 unsigned int priexclusive:1;
00686
00687
00688
00689
00690 unsigned int pulse:1;
00691
00692 unsigned int pulsedial:1;
00693 unsigned int restartpending:1;
00694
00695
00696
00697
00698
00699 unsigned int restrictcid:1;
00700
00701
00702
00703
00704 unsigned int threewaycalling:1;
00705
00706
00707
00708
00709
00710
00711
00712
00713 unsigned int transfer:1;
00714
00715
00716
00717
00718
00719
00720
00721 unsigned int use_callerid:1;
00722
00723
00724
00725
00726
00727
00728 unsigned int use_callingpres:1;
00729
00730
00731
00732
00733
00734 unsigned int usedistinctiveringdetection:1;
00735
00736
00737
00738
00739 unsigned int dahditrcallerid:1;
00740
00741
00742
00743
00744 unsigned int transfertobusy:1;
00745
00746
00747
00748
00749 unsigned int mwimonitor_neon:1;
00750
00751
00752
00753
00754 unsigned int mwimonitor_fsk:1;
00755
00756
00757
00758
00759
00760 unsigned int mwimonitor_rpas:1;
00761
00762 unsigned int mwimonitoractive:1;
00763
00764 unsigned int mwisendactive:1;
00765
00766
00767
00768
00769 unsigned int inservice:1;
00770
00771
00772
00773
00774 unsigned int locallyblocked:1;
00775
00776
00777
00778
00779 unsigned int remotelyblocked:1;
00780 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00781
00782
00783
00784
00785 unsigned int rlt:1;
00786
00787 unsigned int alerting:1;
00788
00789 unsigned int alreadyhungup:1;
00790
00791
00792
00793
00794 unsigned int isidlecall:1;
00795
00796
00797
00798
00799 unsigned int proceeding:1;
00800
00801 unsigned int progress:1;
00802
00803
00804
00805
00806 unsigned int resetting:1;
00807
00808
00809
00810
00811 unsigned int setup_ack:1;
00812 #endif
00813
00814
00815
00816
00817 unsigned int use_smdi:1;
00818
00819 struct ast_smdi_interface *smdi_iface;
00820
00821
00822 struct dahdi_distRings drings;
00823
00824
00825
00826
00827
00828 char context[AST_MAX_CONTEXT];
00829
00830
00831
00832 char defcontext[AST_MAX_CONTEXT];
00833
00834 char exten[AST_MAX_EXTENSION];
00835
00836
00837
00838
00839 char language[MAX_LANGUAGE];
00840
00841
00842
00843
00844 char mohinterpret[MAX_MUSICCLASS];
00845
00846
00847
00848
00849 char mohsuggest[MAX_MUSICCLASS];
00850 char parkinglot[AST_MAX_EXTENSION];
00851 #if defined(PRI_ANI) || defined(HAVE_SS7)
00852
00853 char cid_ani[AST_MAX_EXTENSION];
00854 #endif
00855
00856 int cid_ani2;
00857
00858 char cid_num[AST_MAX_EXTENSION];
00859
00860 int cid_ton;
00861
00862 char cid_name[AST_MAX_EXTENSION];
00863
00864 char lastcid_num[AST_MAX_EXTENSION];
00865
00866 char lastcid_name[AST_MAX_EXTENSION];
00867 char *origcid_num;
00868 char *origcid_name;
00869
00870 char callwait_num[AST_MAX_EXTENSION];
00871
00872 char callwait_name[AST_MAX_EXTENSION];
00873
00874 char rdnis[AST_MAX_EXTENSION];
00875
00876 char dnid[AST_MAX_EXTENSION];
00877
00878
00879
00880
00881 ast_group_t group;
00882
00883 int law;
00884 int confno;
00885 int confusers;
00886 int propconfno;
00887
00888
00889
00890
00891 ast_group_t callgroup;
00892
00893
00894
00895
00896 ast_group_t pickupgroup;
00897
00898
00899
00900
00901 struct ast_variable *vars;
00902 int channel;
00903 int span;
00904 time_t guardtime;
00905 int cid_signalling;
00906 int cid_start;
00907 int callingpres;
00908 int callwaitingrepeat;
00909 int cidcwexpire;
00910
00911 unsigned char *cidspill;
00912
00913 int cidpos;
00914
00915 int cidlen;
00916
00917 int ringt;
00918
00919
00920
00921
00922 int ringt_base;
00923
00924
00925
00926
00927
00928
00929 int stripmsd;
00930
00931 int callwaitcas;
00932
00933 int callwaitrings;
00934
00935 struct {
00936 struct dahdi_echocanparams head;
00937 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
00938 } echocancel;
00939
00940
00941
00942
00943 int echotraining;
00944
00945 char echorest[20];
00946
00947
00948
00949
00950 int busycount;
00951
00952
00953
00954
00955 int busycompare;
00956
00957
00958
00959
00960 int busytonelength;
00961
00962
00963
00964
00965 int busyquietlength;
00966
00967
00968
00969
00970 int busyfuzziness;
00971
00972
00973
00974
00975 int silencethreshold;
00976
00977
00978
00979
00980 int callprogress;
00981 struct timeval flashtime;
00982
00983 struct ast_dsp *dsp;
00984
00985
00986 struct dahdi_dialoperation dop;
00987 int whichwink;
00988
00989 char finaldial[64];
00990 char accountcode[AST_MAX_ACCOUNT_CODE];
00991 int amaflags;
00992 struct tdd_state *tdd;
00993
00994 char call_forward[AST_MAX_EXTENSION];
00995
00996
00997
00998
00999 char mailbox[AST_MAX_EXTENSION];
01000
01001 struct ast_event_sub *mwi_event_sub;
01002
01003 char dialdest[256];
01004
01005 int onhooktime;
01006
01007 int msgstate;
01008 int distinctivering;
01009 int cidrings;
01010 int dtmfrelax;
01011
01012 int fake_event;
01013
01014
01015
01016
01017 int polarityonanswerdelay;
01018
01019 struct timeval polaritydelaytv;
01020
01021
01022
01023
01024 int sendcalleridafter;
01025 #ifdef HAVE_PRI
01026
01027 struct dahdi_pri *pri;
01028
01029 struct dahdi_pvt *bearer;
01030
01031 struct dahdi_pvt *realcall;
01032
01033 q931_call *call;
01034
01035 int prioffset;
01036
01037 int logicalspan;
01038 #endif
01039
01040 int polarity;
01041
01042 int dsp_features;
01043 #ifdef HAVE_SS7
01044
01045 struct dahdi_ss7 *ss7;
01046
01047 struct isup_call *ss7call;
01048 char charge_number[50];
01049 char gen_add_number[50];
01050 char gen_dig_number[50];
01051 char orig_called_num[50];
01052 char redirecting_num[50];
01053 char generic_name[50];
01054 unsigned char gen_add_num_plan;
01055 unsigned char gen_add_nai;
01056 unsigned char gen_add_pres_ind;
01057 unsigned char gen_add_type;
01058 unsigned char gen_dig_type;
01059 unsigned char gen_dig_scheme;
01060 char jip_number[50];
01061 unsigned char lspi_type;
01062 unsigned char lspi_scheme;
01063 unsigned char lspi_context;
01064 char lspi_ident[50];
01065 unsigned int call_ref_ident;
01066 unsigned int call_ref_pc;
01067 unsigned char calling_party_cat;
01068 int transcap;
01069 int cic;
01070 unsigned int dpc;
01071 unsigned int loopedback:1;
01072 #endif
01073
01074 char begindigit;
01075
01076 int muting;
01077 } *iflist = NULL, *ifend = NULL;
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 struct dahdi_chan_conf {
01090 struct dahdi_pvt chan;
01091 #ifdef HAVE_PRI
01092 struct dahdi_pri pri;
01093 #endif
01094
01095 #ifdef HAVE_SS7
01096 struct dahdi_ss7 ss7;
01097 #endif
01098 struct dahdi_params timing;
01099 int is_sig_auto;
01100
01101
01102
01103
01104
01105 char smdi_port[SMDI_MAX_FILENAME_LEN];
01106 };
01107
01108
01109 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01110
01111
01112
01113 struct dahdi_chan_conf conf = {
01114 #ifdef HAVE_PRI
01115 .pri = {
01116 .nsf = PRI_NSF_NONE,
01117 .switchtype = PRI_SWITCH_NI2,
01118 .dialplan = PRI_UNKNOWN + 1,
01119 .localdialplan = PRI_NATIONAL_ISDN + 1,
01120 .nodetype = PRI_CPE,
01121
01122 .minunused = 2,
01123 .idleext = "",
01124 .idledial = "",
01125 .internationalprefix = "",
01126 .nationalprefix = "",
01127 .localprefix = "",
01128 .privateprefix = "",
01129 .unknownprefix = "",
01130 .resetinterval = -1,
01131 },
01132 #endif
01133 #ifdef HAVE_SS7
01134 .ss7 = {
01135 .called_nai = SS7_NAI_NATIONAL,
01136 .calling_nai = SS7_NAI_NATIONAL,
01137 .internationalprefix = "",
01138 .nationalprefix = "",
01139 .subscriberprefix = "",
01140 .unknownprefix = ""
01141 },
01142 #endif
01143 .chan = {
01144 .context = "default",
01145 .cid_num = "",
01146 .cid_name = "",
01147 .mohinterpret = "default",
01148 .mohsuggest = "",
01149 .parkinglot = "",
01150 .transfertobusy = 1,
01151
01152 .cid_signalling = CID_SIG_BELL,
01153 .cid_start = CID_START_RING,
01154 .dahditrcallerid = 0,
01155 .use_callerid = 1,
01156 .sig = -1,
01157 .outsigmod = -1,
01158
01159 .cid_rxgain = +5.0,
01160
01161 .tonezone = -1,
01162
01163 .echocancel.head.tap_length = 1,
01164
01165 .busycount = 3,
01166 .busycompare = 0,
01167 .busytonelength = 0,
01168 .busyquietlength = 0,
01169 .busyfuzziness = 0,
01170 .silencethreshold = 0,
01171
01172 .accountcode = "",
01173
01174 .mailbox = "",
01175
01176
01177 .polarityonanswerdelay = 600,
01178
01179 .sendcalleridafter = DEFAULT_CIDRINGS,
01180
01181 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01182 .buf_no = numbufs
01183 },
01184 .timing = {
01185 .prewinktime = -1,
01186 .preflashtime = -1,
01187 .winktime = -1,
01188 .flashtime = -1,
01189 .starttime = -1,
01190 .rxwinktime = -1,
01191 .rxflashtime = -1,
01192 .debouncetime = -1
01193 },
01194 .is_sig_auto = 1,
01195 .smdi_port = "/dev/ttyS0",
01196 };
01197
01198 return conf;
01199 }
01200
01201
01202 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01203 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01204 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01205 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01206 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01207 static int dahdi_hangup(struct ast_channel *ast);
01208 static int dahdi_answer(struct ast_channel *ast);
01209 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01210 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01211 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01212 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01213 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01214 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01215 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01216 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01217
01218 static const struct ast_channel_tech dahdi_tech = {
01219 .type = "DAHDI",
01220 .description = tdesc,
01221 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01222 .requester = dahdi_request,
01223 .send_digit_begin = dahdi_digit_begin,
01224 .send_digit_end = dahdi_digit_end,
01225 .send_text = dahdi_sendtext,
01226 .call = dahdi_call,
01227 .hangup = dahdi_hangup,
01228 .answer = dahdi_answer,
01229 .read = dahdi_read,
01230 .write = dahdi_write,
01231 .bridge = dahdi_bridge,
01232 .exception = dahdi_exception,
01233 .indicate = dahdi_indicate,
01234 .fixup = dahdi_fixup,
01235 .setoption = dahdi_setoption,
01236 .func_channel_read = dahdi_func_read,
01237 };
01238
01239 #ifdef HAVE_PRI
01240 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01241 #else
01242 #define GET_CHANNEL(p) ((p)->channel)
01243 #endif
01244
01245 struct dahdi_pvt *round_robin[32];
01246
01247 #ifdef HAVE_PRI
01248 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01249 {
01250 int res;
01251
01252 do {
01253 res = ast_mutex_trylock(&pri->lock);
01254 if (res) {
01255 DEADLOCK_AVOIDANCE(&pvt->lock);
01256 }
01257 } while (res);
01258
01259 if (pri->master != AST_PTHREADT_NULL)
01260 pthread_kill(pri->master, SIGURG);
01261 return 0;
01262 }
01263 #endif
01264
01265 #ifdef HAVE_SS7
01266 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01267 {
01268 ast_mutex_unlock(&ss7->lock);
01269 }
01270
01271 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01272 {
01273 int res;
01274
01275 do {
01276 res = ast_mutex_trylock(&pri->lock);
01277 if (res) {
01278 DEADLOCK_AVOIDANCE(&pvt->lock);
01279 }
01280 } while (res);
01281
01282 if (pri->master != AST_PTHREADT_NULL)
01283 pthread_kill(pri->master, SIGURG);
01284 return 0;
01285 }
01286 #endif
01287 #define NUM_CADENCE_MAX 25
01288 static int num_cadence = 4;
01289 static int user_has_defined_cadences = 0;
01290
01291 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01292 { { 125, 125, 2000, 4000 } },
01293 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01294 { { 125, 125, 125, 125, 125, 4000 } },
01295 { { 1000, 500, 2500, 5000 } },
01296 };
01297
01298
01299
01300
01301
01302 static int cidrings[NUM_CADENCE_MAX] = {
01303 2,
01304 4,
01305 3,
01306 2,
01307 };
01308
01309
01310 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01311
01312 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01313 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01314
01315 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01316 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01317
01318 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01319 {
01320 int res;
01321 if (p->subs[SUB_REAL].owner == ast)
01322 res = 0;
01323 else if (p->subs[SUB_CALLWAIT].owner == ast)
01324 res = 1;
01325 else if (p->subs[SUB_THREEWAY].owner == ast)
01326 res = 2;
01327 else {
01328 res = -1;
01329 if (!nullok)
01330 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01331 }
01332 return res;
01333 }
01334
01335 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01336 {
01337 #ifdef HAVE_PRI
01338 if (pri)
01339 ast_mutex_unlock(&pri->lock);
01340 #endif
01341 for (;;) {
01342 if (p->subs[a].owner) {
01343 if (ast_channel_trylock(p->subs[a].owner)) {
01344 DEADLOCK_AVOIDANCE(&p->lock);
01345 } else {
01346 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01347 ast_channel_unlock(p->subs[a].owner);
01348 break;
01349 }
01350 } else
01351 break;
01352 }
01353 #ifdef HAVE_PRI
01354 if (pri)
01355 ast_mutex_lock(&pri->lock);
01356 #endif
01357 }
01358
01359 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01360 {
01361 #ifdef HAVE_PRI
01362 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01363 #endif
01364 #ifdef HAVE_SS7
01365 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01366 #endif
01367
01368 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01369 if (data) {
01370 switch (p->sig) {
01371 #ifdef HAVE_PRI
01372 case SIG_BRI:
01373 case SIG_BRI_PTMP:
01374 case SIG_PRI:
01375 ast_mutex_unlock(&pri->lock);
01376 break;
01377 #endif
01378 #ifdef HAVE_SS7
01379 case SIG_SS7:
01380 ast_mutex_unlock(&ss7->lock);
01381 break;
01382 #endif
01383 default:
01384 break;
01385 }
01386 }
01387 #endif
01388 for (;;) {
01389 if (p->owner) {
01390 if (ast_channel_trylock(p->owner)) {
01391 DEADLOCK_AVOIDANCE(&p->lock);
01392 } else {
01393 ast_queue_frame(p->owner, f);
01394 ast_channel_unlock(p->owner);
01395 break;
01396 }
01397 } else
01398 break;
01399 }
01400 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01401 if (data) {
01402 switch (p->sig) {
01403 #ifdef HAVE_PRI
01404 case SIG_BRI:
01405 case SIG_BRI_PTMP:
01406 case SIG_PRI:
01407 ast_mutex_lock(&pri->lock);
01408 break;
01409 #endif
01410 #ifdef HAVE_SS7
01411 case SIG_SS7:
01412 ast_mutex_lock(&ss7->lock);
01413 break;
01414 #endif
01415 default:
01416 break;
01417 }
01418 }
01419
01420 #endif
01421 }
01422
01423 static int restore_gains(struct dahdi_pvt *p);
01424
01425 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01426 {
01427 int tchan;
01428 int tinthreeway;
01429 struct ast_channel *towner;
01430
01431 ast_debug(1, "Swapping %d and %d\n", a, b);
01432
01433 tchan = p->subs[a].chan;
01434 towner = p->subs[a].owner;
01435 tinthreeway = p->subs[a].inthreeway;
01436
01437 p->subs[a].chan = p->subs[b].chan;
01438 p->subs[a].owner = p->subs[b].owner;
01439 p->subs[a].inthreeway = p->subs[b].inthreeway;
01440
01441 p->subs[b].chan = tchan;
01442 p->subs[b].owner = towner;
01443 p->subs[b].inthreeway = tinthreeway;
01444
01445 if (p->subs[a].owner)
01446 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01447 if (p->subs[b].owner)
01448 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01449 wakeup_sub(p, a, NULL);
01450 wakeup_sub(p, b, NULL);
01451 }
01452
01453 static int dahdi_open(char *fn)
01454 {
01455 int fd;
01456 int isnum;
01457 int chan = 0;
01458 int bs;
01459 int x;
01460 isnum = 1;
01461 for (x = 0; x < strlen(fn); x++) {
01462 if (!isdigit(fn[x])) {
01463 isnum = 0;
01464 break;
01465 }
01466 }
01467 if (isnum) {
01468 chan = atoi(fn);
01469 if (chan < 1) {
01470 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01471 return -1;
01472 }
01473 fn = "/dev/dahdi/channel";
01474 }
01475 fd = open(fn, O_RDWR | O_NONBLOCK);
01476 if (fd < 0) {
01477 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01478 return -1;
01479 }
01480 if (chan) {
01481 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01482 x = errno;
01483 close(fd);
01484 errno = x;
01485 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01486 return -1;
01487 }
01488 }
01489 bs = READ_SIZE;
01490 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01491 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01492 x = errno;
01493 close(fd);
01494 errno = x;
01495 return -1;
01496 }
01497 return fd;
01498 }
01499
01500 static void dahdi_close(int fd)
01501 {
01502 if (fd > 0)
01503 close(fd);
01504 }
01505
01506 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01507 {
01508 dahdi_close(chan_pvt->subs[sub_num].dfd);
01509 chan_pvt->subs[sub_num].dfd = -1;
01510 }
01511
01512 #ifdef HAVE_PRI
01513 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01514 {
01515 dahdi_close(pri->fds[fd_num]);
01516 pri->fds[fd_num] = -1;
01517 }
01518 #endif
01519
01520 #ifdef HAVE_SS7
01521 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
01522 {
01523 dahdi_close(ss7->fds[fd_num]);
01524 ss7->fds[fd_num] = -1;
01525 }
01526 #endif
01527
01528 static int dahdi_setlinear(int dfd, int linear)
01529 {
01530 int res;
01531 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01532 if (res)
01533 return res;
01534 return 0;
01535 }
01536
01537
01538 static int alloc_sub(struct dahdi_pvt *p, int x)
01539 {
01540 struct dahdi_bufferinfo bi;
01541 int res;
01542 if (p->subs[x].dfd >= 0) {
01543 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01544 return -1;
01545 }
01546
01547 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01548 if (p->subs[x].dfd <= -1) {
01549 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01550 return -1;
01551 }
01552
01553 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01554 if (!res) {
01555 bi.txbufpolicy = p->buf_policy;
01556 bi.rxbufpolicy = p->buf_policy;
01557 bi.numbufs = p->buf_no;
01558 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01559 if (res < 0) {
01560 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01561 }
01562 } else
01563 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01564
01565 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01566 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01567 dahdi_close_sub(p, x);
01568 p->subs[x].dfd = -1;
01569 return -1;
01570 }
01571 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01572 return 0;
01573 }
01574
01575 static int unalloc_sub(struct dahdi_pvt *p, int x)
01576 {
01577 if (!x) {
01578 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01579 return -1;
01580 }
01581 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01582 dahdi_close_sub(p, x);
01583 p->subs[x].linear = 0;
01584 p->subs[x].chan = 0;
01585 p->subs[x].owner = NULL;
01586 p->subs[x].inthreeway = 0;
01587 p->polarity = POLARITY_IDLE;
01588 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01589 return 0;
01590 }
01591
01592 static int digit_to_dtmfindex(char digit)
01593 {
01594 if (isdigit(digit))
01595 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01596 else if (digit >= 'A' && digit <= 'D')
01597 return DAHDI_TONE_DTMF_A + (digit - 'A');
01598 else if (digit >= 'a' && digit <= 'd')
01599 return DAHDI_TONE_DTMF_A + (digit - 'a');
01600 else if (digit == '*')
01601 return DAHDI_TONE_DTMF_s;
01602 else if (digit == '#')
01603 return DAHDI_TONE_DTMF_p;
01604 else
01605 return -1;
01606 }
01607
01608 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01609 {
01610 struct dahdi_pvt *pvt;
01611 int idx;
01612 int dtmf = -1;
01613
01614 pvt = chan->tech_pvt;
01615
01616 ast_mutex_lock(&pvt->lock);
01617
01618 idx = dahdi_get_index(chan, pvt, 0);
01619
01620 if ((idx != SUB_REAL) || !pvt->owner)
01621 goto out;
01622
01623 #ifdef HAVE_PRI
01624 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01625 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01626 if (pvt->setup_ack) {
01627 if (!pri_grab(pvt, pvt->pri)) {
01628 pri_information(pvt->pri->pri, pvt->call, digit);
01629 pri_rel(pvt->pri);
01630 } else
01631 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01632 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01633 int res;
01634 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01635 res = strlen(pvt->dialdest);
01636 pvt->dialdest[res++] = digit;
01637 pvt->dialdest[res] = '\0';
01638 }
01639 goto out;
01640 }
01641 #endif
01642 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01643 goto out;
01644
01645 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01646 int res;
01647 struct dahdi_dialoperation zo = {
01648 .op = DAHDI_DIAL_OP_APPEND,
01649 };
01650
01651 zo.dialstr[0] = 'T';
01652 zo.dialstr[1] = digit;
01653 zo.dialstr[2] = '\0';
01654 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01655 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01656 else
01657 pvt->dialing = 1;
01658 } else {
01659 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01660 pvt->dialing = 1;
01661 pvt->begindigit = digit;
01662 }
01663
01664 out:
01665 ast_mutex_unlock(&pvt->lock);
01666
01667 return 0;
01668 }
01669
01670 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01671 {
01672 struct dahdi_pvt *pvt;
01673 int res = 0;
01674 int idx;
01675 int x;
01676
01677 pvt = chan->tech_pvt;
01678
01679 ast_mutex_lock(&pvt->lock);
01680
01681 idx = dahdi_get_index(chan, pvt, 0);
01682
01683 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
01684 goto out;
01685
01686 #ifdef HAVE_PRI
01687
01688 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01689 && !pvt->begindigit)
01690 goto out;
01691 #endif
01692
01693 if (pvt->begindigit) {
01694 x = -1;
01695 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01696 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01697 pvt->dialing = 0;
01698 pvt->begindigit = 0;
01699 }
01700
01701 out:
01702 ast_mutex_unlock(&pvt->lock);
01703
01704 return res;
01705 }
01706
01707 static char *events[] = {
01708 "No event",
01709 "On hook",
01710 "Ring/Answered",
01711 "Wink/Flash",
01712 "Alarm",
01713 "No more alarm",
01714 "HDLC Abort",
01715 "HDLC Overrun",
01716 "HDLC Bad FCS",
01717 "Dial Complete",
01718 "Ringer On",
01719 "Ringer Off",
01720 "Hook Transition Complete",
01721 "Bits Changed",
01722 "Pulse Start",
01723 "Timer Expired",
01724 "Timer Ping",
01725 "Polarity Reversal",
01726 "Ring Begin",
01727 };
01728
01729 static struct {
01730 int alarm;
01731 char *name;
01732 } alarms[] = {
01733 { DAHDI_ALARM_RED, "Red Alarm" },
01734 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01735 { DAHDI_ALARM_BLUE, "Blue Alarm" },
01736 { DAHDI_ALARM_RECOVER, "Recovering" },
01737 { DAHDI_ALARM_LOOPBACK, "Loopback" },
01738 { DAHDI_ALARM_NOTOPEN, "Not Open" },
01739 { DAHDI_ALARM_NONE, "None" },
01740 };
01741
01742 static char *alarm2str(int alm)
01743 {
01744 int x;
01745 for (x = 0; x < ARRAY_LEN(alarms); x++) {
01746 if (alarms[x].alarm & alm)
01747 return alarms[x].name;
01748 }
01749 return alm ? "Unknown Alarm" : "No Alarm";
01750 }
01751
01752 static char *event2str(int event)
01753 {
01754 static char buf[256];
01755 if ((event < (ARRAY_LEN(events))) && (event > -1))
01756 return events[event];
01757 sprintf(buf, "Event %d", event);
01758 return buf;
01759 }
01760
01761 #ifdef HAVE_PRI
01762 static char *dialplan2str(int dialplan)
01763 {
01764 if (dialplan == -1 || dialplan == -2) {
01765 return("Dynamically set dialplan in ISDN");
01766 }
01767 return (pri_plan2str(dialplan));
01768 }
01769 #endif
01770
01771 static char *dahdi_sig2str(int sig)
01772 {
01773 static char buf[256];
01774 switch (sig) {
01775 case SIG_EM:
01776 return "E & M Immediate";
01777 case SIG_EMWINK:
01778 return "E & M Wink";
01779 case SIG_EM_E1:
01780 return "E & M E1";
01781 case SIG_FEATD:
01782 return "Feature Group D (DTMF)";
01783 case SIG_FEATDMF:
01784 return "Feature Group D (MF)";
01785 case SIG_FEATDMF_TA:
01786 return "Feature Groud D (MF) Tandem Access";
01787 case SIG_FEATB:
01788 return "Feature Group B (MF)";
01789 case SIG_E911:
01790 return "E911 (MF)";
01791 case SIG_FGC_CAMA:
01792 return "FGC/CAMA (Dialpulse)";
01793 case SIG_FGC_CAMAMF:
01794 return "FGC/CAMA (MF)";
01795 case SIG_FXSLS:
01796 return "FXS Loopstart";
01797 case SIG_FXSGS:
01798 return "FXS Groundstart";
01799 case SIG_FXSKS:
01800 return "FXS Kewlstart";
01801 case SIG_FXOLS:
01802 return "FXO Loopstart";
01803 case SIG_FXOGS:
01804 return "FXO Groundstart";
01805 case SIG_FXOKS:
01806 return "FXO Kewlstart";
01807 case SIG_PRI:
01808 return "ISDN PRI";
01809 case SIG_BRI:
01810 return "ISDN BRI Point to Point";
01811 case SIG_BRI_PTMP:
01812 return "ISDN BRI Point to MultiPoint";
01813 case SIG_SS7:
01814 return "SS7";
01815 case SIG_SF:
01816 return "SF (Tone) Immediate";
01817 case SIG_SFWINK:
01818 return "SF (Tone) Wink";
01819 case SIG_SF_FEATD:
01820 return "SF (Tone) with Feature Group D (DTMF)";
01821 case SIG_SF_FEATDMF:
01822 return "SF (Tone) with Feature Group D (MF)";
01823 case SIG_SF_FEATB:
01824 return "SF (Tone) with Feature Group B (MF)";
01825 case SIG_GR303FXOKS:
01826 return "GR-303 with FXOKS";
01827 case SIG_GR303FXSKS:
01828 return "GR-303 with FXSKS";
01829 case 0:
01830 return "Pseudo";
01831 default:
01832 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01833 return buf;
01834 }
01835 }
01836
01837 #define sig2str dahdi_sig2str
01838
01839 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
01840 {
01841
01842
01843 struct dahdi_confinfo zi;
01844
01845 memset(&zi, 0, sizeof(zi));
01846 zi.chan = 0;
01847
01848 if (slavechannel > 0) {
01849
01850 zi.confmode = DAHDI_CONF_DIGITALMON;
01851 zi.confno = slavechannel;
01852 } else {
01853 if (!idx) {
01854
01855 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01856 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01857 } else
01858 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01859 zi.confno = p->confno;
01860 }
01861 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01862 return 0;
01863 if (c->dfd < 0)
01864 return 0;
01865 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01866 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01867 return -1;
01868 }
01869 if (slavechannel < 1) {
01870 p->confno = zi.confno;
01871 }
01872 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01873 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01874 return 0;
01875 }
01876
01877 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01878 {
01879
01880 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01881 return 1;
01882
01883 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01884 return 1;
01885 return 0;
01886 }
01887
01888 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
01889 {
01890 struct dahdi_confinfo zi;
01891 if (
01892 (c->dfd < 0) ||
01893
01894 !isourconf(p, c)
01895
01896 ) return 0;
01897 memset(&zi, 0, sizeof(zi));
01898 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01899 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01900 return -1;
01901 }
01902 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01903 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01904 return 0;
01905 }
01906
01907 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01908 {
01909 int x;
01910 int useslavenative;
01911 struct dahdi_pvt *slave = NULL;
01912
01913 useslavenative = 1;
01914
01915 for (x = 0; x < 3; x++) {
01916
01917
01918 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01919 useslavenative = 0;
01920 }
01921
01922
01923 if (useslavenative) {
01924 for (x = 0; x < MAX_SLAVES; x++) {
01925 if (p->slaves[x]) {
01926 if (slave) {
01927
01928
01929 slave = NULL;
01930 useslavenative = 0;
01931 break;
01932 } else {
01933
01934 slave = p->slaves[x];
01935 }
01936 }
01937 }
01938 }
01939
01940 if (!slave)
01941 useslavenative = 0;
01942 else if (slave->law != p->law) {
01943 useslavenative = 0;
01944 slave = NULL;
01945 }
01946 if (out)
01947 *out = slave;
01948 return useslavenative;
01949 }
01950
01951 static int reset_conf(struct dahdi_pvt *p)
01952 {
01953 p->confno = -1;
01954 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01955 if (p->subs[SUB_REAL].dfd > -1) {
01956 struct dahdi_confinfo zi;
01957
01958 memset(&zi, 0, sizeof(zi));
01959 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01960 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01961 }
01962 return 0;
01963 }
01964
01965 static int update_conf(struct dahdi_pvt *p)
01966 {
01967 int needconf = 0;
01968 int x;
01969 int useslavenative;
01970 struct dahdi_pvt *slave = NULL;
01971
01972 useslavenative = isslavenative(p, &slave);
01973
01974 for (x = 0; x < 3; x++) {
01975
01976 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01977 conf_add(p, &p->subs[x], x, 0);
01978 needconf++;
01979 } else {
01980 conf_del(p, &p->subs[x], x);
01981 }
01982 }
01983
01984
01985 for (x = 0; x < MAX_SLAVES; x++) {
01986 if (p->slaves[x]) {
01987 if (useslavenative)
01988 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01989 else {
01990 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01991 needconf++;
01992 }
01993 }
01994 }
01995
01996 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01997 if (useslavenative)
01998 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01999 else {
02000 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02001 needconf++;
02002 }
02003 }
02004
02005 if (p->master) {
02006 if (isslavenative(p->master, NULL)) {
02007 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02008 } else {
02009 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02010 }
02011 }
02012 if (!needconf) {
02013
02014
02015 p->confno = -1;
02016 }
02017 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02018 return 0;
02019 }
02020
02021 static void dahdi_enable_ec(struct dahdi_pvt *p)
02022 {
02023 int x;
02024 int res;
02025 if (!p)
02026 return;
02027 if (p->echocanon) {
02028 ast_debug(1, "Echo cancellation already on\n");
02029 return;
02030 }
02031 if (p->digital) {
02032 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02033 return;
02034 }
02035 if (p->echocancel.head.tap_length) {
02036 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02037 x = 1;
02038 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02039 if (res)
02040 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02041 }
02042 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02043 if (res) {
02044 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02045 } else {
02046 p->echocanon = 1;
02047 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02048 }
02049 } else
02050 ast_debug(1, "No echo cancellation requested\n");
02051 }
02052
02053 static void dahdi_train_ec(struct dahdi_pvt *p)
02054 {
02055 int x;
02056 int res;
02057
02058 if (p && p->echocanon && p->echotraining) {
02059 x = p->echotraining;
02060 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02061 if (res)
02062 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02063 else
02064 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02065 } else {
02066 ast_debug(1, "No echo training requested\n");
02067 }
02068 }
02069
02070 static void dahdi_disable_ec(struct dahdi_pvt *p)
02071 {
02072 int res;
02073
02074 if (p->echocanon) {
02075 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02076
02077 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02078
02079 if (res)
02080 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02081 else
02082 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02083 }
02084
02085 p->echocanon = 0;
02086 }
02087
02088 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02089 {
02090 int j;
02091 int k;
02092 float linear_gain = pow(10.0, gain / 20.0);
02093
02094 switch (law) {
02095 case DAHDI_LAW_ALAW:
02096 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02097 if (gain) {
02098 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02099 if (k > 32767) k = 32767;
02100 if (k < -32767) k = -32767;
02101 g->txgain[j] = AST_LIN2A(k);
02102 } else {
02103 g->txgain[j] = j;
02104 }
02105 }
02106 break;
02107 case DAHDI_LAW_MULAW:
02108 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02109 if (gain) {
02110 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02111 if (k > 32767) k = 32767;
02112 if (k < -32767) k = -32767;
02113 g->txgain[j] = AST_LIN2MU(k);
02114 } else {
02115 g->txgain[j] = j;
02116 }
02117 }
02118 break;
02119 }
02120 }
02121
02122 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02123 {
02124 int j;
02125 int k;
02126 float linear_gain = pow(10.0, gain / 20.0);
02127
02128 switch (law) {
02129 case DAHDI_LAW_ALAW:
02130 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02131 if (gain) {
02132 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02133 if (k > 32767) k = 32767;
02134 if (k < -32767) k = -32767;
02135 g->rxgain[j] = AST_LIN2A(k);
02136 } else {
02137 g->rxgain[j] = j;
02138 }
02139 }
02140 break;
02141 case DAHDI_LAW_MULAW:
02142 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02143 if (gain) {
02144 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02145 if (k > 32767) k = 32767;
02146 if (k < -32767) k = -32767;
02147 g->rxgain[j] = AST_LIN2MU(k);
02148 } else {
02149 g->rxgain[j] = j;
02150 }
02151 }
02152 break;
02153 }
02154 }
02155
02156 static int set_actual_txgain(int fd, int chan, float gain, int law)
02157 {
02158 struct dahdi_gains g;
02159 int res;
02160
02161 memset(&g, 0, sizeof(g));
02162 g.chan = chan;
02163 res = ioctl(fd, DAHDI_GETGAINS, &g);
02164 if (res) {
02165 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02166 return res;
02167 }
02168
02169 fill_txgain(&g, gain, law);
02170
02171 return ioctl(fd, DAHDI_SETGAINS, &g);
02172 }
02173
02174 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02175 {
02176 struct dahdi_gains g;
02177 int res;
02178
02179 memset(&g, 0, sizeof(g));
02180 g.chan = chan;
02181 res = ioctl(fd, DAHDI_GETGAINS, &g);
02182 if (res) {
02183 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02184 return res;
02185 }
02186
02187 fill_rxgain(&g, gain, law);
02188
02189 return ioctl(fd, DAHDI_SETGAINS, &g);
02190 }
02191
02192 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02193 {
02194 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02195 }
02196
02197 static int bump_gains(struct dahdi_pvt *p)
02198 {
02199 int res;
02200
02201
02202 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02203 if (res) {
02204 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02205 return -1;
02206 }
02207
02208 return 0;
02209 }
02210
02211 static int restore_gains(struct dahdi_pvt *p)
02212 {
02213 int res;
02214
02215 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02216 if (res) {
02217 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02218 return -1;
02219 }
02220
02221 return 0;
02222 }
02223
02224 static inline int dahdi_set_hook(int fd, int hs)
02225 {
02226 int x, res;
02227
02228 x = hs;
02229 res = ioctl(fd, DAHDI_HOOK, &x);
02230
02231 if (res < 0) {
02232 if (errno == EINPROGRESS)
02233 return 0;
02234 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02235
02236 }
02237
02238 return res;
02239 }
02240
02241 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02242 {
02243 int x, y, res;
02244 x = muted;
02245 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02246 y = 1;
02247 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02248 if (res)
02249 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02250 }
02251 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02252 if (res < 0)
02253 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02254 return res;
02255 }
02256
02257 static int save_conference(struct dahdi_pvt *p)
02258 {
02259 struct dahdi_confinfo c;
02260 int res;
02261 if (p->saveconf.confmode) {
02262 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02263 return -1;
02264 }
02265 p->saveconf.chan = 0;
02266 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02267 if (res) {
02268 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02269 p->saveconf.confmode = 0;
02270 return -1;
02271 }
02272 memset(&c, 0, sizeof(c));
02273 c.confmode = DAHDI_CONF_NORMAL;
02274 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02275 if (res) {
02276 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02277 return -1;
02278 }
02279 ast_debug(1, "Disabled conferencing\n");
02280 return 0;
02281 }
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301 static void notify_message(char *mailbox_full, int thereornot)
02302 {
02303 char s[sizeof(mwimonitornotify) + 80];
02304 struct ast_event *event;
02305 char *mailbox, *context;
02306
02307
02308 context = mailbox = ast_strdupa(mailbox_full);
02309 strsep(&context, "@");
02310 if (ast_strlen_zero(context))
02311 context = "default";
02312
02313 if (!(event = ast_event_new(AST_EVENT_MWI,
02314 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02315 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02316 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02317 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02318 AST_EVENT_IE_END))) {
02319 return;
02320 }
02321
02322 ast_event_queue_and_cache(event);
02323
02324 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02325 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02326 ast_safe_system(s);
02327 }
02328 }
02329
02330 static int restore_conference(struct dahdi_pvt *p)
02331 {
02332 int res;
02333 if (p->saveconf.confmode) {
02334 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02335 p->saveconf.confmode = 0;
02336 if (res) {
02337 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02338 return -1;
02339 }
02340 }
02341 ast_debug(1, "Restored conferencing\n");
02342 return 0;
02343 }
02344
02345 static int send_callerid(struct dahdi_pvt *p);
02346
02347 static int send_cwcidspill(struct dahdi_pvt *p)
02348 {
02349 p->callwaitcas = 0;
02350 p->cidcwexpire = 0;
02351 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02352 return -1;
02353 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02354
02355 p->cidlen += READ_SIZE * 4;
02356 p->cidpos = 0;
02357 send_callerid(p);
02358 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02359 return 0;
02360 }
02361
02362 static int has_voicemail(struct dahdi_pvt *p)
02363 {
02364 int new_msgs;
02365 struct ast_event *event;
02366 char *mailbox, *context;
02367
02368 mailbox = context = ast_strdupa(p->mailbox);
02369 strsep(&context, "@");
02370 if (ast_strlen_zero(context))
02371 context = "default";
02372
02373 event = ast_event_get_cached(AST_EVENT_MWI,
02374 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02375 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02376 AST_EVENT_IE_END);
02377
02378 if (event) {
02379 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02380 ast_event_destroy(event);
02381 } else
02382 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02383
02384 return new_msgs;
02385 }
02386
02387 static int send_callerid(struct dahdi_pvt *p)
02388 {
02389
02390 int res;
02391
02392 if (p->subs[SUB_REAL].linear) {
02393 p->subs[SUB_REAL].linear = 0;
02394 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02395 }
02396 while (p->cidpos < p->cidlen) {
02397 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02398 if (res < 0) {
02399 if (errno == EAGAIN)
02400 return 0;
02401 else {
02402 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02403 return -1;
02404 }
02405 }
02406 if (!res)
02407 return 0;
02408 p->cidpos += res;
02409 }
02410 ast_free(p->cidspill);
02411 p->cidspill = NULL;
02412 if (p->callwaitcas) {
02413
02414 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02415 } else
02416 restore_conference(p);
02417 return 0;
02418 }
02419
02420 static int dahdi_callwait(struct ast_channel *ast)
02421 {
02422 struct dahdi_pvt *p = ast->tech_pvt;
02423 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02424 if (p->cidspill) {
02425 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02426 ast_free(p->cidspill);
02427 }
02428 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02429 return -1;
02430 save_conference(p);
02431
02432 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02433 if (!p->callwaitrings && p->callwaitingcallerid) {
02434 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02435 p->callwaitcas = 1;
02436 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02437 } else {
02438 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02439 p->callwaitcas = 0;
02440 p->cidlen = 2400 + READ_SIZE * 4;
02441 }
02442 p->cidpos = 0;
02443 send_callerid(p);
02444
02445 return 0;
02446 }
02447
02448 #ifdef HAVE_SS7
02449 static unsigned char cid_pres2ss7pres(int cid_pres)
02450 {
02451 return (cid_pres >> 5) & 0x03;
02452 }
02453
02454 static unsigned char cid_pres2ss7screen(int cid_pres)
02455 {
02456 return cid_pres & 0x03;
02457 }
02458 #endif
02459
02460 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02461 {
02462 struct dahdi_pvt *p = ast->tech_pvt;
02463 int x, res, idx,mysig;
02464 char *c, *n, *l;
02465 #ifdef HAVE_PRI
02466 char *s = NULL;
02467 #endif
02468 char dest[256];
02469 ast_mutex_lock(&p->lock);
02470 ast_copy_string(dest, rdest, sizeof(dest));
02471 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02472 if ((ast->_state == AST_STATE_BUSY)) {
02473 p->subs[SUB_REAL].needbusy = 1;
02474 ast_mutex_unlock(&p->lock);
02475 return 0;
02476 }
02477 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02478 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02479 ast_mutex_unlock(&p->lock);
02480 return -1;
02481 }
02482 p->dialednone = 0;
02483 if ((p->radio || (p->oprmode < 0)))
02484 {
02485
02486 ast_setstate(ast, AST_STATE_UP);
02487 ast_mutex_unlock(&p->lock);
02488 return 0;
02489 }
02490 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02491 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02492 if (res)
02493 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02494 p->outgoing = 1;
02495
02496 if (IS_DIGITAL(ast->transfercapability)){
02497 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02498 } else {
02499 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02500 }
02501
02502 mysig = p->sig;
02503 if (p->outsigmod > -1)
02504 mysig = p->outsigmod;
02505
02506 switch (mysig) {
02507 case SIG_FXOLS:
02508 case SIG_FXOGS:
02509 case SIG_FXOKS:
02510 if (p->owner == ast) {
02511
02512
02513
02514 p->dialing = 1;
02515 if (p->use_callerid) {
02516
02517 if (p->cidspill) {
02518 ast_log(LOG_WARNING, "cidspill already exists??\n");
02519 ast_free(p->cidspill);
02520 }
02521 p->callwaitcas = 0;
02522 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02523 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02524 p->cidpos = 0;
02525 send_callerid(p);
02526 }
02527 }
02528
02529 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02530 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02531 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02532 p->cidrings = cidrings[p->distinctivering - 1];
02533 } else {
02534 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02535 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02536 p->cidrings = p->sendcalleridafter;
02537 }
02538
02539
02540 c = strchr(dest, '/');
02541 if (c)
02542 c++;
02543 if (c && (strlen(c) < p->stripmsd)) {
02544 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02545 c = NULL;
02546 }
02547 if (c) {
02548 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02549 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02550 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
02551 } else {
02552 p->dop.dialstr[0] = '\0';
02553 }
02554 x = DAHDI_RING;
02555 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02556 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02557 ast_mutex_unlock(&p->lock);
02558 return -1;
02559 }
02560 p->dialing = 1;
02561 } else {
02562
02563 p->callwaitrings = 0;
02564 if (ast->cid.cid_num)
02565 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02566 else
02567 p->callwait_num[0] = '\0';
02568 if (ast->cid.cid_name)
02569 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02570 else
02571 p->callwait_name[0] = '\0';
02572
02573 if (dahdi_callwait(ast)) {
02574 ast_mutex_unlock(&p->lock);
02575 return -1;
02576 }
02577
02578 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02579 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02580
02581 }
02582 n = ast->cid.cid_name;
02583 l = ast->cid.cid_num;
02584 if (l)
02585 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02586 else
02587 p->lastcid_num[0] = '\0';
02588 if (n)
02589 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02590 else
02591 p->lastcid_name[0] = '\0';
02592 ast_setstate(ast, AST_STATE_RINGING);
02593 idx = dahdi_get_index(ast, p, 0);
02594 if (idx > -1) {
02595 p->subs[idx].needringing = 1;
02596 }
02597 break;
02598 case SIG_FXSLS:
02599 case SIG_FXSGS:
02600 case SIG_FXSKS:
02601 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02602 ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
02603 p->polaritydelaytv = ast_tvnow();
02604 }
02605
02606 case SIG_EMWINK:
02607 case SIG_EM:
02608 case SIG_EM_E1:
02609 case SIG_FEATD:
02610 case SIG_FEATDMF:
02611 case SIG_E911:
02612 case SIG_FGC_CAMA:
02613 case SIG_FGC_CAMAMF:
02614 case SIG_FEATB:
02615 case SIG_SFWINK:
02616 case SIG_SF:
02617 case SIG_SF_FEATD:
02618 case SIG_SF_FEATDMF:
02619 case SIG_FEATDMF_TA:
02620 case SIG_SF_FEATB:
02621 c = strchr(dest, '/');
02622 if (c)
02623 c++;
02624 else
02625 c = "";
02626 if (strlen(c) < p->stripmsd) {
02627 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02628 ast_mutex_unlock(&p->lock);
02629 return -1;
02630 }
02631 #ifdef HAVE_PRI
02632
02633 if (!p->pri) {
02634 #endif
02635 x = DAHDI_START;
02636 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02637 if (res < 0) {
02638 if (errno != EINPROGRESS) {
02639 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02640 ast_mutex_unlock(&p->lock);
02641 return -1;
02642 }
02643 }
02644 #ifdef HAVE_PRI
02645 }
02646 #endif
02647 ast_debug(1, "Dialing '%s'\n", c);
02648 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02649
02650 c += p->stripmsd;
02651
02652 switch (mysig) {
02653 case SIG_FEATD:
02654 l = ast->cid.cid_num;
02655 if (l)
02656 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02657 else
02658 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02659 break;
02660 case SIG_FEATDMF:
02661 l = ast->cid.cid_num;
02662 if (l)
02663 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02664 else
02665 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02666 break;
02667 case SIG_FEATDMF_TA:
02668 {
02669 const char *cic, *ozz;
02670
02671
02672 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02673 if (!ozz)
02674 ozz = defaultozz;
02675 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02676 if (!cic)
02677 cic = defaultcic;
02678 if (!ozz || !cic) {
02679 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02680 ast_mutex_unlock(&p->lock);
02681 return -1;
02682 }
02683 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02684 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02685 p->whichwink = 0;
02686 }
02687 break;
02688 case SIG_E911:
02689 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02690 break;
02691 case SIG_FGC_CAMA:
02692 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02693 break;
02694 case SIG_FGC_CAMAMF:
02695 case SIG_FEATB:
02696 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02697 break;
02698 default:
02699 if (p->pulse)
02700 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02701 else
02702 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02703 break;
02704 }
02705
02706 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02707 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02708 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02709 p->echorest[sizeof(p->echorest) - 1] = '\0';
02710 p->echobreak = 1;
02711 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02712 } else
02713 p->echobreak = 0;
02714 if (!res) {
02715 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02716 int saveerr = errno;
02717
02718 x = DAHDI_ONHOOK;
02719 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02720 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02721 ast_mutex_unlock(&p->lock);
02722 return -1;
02723 }
02724 } else
02725 ast_debug(1, "Deferring dialing...\n");
02726
02727 p->dialing = 1;
02728 if (ast_strlen_zero(c))
02729 p->dialednone = 1;
02730 ast_setstate(ast, AST_STATE_DIALING);
02731 break;
02732 case 0:
02733
02734 ast_setstate(ast, AST_STATE_UP);
02735 break;
02736 case SIG_PRI:
02737 case SIG_BRI:
02738 case SIG_BRI_PTMP:
02739 case SIG_SS7:
02740
02741 p->dialdest[0] = '\0';
02742 p->dialing = 1;
02743 break;
02744 default:
02745 ast_debug(1, "not yet implemented\n");
02746 ast_mutex_unlock(&p->lock);
02747 return -1;
02748 }
02749 #ifdef HAVE_SS7
02750 if (p->ss7) {
02751 char ss7_called_nai;
02752 int called_nai_strip;
02753 char ss7_calling_nai;
02754 int calling_nai_strip;
02755 const char *charge_str = NULL;
02756 const char *gen_address = NULL;
02757 const char *gen_digits = NULL;
02758 const char *gen_dig_type = NULL;
02759 const char *gen_dig_scheme = NULL;
02760 const char *gen_name = NULL;
02761 const char *jip_digits = NULL;
02762 const char *lspi_ident = NULL;
02763 const char *rlt_flag = NULL;
02764 const char *call_ref_id = NULL;
02765 const char *call_ref_pc = NULL;
02766 const char *send_far = NULL;
02767
02768 c = strchr(dest, '/');
02769 if (c) {
02770 c++;
02771 } else {
02772 c = "";
02773 }
02774 if (strlen(c) < p->stripmsd) {
02775 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02776 ast_mutex_unlock(&p->lock);
02777 return -1;
02778 }
02779
02780 if (!p->hidecallerid) {
02781 l = ast->cid.cid_num;
02782 } else {
02783 l = NULL;
02784 }
02785
02786 if (ss7_grab(p, p->ss7)) {
02787 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02788 ast_mutex_unlock(&p->lock);
02789 return -1;
02790 }
02791 p->digital = IS_DIGITAL(ast->transfercapability);
02792 p->ss7call = isup_new_call(p->ss7->ss7);
02793
02794 if (!p->ss7call) {
02795 ss7_rel(p->ss7);
02796 ast_mutex_unlock(&p->lock);
02797 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02798 return -1;
02799 }
02800
02801 called_nai_strip = 0;
02802 ss7_called_nai = p->ss7->called_nai;
02803 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
02804 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02805 called_nai_strip = strlen(p->ss7->internationalprefix);
02806 ss7_called_nai = SS7_NAI_INTERNATIONAL;
02807 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02808 called_nai_strip = strlen(p->ss7->nationalprefix);
02809 ss7_called_nai = SS7_NAI_NATIONAL;
02810 } else {
02811 ss7_called_nai = SS7_NAI_SUBSCRIBER;
02812 }
02813 }
02814 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02815
02816 calling_nai_strip = 0;
02817 ss7_calling_nai = p->ss7->calling_nai;
02818 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
02819 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02820 calling_nai_strip = strlen(p->ss7->internationalprefix);
02821 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02822 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02823 calling_nai_strip = strlen(p->ss7->nationalprefix);
02824 ss7_calling_nai = SS7_NAI_NATIONAL;
02825 } else {
02826 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02827 }
02828 }
02829 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02830 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02831 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02832
02833 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02834 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02835
02836 ast_channel_lock(ast);
02837
02838 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02839 if (charge_str)
02840 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02841
02842 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02843 if (gen_address)
02844 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);
02845
02846 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02847 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02848 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02849 if (gen_digits)
02850 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
02851
02852 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02853 if (gen_name)
02854 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02855
02856 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02857 if (jip_digits)
02858 isup_set_jip_digits(p->ss7call, jip_digits);
02859
02860 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02861 if (lspi_ident)
02862 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
02863
02864 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02865 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02866 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
02867 }
02868
02869 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02870 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02871 if (call_ref_id && call_ref_pc) {
02872 isup_set_callref(p->ss7call, atoi(call_ref_id),
02873 call_ref_pc ? atoi(call_ref_pc) : 0);
02874 }
02875
02876 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02877 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02878 (isup_far(p->ss7->ss7, p->ss7call));
02879
02880 ast_channel_unlock(ast);
02881
02882 isup_iam(p->ss7->ss7, p->ss7call);
02883 ast_setstate(ast, AST_STATE_DIALING);
02884 ss7_rel(p->ss7);
02885 }
02886 #endif
02887 #ifdef HAVE_PRI
02888 if (p->pri) {
02889 struct pri_sr *sr;
02890 #ifdef SUPPORT_USERUSER
02891 const char *useruser;
02892 #endif
02893 int pridialplan;
02894 int dp_strip;
02895 int prilocaldialplan;
02896 int ldp_strip;
02897 int exclusive;
02898 const char *rr_str;
02899 int redirect_reason;
02900
02901 c = strchr(dest, '/');
02902 if (c) {
02903 c++;
02904 } else {
02905 c = "";
02906 }
02907
02908 l = NULL;
02909 n = NULL;
02910 if (!p->hidecallerid) {
02911 l = ast->cid.cid_num;
02912 if (!p->hidecalleridname) {
02913 n = ast->cid.cid_name;
02914 }
02915 }
02916
02917 if (strlen(c) < p->stripmsd) {
02918 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02919 ast_mutex_unlock(&p->lock);
02920 return -1;
02921 }
02922 if (mysig != SIG_FXSKS) {
02923 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02924 s = strchr(c + p->stripmsd, 'w');
02925 if (s) {
02926 if (strlen(s) > 1)
02927 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02928 else
02929 p->dop.dialstr[0] = '\0';
02930 *s = '\0';
02931 } else {
02932 p->dop.dialstr[0] = '\0';
02933 }
02934 }
02935 if (pri_grab(p, p->pri)) {
02936 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02937 ast_mutex_unlock(&p->lock);
02938 return -1;
02939 }
02940 if (!(p->call = pri_new_call(p->pri->pri))) {
02941 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02942 pri_rel(p->pri);
02943 ast_mutex_unlock(&p->lock);
02944 return -1;
02945 }
02946 if (!(sr = pri_sr_new())) {
02947 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02948 pri_rel(p->pri);
02949 ast_mutex_unlock(&p->lock);
02950 }
02951 if (p->bearer || (mysig == SIG_FXSKS)) {
02952 if (p->bearer) {
02953 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02954 p->bearer->call = p->call;
02955 } else
02956 ast_debug(1, "I'm being setup with no bearer right now...\n");
02957
02958 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02959 }
02960 p->digital = IS_DIGITAL(ast->transfercapability);
02961
02962
02963 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
02964 exclusive = 1;
02965 } else {
02966 exclusive = 0;
02967 }
02968
02969 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02970 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02971 (p->digital ? -1 :
02972 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02973 if (p->pri->facilityenable)
02974 pri_facility_enable(p->pri->pri);
02975
02976 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02977 dp_strip = 0;
02978 pridialplan = p->pri->dialplan - 1;
02979 if (pridialplan == -2 || pridialplan == -3) {
02980 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02981 if (pridialplan == -2) {
02982 dp_strip = strlen(p->pri->internationalprefix);
02983 }
02984 pridialplan = PRI_INTERNATIONAL_ISDN;
02985 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02986 if (pridialplan == -2) {
02987 dp_strip = strlen(p->pri->nationalprefix);
02988 }
02989 pridialplan = PRI_NATIONAL_ISDN;
02990 } else {
02991 pridialplan = PRI_LOCAL_ISDN;
02992 }
02993 }
02994 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02995 switch (c[p->stripmsd]) {
02996 case 'U':
02997 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02998 break;
02999 case 'I':
03000 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03001 break;
03002 case 'N':
03003 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03004 break;
03005 case 'L':
03006 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03007 break;
03008 case 'S':
03009 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03010 break;
03011 case 'V':
03012 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03013 break;
03014 case 'R':
03015 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03016 break;
03017 case 'u':
03018 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03019 break;
03020 case 'e':
03021 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03022 break;
03023 case 'x':
03024 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03025 break;
03026 case 'f':
03027 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03028 break;
03029 case 'n':
03030 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03031 break;
03032 case 'p':
03033 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03034 break;
03035 case 'r':
03036 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03037 break;
03038 default:
03039 if (isalpha(c[p->stripmsd])) {
03040 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03041 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03042 }
03043 break;
03044 }
03045 c++;
03046 }
03047 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03048
03049 ldp_strip = 0;
03050 prilocaldialplan = p->pri->localdialplan - 1;
03051 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03052 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03053 if (prilocaldialplan == -2) {
03054 ldp_strip = strlen(p->pri->internationalprefix);
03055 }
03056 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03057 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03058 if (prilocaldialplan == -2) {
03059 ldp_strip = strlen(p->pri->nationalprefix);
03060 }
03061 prilocaldialplan = PRI_NATIONAL_ISDN;
03062 } else {
03063 prilocaldialplan = PRI_LOCAL_ISDN;
03064 }
03065 }
03066 if (l != NULL) {
03067 while (*l > '9' && *l != '*' && *l != '#') {
03068 switch (*l) {
03069 case 'U':
03070 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03071 break;
03072 case 'I':
03073 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03074 break;
03075 case 'N':
03076 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03077 break;
03078 case 'L':
03079 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03080 break;
03081 case 'S':
03082 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03083 break;
03084 case 'V':
03085 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03086 break;
03087 case 'R':
03088 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03089 break;
03090 case 'u':
03091 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03092 break;
03093 case 'e':
03094 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03095 break;
03096 case 'x':
03097 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03098 break;
03099 case 'f':
03100 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03101 break;
03102 case 'n':
03103 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03104 break;
03105 case 'p':
03106 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03107 break;
03108 case 'r':
03109 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03110 break;
03111 default:
03112 if (isalpha(*l)) {
03113 ast_log(LOG_WARNING,
03114 "Unrecognized prilocaldialplan %s modifier: %c\n",
03115 *l > 'Z' ? "NPI" : "TON", *l);
03116 }
03117 break;
03118 }
03119 l++;
03120 }
03121 }
03122 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03123 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03124 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03125 if (!strcasecmp(rr_str, "UNKNOWN"))
03126 redirect_reason = 0;
03127 else if (!strcasecmp(rr_str, "BUSY"))
03128 redirect_reason = 1;
03129 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03130
03131 redirect_reason = 2;
03132 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03133 redirect_reason = 15;
03134 else
03135 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03136 } else
03137 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03138 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03139
03140 #ifdef SUPPORT_USERUSER
03141
03142 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03143
03144 if (useruser)
03145 pri_sr_set_useruser(sr, useruser);
03146 #endif
03147
03148 if (pri_setup(p->pri->pri, p->call, sr)) {
03149 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03150 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03151 pri_rel(p->pri);
03152 ast_mutex_unlock(&p->lock);
03153 pri_sr_free(sr);
03154 return -1;
03155 }
03156 pri_sr_free(sr);
03157 ast_setstate(ast, AST_STATE_DIALING);
03158 pri_rel(p->pri);
03159 }
03160 #endif
03161 ast_mutex_unlock(&p->lock);
03162 return 0;
03163 }
03164
03165 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03166 {
03167 struct dahdi_pvt *p = *pvt;
03168
03169 if (p->prev)
03170 p->prev->next = p->next;
03171 if (p->next)
03172 p->next->prev = p->prev;
03173 if (p->use_smdi)
03174 ast_smdi_interface_unref(p->smdi_iface);
03175 if (p->mwi_event_sub)
03176 ast_event_unsubscribe(p->mwi_event_sub);
03177 if (p->vars) {
03178 ast_variables_destroy(p->vars);
03179 }
03180 ast_mutex_destroy(&p->lock);
03181 dahdi_close_sub(p, SUB_REAL);
03182 if (p->owner)
03183 p->owner->tech_pvt = NULL;
03184 free(p);
03185 *pvt = NULL;
03186 }
03187
03188 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03189 {
03190 int owned = 0;
03191 int i = 0;
03192
03193 if (!now) {
03194 if (cur->owner) {
03195 owned = 1;
03196 }
03197
03198 for (i = 0; i < 3; i++) {
03199 if (cur->subs[i].owner) {
03200 owned = 1;
03201 }
03202 }
03203 if (!owned) {
03204 if (prev) {
03205 prev->next = cur->next;
03206 if (prev->next)
03207 prev->next->prev = prev;
03208 else
03209 ifend = prev;
03210 } else {
03211 iflist = cur->next;
03212 if (iflist)
03213 iflist->prev = NULL;
03214 else
03215 ifend = NULL;
03216 }
03217 destroy_dahdi_pvt(&cur);
03218 }
03219 } else {
03220 if (prev) {
03221 prev->next = cur->next;
03222 if (prev->next)
03223 prev->next->prev = prev;
03224 else
03225 ifend = prev;
03226 } else {
03227 iflist = cur->next;
03228 if (iflist)
03229 iflist->prev = NULL;
03230 else
03231 ifend = NULL;
03232 }
03233 destroy_dahdi_pvt(&cur);
03234 }
03235 return 0;
03236 }
03237
03238 static void destroy_all_channels(void)
03239 {
03240 int x;
03241 struct dahdi_pvt *p, *pl;
03242
03243 while (num_restart_pending) {
03244 usleep(1);
03245 }
03246
03247 ast_mutex_lock(&iflock);
03248
03249 p = iflist;
03250 while (p) {
03251
03252 if (p->cidspill)
03253 ast_free(p->cidspill);
03254 pl = p;
03255 p = p->next;
03256 x = pl->channel;
03257
03258 if (pl)
03259 destroy_dahdi_pvt(&pl);
03260 if (option_verbose > 2)
03261 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03262 }
03263 iflist = NULL;
03264 ifcount = 0;
03265 ast_mutex_unlock(&iflock);
03266 }
03267
03268 #ifdef HAVE_PRI
03269 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03270
03271 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03272
03273 static char *dahdi_send_keypad_facility_descrip =
03274 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03275 " IE over the current channel.\n";
03276
03277 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03278 {
03279
03280 struct dahdi_pvt *p;
03281 char *digits = (char *) data;
03282
03283 if (ast_strlen_zero(digits)) {
03284 ast_debug(1, "No digit string sent to application!\n");
03285 return -1;
03286 }
03287
03288 p = (struct dahdi_pvt *)chan->tech_pvt;
03289
03290 if (!p) {
03291 ast_debug(1, "Unable to find technology private\n");
03292 return -1;
03293 }
03294
03295 ast_mutex_lock(&p->lock);
03296
03297 if (!p->pri || !p->call) {
03298 ast_debug(1, "Unable to find pri or call on channel!\n");
03299 ast_mutex_unlock(&p->lock);
03300 return -1;
03301 }
03302
03303 if (!pri_grab(p, p->pri)) {
03304 pri_keypad_facility(p->pri->pri, p->call, digits);
03305 pri_rel(p->pri);
03306 } else {
03307 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03308 ast_mutex_unlock(&p->lock);
03309 return -1;
03310 }
03311
03312 ast_mutex_unlock(&p->lock);
03313
03314 return 0;
03315 }
03316
03317 static int pri_is_up(struct dahdi_pri *pri)
03318 {
03319 int x;
03320 for (x = 0; x < NUM_DCHANS; x++) {
03321 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03322 return 1;
03323 }
03324 return 0;
03325 }
03326
03327 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03328 {
03329 bearer->owner = &inuse;
03330 bearer->realcall = crv;
03331 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03332 if (crv->subs[SUB_REAL].owner)
03333 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03334 crv->bearer = bearer;
03335 crv->call = bearer->call;
03336 crv->pri = pri;
03337 return 0;
03338 }
03339
03340 static char *pri_order(int level)
03341 {
03342 switch (level) {
03343 case 0:
03344 return "Primary";
03345 case 1:
03346 return "Secondary";
03347 case 2:
03348 return "Tertiary";
03349 case 3:
03350 return "Quaternary";
03351 default:
03352 return "<Unknown>";
03353 }
03354 }
03355
03356
03357 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03358 {
03359 int x = -1;
03360
03361 for (x = 0; x < NUM_DCHANS; x++) {
03362 if ((pri->dchans[x] == pri->pri))
03363 break;
03364 }
03365
03366 return pri->fds[x];
03367 }
03368
03369 static int pri_find_dchan(struct dahdi_pri *pri)
03370 {
03371 int oldslot = -1;
03372 struct pri *old;
03373 int newslot = -1;
03374 int x;
03375 old = pri->pri;
03376 for (x = 0; x < NUM_DCHANS; x++) {
03377 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03378 newslot = x;
03379 if (pri->dchans[x] == old) {
03380 oldslot = x;
03381 }
03382 }
03383 if (newslot < 0) {
03384 newslot = 0;
03385 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03386 pri->dchannels[newslot]);
03387 }
03388 if (old && (oldslot != newslot))
03389 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03390 pri->dchannels[oldslot], pri->dchannels[newslot]);
03391 pri->pri = pri->dchans[newslot];
03392 return 0;
03393 }
03394 #endif
03395
03396 static int dahdi_hangup(struct ast_channel *ast)
03397 {
03398 int res;
03399 int idx,x, law;
03400
03401 struct dahdi_pvt *p = ast->tech_pvt;
03402 struct dahdi_pvt *tmp = NULL;
03403 struct dahdi_pvt *prev = NULL;
03404 struct dahdi_params par;
03405
03406 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03407 if (!ast->tech_pvt) {
03408 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03409 return 0;
03410 }
03411
03412 ast_mutex_lock(&p->lock);
03413
03414 idx = dahdi_get_index(ast, p, 1);
03415
03416 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03417 x = 1;
03418 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03419 p->cid_num[0] = '\0';
03420 p->cid_name[0] = '\0';
03421 }
03422
03423 x = 0;
03424 dahdi_confmute(p, 0);
03425 p->muting = 0;
03426 restore_gains(p);
03427 if (p->origcid_num) {
03428 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03429 ast_free(p->origcid_num);
03430 p->origcid_num = NULL;
03431 }
03432 if (p->origcid_name) {
03433 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03434 ast_free(p->origcid_name);
03435 p->origcid_name = NULL;
03436 }
03437 if (p->dsp)
03438 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03439 p->exten[0] = '\0';
03440
03441 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03442 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03443 p->ignoredtmf = 0;
03444
03445 if (idx > -1) {
03446
03447 p->subs[idx].owner = NULL;
03448 p->subs[idx].needanswer = 0;
03449 p->subs[idx].needflash = 0;
03450 p->subs[idx].needringing = 0;
03451 p->subs[idx].needbusy = 0;
03452 p->subs[idx].needcongestion = 0;
03453 p->subs[idx].linear = 0;
03454 p->subs[idx].needcallerid = 0;
03455 p->polarity = POLARITY_IDLE;
03456 dahdi_setlinear(p->subs[idx].dfd, 0);
03457 if (idx == SUB_REAL) {
03458 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03459 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03460 if (p->subs[SUB_CALLWAIT].inthreeway) {
03461
03462 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03463
03464 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03465 unalloc_sub(p, SUB_CALLWAIT);
03466 p->owner = NULL;
03467 } else {
03468
03469 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03470 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03471 unalloc_sub(p, SUB_THREEWAY);
03472 if (p->subs[SUB_REAL].inthreeway) {
03473
03474
03475 ast_debug(1, "Call was complete, setting owner to former third call\n");
03476 p->owner = p->subs[SUB_REAL].owner;
03477 } else {
03478
03479 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03480 p->owner = NULL;
03481 }
03482 p->subs[SUB_REAL].inthreeway = 0;
03483 }
03484 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03485
03486 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03487 unalloc_sub(p, SUB_CALLWAIT);
03488 p->owner = p->subs[SUB_REAL].owner;
03489 if (p->owner->_state != AST_STATE_UP)
03490 p->subs[SUB_REAL].needanswer = 1;
03491 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03492 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03493 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03494 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03495 unalloc_sub(p, SUB_THREEWAY);
03496 if (p->subs[SUB_REAL].inthreeway) {
03497
03498
03499 ast_debug(1, "Call was complete, setting owner to former third call\n");
03500 p->owner = p->subs[SUB_REAL].owner;
03501 } else {
03502
03503 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03504 p->owner = NULL;
03505 }
03506 p->subs[SUB_REAL].inthreeway = 0;
03507 }
03508 } else if (idx == SUB_CALLWAIT) {
03509
03510 if (p->subs[SUB_CALLWAIT].inthreeway) {
03511
03512
03513 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03514 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03515 S_OR(p->mohsuggest, NULL),
03516 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03517 }
03518 p->subs[SUB_THREEWAY].inthreeway = 0;
03519
03520 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03521 unalloc_sub(p, SUB_THREEWAY);
03522 } else
03523 unalloc_sub(p, SUB_CALLWAIT);
03524 } else if (idx == SUB_THREEWAY) {
03525 if (p->subs[SUB_CALLWAIT].inthreeway) {
03526
03527
03528 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03529 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03530 S_OR(p->mohsuggest, NULL),
03531 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03532 }
03533 p->subs[SUB_CALLWAIT].inthreeway = 0;
03534 }
03535 p->subs[SUB_REAL].inthreeway = 0;
03536
03537
03538 unalloc_sub(p, SUB_THREEWAY);
03539 } else {
03540
03541 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03542 }
03543 }
03544
03545 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03546 p->owner = NULL;
03547 p->ringt = 0;
03548 p->distinctivering = 0;
03549 p->confirmanswer = 0;
03550 p->cidrings = 1;
03551 p->outgoing = 0;
03552 p->digital = 0;
03553 p->faxhandled = 0;
03554 p->pulsedial = 0;
03555 p->onhooktime = time(NULL);
03556 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03557 p->proceeding = 0;
03558 p->dialing = 0;
03559 p->progress = 0;
03560 p->alerting = 0;
03561 p->setup_ack = 0;
03562 p->rlt = 0;
03563 #endif
03564 if (p->dsp) {
03565 ast_dsp_free(p->dsp);
03566 p->dsp = NULL;
03567 }
03568
03569 law = DAHDI_LAW_DEFAULT;
03570 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03571 if (res < 0)
03572 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03573
03574 #ifdef HAVE_SS7
03575 if (p->ss7) {
03576 if (p->ss7call) {
03577 if (!ss7_grab(p, p->ss7)) {
03578 if (!p->alreadyhungup) {
03579 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03580 int icause = ast->hangupcause ? ast->hangupcause : -1;
03581
03582 if (cause) {
03583 if (atoi(cause))
03584 icause = atoi(cause);
03585 }
03586 isup_rel(p->ss7->ss7, p->ss7call, icause);
03587 ss7_rel(p->ss7);
03588 p->alreadyhungup = 1;
03589 } else
03590 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03591 } else {
03592 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03593 res = -1;
03594 }
03595 }
03596 }
03597 #endif
03598 #ifdef HAVE_PRI
03599 if (p->pri) {
03600 #ifdef SUPPORT_USERUSER
03601 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03602 #endif
03603
03604
03605 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03606 if (!pri_grab(p, p->pri)) {
03607 if (p->alreadyhungup) {
03608 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
03609
03610 #ifdef SUPPORT_USERUSER
03611 pri_call_set_useruser(p->call, useruser);
03612 #endif
03613
03614 pri_hangup(p->pri->pri, p->call, -1);
03615 p->call = NULL;
03616 if (p->bearer)
03617 p->bearer->call = NULL;
03618 } else {
03619 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03620 int icause = ast->hangupcause ? ast->hangupcause : -1;
03621 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03622
03623 #ifdef SUPPORT_USERUSER
03624 pri_call_set_useruser(p->call, useruser);
03625 #endif
03626
03627 p->alreadyhungup = 1;
03628 if (p->bearer)
03629 p->bearer->alreadyhungup = 1;
03630 if (cause) {
03631 if (atoi(cause))
03632 icause = atoi(cause);
03633 }
03634 pri_hangup(p->pri->pri, p->call, icause);
03635 }
03636 if (res < 0)
03637 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03638 pri_rel(p->pri);
03639 } else {
03640 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03641 res = -1;
03642 }
03643 } else {
03644 if (p->bearer)
03645 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03646 p->call = NULL;
03647 res = 0;
03648 }
03649 }
03650 #endif
03651 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03652 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03653 if (res < 0) {
03654 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03655 }
03656 switch (p->sig) {
03657 case SIG_FXOGS:
03658 case SIG_FXOLS:
03659 case SIG_FXOKS:
03660 memset(&par, 0, sizeof(par));
03661 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03662 if (!res) {
03663 #if 0
03664 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03665 #endif
03666
03667 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03668 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03669 else
03670 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03671 }
03672 break;
03673 case SIG_FXSGS:
03674 case SIG_FXSLS:
03675 case SIG_FXSKS:
03676
03677
03678 if (ast->_state != AST_STATE_RESERVED) {
03679 time(&p->guardtime);
03680 p->guardtime += 2;
03681 }
03682 break;
03683 default:
03684 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03685 }
03686 if (p->cidspill)
03687 ast_free(p->cidspill);
03688 if (p->sig)
03689 dahdi_disable_ec(p);
03690 x = 0;
03691 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03692 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03693 p->didtdd = 0;
03694 p->cidspill = NULL;
03695 p->callwaitcas = 0;
03696 p->callwaiting = p->permcallwaiting;
03697 p->hidecallerid = p->permhidecallerid;
03698 p->dialing = 0;
03699 p->rdnis[0] = '\0';
03700 update_conf(p);
03701 reset_conf(p);
03702
03703 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03704 x = 0;
03705 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03706 }
03707 #ifdef HAVE_PRI
03708 if (p->bearer) {
03709 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03710
03711
03712 update_conf(p->bearer);
03713 reset_conf(p->bearer);
03714 p->bearer->owner = NULL;
03715 p->bearer->realcall = NULL;
03716 p->bearer = NULL;
03717 p->subs[SUB_REAL].dfd = -1;
03718 p->pri = NULL;
03719 }
03720 #endif
03721 if (num_restart_pending == 0)
03722 restart_monitor();
03723 }
03724
03725 p->callwaitingrepeat = 0;
03726 p->cidcwexpire = 0;
03727 p->oprmode = 0;
03728 ast->tech_pvt = NULL;
03729 ast_mutex_unlock(&p->lock);
03730 ast_module_unref(ast_module_info->self);
03731 ast_verb(3, "Hungup '%s'\n", ast->name);
03732
03733 ast_mutex_lock(&iflock);
03734
03735 if (p->restartpending) {
03736 num_restart_pending--;
03737 }
03738
03739 tmp = iflist;
03740 prev = NULL;
03741 if (p->destroy) {
03742 while (tmp) {
03743 if (tmp == p) {
03744 destroy_channel(prev, tmp, 0);
03745 break;
03746 } else {
03747 prev = tmp;
03748 tmp = tmp->next;
03749 }
03750 }
03751 }
03752 ast_mutex_unlock(&iflock);
03753 return 0;
03754 }
03755
03756 static int dahdi_answer(struct ast_channel *ast)
03757 {
03758 struct dahdi_pvt *p = ast->tech_pvt;
03759 int res = 0;
03760 int idx;
03761 int oldstate = ast->_state;
03762 ast_setstate(ast, AST_STATE_UP);
03763 ast_mutex_lock(&p->lock);
03764 idx = dahdi_get_index(ast, p, 0);
03765 if (idx < 0)
03766 idx = SUB_REAL;
03767
03768 if ((p->radio || (p->oprmode < 0))) {
03769 ast_mutex_unlock(&p->lock);
03770 return 0;
03771 }
03772 switch (p->sig) {
03773 case SIG_FXSLS:
03774 case SIG_FXSGS:
03775 case SIG_FXSKS:
03776 p->ringt = 0;
03777
03778 case SIG_EM:
03779 case SIG_EM_E1:
03780 case SIG_EMWINK:
03781 case SIG_FEATD:
03782 case SIG_FEATDMF:
03783 case SIG_FEATDMF_TA:
03784 case SIG_E911:
03785 case SIG_FGC_CAMA:
03786 case SIG_FGC_CAMAMF:
03787 case SIG_FEATB:
03788 case SIG_SF:
03789 case SIG_SFWINK:
03790 case SIG_SF_FEATD:
03791 case SIG_SF_FEATDMF:
03792 case SIG_SF_FEATB:
03793 case SIG_FXOLS:
03794 case SIG_FXOGS:
03795 case SIG_FXOKS:
03796
03797 ast_debug(1, "Took %s off hook\n", ast->name);
03798 if (p->hanguponpolarityswitch) {
03799 p->polaritydelaytv = ast_tvnow();
03800 }
03801 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03802 tone_zone_play_tone(p->subs[idx].dfd, -1);
03803 p->dialing = 0;
03804 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03805 if (oldstate == AST_STATE_RINGING) {
03806 ast_debug(1, "Finally swapping real and threeway\n");
03807 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03808 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03809 p->owner = p->subs[SUB_REAL].owner;
03810 }
03811 }
03812 if (p->sig & __DAHDI_SIG_FXS) {
03813 dahdi_enable_ec(p);
03814 dahdi_train_ec(p);
03815 }
03816 break;
03817 #ifdef HAVE_PRI
03818 case SIG_BRI:
03819 case SIG_BRI_PTMP:
03820 case SIG_PRI:
03821
03822 if (!pri_grab(p, p->pri)) {
03823 p->proceeding = 1;
03824 p->dialing = 0;
03825 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03826 pri_rel(p->pri);
03827 } else {
03828 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03829 res = -1;
03830 }
03831 break;
03832 #endif
03833 #ifdef HAVE_SS7
03834 case SIG_SS7:
03835 if (!ss7_grab(p, p->ss7)) {
03836 p->proceeding = 1;
03837 res = isup_anm(p->ss7->ss7, p->ss7call);
03838 ss7_rel(p->ss7);
03839 } else {
03840 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03841 res = -1;
03842 }
03843 break;
03844 #endif
03845 case 0:
03846 ast_mutex_unlock(&p->lock);
03847 return 0;
03848 default:
03849 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03850 res = -1;
03851 }
03852 ast_mutex_unlock(&p->lock);
03853 return res;
03854 }
03855
03856 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03857 {
03858 char *cp;
03859 signed char *scp;
03860 int x;
03861 int idx;
03862 struct dahdi_pvt *p = chan->tech_pvt, *pp;
03863 struct oprmode *oprmode;
03864
03865
03866
03867 if (!data || (datalen < 1)) {
03868 errno = EINVAL;
03869 return -1;
03870 }
03871
03872 switch (option) {
03873 case AST_OPTION_TXGAIN:
03874 scp = (signed char *) data;
03875 idx = dahdi_get_index(chan, p, 0);
03876 if (idx < 0) {
03877 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03878 return -1;
03879 }
03880 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03881 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
03882 case AST_OPTION_RXGAIN:
03883 scp = (signed char *) data;
03884 idx = dahdi_get_index(chan, p, 0);
03885 if (idx < 0) {
03886 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03887 return -1;
03888 }
03889 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03890 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
03891 case AST_OPTION_TONE_VERIFY:
03892 if (!p->dsp)
03893 break;
03894 cp = (char *) data;
03895 switch (*cp) {
03896 case 1:
03897 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03898 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
03899 break;
03900 case 2:
03901 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03902 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
03903 break;
03904 default:
03905 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03906 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03907 break;
03908 }
03909 break;
03910 case AST_OPTION_TDD:
03911
03912 cp = (char *) data;
03913 p->mate = 0;
03914 if (!*cp) {
03915 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03916 if (p->tdd)
03917 tdd_free(p->tdd);
03918 p->tdd = 0;
03919 break;
03920 }
03921 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03922 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03923 dahdi_disable_ec(p);
03924
03925 if (!p->didtdd) {
03926 unsigned char mybuf[41000];
03927 unsigned char *buf;
03928 int size, res, fd, len;
03929 struct pollfd fds[1];
03930
03931 buf = mybuf;
03932 memset(buf, 0x7f, sizeof(mybuf));
03933 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03934 len = 40000;
03935 idx = dahdi_get_index(chan, p, 0);
03936 if (idx < 0) {
03937 ast_log(LOG_WARNING, "No index in TDD?\n");
03938 return -1;
03939 }
03940 fd = p->subs[idx].dfd;
03941 while (len) {
03942 if (ast_check_hangup(chan))
03943 return -1;
03944 size = len;
03945 if (size > READ_SIZE)
03946 size = READ_SIZE;
03947 fds[0].fd = fd;
03948 fds[0].events = POLLPRI | POLLOUT;
03949 fds[0].revents = 0;
03950 res = poll(fds, 1, -1);
03951 if (!res) {
03952 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03953 continue;
03954 }
03955
03956 if (fds[0].revents & POLLPRI)
03957 return -1;
03958 if (!(fds[0].revents & POLLOUT)) {
03959 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03960 continue;
03961 }
03962 res = write(fd, buf, size);
03963 if (res != size) {
03964 if (res == -1) return -1;
03965 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03966 break;
03967 }
03968 len -= size;
03969 buf += size;
03970 }
03971 p->didtdd = 1;
03972 }
03973 if (*cp == 2) {
03974 if (p->tdd)
03975 tdd_free(p->tdd);
03976 p->tdd = 0;
03977 p->mate = 1;
03978 break;
03979 }
03980 if (!p->tdd) {
03981 p->tdd = tdd_new();
03982 }
03983 break;
03984 case AST_OPTION_RELAXDTMF:
03985 if (!p->dsp)
03986 break;
03987 cp = (char *) data;
03988 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03989 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03990 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03991 break;
03992 case AST_OPTION_AUDIO_MODE:
03993 cp = (char *) data;
03994 if (!*cp) {
03995 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03996 x = 0;
03997 dahdi_disable_ec(p);
03998 } else {
03999 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04000 x = 1;
04001 }
04002 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04003 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04004 break;
04005 case AST_OPTION_OPRMODE:
04006 oprmode = (struct oprmode *) data;
04007 pp = oprmode->peer->tech_pvt;
04008 p->oprmode = pp->oprmode = 0;
04009
04010 p->oprpeer = pp;
04011 pp->oprpeer = p;
04012
04013 if (oprmode->mode)
04014 {
04015 pp->oprmode = oprmode->mode;
04016 p->oprmode = -oprmode->mode;
04017 }
04018 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
04019 oprmode->mode, chan->name,oprmode->peer->name);
04020 break;
04021 case AST_OPTION_ECHOCAN:
04022 cp = (char *) data;
04023 if (*cp) {
04024 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
04025 dahdi_enable_ec(p);
04026 } else {
04027 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
04028 dahdi_disable_ec(p);
04029 }
04030 break;
04031 }
04032 errno = 0;
04033
04034 return 0;
04035 }
04036
04037 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
04038 {
04039 struct dahdi_pvt *p = chan->tech_pvt;
04040
04041 if (!strcasecmp(data, "rxgain")) {
04042 ast_mutex_lock(&p->lock);
04043 snprintf(buf, len, "%f", p->rxgain);
04044 ast_mutex_unlock(&p->lock);
04045 } else if (!strcasecmp(data, "txgain")) {
04046 ast_mutex_lock(&p->lock);
04047 snprintf(buf, len, "%f", p->txgain);
04048 ast_mutex_unlock(&p->lock);
04049 } else {
04050 ast_copy_string(buf, "", len);
04051 }
04052 return 0;
04053 }
04054
04055
04056 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04057 {
04058
04059 int x;
04060 int hasslaves;
04061 if (!master)
04062 return;
04063 if (needlock) {
04064 ast_mutex_lock(&master->lock);
04065 if (slave) {
04066 while (ast_mutex_trylock(&slave->lock)) {
04067 DEADLOCK_AVOIDANCE(&master->lock);
04068 }
04069 }
04070 }
04071 hasslaves = 0;
04072 for (x = 0; x < MAX_SLAVES; x++) {
04073 if (master->slaves[x]) {
04074 if (!slave || (master->slaves[x] == slave)) {
04075
04076 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04077 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04078 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04079 master->slaves[x]->master = NULL;
04080 master->slaves[x] = NULL;
04081 } else
04082 hasslaves = 1;
04083 }
04084 if (!hasslaves)
04085 master->inconference = 0;
04086 }
04087 if (!slave) {
04088 if (master->master) {
04089
04090 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04091 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04092 hasslaves = 0;
04093 for (x = 0; x < MAX_SLAVES; x++) {
04094 if (master->master->slaves[x] == master)
04095 master->master->slaves[x] = NULL;
04096 else if (master->master->slaves[x])
04097 hasslaves = 1;
04098 }
04099 if (!hasslaves)
04100 master->master->inconference = 0;
04101 }
04102 master->master = NULL;
04103 }
04104 update_conf(master);
04105 if (needlock) {
04106 if (slave)
04107 ast_mutex_unlock(&slave->lock);
04108 ast_mutex_unlock(&master->lock);
04109 }
04110 }
04111
04112 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04113 int x;
04114 if (!slave || !master) {
04115 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04116 return;
04117 }
04118 for (x = 0; x < MAX_SLAVES; x++) {
04119 if (!master->slaves[x]) {
04120 master->slaves[x] = slave;
04121 break;
04122 }
04123 }
04124 if (x >= MAX_SLAVES) {
04125 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04126 master->slaves[MAX_SLAVES - 1] = slave;
04127 }
04128 if (slave->master)
04129 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04130 slave->master = master;
04131
04132 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04133 }
04134
04135 static void disable_dtmf_detect(struct dahdi_pvt *p)
04136 {
04137 int val;
04138
04139 p->ignoredtmf = 1;
04140
04141 val = 0;
04142 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04143
04144 if (!p->hardwaredtmf && p->dsp) {
04145 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
04146 ast_dsp_set_features(p->dsp, p->dsp_features);
04147 }
04148 }
04149
04150 static void enable_dtmf_detect(struct dahdi_pvt *p)
04151 {
04152 int val;
04153
04154 if (p->channel == CHAN_PSEUDO)
04155 return;
04156
04157 p->ignoredtmf = 0;
04158
04159 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04160 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04161
04162 if (!p->hardwaredtmf && p->dsp) {
04163 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
04164 ast_dsp_set_features(p->dsp, p->dsp_features);
04165 }
04166 }
04167
04168 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)
04169 {
04170 struct ast_channel *who;
04171 struct dahdi_pvt *p0, *p1, *op0, *op1;
04172 struct dahdi_pvt *master = NULL, *slave = NULL;
04173 struct ast_frame *f;
04174 int inconf = 0;
04175 int nothingok = 1;
04176 int ofd0, ofd1;
04177 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04178 int os0 = -1, os1 = -1;
04179 int priority = 0;
04180 struct ast_channel *oc0, *oc1;
04181 enum ast_bridge_result res;
04182
04183 #ifdef PRI_2BCT
04184 int triedtopribridge = 0;
04185 #endif
04186
04187
04188
04189
04190
04191
04192 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04193 return AST_BRIDGE_FAILED_NOWARN;
04194
04195 ast_channel_lock(c0);
04196 while (ast_channel_trylock(c1)) {
04197 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04198 }
04199
04200 p0 = c0->tech_pvt;
04201 p1 = c1->tech_pvt;
04202
04203 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04204 ast_channel_unlock(c0);
04205 ast_channel_unlock(c1);
04206 return AST_BRIDGE_FAILED_NOWARN;
04207 }
04208
04209 oi0 = dahdi_get_index(c0, p0, 0);
04210 oi1 = dahdi_get_index(c1, p1, 0);
04211 if ((oi0 < 0) || (oi1 < 0)) {
04212 ast_channel_unlock(c0);
04213 ast_channel_unlock(c1);
04214 return AST_BRIDGE_FAILED;
04215 }
04216
04217 op0 = p0 = c0->tech_pvt;
04218 op1 = p1 = c1->tech_pvt;
04219 ofd0 = c0->fds[0];
04220 ofd1 = c1->fds[0];
04221 oc0 = p0->owner;
04222 oc1 = p1->owner;
04223
04224 if (ast_mutex_trylock(&p0->lock)) {
04225
04226 ast_channel_unlock(c0);
04227 ast_channel_unlock(c1);
04228 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04229 return AST_BRIDGE_RETRY;
04230 }
04231 if (ast_mutex_trylock(&p1->lock)) {
04232
04233 ast_mutex_unlock(&p0->lock);
04234 ast_channel_unlock(c0);
04235 ast_channel_unlock(c1);
04236 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04237 return AST_BRIDGE_RETRY;
04238 }
04239
04240 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04241 if (p0->owner && p1->owner) {
04242
04243 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04244 master = p0;
04245 slave = p1;
04246 inconf = 1;
04247 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04248 master = p1;
04249 slave = p0;
04250 inconf = 1;
04251 } else {
04252 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04253 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04254 p0->channel,
04255 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04256 p0->subs[SUB_REAL].inthreeway, p0->channel,
04257 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04258 p1->subs[SUB_REAL].inthreeway);
04259 }
04260 nothingok = 0;
04261 }
04262 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04263 if (p1->subs[SUB_THREEWAY].inthreeway) {
04264 master = p1;
04265 slave = p0;
04266 nothingok = 0;
04267 }
04268 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04269 if (p0->subs[SUB_THREEWAY].inthreeway) {
04270 master = p0;
04271 slave = p1;
04272 nothingok = 0;
04273 }
04274 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04275
04276
04277 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04278 master = p1;
04279 slave = p0;
04280 nothingok = 0;
04281 }
04282 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04283
04284 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04285 master = p0;
04286 slave = p1;
04287 nothingok = 0;
04288 }
04289 }
04290 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04291 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04292 if (master && slave) {
04293
04294
04295
04296 if ((oi1 == SUB_THREEWAY) &&
04297 p1->subs[SUB_THREEWAY].inthreeway &&
04298 p1->subs[SUB_REAL].owner &&
04299 p1->subs[SUB_REAL].inthreeway &&
04300 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04301 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04302 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04303 os1 = p1->subs[SUB_REAL].owner->_state;
04304 } else {
04305 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04306 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04307 }
04308 if ((oi0 == SUB_THREEWAY) &&
04309 p0->subs[SUB_THREEWAY].inthreeway &&
04310 p0->subs[SUB_REAL].owner &&
04311 p0->subs[SUB_REAL].inthreeway &&
04312 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04313 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04314 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04315 os0 = p0->subs[SUB_REAL].owner->_state;
04316 } else {
04317 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04318 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04319 }
04320 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04321 if (!p0->echocanbridged || !p1->echocanbridged) {
04322
04323 dahdi_disable_ec(p0);
04324 dahdi_disable_ec(p1);
04325 }
04326 }
04327 dahdi_link(slave, master);
04328 master->inconference = inconf;
04329 } else if (!nothingok)
04330 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04331
04332 update_conf(p0);
04333 update_conf(p1);
04334 t0 = p0->subs[SUB_REAL].inthreeway;
04335 t1 = p1->subs[SUB_REAL].inthreeway;
04336
04337 ast_mutex_unlock(&p0->lock);
04338 ast_mutex_unlock(&p1->lock);
04339
04340 ast_channel_unlock(c0);
04341 ast_channel_unlock(c1);
04342
04343
04344 if ((!master || !slave) && !nothingok) {
04345 dahdi_enable_ec(p0);
04346 dahdi_enable_ec(p1);
04347 return AST_BRIDGE_FAILED;
04348 }
04349
04350 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04351
04352 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04353 disable_dtmf_detect(op0);
04354
04355 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04356 disable_dtmf_detect(op1);
04357
04358 for (;;) {
04359 struct ast_channel *c0_priority[2] = {c0, c1};
04360 struct ast_channel *c1_priority[2] = {c1, c0};
04361
04362
04363
04364
04365 ast_channel_lock(c0);
04366 while (ast_channel_trylock(c1)) {
04367 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04368 }
04369
04370 p0 = c0->tech_pvt;
04371 p1 = c1->tech_pvt;
04372
04373 if (op0 == p0)
04374 i0 = dahdi_get_index(c0, p0, 1);
04375 if (op1 == p1)
04376 i1 = dahdi_get_index(c1, p1, 1);
04377
04378 ast_channel_unlock(c0);
04379 ast_channel_unlock(c1);
04380
04381 if (!timeoutms ||
04382 (op0 != p0) ||
04383 (op1 != p1) ||
04384 (ofd0 != c0->fds[0]) ||
04385 (ofd1 != c1->fds[0]) ||
04386 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04387 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04388 (oc0 != p0->owner) ||
04389 (oc1 != p1->owner) ||
04390 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04391 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04392 (oi0 != i0) ||
04393 (oi1 != i1)) {
04394 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04395 op0->channel, oi0, op1->channel, oi1);
04396 res = AST_BRIDGE_RETRY;
04397 goto return_from_bridge;
04398 }
04399
04400 #ifdef PRI_2BCT
04401 if (!triedtopribridge) {
04402 triedtopribridge = 1;
04403 if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
04404 ast_mutex_lock(&p0->pri->lock);
04405 if (p0->call && p1->call) {
04406 pri_channel_bridge(p0->call, p1->call);
04407 }
04408 ast_mutex_unlock(&p0->pri->lock);
04409 }
04410 }
04411 #endif
04412
04413 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04414 if (!who) {
04415 ast_debug(1, "Ooh, empty read...\n");
04416 continue;
04417 }
04418 f = ast_read(who);
04419 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04420 *fo = f;
04421 *rc = who;
04422 res = AST_BRIDGE_COMPLETE;
04423 goto return_from_bridge;
04424 }
04425 if (f->frametype == AST_FRAME_DTMF) {
04426 if ((who == c0) && p0->pulsedial) {
04427 ast_write(c1, f);
04428 } else if ((who == c1) && p1->pulsedial) {
04429 ast_write(c0, f);
04430 } else {
04431 *fo = f;
04432 *rc = who;
04433 res = AST_BRIDGE_COMPLETE;
04434 goto return_from_bridge;
04435 }
04436 }
04437 ast_frfree(f);
04438
04439
04440 priority = !priority;
04441 }
04442
04443 return_from_bridge:
04444 if (op0 == p0)
04445 dahdi_enable_ec(p0);
04446
04447 if (op1 == p1)
04448 dahdi_enable_ec(p1);
04449
04450 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04451 enable_dtmf_detect(op0);
04452
04453 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04454 enable_dtmf_detect(op1);
04455
04456 dahdi_unlink(slave, master, 1);
04457
04458 return res;
04459 }
04460
04461 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04462 {
04463 struct dahdi_pvt *p = newchan->tech_pvt;
04464 int x;
04465 ast_mutex_lock(&p->lock);
04466 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04467 if (p->owner == oldchan) {
04468 p->owner = newchan;
04469 }
04470 for (x = 0; x < 3; x++)
04471 if (p->subs[x].owner == oldchan) {
04472 if (!x)
04473 dahdi_unlink(NULL, p, 0);
04474 p->subs[x].owner = newchan;
04475 }
04476 if (newchan->_state == AST_STATE_RINGING)
04477 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04478 update_conf(p);
04479 ast_mutex_unlock(&p->lock);
04480 return 0;
04481 }
04482
04483 static int dahdi_ring_phone(struct dahdi_pvt *p)
04484 {
04485 int x;
04486 int res;
04487
04488 x = 0;
04489 x = DAHDI_ONHOOK;
04490 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04491 do {
04492 x = DAHDI_RING;
04493 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04494 if (res) {
04495 switch (errno) {
04496 case EBUSY:
04497 case EINTR:
04498
04499 usleep(10000);
04500 continue;
04501 case EINPROGRESS:
04502 res = 0;
04503 break;
04504 default:
04505 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04506 res = 0;
04507 }
04508 }
04509 } while (res);
04510 return res;
04511 }
04512
04513 static void *ss_thread(void *data);
04514
04515 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
04516
04517 static int attempt_transfer(struct dahdi_pvt *p)
04518 {
04519
04520
04521
04522 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04523
04524
04525 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04526 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04527 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04528 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04529 }
04530 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04531 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04532 }
04533 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04534 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04535 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04536 return -1;
04537 }
04538
04539 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04540 unalloc_sub(p, SUB_THREEWAY);
04541 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04542 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04543 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04544 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04545 }
04546 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04547 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04548 }
04549 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04550 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04551 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04552 return -1;
04553 }
04554
04555 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04556 ast_channel_unlock(p->subs[SUB_REAL].owner);
04557 unalloc_sub(p, SUB_THREEWAY);
04558
04559 return 1;
04560 } else {
04561 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04562 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04563 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04564 return -1;
04565 }
04566 return 0;
04567 }
04568
04569 static int check_for_conference(struct dahdi_pvt *p)
04570 {
04571 struct dahdi_confinfo ci;
04572
04573 if (p->master || (p->confno > -1))
04574 return 0;
04575 memset(&ci, 0, sizeof(ci));
04576 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04577 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04578 return 0;
04579 }
04580
04581
04582
04583 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04584 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04585 return 1;
04586 }
04587 return 0;
04588 }
04589
04590
04591
04592
04593
04594
04595 static int get_alarms(struct dahdi_pvt *p)
04596 {
04597 int res;
04598 struct dahdi_spaninfo zi;
04599 struct dahdi_params params;
04600
04601 memset(&zi, 0, sizeof(zi));
04602 zi.spanno = p->span;
04603
04604 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04605 if (zi.alarms != DAHDI_ALARM_NONE)
04606 return zi.alarms;
04607 } else {
04608 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04609 return 0;
04610 }
04611
04612
04613 memset(¶ms, 0, sizeof(params));
04614 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04615 return params.chan_alarms;
04616
04617 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04618
04619 return DAHDI_ALARM_NONE;
04620 }
04621
04622 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
04623 {
04624 struct dahdi_pvt *p = ast->tech_pvt;
04625 struct ast_frame *f = *dest;
04626
04627 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04628
04629 if (p->confirmanswer) {
04630 ast_debug(1, "Confirm answer on %s!\n", ast->name);
04631
04632
04633 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04634 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04635 *dest = &p->subs[idx].f;
04636
04637 p->confirmanswer = 0;
04638 } else if (p->callwaitcas) {
04639 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04640 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04641 if (p->cidspill)
04642 ast_free(p->cidspill);
04643 send_cwcidspill(p);
04644 }
04645 p->callwaitcas = 0;
04646 p->subs[idx].f.frametype = AST_FRAME_NULL;
04647 p->subs[idx].f.subclass = 0;
04648 *dest = &p->subs[idx].f;
04649 } else if (f->subclass == 'f') {
04650
04651 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04652 p->faxhandled = 1;
04653 if (strcmp(ast->exten, "fax")) {
04654 const char *target_context = S_OR(ast->macrocontext, ast->context);
04655
04656
04657
04658
04659
04660 ast_mutex_unlock(&p->lock);
04661 ast_channel_unlock(ast);
04662 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04663 ast_channel_lock(ast);
04664 ast_mutex_lock(&p->lock);
04665 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04666
04667 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04668 if (ast_async_goto(ast, target_context, "fax", 1))
04669 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04670 } else {
04671 ast_channel_lock(ast);
04672 ast_mutex_lock(&p->lock);
04673 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04674 }
04675 } else {
04676 ast_debug(1, "Already in a fax extension, not redirecting\n");
04677 }
04678 } else {
04679 ast_debug(1, "Fax already handled\n");
04680 }
04681 dahdi_confmute(p, 0);
04682 p->subs[idx].f.frametype = AST_FRAME_NULL;
04683 p->subs[idx].f.subclass = 0;
04684 *dest = &p->subs[idx].f;
04685 }
04686 }
04687
04688 static void handle_alarms(struct dahdi_pvt *p, int alms)
04689 {
04690 const char *alarm_str = alarm2str(alms);
04691
04692 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04693 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04694 "Alarm: %s\r\n"
04695 "Channel: %d\r\n",
04696 alarm_str, p->channel);
04697 }
04698
04699 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04700 {
04701 int res, x;
04702 int idx, mysig;
04703 char *c;
04704 struct dahdi_pvt *p = ast->tech_pvt;
04705 pthread_t threadid;
04706 struct ast_channel *chan;
04707 struct ast_frame *f;
04708
04709 idx = dahdi_get_index(ast, p, 0);
04710 mysig = p->sig;
04711 if (p->outsigmod > -1)
04712 mysig = p->outsigmod;
04713 p->subs[idx].f.frametype = AST_FRAME_NULL;
04714 p->subs[idx].f.subclass = 0;
04715 p->subs[idx].f.datalen = 0;
04716 p->subs[idx].f.samples = 0;
04717 p->subs[idx].f.mallocd = 0;
04718 p->subs[idx].f.offset = 0;
04719 p->subs[idx].f.src = "dahdi_handle_event";
04720 p->subs[idx].f.data.ptr = NULL;
04721 f = &p->subs[idx].f;
04722
04723 if (idx < 0)
04724 return &p->subs[idx].f;
04725 if (p->fake_event) {
04726 res = p->fake_event;
04727 p->fake_event = 0;
04728 } else
04729 res = dahdi_get_event(p->subs[idx].dfd);
04730
04731 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
04732
04733 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04734 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04735 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04736 #ifdef HAVE_PRI
04737 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04738
04739 } else {
04740 #endif
04741 dahdi_confmute(p, 0);
04742 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
04743 p->subs[idx].f.subclass = res & 0xff;
04744 #ifdef HAVE_PRI
04745 }
04746 #endif
04747 dahdi_handle_dtmfup(ast, idx, &f);
04748 return f;
04749 }
04750
04751 if (res & DAHDI_EVENT_DTMFDOWN) {
04752 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04753
04754 dahdi_confmute(p, 1);
04755 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
04756 p->subs[idx].f.subclass = res & 0xff;
04757 return &p->subs[idx].f;
04758 }
04759
04760 switch (res) {
04761 case DAHDI_EVENT_EC_DISABLED:
04762 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04763 p->echocanon = 0;
04764 break;
04765 case DAHDI_EVENT_BITSCHANGED:
04766 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
04767 case DAHDI_EVENT_PULSE_START:
04768
04769 if (!ast->pbx)
04770 tone_zone_play_tone(p->subs[idx].dfd, -1);
04771 break;
04772 case DAHDI_EVENT_DIALCOMPLETE:
04773 if (p->inalarm) break;
04774 if ((p->radio || (p->oprmode < 0))) break;
04775 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
04776 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04777 return NULL;
04778 }
04779 if (!x) {
04780 dahdi_enable_ec(p);
04781 if (p->echobreak) {
04782 dahdi_train_ec(p);
04783 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04784 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04785 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04786 p->echobreak = 0;
04787 } else {
04788 p->dialing = 0;
04789 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04790
04791 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04792 ast_setstate(ast, AST_STATE_UP);
04793 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04794 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04795 break;
04796 } else {
04797
04798 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04799 }
04800 }
04801 if (ast->_state == AST_STATE_DIALING) {
04802 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04803 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04804 } 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)))) {
04805 ast_setstate(ast, AST_STATE_RINGING);
04806 } else if (!p->answeronpolarityswitch) {
04807 ast_setstate(ast, AST_STATE_UP);
04808 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04809 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04810
04811 p->polarity = POLARITY_REV;
04812 } else {
04813
04814 p->polarity = POLARITY_IDLE;
04815 }
04816 }
04817 }
04818 }
04819 break;
04820 case DAHDI_EVENT_ALARM:
04821 #ifdef HAVE_PRI
04822 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04823 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04824
04825 if (p->call) {
04826 if (p->pri && p->pri->pri) {
04827 if (!pri_grab(p, p->pri)) {
04828 pri_hangup(p->pri->pri, p->call, -1);
04829 pri_destroycall(p->pri->pri, p->call);
04830 p->call = NULL;
04831 pri_rel(p->pri);
04832 } else
04833 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04834 } else
04835 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04836 }
04837 if (p->owner)
04838 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04839 }
04840 }
04841 if (p->bearer)
04842 p->bearer->inalarm = 1;
04843 else
04844 #endif
04845 p->inalarm = 1;
04846 res = get_alarms(p);
04847 handle_alarms(p, res);
04848 #ifdef HAVE_PRI
04849 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04850
04851 } else {
04852 break;
04853 }
04854 #endif
04855 #ifdef HAVE_SS7
04856 if (p->sig == SIG_SS7)
04857 break;
04858 #endif
04859 case DAHDI_EVENT_ONHOOK:
04860 if (p->radio) {
04861 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04862 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
04863 break;
04864 }
04865 if (p->oprmode < 0)
04866 {
04867 if (p->oprmode != -1) break;
04868 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04869 {
04870
04871 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04872 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04873 save_conference(p->oprpeer);
04874 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04875 }
04876 break;
04877 }
04878 switch (p->sig) {
04879 case SIG_FXOLS:
04880 case SIG_FXOGS:
04881 case SIG_FXOKS:
04882 p->onhooktime = time(NULL);
04883 p->msgstate = -1;
04884
04885 if (idx == SUB_REAL) {
04886
04887 if (p->subs[SUB_CALLWAIT].owner) {
04888
04889 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04890 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04891 unalloc_sub(p, SUB_CALLWAIT);
04892 #if 0
04893 p->subs[idx].needanswer = 0;
04894 p->subs[idx].needringing = 0;
04895 #endif
04896 p->callwaitingrepeat = 0;
04897 p->cidcwexpire = 0;
04898 p->owner = NULL;
04899
04900 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04901 p->dialing = 1;
04902 dahdi_ring_phone(p);
04903 } else if (p->subs[SUB_THREEWAY].owner) {
04904 unsigned int mssinceflash;
04905
04906
04907 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04908
04909 DLA_UNLOCK(&p->lock);
04910 CHANNEL_DEADLOCK_AVOIDANCE(ast);
04911
04912
04913
04914 DLA_LOCK(&p->lock);
04915 if (p->owner != ast) {
04916 ast_log(LOG_WARNING, "This isn't good...\n");
04917 return NULL;
04918 }
04919 }
04920 if (!p->subs[SUB_THREEWAY].owner) {
04921 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04922 return NULL;
04923 }
04924 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04925 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04926 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04927
04928
04929 if (p->subs[SUB_THREEWAY].owner)
04930 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
04931 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04932 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04933 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04934 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04935 if (p->transfer) {
04936
04937 p->subs[SUB_REAL].inthreeway = 0;
04938 p->subs[SUB_THREEWAY].inthreeway = 0;
04939
04940 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04941 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04942
04943 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04944 p->owner = NULL;
04945
04946 dahdi_ring_phone(p);
04947 } else {
04948 if ((res = attempt_transfer(p)) < 0) {
04949 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04950 if (p->subs[SUB_THREEWAY].owner)
04951 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04952 } else if (res) {
04953
04954 if (p->subs[SUB_THREEWAY].owner)
04955 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04956 break;
04957 }
04958 }
04959 } else {
04960 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04961 if (p->subs[SUB_THREEWAY].owner)
04962 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04963 }
04964 } else {
04965 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04966
04967 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04968 p->owner = NULL;
04969
04970 dahdi_ring_phone(p);
04971 }
04972 }
04973 } else {
04974 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
04975 }
04976
04977 default:
04978 dahdi_disable_ec(p);
04979 return NULL;
04980 }
04981 break;
04982 case DAHDI_EVENT_RINGOFFHOOK:
04983 if (p->inalarm) break;
04984 if (p->oprmode < 0)
04985 {
04986 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04987 {
04988
04989 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04990 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04991 restore_conference(p->oprpeer);
04992 }
04993 break;
04994 }
04995 if (p->radio)
04996 {
04997 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04998 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
04999 break;
05000 }
05001
05002
05003 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05004 c = strchr(p->dialdest, '/');
05005 if (c)
05006 c++;
05007 else
05008 c = p->dialdest;
05009 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05010 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05011 if (strlen(p->dop.dialstr) > 4) {
05012 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05013 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05014 p->echorest[sizeof(p->echorest) - 1] = '\0';
05015 p->echobreak = 1;
05016 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05017 } else
05018 p->echobreak = 0;
05019 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05020 int saveerr = errno;
05021
05022 x = DAHDI_ONHOOK;
05023 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05024 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05025 return NULL;
05026 }
05027 p->dialing = 1;
05028 return &p->subs[idx].f;
05029 }
05030 switch (p->sig) {
05031 case SIG_FXOLS:
05032 case SIG_FXOGS:
05033 case SIG_FXOKS:
05034 switch (ast->_state) {
05035 case AST_STATE_RINGING:
05036 dahdi_enable_ec(p);
05037 dahdi_train_ec(p);
05038 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05039 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05040
05041 p->subs[SUB_REAL].needringing = 0;
05042 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05043 ast_debug(1, "channel %d answered\n", p->channel);
05044 if (p->cidspill) {
05045
05046 ast_free(p->cidspill);
05047 p->cidspill = NULL;
05048 }
05049 p->dialing = 0;
05050 p->callwaitcas = 0;
05051 if (p->confirmanswer) {
05052
05053 p->subs[idx].f.frametype = AST_FRAME_NULL;
05054 p->subs[idx].f.subclass = 0;
05055 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05056
05057 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05058 if (res < 0) {
05059 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05060 p->dop.dialstr[0] = '\0';
05061 return NULL;
05062 } else {
05063 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05064 p->subs[idx].f.frametype = AST_FRAME_NULL;
05065 p->subs[idx].f.subclass = 0;
05066 p->dialing = 1;
05067 }
05068 p->dop.dialstr[0] = '\0';
05069 ast_setstate(ast, AST_STATE_DIALING);
05070 } else
05071 ast_setstate(ast, AST_STATE_UP);
05072 return &p->subs[idx].f;
05073 case AST_STATE_DOWN:
05074 ast_setstate(ast, AST_STATE_RING);
05075 ast->rings = 1;
05076 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05077 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
05078 ast_debug(1, "channel %d picked up\n", p->channel);
05079 return &p->subs[idx].f;
05080 case AST_STATE_UP:
05081
05082 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05083
05084 if (ast_bridged_channel(p->owner))
05085 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05086 p->subs[idx].needunhold = 1;
05087 break;
05088 case AST_STATE_RESERVED:
05089
05090 if (has_voicemail(p))
05091 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05092 else
05093 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05094 break;
05095 default:
05096 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05097 }
05098 break;
05099 case SIG_FXSLS:
05100 case SIG_FXSGS:
05101 case SIG_FXSKS:
05102 if (ast->_state == AST_STATE_RING) {
05103 p->ringt = p->ringt_base;
05104 }
05105
05106
05107
05108 ast_debug(1, "Setting IDLE polarity due "
05109 "to ring. Old polarity was %d\n",
05110 p->polarity);
05111 p->polarity = POLARITY_IDLE;
05112
05113
05114 case SIG_EM:
05115 case SIG_EM_E1:
05116 case SIG_EMWINK:
05117 case SIG_FEATD:
05118 case SIG_FEATDMF:
05119 case SIG_FEATDMF_TA:
05120 case SIG_E911:
05121 case SIG_FGC_CAMA:
05122 case SIG_FGC_CAMAMF:
05123 case SIG_FEATB:
05124 case SIG_SF:
05125 case SIG_SFWINK:
05126 case SIG_SF_FEATD:
05127 case SIG_SF_FEATDMF:
05128 case SIG_SF_FEATB:
05129 if (ast->_state == AST_STATE_PRERING)
05130 ast_setstate(ast, AST_STATE_RING);
05131 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05132 ast_debug(1, "Ring detected\n");
05133 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05134 p->subs[idx].f.subclass = AST_CONTROL_RING;
05135 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05136 ast_debug(1, "Line answered\n");
05137 if (p->confirmanswer) {
05138 p->subs[idx].f.frametype = AST_FRAME_NULL;
05139 p->subs[idx].f.subclass = 0;
05140 } else {
05141 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05142 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05143 ast_setstate(ast, AST_STATE_UP);
05144 }
05145 } else if (ast->_state != AST_STATE_RING)
05146 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05147 break;
05148 default:
05149 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05150 }
05151 break;
05152 case DAHDI_EVENT_RINGBEGIN:
05153 switch (p->sig) {
05154 case SIG_FXSLS:
05155 case SIG_FXSGS:
05156 case SIG_FXSKS:
05157 if (ast->_state == AST_STATE_RING) {
05158 p->ringt = p->ringt_base;
05159 }
05160 break;
05161 }
05162 break;
05163 case DAHDI_EVENT_RINGEROFF:
05164 if (p->inalarm) break;
05165 if ((p->radio || (p->oprmode < 0))) break;
05166 ast->rings++;
05167 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05168 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05169 ast_free(p->cidspill);
05170 p->cidspill = NULL;
05171 p->callwaitcas = 0;
05172 }
05173 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05174 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05175 break;
05176 case DAHDI_EVENT_RINGERON:
05177 break;
05178 case DAHDI_EVENT_NOALARM:
05179 p->inalarm = 0;
05180 #ifdef HAVE_PRI
05181
05182 if (p->bearer)
05183 p->bearer->inalarm = 0;
05184 #endif
05185 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05186 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05187 "Channel: %d\r\n", p->channel);
05188 break;
05189 case DAHDI_EVENT_WINKFLASH:
05190 if (p->inalarm) break;
05191 if (p->radio) break;
05192 if (p->oprmode < 0) break;
05193 if (p->oprmode > 1)
05194 {
05195 struct dahdi_params par;
05196
05197 memset(&par, 0, sizeof(par));
05198 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05199 {
05200 if (!par.rxisoffhook)
05201 {
05202
05203 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05204 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05205 save_conference(p);
05206 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05207 }
05208 }
05209 break;
05210 }
05211
05212 p->flashtime = ast_tvnow();
05213 switch (mysig) {
05214 case SIG_FXOLS:
05215 case SIG_FXOGS:
05216 case SIG_FXOKS:
05217 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05218 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05219 p->callwaitcas = 0;
05220
05221 if (idx != SUB_REAL) {
05222 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
05223 goto winkflashdone;
05224 }
05225
05226 if (p->subs[SUB_CALLWAIT].owner) {
05227
05228 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05229 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05230 p->owner = p->subs[SUB_REAL].owner;
05231 ast_debug(1, "Making %s the new owner\n", p->owner->name);
05232 if (p->owner->_state == AST_STATE_RINGING) {
05233 ast_setstate(p->owner, AST_STATE_UP);
05234 p->subs[SUB_REAL].needanswer = 1;
05235 }
05236 p->callwaitingrepeat = 0;
05237 p->cidcwexpire = 0;
05238
05239 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05240 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05241 S_OR(p->mohsuggest, NULL),
05242 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05243 }
05244 p->subs[SUB_CALLWAIT].needhold = 1;
05245 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05246 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05247 S_OR(p->mohsuggest, NULL),
05248 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05249 }
05250 p->subs[SUB_REAL].needunhold = 1;
05251 } else if (!p->subs[SUB_THREEWAY].owner) {
05252 if (!p->threewaycalling) {
05253
05254 p->subs[SUB_REAL].needflash = 1;
05255 goto winkflashdone;
05256 } else if (!check_for_conference(p)) {
05257 char cid_num[256];
05258 char cid_name[256];
05259
05260 cid_num[0] = 0;
05261 cid_name[0] = 0;
05262 if (p->dahditrcallerid && p->owner) {
05263 if (p->owner->cid.cid_num)
05264 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05265 if (p->owner->cid.cid_name)
05266 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05267 }
05268
05269
05270 if (!((ast->pbx) ||
05271 (ast->_state == AST_STATE_UP) ||
05272 (ast->_state == AST_STATE_RING))) {
05273 ast_debug(1, "Flash when call not up or ringing\n");
05274 goto winkflashdone;
05275 }
05276 if (alloc_sub(p, SUB_THREEWAY)) {
05277 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05278 goto winkflashdone;
05279 }
05280
05281 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05282 if (p->dahditrcallerid) {
05283 if (!p->origcid_num)
05284 p->origcid_num = ast_strdup(p->cid_num);
05285 if (!p->origcid_name)
05286 p->origcid_name = ast_strdup(p->cid_name);
05287 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05288 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05289 }
05290
05291 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05292
05293 dahdi_disable_ec(p);
05294 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05295 if (res)
05296 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05297 p->owner = chan;
05298 if (!chan) {
05299 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05300 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05301 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05302 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05303 dahdi_enable_ec(p);
05304 ast_hangup(chan);
05305 } else {
05306 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05307 int way3bridge = 0, cdr3way = 0;
05308
05309 if (!other) {
05310 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05311 } else
05312 way3bridge = 1;
05313
05314 if (p->subs[SUB_THREEWAY].owner->cdr)
05315 cdr3way = 1;
05316
05317 ast_verb(3, "Started three way call on channel %d\n", p->channel);
05318
05319
05320 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05321 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05322 S_OR(p->mohsuggest, NULL),
05323 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05324 }
05325 p->subs[SUB_THREEWAY].needhold = 1;
05326 }
05327 }
05328 } else {
05329
05330 if (p->subs[SUB_THREEWAY].inthreeway) {
05331
05332 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05333
05334 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05335
05336 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05337 p->owner = p->subs[SUB_REAL].owner;
05338 }
05339
05340 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05341 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05342 p->subs[SUB_REAL].inthreeway = 0;
05343 p->subs[SUB_THREEWAY].inthreeway = 0;
05344 } else {
05345
05346 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05347 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05348 int otherindex = SUB_THREEWAY;
05349 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05350 int way3bridge = 0, cdr3way = 0;
05351
05352 if (!other) {
05353 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05354 } else
05355 way3bridge = 1;
05356
05357 if (p->subs[SUB_THREEWAY].owner->cdr)
05358 cdr3way = 1;
05359
05360 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05361
05362 p->subs[SUB_THREEWAY].inthreeway = 1;
05363 p->subs[SUB_REAL].inthreeway = 1;
05364 if (ast->_state == AST_STATE_UP) {
05365 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05366 otherindex = SUB_REAL;
05367 }
05368 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05369 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05370 p->subs[otherindex].needunhold = 1;
05371 p->owner = p->subs[SUB_REAL].owner;
05372 if (ast->_state == AST_STATE_RINGING) {
05373 ast_debug(1, "Enabling ringtone on real and threeway\n");
05374 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05375 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05376 }
05377 } else {
05378 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05379 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05380 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05381 p->owner = p->subs[SUB_REAL].owner;
05382 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05383 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05384 p->subs[SUB_REAL].needunhold = 1;
05385 dahdi_enable_ec(p);
05386 }
05387
05388 }
05389 }
05390 winkflashdone:
05391 update_conf(p);
05392 break;
05393 case SIG_EM:
05394 case SIG_EM_E1:
05395 case SIG_FEATD:
05396 case SIG_SF:
05397 case SIG_SFWINK:
05398 case SIG_SF_FEATD:
05399 case SIG_FXSLS:
05400 case SIG_FXSGS:
05401 if (option_debug) {
05402 if (p->dialing)
05403 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05404 else
05405 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05406 }
05407 break;
05408 case SIG_FEATDMF_TA:
05409 switch (p->whichwink) {
05410 case 0:
05411 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05412 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05413 break;
05414 case 1:
05415 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05416 break;
05417 case 2:
05418 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05419 return NULL;
05420 }
05421 p->whichwink++;
05422
05423 case SIG_FEATDMF:
05424 case SIG_E911:
05425 case SIG_FGC_CAMAMF:
05426 case SIG_FGC_CAMA:
05427 case SIG_FEATB:
05428 case SIG_SF_FEATDMF:
05429 case SIG_SF_FEATB:
05430 case SIG_EMWINK:
05431
05432 if (!ast_strlen_zero(p->dop.dialstr)) {
05433 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05434 if (res < 0) {
05435 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05436 p->dop.dialstr[0] = '\0';
05437 return NULL;
05438 } else
05439 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05440 }
05441 p->dop.dialstr[0] = '\0';
05442 break;
05443 default:
05444 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05445 }
05446 break;
05447 case DAHDI_EVENT_HOOKCOMPLETE:
05448 if (p->inalarm) break;
05449 if ((p->radio || (p->oprmode < 0))) break;
05450 switch (mysig) {
05451 case SIG_FXSLS:
05452 case SIG_FXSGS:
05453 case SIG_FXSKS:
05454 case SIG_EM:
05455 case SIG_EM_E1:
05456 case SIG_EMWINK:
05457 case SIG_FEATD:
05458 case SIG_SF:
05459 case SIG_SFWINK:
05460 case SIG_SF_FEATD:
05461 if (!ast_strlen_zero(p->dop.dialstr)) {
05462 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05463 if (res < 0) {
05464 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05465 p->dop.dialstr[0] = '\0';
05466 return NULL;
05467 } else
05468 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05469 }
05470 p->dop.dialstr[0] = '\0';
05471 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05472 break;
05473 case SIG_FEATDMF:
05474 case SIG_FEATDMF_TA:
05475 case SIG_E911:
05476 case SIG_FGC_CAMA:
05477 case SIG_FGC_CAMAMF:
05478 case SIG_FEATB:
05479 case SIG_SF_FEATDMF:
05480 case SIG_SF_FEATB:
05481 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05482 break;
05483 default:
05484 break;
05485 }
05486 break;
05487 case DAHDI_EVENT_POLARITY:
05488
05489
05490
05491
05492
05493
05494
05495
05496
05497 if (p->polarityonanswerdelay > 0) {
05498
05499 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05500 switch (ast->_state) {
05501 case AST_STATE_DIALING:
05502 case AST_STATE_RINGING:
05503 if (p->answeronpolarityswitch) {
05504 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
05505 ast_setstate(p->owner, AST_STATE_UP);
05506 p->polarity = POLARITY_REV;
05507 if (p->hanguponpolarityswitch) {
05508 p->polaritydelaytv = ast_tvnow();
05509 }
05510 } else {
05511 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
05512 }
05513 break;
05514 case AST_STATE_UP:
05515 case AST_STATE_RING:
05516 if (p->hanguponpolarityswitch) {
05517 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
05518 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05519 p->polarity = POLARITY_IDLE;
05520 } else {
05521 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
05522 }
05523 break;
05524
05525 case AST_STATE_DOWN:
05526 case AST_STATE_RESERVED:
05527 case AST_STATE_OFFHOOK:
05528 case AST_STATE_BUSY:
05529 case AST_STATE_DIALING_OFFHOOK:
05530 case AST_STATE_PRERING:
05531 default:
05532 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05533 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
05534 }
05535
05536 }
05537
05538 } else {
05539
05540 switch (ast->_state) {
05541 case AST_STATE_DIALING:
05542 case AST_STATE_RINGING:
05543 if (p->answeronpolarityswitch) {
05544 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
05545 }
05546 break;
05547
05548 case AST_STATE_UP:
05549 case AST_STATE_RING:
05550 if (p->hanguponpolarityswitch) {
05551 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);
05552 }
05553 break;
05554
05555 default:
05556 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05557 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
05558 }
05559 }
05560 }
05561 }
05562
05563 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) );
05564 break;
05565 default:
05566 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05567 }
05568 return &p->subs[idx].f;
05569 }
05570
05571 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05572 {
05573 struct dahdi_pvt *p = ast->tech_pvt;
05574 int res;
05575 int usedindex=-1;
05576 int idx;
05577 struct ast_frame *f;
05578
05579
05580 idx = dahdi_get_index(ast, p, 1);
05581
05582 p->subs[idx].f.frametype = AST_FRAME_NULL;
05583 p->subs[idx].f.datalen = 0;
05584 p->subs[idx].f.samples = 0;
05585 p->subs[idx].f.mallocd = 0;
05586 p->subs[idx].f.offset = 0;
05587 p->subs[idx].f.subclass = 0;
05588 p->subs[idx].f.delivery = ast_tv(0,0);
05589 p->subs[idx].f.src = "dahdi_exception";
05590 p->subs[idx].f.data.ptr = NULL;
05591
05592
05593 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05594
05595
05596
05597
05598
05599 if (p->fake_event) {
05600 res = p->fake_event;
05601 p->fake_event = 0;
05602 } else
05603 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05604
05605 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05606 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05607 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05608 p->owner = p->subs[SUB_REAL].owner;
05609 if (p->owner && ast_bridged_channel(p->owner))
05610 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05611 p->subs[SUB_REAL].needunhold = 1;
05612 }
05613 switch (res) {
05614 case DAHDI_EVENT_ONHOOK:
05615 dahdi_disable_ec(p);
05616 if (p->owner) {
05617 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05618 dahdi_ring_phone(p);
05619 p->callwaitingrepeat = 0;
05620 p->cidcwexpire = 0;
05621 } else
05622 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05623 update_conf(p);
05624 break;
05625 case DAHDI_EVENT_RINGOFFHOOK:
05626 dahdi_enable_ec(p);
05627 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05628 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05629 p->subs[SUB_REAL].needanswer = 1;
05630 p->dialing = 0;
05631 }
05632 break;
05633 case DAHDI_EVENT_HOOKCOMPLETE:
05634 case DAHDI_EVENT_RINGERON:
05635 case DAHDI_EVENT_RINGEROFF:
05636
05637 break;
05638 case DAHDI_EVENT_WINKFLASH:
05639 p->flashtime = ast_tvnow();
05640 if (p->owner) {
05641 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05642 if (p->owner->_state != AST_STATE_UP) {
05643
05644 usedindex = dahdi_get_index(p->owner, p, 0);
05645 if (usedindex > -1) {
05646 p->subs[usedindex].needanswer = 1;
05647 }
05648 ast_setstate(p->owner, AST_STATE_UP);
05649 }
05650 p->callwaitingrepeat = 0;
05651 p->cidcwexpire = 0;
05652 if (ast_bridged_channel(p->owner))
05653 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05654 p->subs[SUB_REAL].needunhold = 1;
05655 } else
05656 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05657 update_conf(p);
05658 break;
05659 default:
05660 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05661 }
05662 f = &p->subs[idx].f;
05663 return f;
05664 }
05665 if (!(p->radio || (p->oprmode < 0)))
05666 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05667
05668 if (ast != p->owner) {
05669 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05670 f = &p->subs[idx].f;
05671 return f;
05672 }
05673 f = dahdi_handle_event(ast);
05674 return f;
05675 }
05676
05677 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05678 {
05679 struct dahdi_pvt *p = ast->tech_pvt;
05680 struct ast_frame *f;
05681 ast_mutex_lock(&p->lock);
05682 f = __dahdi_exception(ast);
05683 ast_mutex_unlock(&p->lock);
05684 return f;
05685 }
05686
05687 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05688 {
05689 struct dahdi_pvt *p = ast->tech_pvt;
05690 int res;
05691 int idx;
05692 void *readbuf;
05693 struct ast_frame *f;
05694
05695 while (ast_mutex_trylock(&p->lock)) {
05696 CHANNEL_DEADLOCK_AVOIDANCE(ast);
05697 }
05698
05699 idx = dahdi_get_index(ast, p, 0);
05700
05701
05702 if (idx < 0) {
05703 ast_log(LOG_WARNING, "We dont exist?\n");
05704 ast_mutex_unlock(&p->lock);
05705 return NULL;
05706 }
05707
05708 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05709 ast_mutex_unlock(&p->lock);
05710 return NULL;
05711 }
05712
05713 p->subs[idx].f.frametype = AST_FRAME_NULL;
05714 p->subs[idx].f.datalen = 0;
05715 p->subs[idx].f.samples = 0;
05716 p->subs[idx].f.mallocd = 0;
05717 p->subs[idx].f.offset = 0;
05718 p->subs[idx].f.subclass = 0;
05719 p->subs[idx].f.delivery = ast_tv(0,0);
05720 p->subs[idx].f.src = "dahdi_read";
05721 p->subs[idx].f.data.ptr = NULL;
05722
05723
05724 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05725 {
05726 struct dahdi_params ps;
05727
05728 memset(&ps, 0, sizeof(ps));
05729 ps.channo = p->channel;
05730 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05731 ast_mutex_unlock(&p->lock);
05732 return NULL;
05733 }
05734 p->firstradio = 1;
05735 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05736 if (ps.rxisoffhook)
05737 {
05738 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
05739 }
05740 else
05741 {
05742 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05743 }
05744 ast_mutex_unlock(&p->lock);
05745 return &p->subs[idx].f;
05746 }
05747 if (p->ringt == 1) {
05748 ast_mutex_unlock(&p->lock);
05749 return NULL;
05750 }
05751 else if (p->ringt > 0)
05752 p->ringt--;
05753
05754 if (p->subs[idx].needringing) {
05755
05756 p->subs[idx].needringing = 0;
05757 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05758 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05759 ast_setstate(ast, AST_STATE_RINGING);
05760 ast_mutex_unlock(&p->lock);
05761 return &p->subs[idx].f;
05762 }
05763
05764 if (p->subs[idx].needbusy) {
05765
05766 p->subs[idx].needbusy = 0;
05767 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05768 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
05769 ast_mutex_unlock(&p->lock);
05770 return &p->subs[idx].f;
05771 }
05772
05773 if (p->subs[idx].needcongestion) {
05774
05775 p->subs[idx].needcongestion = 0;
05776 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05777 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
05778 ast_mutex_unlock(&p->lock);
05779 return &p->subs[idx].f;
05780 }
05781
05782 if (p->subs[idx].needcallerid) {
05783 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05784 S_OR(p->lastcid_name, NULL),
05785 S_OR(p->lastcid_num, NULL)
05786 );
05787 p->subs[idx].needcallerid = 0;
05788 }
05789
05790 if (p->subs[idx].needanswer) {
05791
05792 p->subs[idx].needanswer = 0;
05793 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05794 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05795 ast_mutex_unlock(&p->lock);
05796 return &p->subs[idx].f;
05797 }
05798
05799 if (p->subs[idx].needflash) {
05800
05801 p->subs[idx].needflash = 0;
05802 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05803 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
05804 ast_mutex_unlock(&p->lock);
05805 return &p->subs[idx].f;
05806 }
05807
05808 if (p->subs[idx].needhold) {
05809
05810 p->subs[idx].needhold = 0;
05811 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05812 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
05813 ast_mutex_unlock(&p->lock);
05814 ast_debug(1, "Sending hold on '%s'\n", ast->name);
05815 return &p->subs[idx].f;
05816 }
05817
05818 if (p->subs[idx].needunhold) {
05819
05820 p->subs[idx].needunhold = 0;
05821 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05822 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
05823 ast_mutex_unlock(&p->lock);
05824 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05825 return &p->subs[idx].f;
05826 }
05827
05828 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05829 if (!p->subs[idx].linear) {
05830 p->subs[idx].linear = 1;
05831 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05832 if (res)
05833 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
05834 }
05835 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05836 (ast->rawreadformat == AST_FORMAT_ALAW)) {
05837 if (p->subs[idx].linear) {
05838 p->subs[idx].linear = 0;
05839 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05840 if (res)
05841 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
05842 }
05843 } else {
05844 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05845 ast_mutex_unlock(&p->lock);
05846 return NULL;
05847 }
05848 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
05849 CHECK_BLOCKING(ast);
05850 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05851 ast_clear_flag(ast, AST_FLAG_BLOCKING);
05852
05853 if (res < 0) {
05854 f = NULL;
05855 if (res == -1) {
05856 if (errno == EAGAIN) {
05857
05858 ast_mutex_unlock(&p->lock);
05859 return &p->subs[idx].f;
05860 } else if (errno == ELAST) {
05861 f = __dahdi_exception(ast);
05862 } else
05863 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05864 }
05865 ast_mutex_unlock(&p->lock);
05866 return f;
05867 }
05868 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
05869 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05870 f = __dahdi_exception(ast);
05871 ast_mutex_unlock(&p->lock);
05872 return f;
05873 }
05874 if (p->tdd) {
05875 int c;
05876
05877 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05878 if (c < 0) {
05879 ast_debug(1,"tdd_feed failed\n");
05880 ast_mutex_unlock(&p->lock);
05881 return NULL;
05882 }
05883 if (c) {
05884 p->subs[idx].f.subclass = 0;
05885 p->subs[idx].f.frametype = AST_FRAME_TEXT;
05886 p->subs[idx].f.mallocd = 0;
05887 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05888 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
05889 p->subs[idx].f.datalen = 1;
05890 *((char *) p->subs[idx].f.data.ptr) = c;
05891 ast_mutex_unlock(&p->lock);
05892 return &p->subs[idx].f;
05893 }
05894 }
05895
05896 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05897 p->callwaitingrepeat--;
05898 }
05899 if (p->cidcwexpire)
05900 p->cidcwexpire--;
05901
05902 if (p->callwaitingrepeat == 1) {
05903 p->callwaitrings++;
05904 dahdi_callwait(ast);
05905 }
05906
05907 if (p->cidcwexpire == 1) {
05908 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05909 restore_conference(p);
05910 }
05911 if (p->subs[idx].linear) {
05912 p->subs[idx].f.datalen = READ_SIZE * 2;
05913 } else
05914 p->subs[idx].f.datalen = READ_SIZE;
05915
05916
05917 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05918 send_callerid(p);
05919 }
05920
05921 p->subs[idx].f.frametype = AST_FRAME_VOICE;
05922 p->subs[idx].f.subclass = ast->rawreadformat;
05923 p->subs[idx].f.samples = READ_SIZE;
05924 p->subs[idx].f.mallocd = 0;
05925 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05926 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
05927 #if 0
05928 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
05929 #endif
05930 if (p->dialing ||
05931 (idx && (ast->_state != AST_STATE_UP)) ||
05932 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05933 ) {
05934
05935
05936 p->subs[idx].f.frametype = AST_FRAME_NULL;
05937 p->subs[idx].f.subclass = 0;
05938 p->subs[idx].f.samples = 0;
05939 p->subs[idx].f.mallocd = 0;
05940 p->subs[idx].f.offset = 0;
05941 p->subs[idx].f.data.ptr = NULL;
05942 p->subs[idx].f.datalen= 0;
05943 }
05944 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) {
05945
05946 int mute;
05947
05948 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
05949
05950
05951 mute = ast_dsp_was_muted(p->dsp);
05952 if (p->muting != mute) {
05953 p->muting = mute;
05954 dahdi_confmute(p, mute);
05955 }
05956
05957 if (f) {
05958 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05959 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05960
05961
05962 f = NULL;
05963 }
05964 } else if (f->frametype == AST_FRAME_DTMF) {
05965 #ifdef HAVE_PRI
05966 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
05967 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05968 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05969
05970 f->frametype = AST_FRAME_NULL;
05971 f->subclass = 0;
05972 }
05973 #endif
05974
05975 p->pulsedial = 0;
05976 }
05977 }
05978 } else
05979 f = &p->subs[idx].f;
05980
05981 if (f && (f->frametype == AST_FRAME_DTMF))
05982 dahdi_handle_dtmfup(ast, idx, &f);
05983
05984
05985 if (p->fake_event)
05986 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05987
05988 ast_mutex_unlock(&p->lock);
05989 return f;
05990 }
05991
05992 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
05993 {
05994 int sent=0;
05995 int size;
05996 int res;
05997 int fd;
05998 fd = p->subs[idx].dfd;
05999 while (len) {
06000 size = len;
06001 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06002 size = (linear ? READ_SIZE * 2 : READ_SIZE);
06003 res = write(fd, buf, size);
06004 if (res != size) {
06005 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06006 return sent;
06007 }
06008 len -= size;
06009 buf += size;
06010 }
06011 return sent;
06012 }
06013
06014 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06015 {
06016 struct dahdi_pvt *p = ast->tech_pvt;
06017 int res;
06018 int idx;
06019 idx = dahdi_get_index(ast, p, 0);
06020 if (idx < 0) {
06021 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06022 return -1;
06023 }
06024
06025 #if 0
06026 #ifdef HAVE_PRI
06027 ast_mutex_lock(&p->lock);
06028 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06029 if (p->pri->pri) {
06030 if (!pri_grab(p, p->pri)) {
06031 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06032 pri_rel(p->pri);
06033 } else
06034 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06035 }
06036 p->proceeding=1;
06037 }
06038 ast_mutex_unlock(&p->lock);
06039 #endif
06040 #endif
06041
06042 if (frame->frametype != AST_FRAME_VOICE) {
06043 if (frame->frametype != AST_FRAME_IMAGE)
06044 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06045 return 0;
06046 }
06047 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06048 (frame->subclass != AST_FORMAT_ULAW) &&
06049 (frame->subclass != AST_FORMAT_ALAW)) {
06050 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06051 return -1;
06052 }
06053 if (p->dialing) {
06054 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06055 return 0;
06056 }
06057 if (!p->owner) {
06058 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06059 return 0;
06060 }
06061 if (p->cidspill) {
06062 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06063 return 0;
06064 }
06065
06066 if (!frame->data.ptr || !frame->datalen)
06067 return 0;
06068
06069 if (frame->subclass == AST_FORMAT_SLINEAR) {
06070 if (!p->subs[idx].linear) {
06071 p->subs[idx].linear = 1;
06072 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06073 if (res)
06074 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06075 }
06076 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
06077 } else {
06078
06079 if (p->subs[idx].linear) {
06080 p->subs[idx].linear = 0;
06081 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06082 if (res)
06083 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06084 }
06085 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
06086 }
06087 if (res < 0) {
06088 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06089 return -1;
06090 }
06091 return 0;
06092 }
06093
06094 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06095 {
06096 struct dahdi_pvt *p = chan->tech_pvt;
06097 int res=-1;
06098 int idx;
06099 int func = DAHDI_FLASH;
06100 ast_mutex_lock(&p->lock);
06101 idx = dahdi_get_index(chan, p, 0);
06102 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06103 if (idx == SUB_REAL) {
06104 switch (condition) {
06105 case AST_CONTROL_BUSY:
06106 #ifdef HAVE_PRI
06107 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06108 chan->hangupcause = AST_CAUSE_USER_BUSY;
06109 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06110 res = 0;
06111 } else if (!p->progress &&
06112 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06113 && p->pri && !p->outgoing) {
06114 if (p->pri->pri) {
06115 if (!pri_grab(p, p->pri)) {
06116 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06117 pri_rel(p->pri);
06118 }
06119 else
06120 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06121 }
06122 p->progress = 1;
06123 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06124 } else
06125 #endif
06126 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06127 break;
06128 case AST_CONTROL_RINGING:
06129 #ifdef HAVE_PRI
06130 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06131 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06132 if (p->pri->pri) {
06133 if (!pri_grab(p, p->pri)) {
06134 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06135 pri_rel(p->pri);
06136 }
06137 else
06138 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06139 }
06140 p->alerting = 1;
06141 }
06142
06143 #endif
06144 #ifdef HAVE_SS7
06145 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06146 if (p->ss7->ss7) {
06147 ss7_grab(p, p->ss7);
06148
06149 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06150 p->rlt = 1;
06151 if (p->rlt != 1)
06152 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06153 p->alerting = 1;
06154 ss7_rel(p->ss7);
06155 }
06156 }
06157 #endif
06158
06159 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
06160
06161 if (chan->_state != AST_STATE_UP) {
06162 if ((chan->_state != AST_STATE_RING) ||
06163 ((p->sig != SIG_FXSKS) &&
06164 (p->sig != SIG_FXSLS) &&
06165 (p->sig != SIG_FXSGS)))
06166 ast_setstate(chan, AST_STATE_RINGING);
06167 }
06168 break;
06169 case AST_CONTROL_PROCEEDING:
06170 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06171 #ifdef HAVE_PRI
06172 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06173 && p->pri && !p->outgoing) {
06174 if (p->pri->pri) {
06175 if (!pri_grab(p, p->pri)) {
06176 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06177 pri_rel(p->pri);
06178 }
06179 else
06180 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06181 }
06182 p->proceeding = 1;
06183 p->dialing = 0;
06184 }
06185 #endif
06186 #ifdef HAVE_SS7
06187
06188 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
06189 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06190 p->rlt = 1;
06191 }
06192
06193 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
06194 if (p->ss7->ss7) {
06195 ss7_grab(p, p->ss7);
06196 isup_acm(p->ss7->ss7, p->ss7call);
06197 p->proceeding = 1;
06198 ss7_rel(p->ss7);
06199
06200 }
06201 }
06202 #endif
06203
06204 res = 0;
06205 break;
06206 case AST_CONTROL_PROGRESS:
06207 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06208 #ifdef HAVE_PRI
06209 p->digital = 0;
06210 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06211 && p->pri && !p->outgoing) {
06212 if (p->pri->pri) {
06213 if (!pri_grab(p, p->pri)) {
06214 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06215 pri_rel(p->pri);
06216 }
06217 else
06218 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06219 }
06220 p->progress = 1;
06221 }
06222 #endif
06223 #ifdef HAVE_SS7
06224 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
06225 if (p->ss7->ss7) {
06226 ss7_grab(p, p->ss7);
06227 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
06228 p->progress = 1;
06229 ss7_rel(p->ss7);
06230
06231 dahdi_enable_ec(p);
06232
06233 }
06234 }
06235 #endif
06236
06237 res = 0;
06238 break;
06239 case AST_CONTROL_CONGESTION:
06240 chan->hangupcause = AST_CAUSE_CONGESTION;
06241 #ifdef HAVE_PRI
06242 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06243 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06244 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06245 res = 0;
06246 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06247 && p->pri && !p->outgoing) {
06248 if (p->pri) {
06249 if (!pri_grab(p, p->pri)) {
06250 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06251 pri_rel(p->pri);
06252 } else
06253 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06254 }
06255 p->progress = 1;
06256 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06257 } else
06258 #endif
06259 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06260 break;
06261 case AST_CONTROL_HOLD:
06262 #ifdef HAVE_PRI
06263 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06264 if (!pri_grab(p, p->pri)) {
06265 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06266 pri_rel(p->pri);
06267 } else
06268 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06269 } else
06270 #endif
06271 ast_moh_start(chan, data, p->mohinterpret);
06272 break;
06273 case AST_CONTROL_UNHOLD:
06274 #ifdef HAVE_PRI
06275 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06276 if (!pri_grab(p, p->pri)) {
06277 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06278 pri_rel(p->pri);
06279 } else
06280 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06281 } else
06282 #endif
06283 ast_moh_stop(chan);
06284 break;
06285 case AST_CONTROL_RADIO_KEY:
06286 if (p->radio)
06287 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06288 res = 0;
06289 break;
06290 case AST_CONTROL_RADIO_UNKEY:
06291 if (p->radio)
06292 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
06293 res = 0;
06294 break;
06295 case AST_CONTROL_FLASH:
06296
06297 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06298
06299 p->dop.dialstr[0] = '\0';
06300 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06301 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06302 chan->name, strerror(errno));
06303 } else
06304 res = 0;
06305 } else
06306 res = 0;
06307 break;
06308 case AST_CONTROL_SRCUPDATE:
06309 res = 0;
06310 break;
06311 case -1:
06312 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06313 break;
06314 }
06315 } else
06316 res = 0;
06317 ast_mutex_unlock(&p->lock);
06318 return res;
06319 }
06320
06321 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
06322 {
06323 struct ast_channel *tmp;
06324 int deflaw;
06325 int res;
06326 int x,y;
06327 int features;
06328 struct ast_str *chan_name;
06329 struct ast_variable *v;
06330 struct dahdi_params ps;
06331 if (i->subs[idx].owner) {
06332 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
06333 return NULL;
06334 }
06335 y = 1;
06336 chan_name = ast_str_alloca(32);
06337 do {
06338 #ifdef HAVE_PRI
06339 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06340 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06341 else
06342 #endif
06343 if (i->channel == CHAN_PSEUDO)
06344 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
06345 else
06346 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
06347 for (x = 0; x < 3; x++) {
06348 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
06349 break;
06350 }
06351 y++;
06352 } while (x < 3);
06353 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);
06354 if (!tmp)
06355 return NULL;
06356 tmp->tech = &dahdi_tech;
06357 memset(&ps, 0, sizeof(ps));
06358 ps.channo = i->channel;
06359 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06360 if (res) {
06361 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06362 ps.curlaw = DAHDI_LAW_MULAW;
06363 }
06364 if (ps.curlaw == DAHDI_LAW_ALAW)
06365 deflaw = AST_FORMAT_ALAW;
06366 else
06367 deflaw = AST_FORMAT_ULAW;
06368 if (law) {
06369 if (law == DAHDI_LAW_ALAW)
06370 deflaw = AST_FORMAT_ALAW;
06371 else
06372 deflaw = AST_FORMAT_ULAW;
06373 }
06374 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
06375 tmp->nativeformats = deflaw;
06376
06377 tmp->rawreadformat = deflaw;
06378 tmp->readformat = deflaw;
06379 tmp->rawwriteformat = deflaw;
06380 tmp->writeformat = deflaw;
06381 i->subs[idx].linear = 0;
06382 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
06383 features = 0;
06384 if (idx == SUB_REAL) {
06385 if (i->busydetect && CANBUSYDETECT(i))
06386 features |= DSP_FEATURE_BUSY_DETECT;
06387 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
06388 features |= DSP_FEATURE_CALL_PROGRESS;
06389 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
06390 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
06391 features |= DSP_FEATURE_FAX_DETECT;
06392 }
06393 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06394 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
06395 i->hardwaredtmf = 0;
06396 features |= DSP_FEATURE_DIGIT_DETECT;
06397 } else if (NEED_MFDETECT(i)) {
06398 i->hardwaredtmf = 1;
06399 features |= DSP_FEATURE_DIGIT_DETECT;
06400 }
06401 }
06402 if (features) {
06403 if (i->dsp) {
06404 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
06405 } else {
06406 if (i->channel != CHAN_PSEUDO)
06407 i->dsp = ast_dsp_new();
06408 else
06409 i->dsp = NULL;
06410 if (i->dsp) {
06411 i->dsp_features = features;
06412 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06413
06414 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
06415
06416
06417 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06418 features = 0;
06419 }
06420 #endif
06421 ast_dsp_set_features(i->dsp, features);
06422 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06423 if (!ast_strlen_zero(progzone))
06424 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06425 if (i->busydetect && CANBUSYDETECT(i)) {
06426 if(i->silencethreshold > 0)
06427 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06428 ast_dsp_set_busy_count(i->dsp, i->busycount);
06429 if(i->busytonelength > 0)
06430 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06431 if((i->busytonelength == i->busyquietlength) && i->busycompare)
06432 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06433 }
06434 }
06435 }
06436 }
06437
06438 if (state == AST_STATE_RING)
06439 tmp->rings = 1;
06440 tmp->tech_pvt = i;
06441 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06442
06443 tmp->callgroup = i->callgroup;
06444 tmp->pickupgroup = i->pickupgroup;
06445 }
06446 if (!ast_strlen_zero(i->parkinglot))
06447 ast_string_field_set(tmp, parkinglot, i->parkinglot);
06448 if (!ast_strlen_zero(i->language))
06449 ast_string_field_set(tmp, language, i->language);
06450 if (!i->owner)
06451 i->owner = tmp;
06452 if (!ast_strlen_zero(i->accountcode))
06453 ast_string_field_set(tmp, accountcode, i->accountcode);
06454 if (i->amaflags)
06455 tmp->amaflags = i->amaflags;
06456 i->subs[idx].owner = tmp;
06457 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06458 ast_string_field_set(tmp, call_forward, i->call_forward);
06459
06460 if (!i->adsi)
06461 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06462 if (!ast_strlen_zero(i->exten))
06463 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06464 if (!ast_strlen_zero(i->rdnis))
06465 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06466 if (!ast_strlen_zero(i->dnid))
06467 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06468
06469
06470
06471 #ifdef PRI_ANI
06472 if (!ast_strlen_zero(i->cid_ani))
06473 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06474 else
06475 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06476 #else
06477 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06478 #endif
06479 tmp->cid.cid_pres = i->callingpres;
06480 tmp->cid.cid_ton = i->cid_ton;
06481 tmp->cid.cid_ani2 = i->cid_ani2;
06482 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06483 tmp->transfercapability = transfercapability;
06484 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06485 if (transfercapability & AST_TRANS_CAP_DIGITAL)
06486 i->digital = 1;
06487
06488 i->isidlecall = 0;
06489 i->alreadyhungup = 0;
06490 #endif
06491
06492 i->fake_event = 0;
06493
06494 dahdi_confmute(i, 0);
06495 i->muting = 0;
06496
06497 ast_jb_configure(tmp, &global_jbconf);
06498
06499 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
06500
06501 for (v = i->vars ; v ; v = v->next)
06502 pbx_builtin_setvar_helper(tmp, v->name, v->value);
06503
06504 if (startpbx) {
06505 if (ast_pbx_start(tmp)) {
06506 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06507 ast_hangup(tmp);
06508 i->owner = NULL;
06509 return NULL;
06510 }
06511 }
06512
06513 ast_module_ref(ast_module_info->self);
06514 return tmp;
06515 }
06516
06517
06518 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06519 {
06520 char c;
06521
06522 *str = 0;
06523 for (;;)
06524 {
06525
06526 c = ast_waitfordigit(chan, ms);
06527
06528 if (c < 1)
06529 return c;
06530 *str++ = c;
06531 *str = 0;
06532 if (strchr(term, c))
06533 return 1;
06534 }
06535 }
06536
06537 static int dahdi_wink(struct dahdi_pvt *p, int idx)
06538 {
06539 int j;
06540 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
06541 for (;;)
06542 {
06543
06544 j = DAHDI_IOMUX_SIGEVENT;
06545
06546 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06547
06548 if (j & DAHDI_IOMUX_SIGEVENT) break;
06549 }
06550
06551 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06552 return 0;
06553 }
06554
06555
06556
06557
06558
06559
06560
06561
06562
06563
06564 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
06565 {
06566
06567 dahdichan->dnd = on;
06568 ast_verb(3, "%s DND on channel %d\n",
06569 on? "Enabled" : "Disabled",
06570 dahdichan->channel);
06571 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06572 "Channel: DAHDI/%d\r\n"
06573 "Status: %s\r\n", dahdichan->channel,
06574 on? "enabled" : "disabled");
06575 }
06576
06577 static void *ss_thread(void *data)
06578 {
06579 struct ast_channel *chan = data;
06580 struct dahdi_pvt *p = chan->tech_pvt;
06581 char exten[AST_MAX_EXTENSION] = "";
06582 char exten2[AST_MAX_EXTENSION] = "";
06583 unsigned char buf[256];
06584 char dtmfcid[300];
06585 char dtmfbuf[300];
06586 struct callerid_state *cs = NULL;
06587 char *name = NULL, *number = NULL;
06588 int distMatches;
06589 int curRingData[3];
06590 int receivedRingT;
06591 int counter1;
06592 int counter;
06593 int samples = 0;
06594 struct ast_smdi_md_message *smdi_msg = NULL;
06595 int flags = 0;
06596 int i;
06597 int timeout;
06598 int getforward = 0;
06599 char *s1, *s2;
06600 int len = 0;
06601 int res;
06602 int idx;
06603
06604 ast_mutex_lock(&ss_thread_lock);
06605 ss_thread_count++;
06606 ast_mutex_unlock(&ss_thread_lock);
06607
06608
06609
06610 if (!p) {
06611 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06612 ast_hangup(chan);
06613 goto quit;
06614 }
06615 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
06616 idx = dahdi_get_index(chan, p, 1);
06617 if (idx < 0) {
06618 ast_log(LOG_WARNING, "Huh?\n");
06619 ast_hangup(chan);
06620 goto quit;
06621 }
06622 if (p->dsp)
06623 ast_dsp_digitreset(p->dsp);
06624 switch (p->sig) {
06625 #ifdef HAVE_PRI
06626 case SIG_PRI:
06627 case SIG_BRI:
06628 case SIG_BRI_PTMP:
06629
06630 ast_copy_string(exten, p->exten, sizeof(exten));
06631 len = strlen(exten);
06632 res = 0;
06633 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06634 if (len && !ast_ignore_pattern(chan->context, exten))
06635 tone_zone_play_tone(p->subs[idx].dfd, -1);
06636 else
06637 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06638 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06639 timeout = matchdigittimeout;
06640 else
06641 timeout = gendigittimeout;
06642 res = ast_waitfordigit(chan, timeout);
06643 if (res < 0) {
06644 ast_debug(1, "waitfordigit returned < 0...\n");
06645 ast_hangup(chan);
06646 goto quit;
06647 } else if (res) {
06648 exten[len++] = res;
06649 exten[len] = '\0';
06650 } else
06651 break;
06652 }
06653
06654 if (ast_strlen_zero(exten)) {
06655 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
06656 exten[0] = 's';
06657 exten[1] = '\0';
06658 }
06659 tone_zone_play_tone(p->subs[idx].dfd, -1);
06660 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06661
06662 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06663 if (p->dsp) {
06664 ast_dsp_digitreset(p->dsp);
06665 }
06666 if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
06667 if (p->pri->pri) {
06668 if (!pri_grab(p, p->pri)) {
06669 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
06670 p->proceeding = 1;
06671 pri_rel(p->pri);
06672 } else {
06673 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06674 }
06675 }
06676 }
06677 dahdi_enable_ec(p);
06678 ast_setstate(chan, AST_STATE_RING);
06679 res = ast_pbx_run(chan);
06680 if (res) {
06681 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06682 }
06683 } else {
06684 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06685 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06686 ast_hangup(chan);
06687 p->exten[0] = '\0';
06688
06689 p->call = NULL;
06690 }
06691 goto quit;
06692 break;
06693 #endif
06694 case SIG_FEATD:
06695 case SIG_FEATDMF:
06696 case SIG_FEATDMF_TA:
06697 case SIG_E911:
06698 case SIG_FGC_CAMAMF:
06699 case SIG_FEATB:
06700 case SIG_EMWINK:
06701 case SIG_SF_FEATD:
06702 case SIG_SF_FEATDMF:
06703 case SIG_SF_FEATB:
06704 case SIG_SFWINK:
06705 if (dahdi_wink(p, idx))
06706 goto quit;
06707
06708 case SIG_EM:
06709 case SIG_EM_E1:
06710 case SIG_SF:
06711 case SIG_FGC_CAMA:
06712 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06713 if (p->dsp)
06714 ast_dsp_digitreset(p->dsp);
06715
06716 if (p->dsp) {
06717 if (NEED_MFDETECT(p))
06718 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06719 else
06720 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06721 }
06722 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06723
06724 if (!p->immediate)
06725
06726 res = ast_waitfordigit(chan, 5000);
06727 else
06728 res = 0;
06729 if (res > 0) {
06730
06731 dtmfbuf[0] = res;
06732 switch (p->sig) {
06733 case SIG_FEATD:
06734 case SIG_SF_FEATD:
06735 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06736 if (res > 0)
06737 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06738 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06739 break;
06740 case SIG_FEATDMF_TA:
06741 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06742 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06743 if (dahdi_wink(p, idx)) goto quit;
06744 dtmfbuf[0] = 0;
06745
06746 res = ast_waitfordigit(chan, 5000);
06747 if (res <= 0) break;
06748 dtmfbuf[0] = res;
06749
06750 case SIG_FEATDMF:
06751 case SIG_E911:
06752 case SIG_FGC_CAMAMF:
06753 case SIG_SF_FEATDMF:
06754 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06755
06756 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06757 {
06758 if (dahdi_wink(p, idx)) goto quit;
06759 dtmfbuf[0] = 0;
06760
06761 res = ast_waitfordigit(chan, 5000);
06762 if (res <= 0) break;
06763 dtmfbuf[0] = res;
06764 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06765 }
06766 if (res > 0) {
06767
06768 if (p->sig == SIG_E911)
06769 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06770 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06771 }
06772 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06773 break;
06774 case SIG_FEATB:
06775 case SIG_SF_FEATB:
06776 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06777 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06778 break;
06779 case SIG_EMWINK:
06780
06781
06782
06783
06784 if (res == '*') {
06785 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06786 if (res > 0)
06787 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06788 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06789 break;
06790 }
06791 default:
06792
06793 len = 1;
06794 dtmfbuf[len] = '\0';
06795 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06796 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06797 timeout = matchdigittimeout;
06798 } else {
06799 timeout = gendigittimeout;
06800 }
06801 res = ast_waitfordigit(chan, timeout);
06802 if (res < 0) {
06803 ast_debug(1, "waitfordigit returned < 0...\n");
06804 ast_hangup(chan);
06805 goto quit;
06806 } else if (res) {
06807 dtmfbuf[len++] = res;
06808 dtmfbuf[len] = '\0';
06809 } else {
06810 break;
06811 }
06812 }
06813 break;
06814 }
06815 }
06816 if (res == -1) {
06817 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06818 ast_hangup(chan);
06819 goto quit;
06820 } else if (res < 0) {
06821 ast_debug(1, "Got hung up before digits finished\n");
06822 ast_hangup(chan);
06823 goto quit;
06824 }
06825
06826 if (p->sig == SIG_FGC_CAMA) {
06827 char anibuf[100];
06828
06829 if (ast_safe_sleep(chan,1000) == -1) {
06830 ast_hangup(chan);
06831 goto quit;
06832 }
06833 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06834 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06835 res = my_getsigstr(chan, anibuf, "#", 10000);
06836 if ((res > 0) && (strlen(anibuf) > 2)) {
06837 if (anibuf[strlen(anibuf) - 1] == '#')
06838 anibuf[strlen(anibuf) - 1] = 0;
06839 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06840 }
06841 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06842 }
06843
06844 ast_copy_string(exten, dtmfbuf, sizeof(exten));
06845 if (ast_strlen_zero(exten))
06846 ast_copy_string(exten, "s", sizeof(exten));
06847 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06848
06849 if (exten[0] == '*') {
06850 char *stringp=NULL;
06851 ast_copy_string(exten2, exten, sizeof(exten2));
06852
06853 stringp=exten2 +1;
06854 s1 = strsep(&stringp, "*");
06855 s2 = strsep(&stringp, "*");
06856 if (s2) {
06857 if (!ast_strlen_zero(p->cid_num))
06858 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06859 else
06860 ast_set_callerid(chan, s1, NULL, s1);
06861 ast_copy_string(exten, s2, sizeof(exten));
06862 } else
06863 ast_copy_string(exten, s1, sizeof(exten));
06864 } else if (p->sig == SIG_FEATD)
06865 ast_log(LOG_WARNING, "Got a non-Feature Group D 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 if (exten[0] == '*') {
06869 char *stringp=NULL;
06870 ast_copy_string(exten2, exten, sizeof(exten2));
06871
06872 stringp=exten2 +1;
06873 s1 = strsep(&stringp, "#");
06874 s2 = strsep(&stringp, "#");
06875 if (s2) {
06876 if (!ast_strlen_zero(p->cid_num))
06877 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06878 else
06879 if (*(s1 + 2))
06880 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06881 ast_copy_string(exten, s2 + 1, sizeof(exten));
06882 } else
06883 ast_copy_string(exten, s1 + 2, sizeof(exten));
06884 } else
06885 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06886 }
06887 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06888 if (exten[0] == '*') {
06889 char *stringp=NULL;
06890 ast_copy_string(exten2, exten, sizeof(exten2));
06891
06892 stringp=exten2 +1;
06893 s1 = strsep(&stringp, "#");
06894 s2 = strsep(&stringp, "#");
06895 if (s2 && (*(s2 + 1) == '0')) {
06896 if (*(s2 + 2))
06897 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06898 }
06899 if (s1) ast_copy_string(exten, s1, sizeof(exten));
06900 else ast_copy_string(exten, "911", sizeof(exten));
06901 } else
06902 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
06903 }
06904 if (p->sig == SIG_FEATB) {
06905 if (exten[0] == '*') {
06906 char *stringp=NULL;
06907 ast_copy_string(exten2, exten, sizeof(exten2));
06908
06909 stringp=exten2 +1;
06910 s1 = strsep(&stringp, "#");
06911 ast_copy_string(exten, exten2 + 1, sizeof(exten));
06912 } else
06913 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
06914 }
06915 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06916 dahdi_wink(p, idx);
06917
06918
06919
06920 if (ast_safe_sleep(chan,100)) goto quit;
06921 }
06922 dahdi_enable_ec(p);
06923 if (NEED_MFDETECT(p)) {
06924 if (p->dsp) {
06925 if (!p->hardwaredtmf)
06926 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06927 else {
06928 ast_dsp_free(p->dsp);
06929 p->dsp = NULL;
06930 }
06931 }
06932 }
06933
06934 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06935 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06936 if (p->dsp) ast_dsp_digitreset(p->dsp);
06937 res = ast_pbx_run(chan);
06938 if (res) {
06939 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06940 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06941 }
06942 goto quit;
06943 } else {
06944 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06945 sleep(2);
06946 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
06947 if (res < 0)
06948 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06949 else
06950 sleep(1);
06951 res = ast_streamfile(chan, "ss-noservice", chan->language);
06952 if (res >= 0)
06953 ast_waitstream(chan, "");
06954 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06955 ast_hangup(chan);
06956 goto quit;
06957 }
06958 break;
06959 case SIG_FXOLS:
06960 case SIG_FXOGS:
06961 case SIG_FXOKS:
06962
06963 timeout = firstdigittimeout;
06964
06965
06966 if (p->subs[SUB_THREEWAY].owner)
06967 timeout = 999999;
06968 while (len < AST_MAX_EXTENSION-1) {
06969
06970
06971 if (p->immediate)
06972 res = 's';
06973 else
06974 res = ast_waitfordigit(chan, timeout);
06975 timeout = 0;
06976 if (res < 0) {
06977 ast_debug(1, "waitfordigit returned < 0...\n");
06978 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06979 ast_hangup(chan);
06980 goto quit;
06981 } else if (res) {
06982 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
06983 exten[len++]=res;
06984 exten[len] = '\0';
06985 }
06986 if (!ast_ignore_pattern(chan->context, exten))
06987 tone_zone_play_tone(p->subs[idx].dfd, -1);
06988 else
06989 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06990 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06991 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06992 if (getforward) {
06993
06994 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
06995 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06996 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06997 if (res)
06998 break;
06999 usleep(500000);
07000 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07001 sleep(1);
07002 memset(exten, 0, sizeof(exten));
07003 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
07004 len = 0;
07005 getforward = 0;
07006 } else {
07007 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07008 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07009 if (!ast_strlen_zero(p->cid_num)) {
07010 if (!p->hidecallerid)
07011 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07012 else
07013 ast_set_callerid(chan, NULL, NULL, p->cid_num);
07014 }
07015 if (!ast_strlen_zero(p->cid_name)) {
07016 if (!p->hidecallerid)
07017 ast_set_callerid(chan, NULL, p->cid_name, NULL);
07018 }
07019 ast_setstate(chan, AST_STATE_RING);
07020 dahdi_enable_ec(p);
07021 res = ast_pbx_run(chan);
07022 if (res) {
07023 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07024 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07025 }
07026 goto quit;
07027 }
07028 } else {
07029
07030
07031 timeout = matchdigittimeout;
07032 }
07033 } else if (res == 0) {
07034 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
07035 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07036 dahdi_wait_event(p->subs[idx].dfd);
07037 ast_hangup(chan);
07038 goto quit;
07039 } else if (p->callwaiting && !strcmp(exten, "*70")) {
07040 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
07041
07042 p->callwaiting = 0;
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 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
07050 memset(exten, 0, sizeof(exten));
07051 timeout = firstdigittimeout;
07052
07053 } else if (!strcmp(exten,ast_pickup_ext())) {
07054
07055
07056
07057
07058 if (idx == SUB_REAL) {
07059
07060 if (p->subs[SUB_THREEWAY].owner) {
07061
07062
07063 alloc_sub(p, SUB_CALLWAIT);
07064 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07065 unalloc_sub(p, SUB_THREEWAY);
07066 }
07067 dahdi_enable_ec(p);
07068 if (ast_pickup_call(chan)) {
07069 ast_debug(1, "No call pickup possible...\n");
07070 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07071 dahdi_wait_event(p->subs[idx].dfd);
07072 }
07073 ast_hangup(chan);
07074 goto quit;
07075 } else {
07076 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07077 ast_hangup(chan);
07078 goto quit;
07079 }
07080
07081 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07082 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
07083
07084 p->hidecallerid = 1;
07085 if (chan->cid.cid_num)
07086 ast_free(chan->cid.cid_num);
07087 chan->cid.cid_num = NULL;
07088 if (chan->cid.cid_name)
07089 ast_free(chan->cid.cid_name);
07090 chan->cid.cid_name = NULL;
07091 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07092 if (res) {
07093 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07094 chan->name, strerror(errno));
07095 }
07096 len = 0;
07097 memset(exten, 0, sizeof(exten));
07098 timeout = firstdigittimeout;
07099 } else if (p->callreturn && !strcmp(exten, "*69")) {
07100 res = 0;
07101 if (!ast_strlen_zero(p->lastcid_num)) {
07102 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07103 }
07104 if (!res)
07105 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07106 break;
07107 } else if (!strcmp(exten, "*78")) {
07108 dahdi_dnd(p, 1);
07109
07110 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07111 getforward = 0;
07112 memset(exten, 0, sizeof(exten));
07113 len = 0;
07114 } else if (!strcmp(exten, "*79")) {
07115 dahdi_dnd(p, 0);
07116
07117 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07118 getforward = 0;
07119 memset(exten, 0, sizeof(exten));
07120 len = 0;
07121 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07122 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07123 getforward = 1;
07124 memset(exten, 0, sizeof(exten));
07125 len = 0;
07126 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07127 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
07128 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07129 memset(p->call_forward, 0, sizeof(p->call_forward));
07130 getforward = 0;
07131 memset(exten, 0, sizeof(exten));
07132 len = 0;
07133 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07134 p->subs[SUB_THREEWAY].owner &&
07135 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07136
07137
07138 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07139 ast_verb(3, "Parking call to '%s'\n", chan->name);
07140 break;
07141 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07142 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
07143 res = ast_db_put("blacklist", p->lastcid_num, "1");
07144 if (!res) {
07145 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07146 memset(exten, 0, sizeof(exten));
07147 len = 0;
07148 }
07149 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07150 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
07151
07152 p->hidecallerid = 0;
07153 if (chan->cid.cid_num)
07154 ast_free(chan->cid.cid_num);
07155 chan->cid.cid_num = NULL;
07156 if (chan->cid.cid_name)
07157 ast_free(chan->cid.cid_name);
07158 chan->cid.cid_name = NULL;
07159 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07160 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07161 if (res) {
07162 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07163 chan->name, strerror(errno));
07164 }
07165 len = 0;
07166 memset(exten, 0, sizeof(exten));
07167 timeout = firstdigittimeout;
07168 } else if (!strcmp(exten, "*0")) {
07169 struct ast_channel *nbridge =
07170 p->subs[SUB_THREEWAY].owner;
07171 struct dahdi_pvt *pbridge = NULL;
07172
07173 if (nbridge && ast_bridged_channel(nbridge))
07174 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07175 if (nbridge && pbridge &&
07176 (nbridge->tech == &dahdi_tech) &&
07177 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
07178 ISTRUNK(pbridge)) {
07179 int func = DAHDI_FLASH;
07180
07181 p->dop.dialstr[0] = '\0';
07182
07183 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07184 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07185 nbridge->name, strerror(errno));
07186 }
07187 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07188 unalloc_sub(p, SUB_THREEWAY);
07189 p->owner = p->subs[SUB_REAL].owner;
07190 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07191 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07192 ast_hangup(chan);
07193 goto quit;
07194 } else {
07195 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07196 dahdi_wait_event(p->subs[idx].dfd);
07197 tone_zone_play_tone(p->subs[idx].dfd, -1);
07198 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07199 unalloc_sub(p, SUB_THREEWAY);
07200 p->owner = p->subs[SUB_REAL].owner;
07201 ast_hangup(chan);
07202 goto quit;
07203 }
07204 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07205 ((exten[0] != '*') || (strlen(exten) > 2))) {
07206 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);
07207 break;
07208 }
07209 if (!timeout)
07210 timeout = gendigittimeout;
07211 if (len && !ast_ignore_pattern(chan->context, exten))
07212 tone_zone_play_tone(p->subs[idx].dfd, -1);
07213 }
07214 break;
07215 case SIG_FXSLS:
07216 case SIG_FXSGS:
07217 case SIG_FXSKS:
07218 #ifdef HAVE_PRI
07219 if (p->pri) {
07220
07221 struct ast_frame *f;
07222 int res;
07223 time_t start;
07224
07225 time(&start);
07226 ast_setstate(chan, AST_STATE_RING);
07227 while (time(NULL) < start + 3) {
07228 res = ast_waitfor(chan, 1000);
07229 if (res) {
07230 f = ast_read(chan);
07231 if (!f) {
07232 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07233 ast_hangup(chan);
07234 goto quit;
07235 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07236 res = 1;
07237 } else
07238 res = 0;
07239 ast_frfree(f);
07240 if (res) {
07241 ast_debug(1, "Got ring!\n");
07242 res = 0;
07243 break;
07244 }
07245 }
07246 }
07247 }
07248 #endif
07249
07250 if (p->use_smdi && p->smdi_iface) {
07251 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07252
07253 if (smdi_msg != NULL) {
07254 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07255
07256 if (smdi_msg->type == 'B')
07257 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07258 else if (smdi_msg->type == 'N')
07259 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07260
07261 ast_debug(1, "Received SMDI message on %s\n", chan->name);
07262 } else {
07263 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07264 }
07265 }
07266
07267 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07268 number = smdi_msg->calling_st;
07269
07270
07271
07272
07273 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
07274
07275 if (p->cid_signalling == CID_SIG_DTMF) {
07276 int k = 0;
07277 cs = NULL;
07278 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
07279 dahdi_setlinear(p->subs[idx].dfd, 0);
07280
07281
07282
07283
07284
07285
07286 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
07287 res = 4000;
07288 for (;;) {
07289 struct ast_frame *f;
07290 res = ast_waitfor(chan, res);
07291 if (res <= 0) {
07292
07293
07294
07295
07296
07297 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07298 "Exiting simple switch\n");
07299 ast_hangup(chan);
07300 goto quit;
07301 }
07302 f = ast_read(chan);
07303 if (!f)
07304 break;
07305 if (f->frametype == AST_FRAME_DTMF) {
07306 if (k < ARRAY_LEN(dtmfbuf) - 1) {
07307 dtmfbuf[k++] = f->subclass;
07308 }
07309 ast_debug(1, "CID got digit '%c'\n", f->subclass);
07310 res = 4000;
07311 }
07312 ast_frfree(f);
07313 if (chan->_state == AST_STATE_RING ||
07314 chan->_state == AST_STATE_RINGING)
07315 break;
07316 }
07317 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
07318 dtmfbuf[k] = '\0';
07319 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07320
07321 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
07322 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07323 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
07324
07325 if (!ast_strlen_zero(dtmfcid))
07326 number = dtmfcid;
07327 else
07328 number = NULL;
07329
07330 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07331 cs = callerid_new(p->cid_signalling);
07332 if (cs) {
07333 samples = 0;
07334 #if 1
07335 bump_gains(p);
07336 #endif
07337
07338 dahdi_setlinear(p->subs[idx].dfd, 0);
07339
07340
07341 for (;;) {
07342 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07343 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07344 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07345 callerid_free(cs);
07346 ast_hangup(chan);
07347 goto quit;
07348 }
07349 if (i & DAHDI_IOMUX_SIGEVENT) {
07350 res = dahdi_get_event(p->subs[idx].dfd);
07351 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07352 if (res == DAHDI_EVENT_NOALARM) {
07353 p->inalarm = 0;
07354 }
07355
07356 if (p->cid_signalling == CID_SIG_V23_JP) {
07357 if (res == DAHDI_EVENT_RINGBEGIN) {
07358 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07359 usleep(1);
07360 }
07361 } else {
07362 res = 0;
07363 break;
07364 }
07365 } else if (i & DAHDI_IOMUX_READ) {
07366 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07367 if (res < 0) {
07368 if (errno != ELAST) {
07369 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07370 callerid_free(cs);
07371 ast_hangup(chan);
07372 goto quit;
07373 }
07374 break;
07375 }
07376 samples += res;
07377
07378 if (p->cid_signalling == CID_SIG_V23_JP) {
07379 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07380 } else {
07381 res = callerid_feed(cs, buf, res, AST_LAW(p));
07382 }
07383 if (res < 0) {
07384
07385
07386
07387
07388 ast_log(LOG_WARNING,
07389 "Failed to decode CallerID on channel '%s'\n",
07390 chan->name);
07391 break;
07392 } else if (res)
07393 break;
07394 else if (samples > (8000 * 10))
07395 break;
07396 }
07397 }
07398 if (res == 1) {
07399 callerid_get(cs, &name, &number, &flags);
07400 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07401 }
07402
07403 if (p->cid_signalling == CID_SIG_V23_JP) {
07404 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07405 usleep(1);
07406 }
07407
07408
07409 res = 4000;
07410 for (;;) {
07411 struct ast_frame *f;
07412 res = ast_waitfor(chan, res);
07413 if (res <= 0) {
07414 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07415 "Exiting simple switch\n");
07416 ast_hangup(chan);
07417 goto quit;
07418 }
07419 if (!(f = ast_read(chan))) {
07420 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07421 ast_hangup(chan);
07422 goto quit;
07423 }
07424 ast_frfree(f);
07425 if (chan->_state == AST_STATE_RING ||
07426 chan->_state == AST_STATE_RINGING)
07427 break;
07428 }
07429
07430
07431
07432 if (p->usedistinctiveringdetection) {
07433 len = 0;
07434 distMatches = 0;
07435
07436 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07437 curRingData[receivedRingT] = 0;
07438 receivedRingT = 0;
07439 counter = 0;
07440 counter1 = 0;
07441
07442 if (strcmp(p->context,p->defcontext) != 0) {
07443 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07444 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07445 }
07446
07447 for (;;) {
07448 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07449 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07450 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07451 callerid_free(cs);
07452 ast_hangup(chan);
07453 goto quit;
07454 }
07455 if (i & DAHDI_IOMUX_SIGEVENT) {
07456 res = dahdi_get_event(p->subs[idx].dfd);
07457 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07458 if (res == DAHDI_EVENT_NOALARM) {
07459 p->inalarm = 0;
07460 }
07461 res = 0;
07462
07463
07464 curRingData[receivedRingT] = p->ringt;
07465
07466 if (p->ringt < p->ringt_base/2)
07467 break;
07468
07469
07470 if (++receivedRingT == ARRAY_LEN(curRingData))
07471 break;
07472 } else if (i & DAHDI_IOMUX_READ) {
07473 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07474 if (res < 0) {
07475 if (errno != ELAST) {
07476 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07477 callerid_free(cs);
07478 ast_hangup(chan);
07479 goto quit;
07480 }
07481 break;
07482 }
07483 if (p->ringt)
07484 p->ringt--;
07485 if (p->ringt == 1) {
07486 res = -1;
07487 break;
07488 }
07489 }
07490 }
07491
07492 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07493 for (counter = 0; counter < 3; counter++) {
07494
07495
07496 distMatches = 0;
07497 for (counter1 = 0; counter1 < 3; counter1++) {
07498 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07499 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07500 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07501 curRingData[counter1]);
07502 distMatches++;
07503 }
07504 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07505 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07506 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07507 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07508 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07509 distMatches++;
07510 }
07511 }
07512
07513 if (distMatches == 3) {
07514
07515 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07516 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07517 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07518 break;
07519 }
07520 }
07521 }
07522
07523 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07524 #if 1
07525 restore_gains(p);
07526 #endif
07527 } else
07528 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07529 } else {
07530 ast_log(LOG_WARNING, "Channel %s in prering "
07531 "state, but I have nothing to do. "
07532 "Terminating simple switch, should be "
07533 "restarted by the actual ring.\n",
07534 chan->name);
07535 ast_hangup(chan);
07536 goto quit;
07537 }
07538 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07539 if (p->cid_signalling == CID_SIG_DTMF) {
07540 int k = 0;
07541 cs = NULL;
07542 dahdi_setlinear(p->subs[idx].dfd, 0);
07543 res = 2000;
07544 for (;;) {
07545 struct ast_frame *f;
07546 res = ast_waitfor(chan, res);
07547 if (res <= 0) {
07548 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07549 "Exiting simple switch\n");
07550 ast_hangup(chan);
07551 return NULL;
07552 }
07553 f = ast_read(chan);
07554 if (f->frametype == AST_FRAME_DTMF) {
07555 dtmfbuf[k++] = f->subclass;
07556 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07557 res = 2000;
07558 }
07559 ast_frfree(f);
07560
07561 if (p->ringt_base == p->ringt)
07562 break;
07563
07564 }
07565 dtmfbuf[k] = '\0';
07566 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07567
07568 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07569 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07570 dtmfcid, flags);
07571
07572 if (!ast_strlen_zero(dtmfcid))
07573 number = dtmfcid;
07574 else
07575 number = NULL;
07576
07577 } else {
07578
07579 cs = callerid_new(p->cid_signalling);
07580 if (cs) {
07581 #if 1
07582 bump_gains(p);
07583 #endif
07584 samples = 0;
07585 len = 0;
07586 distMatches = 0;
07587
07588 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07589 curRingData[receivedRingT] = 0;
07590 receivedRingT = 0;
07591 counter = 0;
07592 counter1 = 0;
07593
07594 if (strcmp(p->context,p->defcontext) != 0) {
07595 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07596 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07597 }
07598
07599
07600 dahdi_setlinear(p->subs[idx].dfd, 0);
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 if (res == DAHDI_EVENT_NOALARM) {
07613 p->inalarm = 0;
07614 }
07615
07616 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07617 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07618 p->polarity = POLARITY_IDLE;
07619 callerid_free(cs);
07620 ast_hangup(chan);
07621 goto quit;
07622 }
07623 res = 0;
07624
07625
07626 curRingData[receivedRingT] = p->ringt;
07627
07628 if (p->ringt < p->ringt_base/2)
07629 break;
07630
07631
07632 if (++receivedRingT == ARRAY_LEN(curRingData))
07633 break;
07634 } else if (i & DAHDI_IOMUX_READ) {
07635 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07636 if (res < 0) {
07637 if (errno != ELAST) {
07638 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07639 callerid_free(cs);
07640 ast_hangup(chan);
07641 goto quit;
07642 }
07643 break;
07644 }
07645 if (p->ringt)
07646 p->ringt--;
07647 if (p->ringt == 1) {
07648 res = -1;
07649 break;
07650 }
07651 samples += res;
07652 res = callerid_feed(cs, buf, res, AST_LAW(p));
07653 if (res < 0) {
07654
07655
07656
07657
07658 ast_log(LOG_WARNING,
07659 "Failed to decode CallerID on channel '%s'\n",
07660 chan->name);
07661 break;
07662 } else if (res)
07663 break;
07664 else if (samples > (8000 * 10))
07665 break;
07666 }
07667 }
07668 if (res == 1) {
07669 callerid_get(cs, &name, &number, &flags);
07670 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07671 }
07672 if (distinctiveringaftercid == 1) {
07673
07674 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07675 curRingData[receivedRingT] = 0;
07676 }
07677 receivedRingT = 0;
07678 ast_verb(3, "Detecting post-CID distinctive ring\n");
07679 for (;;) {
07680 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07681 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07682 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07683 callerid_free(cs);
07684 ast_hangup(chan);
07685 goto quit;
07686 }
07687 if (i & DAHDI_IOMUX_SIGEVENT) {
07688 res = dahdi_get_event(p->subs[idx].dfd);
07689 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07690 if (res == DAHDI_EVENT_NOALARM) {
07691 p->inalarm = 0;
07692 }
07693 res = 0;
07694
07695
07696 curRingData[receivedRingT] = p->ringt;
07697
07698 if (p->ringt < p->ringt_base/2)
07699 break;
07700
07701
07702 if (++receivedRingT == ARRAY_LEN(curRingData))
07703 break;
07704 } else if (i & DAHDI_IOMUX_READ) {
07705 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07706 if (res < 0) {
07707 if (errno != ELAST) {
07708 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07709 callerid_free(cs);
07710 ast_hangup(chan);
07711 goto quit;
07712 }
07713 break;
07714 }
07715 if (p->ringt)
07716 p->ringt--;
07717 if (p->ringt == 1) {
07718 res = -1;
07719 break;
07720 }
07721 }
07722 }
07723 }
07724 if (p->usedistinctiveringdetection) {
07725
07726 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07727
07728 for (counter = 0; counter < 3; counter++) {
07729
07730
07731
07732 ast_verb(3, "Checking %d,%d,%d\n",
07733 p->drings.ringnum[counter].ring[0],
07734 p->drings.ringnum[counter].ring[1],
07735 p->drings.ringnum[counter].ring[2]);
07736 distMatches = 0;
07737 for (counter1 = 0; counter1 < 3; counter1++) {
07738 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07739 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07740 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07741 curRingData[counter1]);
07742 distMatches++;
07743 }
07744 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07745 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07746 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07747 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07748 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07749 distMatches++;
07750 }
07751 }
07752 if (distMatches == 3) {
07753
07754 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07755 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07756 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07757 break;
07758 }
07759 }
07760 }
07761
07762 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07763 #if 1
07764 restore_gains(p);
07765 #endif
07766 if (res < 0) {
07767 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07768 }
07769 } else
07770 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07771 }
07772 }
07773 else
07774 cs = NULL;
07775
07776 if (number)
07777 ast_shrink_phone_number(number);
07778 ast_set_callerid(chan, number, name, number);
07779
07780 if (smdi_msg)
07781 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07782
07783 if (cs)
07784 callerid_free(cs);
07785
07786 if (flags & CID_MSGWAITING) {
07787 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
07788 notify_message(p->mailbox, 1);
07789
07790 if (p->mwimonitor_rpas) {
07791 ast_hangup(chan);
07792 return NULL;
07793 }
07794 } else if (flags & CID_NOMSGWAITING) {
07795 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
07796 notify_message(p->mailbox, 0);
07797
07798 if (p->mwimonitor_rpas) {
07799 ast_hangup(chan);
07800 return NULL;
07801 }
07802 }
07803
07804 ast_setstate(chan, AST_STATE_RING);
07805 chan->rings = 1;
07806 p->ringt = p->ringt_base;
07807 res = ast_pbx_run(chan);
07808 if (res) {
07809 ast_hangup(chan);
07810 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07811 }
07812 goto quit;
07813 default:
07814 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07815 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07816 if (res < 0)
07817 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07818 }
07819 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07820 if (res < 0)
07821 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07822 ast_hangup(chan);
07823 quit:
07824 ast_mutex_lock(&ss_thread_lock);
07825 ss_thread_count--;
07826 ast_cond_signal(&ss_thread_complete);
07827 ast_mutex_unlock(&ss_thread_lock);
07828 return NULL;
07829 }
07830
07831 struct mwi_thread_data {
07832 struct dahdi_pvt *pvt;
07833 unsigned char buf[READ_SIZE];
07834 size_t len;
07835 };
07836
07837 static int calc_energy(const unsigned char *buf, int len, int law)
07838 {
07839 int x;
07840 int sum = 0;
07841
07842 if (!len)
07843 return 0;
07844
07845 for (x = 0; x < len; x++)
07846 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07847
07848 return sum / len;
07849 }
07850
07851 static void *mwi_thread(void *data)
07852 {
07853 struct mwi_thread_data *mtd = data;
07854 struct callerid_state *cs;
07855 pthread_t threadid;
07856 int samples = 0;
07857 char *name, *number;
07858 int flags;
07859 int i, res;
07860 unsigned int spill_done = 0;
07861 int spill_result = -1;
07862
07863 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
07864 mtd->pvt->mwimonitoractive = 0;
07865
07866 return NULL;
07867 }
07868
07869 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
07870
07871 bump_gains(mtd->pvt);
07872
07873 for (;;) {
07874 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07875 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07876 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07877 goto quit;
07878 }
07879
07880 if (i & DAHDI_IOMUX_SIGEVENT) {
07881 struct ast_channel *chan;
07882
07883
07884
07885
07886 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07887
07888 switch (res) {
07889 case DAHDI_EVENT_NEONMWI_ACTIVE:
07890 case DAHDI_EVENT_NEONMWI_INACTIVE:
07891 case DAHDI_EVENT_NONE:
07892 case DAHDI_EVENT_BITSCHANGED:
07893 break;
07894 case DAHDI_EVENT_NOALARM:
07895 mtd->pvt->inalarm = 0;
07896 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
07897 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07898 "Channel: %d\r\n", mtd->pvt->channel);
07899 break;
07900 case DAHDI_EVENT_ALARM:
07901 mtd->pvt->inalarm = 1;
07902 res = get_alarms(mtd->pvt);
07903 handle_alarms(mtd->pvt, res);
07904 break;
07905 default:
07906 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
07907 callerid_free(cs);
07908
07909 restore_gains(mtd->pvt);
07910 mtd->pvt->ringt = mtd->pvt->ringt_base;
07911
07912 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
07913 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07914 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
07915 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07916 if (res < 0)
07917 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
07918 ast_hangup(chan);
07919 goto quit;
07920 }
07921 goto quit_no_clean;
07922
07923 } else {
07924 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
07925 }
07926 }
07927 } else if (i & DAHDI_IOMUX_READ) {
07928 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07929 if (errno != ELAST) {
07930 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07931 goto quit;
07932 }
07933 break;
07934 }
07935 samples += res;
07936 if (!spill_done) {
07937 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
07938
07939
07940
07941
07942 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
07943 break;
07944 } else if (spill_result) {
07945 spill_done = 1;
07946 }
07947 } else {
07948
07949
07950
07951 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
07952 break;
07953 }
07954 if (samples > (8000 * 4))
07955 break;
07956 }
07957 }
07958
07959 if (spill_result == 1) {
07960 callerid_get(cs, &name, &number, &flags);
07961 if (flags & CID_MSGWAITING) {
07962 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
07963 notify_message(mtd->pvt->mailbox, 1);
07964 } else if (flags & CID_NOMSGWAITING) {
07965 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
07966 notify_message(mtd->pvt->mailbox, 0);
07967 } else {
07968 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
07969 }
07970 }
07971
07972
07973 quit:
07974 callerid_free(cs);
07975
07976 restore_gains(mtd->pvt);
07977
07978 quit_no_clean:
07979 mtd->pvt->mwimonitoractive = 0;
07980
07981 ast_free(mtd);
07982
07983 return NULL;
07984 }
07985
07986
07987
07988
07989 enum mwisend_states {
07990 MWI_SEND_SA,
07991 MWI_SEND_SA_WAIT,
07992 MWI_SEND_PAUSE,
07993 MWI_SEND_SPILL,
07994 MWI_SEND_CLEANUP,
07995 MWI_SEND_DONE
07996 };
07997
07998 static void *mwi_send_thread(void *data)
07999 {
08000 struct mwi_thread_data *mtd = data;
08001 struct timeval timeout_basis, suspend, now;
08002 int x, i, res;
08003 int num_read;
08004 enum mwisend_states mwi_send_state = MWI_SEND_SPILL;
08005
08006 ast_mutex_lock(&mwi_thread_lock);
08007 mwi_thread_count++;
08008 ast_mutex_unlock(&mwi_thread_lock);
08009
08010
08011 if(mwisend_rpas) {
08012 mwi_send_state = MWI_SEND_SA;
08013 }
08014
08015 gettimeofday(&timeout_basis, NULL);
08016
08017 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
08018 if (!mtd->pvt->cidspill) {
08019 mtd->pvt->mwisendactive = 0;
08020 ast_free(mtd);
08021 return NULL;
08022 }
08023 x = DAHDI_FLUSH_BOTH;
08024 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08025 x = 3000;
08026 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08027 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
08028 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
08029 mtd->pvt->cidpos = 0;
08030
08031 while (MWI_SEND_DONE != mwi_send_state) {
08032 num_read = 0;
08033 gettimeofday(&now, NULL);
08034 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
08035 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
08036 goto quit;
08037 }
08038
08039 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08040 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
08041 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08042 goto quit;
08043 }
08044
08045 if (i & DAHDI_IOMUX_SIGEVENT) {
08046
08047
08048
08049 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
08050 switch (res) {
08051 case DAHDI_EVENT_RINGEROFF:
08052 if(mwi_send_state == MWI_SEND_SA_WAIT) {
08053 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
08054 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
08055 goto quit;
08056 }
08057 mwi_send_state = MWI_SEND_PAUSE;
08058 gettimeofday(&suspend, NULL);
08059 }
08060 break;
08061 case DAHDI_EVENT_RINGERON:
08062 case DAHDI_EVENT_HOOKCOMPLETE:
08063 break;
08064 default:
08065
08066 if (0 < handle_init_event(mtd->pvt, res)) {
08067
08068 goto quit;
08069 }
08070 break;
08071 }
08072 } else if (i & DAHDI_IOMUX_READ) {
08073 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
08074 if (errno != ELAST) {
08075 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08076 goto quit;
08077 }
08078 break;
08079 }
08080 }
08081
08082 switch ( mwi_send_state) {
08083 case MWI_SEND_SA:
08084
08085 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
08086 if (res) {
08087 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
08088 goto quit;
08089 }
08090 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING);
08091 mwi_send_state = MWI_SEND_SA_WAIT;
08092 break;
08093 case MWI_SEND_SA_WAIT:
08094 break;
08095 case MWI_SEND_PAUSE:
08096 gettimeofday(&now, NULL);
08097 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
08098 mwi_send_state = MWI_SEND_SPILL;
08099 }
08100 break;
08101 case MWI_SEND_SPILL:
08102
08103 if(0 < num_read) {
08104 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
08105 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
08106 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
08107 if (res > 0) {
08108 mtd->pvt->cidpos += res;
08109 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
08110 ast_free(mtd->pvt->cidspill);
08111 mtd->pvt->cidspill = NULL;
08112 mtd->pvt->cidpos = 0;
08113 mtd->pvt->cidlen = 0;
08114 mwi_send_state = MWI_SEND_CLEANUP;
08115 }
08116 } else {
08117 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
08118 goto quit;
08119 }
08120 }
08121 break;
08122 case MWI_SEND_CLEANUP:
08123
08124 mwi_send_state = MWI_SEND_DONE;
08125 break;
08126 default:
08127
08128 goto quit;
08129 break;
08130 }
08131 }
08132
08133 quit:
08134 if(mtd->pvt->cidspill) {
08135 ast_free(mtd->pvt->cidspill);
08136 mtd->pvt->cidspill = NULL;
08137 }
08138 mtd->pvt->mwisendactive = 0;
08139 ast_free(mtd);
08140
08141 ast_mutex_lock(&mwi_thread_lock);
08142 mwi_thread_count--;
08143 ast_cond_signal(&mwi_thread_complete);
08144 ast_mutex_unlock(&mwi_thread_lock);
08145
08146 return NULL;
08147 }
08148
08149
08150
08151 static int dahdi_destroy_channel_bynum(int channel)
08152 {
08153 struct dahdi_pvt *tmp = NULL;
08154 struct dahdi_pvt *prev = NULL;
08155
08156 tmp = iflist;
08157 while (tmp) {
08158 if (tmp->channel == channel) {
08159 int x = DAHDI_FLASH;
08160 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08161 destroy_channel(prev, tmp, 1);
08162 ast_module_unref(ast_module_info->self);
08163 return RESULT_SUCCESS;
08164 }
08165 prev = tmp;
08166 tmp = tmp->next;
08167 }
08168 return RESULT_FAILURE;
08169 }
08170
08171 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
08172 {
08173 int res;
08174 pthread_t threadid;
08175 struct ast_channel *chan;
08176
08177
08178
08179 switch (event) {
08180 case DAHDI_EVENT_NONE:
08181 case DAHDI_EVENT_BITSCHANGED:
08182 break;
08183 case DAHDI_EVENT_WINKFLASH:
08184 case DAHDI_EVENT_RINGOFFHOOK:
08185 if (i->inalarm) break;
08186 if (i->radio) break;
08187
08188 switch (i->sig) {
08189 case SIG_FXOLS:
08190 case SIG_FXOGS:
08191 case SIG_FXOKS:
08192 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08193 if (res && (errno == EBUSY))
08194 break;
08195 if (i->cidspill) {
08196
08197 ast_free(i->cidspill);
08198 i->cidspill = NULL;
08199 }
08200 if (i->immediate) {
08201 dahdi_enable_ec(i);
08202
08203 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08204 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08205 if (!chan) {
08206 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08207 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08208 if (res < 0)
08209 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08210 }
08211 } else {
08212
08213 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08214 if (chan) {
08215 if (has_voicemail(i))
08216 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08217 else
08218 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08219 if (res < 0)
08220 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08221 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08222 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08223 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08224 if (res < 0)
08225 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08226 ast_hangup(chan);
08227 }
08228 } else
08229 ast_log(LOG_WARNING, "Unable to create channel\n");
08230 }
08231 break;
08232 case SIG_FXSLS:
08233 case SIG_FXSGS:
08234 case SIG_FXSKS:
08235 i->ringt = i->ringt_base;
08236
08237 case SIG_EMWINK:
08238 case SIG_FEATD:
08239 case SIG_FEATDMF:
08240 case SIG_FEATDMF_TA:
08241 case SIG_E911:
08242 case SIG_FGC_CAMA:
08243 case SIG_FGC_CAMAMF:
08244 case SIG_FEATB:
08245 case SIG_EM:
08246 case SIG_EM_E1:
08247 case SIG_SFWINK:
08248 case SIG_SF_FEATD:
08249 case SIG_SF_FEATDMF:
08250 case SIG_SF_FEATB:
08251 case SIG_SF:
08252
08253 if (i->cid_start == CID_START_POLARITY_IN) {
08254 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08255 } else {
08256 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08257 }
08258
08259 if (!chan) {
08260 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08261 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08262 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08263 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08264 if (res < 0) {
08265 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08266 }
08267 ast_hangup(chan);
08268 }
08269 break;
08270 default:
08271 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08272 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08273 if (res < 0)
08274 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08275 return NULL;
08276 }
08277 break;
08278 case DAHDI_EVENT_NOALARM:
08279 i->inalarm = 0;
08280 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08281 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08282 "Channel: %d\r\n", i->channel);
08283 break;
08284 case DAHDI_EVENT_ALARM:
08285 i->inalarm = 1;
08286 res = get_alarms(i);
08287 handle_alarms(i, res);
08288
08289 case DAHDI_EVENT_ONHOOK:
08290 if (i->radio)
08291 break;
08292
08293 switch (i->sig) {
08294 case SIG_FXOLS:
08295 case SIG_FXOGS:
08296 case SIG_FEATD:
08297 case SIG_FEATDMF:
08298 case SIG_FEATDMF_TA:
08299 case SIG_E911:
08300 case SIG_FGC_CAMA:
08301 case SIG_FGC_CAMAMF:
08302 case SIG_FEATB:
08303 case SIG_EM:
08304 case SIG_EM_E1:
08305 case SIG_EMWINK:
08306 case SIG_SF_FEATD:
08307 case SIG_SF_FEATDMF:
08308 case SIG_SF_FEATB:
08309 case SIG_SF:
08310 case SIG_SFWINK:
08311 case SIG_FXSLS:
08312 case SIG_FXSGS:
08313 case SIG_FXSKS:
08314 case SIG_GR303FXSKS:
08315 dahdi_disable_ec(i);
08316 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08317 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08318 break;
08319 case SIG_GR303FXOKS:
08320 case SIG_FXOKS:
08321 dahdi_disable_ec(i);
08322
08323 #ifdef ZHONE_HACK
08324 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08325 usleep(1);
08326 #endif
08327 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08328 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08329 break;
08330 case SIG_PRI:
08331 case SIG_SS7:
08332 case SIG_BRI:
08333 case SIG_BRI_PTMP:
08334 dahdi_disable_ec(i);
08335 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08336 break;
08337 default:
08338 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08339 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08340 return NULL;
08341 }
08342 break;
08343 case DAHDI_EVENT_POLARITY:
08344 switch (i->sig) {
08345 case SIG_FXSLS:
08346 case SIG_FXSKS:
08347 case SIG_FXSGS:
08348
08349
08350
08351
08352 if (i->hanguponpolarityswitch)
08353 i->polarity = POLARITY_REV;
08354 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08355 i->polarity = POLARITY_REV;
08356 ast_verb(2, "Starting post polarity "
08357 "CID detection on channel %d\n",
08358 i->channel);
08359 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08360 if (!chan) {
08361 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08362 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08363 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08364 }
08365 }
08366 break;
08367 default:
08368 ast_log(LOG_WARNING, "handle_init_event detected "
08369 "polarity reversal on non-FXO (SIG_FXS) "
08370 "interface %d\n", i->channel);
08371 }
08372 break;
08373 case DAHDI_EVENT_REMOVED:
08374 ast_log(LOG_NOTICE,
08375 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08376 i->channel);
08377 return i;
08378 case DAHDI_EVENT_NEONMWI_ACTIVE:
08379 if (i->mwimonitor_neon) {
08380 notify_message(i->mailbox, 1);
08381 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08382 }
08383 break;
08384 case DAHDI_EVENT_NEONMWI_INACTIVE:
08385 if (i->mwimonitor_neon) {
08386 notify_message(i->mailbox, 0);
08387 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08388 }
08389 break;
08390 }
08391 return NULL;
08392 }
08393
08394 static void *do_monitor(void *data)
08395 {
08396 int count, res, res2, spoint, pollres=0;
08397 struct dahdi_pvt *i;
08398 struct dahdi_pvt *last = NULL;
08399 struct dahdi_pvt *doomed;
08400 time_t thispass = 0, lastpass = 0;
08401 int found;
08402 char buf[1024];
08403 struct pollfd *pfds=NULL;
08404 int lastalloc = -1;
08405
08406
08407
08408 #if 0
08409 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08410 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08411 return NULL;
08412 }
08413 ast_debug(1, "Monitor starting...\n");
08414 #endif
08415 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08416
08417 for (;;) {
08418
08419 ast_mutex_lock(&iflock);
08420 if (!pfds || (lastalloc != ifcount)) {
08421 if (pfds) {
08422 ast_free(pfds);
08423 pfds = NULL;
08424 }
08425 if (ifcount) {
08426 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08427 ast_mutex_unlock(&iflock);
08428 return NULL;
08429 }
08430 }
08431 lastalloc = ifcount;
08432 }
08433
08434
08435 count = 0;
08436 i = iflist;
08437 while (i) {
08438 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08439 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
08440
08441 pfds[count].fd = i->subs[SUB_REAL].dfd;
08442 pfds[count].events = POLLPRI;
08443 pfds[count].revents = 0;
08444
08445
08446 if (i->cidspill || i->mwimonitor_fsk)
08447 pfds[count].events |= POLLIN;
08448 count++;
08449 }
08450 }
08451 i = i->next;
08452 }
08453
08454 ast_mutex_unlock(&iflock);
08455
08456 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08457 pthread_testcancel();
08458
08459 res = poll(pfds, count, 1000);
08460 pthread_testcancel();
08461 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08462
08463
08464 if (res < 0) {
08465 if ((errno != EAGAIN) && (errno != EINTR))
08466 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08467 continue;
08468 }
08469
08470
08471 ast_mutex_lock(&iflock);
08472 found = 0;
08473 spoint = 0;
08474 lastpass = thispass;
08475 thispass = time(NULL);
08476 i = iflist;
08477 doomed = NULL;
08478 for (i = iflist;; i = i->next) {
08479 if (doomed) {
08480 int res;
08481 res = dahdi_destroy_channel_bynum(doomed->channel);
08482 if (!res) {
08483 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08484 }
08485 doomed = NULL;
08486 }
08487 if (!i) {
08488 break;
08489 }
08490
08491 if (thispass != lastpass) {
08492 if (!found && ((i == last) || ((i == iflist) && !last))) {
08493 last = i;
08494 if (last) {
08495 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) {
08496 res = has_voicemail(last);
08497 if (last->msgstate != res) {
08498
08499
08500
08501
08502 pthread_attr_t attr;
08503 pthread_t threadid;
08504 struct mwi_thread_data *mtd;
08505 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08506 if (res2) {
08507
08508 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08509 }
08510 pthread_attr_init(&attr);
08511 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08512 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08513 last->msgstate = res;
08514 mtd->pvt = last;
08515 last->mwisendactive = 1;
08516 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
08517 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
08518 ast_free(mtd);
08519 last->mwisendactive = 0;
08520 }
08521 }
08522 found ++;
08523 }
08524 }
08525 last = last->next;
08526 }
08527 }
08528 }
08529 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08530 if (i->radio && !i->owner)
08531 {
08532 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08533 if (res)
08534 {
08535 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08536
08537 ast_mutex_unlock(&iflock);
08538 doomed = handle_init_event(i, res);
08539 ast_mutex_lock(&iflock);
08540 }
08541 continue;
08542 }
08543 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08544 if (pollres & POLLIN) {
08545 if (i->owner || i->subs[SUB_REAL].owner) {
08546 #ifdef HAVE_PRI
08547 if (!i->pri)
08548 #endif
08549 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08550 continue;
08551 }
08552 if (!i->cidspill && !i->mwimonitor_fsk) {
08553 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08554 continue;
08555 }
08556 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08557 if (res > 0) {
08558 if (i->mwimonitor_fsk) {
08559 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08560 pthread_attr_t attr;
08561 pthread_t threadid;
08562 struct mwi_thread_data *mtd;
08563
08564 pthread_attr_init(&attr);
08565 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08566
08567 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08568 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08569 mtd->pvt = i;
08570 memcpy(mtd->buf, buf, res);
08571 mtd->len = res;
08572 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08573 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08574 ast_free(mtd);
08575 }
08576 i->mwimonitoractive = 1;
08577 }
08578 }
08579 }
08580 } else {
08581 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08582 }
08583 }
08584 if (pollres & POLLPRI) {
08585 if (i->owner || i->subs[SUB_REAL].owner) {
08586 #ifdef HAVE_PRI
08587 if (!i->pri)
08588 #endif
08589 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08590 continue;
08591 }
08592 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08593 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08594
08595 ast_mutex_unlock(&iflock);
08596 doomed = handle_init_event(i, res);
08597 ast_mutex_lock(&iflock);
08598 }
08599 }
08600 }
08601 ast_mutex_unlock(&iflock);
08602 }
08603
08604 return NULL;
08605
08606 }
08607
08608 static int restart_monitor(void)
08609 {
08610
08611 if (monitor_thread == AST_PTHREADT_STOP)
08612 return 0;
08613 ast_mutex_lock(&monlock);
08614 if (monitor_thread == pthread_self()) {
08615 ast_mutex_unlock(&monlock);
08616 ast_log(LOG_WARNING, "Cannot kill myself\n");
08617 return -1;
08618 }
08619 if (monitor_thread != AST_PTHREADT_NULL) {
08620
08621 pthread_kill(monitor_thread, SIGURG);
08622 } else {
08623
08624 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08625 ast_mutex_unlock(&monlock);
08626 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08627 return -1;
08628 }
08629 }
08630 ast_mutex_unlock(&monlock);
08631 return 0;
08632 }
08633
08634 #ifdef HAVE_PRI
08635 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08636 {
08637 int x;
08638 int trunkgroup;
08639
08640 trunkgroup = pris[*span].mastertrunkgroup;
08641 if (trunkgroup) {
08642
08643 for (x = 0; x < NUM_SPANS; x++) {
08644 if (pris[x].trunkgroup == trunkgroup) {
08645 *span = x;
08646 return 0;
08647 }
08648 }
08649 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08650 *span = -1;
08651 } else {
08652 if (pris[*span].trunkgroup) {
08653 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08654 *span = -1;
08655 } else if (pris[*span].mastertrunkgroup) {
08656 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08657 *span = -1;
08658 } else {
08659 if (si->totalchans == 31) {
08660
08661 pris[*span].dchannels[0] = 16 + offset;
08662 } else if (si->totalchans == 24) {
08663
08664 pris[*span].dchannels[0] = 24 + offset;
08665 } else if (si->totalchans == 3) {
08666
08667 pris[*span].dchannels[0] = 3 + offset;
08668 } else {
08669 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);
08670 *span = -1;
08671 return 0;
08672 }
08673 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08674 pris[*span].offset = offset;
08675 pris[*span].span = *span + 1;
08676 }
08677 }
08678 return 0;
08679 }
08680
08681 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08682 {
08683 struct dahdi_spaninfo si;
08684 struct dahdi_params p;
08685 int fd;
08686 int span;
08687 int ospan=0;
08688 int x,y;
08689 for (x = 0; x < NUM_SPANS; x++) {
08690 if (pris[x].trunkgroup == trunkgroup) {
08691 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08692 return -1;
08693 }
08694 }
08695 for (y = 0; y < NUM_DCHANS; y++) {
08696 if (!channels[y])
08697 break;
08698 memset(&si, 0, sizeof(si));
08699 memset(&p, 0, sizeof(p));
08700 fd = open("/dev/dahdi/channel", O_RDWR);
08701 if (fd < 0) {
08702 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08703 return -1;
08704 }
08705 x = channels[y];
08706 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08707 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08708 close(fd);
08709 return -1;
08710 }
08711 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08712 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08713 return -1;
08714 }
08715 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08716 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08717 close(fd);
08718 return -1;
08719 }
08720 span = p.spanno - 1;
08721 if (pris[span].trunkgroup) {
08722 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08723 close(fd);
08724 return -1;
08725 }
08726 if (pris[span].pvts[0]) {
08727 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08728 close(fd);
08729 return -1;
08730 }
08731 if (!y) {
08732 pris[span].trunkgroup = trunkgroup;
08733 pris[span].offset = channels[y] - p.chanpos;
08734 ospan = span;
08735 }
08736 pris[ospan].dchannels[y] = channels[y];
08737 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08738 pris[span].span = span + 1;
08739 close(fd);
08740 }
08741 return 0;
08742 }
08743
08744 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08745 {
08746 if (pris[span].mastertrunkgroup) {
08747 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);
08748 return -1;
08749 }
08750 pris[span].mastertrunkgroup = trunkgroup;
08751 pris[span].prilogicalspan = logicalspan;
08752 return 0;
08753 }
08754
08755 #endif
08756
08757 #ifdef HAVE_SS7
08758
08759 static unsigned int parse_pointcode(const char *pcstring)
08760 {
08761 unsigned int code1, code2, code3;
08762 int numvals;
08763
08764 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
08765 if (numvals == 1)
08766 return code1;
08767 if (numvals == 3)
08768 return (code1 << 16) | (code2 << 8) | code3;
08769
08770 return 0;
08771 }
08772
08773 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
08774 {
08775 if ((linkset < 0) || (linkset >= NUM_SPANS))
08776 return NULL;
08777 else
08778 return &linksets[linkset - 1];
08779 }
08780 #endif
08781
08782
08783
08784
08785
08786
08787 static int sigtype_to_signalling(int sigtype)
08788 {
08789 return sigtype;
08790 }
08791
08792 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08793 {
08794
08795 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08796 char fn[80];
08797 struct dahdi_bufferinfo bi;
08798
08799 int res;
08800 int span = 0;
08801 int here = 0;
08802 int x;
08803 struct dahdi_pvt **wlist;
08804 struct dahdi_pvt **wend;
08805 struct dahdi_params p;
08806
08807 wlist = &iflist;
08808 wend = &ifend;
08809
08810 #ifdef HAVE_PRI
08811 if (pri) {
08812 wlist = &pri->crvs;
08813 wend = &pri->crvend;
08814 }
08815 #endif
08816
08817 tmp2 = *wlist;
08818 prev = NULL;
08819
08820 while (tmp2) {
08821 if (!tmp2->destroy) {
08822 if (tmp2->channel == channel) {
08823 tmp = tmp2;
08824 here = 1;
08825 break;
08826 }
08827 if (tmp2->channel > channel) {
08828 break;
08829 }
08830 }
08831 prev = tmp2;
08832 tmp2 = tmp2->next;
08833 }
08834
08835 if (!here && reloading != 1) {
08836 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08837 if (tmp)
08838 free(tmp);
08839 return NULL;
08840 }
08841 ast_mutex_init(&tmp->lock);
08842 ifcount++;
08843 for (x = 0; x < 3; x++)
08844 tmp->subs[x].dfd = -1;
08845 tmp->channel = channel;
08846 tmp->priindication_oob = conf->chan.priindication_oob;
08847 }
08848
08849 if (tmp) {
08850 int chan_sig = conf->chan.sig;
08851 if (!here) {
08852 if ((channel != CHAN_PSEUDO) && !pri) {
08853 int count = 0;
08854 snprintf(fn, sizeof(fn), "%d", channel);
08855
08856 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08857 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08858 usleep(1);
08859 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08860 count++;
08861 }
08862
08863 if (tmp->subs[SUB_REAL].dfd < 0) {
08864 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);
08865 destroy_dahdi_pvt(&tmp);
08866 return NULL;
08867 }
08868 memset(&p, 0, sizeof(p));
08869 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08870 if (res < 0) {
08871 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08872 destroy_dahdi_pvt(&tmp);
08873 return NULL;
08874 }
08875 if (conf->is_sig_auto)
08876 chan_sig = sigtype_to_signalling(p.sigtype);
08877 if (p.sigtype != (chan_sig & 0x3ffff)) {
08878 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));
08879 destroy_dahdi_pvt(&tmp);
08880 return NULL;
08881 }
08882 tmp->law = p.curlaw;
08883 tmp->span = p.spanno;
08884 span = p.spanno - 1;
08885 } else {
08886 if (channel == CHAN_PSEUDO)
08887 chan_sig = 0;
08888 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08889 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08890 return NULL;
08891 }
08892 }
08893 #ifdef HAVE_SS7
08894 if (chan_sig == SIG_SS7) {
08895 struct dahdi_ss7 *ss7;
08896 int clear = 0;
08897 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08898 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08899 destroy_dahdi_pvt(&tmp);
08900 return NULL;
08901 }
08902
08903 ss7 = ss7_resolve_linkset(cur_linkset);
08904 if (!ss7) {
08905 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08906 destroy_dahdi_pvt(&tmp);
08907 return NULL;
08908 }
08909 if (cur_cicbeginswith < 0) {
08910 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08911 destroy_dahdi_pvt(&tmp);
08912 return NULL;
08913 }
08914
08915 tmp->cic = cur_cicbeginswith++;
08916
08917
08918 tmp->dpc = cur_defaultdpc;
08919
08920 tmp->ss7 = ss7;
08921 tmp->ss7call = NULL;
08922 ss7->pvts[ss7->numchans++] = tmp;
08923
08924 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
08925 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
08926 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
08927 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
08928
08929 ss7->called_nai = conf->ss7.called_nai;
08930 ss7->calling_nai = conf->ss7.calling_nai;
08931 }
08932 #endif
08933 #ifdef HAVE_PRI
08934 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08935 int offset;
08936 int myswitchtype;
08937 int matchesdchan;
08938 int x,y;
08939 offset = 0;
08940 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
08941 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08942 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08943 destroy_dahdi_pvt(&tmp);
08944 return NULL;
08945 }
08946 if (span >= NUM_SPANS) {
08947 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08948 destroy_dahdi_pvt(&tmp);
08949 return NULL;
08950 } else {
08951 struct dahdi_spaninfo si;
08952 si.spanno = 0;
08953 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08954 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08955 destroy_dahdi_pvt(&tmp);
08956 return NULL;
08957 }
08958
08959 tmp->logicalspan = pris[span].prilogicalspan;
08960 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08961 if (span < 0) {
08962 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08963 destroy_dahdi_pvt(&tmp);
08964 return NULL;
08965 }
08966 if ((chan_sig == SIG_PRI) ||
08967 (chan_sig == SIG_BRI) ||
08968 (chan_sig == SIG_BRI_PTMP))
08969 myswitchtype = conf->pri.switchtype;
08970 else
08971 myswitchtype = PRI_SWITCH_GR303_TMC;
08972
08973 matchesdchan=0;
08974 for (x = 0; x < NUM_SPANS; x++) {
08975 for (y = 0; y < NUM_DCHANS; y++) {
08976 if (pris[x].dchannels[y] == tmp->channel) {
08977 matchesdchan = 1;
08978 break;
08979 }
08980 }
08981 }
08982 offset = p.chanpos;
08983 if (!matchesdchan) {
08984 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08985 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08986 destroy_dahdi_pvt(&tmp);
08987 return NULL;
08988 }
08989 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08990 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08991 destroy_dahdi_pvt(&tmp);
08992 return NULL;
08993 }
08994 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08995 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08996 destroy_dahdi_pvt(&tmp);
08997 return NULL;
08998 }
08999 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
09000 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
09001 destroy_dahdi_pvt(&tmp);
09002 return NULL;
09003 }
09004 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
09005 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
09006 destroy_dahdi_pvt(&tmp);
09007 return NULL;
09008 }
09009 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
09010 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
09011 destroy_dahdi_pvt(&tmp);
09012 return NULL;
09013 }
09014 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
09015 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
09016 destroy_dahdi_pvt(&tmp);
09017 return NULL;
09018 }
09019 if (pris[span].numchans >= MAX_CHANNELS) {
09020 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
09021 pris[span].trunkgroup);
09022 destroy_dahdi_pvt(&tmp);
09023 return NULL;
09024 }
09025
09026 pris[span].sig = chan_sig;
09027 pris[span].nodetype = conf->pri.nodetype;
09028 pris[span].switchtype = myswitchtype;
09029 pris[span].nsf = conf->pri.nsf;
09030 pris[span].dialplan = conf->pri.dialplan;
09031 pris[span].localdialplan = conf->pri.localdialplan;
09032 pris[span].pvts[pris[span].numchans++] = tmp;
09033 pris[span].minunused = conf->pri.minunused;
09034 pris[span].minidle = conf->pri.minidle;
09035 pris[span].overlapdial = conf->pri.overlapdial;
09036 #ifdef HAVE_PRI_INBANDDISCONNECT
09037 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
09038 #endif
09039 pris[span].facilityenable = conf->pri.facilityenable;
09040 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
09041 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
09042 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
09043 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
09044 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
09045 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
09046 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
09047 pris[span].resetinterval = conf->pri.resetinterval;
09048
09049 tmp->pri = &pris[span];
09050 tmp->prioffset = offset;
09051 tmp->call = NULL;
09052 } else {
09053 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
09054 destroy_dahdi_pvt(&tmp);
09055 return NULL;
09056 }
09057 }
09058 } else {
09059 tmp->prioffset = 0;
09060 }
09061 #endif
09062 } else {
09063 chan_sig = tmp->sig;
09064 if (tmp->subs[SUB_REAL].dfd > -1) {
09065 memset(&p, 0, sizeof(p));
09066 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
09067 }
09068 }
09069
09070 switch (chan_sig) {
09071 case SIG_FXSKS:
09072 case SIG_FXSLS:
09073 case SIG_EM:
09074 case SIG_EM_E1:
09075 case SIG_EMWINK:
09076 case SIG_FEATD:
09077 case SIG_FEATDMF:
09078 case SIG_FEATDMF_TA:
09079 case SIG_FEATB:
09080 case SIG_E911:
09081 case SIG_SF:
09082 case SIG_SFWINK:
09083 case SIG_FGC_CAMA:
09084 case SIG_FGC_CAMAMF:
09085 case SIG_SF_FEATD:
09086 case SIG_SF_FEATDMF:
09087 case SIG_SF_FEATB:
09088 p.starttime = 250;
09089 break;
09090 }
09091
09092 if (tmp->radio) {
09093
09094 p.channo = channel;
09095 p.rxwinktime = 1;
09096 p.rxflashtime = 1;
09097 p.starttime = 1;
09098 p.debouncetime = 5;
09099 }
09100 if (!tmp->radio) {
09101 p.channo = channel;
09102
09103 if (conf->timing.prewinktime >= 0)
09104 p.prewinktime = conf->timing.prewinktime;
09105 if (conf->timing.preflashtime >= 0)
09106 p.preflashtime = conf->timing.preflashtime;
09107 if (conf->timing.winktime >= 0)
09108 p.winktime = conf->timing.winktime;
09109 if (conf->timing.flashtime >= 0)
09110 p.flashtime = conf->timing.flashtime;
09111 if (conf->timing.starttime >= 0)
09112 p.starttime = conf->timing.starttime;
09113 if (conf->timing.rxwinktime >= 0)
09114 p.rxwinktime = conf->timing.rxwinktime;
09115 if (conf->timing.rxflashtime >= 0)
09116 p.rxflashtime = conf->timing.rxflashtime;
09117 if (conf->timing.debouncetime >= 0)
09118 p.debouncetime = conf->timing.debouncetime;
09119 }
09120
09121
09122 if (tmp->subs[SUB_REAL].dfd >= 0)
09123 {
09124 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09125 if (res < 0) {
09126 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09127 destroy_dahdi_pvt(&tmp);
09128 return NULL;
09129 }
09130 }
09131 #if 1
09132 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09133 memset(&bi, 0, sizeof(bi));
09134 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09135 if (!res) {
09136 bi.txbufpolicy = conf->chan.buf_policy;
09137 bi.rxbufpolicy = conf->chan.buf_policy;
09138 bi.numbufs = conf->chan.buf_no;
09139 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09140 if (res < 0) {
09141 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09142 }
09143 } else
09144 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09145 }
09146 #endif
09147 tmp->immediate = conf->chan.immediate;
09148 tmp->transfertobusy = conf->chan.transfertobusy;
09149 if (chan_sig & __DAHDI_SIG_FXS) {
09150 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
09151 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
09152 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
09153 }
09154 tmp->sig = chan_sig;
09155 tmp->outsigmod = conf->chan.outsigmod;
09156 tmp->ringt_base = ringt_base;
09157 tmp->firstradio = 0;
09158 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09159 tmp->permcallwaiting = conf->chan.callwaiting;
09160 else
09161 tmp->permcallwaiting = 0;
09162
09163 tmp->destroy = 0;
09164 tmp->drings = conf->chan.drings;
09165
09166
09167 if (tmp->drings.ringnum[0].range == 0)
09168 tmp->drings.ringnum[0].range = 10;
09169 if (tmp->drings.ringnum[1].range == 0)
09170 tmp->drings.ringnum[1].range = 10;
09171 if (tmp->drings.ringnum[2].range == 0)
09172 tmp->drings.ringnum[2].range = 10;
09173
09174 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
09175 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09176 tmp->threewaycalling = conf->chan.threewaycalling;
09177 tmp->adsi = conf->chan.adsi;
09178 tmp->use_smdi = conf->chan.use_smdi;
09179 tmp->permhidecallerid = conf->chan.hidecallerid;
09180 tmp->hidecalleridname = conf->chan.hidecalleridname;
09181 tmp->callreturn = conf->chan.callreturn;
09182 tmp->echocancel = conf->chan.echocancel;
09183 tmp->echotraining = conf->chan.echotraining;
09184 tmp->pulse = conf->chan.pulse;
09185 if (tmp->echocancel.head.tap_length) {
09186 tmp->echocanbridged = conf->chan.echocanbridged;
09187 } else {
09188 if (conf->chan.echocanbridged)
09189 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09190 tmp->echocanbridged = 0;
09191 }
09192 tmp->busydetect = conf->chan.busydetect;
09193 tmp->busycount = conf->chan.busycount;
09194 tmp->busycompare = conf->chan.busycompare;
09195 tmp->busytonelength = conf->chan.busytonelength;
09196 tmp->busyquietlength = conf->chan.busyquietlength;
09197 tmp->busyfuzziness = conf->chan.busyfuzziness;
09198 tmp->silencethreshold = conf->chan.silencethreshold;
09199 tmp->callprogress = conf->chan.callprogress;
09200 tmp->cancallforward = conf->chan.cancallforward;
09201 tmp->dtmfrelax = conf->chan.dtmfrelax;
09202 tmp->callwaiting = tmp->permcallwaiting;
09203 tmp->hidecallerid = tmp->permhidecallerid;
09204 tmp->channel = channel;
09205 tmp->stripmsd = conf->chan.stripmsd;
09206 tmp->use_callerid = conf->chan.use_callerid;
09207 tmp->cid_signalling = conf->chan.cid_signalling;
09208 tmp->cid_start = conf->chan.cid_start;
09209 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09210 tmp->restrictcid = conf->chan.restrictcid;
09211 tmp->use_callingpres = conf->chan.use_callingpres;
09212 tmp->priexclusive = conf->chan.priexclusive;
09213 if (tmp->usedistinctiveringdetection) {
09214 if (!tmp->use_callerid) {
09215 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09216 tmp->use_callerid = 1;
09217 }
09218 }
09219
09220 if (tmp->cid_signalling == CID_SIG_SMDI) {
09221 if (!tmp->use_smdi) {
09222 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09223 tmp->use_smdi = 1;
09224 }
09225 }
09226 if (tmp->use_smdi) {
09227 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09228 if (!(tmp->smdi_iface)) {
09229 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09230 tmp->use_smdi = 0;
09231 }
09232 }
09233
09234 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09235 tmp->amaflags = conf->chan.amaflags;
09236 if (!here) {
09237 tmp->confno = -1;
09238 tmp->propconfno = -1;
09239 }
09240 tmp->canpark = conf->chan.canpark;
09241 tmp->transfer = conf->chan.transfer;
09242 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09243 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09244 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09245 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09246 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09247 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
09248 tmp->cid_ton = 0;
09249 switch (tmp->sig) {
09250 case SIG_PRI:
09251 case SIG_BRI:
09252 case SIG_BRI_PTMP:
09253 case SIG_SS7:
09254 tmp->cid_num[0] = '\0';
09255 tmp->cid_name[0] = '\0';
09256 break;
09257 default:
09258 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09259 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09260 break;
09261 }
09262 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09263 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
09264 char *mailbox, *context;
09265 mailbox = context = ast_strdupa(tmp->mailbox);
09266 strsep(&context, "@");
09267 if (ast_strlen_zero(context))
09268 context = "default";
09269 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
09270 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
09271 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
09272 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
09273 AST_EVENT_IE_END);
09274 }
09275 tmp->msgstate = -1;
09276 tmp->group = conf->chan.group;
09277 tmp->callgroup = conf->chan.callgroup;
09278 tmp->pickupgroup= conf->chan.pickupgroup;
09279 if (conf->chan.vars) {
09280 struct ast_variable *v, *tmpvar;
09281 for (v = conf->chan.vars ; v ; v = v->next) {
09282 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
09283 tmpvar->next = tmp->vars;
09284 tmp->vars = tmpvar;
09285 }
09286 }
09287 }
09288 tmp->cid_rxgain = conf->chan.cid_rxgain;
09289 tmp->rxgain = conf->chan.rxgain;
09290 tmp->txgain = conf->chan.txgain;
09291 tmp->tonezone = conf->chan.tonezone;
09292 tmp->onhooktime = time(NULL);
09293 if (tmp->subs[SUB_REAL].dfd > -1) {
09294 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09295 if (tmp->dsp)
09296 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09297 update_conf(tmp);
09298 if (!here) {
09299 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
09300
09301 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09302 }
09303 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09304 #ifdef HAVE_PRI
09305
09306 if (tmp->pri && !pri_is_up(tmp->pri))
09307 tmp->inalarm = 1;
09308 #endif
09309 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09310 tmp->inalarm = 1;
09311 handle_alarms(tmp, res);
09312 }
09313 }
09314
09315 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09316 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09317 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09318 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09319 if (!here) {
09320 tmp->locallyblocked = tmp->remotelyblocked = 0;
09321 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09322 tmp->inservice = 0;
09323 else
09324 tmp->inservice = 1;
09325 }
09326 }
09327 if (tmp && !here) {
09328
09329 if (!*wlist) {
09330 *wlist = tmp;
09331 tmp->prev = NULL;
09332 tmp->next = NULL;
09333 *wend = tmp;
09334 } else {
09335
09336 struct dahdi_pvt *working = *wlist;
09337
09338
09339 if (working->channel > tmp->channel) {
09340 tmp->next = *wlist;
09341 tmp->prev = NULL;
09342 (*wlist)->prev = tmp;
09343 *wlist = tmp;
09344 } else {
09345
09346 while (working) {
09347
09348 if (working->next) {
09349 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09350 tmp->next = working->next;
09351 tmp->prev = working;
09352 working->next->prev = tmp;
09353 working->next = tmp;
09354 break;
09355 }
09356 } else {
09357
09358 if (working->channel < tmp->channel) {
09359 working->next = tmp;
09360 tmp->next = NULL;
09361 tmp->prev = working;
09362 *wend = tmp;
09363 break;
09364 }
09365 }
09366 working = working->next;
09367 }
09368 }
09369 }
09370 }
09371 return tmp;
09372 }
09373
09374 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09375 {
09376 int res;
09377 struct dahdi_params par;
09378
09379
09380 if (groupmatch) {
09381 if ((p->group & groupmatch) != groupmatch)
09382 return 0;
09383 *groupmatched = 1;
09384 }
09385
09386 if (channelmatch != -1) {
09387 if (p->channel != channelmatch)
09388 return 0;
09389 *channelmatched = 1;
09390 }
09391
09392 if (busy) {
09393 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09394 *busy = 1;
09395 }
09396
09397 if (p->dnd)
09398 return 0;
09399
09400 if (p->guardtime && (time(NULL) < p->guardtime))
09401 return 0;
09402
09403 if (p->locallyblocked || p->remotelyblocked)
09404 return 0;
09405
09406
09407 if (!p->owner) {
09408 #ifdef HAVE_PRI
09409
09410 if (p->pri) {
09411 if (p->resetting || p->call)
09412 return 0;
09413 else
09414 return 1;
09415 }
09416 #endif
09417 #ifdef HAVE_SS7
09418
09419 if (p->ss7) {
09420 if (p->ss7call)
09421 return 0;
09422 else
09423 return 1;
09424 }
09425 #endif
09426 if (!(p->radio || (p->oprmode < 0)))
09427 {
09428 if (!p->sig || (p->sig == SIG_FXSLS))
09429 return 1;
09430
09431 if (p->subs[SUB_REAL].dfd > -1) {
09432 memset(&par, 0, sizeof(par));
09433 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09434 } else {
09435
09436 res = 0;
09437 par.rxisoffhook = 0;
09438 }
09439 if (res) {
09440 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09441 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09442
09443
09444
09445 if (par.rxbits > -1)
09446 return 1;
09447 if (par.rxisoffhook)
09448 return 1;
09449 else
09450 return 0;
09451 } else if (par.rxisoffhook) {
09452 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09453
09454 #ifdef DAHDI_CHECK_HOOKSTATE
09455 return 0;
09456 #else
09457 return 1;
09458 #endif
09459 }
09460 }
09461 return 1;
09462 }
09463
09464
09465 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09466 return 0;
09467
09468 if (!p->callwaiting) {
09469
09470 return 0;
09471 }
09472
09473 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09474
09475 return 0;
09476 }
09477
09478 if ((p->owner->_state != AST_STATE_UP) &&
09479 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09480
09481 return 0;
09482 }
09483 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09484
09485 return 0;
09486 }
09487
09488 return 1;
09489 }
09490
09491 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09492 {
09493 struct dahdi_pvt *p;
09494 struct dahdi_bufferinfo bi;
09495 int res;
09496
09497 if ((p = ast_malloc(sizeof(*p)))) {
09498 memcpy(p, src, sizeof(struct dahdi_pvt));
09499 ast_mutex_init(&p->lock);
09500 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09501
09502 if (p->subs[SUB_REAL].dfd < 0) {
09503 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09504 destroy_dahdi_pvt(&p);
09505 return NULL;
09506 }
09507 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09508 if (!res) {
09509 bi.txbufpolicy = src->buf_policy;
09510 bi.rxbufpolicy = src->buf_policy;
09511 bi.numbufs = src->buf_no;
09512 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09513 if (res < 0) {
09514 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09515 }
09516 } else
09517 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09518 }
09519 p->destroy = 1;
09520 p->next = iflist;
09521 p->prev = NULL;
09522 iflist = p;
09523 if (iflist->next)
09524 iflist->next->prev = p;
09525 return p;
09526 }
09527
09528
09529 #ifdef HAVE_PRI
09530 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09531 {
09532 int x;
09533 if (backwards)
09534 x = pri->numchans;
09535 else
09536 x = 0;
09537 for (;;) {
09538 if (backwards && (x < 0))
09539 break;
09540 if (!backwards && (x >= pri->numchans))
09541 break;
09542 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09543 ast_debug(1, "Found empty available channel %d/%d\n",
09544 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09545 return x;
09546 }
09547 if (backwards)
09548 x--;
09549 else
09550 x++;
09551 }
09552 return -1;
09553 }
09554 #endif
09555
09556 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09557 {
09558 ast_group_t groupmatch = 0;
09559 int channelmatch = -1;
09560 int roundrobin = 0;
09561 int callwait = 0;
09562 int busy = 0;
09563 struct dahdi_pvt *p;
09564 struct ast_channel *tmp = NULL;
09565 char *dest=NULL;
09566 int x;
09567 char *s;
09568 char opt=0;
09569 int res=0, y=0;
09570 int backwards = 0;
09571 #ifdef HAVE_PRI
09572 int crv;
09573 int bearer = -1;
09574 int trunkgroup;
09575 struct dahdi_pri *pri=NULL;
09576 #endif
09577 struct dahdi_pvt *exitpvt, *start, *end;
09578 ast_mutex_t *lock;
09579 int channelmatched = 0;
09580 int groupmatched = 0;
09581
09582
09583
09584
09585
09586
09587
09588
09589
09590
09591
09592
09593
09594
09595
09596
09597
09598
09599
09600 lock = &iflock;
09601 start = iflist;
09602 end = ifend;
09603 if (data) {
09604 dest = ast_strdupa((char *)data);
09605 } else {
09606 ast_log(LOG_WARNING, "Channel requested with no data\n");
09607 return NULL;
09608 }
09609 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09610
09611 char *stringp;
09612
09613 stringp = dest + 1;
09614 s = strsep(&stringp, "/");
09615 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09616 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09617 return NULL;
09618 }
09619 groupmatch = ((ast_group_t) 1 << x);
09620 if (toupper(dest[0]) == 'G') {
09621 if (dest[0] == 'G') {
09622 backwards = 1;
09623 p = ifend;
09624 } else
09625 p = iflist;
09626 } else {
09627 if (dest[0] == 'R') {
09628 backwards = 1;
09629 p = round_robin[x]?round_robin[x]->prev:ifend;
09630 if (!p)
09631 p = ifend;
09632 } else {
09633 p = round_robin[x]?round_robin[x]->next:iflist;
09634 if (!p)
09635 p = iflist;
09636 }
09637 roundrobin = 1;
09638 }
09639 } else {
09640 char *stringp;
09641
09642 stringp = dest;
09643 s = strsep(&stringp, "/");
09644 p = iflist;
09645 if (!strcasecmp(s, "pseudo")) {
09646
09647 x = CHAN_PSEUDO;
09648 channelmatch = x;
09649 }
09650 #ifdef HAVE_PRI
09651 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09652 if ((trunkgroup < 1) || (crv < 1)) {
09653 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09654 return NULL;
09655 }
09656 res--;
09657 for (x = 0; x < NUM_SPANS; x++) {
09658 if (pris[x].trunkgroup == trunkgroup) {
09659 pri = pris + x;
09660 lock = &pri->lock;
09661 start = pri->crvs;
09662 end = pri->crvend;
09663 break;
09664 }
09665 }
09666 if (!pri) {
09667 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09668 return NULL;
09669 }
09670 channelmatch = crv;
09671 p = pris[x].crvs;
09672 }
09673 #endif
09674 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09675 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09676 return NULL;
09677 } else {
09678 channelmatch = x;
09679 }
09680 }
09681
09682 ast_mutex_lock(lock);
09683 exitpvt = p;
09684 while (p && !tmp) {
09685 if (roundrobin)
09686 round_robin[x] = p;
09687 #if 0
09688 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09689 #endif
09690
09691 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09692 ast_debug(1, "Using channel %d\n", p->channel);
09693 if (p->inalarm)
09694 goto next;
09695
09696 callwait = (p->owner != NULL);
09697 #ifdef HAVE_PRI
09698 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09699 if (p->sig != SIG_FXSKS) {
09700
09701
09702 bearer = pri_find_empty_chan(pri, 0);
09703 if (bearer < 0) {
09704 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09705 p = NULL;
09706 break;
09707 }
09708 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09709 } else {
09710 if (alloc_sub(p, 0)) {
09711 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09712 p = NULL;
09713 break;
09714 } else
09715 ast_debug(1, "Allocated placeholder pseudo channel\n");
09716
09717 p->pri = pri;
09718 }
09719 }
09720 #endif
09721 if (p->channel == CHAN_PSEUDO) {
09722 p = chandup(p);
09723 if (!p) {
09724 break;
09725 }
09726 }
09727 if (p->owner) {
09728 if (alloc_sub(p, SUB_CALLWAIT)) {
09729 p = NULL;
09730 break;
09731 }
09732 }
09733 p->outgoing = 1;
09734 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09735 if (!tmp) {
09736 p->outgoing = 0;
09737 }
09738 #ifdef HAVE_PRI
09739 if (p->bearer) {
09740
09741 p->bearer->owner = tmp;
09742 }
09743 #endif
09744
09745 if (res > 1) {
09746 if (opt == 'c') {
09747
09748 p->confirmanswer = 1;
09749 } else if (opt == 'r') {
09750
09751 if (res < 3)
09752 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09753 else
09754 p->distinctivering = y;
09755 } else if (opt == 'd') {
09756
09757 p->digital = 1;
09758 if (tmp)
09759 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09760 } else {
09761 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09762 }
09763 }
09764
09765 if (tmp && callwait)
09766 tmp->cdrflags |= AST_CDR_CALLWAIT;
09767 break;
09768 }
09769 next:
09770 if (backwards) {
09771 p = p->prev;
09772 if (!p)
09773 p = end;
09774 } else {
09775 p = p->next;
09776 if (!p)
09777 p = start;
09778 }
09779
09780 if (p == exitpvt)
09781 break;
09782 }
09783 ast_mutex_unlock(lock);
09784 restart_monitor();
09785 if (callwait)
09786 *cause = AST_CAUSE_BUSY;
09787 else if (!tmp) {
09788 if (channelmatched) {
09789 if (busy)
09790 *cause = AST_CAUSE_BUSY;
09791 } else if (groupmatched) {
09792 *cause = AST_CAUSE_CONGESTION;
09793 }
09794 }
09795
09796 return tmp;
09797 }
09798
09799 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09800 static int dahdi_setlaw(int dfd, int law)
09801 {
09802 return ioctl(dfd, DAHDI_SETLAW, &law);
09803 }
09804 #endif
09805
09806 #ifdef HAVE_SS7
09807
09808 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
09809 {
09810 int i;
09811 int winner = -1;
09812 for (i = 0; i < linkset->numchans; i++) {
09813 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09814 winner = i;
09815 break;
09816 }
09817 }
09818 return winner;
09819 }
09820
09821 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09822 {
09823 unsigned char status[32];
09824 struct dahdi_pvt *p = NULL;
09825 int i, offset;
09826
09827 for (i = 0; i < linkset->numchans; i++) {
09828 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09829 p = linkset->pvts[i];
09830 offset = p->cic - startcic;
09831 status[offset] = 0;
09832 if (p->locallyblocked)
09833 status[offset] |= (1 << 0) | (1 << 4);
09834 if (p->remotelyblocked)
09835 status[offset] |= (1 << 1) | (1 << 5);
09836 if (p->ss7call) {
09837 if (p->outgoing)
09838 status[offset] |= (1 << 3);
09839 else
09840 status[offset] |= (1 << 2);
09841 } else
09842 status[offset] |= 0x3 << 2;
09843 }
09844 }
09845
09846 if (p)
09847 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09848 else
09849 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09850
09851 }
09852
09853 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
09854 {
09855 int i;
09856
09857 for (i = 0; i < linkset->numchans; i++) {
09858 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09859 if (state) {
09860 if (state[i])
09861 linkset->pvts[i]->remotelyblocked = block;
09862 } else
09863 linkset->pvts[i]->remotelyblocked = block;
09864 }
09865 }
09866 }
09867
09868 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09869 {
09870 int i;
09871
09872 for (i = 0; i < linkset->numchans; i++) {
09873 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09874 linkset->pvts[i]->inservice = 1;
09875 }
09876 }
09877
09878 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
09879 {
09880 int i, startcic = -1, endcic, dpc;
09881
09882 if (linkset->numchans <= 0)
09883 return;
09884
09885 startcic = linkset->pvts[0]->cic;
09886
09887 dpc = linkset->pvts[0]->dpc;
09888
09889 for (i = 0; i < linkset->numchans; i++) {
09890 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)) {
09891 continue;
09892 } else {
09893 endcic = linkset->pvts[i]->cic;
09894 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09895 isup_grs(linkset->ss7, startcic, endcic, dpc);
09896
09897
09898 if (linkset->pvts[i+1]) {
09899 startcic = linkset->pvts[i+1]->cic;
09900 dpc = linkset->pvts[i+1]->dpc;
09901 }
09902 }
09903 }
09904 }
09905
09906 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
09907 {
09908 if (p->loopedback != enable) {
09909 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09910 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09911 return;
09912 }
09913 p->loopedback = enable;
09914 }
09915 }
09916
09917
09918 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
09919 {
09920 struct ss7 *ss7 = linkset->ss7;
09921 int res;
09922 int law = 1;
09923 struct ast_channel *c;
09924 char tmp[256];
09925
09926 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09927 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09928
09929 if (linkset->type == SS7_ITU)
09930 law = DAHDI_LAW_ALAW;
09931 else
09932 law = DAHDI_LAW_MULAW;
09933
09934 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09935 if (res < 0)
09936 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09937
09938 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09939 p->proceeding = 1;
09940 isup_acm(ss7, p->ss7call);
09941 }
09942
09943 ast_mutex_unlock(&linkset->lock);
09944 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09945
09946 if (!c) {
09947 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09948
09949 ast_mutex_lock(&linkset->lock);
09950 return;
09951 } else
09952 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09953
09954 dahdi_enable_ec(p);
09955
09956
09957
09958
09959
09960 ast_mutex_unlock(&p->lock);
09961
09962 if (!ast_strlen_zero(p->charge_number)) {
09963 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09964
09965 p->charge_number[0] = 0;
09966 }
09967 if (!ast_strlen_zero(p->gen_add_number)) {
09968 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09969
09970 p->gen_add_number[0] = 0;
09971 }
09972 if (!ast_strlen_zero(p->jip_number)) {
09973 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09974
09975 p->jip_number[0] = 0;
09976 }
09977 if (!ast_strlen_zero(p->gen_dig_number)) {
09978 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09979
09980 p->gen_dig_number[0] = 0;
09981 }
09982 if (!ast_strlen_zero(p->orig_called_num)) {
09983 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09984
09985 p->orig_called_num[0] = 0;
09986 }
09987
09988 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09989 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09990
09991 p->gen_dig_type = 0;
09992
09993 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09994 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09995
09996 p->gen_dig_scheme = 0;
09997
09998 if (!ast_strlen_zero(p->lspi_ident)) {
09999 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
10000
10001 p->lspi_ident[0] = 0;
10002 }
10003
10004 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
10005 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
10006
10007 p->call_ref_ident = 0;
10008
10009 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
10010 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
10011
10012 p->call_ref_pc = 0;
10013
10014 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
10015 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
10016
10017 p->calling_party_cat = 0;
10018
10019 if (!ast_strlen_zero(p->redirecting_num)) {
10020 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
10021
10022 p->redirecting_num[0] = 0;
10023 }
10024 if (!ast_strlen_zero(p->generic_name)) {
10025 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
10026
10027 p->generic_name[0] = 0;
10028 }
10029
10030 ast_mutex_lock(&p->lock);
10031 ast_mutex_lock(&linkset->lock);
10032 }
10033
10034 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
10035 {
10036 if (ast_strlen_zero(number)) {
10037 if (size) {
10038 *buf = '\0';
10039 }
10040 return;
10041 }
10042 switch (nai) {
10043 case SS7_NAI_INTERNATIONAL:
10044 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
10045 break;
10046 case SS7_NAI_NATIONAL:
10047 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
10048 break;
10049 case SS7_NAI_SUBSCRIBER:
10050 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
10051 break;
10052 case SS7_NAI_UNKNOWN:
10053 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
10054 break;
10055 default:
10056 snprintf(buf, size, "%s", number);
10057 break;
10058 }
10059 }
10060 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
10061 {
10062 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
10063 }
10064
10065 static void *ss7_linkset(void *data)
10066 {
10067 int res, i;
10068 struct timeval *next = NULL, tv;
10069 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
10070 struct ss7 *ss7 = linkset->ss7;
10071 ss7_event *e = NULL;
10072 struct dahdi_pvt *p;
10073 int chanpos;
10074 struct pollfd pollers[NUM_DCHANS];
10075 int cic;
10076 unsigned int dpc;
10077 int nextms = 0;
10078
10079 ss7_start(ss7);
10080
10081 while(1) {
10082 ast_mutex_lock(&linkset->lock);
10083 if ((next = ss7_schedule_next(ss7))) {
10084 tv = ast_tvnow();
10085 tv.tv_sec = next->tv_sec - tv.tv_sec;
10086 tv.tv_usec = next->tv_usec - tv.tv_usec;
10087 if (tv.tv_usec < 0) {
10088 tv.tv_usec += 1000000;
10089 tv.tv_sec -= 1;
10090 }
10091 if (tv.tv_sec < 0) {
10092 tv.tv_sec = 0;
10093 tv.tv_usec = 0;
10094 }
10095 nextms = tv.tv_sec * 1000;
10096 nextms += tv.tv_usec / 1000;
10097 }
10098 ast_mutex_unlock(&linkset->lock);
10099
10100 for (i = 0; i < linkset->numsigchans; i++) {
10101 pollers[i].fd = linkset->fds[i];
10102 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
10103 pollers[i].revents = 0;
10104 }
10105
10106 res = poll(pollers, linkset->numsigchans, nextms);
10107 if ((res < 0) && (errno != EINTR)) {
10108 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
10109 } else if (!res) {
10110 ast_mutex_lock(&linkset->lock);
10111 ss7_schedule_run(ss7);
10112 ast_mutex_unlock(&linkset->lock);
10113 continue;
10114 }
10115
10116 ast_mutex_lock(&linkset->lock);
10117 for (i = 0; i < linkset->numsigchans; i++) {
10118 if (pollers[i].revents & POLLPRI) {
10119 int x;
10120 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
10121 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
10122 }
10123 switch (x) {
10124 case DAHDI_EVENT_OVERRUN:
10125 ast_debug(1, "Overrun detected!\n");
10126 break;
10127 case DAHDI_EVENT_BADFCS:
10128 ast_debug(1, "Bad FCS\n");
10129 break;
10130 case DAHDI_EVENT_ABORT:
10131 ast_debug(1, "HDLC Abort\n");
10132 break;
10133 case DAHDI_EVENT_ALARM:
10134 ast_log(LOG_ERROR, "Alarm on link!\n");
10135 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
10136 linkset->linkstate[i] &= ~LINKSTATE_UP;
10137 ss7_link_alarm(ss7, pollers[i].fd);
10138 break;
10139 case DAHDI_EVENT_NOALARM:
10140 ast_log(LOG_ERROR, "Alarm cleared on link\n");
10141 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
10142 linkset->linkstate[i] |= LINKSTATE_STARTING;
10143 ss7_link_noalarm(ss7, pollers[i].fd);
10144 break;
10145 default:
10146 ast_log(LOG_ERROR, "Got exception %d!\n", x);
10147 break;
10148 }
10149 }
10150
10151 if (pollers[i].revents & POLLIN) {
10152 ast_mutex_lock(&linkset->lock);
10153 res = ss7_read(ss7, pollers[i].fd);
10154 ast_mutex_unlock(&linkset->lock);
10155 }
10156
10157 if (pollers[i].revents & POLLOUT) {
10158 ast_mutex_lock(&linkset->lock);
10159 res = ss7_write(ss7, pollers[i].fd);
10160 ast_mutex_unlock(&linkset->lock);
10161 if (res < 0) {
10162 ast_debug(1, "Error in write %s\n", strerror(errno));
10163 }
10164 }
10165 }
10166
10167 while ((e = ss7_check_event(ss7))) {
10168 switch (e->e) {
10169 case SS7_EVENT_UP:
10170 if (linkset->state != LINKSET_STATE_UP) {
10171 ast_verbose("--- SS7 Up ---\n");
10172 ss7_reset_linkset(linkset);
10173 }
10174 linkset->state = LINKSET_STATE_UP;
10175 break;
10176 case SS7_EVENT_DOWN:
10177 ast_verbose("--- SS7 Down ---\n");
10178 linkset->state = LINKSET_STATE_DOWN;
10179 for (i = 0; i < linkset->numchans; i++) {
10180 struct dahdi_pvt *p = linkset->pvts[i];
10181 if (p)
10182 p->inalarm = 1;
10183 }
10184 break;
10185 case MTP2_LINK_UP:
10186 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
10187 break;
10188 case MTP2_LINK_DOWN:
10189 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
10190 break;
10191 case ISUP_EVENT_CPG:
10192 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
10193 if (chanpos < 0) {
10194 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
10195 break;
10196 }
10197 p = linkset->pvts[chanpos];
10198 ast_mutex_lock(&p->lock);
10199 switch (e->cpg.event) {
10200 case CPG_EVENT_ALERTING:
10201 p->alerting = 1;
10202 p->subs[SUB_REAL].needringing = 1;
10203 break;
10204 case CPG_EVENT_PROGRESS:
10205 case CPG_EVENT_INBANDINFO:
10206 {
10207 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10208 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
10209 dahdi_queue_frame(p, &f, linkset);
10210 p->progress = 1;
10211 p->dialing = 0;
10212 if (p->dsp && p->dsp_features) {
10213 ast_dsp_set_features(p->dsp, p->dsp_features);
10214 p->dsp_features = 0;
10215 }
10216 }
10217 break;
10218 default:
10219 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
10220 }
10221
10222 ast_mutex_unlock(&p->lock);
10223 break;
10224 case ISUP_EVENT_RSC:
10225 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
10226 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
10227 if (chanpos < 0) {
10228 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
10229 break;
10230 }
10231 p = linkset->pvts[chanpos];
10232 ast_mutex_lock(&p->lock);
10233 p->inservice = 1;
10234 p->remotelyblocked = 0;
10235 dpc = p->dpc;
10236 isup_set_call_dpc(e->rsc.call, dpc);
10237 if (p->ss7call)
10238 p->ss7call = NULL;
10239 if (p->owner)
10240 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10241 ast_mutex_unlock(&p->lock);
10242 isup_rlc(ss7, e->rsc.call);
10243 break;
10244 case ISUP_EVENT_GRS:
10245 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
10246 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
10247 if (chanpos < 0) {
10248 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
10249 break;
10250 }
10251 p = linkset->pvts[chanpos];
10252 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
10253 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
10254 break;
10255 case ISUP_EVENT_CQM:
10256 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
10257 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
10258 break;
10259 case ISUP_EVENT_GRA:
10260 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
10261 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
10262 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
10263 break;
10264 case ISUP_EVENT_IAM:
10265 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);
10266 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
10267 if (chanpos < 0) {
10268 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
10269 isup_rel(ss7, e->iam.call, -1);
10270 break;
10271 }
10272 p = linkset->pvts[chanpos];
10273 ast_mutex_lock(&p->lock);
10274 if (p->owner) {
10275 if (p->ss7call == e->iam.call) {
10276 ast_mutex_unlock(&p->lock);
10277 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
10278 break;
10279 } else {
10280 ast_mutex_unlock(&p->lock);
10281 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
10282 break;
10283 }
10284 }
10285
10286 dpc = p->dpc;
10287 p->ss7call = e->iam.call;
10288 isup_set_call_dpc(p->ss7call, dpc);
10289
10290 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
10291 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
10292 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
10293 } else
10294 p->cid_num[0] = 0;
10295
10296 if (p->immediate) {
10297 p->exten[0] = 's';
10298 p->exten[1] = '\0';
10299 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
10300 char *st;
10301 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
10302 st = strchr(p->exten, '#');
10303 if (st)
10304 *st = '\0';
10305 } else
10306 p->exten[0] = '\0';
10307
10308 p->cid_ani[0] = '\0';
10309 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
10310 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
10311 else
10312 p->cid_name[0] = '\0';
10313
10314 p->cid_ani2 = e->iam.oli_ani2;
10315 p->cid_ton = 0;
10316 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
10317 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
10318 p->gen_add_type = e->iam.gen_add_type;
10319 p->gen_add_nai = e->iam.gen_add_nai;
10320 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
10321 p->gen_add_num_plan = e->iam.gen_add_num_plan;
10322 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
10323 p->gen_dig_type = e->iam.gen_dig_type;
10324 p->gen_dig_scheme = e->iam.gen_dig_scheme;
10325 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
10326 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
10327 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
10328 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
10329 p->calling_party_cat = e->iam.calling_party_cat;
10330
10331
10332 if (!ast_strlen_zero(e->iam.called_party_num))
10333 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
10334
10335 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
10336
10337 if (e->iam.cot_check_required) {
10338 dahdi_loopback(p, 1);
10339 } else
10340 ss7_start_call(p, linkset);
10341 } else {
10342 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
10343 p->alreadyhungup = 1;
10344 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
10345 }
10346 ast_mutex_unlock(&p->lock);
10347 break;
10348 case ISUP_EVENT_COT:
10349 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
10350 if (chanpos < 0) {
10351 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
10352 isup_rel(ss7, e->cot.call, -1);
10353 break;
10354 }
10355 p = linkset->pvts[chanpos];
10356
10357 ast_mutex_lock(&p->lock);
10358
10359 if (p->loopedback) {
10360 dahdi_loopback(p, 0);
10361 ss7_start_call(p, linkset);
10362 }
10363
10364 ast_mutex_unlock(&p->lock);
10365
10366 break;
10367 case ISUP_EVENT_CCR:
10368 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
10369 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
10370 if (chanpos < 0) {
10371 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
10372 break;
10373 }
10374
10375 p = linkset->pvts[chanpos];
10376
10377 ast_mutex_lock(&p->lock);
10378 dahdi_loopback(p, 1);
10379 ast_mutex_unlock(&p->lock);
10380
10381 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
10382 break;
10383 case ISUP_EVENT_CVT:
10384 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
10385 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
10386 if (chanpos < 0) {
10387 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
10388 break;
10389 }
10390
10391 p = linkset->pvts[chanpos];
10392
10393 ast_mutex_lock(&p->lock);
10394 dahdi_loopback(p, 1);
10395 ast_mutex_unlock(&p->lock);
10396
10397 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
10398 break;
10399 case ISUP_EVENT_REL:
10400 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
10401 if (chanpos < 0) {
10402 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
10403 break;
10404 }
10405 p = linkset->pvts[chanpos];
10406 ast_mutex_lock(&p->lock);
10407 if (p->owner) {
10408 p->owner->hangupcause = e->rel.cause;
10409 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10410 } else if (!p->restartpending)
10411 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
10412
10413
10414 dahdi_loopback(p, 0);
10415
10416 isup_rlc(ss7, e->rel.call);
10417 p->ss7call = NULL;
10418
10419 ast_mutex_unlock(&p->lock);
10420 break;
10421 case ISUP_EVENT_ACM:
10422 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
10423 if (chanpos < 0) {
10424 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
10425 isup_rel(ss7, e->acm.call, -1);
10426 break;
10427 } else {
10428 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10429
10430 p = linkset->pvts[chanpos];
10431
10432 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
10433
10434 if (e->acm.call_ref_ident > 0) {
10435 p->rlt = 1;
10436 }
10437
10438 ast_mutex_lock(&p->lock);
10439 dahdi_queue_frame(p, &f, linkset);
10440 p->proceeding = 1;
10441 p->dialing = 0;
10442
10443 if (e->acm.called_party_status_ind == 1) {
10444 p->alerting = 1;
10445 p->subs[SUB_REAL].needringing = 1;
10446 }
10447 ast_mutex_unlock(&p->lock);
10448 }
10449 break;
10450 case ISUP_EVENT_CGB:
10451 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
10452 if (chanpos < 0) {
10453 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
10454 break;
10455 }
10456 p = linkset->pvts[chanpos];
10457 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
10458 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
10459 break;
10460 case ISUP_EVENT_CGU:
10461 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
10462 if (chanpos < 0) {
10463 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
10464 break;
10465 }
10466 p = linkset->pvts[chanpos];
10467 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
10468 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
10469 break;
10470 case ISUP_EVENT_UCIC:
10471 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
10472 if (chanpos < 0) {
10473 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
10474 break;
10475 }
10476 p = linkset->pvts[chanpos];
10477 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
10478 ast_mutex_lock(&p->lock);
10479 p->remotelyblocked = 1;
10480 p->inservice = 0;
10481 ast_mutex_unlock(&p->lock);
10482 break;
10483 case ISUP_EVENT_BLO:
10484 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
10485 if (chanpos < 0) {
10486 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
10487 break;
10488 }
10489 p = linkset->pvts[chanpos];
10490 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
10491 ast_mutex_lock(&p->lock);
10492 p->remotelyblocked = 1;
10493 ast_mutex_unlock(&p->lock);
10494 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
10495 break;
10496 case ISUP_EVENT_BLA:
10497 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
10498 if (chanpos < 0) {
10499 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
10500 break;
10501 }
10502 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
10503 p = linkset->pvts[chanpos];
10504 ast_mutex_lock(&p->lock);
10505 p->locallyblocked = 1;
10506 ast_mutex_unlock(&p->lock);
10507 break;
10508 case ISUP_EVENT_UBL:
10509 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
10510 if (chanpos < 0) {
10511 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
10512 break;
10513 }
10514 p = linkset->pvts[chanpos];
10515 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
10516 ast_mutex_lock(&p->lock);
10517 p->remotelyblocked = 0;
10518 ast_mutex_unlock(&p->lock);
10519 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
10520 break;
10521 case ISUP_EVENT_UBA:
10522 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
10523 if (chanpos < 0) {
10524 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
10525 break;
10526 }
10527 p = linkset->pvts[chanpos];
10528 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
10529 ast_mutex_lock(&p->lock);
10530 p->locallyblocked = 0;
10531 ast_mutex_unlock(&p->lock);
10532 break;
10533 case ISUP_EVENT_CON:
10534 case ISUP_EVENT_ANM:
10535 if (e->e == ISUP_EVENT_CON)
10536 cic = e->con.cic;
10537 else
10538 cic = e->anm.cic;
10539
10540 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
10541 if (chanpos < 0) {
10542 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
10543 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
10544 break;
10545 } else {
10546 p = linkset->pvts[chanpos];
10547 ast_mutex_lock(&p->lock);
10548 p->subs[SUB_REAL].needanswer = 1;
10549 if (p->dsp && p->dsp_features) {
10550 ast_dsp_set_features(p->dsp, p->dsp_features);
10551 p->dsp_features = 0;
10552 }
10553 dahdi_enable_ec(p);
10554 ast_mutex_unlock(&p->lock);
10555 }
10556 break;
10557 case ISUP_EVENT_RLC:
10558 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
10559 if (chanpos < 0) {
10560 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
10561 break;
10562 } else {
10563 p = linkset->pvts[chanpos];
10564 ast_mutex_lock(&p->lock);
10565 if (p->alreadyhungup)
10566 p->ss7call = NULL;
10567 else
10568 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
10569 ast_mutex_unlock(&p->lock);
10570 }
10571 break;
10572 case ISUP_EVENT_FAA:
10573 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
10574 if (chanpos < 0) {
10575 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
10576 break;
10577 } else {
10578 p = linkset->pvts[chanpos];
10579 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
10580 ast_mutex_lock(&p->lock);
10581 if (p->alreadyhungup){
10582 p->ss7call = NULL;
10583 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
10584 }
10585 ast_mutex_unlock(&p->lock);
10586 }
10587 break;
10588 default:
10589 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
10590 break;
10591 }
10592 }
10593 ast_mutex_unlock(&linkset->lock);
10594 }
10595
10596 return 0;
10597 }
10598
10599 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
10600 {
10601 #if 0
10602 int i;
10603
10604 for (i = 0; i < NUM_SPANS; i++)
10605 if (linksets[i].ss7 == ss7)
10606 break;
10607
10608 ast_verbose("[%d] %s", i+1, s);
10609 #else
10610 ast_verbose("%s", s);
10611 #endif
10612 }
10613
10614 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
10615 {
10616 #if 0
10617 int i;
10618
10619 for (i = 0; i < NUM_SPANS; i++)
10620 if (linksets[i].ss7 == ss7)
10621 break;
10622
10623 #else
10624 ast_log(LOG_ERROR, "%s", s);
10625 #endif
10626 }
10627
10628 #endif
10629
10630 #ifdef HAVE_PRI
10631 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10632 {
10633 struct dahdi_pvt *p;
10634 p = pri->crvs;
10635 while (p) {
10636 if (p->channel == crv)
10637 return p;
10638 p = p->next;
10639 }
10640 return NULL;
10641 }
10642
10643
10644 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10645 {
10646 int x;
10647 int span = PRI_SPAN(channel);
10648 int spanfd;
10649 struct dahdi_params param;
10650 int principle = -1;
10651 int explicit = PRI_EXPLICIT(channel);
10652 channel = PRI_CHANNEL(channel);
10653
10654 if (!explicit) {
10655 spanfd = pri_active_dchan_fd(pri);
10656 memset(¶m, 0, sizeof(param));
10657 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
10658 return -1;
10659 span = pris[param.spanno - 1].prilogicalspan;
10660 }
10661
10662 for (x = 0; x < pri->numchans; x++) {
10663 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10664 principle = x;
10665 break;
10666 }
10667 }
10668
10669 return principle;
10670 }
10671
10672 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10673 {
10674 int x;
10675 struct dahdi_pvt *crv;
10676 if (!c) {
10677 if (principle < 0)
10678 return -1;
10679 return principle;
10680 }
10681 if ((principle > -1) &&
10682 (principle < pri->numchans) &&
10683 (pri->pvts[principle]) &&
10684 (pri->pvts[principle]->call == c))
10685 return principle;
10686
10687 for (x = 0; x < pri->numchans; x++) {
10688 if (!pri->pvts[x])
10689 continue;
10690 if (pri->pvts[x]->call == c) {
10691
10692 if (principle != x) {
10693 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10694
10695 ast_verb(3, "Moving call from channel %d to channel %d\n",
10696 old->channel, new->channel);
10697 if (new->owner) {
10698 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10699 old->channel, new->channel, new->channel);
10700 return -1;
10701 }
10702
10703 new->owner = old->owner;
10704 old->owner = NULL;
10705 if (new->owner) {
10706 ast_string_field_build(new->owner, name,
10707 "DAHDI/%d:%d-%d", pri->trunkgroup,
10708 new->channel, 1);
10709 new->owner->tech_pvt = new;
10710 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10711 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10712 old->subs[SUB_REAL].owner = NULL;
10713 } else
10714 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);
10715 new->call = old->call;
10716 old->call = NULL;
10717
10718
10719 new->dsp = old->dsp;
10720 new->dsp_features = old->dsp_features;
10721 old->dsp = NULL;
10722 old->dsp_features = 0;
10723 }
10724 return principle;
10725 }
10726 }
10727
10728 crv = pri->crvs;
10729 while (crv) {
10730 if (crv->call == c) {
10731
10732 if (crv->bearer)
10733 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10734 else if (pri->pvts[principle]->owner)
10735 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10736 else {
10737
10738
10739 dahdi_close_sub(crv, SUB_REAL);
10740 pri->pvts[principle]->call = crv->call;
10741 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10742 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10743 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10744 pri->trunkgroup, crv->channel);
10745 wakeup_sub(crv, SUB_REAL, pri);
10746 }
10747 return principle;
10748 }
10749 crv = crv->next;
10750 }
10751 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10752 return -1;
10753 }
10754
10755 static void *do_idle_thread(void *vchan)
10756 {
10757 struct ast_channel *chan = vchan;
10758 struct dahdi_pvt *pvt = chan->tech_pvt;
10759 struct ast_frame *f;
10760 char ex[80];
10761
10762 int newms, ms = 30000;
10763 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10764 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10765 if (ast_call(chan, ex, 0)) {
10766 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10767 ast_hangup(chan);
10768 return NULL;
10769 }
10770 while ((newms = ast_waitfor(chan, ms)) > 0) {
10771 f = ast_read(chan);
10772 if (!f) {
10773
10774 break;
10775 }
10776 if (f->frametype == AST_FRAME_CONTROL) {
10777 switch (f->subclass) {
10778 case AST_CONTROL_ANSWER:
10779
10780 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10781 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10782 chan->priority = 1;
10783 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10784 ast_pbx_run(chan);
10785
10786 return NULL;
10787 case AST_CONTROL_BUSY:
10788 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10789 break;
10790 case AST_CONTROL_CONGESTION:
10791 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10792 break;
10793 };
10794 }
10795 ast_frfree(f);
10796 ms = newms;
10797 }
10798
10799 ast_hangup(chan);
10800 return NULL;
10801 }
10802
10803 #ifndef PRI_RESTART
10804 #error "Upgrade your libpri"
10805 #endif
10806 static void dahdi_pri_message(struct pri *pri, char *s)
10807 {
10808 int x, y;
10809 int dchan = -1, span = -1;
10810 int dchancount = 0;
10811
10812 if (pri) {
10813 for (x = 0; x < NUM_SPANS; x++) {
10814 for (y = 0; y < NUM_DCHANS; y++) {
10815 if (pris[x].dchans[y])
10816 dchancount++;
10817
10818 if (pris[x].dchans[y] == pri)
10819 dchan = y;
10820 }
10821 if (dchan >= 0) {
10822 span = x;
10823 break;
10824 }
10825 dchancount = 0;
10826 }
10827 if (dchancount > 1 && (span > -1))
10828 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10829 else
10830 ast_verbose("%s", s);
10831 } else
10832 ast_verbose("%s", s);
10833
10834 ast_mutex_lock(&pridebugfdlock);
10835
10836 if (pridebugfd >= 0) {
10837 if (write(pridebugfd, s, strlen(s)) < 0) {
10838 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10839 }
10840 }
10841
10842 ast_mutex_unlock(&pridebugfdlock);
10843 }
10844
10845 static void dahdi_pri_error(struct pri *pri, char *s)
10846 {
10847 int x, y;
10848 int dchan = -1, span = -1;
10849 int dchancount = 0;
10850
10851 if (pri) {
10852 for (x = 0; x < NUM_SPANS; x++) {
10853 for (y = 0; y < NUM_DCHANS; y++) {
10854 if (pris[x].dchans[y])
10855 dchancount++;
10856
10857 if (pris[x].dchans[y] == pri)
10858 dchan = y;
10859 }
10860 if (dchan >= 0) {
10861 span = x;
10862 break;
10863 }
10864 dchancount = 0;
10865 }
10866 if ((dchancount > 1) && (span > -1))
10867 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10868 else
10869 ast_log(LOG_ERROR, "%s", s);
10870 } else
10871 ast_log(LOG_ERROR, "%s", s);
10872
10873 ast_mutex_lock(&pridebugfdlock);
10874
10875 if (pridebugfd >= 0) {
10876 if (write(pridebugfd, s, strlen(s)) < 0) {
10877 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10878 }
10879 }
10880
10881 ast_mutex_unlock(&pridebugfdlock);
10882 }
10883
10884 static int pri_check_restart(struct dahdi_pri *pri)
10885 {
10886 do {
10887 pri->resetpos++;
10888 } while ((pri->resetpos < pri->numchans) &&
10889 (!pri->pvts[pri->resetpos] ||
10890 pri->pvts[pri->resetpos]->call ||
10891 pri->pvts[pri->resetpos]->resetting));
10892 if (pri->resetpos < pri->numchans) {
10893
10894 pri->pvts[pri->resetpos]->resetting = 1;
10895 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10896 } else {
10897 pri->resetting = 0;
10898 time(&pri->lastreset);
10899 }
10900 return 0;
10901 }
10902
10903 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10904 {
10905 int x;
10906 int redo;
10907 ast_mutex_unlock(&pri->lock);
10908 ast_mutex_lock(&p->lock);
10909 do {
10910 redo = 0;
10911 for (x = 0; x < 3; x++) {
10912 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10913 redo++;
10914 DEADLOCK_AVOIDANCE(&p->lock);
10915 }
10916 if (p->subs[x].owner) {
10917 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10918 ast_channel_unlock(p->subs[x].owner);
10919 }
10920 }
10921 } while (redo);
10922 ast_mutex_unlock(&p->lock);
10923 ast_mutex_lock(&pri->lock);
10924 return 0;
10925 }
10926
10927 static char * redirectingreason2str(int redirectingreason)
10928 {
10929 switch (redirectingreason) {
10930 case 0:
10931 return "UNKNOWN";
10932 case 1:
10933 return "BUSY";
10934 case 2:
10935 return "NO_REPLY";
10936 case 0xF:
10937 return "UNCONDITIONAL";
10938 default:
10939 return "NOREDIRECT";
10940 }
10941 }
10942
10943 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10944 {
10945 if (pri->dialplan == -2) {
10946 snprintf(buf, size, "%s", number);
10947 return;
10948 }
10949 if (ast_strlen_zero(number)) {
10950 if (size) {
10951 *buf = '\0';
10952 }
10953 return;
10954 }
10955 switch (plan) {
10956 case PRI_INTERNATIONAL_ISDN:
10957 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10958 break;
10959 case PRI_NATIONAL_ISDN:
10960 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10961 break;
10962 case PRI_LOCAL_ISDN:
10963 snprintf(buf, size, "%s%s", pri->localprefix, number);
10964 break;
10965 case PRI_PRIVATE:
10966 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10967 break;
10968 case PRI_UNKNOWN:
10969 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10970 break;
10971 default:
10972 snprintf(buf, size, "%s", number);
10973 break;
10974 }
10975 }
10976
10977
10978 static void *pri_dchannel(void *vpri)
10979 {
10980 struct dahdi_pri *pri = vpri;
10981 pri_event *e;
10982 struct pollfd fds[NUM_DCHANS];
10983 int res;
10984 int chanpos = 0;
10985 int x;
10986 int haveidles;
10987 int activeidles;
10988 int nextidle = -1;
10989 struct ast_channel *c;
10990 struct timeval tv, lowest, *next;
10991 struct timeval lastidle = ast_tvnow();
10992 int doidling=0;
10993 char *cc;
10994 char idlen[80];
10995 struct ast_channel *idle;
10996 pthread_t p;
10997 time_t t;
10998 int i, which=-1;
10999 int numdchans;
11000 int cause=0;
11001 struct dahdi_pvt *crv;
11002 pthread_t threadid;
11003 char ani2str[6];
11004 char plancallingnum[256];
11005 char plancallingani[256];
11006 char calledtonstr[10];
11007
11008 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11009
11010 gettimeofday(&lastidle, NULL);
11011 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
11012
11013 cc = strchr(pri->idleext, '@');
11014 if (cc) {
11015 *cc = '\0';
11016 cc++;
11017 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
11018 #if 0
11019
11020 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
11021 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
11022 else
11023 #endif
11024 doidling = 1;
11025 } else
11026 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
11027 }
11028 for (;;) {
11029 for (i = 0; i < NUM_DCHANS; i++) {
11030 if (!pri->dchannels[i])
11031 break;
11032 fds[i].fd = pri->fds[i];
11033 fds[i].events = POLLIN | POLLPRI;
11034 fds[i].revents = 0;
11035 }
11036 numdchans = i;
11037 time(&t);
11038 ast_mutex_lock(&pri->lock);
11039 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
11040 if (pri->resetting && pri_is_up(pri)) {
11041 if (pri->resetpos < 0)
11042 pri_check_restart(pri);
11043 } else {
11044 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
11045 pri->resetting = 1;
11046 pri->resetpos = -1;
11047 }
11048 }
11049 }
11050
11051 if (doidling && pri_is_up(pri)) {
11052 nextidle = -1;
11053 haveidles = 0;
11054 activeidles = 0;
11055 for (x = pri->numchans; x >= 0; x--) {
11056 if (pri->pvts[x] && !pri->pvts[x]->owner &&
11057 !pri->pvts[x]->call) {
11058 if (haveidles < pri->minunused) {
11059 haveidles++;
11060 } else if (!pri->pvts[x]->resetting) {
11061 nextidle = x;
11062 break;
11063 }
11064 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
11065 activeidles++;
11066 }
11067 if (nextidle > -1) {
11068 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
11069
11070 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
11071 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
11072 if (idle) {
11073 pri->pvts[nextidle]->isidlecall = 1;
11074 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
11075 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
11076 dahdi_hangup(idle);
11077 }
11078 } else
11079 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
11080 lastidle = ast_tvnow();
11081 }
11082 } else if ((haveidles < pri->minunused) &&
11083 (activeidles > pri->minidle)) {
11084
11085
11086 for (x = pri->numchans; x >= 0; x--) {
11087
11088 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
11089 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11090 haveidles++;
11091
11092
11093 if ((haveidles >= pri->minunused) ||
11094 (activeidles <= pri->minidle))
11095 break;
11096 }
11097 }
11098 }
11099 }
11100
11101 lowest = ast_tv(60, 0);
11102 for (i = 0; i < NUM_DCHANS; i++) {
11103
11104 if (!pri->dchannels[i])
11105 break;
11106 if ((next = pri_schedule_next(pri->dchans[i]))) {
11107
11108 tv = ast_tvsub(*next, ast_tvnow());
11109 if (tv.tv_sec < 0) {
11110 tv = ast_tv(0,0);
11111 }
11112 if (doidling || pri->resetting) {
11113 if (tv.tv_sec > 1) {
11114 tv = ast_tv(1, 0);
11115 }
11116 } else {
11117 if (tv.tv_sec > 60) {
11118 tv = ast_tv(60, 0);
11119 }
11120 }
11121 } else if (doidling || pri->resetting) {
11122
11123
11124 tv = ast_tv(1,0);
11125 } else {
11126
11127 tv = ast_tv(60, 0);
11128 }
11129 if (!i || ast_tvcmp(tv, lowest) < 0) {
11130 lowest = tv;
11131 }
11132 }
11133 ast_mutex_unlock(&pri->lock);
11134
11135 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11136 pthread_testcancel();
11137 e = NULL;
11138 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11139 pthread_testcancel();
11140 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11141
11142 ast_mutex_lock(&pri->lock);
11143 if (!res) {
11144 for (which = 0; which < NUM_DCHANS; which++) {
11145 if (!pri->dchans[which])
11146 break;
11147
11148 e = pri_schedule_run(pri->dchans[which]);
11149 if (e)
11150 break;
11151 }
11152 } else if (res > -1) {
11153 for (which = 0; which < NUM_DCHANS; which++) {
11154 if (!pri->dchans[which])
11155 break;
11156 if (fds[which].revents & POLLPRI) {
11157
11158 x = 0;
11159 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11160 if (x) {
11161 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);
11162 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
11163 "PRIEvent: %s\r\n"
11164 "PRIEventCode: %d\r\n"
11165 "D-channel: %s\r\n"
11166 "Span: %d\r\n",
11167 event2str(x),
11168 x,
11169 pri_order(which),
11170 pri->span
11171 );
11172 }
11173
11174 if (x == DAHDI_EVENT_ALARM) {
11175 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11176 pri_find_dchan(pri);
11177 } else if (x == DAHDI_EVENT_NOALARM) {
11178 pri->dchanavail[which] |= DCHAN_NOTINALARM;
11179 pri_restart(pri->dchans[which]);
11180 }
11181
11182 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11183 } else if (fds[which].revents & POLLIN) {
11184 e = pri_check_event(pri->dchans[which]);
11185 }
11186 if (e)
11187 break;
11188 }
11189 } else if (errno != EINTR)
11190 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11191
11192 if (e) {
11193 if (pri->debug)
11194 pri_dump_event(pri->dchans[which], e);
11195
11196 if (e->e != PRI_EVENT_DCHAN_DOWN) {
11197 if (!(pri->dchanavail[which] & DCHAN_UP)) {
11198 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11199 }
11200 pri->dchanavail[which] |= DCHAN_UP;
11201 } else if (pri->sig != SIG_BRI_PTMP) {
11202 if (pri->dchanavail[which] & DCHAN_UP) {
11203 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11204 }
11205 pri->dchanavail[which] &= ~DCHAN_UP;
11206 }
11207
11208 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11209
11210 pri->pri = pri->dchans[which];
11211
11212 switch (e->e) {
11213 case PRI_EVENT_DCHAN_UP:
11214 if (!pri->pri) pri_find_dchan(pri);
11215
11216
11217 time(&pri->lastreset);
11218
11219
11220 if (pri->resetinterval > -1) {
11221 pri->lastreset -= pri->resetinterval;
11222 pri->lastreset += 5;
11223 }
11224 pri->resetting = 0;
11225
11226 for (i = 0; i < pri->numchans; i++)
11227 if (pri->pvts[i]) {
11228 pri->pvts[i]->inalarm = 0;
11229 }
11230 break;
11231 case PRI_EVENT_DCHAN_DOWN:
11232 pri_find_dchan(pri);
11233 if (!pri_is_up(pri)) {
11234 pri->resetting = 0;
11235
11236 for (i = 0; i < pri->numchans; i++) {
11237 struct dahdi_pvt *p = pri->pvts[i];
11238 if (p) {
11239 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11240
11241 if (p->call) {
11242 if (p->pri && p->pri->pri) {
11243 pri_hangup(p->pri->pri, p->call, -1);
11244 pri_destroycall(p->pri->pri, p->call);
11245 p->call = NULL;
11246 } else
11247 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
11248 }
11249 if (p->realcall) {
11250 pri_hangup_all(p->realcall, pri);
11251 } else if (p->owner)
11252 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11253 }
11254 p->inalarm = 1;
11255 }
11256 }
11257 }
11258 break;
11259 case PRI_EVENT_RESTART:
11260 if (e->restart.channel > -1) {
11261 chanpos = pri_find_principle(pri, e->restart.channel);
11262 if (chanpos < 0)
11263 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
11264 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11265 else {
11266 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
11267 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11268 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11269 if (pri->pvts[chanpos]->call) {
11270 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11271 pri->pvts[chanpos]->call = NULL;
11272 }
11273
11274 if (pri->pvts[chanpos]->realcall)
11275 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11276 else if (pri->pvts[chanpos]->owner)
11277 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11278 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11279 }
11280 } else {
11281 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
11282 for (x = 0; x < pri->numchans; x++)
11283 if (pri->pvts[x]) {
11284 ast_mutex_lock(&pri->pvts[x]->lock);
11285 if (pri->pvts[x]->call) {
11286 pri_destroycall(pri->pri, pri->pvts[x]->call);
11287 pri->pvts[x]->call = NULL;
11288 }
11289 if (pri->pvts[x]->realcall)
11290 pri_hangup_all(pri->pvts[x]->realcall, pri);
11291 else if (pri->pvts[x]->owner)
11292 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11293 ast_mutex_unlock(&pri->pvts[x]->lock);
11294 }
11295 }
11296 break;
11297 case PRI_EVENT_KEYPAD_DIGIT:
11298 chanpos = pri_find_principle(pri, e->digit.channel);
11299 if (chanpos < 0) {
11300 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
11301 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
11302 } else {
11303 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
11304 if (chanpos > -1) {
11305 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11306
11307 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
11308
11309 int digitlen = strlen(e->digit.digits);
11310 char digit;
11311 int i;
11312 for (i = 0; i < digitlen; i++) {
11313 digit = e->digit.digits[i];
11314 {
11315 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11316 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11317 }
11318 }
11319 }
11320 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11321 }
11322 }
11323 break;
11324
11325 case PRI_EVENT_INFO_RECEIVED:
11326 chanpos = pri_find_principle(pri, e->ring.channel);
11327 if (chanpos < 0) {
11328 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
11329 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11330 } else {
11331 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
11332 if (chanpos > -1) {
11333 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11334
11335 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
11336
11337 int digitlen = strlen(e->ring.callednum);
11338 char digit;
11339 int i;
11340 for (i = 0; i < digitlen; i++) {
11341 digit = e->ring.callednum[i];
11342 {
11343 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11344 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11345 }
11346 }
11347 }
11348 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11349 }
11350 }
11351 break;
11352 case PRI_EVENT_RING:
11353 crv = NULL;
11354 if (e->ring.channel == -1)
11355 chanpos = pri_find_empty_chan(pri, 1);
11356 else
11357 chanpos = pri_find_principle(pri, e->ring.channel);
11358
11359 if (chanpos < 0) {
11360 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
11361 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11362 } else {
11363 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11364 if (pri->pvts[chanpos]->owner) {
11365 if (pri->pvts[chanpos]->call == e->ring.call) {
11366 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
11367 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11368 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11369 break;
11370 } else {
11371
11372 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
11373 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11374 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11375 chanpos = -1;
11376 }
11377 }
11378 if (chanpos > -1)
11379 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11380 }
11381 if ((chanpos < 0) && (e->ring.flexible))
11382 chanpos = pri_find_empty_chan(pri, 1);
11383 if (chanpos > -1) {
11384 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11385 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11386
11387 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11388 if (crv)
11389 ast_mutex_lock(&crv->lock);
11390 if (!crv || crv->owner) {
11391 pri->pvts[chanpos]->call = NULL;
11392 if (crv) {
11393 if (crv->owner)
11394 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11395 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);
11396 } else
11397 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);
11398 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11399 if (crv)
11400 ast_mutex_unlock(&crv->lock);
11401 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11402 break;
11403 }
11404 }
11405 pri->pvts[chanpos]->call = e->ring.call;
11406 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11407 if (pri->pvts[chanpos]->use_callerid) {
11408 ast_shrink_phone_number(plancallingnum);
11409 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11410 #ifdef PRI_ANI
11411 if (!ast_strlen_zero(e->ring.callingani)) {
11412 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11413 ast_shrink_phone_number(plancallingani);
11414 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11415 } else {
11416 pri->pvts[chanpos]->cid_ani[0] = '\0';
11417 }
11418 #endif
11419 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11420 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
11421 } else {
11422 pri->pvts[chanpos]->cid_num[0] = '\0';
11423 pri->pvts[chanpos]->cid_ani[0] = '\0';
11424 pri->pvts[chanpos]->cid_name[0] = '\0';
11425 pri->pvts[chanpos]->cid_ton = 0;
11426 }
11427 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11428 e->ring.redirectingnum, e->ring.callingplanrdnis);
11429
11430 if (pri->pvts[chanpos]->immediate) {
11431 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
11432 pri->pvts[chanpos]->exten[0] = 's';
11433 pri->pvts[chanpos]->exten[1] = '\0';
11434 }
11435
11436 else if (!ast_strlen_zero(e->ring.callednum)) {
11437 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11438 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11439 } else if (pri->overlapdial)
11440 pri->pvts[chanpos]->exten[0] = '\0';
11441 else {
11442
11443 pri->pvts[chanpos]->exten[0] = 's';
11444 pri->pvts[chanpos]->exten[1] = '\0';
11445 }
11446
11447 if (!ast_strlen_zero(e->ring.callednum))
11448 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11449
11450 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11451 ast_verb(3, "Going to extension s|1 because of Complete received\n");
11452 pri->pvts[chanpos]->exten[0] = 's';
11453 pri->pvts[chanpos]->exten[1] = '\0';
11454 }
11455
11456
11457 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11458 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11459
11460 int law;
11461 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11462
11463 law = 1;
11464 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11465 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11466 }
11467 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11468 law = DAHDI_LAW_ALAW;
11469 else
11470 law = DAHDI_LAW_MULAW;
11471 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11472 if (res < 0)
11473 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11474 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11475 if (res < 0)
11476 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11477 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11478
11479 pri->pvts[chanpos]->proceeding = 1;
11480 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11481 } else {
11482 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
11483 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11484 else
11485 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11486 }
11487
11488 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11489
11490
11491 if (!e->ring.complete
11492 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11493 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11494
11495
11496
11497
11498 ast_mutex_unlock(&pri->lock);
11499 if (crv) {
11500
11501 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11502 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11503 pri->pvts[chanpos]->owner = &inuse;
11504 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11505 } else {
11506 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11507 }
11508 ast_mutex_lock(&pri->lock);
11509 if (c) {
11510 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11511 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11512 }
11513 if (e->ring.ani2 >= 0) {
11514 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11515 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11516 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11517 }
11518
11519 #ifdef SUPPORT_USERUSER
11520 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11521 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11522 }
11523 #endif
11524
11525 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11526 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11527 if (e->ring.redirectingreason >= 0)
11528 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11529 }
11530 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
11531 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11532 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11533 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11534 } else {
11535 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11536 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11537 if (c)
11538 ast_hangup(c);
11539 else {
11540 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11541 pri->pvts[chanpos]->call = NULL;
11542 }
11543 }
11544 } else {
11545
11546
11547
11548
11549 ast_mutex_unlock(&pri->lock);
11550 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
11551 ast_mutex_lock(&pri->lock);
11552 if (c) {
11553
11554
11555
11556
11557
11558
11559
11560
11561 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11562 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11563 }
11564 if (e->ring.ani2 >= 0) {
11565 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11566 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11567 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11568 }
11569
11570 #ifdef SUPPORT_USERUSER
11571 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11572 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11573 }
11574 #endif
11575
11576 if (e->ring.redirectingreason >= 0)
11577 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11578
11579 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11580 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11581 }
11582 if (c && !ast_pbx_start(c)) {
11583 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11584 plancallingnum, pri->pvts[chanpos]->exten,
11585 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11586
11587 dahdi_enable_ec(pri->pvts[chanpos]);
11588 } else {
11589 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11590 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11591 if (c) {
11592 ast_hangup(c);
11593 } else {
11594 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11595 pri->pvts[chanpos]->call = NULL;
11596 }
11597 }
11598 }
11599 } else {
11600 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
11601 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
11602 pri->pvts[chanpos]->prioffset, pri->span);
11603 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11604 pri->pvts[chanpos]->call = NULL;
11605 pri->pvts[chanpos]->exten[0] = '\0';
11606 }
11607 if (crv)
11608 ast_mutex_unlock(&crv->lock);
11609 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11610 } else {
11611 if (e->ring.flexible)
11612 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11613 else
11614 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11615 }
11616 break;
11617 case PRI_EVENT_RINGING:
11618 chanpos = pri_find_principle(pri, e->ringing.channel);
11619 if (chanpos < 0) {
11620 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
11621 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11622 } else {
11623 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
11624 if (chanpos < 0) {
11625 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
11626 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11627 } else {
11628 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11629 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11630 dahdi_enable_ec(pri->pvts[chanpos]);
11631 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11632 pri->pvts[chanpos]->alerting = 1;
11633 } else
11634 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11635
11636 #ifdef PRI_PROGRESS_MASK
11637 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11638 #else
11639 if (e->ringing.progress == 8) {
11640 #endif
11641
11642 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11643
11644 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11645 pri->pvts[chanpos]->dsp_features = 0;
11646 }
11647 }
11648
11649 #ifdef SUPPORT_USERUSER
11650 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11651 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11652 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11653 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11654 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11655 }
11656 #endif
11657
11658 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11659 }
11660 }
11661 break;
11662 case PRI_EVENT_PROGRESS:
11663
11664 chanpos = pri_find_principle(pri, e->proceeding.channel);
11665 if (chanpos > -1) {
11666 #ifdef PRI_PROGRESS_MASK
11667 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11668 #else
11669 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11670 #endif
11671 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11672
11673 if (e->proceeding.cause > -1) {
11674 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11675
11676
11677 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11678 if (pri->pvts[chanpos]->owner) {
11679 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11680
11681 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11682 f.subclass = AST_CONTROL_BUSY;
11683 }
11684 }
11685 }
11686
11687 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11688 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11689 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11690 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11691 #ifdef PRI_PROGRESS_MASK
11692 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11693 #else
11694 if (e->proceeding.progress == 8) {
11695 #endif
11696
11697 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11698 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11699 pri->pvts[chanpos]->dsp_features = 0;
11700 }
11701
11702 f.subclass = AST_CONTROL_PROGRESS;
11703 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11704 }
11705 pri->pvts[chanpos]->progress = 1;
11706 pri->pvts[chanpos]->dialing = 0;
11707 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11708 }
11709 }
11710 break;
11711 case PRI_EVENT_PROCEEDING:
11712 chanpos = pri_find_principle(pri, e->proceeding.channel);
11713 if (chanpos > -1) {
11714 if (!pri->pvts[chanpos]->proceeding) {
11715 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11716
11717 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11718 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11719 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11720 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11721 #ifdef PRI_PROGRESS_MASK
11722 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11723 #else
11724 if (e->proceeding.progress == 8) {
11725 #endif
11726
11727 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11728 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11729 pri->pvts[chanpos]->dsp_features = 0;
11730 }
11731
11732 f.subclass = AST_CONTROL_PROGRESS;
11733 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11734 }
11735 pri->pvts[chanpos]->proceeding = 1;
11736 pri->pvts[chanpos]->dialing = 0;
11737 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11738 }
11739 }
11740 break;
11741 case PRI_EVENT_FACNAME:
11742 chanpos = pri_find_principle(pri, e->facname.channel);
11743 if (chanpos < 0) {
11744 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11745 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11746 } else {
11747 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11748 if (chanpos < 0) {
11749 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
11750 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11751 } else {
11752
11753 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11754 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11755 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11756 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11757 dahdi_enable_ec(pri->pvts[chanpos]);
11758 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11759 }
11760 }
11761 break;
11762 case PRI_EVENT_ANSWER:
11763 chanpos = pri_find_principle(pri, e->answer.channel);
11764 if (chanpos < 0) {
11765 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
11766 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11767 } else {
11768 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11769 if (chanpos < 0) {
11770 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
11771 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11772 } else {
11773 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11774
11775
11776
11777
11778
11779 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11780 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11781 pri->pvts[chanpos]->dsp_features = 0;
11782 }
11783 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11784 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11785 x = DAHDI_START;
11786 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11787 if (res < 0) {
11788 if (errno != EINPROGRESS) {
11789 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11790 }
11791 }
11792 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11793 pri->pvts[chanpos]->dialing = 1;
11794
11795 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11796 if (res < 0) {
11797 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11798 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11799 } else
11800 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11801
11802 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11803 } else if (pri->pvts[chanpos]->confirmanswer) {
11804 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11805 } else {
11806 pri->pvts[chanpos]->dialing = 0;
11807 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11808
11809 dahdi_enable_ec(pri->pvts[chanpos]);
11810 }
11811
11812 #ifdef SUPPORT_USERUSER
11813 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11814 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11815 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11816 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11817 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11818 }
11819 #endif
11820
11821 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11822 }
11823 }
11824 break;
11825 case PRI_EVENT_HANGUP:
11826 chanpos = pri_find_principle(pri, e->hangup.channel);
11827 if (chanpos < 0) {
11828 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
11829 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11830 } else {
11831 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11832 if (chanpos > -1) {
11833 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11834 if (!pri->pvts[chanpos]->alreadyhungup) {
11835
11836 pri->pvts[chanpos]->alreadyhungup = 1;
11837 if (pri->pvts[chanpos]->realcall)
11838 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11839 else if (pri->pvts[chanpos]->owner) {
11840
11841 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11842 switch (pri->pvts[chanpos]->owner->_state) {
11843 case AST_STATE_BUSY:
11844 case AST_STATE_UP:
11845 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11846 break;
11847 default:
11848 switch (e->hangup.cause) {
11849 case PRI_CAUSE_USER_BUSY:
11850 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11851 break;
11852 case PRI_CAUSE_CALL_REJECTED:
11853 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11854 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11855 case PRI_CAUSE_SWITCH_CONGESTION:
11856 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11857 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11858 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11859 break;
11860 default:
11861 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11862 }
11863 break;
11864 }
11865 }
11866 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11867 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11868 } else {
11869 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11870 pri->pvts[chanpos]->call = NULL;
11871 }
11872 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11873 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11874 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11875 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11876 pri->pvts[chanpos]->resetting = 1;
11877 }
11878 if (e->hangup.aoc_units > -1)
11879 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11880 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11881
11882 #ifdef SUPPORT_USERUSER
11883 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11884 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11885 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11886 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11887 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11888 }
11889 #endif
11890
11891 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11892 } else {
11893 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
11894 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11895 }
11896 }
11897 break;
11898 #ifndef PRI_EVENT_HANGUP_REQ
11899 #error please update libpri
11900 #endif
11901 case PRI_EVENT_HANGUP_REQ:
11902 chanpos = pri_find_principle(pri, e->hangup.channel);
11903 if (chanpos < 0) {
11904 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11905 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11906 } else {
11907 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11908 if (chanpos > -1) {
11909 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11910 if (pri->pvts[chanpos]->realcall)
11911 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11912 else if (pri->pvts[chanpos]->owner) {
11913 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11914 switch (pri->pvts[chanpos]->owner->_state) {
11915 case AST_STATE_BUSY:
11916 case AST_STATE_UP:
11917 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11918 break;
11919 default:
11920 switch (e->hangup.cause) {
11921 case PRI_CAUSE_USER_BUSY:
11922 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11923 break;
11924 case PRI_CAUSE_CALL_REJECTED:
11925 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11926 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11927 case PRI_CAUSE_SWITCH_CONGESTION:
11928 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11929 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11930 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11931 break;
11932 default:
11933 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11934 }
11935 break;
11936 }
11937 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);
11938 if (e->hangup.aoc_units > -1)
11939 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11940 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11941 } else {
11942 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11943 pri->pvts[chanpos]->call = NULL;
11944 }
11945 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11946 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11947 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11948 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11949 pri->pvts[chanpos]->resetting = 1;
11950 }
11951
11952 #ifdef SUPPORT_USERUSER
11953 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11954 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11955 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11956 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11957 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11958 }
11959 #endif
11960
11961 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11962 } else {
11963 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);
11964 }
11965 }
11966 break;
11967 case PRI_EVENT_HANGUP_ACK:
11968 chanpos = pri_find_principle(pri, e->hangup.channel);
11969 if (chanpos < 0) {
11970 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11971 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11972 } else {
11973 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11974 if (chanpos > -1) {
11975 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11976 pri->pvts[chanpos]->call = NULL;
11977 pri->pvts[chanpos]->resetting = 0;
11978 if (pri->pvts[chanpos]->owner) {
11979 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11980 }
11981
11982 #ifdef SUPPORT_USERUSER
11983 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11984 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11985 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11986 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11987 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11988 }
11989 #endif
11990
11991 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11992 }
11993 }
11994 break;
11995 case PRI_EVENT_CONFIG_ERR:
11996 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11997 break;
11998 case PRI_EVENT_RESTART_ACK:
11999 chanpos = pri_find_principle(pri, e->restartack.channel);
12000 if (chanpos < 0) {
12001
12002
12003
12004 for (x = 0; x < pri->numchans; x++) {
12005 if (pri->pvts[x] && pri->pvts[x]->resetting) {
12006 chanpos = x;
12007 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12008 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
12009 pri->pvts[chanpos]->prioffset, pri->span);
12010 if (pri->pvts[chanpos]->realcall)
12011 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12012 else if (pri->pvts[chanpos]->owner) {
12013 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
12014 pri->pvts[chanpos]->prioffset, pri->span);
12015 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12016 }
12017 pri->pvts[chanpos]->resetting = 0;
12018 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
12019 pri->pvts[chanpos]->prioffset, pri->span);
12020 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12021 if (pri->resetting)
12022 pri_check_restart(pri);
12023 break;
12024 }
12025 }
12026 if (chanpos < 0) {
12027 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
12028 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
12029 }
12030 } else {
12031 if (pri->pvts[chanpos]) {
12032 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12033 if (pri->pvts[chanpos]->realcall)
12034 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12035 else if (pri->pvts[chanpos]->owner) {
12036 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
12037 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
12038 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12039 }
12040 pri->pvts[chanpos]->resetting = 0;
12041 pri->pvts[chanpos]->inservice = 1;
12042 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
12043 pri->pvts[chanpos]->prioffset, pri->span);
12044 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12045 if (pri->resetting)
12046 pri_check_restart(pri);
12047 }
12048 }
12049 break;
12050 case PRI_EVENT_SETUP_ACK:
12051 chanpos = pri_find_principle(pri, e->setup_ack.channel);
12052 if (chanpos < 0) {
12053 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
12054 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
12055 } else {
12056 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
12057 if (chanpos > -1) {
12058 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12059 pri->pvts[chanpos]->setup_ack = 1;
12060
12061 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
12062 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
12063 pri_information(pri->pri, pri->pvts[chanpos]->call,
12064 pri->pvts[chanpos]->dialdest[x]);
12065 }
12066 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12067 } else
12068 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
12069 }
12070 break;
12071 case PRI_EVENT_NOTIFY:
12072 chanpos = pri_find_principle(pri, e->notify.channel);
12073 if (chanpos < 0) {
12074 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
12075 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
12076 } else {
12077 struct ast_frame f = { AST_FRAME_CONTROL, };
12078 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12079 switch (e->notify.info) {
12080 case PRI_NOTIFY_REMOTE_HOLD:
12081 f.subclass = AST_CONTROL_HOLD;
12082 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12083 break;
12084 case PRI_NOTIFY_REMOTE_RETRIEVAL:
12085 f.subclass = AST_CONTROL_UNHOLD;
12086 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12087 break;
12088 }
12089 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12090 }
12091 break;
12092 default:
12093 ast_debug(1, "Event: %d\n", e->e);
12094 }
12095 }
12096 ast_mutex_unlock(&pri->lock);
12097 }
12098
12099 return NULL;
12100 }
12101
12102 static int start_pri(struct dahdi_pri *pri)
12103 {
12104 int res, x;
12105 struct dahdi_params p;
12106 struct dahdi_bufferinfo bi;
12107 struct dahdi_spaninfo si;
12108 int i;
12109
12110 for (i = 0; i < NUM_DCHANS; i++) {
12111 if (!pri->dchannels[i])
12112 break;
12113 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
12114 x = pri->dchannels[i];
12115 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
12116 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12117 return -1;
12118 }
12119 memset(&p, 0, sizeof(p));
12120 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12121 if (res) {
12122 dahdi_close_pri_fd(pri, i);
12123 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12124 return -1;
12125 }
12126 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12127 dahdi_close_pri_fd(pri, i);
12128 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
12129 return -1;
12130 }
12131 memset(&si, 0, sizeof(si));
12132 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12133 if (res) {
12134 dahdi_close_pri_fd(pri, i);
12135 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12136 }
12137 if (!si.alarms)
12138 pri->dchanavail[i] |= DCHAN_NOTINALARM;
12139 else
12140 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12141 memset(&bi, 0, sizeof(bi));
12142 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12143 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12144 bi.numbufs = 32;
12145 bi.bufsize = 1024;
12146 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12147 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12148 dahdi_close_pri_fd(pri, i);
12149 return -1;
12150 }
12151 switch (pri->sig) {
12152 case SIG_BRI:
12153 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12154 break;
12155 case SIG_BRI_PTMP:
12156 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12157 break;
12158 default:
12159 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12160 }
12161
12162 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12163 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12164 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12165 #ifdef HAVE_PRI_INBANDDISCONNECT
12166 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12167 #endif
12168
12169 if (i)
12170 pri_enslave(pri->dchans[0], pri->dchans[i]);
12171 if (!pri->dchans[i]) {
12172 dahdi_close_pri_fd(pri, i);
12173 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12174 return -1;
12175 }
12176 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12177 pri_set_nsf(pri->dchans[i], pri->nsf);
12178 #ifdef PRI_GETSET_TIMERS
12179 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12180 if (pritimers[x] != 0)
12181 pri_set_timer(pri->dchans[i], x, pritimers[x]);
12182 }
12183 #endif
12184 }
12185
12186 pri->pri = pri->dchans[0];
12187 pri->resetpos = -1;
12188 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12189 for (i = 0; i < NUM_DCHANS; i++) {
12190 if (!pri->dchannels[i])
12191 break;
12192 dahdi_close_pri_fd(pri, i);
12193 }
12194 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12195 return -1;
12196 }
12197 return 0;
12198 }
12199
12200 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
12201 {
12202 int which, span;
12203 char *ret = NULL;
12204
12205 if (pos != rpos)
12206 return ret;
12207
12208 for (which = span = 0; span < NUM_SPANS; span++) {
12209 if (pris[span].pri && ++which > state) {
12210 if (asprintf(&ret, "%d", span + 1) < 0) {
12211 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12212 }
12213 break;
12214 }
12215 }
12216 return ret;
12217 }
12218
12219 static char *complete_span_4(const char *line, const char *word, int pos, int state)
12220 {
12221 return complete_span_helper(line,word,pos,state,3);
12222 }
12223
12224 static char *complete_span_5(const char *line, const char *word, int pos, int state)
12225 {
12226 return complete_span_helper(line,word,pos,state,4);
12227 }
12228
12229 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12230 {
12231 switch (cmd) {
12232 case CLI_INIT:
12233 e->command = "pri unset debug file";
12234 e->usage = "Usage: pri unset debug file\n"
12235 " Stop sending debug output to the previously \n"
12236 " specified file\n";
12237 return NULL;
12238 case CLI_GENERATE:
12239 return NULL;
12240 }
12241
12242 ast_mutex_lock(&pridebugfdlock);
12243 close(pridebugfd);
12244 pridebugfd = -1;
12245 ast_cli(a->fd, "PRI debug output to file disabled\n");
12246 ast_mutex_unlock(&pridebugfdlock);
12247 return CLI_SUCCESS;
12248 }
12249
12250 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12251 {
12252 int myfd;
12253 switch (cmd) {
12254 case CLI_INIT:
12255 e->command = "pri set debug file";
12256 e->usage = "Usage: pri set debug file [output-file]\n"
12257 " Sends PRI debug output to the specified output file\n";
12258 return NULL;
12259 case CLI_GENERATE:
12260 return NULL;
12261 }
12262 if (a->argc < 5)
12263 return CLI_SHOWUSAGE;
12264
12265 if (ast_strlen_zero(a->argv[4]))
12266 return CLI_SHOWUSAGE;
12267
12268 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12269 if (myfd < 0) {
12270 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12271 return CLI_SUCCESS;
12272 }
12273
12274 ast_mutex_lock(&pridebugfdlock);
12275
12276 if (pridebugfd >= 0)
12277 close(pridebugfd);
12278
12279 pridebugfd = myfd;
12280 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12281 ast_mutex_unlock(&pridebugfdlock);
12282 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12283 return CLI_SUCCESS;
12284 }
12285
12286 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12287 {
12288 int span;
12289 int x;
12290 switch (cmd) {
12291 case CLI_INIT:
12292 e->command = "pri debug span";
12293 e->usage =
12294 "Usage: pri debug span <span>\n"
12295 " Enables debugging on a given PRI span\n";
12296 return NULL;
12297 case CLI_GENERATE:
12298 return complete_span_4(a->line, a->word, a->pos, a->n);
12299 }
12300 if (a->argc < 4) {
12301 return CLI_SHOWUSAGE;
12302 }
12303 span = atoi(a->argv[3]);
12304 if ((span < 1) || (span > NUM_SPANS)) {
12305 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
12306 return CLI_SUCCESS;
12307 }
12308 if (!pris[span-1].pri) {
12309 ast_cli(a->fd, "No PRI running on span %d\n", span);
12310 return CLI_SUCCESS;
12311 }
12312 for (x = 0; x < NUM_DCHANS; x++) {
12313 if (pris[span-1].dchans[x])
12314 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12315 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12316 PRI_DEBUG_Q921_STATE);
12317 }
12318 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
12319 return CLI_SUCCESS;
12320 }
12321
12322
12323
12324 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12325 {
12326 int span;
12327 int x;
12328 switch (cmd) {
12329 case CLI_INIT:
12330 e->command = "pri no debug span";
12331 e->usage =
12332 "Usage: pri no debug span <span>\n"
12333 " Disables debugging on a given PRI span\n";
12334 return NULL;
12335 case CLI_GENERATE:
12336 return complete_span_5(a->line, a->word, a->pos, a->n);
12337 }
12338 if (a->argc < 5)
12339 return CLI_SHOWUSAGE;
12340
12341 span = atoi(a->argv[4]);
12342 if ((span < 1) || (span > NUM_SPANS)) {
12343 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12344 return CLI_SUCCESS;
12345 }
12346 if (!pris[span-1].pri) {
12347 ast_cli(a->fd, "No PRI running on span %d\n", span);
12348 return CLI_SUCCESS;
12349 }
12350 for (x = 0; x < NUM_DCHANS; x++) {
12351 if (pris[span-1].dchans[x])
12352 pri_set_debug(pris[span-1].dchans[x], 0);
12353 }
12354 ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12355 return CLI_SUCCESS;
12356 }
12357
12358 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12359 {
12360 int span;
12361 int x;
12362 switch (cmd) {
12363 case CLI_INIT:
12364 e->command = "pri intensive debug span";
12365 e->usage =
12366 "Usage: pri intensive debug span <span>\n"
12367 " Enables debugging down to the Q.921 level\n";
12368 return NULL;
12369 case CLI_GENERATE:
12370 return complete_span_5(a->line, a->word, a->pos, a->n);
12371 }
12372
12373 if (a->argc < 5)
12374 return CLI_SHOWUSAGE;
12375 span = atoi(a->argv[4]);
12376 if ((span < 1) || (span > NUM_SPANS)) {
12377 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12378 return CLI_SUCCESS;
12379 }
12380 if (!pris[span-1].pri) {
12381 ast_cli(a->fd, "No PRI running on span %d\n", span);
12382 return CLI_SUCCESS;
12383 }
12384 for (x = 0; x < NUM_DCHANS; x++) {
12385 if (pris[span-1].dchans[x])
12386 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12387 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12388 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12389 }
12390 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12391 return CLI_SUCCESS;
12392 }
12393
12394 static void build_status(char *s, size_t len, int status, int active)
12395 {
12396 if (!s || len < 1) {
12397 return;
12398 }
12399 s[0] = '\0';
12400 if (status & DCHAN_PROVISIONED)
12401 strncat(s, "Provisioned, ", len - strlen(s) - 1);
12402 if (!(status & DCHAN_NOTINALARM))
12403 strncat(s, "In Alarm, ", len - strlen(s) - 1);
12404 if (status & DCHAN_UP)
12405 strncat(s, "Up", len - strlen(s) - 1);
12406 else
12407 strncat(s, "Down", len - strlen(s) - 1);
12408 if (active)
12409 strncat(s, ", Active", len - strlen(s) - 1);
12410 else
12411 strncat(s, ", Standby", len - strlen(s) - 1);
12412 s[len - 1] = '\0';
12413 }
12414
12415 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12416 {
12417 int span;
12418 int x;
12419 char status[256];
12420
12421 switch (cmd) {
12422 case CLI_INIT:
12423 e->command = "pri show spans";
12424 e->usage =
12425 "Usage: pri show spans\n"
12426 " Displays PRI Information\n";
12427 return NULL;
12428 case CLI_GENERATE:
12429 return NULL;
12430 }
12431
12432 if (a->argc != 3)
12433 return CLI_SHOWUSAGE;
12434
12435 for (span = 0; span < NUM_SPANS; span++) {
12436 if (pris[span].pri) {
12437 for (x = 0; x < NUM_DCHANS; x++) {
12438 if (pris[span].dchannels[x]) {
12439 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12440 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12441 }
12442 }
12443 }
12444 }
12445 return CLI_SUCCESS;
12446 }
12447
12448 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12449 {
12450 int span;
12451 int x;
12452 char status[256];
12453 switch (cmd) {
12454 case CLI_INIT:
12455 e->command = "pri show span";
12456 e->usage =
12457 "Usage: pri show span <span>\n"
12458 " Displays PRI Information on a given PRI span\n";
12459 return NULL;
12460 case CLI_GENERATE:
12461 return complete_span_4(a->line, a->word, a->pos, a->n);
12462 }
12463
12464 if (a->argc < 4)
12465 return CLI_SHOWUSAGE;
12466 span = atoi(a->argv[3]);
12467 if ((span < 1) || (span > NUM_SPANS)) {
12468 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12469 return CLI_SUCCESS;
12470 }
12471 if (!pris[span-1].pri) {
12472 ast_cli(a->fd, "No PRI running on span %d\n", span);
12473 return CLI_SUCCESS;
12474 }
12475 for (x = 0; x < NUM_DCHANS; x++) {
12476 if (pris[span-1].dchannels[x]) {
12477 #ifdef PRI_DUMP_INFO_STR
12478 char *info_str = NULL;
12479 #endif
12480 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12481 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12482 ast_cli(a->fd, "Status: %s\n", status);
12483 #ifdef PRI_DUMP_INFO_STR
12484 info_str = pri_dump_info_str(pris[span-1].pri);
12485 if (info_str) {
12486 ast_cli(a->fd, "%s", info_str);
12487 ast_free(info_str);
12488 }
12489 #else
12490 pri_dump_info(pris[span-1].pri);
12491 #endif
12492 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12493 }
12494 }
12495 return CLI_SUCCESS;
12496 }
12497
12498 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12499 {
12500 int x;
12501 int span;
12502 int count=0;
12503 int debug=0;
12504
12505 switch (cmd) {
12506 case CLI_INIT:
12507 e->command = "pri show debug";
12508 e->usage =
12509 "Usage: pri show debug\n"
12510 " Show the debug state of pri spans\n";
12511 return NULL;
12512 case CLI_GENERATE:
12513 return NULL;
12514 }
12515
12516 for (span = 0; span < NUM_SPANS; span++) {
12517 if (pris[span].pri) {
12518 for (x = 0; x < NUM_DCHANS; x++) {
12519 debug = 0;
12520 if (pris[span].dchans[x]) {
12521 debug = pri_get_debug(pris[span].dchans[x]);
12522 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" );
12523 count++;
12524 }
12525 }
12526 }
12527
12528 }
12529 ast_mutex_lock(&pridebugfdlock);
12530 if (pridebugfd >= 0)
12531 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12532 ast_mutex_unlock(&pridebugfdlock);
12533
12534 if (!count)
12535 ast_cli(a->fd, "No debug set or no PRI running\n");
12536 return CLI_SUCCESS;
12537 }
12538
12539 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12540 {
12541 switch (cmd) {
12542 case CLI_INIT:
12543 e->command = "pri show version";
12544 e->usage =
12545 "Usage: pri show version\n"
12546 "Show libpri version information\n";
12547 return NULL;
12548 case CLI_GENERATE:
12549 return NULL;
12550 }
12551
12552 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12553
12554 return CLI_SUCCESS;
12555 }
12556
12557 static struct ast_cli_entry dahdi_pri_cli[] = {
12558 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
12559 AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
12560 AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
12561 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
12562 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
12563 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
12564 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
12565 AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
12566 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
12567 };
12568
12569 #endif
12570
12571 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12572 {
12573 int channel;
12574 int ret;
12575 switch (cmd) {
12576 case CLI_INIT:
12577 e->command = "dahdi destroy channel";
12578 e->usage =
12579 "Usage: dahdi destroy channel <chan num>\n"
12580 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12581 return NULL;
12582 case CLI_GENERATE:
12583 return NULL;
12584 }
12585 if (a->argc != 4)
12586 return CLI_SHOWUSAGE;
12587
12588 channel = atoi(a->argv[3]);
12589 ret = dahdi_destroy_channel_bynum(channel);
12590 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12591 }
12592
12593 static void dahdi_softhangup_all(void)
12594 {
12595 struct dahdi_pvt *p;
12596 retry:
12597 ast_mutex_lock(&iflock);
12598 for (p = iflist; p; p = p->next) {
12599 ast_mutex_lock(&p->lock);
12600 if (p->owner && !p->restartpending) {
12601 if (ast_channel_trylock(p->owner)) {
12602 if (option_debug > 2)
12603 ast_verbose("Avoiding deadlock\n");
12604
12605 ast_mutex_unlock(&p->lock);
12606 ast_mutex_unlock(&iflock);
12607 goto retry;
12608 }
12609 if (option_debug > 2)
12610 ast_verbose("Softhanging up on %s\n", p->owner->name);
12611 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12612 p->restartpending = 1;
12613 num_restart_pending++;
12614 ast_channel_unlock(p->owner);
12615 }
12616 ast_mutex_unlock(&p->lock);
12617 }
12618 ast_mutex_unlock(&iflock);
12619 }
12620
12621 static int setup_dahdi(int reload);
12622 static int dahdi_restart(void)
12623 {
12624 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12625 int i, j;
12626 #endif
12627 int cancel_code;
12628 struct dahdi_pvt *p;
12629
12630 ast_mutex_lock(&restart_lock);
12631
12632 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12633 dahdi_softhangup_all();
12634 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12635
12636 #if defined(HAVE_PRI)
12637 for (i = 0; i < NUM_SPANS; i++) {
12638 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12639 cancel_code = pthread_cancel(pris[i].master);
12640 pthread_kill(pris[i].master, SIGURG);
12641 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12642 pthread_join(pris[i].master, NULL);
12643 ast_debug(4, "Joined thread of span %d\n", i);
12644 }
12645 }
12646 #endif
12647
12648 #if defined(HAVE_SS7)
12649 for (i = 0; i < NUM_SPANS; i++) {
12650 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12651 cancel_code = pthread_cancel(linksets[i].master);
12652 pthread_kill(linksets[i].master, SIGURG);
12653 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12654 pthread_join(linksets[i].master, NULL);
12655 ast_debug(4, "Joined thread of span %d\n", i);
12656 }
12657 }
12658 #endif
12659
12660 ast_mutex_lock(&monlock);
12661 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12662 cancel_code = pthread_cancel(monitor_thread);
12663 pthread_kill(monitor_thread, SIGURG);
12664 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12665 pthread_join(monitor_thread, NULL);
12666 ast_debug(4, "Joined monitor thread\n");
12667 }
12668 monitor_thread = AST_PTHREADT_NULL;
12669
12670 ast_mutex_lock(&mwi_thread_lock);
12671 while (mwi_thread_count > 0) {
12672 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12673 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12674 }
12675 ast_mutex_unlock(&mwi_thread_lock);
12676 ast_mutex_lock(&ss_thread_lock);
12677 while (ss_thread_count > 0) {
12678 int x = DAHDI_FLASH;
12679 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12680
12681 for (p = iflist; p; p = p->next) {
12682 if (p->owner)
12683 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
12684 }
12685 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12686 }
12687
12688
12689 dahdi_softhangup_all();
12690 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12691 destroy_all_channels();
12692 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12693
12694 ast_mutex_unlock(&monlock);
12695
12696 #ifdef HAVE_PRI
12697 for (i = 0; i < NUM_SPANS; i++) {
12698 for (j = 0; j < NUM_DCHANS; j++)
12699 dahdi_close_pri_fd(&(pris[i]), j);
12700 }
12701
12702 memset(pris, 0, sizeof(pris));
12703 for (i = 0; i < NUM_SPANS; i++) {
12704 ast_mutex_init(&pris[i].lock);
12705 pris[i].offset = -1;
12706 pris[i].master = AST_PTHREADT_NULL;
12707 for (j = 0; j < NUM_DCHANS; j++)
12708 pris[i].fds[j] = -1;
12709 }
12710 pri_set_error(dahdi_pri_error);
12711 pri_set_message(dahdi_pri_message);
12712 #endif
12713 #ifdef HAVE_SS7
12714 for (i = 0; i < NUM_SPANS; i++) {
12715 for (j = 0; j < NUM_DCHANS; j++)
12716 dahdi_close_ss7_fd(&(linksets[i]), j);
12717 }
12718
12719 memset(linksets, 0, sizeof(linksets));
12720 for (i = 0; i < NUM_SPANS; i++) {
12721 ast_mutex_init(&linksets[i].lock);
12722 linksets[i].master = AST_PTHREADT_NULL;
12723 for (j = 0; j < NUM_DCHANS; j++)
12724 linksets[i].fds[j] = -1;
12725 }
12726 ss7_set_error(dahdi_ss7_error);
12727 ss7_set_message(dahdi_ss7_message);
12728 #endif
12729
12730 if (setup_dahdi(2) != 0) {
12731 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12732 ast_mutex_unlock(&ss_thread_lock);
12733 return 1;
12734 }
12735 ast_mutex_unlock(&ss_thread_lock);
12736 ast_mutex_unlock(&restart_lock);
12737 return 0;
12738 }
12739
12740 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12741 {
12742 switch (cmd) {
12743 case CLI_INIT:
12744 e->command = "dahdi restart";
12745 e->usage =
12746 "Usage: dahdi restart\n"
12747 " Restarts the DAHDI channels: destroys them all and then\n"
12748 " re-reads them from chan_dahdi.conf.\n"
12749 " Note that this will STOP any running CALL on DAHDI channels.\n"
12750 "";
12751 return NULL;
12752 case CLI_GENERATE:
12753 return NULL;
12754 }
12755 if (a->argc != 2)
12756 return CLI_SHOWUSAGE;
12757
12758 if (dahdi_restart() != 0)
12759 return CLI_FAILURE;
12760 return CLI_SUCCESS;
12761 }
12762
12763 static int action_dahdirestart(struct mansession *s, const struct message *m)
12764 {
12765 if (dahdi_restart() != 0) {
12766 astman_send_error(s, m, "Failed rereading DAHDI configuration");
12767 return 1;
12768 }
12769 astman_send_ack(s, m, "DAHDIRestart: Success");
12770 return 0;
12771 }
12772
12773 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12774 {
12775 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12776 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12777 unsigned int targetnum = 0;
12778 int filtertype = 0;
12779 struct dahdi_pvt *tmp = NULL;
12780 char tmps[20] = "";
12781 char statestr[20] = "";
12782 char blockstr[20] = "";
12783 ast_mutex_t *lock;
12784 struct dahdi_pvt *start;
12785 #ifdef HAVE_PRI
12786 int trunkgroup;
12787 struct dahdi_pri *pri = NULL;
12788 int x;
12789 #endif
12790 switch (cmd) {
12791 case CLI_INIT:
12792 e->command = "dahdi show channels [trunkgroup|group|context]";
12793 e->usage =
12794 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12795 " Shows a list of available channels with optional filtering\n"
12796 " <group> must be a number between 0 and 63\n";
12797 return NULL;
12798 case CLI_GENERATE:
12799 return NULL;
12800 }
12801
12802 lock = &iflock;
12803 start = iflist;
12804
12805
12806
12807 if (!((a->argc == 3) || (a->argc == 5)))
12808 return CLI_SHOWUSAGE;
12809
12810 if (a->argc == 5) {
12811 #ifdef HAVE_PRI
12812 if (!strcasecmp(a->argv[3], "trunkgroup")) {
12813
12814 if ((trunkgroup = atoi(a->argv[4])) < 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 if (!strcasecmp(a->argv[3], "group")) {
12832 targetnum = atoi(a->argv[4]);
12833 if ((targetnum < 0) || (targetnum > 63))
12834 return CLI_SHOWUSAGE;
12835 targetnum = 1 << targetnum;
12836 filtertype = 1;
12837 } else if (!strcasecmp(a->argv[3], "context")) {
12838 filtertype = 2;
12839 }
12840 }
12841
12842 ast_mutex_lock(lock);
12843 #ifdef HAVE_PRI
12844 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12845 #else
12846 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12847 #endif
12848
12849 tmp = start;
12850 while (tmp) {
12851 if (filtertype) {
12852 switch(filtertype) {
12853 case 1:
12854 if (!(tmp->group & targetnum)) {
12855 tmp = tmp->next;
12856 continue;
12857 }
12858 break;
12859 case 2:
12860 if (strcasecmp(tmp->context, a->argv[4])) {
12861 tmp = tmp->next;
12862 continue;
12863 }
12864 break;
12865 default:
12866 ;
12867 }
12868 }
12869 if (tmp->channel > 0) {
12870 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12871 } else
12872 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12873
12874 if (tmp->locallyblocked)
12875 blockstr[0] = 'L';
12876 else
12877 blockstr[0] = ' ';
12878
12879 if (tmp->remotelyblocked)
12880 blockstr[1] = 'R';
12881 else
12882 blockstr[1] = ' ';
12883
12884 blockstr[2] = '\0';
12885
12886 snprintf(statestr, sizeof(statestr), "%s", "In Service");
12887
12888 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12889 tmp = tmp->next;
12890 }
12891 ast_mutex_unlock(lock);
12892 return CLI_SUCCESS;
12893 #undef FORMAT
12894 #undef FORMAT2
12895 }
12896
12897 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12898 {
12899 int channel;
12900 struct dahdi_pvt *tmp = NULL;
12901 struct dahdi_confinfo ci;
12902 struct dahdi_params ps;
12903 int x;
12904 ast_mutex_t *lock;
12905 struct dahdi_pvt *start;
12906 #ifdef HAVE_PRI
12907 char *c;
12908 int trunkgroup;
12909 struct dahdi_pri *pri=NULL;
12910 #endif
12911 switch (cmd) {
12912 case CLI_INIT:
12913 e->command = "dahdi show channel";
12914 e->usage =
12915 "Usage: dahdi show channel <chan num>\n"
12916 " Detailed information about a given channel\n";
12917 return NULL;
12918 case CLI_GENERATE:
12919 return NULL;
12920 }
12921
12922 lock = &iflock;
12923 start = iflist;
12924
12925 if (a->argc != 4)
12926 return CLI_SHOWUSAGE;
12927 #ifdef HAVE_PRI
12928 if ((c = strchr(a->argv[3], ':'))) {
12929 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12930 return CLI_SHOWUSAGE;
12931 if ((trunkgroup < 1) || (channel < 1))
12932 return CLI_SHOWUSAGE;
12933 for (x = 0; x < NUM_SPANS; x++) {
12934 if (pris[x].trunkgroup == trunkgroup) {
12935 pri = pris + x;
12936 break;
12937 }
12938 }
12939 if (pri) {
12940 start = pri->crvs;
12941 lock = &pri->lock;
12942 } else {
12943 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12944 return CLI_FAILURE;
12945 }
12946 } else
12947 #endif
12948 channel = atoi(a->argv[3]);
12949
12950 ast_mutex_lock(lock);
12951 tmp = start;
12952 while (tmp) {
12953 if (tmp->channel == channel) {
12954 #ifdef HAVE_PRI
12955 if (pri)
12956 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12957 else
12958 #endif
12959 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12960 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12961 ast_cli(a->fd, "Span: %d\n", tmp->span);
12962 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12963 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12964 ast_cli(a->fd, "Context: %s\n", tmp->context);
12965 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12966 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12967 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12968 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12969 if (tmp->vars) {
12970 struct ast_variable *v;
12971 ast_cli(a->fd, "Variables:\n");
12972 for (v = tmp->vars ; v ; v = v->next)
12973 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
12974 }
12975 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12976 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12977 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12978 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12979 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12980 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)" : "");
12981 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)" : "");
12982 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)" : "");
12983 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12984 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12985 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12986 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12987 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12988 if (tmp->busydetect) {
12989 #if defined(BUSYDETECT_TONEONLY)
12990 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12991 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12992 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12993 #endif
12994 #ifdef BUSYDETECT_DEBUG
12995 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
12996 #endif
12997 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
12998 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
12999 }
13000 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
13001 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
13002 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
13003 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
13004 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
13005 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
13006 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
13007 ast_cli(a->fd, "Echo Cancellation:\n");
13008
13009 if (tmp->echocancel.head.tap_length) {
13010 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
13011 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
13012 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
13013 }
13014 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
13015 } else {
13016 ast_cli(a->fd, "\tnone\n");
13017 }
13018 if (tmp->master)
13019 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
13020 for (x = 0; x < MAX_SLAVES; x++) {
13021 if (tmp->slaves[x])
13022 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
13023 }
13024 #ifdef HAVE_SS7
13025 if (tmp->ss7) {
13026 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
13027 }
13028 #endif
13029 #ifdef HAVE_PRI
13030 if (tmp->pri) {
13031 ast_cli(a->fd, "PRI Flags: ");
13032 if (tmp->resetting)
13033 ast_cli(a->fd, "Resetting ");
13034 if (tmp->call)
13035 ast_cli(a->fd, "Call ");
13036 if (tmp->bearer)
13037 ast_cli(a->fd, "Bearer ");
13038 ast_cli(a->fd, "\n");
13039 if (tmp->logicalspan)
13040 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
13041 else
13042 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
13043 }
13044
13045 #endif
13046 memset(&ci, 0, sizeof(ci));
13047 ps.channo = tmp->channel;
13048 if (tmp->subs[SUB_REAL].dfd > -1) {
13049 memset(&ci, 0, sizeof(ci));
13050 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
13051 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
13052 }
13053 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
13054 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
13055 }
13056 memset(&ps, 0, sizeof(ps));
13057 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
13058 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
13059 } else {
13060 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
13061 }
13062 }
13063 if (ISTRUNK(tmp)) {
13064 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
13065 if (!ast_strlen_zero(progzone))
13066 ast_cli(a->fd, "Progress Zone: %s\n", progzone);
13067 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
13068 if(tmp->busydetect) {
13069 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
13070 if(tmp->busytonelength > 0) {
13071 ast_cli(a->fd, "Busy Pattern:\n");
13072 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
13073 if (tmp->busyquietlength > 0)
13074 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
13075 else
13076 ast_cli(a->fd, " -- Detect Tone Only\n");
13077 if(tmp->busyfuzziness > 0)
13078 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
13079 }
13080 }
13081 }
13082 ast_mutex_unlock(lock);
13083 return CLI_SUCCESS;
13084 }
13085 tmp = tmp->next;
13086 }
13087
13088 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13089 ast_mutex_unlock(lock);
13090 return CLI_FAILURE;
13091 }
13092
13093 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13094 {
13095 int i, j;
13096 switch (cmd) {
13097 case CLI_INIT:
13098 e->command = "dahdi show cadences";
13099 e->usage =
13100 "Usage: dahdi show cadences\n"
13101 " Shows all cadences currently defined\n";
13102 return NULL;
13103 case CLI_GENERATE:
13104 return NULL;
13105 }
13106 for (i = 0; i < num_cadence; i++) {
13107 char output[1024];
13108 char tmp[16], tmp2[64];
13109 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
13110 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
13111
13112 for (j = 0; j < 16; j++) {
13113 if (cadences[i].ringcadence[j] == 0)
13114 break;
13115 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
13116 if (cidrings[i] * 2 - 1 == j)
13117 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
13118 else
13119 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
13120 if (j != 0)
13121 strncat(output, ",", sizeof(output) - strlen(output) - 1);
13122 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
13123 }
13124 ast_cli(a->fd,"%s\n",output);
13125 }
13126 return CLI_SUCCESS;
13127 }
13128
13129
13130 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13131 {
13132 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
13133 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
13134 int span;
13135 int res;
13136 char alarmstr[50];
13137
13138 int ctl;
13139 struct dahdi_spaninfo s;
13140
13141 switch (cmd) {
13142 case CLI_INIT:
13143 e->command = "dahdi show status";
13144 e->usage =
13145 "Usage: dahdi show status\n"
13146 " Shows a list of DAHDI cards with status\n";
13147 return NULL;
13148 case CLI_GENERATE:
13149 return NULL;
13150 }
13151 ctl = open("/dev/dahdi/ctl", O_RDWR);
13152 if (ctl < 0) {
13153 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13154 return CLI_FAILURE;
13155 }
13156 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13157
13158 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13159 s.spanno = span;
13160 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13161 if (res) {
13162 continue;
13163 }
13164 alarmstr[0] = '\0';
13165 if (s.alarms > 0) {
13166 if (s.alarms & DAHDI_ALARM_BLUE)
13167 strcat(alarmstr, "BLU/");
13168 if (s.alarms & DAHDI_ALARM_YELLOW)
13169 strcat(alarmstr, "YEL/");
13170 if (s.alarms & DAHDI_ALARM_RED)
13171 strcat(alarmstr, "RED/");
13172 if (s.alarms & DAHDI_ALARM_LOOPBACK)
13173 strcat(alarmstr, "LB/");
13174 if (s.alarms & DAHDI_ALARM_RECOVER)
13175 strcat(alarmstr, "REC/");
13176 if (s.alarms & DAHDI_ALARM_NOTOPEN)
13177 strcat(alarmstr, "NOP/");
13178 if (!strlen(alarmstr))
13179 strcat(alarmstr, "UUU/");
13180 if (strlen(alarmstr)) {
13181
13182 alarmstr[strlen(alarmstr) - 1] = '\0';
13183 }
13184 } else {
13185 if (s.numchans)
13186 strcpy(alarmstr, "OK");
13187 else
13188 strcpy(alarmstr, "UNCONFIGURED");
13189 }
13190
13191 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13192 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13193 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13194 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13195 "CAS"
13196 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13197 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13198 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13199 "Unk"
13200 , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13201 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13202 , lbostr[s.lbo]
13203 );
13204 }
13205 close(ctl);
13206
13207 return CLI_SUCCESS;
13208 #undef FORMAT
13209 #undef FORMAT2
13210 }
13211
13212 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13213 {
13214 int pseudo_fd = -1;
13215 struct dahdi_versioninfo vi;
13216
13217 switch (cmd) {
13218 case CLI_INIT:
13219 e->command = "dahdi show version";
13220 e->usage =
13221 "Usage: dahdi show version\n"
13222 " Shows the DAHDI version in use\n";
13223 return NULL;
13224 case CLI_GENERATE:
13225 return NULL;
13226 }
13227 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13228 ast_cli(a->fd, "Failed to open control file to get version.\n");
13229 return CLI_SUCCESS;
13230 }
13231
13232 strcpy(vi.version, "Unknown");
13233 strcpy(vi.echo_canceller, "Unknown");
13234
13235 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13236 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13237 else
13238 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13239
13240 close(pseudo_fd);
13241
13242 return CLI_SUCCESS;
13243 }
13244
13245 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13246 {
13247 int channel;
13248 int gain;
13249 int tx;
13250 struct dahdi_hwgain hwgain;
13251 struct dahdi_pvt *tmp = NULL;
13252
13253 switch (cmd) {
13254 case CLI_INIT:
13255 e->command = "dahdi set hwgain";
13256 e->usage =
13257 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
13258 " Sets the hardware gain on a a given channel, overriding the\n"
13259 " value provided at module loadtime, whether the channel is in\n"
13260 " use or not. Changes take effect immediately.\n"
13261 " <rx|tx> which direction do you want to change (relative to our module)\n"
13262 " <chan num> is the channel number relative to the device\n"
13263 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13264 return NULL;
13265 case CLI_GENERATE:
13266 return NULL;
13267 }
13268
13269 if (a->argc != 6)
13270 return CLI_SHOWUSAGE;
13271
13272 if (!strcasecmp("rx", a->argv[3]))
13273 tx = 0;
13274 else if (!strcasecmp("tx", a->argv[3]))
13275 tx = 1;
13276 else
13277 return CLI_SHOWUSAGE;
13278
13279 channel = atoi(a->argv[4]);
13280 gain = atof(a->argv[5])*10.0;
13281
13282 ast_mutex_lock(&iflock);
13283
13284 for (tmp = iflist; tmp; tmp = tmp->next) {
13285
13286 if (tmp->channel != channel)
13287 continue;
13288
13289 if (tmp->subs[SUB_REAL].dfd == -1)
13290 break;
13291
13292 hwgain.newgain = gain;
13293 hwgain.tx = tx;
13294 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
13295 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
13296 ast_mutex_unlock(&iflock);
13297 return CLI_FAILURE;
13298 }
13299 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
13300 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
13301 break;
13302 }
13303
13304 ast_mutex_unlock(&iflock);
13305
13306 if (tmp)
13307 return CLI_SUCCESS;
13308
13309 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13310 return CLI_FAILURE;
13311
13312 }
13313
13314 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13315 {
13316 int channel;
13317 float gain;
13318 int tx;
13319 int res;
13320 ast_mutex_t *lock;
13321 struct dahdi_pvt *tmp = NULL;
13322
13323 switch (cmd) {
13324 case CLI_INIT:
13325 e->command = "dahdi set swgain";
13326 e->usage =
13327 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13328 " Sets the software gain on a a given channel, overriding the\n"
13329 " value provided at module loadtime, whether the channel is in\n"
13330 " use or not. Changes take effect immediately.\n"
13331 " <rx|tx> which direction do you want to change (relative to our module)\n"
13332 " <chan num> is the channel number relative to the device\n"
13333 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13334 return NULL;
13335 case CLI_GENERATE:
13336 return NULL;
13337 }
13338
13339 lock = &iflock;
13340
13341 if (a->argc != 6)
13342 return CLI_SHOWUSAGE;
13343
13344 if (!strcasecmp("rx", a->argv[3]))
13345 tx = 0;
13346 else if (!strcasecmp("tx", a->argv[3]))
13347 tx = 1;
13348 else
13349 return CLI_SHOWUSAGE;
13350
13351 channel = atoi(a->argv[4]);
13352 gain = atof(a->argv[5]);
13353
13354 ast_mutex_lock(lock);
13355 for (tmp = iflist; tmp; tmp = tmp->next) {
13356
13357 if (tmp->channel != channel)
13358 continue;
13359
13360 if (tmp->subs[SUB_REAL].dfd == -1)
13361 break;
13362
13363 if (tx)
13364 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13365 else
13366 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13367
13368 if (res) {
13369 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13370 ast_mutex_unlock(lock);
13371 return CLI_FAILURE;
13372 }
13373
13374 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13375 tx ? "tx" : "rx", gain, channel);
13376 break;
13377 }
13378 ast_mutex_unlock(lock);
13379
13380 if (tmp)
13381 return CLI_SUCCESS;
13382
13383 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13384 return CLI_FAILURE;
13385
13386 }
13387
13388 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13389 {
13390 int channel;
13391 int on;
13392 struct dahdi_pvt *dahdi_chan = NULL;
13393
13394 switch (cmd) {
13395 case CLI_INIT:
13396 e->command = "dahdi set dnd";
13397 e->usage =
13398 "Usage: dahdi set dnd <chan#> <on|off>\n"
13399 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13400 " Changes take effect immediately.\n"
13401 " <chan num> is the channel number\n"
13402 " <on|off> Enable or disable DND mode?\n"
13403 ;
13404 return NULL;
13405 case CLI_GENERATE:
13406 return NULL;
13407 }
13408
13409 if (a->argc != 5)
13410 return CLI_SHOWUSAGE;
13411
13412 if ((channel = atoi(a->argv[3])) <= 0) {
13413 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13414 return CLI_SHOWUSAGE;
13415 }
13416
13417 if (ast_true(a->argv[4]))
13418 on = 1;
13419 else if (ast_false(a->argv[4]))
13420 on = 0;
13421 else {
13422 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13423 return CLI_SHOWUSAGE;
13424 }
13425
13426 ast_mutex_lock(&iflock);
13427 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13428 if (dahdi_chan->channel != channel)
13429 continue;
13430
13431
13432 dahdi_dnd(dahdi_chan, on);
13433 break;
13434 }
13435 ast_mutex_unlock(&iflock);
13436
13437 if (!dahdi_chan) {
13438 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13439 return CLI_FAILURE;
13440 }
13441
13442 return CLI_SUCCESS;
13443 }
13444
13445 static struct ast_cli_entry dahdi_cli[] = {
13446 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
13447 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
13448 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
13449 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
13450 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
13451 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
13452 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
13453 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
13454 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
13455 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
13456 };
13457
13458 #define TRANSFER 0
13459 #define HANGUP 1
13460
13461 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13462 {
13463 if (p) {
13464 switch (mode) {
13465 case TRANSFER:
13466 p->fake_event = DAHDI_EVENT_WINKFLASH;
13467 break;
13468 case HANGUP:
13469 p->fake_event = DAHDI_EVENT_ONHOOK;
13470 break;
13471 default:
13472 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
13473 }
13474 }
13475 return 0;
13476 }
13477 static struct dahdi_pvt *find_channel(int channel)
13478 {
13479 struct dahdi_pvt *p = iflist;
13480 while (p) {
13481 if (p->channel == channel) {
13482 break;
13483 }
13484 p = p->next;
13485 }
13486 return p;
13487 }
13488
13489 static int action_dahdidndon(struct mansession *s, const struct message *m)
13490 {
13491 struct dahdi_pvt *p = NULL;
13492 const char *channel = astman_get_header(m, "DAHDIChannel");
13493
13494 if (ast_strlen_zero(channel)) {
13495 astman_send_error(s, m, "No channel specified");
13496 return 0;
13497 }
13498 p = find_channel(atoi(channel));
13499 if (!p) {
13500 astman_send_error(s, m, "No such channel");
13501 return 0;
13502 }
13503 p->dnd = 1;
13504 astman_send_ack(s, m, "DND Enabled");
13505 return 0;
13506 }
13507
13508 static int action_dahdidndoff(struct mansession *s, const struct message *m)
13509 {
13510 struct dahdi_pvt *p = NULL;
13511 const char *channel = astman_get_header(m, "DAHDIChannel");
13512
13513 if (ast_strlen_zero(channel)) {
13514 astman_send_error(s, m, "No channel specified");
13515 return 0;
13516 }
13517 p = find_channel(atoi(channel));
13518 if (!p) {
13519 astman_send_error(s, m, "No such channel");
13520 return 0;
13521 }
13522 p->dnd = 0;
13523 astman_send_ack(s, m, "DND Disabled");
13524 return 0;
13525 }
13526
13527 static int action_transfer(struct mansession *s, const struct message *m)
13528 {
13529 struct dahdi_pvt *p = NULL;
13530 const char *channel = astman_get_header(m, "DAHDIChannel");
13531
13532 if (ast_strlen_zero(channel)) {
13533 astman_send_error(s, m, "No channel specified");
13534 return 0;
13535 }
13536 p = find_channel(atoi(channel));
13537 if (!p) {
13538 astman_send_error(s, m, "No such channel");
13539 return 0;
13540 }
13541 dahdi_fake_event(p,TRANSFER);
13542 astman_send_ack(s, m, "DAHDITransfer");
13543 return 0;
13544 }
13545
13546 static int action_transferhangup(struct mansession *s, const struct message *m)
13547 {
13548 struct dahdi_pvt *p = NULL;
13549 const char *channel = astman_get_header(m, "DAHDIChannel");
13550
13551 if (ast_strlen_zero(channel)) {
13552 astman_send_error(s, m, "No channel specified");
13553 return 0;
13554 }
13555 p = find_channel(atoi(channel));
13556 if (!p) {
13557 astman_send_error(s, m, "No such channel");
13558 return 0;
13559 }
13560 dahdi_fake_event(p,HANGUP);
13561 astman_send_ack(s, m, "DAHDIHangup");
13562 return 0;
13563 }
13564
13565 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
13566 {
13567 struct dahdi_pvt *p = NULL;
13568 const char *channel = astman_get_header(m, "DAHDIChannel");
13569 const char *number = astman_get_header(m, "Number");
13570 int i;
13571
13572 if (ast_strlen_zero(channel)) {
13573 astman_send_error(s, m, "No channel specified");
13574 return 0;
13575 }
13576 if (ast_strlen_zero(number)) {
13577 astman_send_error(s, m, "No number specified");
13578 return 0;
13579 }
13580 p = find_channel(atoi(channel));
13581 if (!p) {
13582 astman_send_error(s, m, "No such channel");
13583 return 0;
13584 }
13585 if (!p->owner) {
13586 astman_send_error(s, m, "Channel does not have it's owner");
13587 return 0;
13588 }
13589 for (i = 0; i < strlen(number); i++) {
13590 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13591 dahdi_queue_frame(p, &f, NULL);
13592 }
13593 astman_send_ack(s, m, "DAHDIDialOffhook");
13594 return 0;
13595 }
13596
13597 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
13598 {
13599 struct dahdi_pvt *tmp = NULL;
13600 const char *id = astman_get_header(m, "ActionID");
13601 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13602 char idText[256] = "";
13603 int channels = 0;
13604 int dahdichanquery = -1;
13605 if (!ast_strlen_zero(dahdichannel)) {
13606 dahdichanquery = atoi(dahdichannel);
13607 }
13608
13609 astman_send_ack(s, m, "DAHDI channel status will follow");
13610 if (!ast_strlen_zero(id))
13611 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13612
13613 ast_mutex_lock(&iflock);
13614
13615 tmp = iflist;
13616 while (tmp) {
13617 if (tmp->channel > 0) {
13618 int alm = get_alarms(tmp);
13619
13620
13621 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13622 continue;
13623
13624 channels++;
13625 if (tmp->owner) {
13626
13627 astman_append(s,
13628 "Event: DAHDIShowChannels\r\n"
13629 "DAHDIChannel: %d\r\n"
13630 "Channel: %s\r\n"
13631 "Uniqueid: %s\r\n"
13632 "AccountCode: %s\r\n"
13633 "Signalling: %s\r\n"
13634 "SignallingCode: %d\r\n"
13635 "Context: %s\r\n"
13636 "DND: %s\r\n"
13637 "Alarm: %s\r\n"
13638 "%s"
13639 "\r\n",
13640 tmp->channel,
13641 tmp->owner->name,
13642 tmp->owner->uniqueid,
13643 tmp->owner->accountcode,
13644 sig2str(tmp->sig),
13645 tmp->sig,
13646 tmp->context,
13647 tmp->dnd ? "Enabled" : "Disabled",
13648 alarm2str(alm), idText);
13649 } else {
13650 astman_append(s,
13651 "Event: DAHDIShowChannels\r\n"
13652 "DAHDIChannel: %d\r\n"
13653 "Signalling: %s\r\n"
13654 "SignallingCode: %d\r\n"
13655 "Context: %s\r\n"
13656 "DND: %s\r\n"
13657 "Alarm: %s\r\n"
13658 "%s"
13659 "\r\n",
13660 tmp->channel, sig2str(tmp->sig), tmp->sig,
13661 tmp->context,
13662 tmp->dnd ? "Enabled" : "Disabled",
13663 alarm2str(alm), idText);
13664 }
13665 }
13666
13667 tmp = tmp->next;
13668 }
13669
13670 ast_mutex_unlock(&iflock);
13671
13672 astman_append(s,
13673 "Event: DAHDIShowChannelsComplete\r\n"
13674 "%s"
13675 "Items: %d\r\n"
13676 "\r\n",
13677 idText,
13678 channels);
13679 return 0;
13680 }
13681
13682 #ifdef HAVE_SS7
13683 static int linkset_addsigchan(int sigchan)
13684 {
13685 struct dahdi_ss7 *link;
13686 int res;
13687 int curfd;
13688 struct dahdi_params p;
13689 struct dahdi_bufferinfo bi;
13690 struct dahdi_spaninfo si;
13691
13692
13693 link = ss7_resolve_linkset(cur_linkset);
13694 if (!link) {
13695 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
13696 return -1;
13697 }
13698
13699 if (cur_ss7type < 0) {
13700 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13701 return -1;
13702 }
13703
13704 if (!link->ss7)
13705 link->ss7 = ss7_new(cur_ss7type);
13706
13707 if (!link->ss7) {
13708 ast_log(LOG_ERROR, "Can't create new SS7!\n");
13709 return -1;
13710 }
13711
13712 link->type = cur_ss7type;
13713
13714 if (cur_pointcode < 0) {
13715 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13716 return -1;
13717 } else
13718 ss7_set_pc(link->ss7, cur_pointcode);
13719
13720 if (sigchan < 0) {
13721 ast_log(LOG_ERROR, "Invalid sigchan!\n");
13722 return -1;
13723 } else {
13724 if (link->numsigchans >= NUM_DCHANS) {
13725 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13726 return -1;
13727 }
13728 curfd = link->numsigchans;
13729
13730 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13731 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13732 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13733 return -1;
13734 }
13735 memset(&p, 0, sizeof(p));
13736 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13737 if (res) {
13738 dahdi_close_ss7_fd(link, curfd);
13739 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13740 return -1;
13741 }
13742 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13743 dahdi_close_ss7_fd(link, curfd);
13744 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13745 return -1;
13746 }
13747
13748 memset(&bi, 0, sizeof(bi));
13749 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13750 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13751 bi.numbufs = 32;
13752 bi.bufsize = 512;
13753
13754 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13755 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13756 dahdi_close_ss7_fd(link, curfd);
13757 return -1;
13758 }
13759
13760 if (p.sigtype == DAHDI_SIG_MTP2)
13761 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13762 else
13763 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13764
13765 link->numsigchans++;
13766
13767 memset(&si, 0, sizeof(si));
13768 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13769 if (res) {
13770 dahdi_close_ss7_fd(link, curfd);
13771 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13772 }
13773
13774 if (!si.alarms) {
13775 link->linkstate[curfd] = LINKSTATE_DOWN;
13776 ss7_link_noalarm(link->ss7, link->fds[curfd]);
13777 } else {
13778 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13779 ss7_link_alarm(link->ss7, link->fds[curfd]);
13780 }
13781 }
13782
13783 if (cur_adjpointcode < 0) {
13784 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13785 return -1;
13786 } else {
13787 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13788 }
13789
13790 if (cur_defaultdpc < 0) {
13791 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13792 return -1;
13793 }
13794
13795 if (cur_networkindicator < 0) {
13796 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13797 return -1;
13798 } else
13799 ss7_set_network_ind(link->ss7, cur_networkindicator);
13800
13801 return 0;
13802 }
13803
13804 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13805 {
13806 int span;
13807 switch (cmd) {
13808 case CLI_INIT:
13809 e->command = "ss7 no debug linkset";
13810 e->usage =
13811 "Usage: ss7 no debug linkset <span>\n"
13812 " Disables debugging on a given SS7 linkset\n";
13813 return NULL;
13814 case CLI_GENERATE:
13815 return NULL;
13816 }
13817 if (a->argc < 5)
13818 return CLI_SHOWUSAGE;
13819 span = atoi(a->argv[4]);
13820 if ((span < 1) || (span > NUM_SPANS)) {
13821 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13822 return CLI_SUCCESS;
13823 }
13824 if (!linksets[span-1].ss7) {
13825 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13826 return CLI_SUCCESS;
13827 }
13828 if (linksets[span-1].ss7)
13829 ss7_set_debug(linksets[span-1].ss7, 0);
13830
13831 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13832 return CLI_SUCCESS;
13833 }
13834
13835 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13836 {
13837 int span;
13838 switch (cmd) {
13839 case CLI_INIT:
13840 e->command = "ss7 debug linkset";
13841 e->usage =
13842 "Usage: ss7 debug linkset <linkset>\n"
13843 " Enables debugging on a given SS7 linkset\n";
13844 return NULL;
13845 case CLI_GENERATE:
13846 return NULL;
13847 }
13848 if (a->argc < 4)
13849 return CLI_SHOWUSAGE;
13850 span = atoi(a->argv[3]);
13851 if ((span < 1) || (span > NUM_SPANS)) {
13852 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13853 return CLI_SUCCESS;
13854 }
13855 if (!linksets[span-1].ss7) {
13856 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13857 return CLI_SUCCESS;
13858 }
13859 if (linksets[span-1].ss7)
13860 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13861
13862 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13863 return CLI_SUCCESS;
13864 }
13865
13866 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13867 {
13868 int linkset, cic;
13869 int blocked = -1, i;
13870 switch (cmd) {
13871 case CLI_INIT:
13872 e->command = "ss7 block cic";
13873 e->usage =
13874 "Usage: ss7 block cic <linkset> <CIC>\n"
13875 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13876 return NULL;
13877 case CLI_GENERATE:
13878 return NULL;
13879 }
13880 if (a->argc == 5)
13881 linkset = atoi(a->argv[3]);
13882 else
13883 return CLI_SHOWUSAGE;
13884
13885 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13886 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13887 return CLI_SUCCESS;
13888 }
13889
13890 if (!linksets[linkset-1].ss7) {
13891 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13892 return CLI_SUCCESS;
13893 }
13894
13895 cic = atoi(a->argv[4]);
13896
13897 if (cic < 1) {
13898 ast_cli(a->fd, "Invalid CIC specified!\n");
13899 return CLI_SUCCESS;
13900 }
13901
13902 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13903 if (linksets[linkset-1].pvts[i]->cic == cic) {
13904 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13905 if (!blocked) {
13906 ast_mutex_lock(&linksets[linkset-1].lock);
13907 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13908 ast_mutex_unlock(&linksets[linkset-1].lock);
13909 }
13910 }
13911 }
13912
13913 if (blocked < 0) {
13914 ast_cli(a->fd, "Invalid CIC specified!\n");
13915 return CLI_SUCCESS;
13916 }
13917
13918 if (!blocked)
13919 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13920 else
13921 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13922
13923
13924 pthread_kill(linksets[linkset-1].master, SIGURG);
13925
13926 return CLI_SUCCESS;
13927 }
13928
13929 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13930 {
13931 int linkset;
13932 int i;
13933 switch (cmd) {
13934 case CLI_INIT:
13935 e->command = "ss7 block linkset";
13936 e->usage =
13937 "Usage: ss7 block linkset <linkset number>\n"
13938 " Sends a remote blocking request for all CICs on the given linkset\n";
13939 return NULL;
13940 case CLI_GENERATE:
13941 return NULL;
13942 }
13943 if (a->argc == 4)
13944 linkset = atoi(a->argv[3]);
13945 else
13946 return CLI_SHOWUSAGE;
13947
13948 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13949 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13950 return CLI_SUCCESS;
13951 }
13952
13953 if (!linksets[linkset-1].ss7) {
13954 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13955 return CLI_SUCCESS;
13956 }
13957
13958 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13959 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13960 ast_mutex_lock(&linksets[linkset-1].lock);
13961 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13962 ast_mutex_unlock(&linksets[linkset-1].lock);
13963 }
13964
13965
13966 pthread_kill(linksets[linkset-1].master, SIGURG);
13967
13968 return CLI_SUCCESS;
13969 }
13970
13971 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13972 {
13973 int linkset, cic;
13974 int i, blocked = -1;
13975 switch (cmd) {
13976 case CLI_INIT:
13977 e->command = "ss7 unblock cic";
13978 e->usage =
13979 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13980 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13981 return NULL;
13982 case CLI_GENERATE:
13983 return NULL;
13984 }
13985
13986 if (a->argc == 5)
13987 linkset = atoi(a->argv[3]);
13988 else
13989 return CLI_SHOWUSAGE;
13990
13991 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13992 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13993 return CLI_SUCCESS;
13994 }
13995
13996 if (!linksets[linkset-1].ss7) {
13997 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13998 return CLI_SUCCESS;
13999 }
14000
14001 cic = atoi(a->argv[4]);
14002
14003 if (cic < 1) {
14004 ast_cli(a->fd, "Invalid CIC specified!\n");
14005 return CLI_SUCCESS;
14006 }
14007
14008 for (i = 0; i < linksets[linkset-1].numchans; i++) {
14009 if (linksets[linkset-1].pvts[i]->cic == cic) {
14010 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
14011 if (blocked) {
14012 ast_mutex_lock(&linksets[linkset-1].lock);
14013 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
14014 ast_mutex_unlock(&linksets[linkset-1].lock);
14015 }
14016 }
14017 }
14018
14019 if (blocked > 0)
14020 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
14021
14022
14023 pthread_kill(linksets[linkset-1].master, SIGURG);
14024
14025 return CLI_SUCCESS;
14026 }
14027
14028 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14029 {
14030 int linkset;
14031 int i;
14032 switch (cmd) {
14033 case CLI_INIT:
14034 e->command = "ss7 unblock linkset";
14035 e->usage =
14036 "Usage: ss7 unblock linkset <linkset number>\n"
14037 " Sends a remote unblocking request for all CICs on the specified linkset\n";
14038 return NULL;
14039 case CLI_GENERATE:
14040 return NULL;
14041 }
14042
14043 if (a->argc == 4)
14044 linkset = atoi(a->argv[3]);
14045 else
14046 return CLI_SHOWUSAGE;
14047
14048 if ((linkset < 1) || (linkset > NUM_SPANS)) {
14049 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
14050 return CLI_SUCCESS;
14051 }
14052
14053 if (!linksets[linkset-1].ss7) {
14054 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
14055 return CLI_SUCCESS;
14056 }
14057
14058 for (i = 0; i < linksets[linkset-1].numchans; i++) {
14059 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
14060 ast_mutex_lock(&linksets[linkset-1].lock);
14061 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
14062 ast_mutex_unlock(&linksets[linkset-1].lock);
14063 }
14064
14065
14066 pthread_kill(linksets[linkset-1].master, SIGURG);
14067
14068 return CLI_SUCCESS;
14069 }
14070
14071 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14072 {
14073 int linkset;
14074 struct dahdi_ss7 *ss7;
14075 switch (cmd) {
14076 case CLI_INIT:
14077 e->command = "ss7 show linkset";
14078 e->usage =
14079 "Usage: ss7 show linkset <span>\n"
14080 " Shows the status of an SS7 linkset.\n";
14081 return NULL;
14082 case CLI_GENERATE:
14083 return NULL;
14084 }
14085
14086 if (a->argc < 4)
14087 return CLI_SHOWUSAGE;
14088 linkset = atoi(a->argv[3]);
14089 if ((linkset < 1) || (linkset > NUM_SPANS)) {
14090 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
14091 return CLI_SUCCESS;
14092 }
14093 if (!linksets[linkset-1].ss7) {
14094 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
14095 return CLI_SUCCESS;
14096 }
14097 if (linksets[linkset-1].ss7)
14098 ss7 = &linksets[linkset-1];
14099
14100 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
14101
14102 return CLI_SUCCESS;
14103 }
14104
14105 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14106 {
14107 switch (cmd) {
14108 case CLI_INIT:
14109 e->command = "ss7 show version";
14110 e->usage =
14111 "Usage: ss7 show version\n"
14112 " Show the libss7 version\n";
14113 return NULL;
14114 case CLI_GENERATE:
14115 return NULL;
14116 }
14117
14118 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
14119
14120 return CLI_SUCCESS;
14121 }
14122
14123 static struct ast_cli_entry dahdi_ss7_cli[] = {
14124 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
14125 AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"),
14126 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
14127 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
14128 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
14129 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
14130 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
14131 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
14132 };
14133 #endif
14134
14135 static int __unload_module(void)
14136 {
14137 struct dahdi_pvt *p;
14138 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14139 int i, j;
14140 #endif
14141
14142 #ifdef HAVE_PRI
14143 for (i = 0; i < NUM_SPANS; i++) {
14144 if (pris[i].master != AST_PTHREADT_NULL)
14145 pthread_cancel(pris[i].master);
14146 }
14147 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14148 ast_unregister_application(dahdi_send_keypad_facility_app);
14149 #endif
14150 #if defined(HAVE_SS7)
14151 for (i = 0; i < NUM_SPANS; i++) {
14152 if (linksets[i].master != AST_PTHREADT_NULL)
14153 pthread_cancel(linksets[i].master);
14154 }
14155 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14156 #endif
14157
14158 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14159 ast_manager_unregister( "DAHDIDialOffhook" );
14160 ast_manager_unregister( "DAHDIHangup" );
14161 ast_manager_unregister( "DAHDITransfer" );
14162 ast_manager_unregister( "DAHDIDNDoff" );
14163 ast_manager_unregister( "DAHDIDNDon" );
14164 ast_manager_unregister("DAHDIShowChannels");
14165 ast_manager_unregister("DAHDIRestart");
14166 ast_channel_unregister(&dahdi_tech);
14167 ast_mutex_lock(&iflock);
14168
14169 p = iflist;
14170 while (p) {
14171 if (p->owner)
14172 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14173 p = p->next;
14174 }
14175 ast_mutex_unlock(&iflock);
14176 ast_mutex_lock(&monlock);
14177 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14178 pthread_cancel(monitor_thread);
14179 pthread_kill(monitor_thread, SIGURG);
14180 pthread_join(monitor_thread, NULL);
14181 }
14182 monitor_thread = AST_PTHREADT_STOP;
14183 ast_mutex_unlock(&monlock);
14184
14185 destroy_all_channels();
14186
14187 #if defined(HAVE_PRI)
14188 for (i = 0; i < NUM_SPANS; i++) {
14189 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14190 pthread_join(pris[i].master, NULL);
14191 for (j = 0; j < NUM_DCHANS; j++) {
14192 dahdi_close_pri_fd(&(pris[i]), j);
14193 }
14194 }
14195 #endif
14196
14197 #if defined(HAVE_SS7)
14198 for (i = 0; i < NUM_SPANS; i++) {
14199 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14200 pthread_join(linksets[i].master, NULL);
14201 for (j = 0; j < NUM_DCHANS; j++) {
14202 dahdi_close_ss7_fd(&(linksets[i]), j);
14203 }
14204 }
14205 #endif
14206
14207 ast_cond_destroy(&mwi_thread_complete);
14208 ast_cond_destroy(&ss_thread_complete);
14209 return 0;
14210 }
14211
14212 static int unload_module(void)
14213 {
14214 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14215 int y;
14216 #endif
14217 #ifdef HAVE_PRI
14218 for (y = 0; y < NUM_SPANS; y++)
14219 ast_mutex_destroy(&pris[y].lock);
14220 #endif
14221 #ifdef HAVE_SS7
14222 for (y = 0; y < NUM_SPANS; y++)
14223 ast_mutex_destroy(&linksets[y].lock);
14224 #endif
14225 return __unload_module();
14226 }
14227
14228 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
14229 {
14230 char *c, *chan;
14231 int x, start, finish;
14232 struct dahdi_pvt *tmp;
14233 #ifdef HAVE_PRI
14234 struct dahdi_pri *pri;
14235 int trunkgroup, y;
14236 #endif
14237
14238 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14239 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14240 return -1;
14241 }
14242
14243 c = ast_strdupa(value);
14244
14245 #ifdef HAVE_PRI
14246 pri = NULL;
14247 if (iscrv) {
14248 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14249 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14250 return -1;
14251 }
14252 if (trunkgroup < 1) {
14253 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14254 return -1;
14255 }
14256 c += y;
14257 for (y = 0; y < NUM_SPANS; y++) {
14258 if (pris[y].trunkgroup == trunkgroup) {
14259 pri = pris + y;
14260 break;
14261 }
14262 }
14263 if (!pri) {
14264 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14265 return -1;
14266 }
14267 }
14268 #endif
14269
14270 while ((chan = strsep(&c, ","))) {
14271 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14272
14273 } else if (sscanf(chan, "%30d", &start)) {
14274
14275 finish = start;
14276 } else if (!strcasecmp(chan, "pseudo")) {
14277 finish = start = CHAN_PSEUDO;
14278 if (found_pseudo)
14279 *found_pseudo = 1;
14280 } else {
14281 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14282 return -1;
14283 }
14284 if (finish < start) {
14285 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14286 x = finish;
14287 finish = start;
14288 start = x;
14289 }
14290
14291 for (x = start; x <= finish; x++) {
14292 #ifdef HAVE_PRI
14293 tmp = mkintf(x, conf, pri, reload);
14294 #else
14295 tmp = mkintf(x, conf, NULL, reload);
14296 #endif
14297
14298 if (tmp) {
14299 #ifdef HAVE_PRI
14300 if (pri)
14301 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14302 else
14303 #endif
14304 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14305 } else {
14306 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14307 (reload == 1) ? "reconfigure" : "register", value);
14308 return -1;
14309 }
14310 }
14311 }
14312
14313 return 0;
14314 }
14315
14316
14317
14318 #define MAX_CHANLIST_LEN 80
14319
14320 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
14321 {
14322 char *parse = ast_strdupa(data);
14323 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14324 unsigned int param_count;
14325 unsigned int x;
14326
14327 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14328 return;
14329
14330 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14331
14332
14333
14334 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14335
14336 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14337 confp->chan.echocancel.head.tap_length = x;
14338 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14339 confp->chan.echocancel.head.tap_length = 128;
14340
14341
14342
14343 for (x = 1; x < param_count; x++) {
14344 struct {
14345 char *name;
14346 char *value;
14347 } param;
14348
14349 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
14350 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14351 continue;
14352 }
14353
14354 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14355 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14356 continue;
14357 }
14358
14359 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14360
14361 if (param.value) {
14362 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14363 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14364 continue;
14365 }
14366 }
14367 confp->chan.echocancel.head.param_count++;
14368 }
14369 }
14370
14371
14372 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
14373
14374 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
14375
14376 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
14377 {
14378 struct dahdi_pvt *tmp;
14379 int y;
14380 int found_pseudo = 0;
14381 char dahdichan[MAX_CHANLIST_LEN] = {};
14382
14383 for (; v; v = v->next) {
14384 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14385 continue;
14386
14387
14388 if (!strcasecmp(v->name, "parkinglot")) {
14389 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
14390 }
14391
14392
14393 if (!strcasecmp(v->name, "channel")
14394 #ifdef HAVE_PRI
14395 || !strcasecmp(v->name, "crv")
14396 #endif
14397 ) {
14398 int iscrv;
14399 if (options & PROC_DAHDI_OPT_NOCHAN) {
14400 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
14401 continue;
14402 }
14403 iscrv = !strcasecmp(v->name, "crv");
14404 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14405 return -1;
14406 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
14407 } else if (!strcasecmp(v->name, "buffers")) {
14408 int res;
14409 char policy[21] = "";
14410
14411 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
14412 if (res != 2) {
14413 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14414 confp->chan.buf_no = numbufs;
14415 continue;
14416 }
14417 if (confp->chan.buf_no < 0)
14418 confp->chan.buf_no = numbufs;
14419 if (!strcasecmp(policy, "full")) {
14420 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14421 } else if (!strcasecmp(policy, "immediate")) {
14422 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14423 } else {
14424 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14425 }
14426 } else if (!strcasecmp(v->name, "dahdichan")) {
14427 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14428 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14429 usedistinctiveringdetection = ast_true(v->value);
14430 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14431 distinctiveringaftercid = ast_true(v->value);
14432 } else if (!strcasecmp(v->name, "dring1context")) {
14433 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14434 } else if (!strcasecmp(v->name, "dring2context")) {
14435 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14436 } else if (!strcasecmp(v->name, "dring3context")) {
14437 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14438 } else if (!strcasecmp(v->name, "dring1range")) {
14439 confp->chan.drings.ringnum[0].range = atoi(v->value);
14440 } else if (!strcasecmp(v->name, "dring2range")) {
14441 confp->chan.drings.ringnum[1].range = atoi(v->value);
14442 } else if (!strcasecmp(v->name, "dring3range")) {
14443 confp->chan.drings.ringnum[2].range = atoi(v->value);
14444 } else if (!strcasecmp(v->name, "dring1")) {
14445 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]);
14446 } else if (!strcasecmp(v->name, "dring2")) {
14447 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]);
14448 } else if (!strcasecmp(v->name, "dring3")) {
14449 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]);
14450 } else if (!strcasecmp(v->name, "usecallerid")) {
14451 confp->chan.use_callerid = ast_true(v->value);
14452 } else if (!strcasecmp(v->name, "cidsignalling")) {
14453 if (!strcasecmp(v->value, "bell"))
14454 confp->chan.cid_signalling = CID_SIG_BELL;
14455 else if (!strcasecmp(v->value, "v23"))
14456 confp->chan.cid_signalling = CID_SIG_V23;
14457 else if (!strcasecmp(v->value, "dtmf"))
14458 confp->chan.cid_signalling = CID_SIG_DTMF;
14459 else if (!strcasecmp(v->value, "smdi"))
14460 confp->chan.cid_signalling = CID_SIG_SMDI;
14461 else if (!strcasecmp(v->value, "v23_jp"))
14462 confp->chan.cid_signalling = CID_SIG_V23_JP;
14463 else if (ast_true(v->value))
14464 confp->chan.cid_signalling = CID_SIG_BELL;
14465 } else if (!strcasecmp(v->name, "cidstart")) {
14466 if (!strcasecmp(v->value, "ring"))
14467 confp->chan.cid_start = CID_START_RING;
14468 else if (!strcasecmp(v->value, "polarity_in"))
14469 confp->chan.cid_start = CID_START_POLARITY_IN;
14470 else if (!strcasecmp(v->value, "polarity"))
14471 confp->chan.cid_start = CID_START_POLARITY;
14472 else if (ast_true(v->value))
14473 confp->chan.cid_start = CID_START_RING;
14474 } else if (!strcasecmp(v->name, "threewaycalling")) {
14475 confp->chan.threewaycalling = ast_true(v->value);
14476 } else if (!strcasecmp(v->name, "cancallforward")) {
14477 confp->chan.cancallforward = ast_true(v->value);
14478 } else if (!strcasecmp(v->name, "relaxdtmf")) {
14479 if (ast_true(v->value))
14480 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14481 else
14482 confp->chan.dtmfrelax = 0;
14483 } else if (!strcasecmp(v->name, "mailbox")) {
14484 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14485 } else if (!strcasecmp(v->name, "hasvoicemail")) {
14486 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14487 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14488 }
14489 } else if (!strcasecmp(v->name, "adsi")) {
14490 confp->chan.adsi = ast_true(v->value);
14491 } else if (!strcasecmp(v->name, "usesmdi")) {
14492 confp->chan.use_smdi = ast_true(v->value);
14493 } else if (!strcasecmp(v->name, "smdiport")) {
14494 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14495 } else if (!strcasecmp(v->name, "transfer")) {
14496 confp->chan.transfer = ast_true(v->value);
14497 } else if (!strcasecmp(v->name, "canpark")) {
14498 confp->chan.canpark = ast_true(v->value);
14499 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14500 confp->chan.echocanbridged = ast_true(v->value);
14501 } else if (!strcasecmp(v->name, "busydetect")) {
14502 confp->chan.busydetect = ast_true(v->value);
14503 } else if (!strcasecmp(v->name, "busycount")) {
14504 confp->chan.busycount = atoi(v->value);
14505 } else if (!strcasecmp(v->name, "silencethreshold")) {
14506 confp->chan.silencethreshold = atoi(v->value);
14507 } else if (!strcasecmp(v->name, "busycompare")) {
14508 confp->chan.busycompare = ast_true(v->value);
14509 } else if (!strcasecmp(v->name, "busypattern")) {
14510 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
14511 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14512 }
14513 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
14514 if (count == 1)
14515 confp->chan.busyquietlength = 0;
14516 else if (count < 1)
14517 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
14518 } else if (!strcasecmp(v->name, "busyfuzziness")) {
14519 confp->chan.busyfuzziness = atoi(v->value);
14520 } else if (!strcasecmp(v->name, "callprogress")) {
14521 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14522 if (ast_true(v->value))
14523 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14524 } else if (!strcasecmp(v->name, "faxdetect")) {
14525 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14526 if (!strcasecmp(v->value, "incoming")) {
14527 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14528 } else if (!strcasecmp(v->value, "outgoing")) {
14529 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14530 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14531 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14532 } else if (!strcasecmp(v->name, "echocancel")) {
14533 process_echocancel(confp, v->value, v->lineno);
14534 } else if (!strcasecmp(v->name, "echotraining")) {
14535 if (sscanf(v->value, "%30d", &y) == 1) {
14536 if ((y < 10) || (y > 4000)) {
14537 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
14538 } else {
14539 confp->chan.echotraining = y;
14540 }
14541 } else if (ast_true(v->value)) {
14542 confp->chan.echotraining = 400;
14543 } else
14544 confp->chan.echotraining = 0;
14545 } else if (!strcasecmp(v->name, "hidecallerid")) {
14546 confp->chan.hidecallerid = ast_true(v->value);
14547 } else if (!strcasecmp(v->name, "hidecalleridname")) {
14548 confp->chan.hidecalleridname = ast_true(v->value);
14549 } else if (!strcasecmp(v->name, "pulsedial")) {
14550 confp->chan.pulse = ast_true(v->value);
14551 } else if (!strcasecmp(v->name, "callreturn")) {
14552 confp->chan.callreturn = ast_true(v->value);
14553 } else if (!strcasecmp(v->name, "callwaiting")) {
14554 confp->chan.callwaiting = ast_true(v->value);
14555 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14556 confp->chan.callwaitingcallerid = ast_true(v->value);
14557 } else if (!strcasecmp(v->name, "context")) {
14558 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14559 } else if (!strcasecmp(v->name, "language")) {
14560 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14561 } else if (!strcasecmp(v->name, "progzone")) {
14562 ast_copy_string(progzone, v->value, sizeof(progzone));
14563 } else if (!strcasecmp(v->name, "mohinterpret")
14564 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14565 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14566 } else if (!strcasecmp(v->name, "mohsuggest")) {
14567 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14568 } else if (!strcasecmp(v->name, "parkinglot")) {
14569 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
14570 } else if (!strcasecmp(v->name, "stripmsd")) {
14571 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14572 confp->chan.stripmsd = atoi(v->value);
14573 } else if (!strcasecmp(v->name, "jitterbuffers")) {
14574 numbufs = atoi(v->value);
14575 } else if (!strcasecmp(v->name, "group")) {
14576 confp->chan.group = ast_get_group(v->value);
14577 } else if (!strcasecmp(v->name, "callgroup")) {
14578 if (!strcasecmp(v->value, "none"))
14579 confp->chan.callgroup = 0;
14580 else
14581 confp->chan.callgroup = ast_get_group(v->value);
14582 } else if (!strcasecmp(v->name, "pickupgroup")) {
14583 if (!strcasecmp(v->value, "none"))
14584 confp->chan.pickupgroup = 0;
14585 else
14586 confp->chan.pickupgroup = ast_get_group(v->value);
14587 } else if (!strcasecmp(v->name, "setvar")) {
14588 char *varname = ast_strdupa(v->value), *varval = NULL;
14589 struct ast_variable *tmpvar;
14590 if (varname && (varval = strchr(varname, '='))) {
14591 *varval++ = '\0';
14592 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14593 tmpvar->next = confp->chan.vars;
14594 confp->chan.vars = tmpvar;
14595 }
14596 }
14597 } else if (!strcasecmp(v->name, "immediate")) {
14598 confp->chan.immediate = ast_true(v->value);
14599 } else if (!strcasecmp(v->name, "transfertobusy")) {
14600 confp->chan.transfertobusy = ast_true(v->value);
14601 } else if (!strcasecmp(v->name, "mwimonitor")) {
14602 confp->chan.mwimonitor_neon = 0;
14603 confp->chan.mwimonitor_fsk = 0;
14604 confp->chan.mwimonitor_rpas = 0;
14605 if (strcasestr(v->value, "fsk")) {
14606 confp->chan.mwimonitor_fsk = 1;
14607 }
14608 if (strcasestr(v->value, "rpas")) {
14609 confp->chan.mwimonitor_rpas = 1;
14610 }
14611 if (strcasestr(v->value, "neon")) {
14612 confp->chan.mwimonitor_neon = 1;
14613 }
14614
14615 if (ast_true(v->value)) {
14616 confp->chan.mwimonitor_fsk = 1;
14617 }
14618 } else if (!strcasecmp(v->name, "cid_rxgain")) {
14619 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
14620 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14621 }
14622 } else if (!strcasecmp(v->name, "rxgain")) {
14623 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
14624 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14625 }
14626 } else if (!strcasecmp(v->name, "txgain")) {
14627 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
14628 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14629 }
14630 } else if (!strcasecmp(v->name, "tonezone")) {
14631 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
14632 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14633 }
14634 } else if (!strcasecmp(v->name, "callerid")) {
14635 if (!strcasecmp(v->value, "asreceived")) {
14636 confp->chan.cid_num[0] = '\0';
14637 confp->chan.cid_name[0] = '\0';
14638 } else {
14639 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14640 }
14641 } else if (!strcasecmp(v->name, "fullname")) {
14642 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14643 } else if (!strcasecmp(v->name, "cid_number")) {
14644 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14645 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14646 confp->chan.dahditrcallerid = ast_true(v->value);
14647 } else if (!strcasecmp(v->name, "restrictcid")) {
14648 confp->chan.restrictcid = ast_true(v->value);
14649 } else if (!strcasecmp(v->name, "usecallingpres")) {
14650 confp->chan.use_callingpres = ast_true(v->value);
14651 } else if (!strcasecmp(v->name, "accountcode")) {
14652 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14653 } else if (!strcasecmp(v->name, "amaflags")) {
14654 y = ast_cdr_amaflags2int(v->value);
14655 if (y < 0)
14656 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14657 else
14658 confp->chan.amaflags = y;
14659 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14660 confp->chan.polarityonanswerdelay = atoi(v->value);
14661 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14662 confp->chan.answeronpolarityswitch = ast_true(v->value);
14663 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14664 confp->chan.hanguponpolarityswitch = ast_true(v->value);
14665 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14666 confp->chan.sendcalleridafter = atoi(v->value);
14667 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14668 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14669 } else if (!strcasecmp(v->name, "mwisendtype")) {
14670 if (!strcasecmp(v->value, "rpas")) {
14671 mwisend_rpas = 1;
14672 } else {
14673 mwisend_rpas = 0;
14674 }
14675 } else if (reload != 1) {
14676 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14677 int orig_radio = confp->chan.radio;
14678 int orig_outsigmod = confp->chan.outsigmod;
14679 int orig_auto = confp->is_sig_auto;
14680
14681 confp->chan.radio = 0;
14682 confp->chan.outsigmod = -1;
14683 confp->is_sig_auto = 0;
14684 if (!strcasecmp(v->value, "em")) {
14685 confp->chan.sig = SIG_EM;
14686 } else if (!strcasecmp(v->value, "em_e1")) {
14687 confp->chan.sig = SIG_EM_E1;
14688 } else if (!strcasecmp(v->value, "em_w")) {
14689 confp->chan.sig = SIG_EMWINK;
14690 } else if (!strcasecmp(v->value, "fxs_ls")) {
14691 confp->chan.sig = SIG_FXSLS;
14692 } else if (!strcasecmp(v->value, "fxs_gs")) {
14693 confp->chan.sig = SIG_FXSGS;
14694 } else if (!strcasecmp(v->value, "fxs_ks")) {
14695 confp->chan.sig = SIG_FXSKS;
14696 } else if (!strcasecmp(v->value, "fxo_ls")) {
14697 confp->chan.sig = SIG_FXOLS;
14698 } else if (!strcasecmp(v->value, "fxo_gs")) {
14699 confp->chan.sig = SIG_FXOGS;
14700 } else if (!strcasecmp(v->value, "fxo_ks")) {
14701 confp->chan.sig = SIG_FXOKS;
14702 } else if (!strcasecmp(v->value, "fxs_rx")) {
14703 confp->chan.sig = SIG_FXSKS;
14704 confp->chan.radio = 1;
14705 } else if (!strcasecmp(v->value, "fxo_rx")) {
14706 confp->chan.sig = SIG_FXOLS;
14707 confp->chan.radio = 1;
14708 } else if (!strcasecmp(v->value, "fxs_tx")) {
14709 confp->chan.sig = SIG_FXSLS;
14710 confp->chan.radio = 1;
14711 } else if (!strcasecmp(v->value, "fxo_tx")) {
14712 confp->chan.sig = SIG_FXOGS;
14713 confp->chan.radio = 1;
14714 } else if (!strcasecmp(v->value, "em_rx")) {
14715 confp->chan.sig = SIG_EM;
14716 confp->chan.radio = 1;
14717 } else if (!strcasecmp(v->value, "em_tx")) {
14718 confp->chan.sig = SIG_EM;
14719 confp->chan.radio = 1;
14720 } else if (!strcasecmp(v->value, "em_rxtx")) {
14721 confp->chan.sig = SIG_EM;
14722 confp->chan.radio = 2;
14723 } else if (!strcasecmp(v->value, "em_txrx")) {
14724 confp->chan.sig = SIG_EM;
14725 confp->chan.radio = 2;
14726 } else if (!strcasecmp(v->value, "sf")) {
14727 confp->chan.sig = SIG_SF;
14728 } else if (!strcasecmp(v->value, "sf_w")) {
14729 confp->chan.sig = SIG_SFWINK;
14730 } else if (!strcasecmp(v->value, "sf_featd")) {
14731 confp->chan.sig = SIG_FEATD;
14732 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14733 confp->chan.sig = SIG_FEATDMF;
14734 } else if (!strcasecmp(v->value, "sf_featb")) {
14735 confp->chan.sig = SIG_SF_FEATB;
14736 } else if (!strcasecmp(v->value, "sf")) {
14737 confp->chan.sig = SIG_SF;
14738 } else if (!strcasecmp(v->value, "sf_rx")) {
14739 confp->chan.sig = SIG_SF;
14740 confp->chan.radio = 1;
14741 } else if (!strcasecmp(v->value, "sf_tx")) {
14742 confp->chan.sig = SIG_SF;
14743 confp->chan.radio = 1;
14744 } else if (!strcasecmp(v->value, "sf_rxtx")) {
14745 confp->chan.sig = SIG_SF;
14746 confp->chan.radio = 2;
14747 } else if (!strcasecmp(v->value, "sf_txrx")) {
14748 confp->chan.sig = SIG_SF;
14749 confp->chan.radio = 2;
14750 } else if (!strcasecmp(v->value, "featd")) {
14751 confp->chan.sig = SIG_FEATD;
14752 } else if (!strcasecmp(v->value, "featdmf")) {
14753 confp->chan.sig = SIG_FEATDMF;
14754 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14755 confp->chan.sig = SIG_FEATDMF_TA;
14756 } else if (!strcasecmp(v->value, "e911")) {
14757 confp->chan.sig = SIG_E911;
14758 } else if (!strcasecmp(v->value, "fgccama")) {
14759 confp->chan.sig = SIG_FGC_CAMA;
14760 } else if (!strcasecmp(v->value, "fgccamamf")) {
14761 confp->chan.sig = SIG_FGC_CAMAMF;
14762 } else if (!strcasecmp(v->value, "featb")) {
14763 confp->chan.sig = SIG_FEATB;
14764 #ifdef HAVE_PRI
14765 } else if (!strcasecmp(v->value, "pri_net")) {
14766 confp->chan.sig = SIG_PRI;
14767 confp->pri.nodetype = PRI_NETWORK;
14768 } else if (!strcasecmp(v->value, "pri_cpe")) {
14769 confp->chan.sig = SIG_PRI;
14770 confp->pri.nodetype = PRI_CPE;
14771 } else if (!strcasecmp(v->value, "bri_cpe")) {
14772 confp->chan.sig = SIG_BRI;
14773 confp->pri.nodetype = PRI_CPE;
14774 } else if (!strcasecmp(v->value, "bri_net")) {
14775 confp->chan.sig = SIG_BRI;
14776 confp->pri.nodetype = PRI_NETWORK;
14777 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14778 confp->chan.sig = SIG_BRI_PTMP;
14779 confp->pri.nodetype = PRI_CPE;
14780 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14781 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
14782 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14783 confp->chan.sig = SIG_GR303FXOKS;
14784 confp->pri.nodetype = PRI_NETWORK;
14785 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14786 confp->chan.sig = SIG_GR303FXSKS;
14787 confp->pri.nodetype = PRI_CPE;
14788 #endif
14789 #ifdef HAVE_SS7
14790 } else if (!strcasecmp(v->value, "ss7")) {
14791 confp->chan.sig = SIG_SS7;
14792 #endif
14793 } else if (!strcasecmp(v->value, "auto")) {
14794 confp->is_sig_auto = 1;
14795 } else {
14796 confp->chan.outsigmod = orig_outsigmod;
14797 confp->chan.radio = orig_radio;
14798 confp->is_sig_auto = orig_auto;
14799 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14800 }
14801 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14802 if (!strcasecmp(v->value, "em")) {
14803 confp->chan.outsigmod = SIG_EM;
14804 } else if (!strcasecmp(v->value, "em_e1")) {
14805 confp->chan.outsigmod = SIG_EM_E1;
14806 } else if (!strcasecmp(v->value, "em_w")) {
14807 confp->chan.outsigmod = SIG_EMWINK;
14808 } else if (!strcasecmp(v->value, "sf")) {
14809 confp->chan.outsigmod = SIG_SF;
14810 } else if (!strcasecmp(v->value, "sf_w")) {
14811 confp->chan.outsigmod = SIG_SFWINK;
14812 } else if (!strcasecmp(v->value, "sf_featd")) {
14813 confp->chan.outsigmod = SIG_FEATD;
14814 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14815 confp->chan.outsigmod = SIG_FEATDMF;
14816 } else if (!strcasecmp(v->value, "sf_featb")) {
14817 confp->chan.outsigmod = SIG_SF_FEATB;
14818 } else if (!strcasecmp(v->value, "sf")) {
14819 confp->chan.outsigmod = SIG_SF;
14820 } else if (!strcasecmp(v->value, "featd")) {
14821 confp->chan.outsigmod = SIG_FEATD;
14822 } else if (!strcasecmp(v->value, "featdmf")) {
14823 confp->chan.outsigmod = SIG_FEATDMF;
14824 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14825 confp->chan.outsigmod = SIG_FEATDMF_TA;
14826 } else if (!strcasecmp(v->value, "e911")) {
14827 confp->chan.outsigmod = SIG_E911;
14828 } else if (!strcasecmp(v->value, "fgccama")) {
14829 confp->chan.outsigmod = SIG_FGC_CAMA;
14830 } else if (!strcasecmp(v->value, "fgccamamf")) {
14831 confp->chan.outsigmod = SIG_FGC_CAMAMF;
14832 } else if (!strcasecmp(v->value, "featb")) {
14833 confp->chan.outsigmod = SIG_FEATB;
14834 } else {
14835 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14836 }
14837 #ifdef HAVE_PRI
14838 } else if (!strcasecmp(v->name, "pridialplan")) {
14839 if (!strcasecmp(v->value, "national")) {
14840 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14841 } else if (!strcasecmp(v->value, "unknown")) {
14842 confp->pri.dialplan = PRI_UNKNOWN + 1;
14843 } else if (!strcasecmp(v->value, "private")) {
14844 confp->pri.dialplan = PRI_PRIVATE + 1;
14845 } else if (!strcasecmp(v->value, "international")) {
14846 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14847 } else if (!strcasecmp(v->value, "local")) {
14848 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14849 } else if (!strcasecmp(v->value, "dynamic")) {
14850 confp->pri.dialplan = -1;
14851 } else if (!strcasecmp(v->value, "redundant")) {
14852 confp->pri.dialplan = -2;
14853 } else {
14854 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14855 }
14856 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14857 if (!strcasecmp(v->value, "national")) {
14858 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14859 } else if (!strcasecmp(v->value, "unknown")) {
14860 confp->pri.localdialplan = PRI_UNKNOWN + 1;
14861 } else if (!strcasecmp(v->value, "private")) {
14862 confp->pri.localdialplan = PRI_PRIVATE + 1;
14863 } else if (!strcasecmp(v->value, "international")) {
14864 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14865 } else if (!strcasecmp(v->value, "local")) {
14866 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14867 } else if (!strcasecmp(v->value, "dynamic")) {
14868 confp->pri.localdialplan = -1;
14869 } else if (!strcasecmp(v->value, "redundant")) {
14870 confp->pri.localdialplan = -2;
14871 } else {
14872 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14873 }
14874 } else if (!strcasecmp(v->name, "switchtype")) {
14875 if (!strcasecmp(v->value, "national"))
14876 confp->pri.switchtype = PRI_SWITCH_NI2;
14877 else if (!strcasecmp(v->value, "ni1"))
14878 confp->pri.switchtype = PRI_SWITCH_NI1;
14879 else if (!strcasecmp(v->value, "dms100"))
14880 confp->pri.switchtype = PRI_SWITCH_DMS100;
14881 else if (!strcasecmp(v->value, "4ess"))
14882 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14883 else if (!strcasecmp(v->value, "5ess"))
14884 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14885 else if (!strcasecmp(v->value, "euroisdn"))
14886 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14887 else if (!strcasecmp(v->value, "qsig"))
14888 confp->pri.switchtype = PRI_SWITCH_QSIG;
14889 else {
14890 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14891 return -1;
14892 }
14893 } else if (!strcasecmp(v->name, "nsf")) {
14894 if (!strcasecmp(v->value, "sdn"))
14895 confp->pri.nsf = PRI_NSF_SDN;
14896 else if (!strcasecmp(v->value, "megacom"))
14897 confp->pri.nsf = PRI_NSF_MEGACOM;
14898 else if (!strcasecmp(v->value, "tollfreemegacom"))
14899 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14900 else if (!strcasecmp(v->value, "accunet"))
14901 confp->pri.nsf = PRI_NSF_ACCUNET;
14902 else if (!strcasecmp(v->value, "none"))
14903 confp->pri.nsf = PRI_NSF_NONE;
14904 else {
14905 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14906 confp->pri.nsf = PRI_NSF_NONE;
14907 }
14908 } else if (!strcasecmp(v->name, "priindication")) {
14909 if (!strcasecmp(v->value, "outofband"))
14910 confp->chan.priindication_oob = 1;
14911 else if (!strcasecmp(v->value, "inband"))
14912 confp->chan.priindication_oob = 0;
14913 else
14914 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14915 v->value, v->lineno);
14916 } else if (!strcasecmp(v->name, "priexclusive")) {
14917 confp->chan.priexclusive = ast_true(v->value);
14918 } else if (!strcasecmp(v->name, "internationalprefix")) {
14919 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14920 } else if (!strcasecmp(v->name, "nationalprefix")) {
14921 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14922 } else if (!strcasecmp(v->name, "localprefix")) {
14923 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14924 } else if (!strcasecmp(v->name, "privateprefix")) {
14925 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14926 } else if (!strcasecmp(v->name, "unknownprefix")) {
14927 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14928 } else if (!strcasecmp(v->name, "resetinterval")) {
14929 if (!strcasecmp(v->value, "never"))
14930 confp->pri.resetinterval = -1;
14931 else if (atoi(v->value) >= 60)
14932 confp->pri.resetinterval = atoi(v->value);
14933 else
14934 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14935 v->value, v->lineno);
14936 } else if (!strcasecmp(v->name, "minunused")) {
14937 confp->pri.minunused = atoi(v->value);
14938 } else if (!strcasecmp(v->name, "minidle")) {
14939 confp->pri.minidle = atoi(v->value);
14940 } else if (!strcasecmp(v->name, "idleext")) {
14941 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14942 } else if (!strcasecmp(v->name, "idledial")) {
14943 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14944 } else if (!strcasecmp(v->name, "overlapdial")) {
14945 if (ast_true(v->value)) {
14946 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14947 } else if (!strcasecmp(v->value, "incoming")) {
14948 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14949 } else if (!strcasecmp(v->value, "outgoing")) {
14950 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14951 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14952 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14953 } else {
14954 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14955 }
14956 #ifdef HAVE_PRI_INBANDDISCONNECT
14957 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14958 confp->pri.inbanddisconnect = ast_true(v->value);
14959 #endif
14960 } else if (!strcasecmp(v->name, "pritimer")) {
14961 #ifdef PRI_GETSET_TIMERS
14962 char tmp[20];
14963 char *timerc;
14964 char *c;
14965 int timer;
14966 int timeridx;
14967
14968 ast_copy_string(tmp, v->value, sizeof(tmp));
14969 c = tmp;
14970 timerc = strsep(&c, ",");
14971 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
14972 timeridx = pri_timer2idx(timerc);
14973 timer = atoi(c);
14974 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
14975 ast_log(LOG_WARNING,
14976 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
14977 v->lineno);
14978 } else if (!timer) {
14979 ast_log(LOG_WARNING,
14980 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
14981 c, timerc, v->lineno);
14982 } else {
14983 pritimers[timeridx] = timer;
14984 }
14985 } else {
14986 ast_log(LOG_WARNING,
14987 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
14988 v->value, v->lineno);
14989 }
14990
14991 } else if (!strcasecmp(v->name, "facilityenable")) {
14992 confp->pri.facilityenable = ast_true(v->value);
14993 #endif
14994 #endif
14995 #ifdef HAVE_SS7
14996 } else if (!strcasecmp(v->name, "ss7type")) {
14997 if (!strcasecmp(v->value, "itu")) {
14998 cur_ss7type = SS7_ITU;
14999 } else if (!strcasecmp(v->value, "ansi")) {
15000 cur_ss7type = SS7_ANSI;
15001 } else
15002 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
15003 } else if (!strcasecmp(v->name, "linkset")) {
15004 cur_linkset = atoi(v->value);
15005 } else if (!strcasecmp(v->name, "pointcode")) {
15006 cur_pointcode = parse_pointcode(v->value);
15007 } else if (!strcasecmp(v->name, "adjpointcode")) {
15008 cur_adjpointcode = parse_pointcode(v->value);
15009 } else if (!strcasecmp(v->name, "defaultdpc")) {
15010 cur_defaultdpc = parse_pointcode(v->value);
15011 } else if (!strcasecmp(v->name, "cicbeginswith")) {
15012 cur_cicbeginswith = atoi(v->value);
15013 } else if (!strcasecmp(v->name, "networkindicator")) {
15014 if (!strcasecmp(v->value, "national"))
15015 cur_networkindicator = SS7_NI_NAT;
15016 else if (!strcasecmp(v->value, "national_spare"))
15017 cur_networkindicator = SS7_NI_NAT_SPARE;
15018 else if (!strcasecmp(v->value, "international"))
15019 cur_networkindicator = SS7_NI_INT;
15020 else if (!strcasecmp(v->value, "international_spare"))
15021 cur_networkindicator = SS7_NI_INT_SPARE;
15022 else
15023 cur_networkindicator = -1;
15024 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
15025 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
15026 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
15027 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
15028 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
15029 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
15030 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
15031 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
15032 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
15033 if (!strcasecmp(v->value, "national")) {
15034 confp->ss7.called_nai = SS7_NAI_NATIONAL;
15035 } else if (!strcasecmp(v->value, "international")) {
15036 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
15037 } else if (!strcasecmp(v->value, "subscriber")) {
15038 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
15039 } else if (!strcasecmp(v->value, "dynamic")) {
15040 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
15041 } else {
15042 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
15043 }
15044 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
15045 if (!strcasecmp(v->value, "national")) {
15046 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
15047 } else if (!strcasecmp(v->value, "international")) {
15048 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
15049 } else if (!strcasecmp(v->value, "subscriber")) {
15050 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
15051 } else if (!strcasecmp(v->value, "dynamic")) {
15052 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
15053 } else {
15054 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
15055 }
15056 } else if (!strcasecmp(v->name, "sigchan")) {
15057 int sigchan, res;
15058 sigchan = atoi(v->value);
15059 res = linkset_addsigchan(sigchan);
15060 if (res < 0)
15061 return -1;
15062
15063 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
15064 struct dahdi_ss7 *link;
15065 link = ss7_resolve_linkset(cur_linkset);
15066 if (!link) {
15067 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
15068 return -1;
15069 }
15070 if (ast_true(v->value))
15071 link->flags |= LINKSET_FLAG_EXPLICITACM;
15072
15073 #endif
15074 } else if (!strcasecmp(v->name, "cadence")) {
15075
15076 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
15077 int i;
15078 struct dahdi_ring_cadence new_cadence;
15079 int cid_location = -1;
15080 int firstcadencepos = 0;
15081 char original_args[80];
15082 int cadence_is_ok = 1;
15083
15084 ast_copy_string(original_args, v->value, sizeof(original_args));
15085
15086 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]);
15087
15088
15089 if (element_count % 2 == 1) {
15090 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
15091 cadence_is_ok = 0;
15092 }
15093
15094
15095 for (i = 0; i < element_count; i++) {
15096 if (c[i] == 0) {
15097 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
15098 cadence_is_ok = 0;
15099 break;
15100 } else if (c[i] < 0) {
15101 if (i % 2 == 1) {
15102
15103 if (cid_location == -1) {
15104 cid_location = i;
15105 c[i] *= -1;
15106 } else {
15107 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
15108 cadence_is_ok = 0;
15109 break;
15110 }
15111 } else {
15112 if (firstcadencepos == 0) {
15113 firstcadencepos = i;
15114
15115 } else {
15116 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
15117 cadence_is_ok = 0;
15118 break;
15119 }
15120 }
15121 }
15122 }
15123
15124
15125 for (i = 0; i < 16; i++) {
15126 new_cadence.ringcadence[i] = c[i];
15127 }
15128
15129 if (cadence_is_ok) {
15130
15131 if (element_count < 2) {
15132 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
15133 } else {
15134 if (cid_location == -1) {
15135
15136 cid_location = 1;
15137 } else {
15138
15139 cid_location = (cid_location + 1) / 2;
15140 }
15141
15142 if (!user_has_defined_cadences++)
15143
15144 num_cadence = 0;
15145 if ((num_cadence+1) >= NUM_CADENCE_MAX)
15146 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
15147 else {
15148 cadences[num_cadence] = new_cadence;
15149 cidrings[num_cadence++] = cid_location;
15150 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
15151 }
15152 }
15153 }
15154 } else if (!strcasecmp(v->name, "ringtimeout")) {
15155 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
15156 } else if (!strcasecmp(v->name, "prewink")) {
15157 confp->timing.prewinktime = atoi(v->value);
15158 } else if (!strcasecmp(v->name, "preflash")) {
15159 confp->timing.preflashtime = atoi(v->value);
15160 } else if (!strcasecmp(v->name, "wink")) {
15161 confp->timing.winktime = atoi(v->value);
15162 } else if (!strcasecmp(v->name, "flash")) {
15163 confp->timing.flashtime = atoi(v->value);
15164 } else if (!strcasecmp(v->name, "start")) {
15165 confp->timing.starttime = atoi(v->value);
15166 } else if (!strcasecmp(v->name, "rxwink")) {
15167 confp->timing.rxwinktime = atoi(v->value);
15168 } else if (!strcasecmp(v->name, "rxflash")) {
15169 confp->timing.rxflashtime = atoi(v->value);
15170 } else if (!strcasecmp(v->name, "debounce")) {
15171 confp->timing.debouncetime = atoi(v->value);
15172 } else if (!strcasecmp(v->name, "toneduration")) {
15173 int toneduration;
15174 int ctlfd;
15175 int res;
15176 struct dahdi_dialparams dps;
15177
15178 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
15179 if (ctlfd == -1) {
15180 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
15181 return -1;
15182 }
15183
15184 toneduration = atoi(v->value);
15185 if (toneduration > -1) {
15186 memset(&dps, 0, sizeof(dps));
15187
15188 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
15189 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
15190 if (res < 0) {
15191 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
15192 return -1;
15193 }
15194 }
15195 close(ctlfd);
15196 } else if (!strcasecmp(v->name, "defaultcic")) {
15197 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
15198 } else if (!strcasecmp(v->name, "defaultozz")) {
15199 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
15200 } else if (!strcasecmp(v->name, "mwilevel")) {
15201 mwilevel = atoi(v->value);
15202 }
15203 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
15204 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
15205 }
15206 if (dahdichan[0]) {
15207
15208
15209 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
15210 return -1;
15211 }
15212 }
15213
15214
15215 if (!found_pseudo && reload != 1) {
15216
15217
15218
15219
15220 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
15221
15222 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
15223
15224 if (tmp) {
15225 ast_verb(3, "Automatically generated pseudo channel\n");
15226 } else {
15227 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
15228 }
15229 }
15230 return 0;
15231 }
15232
15233 static int setup_dahdi(int reload)
15234 {
15235 struct ast_config *cfg, *ucfg;
15236 struct ast_variable *v;
15237 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
15238 struct dahdi_chan_conf conf;
15239 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
15240 const char *cat;
15241 int res;
15242
15243 #ifdef HAVE_PRI
15244 char *c;
15245 int spanno;
15246 int i;
15247 int logicalspan;
15248 int trunkgroup;
15249 int dchannels[NUM_DCHANS];
15250 #endif
15251
15252 cfg = ast_config_load(config, config_flags);
15253
15254
15255 if (!cfg) {
15256 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
15257 return 0;
15258 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
15259 ucfg = ast_config_load("users.conf", config_flags);
15260 if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
15261 return 0;
15262 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15263 cfg = ast_config_load(config, config_flags);
15264 } else {
15265 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15266 ucfg = ast_config_load("users.conf", config_flags);
15267 }
15268
15269
15270 ast_mutex_lock(&iflock);
15271 #ifdef HAVE_PRI
15272 if (reload != 1) {
15273
15274 v = ast_variable_browse(cfg, "trunkgroups");
15275 while (v) {
15276 if (!strcasecmp(v->name, "trunkgroup")) {
15277 trunkgroup = atoi(v->value);
15278 if (trunkgroup > 0) {
15279 if ((c = strchr(v->value, ','))) {
15280 i = 0;
15281 memset(dchannels, 0, sizeof(dchannels));
15282 while (c && (i < NUM_DCHANS)) {
15283 dchannels[i] = atoi(c + 1);
15284 if (dchannels[i] < 0) {
15285 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);
15286 } else
15287 i++;
15288 c = strchr(c + 1, ',');
15289 }
15290 if (i) {
15291 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
15292 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);
15293 } else
15294 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");
15295 } else
15296 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15297 } else
15298 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15299 } else
15300 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
15301 } else if (!strcasecmp(v->name, "spanmap")) {
15302 spanno = atoi(v->value);
15303 if (spanno > 0) {
15304 if ((c = strchr(v->value, ','))) {
15305 trunkgroup = atoi(c + 1);
15306 if (trunkgroup > 0) {
15307 if ((c = strchr(c + 1, ',')))
15308 logicalspan = atoi(c + 1);
15309 else
15310 logicalspan = 0;
15311 if (logicalspan >= 0) {
15312 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15313 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15314 } else
15315 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15316 } else
15317 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);
15318 } else
15319 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15320 } else
15321 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15322 } else
15323 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15324 } else {
15325 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15326 }
15327 v = v->next;
15328 }
15329 }
15330 #endif
15331
15332
15333 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
15334
15335 mwimonitornotify[0] = '\0';
15336
15337 v = ast_variable_browse(cfg, "channels");
15338 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
15339 ast_mutex_unlock(&iflock);
15340 ast_config_destroy(cfg);
15341 if (ucfg) {
15342 ast_config_destroy(ucfg);
15343 }
15344 return res;
15345 }
15346
15347
15348 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15349
15350
15351
15352 if (!strcasecmp(cat, "general") ||
15353 !strcasecmp(cat, "trunkgroups") ||
15354 !strcasecmp(cat, "globals") ||
15355 !strcasecmp(cat, "channels")) {
15356 continue;
15357 }
15358
15359 memcpy(&conf, &base_conf, sizeof(conf));
15360
15361 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
15362 ast_mutex_unlock(&iflock);
15363 ast_config_destroy(cfg);
15364 if (ucfg) {
15365 ast_config_destroy(ucfg);
15366 }
15367 return res;
15368 }
15369 }
15370
15371 ast_config_destroy(cfg);
15372
15373 if (ucfg) {
15374 const char *chans;
15375
15376 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
15377
15378 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15379 if (!strcasecmp(cat, "general")) {
15380 continue;
15381 }
15382
15383 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
15384
15385 if (ast_strlen_zero(chans)) {
15386 continue;
15387 }
15388
15389 memcpy(&conf, &base_conf, sizeof(conf));
15390
15391 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
15392 ast_config_destroy(ucfg);
15393 ast_mutex_unlock(&iflock);
15394 return res;
15395 }
15396 }
15397 ast_config_destroy(ucfg);
15398 }
15399 ast_mutex_unlock(&iflock);
15400
15401 #ifdef HAVE_PRI
15402 if (reload != 1) {
15403 int x;
15404 for (x = 0; x < NUM_SPANS; x++) {
15405 if (pris[x].pvts[0]) {
15406 if (start_pri(pris + x)) {
15407 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15408 return -1;
15409 } else
15410 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
15411 }
15412 }
15413 }
15414 #endif
15415 #ifdef HAVE_SS7
15416 if (reload != 1) {
15417 int x;
15418 for (x = 0; x < NUM_SPANS; x++) {
15419 if (linksets[x].ss7) {
15420 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
15421 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
15422 return -1;
15423 } else
15424 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
15425 }
15426 }
15427 }
15428 #endif
15429
15430 restart_monitor();
15431 return 0;
15432 }
15433
15434 static int load_module(void)
15435 {
15436 int res;
15437 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15438 int y, i;
15439 #endif
15440
15441 #ifdef HAVE_PRI
15442 memset(pris, 0, sizeof(pris));
15443 for (y = 0; y < NUM_SPANS; y++) {
15444 ast_mutex_init(&pris[y].lock);
15445 pris[y].offset = -1;
15446 pris[y].master = AST_PTHREADT_NULL;
15447 for (i = 0; i < NUM_DCHANS; i++)
15448 pris[y].fds[i] = -1;
15449 }
15450 pri_set_error(dahdi_pri_error);
15451 pri_set_message(dahdi_pri_message);
15452 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15453 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15454 #endif
15455 #ifdef HAVE_SS7
15456 memset(linksets, 0, sizeof(linksets));
15457 for (y = 0; y < NUM_SPANS; y++) {
15458 ast_mutex_init(&linksets[y].lock);
15459 linksets[y].master = AST_PTHREADT_NULL;
15460 for (i = 0; i < NUM_DCHANS; i++)
15461 linksets[y].fds[i] = -1;
15462 }
15463 ss7_set_error(dahdi_ss7_error);
15464 ss7_set_message(dahdi_ss7_message);
15465 #endif
15466 res = setup_dahdi(0);
15467
15468 if (res)
15469 return AST_MODULE_LOAD_DECLINE;
15470 if (ast_channel_register(&dahdi_tech)) {
15471 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15472 __unload_module();
15473 return AST_MODULE_LOAD_FAILURE;
15474 }
15475 #ifdef HAVE_PRI
15476 ast_string_field_init(&inuse, 16);
15477 ast_string_field_set(&inuse, name, "GR-303InUse");
15478 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15479 #endif
15480 #ifdef HAVE_SS7
15481 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15482 #endif
15483
15484 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15485
15486 memset(round_robin, 0, sizeof(round_robin));
15487 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15488 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15489 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15490 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15491 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15492 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15493 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15494
15495 ast_cond_init(&mwi_thread_complete, NULL);
15496 ast_cond_init(&ss_thread_complete, NULL);
15497
15498 return res;
15499 }
15500
15501 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15502 {
15503 #define END_SILENCE_LEN 400
15504 #define HEADER_MS 50
15505 #define TRAILER_MS 5
15506 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15507 #define ASCII_BYTES_PER_CHAR 80
15508
15509 unsigned char *buf,*mybuf;
15510 struct dahdi_pvt *p = c->tech_pvt;
15511 struct pollfd fds[1];
15512 int size,res,fd,len,x;
15513 int bytes=0;
15514
15515 float cr = 1.0;
15516 float ci = 0.0;
15517 float scont = 0.0;
15518 int idx;
15519
15520 idx = dahdi_get_index(c, p, 0);
15521 if (idx < 0) {
15522 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
15523 return -1;
15524 }
15525 if (!text[0]) return(0);
15526 if ((!p->tdd) && (!p->mate)) return(0);
15527 if (p->mate)
15528 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15529 else
15530 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15531 if (!buf)
15532 return -1;
15533 mybuf = buf;
15534 if (p->mate) {
15535 int codec = AST_LAW(p);
15536 for (x = 0; x < HEADER_MS; x++) {
15537 PUT_CLID_MARKMS;
15538 }
15539
15540 for (x = 0; text[x]; x++) {
15541 PUT_CLID(text[x]);
15542 }
15543 for (x = 0; x < TRAILER_MS; x++) {
15544 PUT_CLID_MARKMS;
15545 }
15546 len = bytes;
15547 buf = mybuf;
15548 } else {
15549 len = tdd_generate(p->tdd, buf, text);
15550 if (len < 1) {
15551 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15552 ast_free(mybuf);
15553 return -1;
15554 }
15555 }
15556 memset(buf + len, 0x7f, END_SILENCE_LEN);
15557 len += END_SILENCE_LEN;
15558 fd = p->subs[idx].dfd;
15559 while (len) {
15560 if (ast_check_hangup(c)) {
15561 ast_free(mybuf);
15562 return -1;
15563 }
15564 size = len;
15565 if (size > READ_SIZE)
15566 size = READ_SIZE;
15567 fds[0].fd = fd;
15568 fds[0].events = POLLOUT | POLLPRI;
15569 fds[0].revents = 0;
15570 res = poll(fds, 1, -1);
15571 if (!res) {
15572 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15573 continue;
15574 }
15575
15576 if (fds[0].revents & POLLPRI) {
15577 ast_free(mybuf);
15578 return -1;
15579 }
15580 if (!(fds[0].revents & POLLOUT)) {
15581 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15582 continue;
15583 }
15584 res = write(fd, buf, size);
15585 if (res != size) {
15586 if (res == -1) {
15587 ast_free(mybuf);
15588 return -1;
15589 }
15590 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15591 break;
15592 }
15593 len -= size;
15594 buf += size;
15595 }
15596 ast_free(mybuf);
15597 return(0);
15598 }
15599
15600
15601 static int reload(void)
15602 {
15603 int res = 0;
15604
15605 res = setup_dahdi(1);
15606 if (res) {
15607 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15608 return -1;
15609 }
15610 return 0;
15611 }
15612
15613
15614
15615
15616
15617 #ifdef HAVE_PRI
15618 #ifdef HAVE_SS7
15619 #define tdesc "DAHDI Telephony w/PRI & SS7"
15620 #else
15621 #define tdesc "DAHDI Telephony w/PRI"
15622 #endif
15623 #else
15624 #ifdef HAVE_SS7
15625 #define tdesc "DAHDI Telephony w/SS7"
15626 #else
15627 #define tdesc "DAHDI Telephony"
15628 #endif
15629 #endif
15630
15631 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15632 .load = load_module,
15633 .unload = unload_module,
15634 .reload = reload,
15635 );
15636
15637