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: 232093 $")
00051
00052 #ifdef __NetBSD__
00053 #include <pthread.h>
00054 #include <signal.h>
00055 #else
00056 #include <sys/signal.h>
00057 #endif
00058 #include <sys/ioctl.h>
00059 #include <math.h>
00060 #include <ctype.h>
00061
00062 #include <dahdi/user.h>
00063 #include <dahdi/tonezone.h>
00064
00065 #ifdef HAVE_PRI
00066 #include <libpri.h>
00067 #endif
00068
00069 #ifdef HAVE_SS7
00070 #include <libss7.h>
00071 #endif
00072
00073 #include "asterisk/lock.h"
00074 #include "asterisk/channel.h"
00075 #include "asterisk/config.h"
00076 #include "asterisk/module.h"
00077 #include "asterisk/pbx.h"
00078 #include "asterisk/file.h"
00079 #include "asterisk/ulaw.h"
00080 #include "asterisk/alaw.h"
00081 #include "asterisk/callerid.h"
00082 #include "asterisk/adsi.h"
00083 #include "asterisk/cli.h"
00084 #include "asterisk/cdr.h"
00085 #include "asterisk/features.h"
00086 #include "asterisk/musiconhold.h"
00087 #include "asterisk/say.h"
00088 #include "asterisk/tdd.h"
00089 #include "asterisk/app.h"
00090 #include "asterisk/dsp.h"
00091 #include "asterisk/astdb.h"
00092 #include "asterisk/manager.h"
00093 #include "asterisk/causes.h"
00094 #include "asterisk/term.h"
00095 #include "asterisk/utils.h"
00096 #include "asterisk/transcap.h"
00097 #include "asterisk/stringfields.h"
00098 #include "asterisk/abstract_jb.h"
00099 #include "asterisk/smdi.h"
00100 #include "asterisk/astobj.h"
00101 #include "asterisk/event.h"
00102 #include "asterisk/devicestate.h"
00103
00104 #define SMDI_MD_WAIT_TIMEOUT 1500
00105
00106 static const char *lbostr[] = {
00107 "0 db (CSU)/0-133 feet (DSX-1)",
00108 "133-266 feet (DSX-1)",
00109 "266-399 feet (DSX-1)",
00110 "399-533 feet (DSX-1)",
00111 "533-655 feet (DSX-1)",
00112 "-7.5db (CSU)",
00113 "-15db (CSU)",
00114 "-22.5db (CSU)"
00115 };
00116
00117
00118 static struct ast_jb_conf default_jbconf =
00119 {
00120 .flags = 0,
00121 .max_size = -1,
00122 .resync_threshold = -1,
00123 .impl = ""
00124 };
00125 static struct ast_jb_conf global_jbconf;
00126
00127
00128 #undef SUPPORT_USERUSER
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 #define DEFAULT_CIDRINGS 1
00150
00151 #define CHANNEL_PSEUDO -12
00152
00153 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00154
00155
00156
00157 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
00158
00159 static const char tdesc[] = "DAHDI Telephony Driver"
00160 #ifdef HAVE_PRI
00161 " w/PRI"
00162 #endif
00163 #ifdef HAVE_SS7
00164 " w/SS7"
00165 #endif
00166 ;
00167
00168 static const char config[] = "chan_dahdi.conf";
00169
00170 #define SIG_EM DAHDI_SIG_EM
00171 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00173 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00174 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00175 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00176 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00177 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00178 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00179 #define SIG_FXSLS DAHDI_SIG_FXSLS
00180 #define SIG_FXSGS DAHDI_SIG_FXSGS
00181 #define SIG_FXSKS DAHDI_SIG_FXSKS
00182 #define SIG_FXOLS DAHDI_SIG_FXOLS
00183 #define SIG_FXOGS DAHDI_SIG_FXOGS
00184 #define SIG_FXOKS DAHDI_SIG_FXOKS
00185 #define SIG_PRI DAHDI_SIG_CLEAR
00186 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00187 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00188 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00189 #define SIG_SF DAHDI_SIG_SF
00190 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00191 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00192 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00193 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00194 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00195 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00196 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00197
00198 #ifdef LOTS_OF_SPANS
00199 #define NUM_SPANS DAHDI_MAX_SPANS
00200 #else
00201 #define NUM_SPANS 32
00202 #endif
00203 #define NUM_DCHANS 4
00204 #define MAX_CHANNELS 672
00205
00206 #define CHAN_PSEUDO -2
00207
00208 #define DCHAN_PROVISIONED (1 << 0)
00209 #define DCHAN_NOTINALARM (1 << 1)
00210 #define DCHAN_UP (1 << 2)
00211
00212 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00213
00214
00215 #define DAHDI_OVERLAPDIAL_NONE 0
00216 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00217 #define DAHDI_OVERLAPDIAL_INCOMING 2
00218 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00219
00220
00221 #define CALLPROGRESS_PROGRESS 1
00222 #define CALLPROGRESS_FAX_OUTGOING 2
00223 #define CALLPROGRESS_FAX_INCOMING 4
00224 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00225
00226 static char defaultcic[64] = "";
00227 static char defaultozz[64] = "";
00228
00229 static char parkinglot[AST_MAX_EXTENSION] = "";
00230
00231
00232 static char mwimonitornotify[PATH_MAX] = "";
00233 static int mwisend_rpas = 0;
00234
00235 static char progzone[10] = "";
00236
00237 static int usedistinctiveringdetection = 0;
00238 static int distinctiveringaftercid = 0;
00239
00240 static int numbufs = 4;
00241
00242 static int mwilevel = 512;
00243
00244 #ifdef HAVE_PRI
00245 static struct ast_channel inuse;
00246 #ifdef PRI_GETSET_TIMERS
00247 static int pritimers[PRI_MAX_TIMERS];
00248 #endif
00249 static int pridebugfd = -1;
00250 static char pridebugfilename[1024] = "";
00251 #endif
00252
00253
00254 static int firstdigittimeout = 16000;
00255
00256
00257 static int gendigittimeout = 8000;
00258
00259
00260 static int matchdigittimeout = 3000;
00261
00262
00263 AST_MUTEX_DEFINE_STATIC(iflock);
00264
00265
00266 static int ifcount = 0;
00267
00268 #ifdef HAVE_PRI
00269 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00270 #endif
00271
00272
00273
00274 AST_MUTEX_DEFINE_STATIC(monlock);
00275
00276
00277
00278 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00279 static ast_cond_t mwi_thread_complete;
00280 static ast_cond_t ss_thread_complete;
00281 AST_MUTEX_DEFINE_STATIC(mwi_thread_lock);
00282 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00283 AST_MUTEX_DEFINE_STATIC(restart_lock);
00284 static int mwi_thread_count = 0;
00285 static int ss_thread_count = 0;
00286 static int num_restart_pending = 0;
00287
00288 static int restart_monitor(void);
00289
00290 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00291
00292 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00293
00294 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00295 {
00296
00297
00298
00299
00300 }
00301
00302
00303 static inline int dahdi_get_event(int fd)
00304 {
00305 int j;
00306 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00307 return -1;
00308 return j;
00309 }
00310
00311
00312 static inline int dahdi_wait_event(int fd)
00313 {
00314 int i, j = 0;
00315 i = DAHDI_IOMUX_SIGEVENT;
00316 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00317 return -1;
00318 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00319 return -1;
00320 return j;
00321 }
00322
00323
00324 #define READ_SIZE 160
00325
00326 #define MASK_AVAIL (1 << 0)
00327 #define MASK_INUSE (1 << 1)
00328
00329 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00330 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00331 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00332 #define MIN_MS_SINCE_FLASH ( (2000) )
00333 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00334
00335 struct dahdi_pvt;
00336
00337
00338
00339
00340
00341 static int ringt_base = DEFAULT_RINGT;
00342
00343 #ifdef HAVE_SS7
00344
00345 #define LINKSTATE_INALARM (1 << 0)
00346 #define LINKSTATE_STARTING (1 << 1)
00347 #define LINKSTATE_UP (1 << 2)
00348 #define LINKSTATE_DOWN (1 << 3)
00349
00350 #define SS7_NAI_DYNAMIC -1
00351
00352 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00353
00354 struct dahdi_ss7 {
00355 pthread_t master;
00356 ast_mutex_t lock;
00357 int fds[NUM_DCHANS];
00358 int numsigchans;
00359 int linkstate[NUM_DCHANS];
00360 int numchans;
00361 int type;
00362 enum {
00363 LINKSET_STATE_DOWN = 0,
00364 LINKSET_STATE_UP
00365 } state;
00366 char called_nai;
00367 char calling_nai;
00368 char internationalprefix[10];
00369 char nationalprefix[10];
00370 char subscriberprefix[20];
00371 char unknownprefix[20];
00372 struct ss7 *ss7;
00373 struct dahdi_pvt *pvts[MAX_CHANNELS];
00374 int flags;
00375 };
00376
00377 static struct dahdi_ss7 linksets[NUM_SPANS];
00378
00379 static int cur_ss7type = -1;
00380 static int cur_linkset = -1;
00381 static int cur_pointcode = -1;
00382 static int cur_cicbeginswith = -1;
00383 static int cur_adjpointcode = -1;
00384 static int cur_networkindicator = -1;
00385 static int cur_defaultdpc = -1;
00386 #endif
00387
00388 #ifdef HAVE_PRI
00389
00390 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00391 #define PRI_CHANNEL(p) ((p) & 0xff)
00392 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00393 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00394
00395 struct dahdi_pri {
00396 pthread_t master;
00397 ast_mutex_t lock;
00398 char idleext[AST_MAX_EXTENSION];
00399 char idlecontext[AST_MAX_CONTEXT];
00400 char idledial[AST_MAX_EXTENSION];
00401 int minunused;
00402 int minidle;
00403 int nodetype;
00404 int switchtype;
00405 int nsf;
00406 int dialplan;
00407 int localdialplan;
00408 char internationalprefix[10];
00409 char nationalprefix[10];
00410 char localprefix[20];
00411 char privateprefix[20];
00412 char unknownprefix[20];
00413 int dchannels[NUM_DCHANS];
00414 int trunkgroup;
00415 int mastertrunkgroup;
00416 int prilogicalspan;
00417 int numchans;
00418 int overlapdial;
00419 int facilityenable;
00420 struct pri *dchans[NUM_DCHANS];
00421 int dchanavail[NUM_DCHANS];
00422 struct pri *pri;
00423
00424 int debug;
00425 int fds[NUM_DCHANS];
00426
00427 int offset;
00428
00429 int span;
00430
00431 int resetting;
00432
00433 int resetpos;
00434 #ifdef HAVE_PRI_INBANDDISCONNECT
00435 unsigned int inbanddisconnect:1;
00436 #endif
00437 time_t lastreset;
00438 long resetinterval;
00439
00440 int sig;
00441 struct dahdi_pvt *pvts[MAX_CHANNELS];
00442 struct dahdi_pvt *crvs;
00443 struct dahdi_pvt *crvend;
00444 };
00445
00446
00447 static struct dahdi_pri pris[NUM_SPANS];
00448
00449 #if 0
00450 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00451 #else
00452 #define DEFAULT_PRI_DEBUG 0
00453 #endif
00454
00455 static inline void pri_rel(struct dahdi_pri *pri)
00456 {
00457 ast_mutex_unlock(&pri->lock);
00458 }
00459
00460 #else
00461
00462 struct dahdi_pri;
00463 #endif
00464
00465 #define SUB_REAL 0
00466 #define SUB_CALLWAIT 1
00467 #define SUB_THREEWAY 2
00468
00469
00470 #define POLARITY_IDLE 0
00471 #define POLARITY_REV 1
00472
00473
00474 struct distRingData {
00475 int ring[3];
00476 int range;
00477 };
00478 struct ringContextData {
00479 char contextData[AST_MAX_CONTEXT];
00480 };
00481 struct dahdi_distRings {
00482 struct distRingData ringnum[3];
00483 struct ringContextData ringContext[3];
00484 };
00485
00486 static char *subnames[] = {
00487 "Real",
00488 "Callwait",
00489 "Threeway"
00490 };
00491
00492 struct dahdi_subchannel {
00493 int dfd;
00494 struct ast_channel *owner;
00495 int chan;
00496 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00497 struct ast_frame f;
00498 unsigned int needringing:1;
00499 unsigned int needbusy:1;
00500 unsigned int needcongestion:1;
00501 unsigned int needcallerid:1;
00502 unsigned int needanswer:1;
00503 unsigned int needflash:1;
00504 unsigned int needhold:1;
00505 unsigned int needunhold:1;
00506 unsigned int linear:1;
00507 unsigned int inthreeway:1;
00508 struct dahdi_confinfo curconf;
00509 };
00510
00511 #define CONF_USER_REAL (1 << 0)
00512 #define CONF_USER_THIRDCALL (1 << 1)
00513
00514 #define MAX_SLAVES 4
00515
00516 static struct dahdi_pvt {
00517 ast_mutex_t lock;
00518 struct ast_channel *owner;
00519
00520
00521 struct dahdi_subchannel sub_unused;
00522 struct dahdi_subchannel subs[3];
00523 struct dahdi_confinfo saveconf;
00524
00525 struct dahdi_pvt *slaves[MAX_SLAVES];
00526 struct dahdi_pvt *master;
00527 int inconference;
00528
00529 int buf_no;
00530 int buf_policy;
00531 int sig;
00532
00533
00534
00535
00536 int radio;
00537 int outsigmod;
00538 int oprmode;
00539 struct dahdi_pvt *oprpeer;
00540
00541 float cid_rxgain;
00542
00543 float rxgain;
00544
00545 float txgain;
00546 int tonezone;
00547 struct dahdi_pvt *next;
00548 struct dahdi_pvt *prev;
00549
00550
00551
00552
00553
00554
00555
00556 unsigned int adsi:1;
00557
00558
00559
00560
00561
00562 unsigned int answeronpolarityswitch:1;
00563
00564
00565
00566
00567
00568 unsigned int busydetect:1;
00569
00570
00571
00572
00573
00574 unsigned int callreturn:1;
00575
00576
00577
00578
00579
00580
00581 unsigned int callwaiting:1;
00582
00583
00584
00585
00586 unsigned int callwaitingcallerid:1;
00587
00588
00589
00590
00591
00592
00593 unsigned int cancallforward:1;
00594
00595
00596
00597
00598 unsigned int canpark:1;
00599
00600 unsigned int confirmanswer:1;
00601
00602
00603
00604
00605 unsigned int destroy:1;
00606 unsigned int didtdd:1;
00607
00608 unsigned int dialednone:1;
00609
00610 unsigned int dialing:1;
00611
00612 unsigned int digital:1;
00613
00614 unsigned int dnd:1;
00615
00616 unsigned int echobreak:1;
00617
00618
00619
00620
00621
00622 unsigned int echocanbridged:1;
00623
00624 unsigned int echocanon:1;
00625
00626 unsigned int faxhandled:1;
00627
00628 unsigned int firstradio:1;
00629
00630
00631
00632
00633 unsigned int hanguponpolarityswitch:1;
00634
00635 unsigned int hardwaredtmf:1;
00636
00637
00638
00639
00640
00641
00642 unsigned int hidecallerid:1;
00643
00644
00645
00646
00647
00648 unsigned int hidecalleridname:1;
00649
00650 unsigned int ignoredtmf:1;
00651
00652
00653
00654
00655
00656 unsigned int immediate:1;
00657
00658 unsigned int inalarm:1;
00659
00660 unsigned int mate:1;
00661
00662 unsigned int outgoing:1;
00663
00664
00665
00666
00667
00668
00669 unsigned int permcallwaiting:1;
00670
00671
00672
00673
00674 unsigned int permhidecallerid:1;
00675
00676
00677
00678
00679 unsigned int priindication_oob:1;
00680
00681
00682
00683
00684 unsigned int priexclusive:1;
00685
00686
00687
00688
00689 unsigned int pulse:1;
00690
00691 unsigned int pulsedial:1;
00692 unsigned int restartpending:1;
00693
00694
00695
00696
00697
00698 unsigned int restrictcid:1;
00699
00700
00701
00702
00703 unsigned int threewaycalling:1;
00704
00705
00706
00707
00708
00709
00710
00711
00712 unsigned int transfer:1;
00713
00714
00715
00716
00717
00718
00719
00720 unsigned int use_callerid:1;
00721
00722
00723
00724
00725
00726
00727 unsigned int use_callingpres:1;
00728
00729
00730
00731
00732
00733 unsigned int usedistinctiveringdetection:1;
00734
00735
00736
00737
00738 unsigned int dahditrcallerid:1;
00739
00740
00741
00742
00743 unsigned int transfertobusy:1;
00744
00745
00746
00747
00748 unsigned int mwimonitor_neon:1;
00749
00750
00751
00752
00753 unsigned int mwimonitor_fsk:1;
00754
00755
00756
00757
00758
00759 unsigned int mwimonitor_rpas:1;
00760
00761 unsigned int mwimonitoractive:1;
00762
00763 unsigned int mwisendactive:1;
00764
00765
00766
00767
00768 unsigned int inservice:1;
00769
00770
00771
00772
00773 unsigned int locallyblocked:1;
00774
00775
00776
00777
00778 unsigned int remotelyblocked:1;
00779 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00780
00781
00782
00783
00784 unsigned int rlt:1;
00785
00786 unsigned int alerting:1;
00787
00788 unsigned int alreadyhungup:1;
00789
00790
00791
00792
00793 unsigned int isidlecall:1;
00794
00795
00796
00797
00798 unsigned int proceeding:1;
00799
00800 unsigned int progress:1;
00801
00802
00803
00804
00805 unsigned int resetting:1;
00806
00807
00808
00809
00810 unsigned int setup_ack:1;
00811 #endif
00812
00813
00814
00815
00816 unsigned int use_smdi:1;
00817
00818 struct ast_smdi_interface *smdi_iface;
00819
00820
00821 struct dahdi_distRings drings;
00822
00823
00824
00825
00826
00827 char context[AST_MAX_CONTEXT];
00828
00829
00830
00831 char defcontext[AST_MAX_CONTEXT];
00832
00833 char exten[AST_MAX_EXTENSION];
00834
00835
00836
00837
00838 char language[MAX_LANGUAGE];
00839
00840
00841
00842
00843 char mohinterpret[MAX_MUSICCLASS];
00844
00845
00846
00847
00848 char mohsuggest[MAX_MUSICCLASS];
00849 char parkinglot[AST_MAX_EXTENSION];
00850 #if defined(PRI_ANI) || defined(HAVE_SS7)
00851
00852 char cid_ani[AST_MAX_EXTENSION];
00853 #endif
00854
00855 int cid_ani2;
00856
00857 char cid_num[AST_MAX_EXTENSION];
00858
00859 int cid_ton;
00860
00861 char cid_name[AST_MAX_EXTENSION];
00862
00863 char lastcid_num[AST_MAX_EXTENSION];
00864
00865 char lastcid_name[AST_MAX_EXTENSION];
00866 char *origcid_num;
00867 char *origcid_name;
00868
00869 char callwait_num[AST_MAX_EXTENSION];
00870
00871 char callwait_name[AST_MAX_EXTENSION];
00872
00873 char rdnis[AST_MAX_EXTENSION];
00874
00875 char dnid[AST_MAX_EXTENSION];
00876
00877
00878
00879
00880 ast_group_t group;
00881
00882 int law;
00883 int confno;
00884 int confusers;
00885 int propconfno;
00886
00887
00888
00889
00890 ast_group_t callgroup;
00891
00892
00893
00894
00895 ast_group_t pickupgroup;
00896
00897
00898
00899
00900 struct ast_variable *vars;
00901 int channel;
00902 int span;
00903 time_t guardtime;
00904 int cid_signalling;
00905 int cid_start;
00906 int callingpres;
00907 int callwaitingrepeat;
00908 int cidcwexpire;
00909
00910 unsigned char *cidspill;
00911
00912 int cidpos;
00913
00914 int cidlen;
00915
00916 int ringt;
00917
00918
00919
00920
00921 int ringt_base;
00922
00923
00924
00925
00926
00927
00928 int stripmsd;
00929
00930 int callwaitcas;
00931
00932 int callwaitrings;
00933
00934 struct {
00935 struct dahdi_echocanparams head;
00936 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
00937 } echocancel;
00938
00939
00940
00941
00942 int echotraining;
00943
00944 char echorest[20];
00945
00946
00947
00948
00949 int busycount;
00950
00951
00952
00953
00954 int busy_tonelength;
00955
00956
00957
00958
00959 int busy_quietlength;
00960
00961
00962
00963
00964 int callprogress;
00965 struct timeval flashtime;
00966
00967 struct ast_dsp *dsp;
00968
00969
00970 struct dahdi_dialoperation dop;
00971 int whichwink;
00972
00973 char finaldial[64];
00974 char accountcode[AST_MAX_ACCOUNT_CODE];
00975 int amaflags;
00976 struct tdd_state *tdd;
00977
00978 char call_forward[AST_MAX_EXTENSION];
00979
00980
00981
00982
00983 char mailbox[AST_MAX_EXTENSION];
00984
00985 struct ast_event_sub *mwi_event_sub;
00986
00987 char dialdest[256];
00988
00989 int onhooktime;
00990
00991 int msgstate;
00992 int distinctivering;
00993 int cidrings;
00994 int dtmfrelax;
00995
00996 int fake_event;
00997
00998
00999
01000
01001 int polarityonanswerdelay;
01002
01003 struct timeval polaritydelaytv;
01004
01005
01006
01007
01008 int sendcalleridafter;
01009 #ifdef HAVE_PRI
01010
01011 struct dahdi_pri *pri;
01012
01013 struct dahdi_pvt *bearer;
01014
01015 struct dahdi_pvt *realcall;
01016
01017 q931_call *call;
01018
01019 int prioffset;
01020
01021 int logicalspan;
01022 #endif
01023
01024 int polarity;
01025
01026 int dsp_features;
01027 #ifdef HAVE_SS7
01028
01029 struct dahdi_ss7 *ss7;
01030
01031 struct isup_call *ss7call;
01032 char charge_number[50];
01033 char gen_add_number[50];
01034 char gen_dig_number[50];
01035 char orig_called_num[50];
01036 char redirecting_num[50];
01037 char generic_name[50];
01038 unsigned char gen_add_num_plan;
01039 unsigned char gen_add_nai;
01040 unsigned char gen_add_pres_ind;
01041 unsigned char gen_add_type;
01042 unsigned char gen_dig_type;
01043 unsigned char gen_dig_scheme;
01044 char jip_number[50];
01045 unsigned char lspi_type;
01046 unsigned char lspi_scheme;
01047 unsigned char lspi_context;
01048 char lspi_ident[50];
01049 unsigned int call_ref_ident;
01050 unsigned int call_ref_pc;
01051 unsigned char calling_party_cat;
01052 int transcap;
01053 int cic;
01054 unsigned int dpc;
01055 unsigned int loopedback:1;
01056 #endif
01057
01058 char begindigit;
01059
01060 int muting;
01061 } *iflist = NULL, *ifend = NULL;
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 struct dahdi_chan_conf {
01074 struct dahdi_pvt chan;
01075 #ifdef HAVE_PRI
01076 struct dahdi_pri pri;
01077 #endif
01078
01079 #ifdef HAVE_SS7
01080 struct dahdi_ss7 ss7;
01081 #endif
01082 struct dahdi_params timing;
01083 int is_sig_auto;
01084
01085
01086
01087
01088
01089 char smdi_port[SMDI_MAX_FILENAME_LEN];
01090 };
01091
01092
01093 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01094
01095
01096
01097 struct dahdi_chan_conf conf = {
01098 #ifdef HAVE_PRI
01099 .pri = {
01100 .nsf = PRI_NSF_NONE,
01101 .switchtype = PRI_SWITCH_NI2,
01102 .dialplan = PRI_UNKNOWN + 1,
01103 .localdialplan = PRI_NATIONAL_ISDN + 1,
01104 .nodetype = PRI_CPE,
01105
01106 .minunused = 2,
01107 .idleext = "",
01108 .idledial = "",
01109 .internationalprefix = "",
01110 .nationalprefix = "",
01111 .localprefix = "",
01112 .privateprefix = "",
01113 .unknownprefix = "",
01114 .resetinterval = -1,
01115 },
01116 #endif
01117 #ifdef HAVE_SS7
01118 .ss7 = {
01119 .called_nai = SS7_NAI_NATIONAL,
01120 .calling_nai = SS7_NAI_NATIONAL,
01121 .internationalprefix = "",
01122 .nationalprefix = "",
01123 .subscriberprefix = "",
01124 .unknownprefix = ""
01125 },
01126 #endif
01127 .chan = {
01128 .context = "default",
01129 .cid_num = "",
01130 .cid_name = "",
01131 .mohinterpret = "default",
01132 .mohsuggest = "",
01133 .parkinglot = "",
01134 .transfertobusy = 1,
01135
01136 .cid_signalling = CID_SIG_BELL,
01137 .cid_start = CID_START_RING,
01138 .dahditrcallerid = 0,
01139 .use_callerid = 1,
01140 .sig = -1,
01141 .outsigmod = -1,
01142
01143 .cid_rxgain = +5.0,
01144
01145 .tonezone = -1,
01146
01147 .echocancel.head.tap_length = 1,
01148
01149 .busycount = 3,
01150
01151 .accountcode = "",
01152
01153 .mailbox = "",
01154
01155
01156 .polarityonanswerdelay = 600,
01157
01158 .sendcalleridafter = DEFAULT_CIDRINGS,
01159
01160 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01161 .buf_no = numbufs
01162 },
01163 .timing = {
01164 .prewinktime = -1,
01165 .preflashtime = -1,
01166 .winktime = -1,
01167 .flashtime = -1,
01168 .starttime = -1,
01169 .rxwinktime = -1,
01170 .rxflashtime = -1,
01171 .debouncetime = -1
01172 },
01173 .is_sig_auto = 1,
01174 .smdi_port = "/dev/ttyS0",
01175 };
01176
01177 return conf;
01178 }
01179
01180
01181 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01182 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01183 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01184 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01185 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01186 static int dahdi_hangup(struct ast_channel *ast);
01187 static int dahdi_answer(struct ast_channel *ast);
01188 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01189 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01190 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01191 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01192 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01193 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01194 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01195 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01196
01197 static const struct ast_channel_tech dahdi_tech = {
01198 .type = "DAHDI",
01199 .description = tdesc,
01200 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01201 .requester = dahdi_request,
01202 .send_digit_begin = dahdi_digit_begin,
01203 .send_digit_end = dahdi_digit_end,
01204 .send_text = dahdi_sendtext,
01205 .call = dahdi_call,
01206 .hangup = dahdi_hangup,
01207 .answer = dahdi_answer,
01208 .read = dahdi_read,
01209 .write = dahdi_write,
01210 .bridge = dahdi_bridge,
01211 .exception = dahdi_exception,
01212 .indicate = dahdi_indicate,
01213 .fixup = dahdi_fixup,
01214 .setoption = dahdi_setoption,
01215 .func_channel_read = dahdi_func_read,
01216 };
01217
01218 #ifdef HAVE_PRI
01219 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01220 #else
01221 #define GET_CHANNEL(p) ((p)->channel)
01222 #endif
01223
01224 struct dahdi_pvt *round_robin[32];
01225
01226 #ifdef HAVE_PRI
01227 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01228 {
01229 int res;
01230
01231 do {
01232 res = ast_mutex_trylock(&pri->lock);
01233 if (res) {
01234 DEADLOCK_AVOIDANCE(&pvt->lock);
01235 }
01236 } while (res);
01237
01238 if (pri->master != AST_PTHREADT_NULL)
01239 pthread_kill(pri->master, SIGURG);
01240 return 0;
01241 }
01242 #endif
01243
01244 #ifdef HAVE_SS7
01245 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01246 {
01247 ast_mutex_unlock(&ss7->lock);
01248 }
01249
01250 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01251 {
01252 int res;
01253
01254 do {
01255 res = ast_mutex_trylock(&pri->lock);
01256 if (res) {
01257 DEADLOCK_AVOIDANCE(&pvt->lock);
01258 }
01259 } while (res);
01260
01261 if (pri->master != AST_PTHREADT_NULL)
01262 pthread_kill(pri->master, SIGURG);
01263 return 0;
01264 }
01265 #endif
01266 #define NUM_CADENCE_MAX 25
01267 static int num_cadence = 4;
01268 static int user_has_defined_cadences = 0;
01269
01270 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01271 { { 125, 125, 2000, 4000 } },
01272 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01273 { { 125, 125, 125, 125, 125, 4000 } },
01274 { { 1000, 500, 2500, 5000 } },
01275 };
01276
01277
01278
01279
01280
01281 static int cidrings[NUM_CADENCE_MAX] = {
01282 2,
01283 4,
01284 3,
01285 2,
01286 };
01287
01288
01289 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01290
01291 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01292 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01293
01294 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01295 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01296
01297 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01298 {
01299 int res;
01300 if (p->subs[SUB_REAL].owner == ast)
01301 res = 0;
01302 else if (p->subs[SUB_CALLWAIT].owner == ast)
01303 res = 1;
01304 else if (p->subs[SUB_THREEWAY].owner == ast)
01305 res = 2;
01306 else {
01307 res = -1;
01308 if (!nullok)
01309 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01310 }
01311 return res;
01312 }
01313
01314 #ifdef HAVE_PRI
01315 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01316 #else
01317 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01318 #endif
01319 {
01320 #ifdef HAVE_PRI
01321 if (pri)
01322 ast_mutex_unlock(&pri->lock);
01323 #endif
01324 for (;;) {
01325 if (p->subs[a].owner) {
01326 if (ast_channel_trylock(p->subs[a].owner)) {
01327 DEADLOCK_AVOIDANCE(&p->lock);
01328 } else {
01329 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01330 ast_channel_unlock(p->subs[a].owner);
01331 break;
01332 }
01333 } else
01334 break;
01335 }
01336 #ifdef HAVE_PRI
01337 if (pri)
01338 ast_mutex_lock(&pri->lock);
01339 #endif
01340 }
01341
01342 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01343 {
01344 #ifdef HAVE_PRI
01345 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01346 #endif
01347 #ifdef HAVE_SS7
01348 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01349 #endif
01350
01351 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01352 if (data) {
01353 switch (p->sig) {
01354 #ifdef HAVE_PRI
01355 case SIG_BRI:
01356 case SIG_BRI_PTMP:
01357 case SIG_PRI:
01358 ast_mutex_unlock(&pri->lock);
01359 break;
01360 #endif
01361 #ifdef HAVE_SS7
01362 case SIG_SS7:
01363 ast_mutex_unlock(&ss7->lock);
01364 break;
01365 #endif
01366 default:
01367 break;
01368 }
01369 }
01370 #endif
01371 for (;;) {
01372 if (p->owner) {
01373 if (ast_channel_trylock(p->owner)) {
01374 DEADLOCK_AVOIDANCE(&p->lock);
01375 } else {
01376 ast_queue_frame(p->owner, f);
01377 ast_channel_unlock(p->owner);
01378 break;
01379 }
01380 } else
01381 break;
01382 }
01383 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01384 if (data) {
01385 switch (p->sig) {
01386 #ifdef HAVE_PRI
01387 case SIG_BRI:
01388 case SIG_BRI_PTMP:
01389 case SIG_PRI:
01390 ast_mutex_lock(&pri->lock);
01391 break;
01392 #endif
01393 #ifdef HAVE_SS7
01394 case SIG_SS7:
01395 ast_mutex_lock(&ss7->lock);
01396 break;
01397 #endif
01398 default:
01399 break;
01400 }
01401 }
01402
01403 #endif
01404 }
01405
01406 static int restore_gains(struct dahdi_pvt *p);
01407
01408 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01409 {
01410 int tchan;
01411 int tinthreeway;
01412 struct ast_channel *towner;
01413
01414 ast_debug(1, "Swapping %d and %d\n", a, b);
01415
01416 tchan = p->subs[a].chan;
01417 towner = p->subs[a].owner;
01418 tinthreeway = p->subs[a].inthreeway;
01419
01420 p->subs[a].chan = p->subs[b].chan;
01421 p->subs[a].owner = p->subs[b].owner;
01422 p->subs[a].inthreeway = p->subs[b].inthreeway;
01423
01424 p->subs[b].chan = tchan;
01425 p->subs[b].owner = towner;
01426 p->subs[b].inthreeway = tinthreeway;
01427
01428 if (p->subs[a].owner)
01429 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01430 if (p->subs[b].owner)
01431 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01432 wakeup_sub(p, a, NULL);
01433 wakeup_sub(p, b, NULL);
01434 }
01435
01436 static int dahdi_open(char *fn)
01437 {
01438 int fd;
01439 int isnum;
01440 int chan = 0;
01441 int bs;
01442 int x;
01443 isnum = 1;
01444 for (x = 0; x < strlen(fn); x++) {
01445 if (!isdigit(fn[x])) {
01446 isnum = 0;
01447 break;
01448 }
01449 }
01450 if (isnum) {
01451 chan = atoi(fn);
01452 if (chan < 1) {
01453 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01454 return -1;
01455 }
01456 fn = "/dev/dahdi/channel";
01457 }
01458 fd = open(fn, O_RDWR | O_NONBLOCK);
01459 if (fd < 0) {
01460 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01461 return -1;
01462 }
01463 if (chan) {
01464 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01465 x = errno;
01466 close(fd);
01467 errno = x;
01468 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01469 return -1;
01470 }
01471 }
01472 bs = READ_SIZE;
01473 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01474 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01475 x = errno;
01476 close(fd);
01477 errno = x;
01478 return -1;
01479 }
01480 return fd;
01481 }
01482
01483 static void dahdi_close(int fd)
01484 {
01485 if (fd > 0)
01486 close(fd);
01487 }
01488
01489 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01490 {
01491 dahdi_close(chan_pvt->subs[sub_num].dfd);
01492 chan_pvt->subs[sub_num].dfd = -1;
01493 }
01494
01495 #ifdef HAVE_PRI
01496 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01497 {
01498 dahdi_close(pri->fds[fd_num]);
01499 pri->fds[fd_num] = -1;
01500 }
01501 #endif
01502
01503 #ifdef HAVE_SS7
01504 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
01505 {
01506 dahdi_close(ss7->fds[fd_num]);
01507 ss7->fds[fd_num] = -1;
01508 }
01509 #endif
01510
01511 static int dahdi_setlinear(int dfd, int linear)
01512 {
01513 int res;
01514 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01515 if (res)
01516 return res;
01517 return 0;
01518 }
01519
01520
01521 static int alloc_sub(struct dahdi_pvt *p, int x)
01522 {
01523 struct dahdi_bufferinfo bi;
01524 int res;
01525 if (p->subs[x].dfd >= 0) {
01526 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01527 return -1;
01528 }
01529
01530 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01531 if (p->subs[x].dfd <= -1) {
01532 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01533 return -1;
01534 }
01535
01536 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01537 if (!res) {
01538 bi.txbufpolicy = p->buf_policy;
01539 bi.rxbufpolicy = p->buf_policy;
01540 bi.numbufs = p->buf_no;
01541 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01542 if (res < 0) {
01543 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01544 }
01545 } else
01546 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01547
01548 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01549 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01550 dahdi_close_sub(p, x);
01551 p->subs[x].dfd = -1;
01552 return -1;
01553 }
01554 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01555 return 0;
01556 }
01557
01558 static int unalloc_sub(struct dahdi_pvt *p, int x)
01559 {
01560 if (!x) {
01561 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01562 return -1;
01563 }
01564 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01565 dahdi_close_sub(p, x);
01566 p->subs[x].linear = 0;
01567 p->subs[x].chan = 0;
01568 p->subs[x].owner = NULL;
01569 p->subs[x].inthreeway = 0;
01570 p->polarity = POLARITY_IDLE;
01571 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01572 return 0;
01573 }
01574
01575 static int digit_to_dtmfindex(char digit)
01576 {
01577 if (isdigit(digit))
01578 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01579 else if (digit >= 'A' && digit <= 'D')
01580 return DAHDI_TONE_DTMF_A + (digit - 'A');
01581 else if (digit >= 'a' && digit <= 'd')
01582 return DAHDI_TONE_DTMF_A + (digit - 'a');
01583 else if (digit == '*')
01584 return DAHDI_TONE_DTMF_s;
01585 else if (digit == '#')
01586 return DAHDI_TONE_DTMF_p;
01587 else
01588 return -1;
01589 }
01590
01591 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01592 {
01593 struct dahdi_pvt *pvt;
01594 int idx;
01595 int dtmf = -1;
01596
01597 pvt = chan->tech_pvt;
01598
01599 ast_mutex_lock(&pvt->lock);
01600
01601 idx = dahdi_get_index(chan, pvt, 0);
01602
01603 if ((idx != SUB_REAL) || !pvt->owner)
01604 goto out;
01605
01606 #ifdef HAVE_PRI
01607 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01608 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01609 if (pvt->setup_ack) {
01610 if (!pri_grab(pvt, pvt->pri)) {
01611 pri_information(pvt->pri->pri, pvt->call, digit);
01612 pri_rel(pvt->pri);
01613 } else
01614 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01615 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01616 int res;
01617 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01618 res = strlen(pvt->dialdest);
01619 pvt->dialdest[res++] = digit;
01620 pvt->dialdest[res] = '\0';
01621 }
01622 goto out;
01623 }
01624 #endif
01625 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01626 goto out;
01627
01628 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01629 int res;
01630 struct dahdi_dialoperation zo = {
01631 .op = DAHDI_DIAL_OP_APPEND,
01632 };
01633
01634 zo.dialstr[0] = 'T';
01635 zo.dialstr[1] = digit;
01636 zo.dialstr[2] = '\0';
01637 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01638 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01639 else
01640 pvt->dialing = 1;
01641 } else {
01642 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01643 pvt->dialing = 1;
01644 pvt->begindigit = digit;
01645 }
01646
01647 out:
01648 ast_mutex_unlock(&pvt->lock);
01649
01650 return 0;
01651 }
01652
01653 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01654 {
01655 struct dahdi_pvt *pvt;
01656 int res = 0;
01657 int idx;
01658 int x;
01659
01660 pvt = chan->tech_pvt;
01661
01662 ast_mutex_lock(&pvt->lock);
01663
01664 idx = dahdi_get_index(chan, pvt, 0);
01665
01666 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
01667 goto out;
01668
01669 #ifdef HAVE_PRI
01670
01671 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01672 && !pvt->begindigit)
01673 goto out;
01674 #endif
01675
01676 if (pvt->begindigit) {
01677 x = -1;
01678 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01679 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01680 pvt->dialing = 0;
01681 pvt->begindigit = 0;
01682 }
01683
01684 out:
01685 ast_mutex_unlock(&pvt->lock);
01686
01687 return res;
01688 }
01689
01690 static char *events[] = {
01691 "No event",
01692 "On hook",
01693 "Ring/Answered",
01694 "Wink/Flash",
01695 "Alarm",
01696 "No more alarm",
01697 "HDLC Abort",
01698 "HDLC Overrun",
01699 "HDLC Bad FCS",
01700 "Dial Complete",
01701 "Ringer On",
01702 "Ringer Off",
01703 "Hook Transition Complete",
01704 "Bits Changed",
01705 "Pulse Start",
01706 "Timer Expired",
01707 "Timer Ping",
01708 "Polarity Reversal",
01709 "Ring Begin",
01710 };
01711
01712 static struct {
01713 int alarm;
01714 char *name;
01715 } alarms[] = {
01716 { DAHDI_ALARM_RED, "Red Alarm" },
01717 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01718 { DAHDI_ALARM_BLUE, "Blue Alarm" },
01719 { DAHDI_ALARM_RECOVER, "Recovering" },
01720 { DAHDI_ALARM_LOOPBACK, "Loopback" },
01721 { DAHDI_ALARM_NOTOPEN, "Not Open" },
01722 { DAHDI_ALARM_NONE, "None" },
01723 };
01724
01725 static char *alarm2str(int alm)
01726 {
01727 int x;
01728 for (x = 0; x < ARRAY_LEN(alarms); x++) {
01729 if (alarms[x].alarm & alm)
01730 return alarms[x].name;
01731 }
01732 return alm ? "Unknown Alarm" : "No Alarm";
01733 }
01734
01735 static char *event2str(int event)
01736 {
01737 static char buf[256];
01738 if ((event < (ARRAY_LEN(events))) && (event > -1))
01739 return events[event];
01740 sprintf(buf, "Event %d", event);
01741 return buf;
01742 }
01743
01744 #ifdef HAVE_PRI
01745 static char *dialplan2str(int dialplan)
01746 {
01747 if (dialplan == -1 || dialplan == -2) {
01748 return("Dynamically set dialplan in ISDN");
01749 }
01750 return (pri_plan2str(dialplan));
01751 }
01752 #endif
01753
01754 static char *dahdi_sig2str(int sig)
01755 {
01756 static char buf[256];
01757 switch (sig) {
01758 case SIG_EM:
01759 return "E & M Immediate";
01760 case SIG_EMWINK:
01761 return "E & M Wink";
01762 case SIG_EM_E1:
01763 return "E & M E1";
01764 case SIG_FEATD:
01765 return "Feature Group D (DTMF)";
01766 case SIG_FEATDMF:
01767 return "Feature Group D (MF)";
01768 case SIG_FEATDMF_TA:
01769 return "Feature Groud D (MF) Tandem Access";
01770 case SIG_FEATB:
01771 return "Feature Group B (MF)";
01772 case SIG_E911:
01773 return "E911 (MF)";
01774 case SIG_FGC_CAMA:
01775 return "FGC/CAMA (Dialpulse)";
01776 case SIG_FGC_CAMAMF:
01777 return "FGC/CAMA (MF)";
01778 case SIG_FXSLS:
01779 return "FXS Loopstart";
01780 case SIG_FXSGS:
01781 return "FXS Groundstart";
01782 case SIG_FXSKS:
01783 return "FXS Kewlstart";
01784 case SIG_FXOLS:
01785 return "FXO Loopstart";
01786 case SIG_FXOGS:
01787 return "FXO Groundstart";
01788 case SIG_FXOKS:
01789 return "FXO Kewlstart";
01790 case SIG_PRI:
01791 return "ISDN PRI";
01792 case SIG_BRI:
01793 return "ISDN BRI Point to Point";
01794 case SIG_BRI_PTMP:
01795 return "ISDN BRI Point to MultiPoint";
01796 case SIG_SS7:
01797 return "SS7";
01798 case SIG_SF:
01799 return "SF (Tone) Immediate";
01800 case SIG_SFWINK:
01801 return "SF (Tone) Wink";
01802 case SIG_SF_FEATD:
01803 return "SF (Tone) with Feature Group D (DTMF)";
01804 case SIG_SF_FEATDMF:
01805 return "SF (Tone) with Feature Group D (MF)";
01806 case SIG_SF_FEATB:
01807 return "SF (Tone) with Feature Group B (MF)";
01808 case SIG_GR303FXOKS:
01809 return "GR-303 with FXOKS";
01810 case SIG_GR303FXSKS:
01811 return "GR-303 with FXSKS";
01812 case 0:
01813 return "Pseudo";
01814 default:
01815 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01816 return buf;
01817 }
01818 }
01819
01820 #define sig2str dahdi_sig2str
01821
01822 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
01823 {
01824
01825
01826 struct dahdi_confinfo zi;
01827
01828 memset(&zi, 0, sizeof(zi));
01829 zi.chan = 0;
01830
01831 if (slavechannel > 0) {
01832
01833 zi.confmode = DAHDI_CONF_DIGITALMON;
01834 zi.confno = slavechannel;
01835 } else {
01836 if (!idx) {
01837
01838 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01839 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01840 } else
01841 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01842 zi.confno = p->confno;
01843 }
01844 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01845 return 0;
01846 if (c->dfd < 0)
01847 return 0;
01848 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01849 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01850 return -1;
01851 }
01852 if (slavechannel < 1) {
01853 p->confno = zi.confno;
01854 }
01855 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01856 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01857 return 0;
01858 }
01859
01860 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01861 {
01862
01863 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01864 return 1;
01865
01866 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01867 return 1;
01868 return 0;
01869 }
01870
01871 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
01872 {
01873 struct dahdi_confinfo zi;
01874 if (
01875 (c->dfd < 0) ||
01876
01877 !isourconf(p, c)
01878
01879 ) return 0;
01880 memset(&zi, 0, sizeof(zi));
01881 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01882 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01883 return -1;
01884 }
01885 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01886 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01887 return 0;
01888 }
01889
01890 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01891 {
01892 int x;
01893 int useslavenative;
01894 struct dahdi_pvt *slave = NULL;
01895
01896 useslavenative = 1;
01897
01898 for (x = 0; x < 3; x++) {
01899
01900
01901 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01902 useslavenative = 0;
01903 }
01904
01905
01906 if (useslavenative) {
01907 for (x = 0; x < MAX_SLAVES; x++) {
01908 if (p->slaves[x]) {
01909 if (slave) {
01910
01911
01912 slave = NULL;
01913 useslavenative = 0;
01914 break;
01915 } else {
01916
01917 slave = p->slaves[x];
01918 }
01919 }
01920 }
01921 }
01922
01923 if (!slave)
01924 useslavenative = 0;
01925 else if (slave->law != p->law) {
01926 useslavenative = 0;
01927 slave = NULL;
01928 }
01929 if (out)
01930 *out = slave;
01931 return useslavenative;
01932 }
01933
01934 static int reset_conf(struct dahdi_pvt *p)
01935 {
01936 p->confno = -1;
01937 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01938 if (p->subs[SUB_REAL].dfd > -1) {
01939 struct dahdi_confinfo zi;
01940
01941 memset(&zi, 0, sizeof(zi));
01942 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01943 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01944 }
01945 return 0;
01946 }
01947
01948 static int update_conf(struct dahdi_pvt *p)
01949 {
01950 int needconf = 0;
01951 int x;
01952 int useslavenative;
01953 struct dahdi_pvt *slave = NULL;
01954
01955 useslavenative = isslavenative(p, &slave);
01956
01957 for (x = 0; x < 3; x++) {
01958
01959 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01960 conf_add(p, &p->subs[x], x, 0);
01961 needconf++;
01962 } else {
01963 conf_del(p, &p->subs[x], x);
01964 }
01965 }
01966
01967
01968 for (x = 0; x < MAX_SLAVES; x++) {
01969 if (p->slaves[x]) {
01970 if (useslavenative)
01971 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01972 else {
01973 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01974 needconf++;
01975 }
01976 }
01977 }
01978
01979 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01980 if (useslavenative)
01981 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01982 else {
01983 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01984 needconf++;
01985 }
01986 }
01987
01988 if (p->master) {
01989 if (isslavenative(p->master, NULL)) {
01990 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01991 } else {
01992 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01993 }
01994 }
01995 if (!needconf) {
01996
01997
01998 p->confno = -1;
01999 }
02000 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02001 return 0;
02002 }
02003
02004 static void dahdi_enable_ec(struct dahdi_pvt *p)
02005 {
02006 int x;
02007 int res;
02008 if (!p)
02009 return;
02010 if (p->echocanon) {
02011 ast_debug(1, "Echo cancellation already on\n");
02012 return;
02013 }
02014 if (p->digital) {
02015 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02016 return;
02017 }
02018 if (p->echocancel.head.tap_length) {
02019 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02020 x = 1;
02021 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02022 if (res)
02023 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02024 }
02025 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02026 if (res) {
02027 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02028 } else {
02029 p->echocanon = 1;
02030 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02031 }
02032 } else
02033 ast_debug(1, "No echo cancellation requested\n");
02034 }
02035
02036 static void dahdi_train_ec(struct dahdi_pvt *p)
02037 {
02038 int x;
02039 int res;
02040
02041 if (p && p->echocanon && p->echotraining) {
02042 x = p->echotraining;
02043 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02044 if (res)
02045 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02046 else
02047 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02048 } else {
02049 ast_debug(1, "No echo training requested\n");
02050 }
02051 }
02052
02053 static void dahdi_disable_ec(struct dahdi_pvt *p)
02054 {
02055 int res;
02056
02057 if (p->echocanon) {
02058 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02059
02060 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02061
02062 if (res)
02063 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02064 else
02065 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02066 }
02067
02068 p->echocanon = 0;
02069 }
02070
02071 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02072 {
02073 int j;
02074 int k;
02075 float linear_gain = pow(10.0, gain / 20.0);
02076
02077 switch (law) {
02078 case DAHDI_LAW_ALAW:
02079 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02080 if (gain) {
02081 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02082 if (k > 32767) k = 32767;
02083 if (k < -32767) k = -32767;
02084 g->txgain[j] = AST_LIN2A(k);
02085 } else {
02086 g->txgain[j] = j;
02087 }
02088 }
02089 break;
02090 case DAHDI_LAW_MULAW:
02091 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02092 if (gain) {
02093 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02094 if (k > 32767) k = 32767;
02095 if (k < -32767) k = -32767;
02096 g->txgain[j] = AST_LIN2MU(k);
02097 } else {
02098 g->txgain[j] = j;
02099 }
02100 }
02101 break;
02102 }
02103 }
02104
02105 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02106 {
02107 int j;
02108 int k;
02109 float linear_gain = pow(10.0, gain / 20.0);
02110
02111 switch (law) {
02112 case DAHDI_LAW_ALAW:
02113 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02114 if (gain) {
02115 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02116 if (k > 32767) k = 32767;
02117 if (k < -32767) k = -32767;
02118 g->rxgain[j] = AST_LIN2A(k);
02119 } else {
02120 g->rxgain[j] = j;
02121 }
02122 }
02123 break;
02124 case DAHDI_LAW_MULAW:
02125 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02126 if (gain) {
02127 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02128 if (k > 32767) k = 32767;
02129 if (k < -32767) k = -32767;
02130 g->rxgain[j] = AST_LIN2MU(k);
02131 } else {
02132 g->rxgain[j] = j;
02133 }
02134 }
02135 break;
02136 }
02137 }
02138
02139 static int set_actual_txgain(int fd, int chan, float gain, int law)
02140 {
02141 struct dahdi_gains g;
02142 int res;
02143
02144 memset(&g, 0, sizeof(g));
02145 g.chan = chan;
02146 res = ioctl(fd, DAHDI_GETGAINS, &g);
02147 if (res) {
02148 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02149 return res;
02150 }
02151
02152 fill_txgain(&g, gain, law);
02153
02154 return ioctl(fd, DAHDI_SETGAINS, &g);
02155 }
02156
02157 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02158 {
02159 struct dahdi_gains g;
02160 int res;
02161
02162 memset(&g, 0, sizeof(g));
02163 g.chan = chan;
02164 res = ioctl(fd, DAHDI_GETGAINS, &g);
02165 if (res) {
02166 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02167 return res;
02168 }
02169
02170 fill_rxgain(&g, gain, law);
02171
02172 return ioctl(fd, DAHDI_SETGAINS, &g);
02173 }
02174
02175 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02176 {
02177 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02178 }
02179
02180 static int bump_gains(struct dahdi_pvt *p)
02181 {
02182 int res;
02183
02184
02185 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02186 if (res) {
02187 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02188 return -1;
02189 }
02190
02191 return 0;
02192 }
02193
02194 static int restore_gains(struct dahdi_pvt *p)
02195 {
02196 int res;
02197
02198 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02199 if (res) {
02200 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02201 return -1;
02202 }
02203
02204 return 0;
02205 }
02206
02207 static inline int dahdi_set_hook(int fd, int hs)
02208 {
02209 int x, res;
02210
02211 x = hs;
02212 res = ioctl(fd, DAHDI_HOOK, &x);
02213
02214 if (res < 0) {
02215 if (errno == EINPROGRESS)
02216 return 0;
02217 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02218
02219 }
02220
02221 return res;
02222 }
02223
02224 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02225 {
02226 int x, y, res;
02227 x = muted;
02228 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02229 y = 1;
02230 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02231 if (res)
02232 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02233 }
02234 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02235 if (res < 0)
02236 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02237 return res;
02238 }
02239
02240 static int save_conference(struct dahdi_pvt *p)
02241 {
02242 struct dahdi_confinfo c;
02243 int res;
02244 if (p->saveconf.confmode) {
02245 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02246 return -1;
02247 }
02248 p->saveconf.chan = 0;
02249 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02250 if (res) {
02251 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02252 p->saveconf.confmode = 0;
02253 return -1;
02254 }
02255 memset(&c, 0, sizeof(c));
02256 c.confmode = DAHDI_CONF_NORMAL;
02257 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02258 if (res) {
02259 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02260 return -1;
02261 }
02262 ast_debug(1, "Disabled conferencing\n");
02263 return 0;
02264 }
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284 static void notify_message(char *mailbox_full, int thereornot)
02285 {
02286 char s[sizeof(mwimonitornotify) + 80];
02287 struct ast_event *event;
02288 char *mailbox, *context;
02289
02290
02291 context = mailbox = ast_strdupa(mailbox_full);
02292 strsep(&context, "@");
02293 if (ast_strlen_zero(context))
02294 context = "default";
02295
02296 if (!(event = ast_event_new(AST_EVENT_MWI,
02297 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02298 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02299 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02300 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02301 AST_EVENT_IE_END))) {
02302 return;
02303 }
02304
02305 ast_event_queue_and_cache(event);
02306
02307 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02308 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02309 ast_safe_system(s);
02310 }
02311 }
02312
02313 static int restore_conference(struct dahdi_pvt *p)
02314 {
02315 int res;
02316 if (p->saveconf.confmode) {
02317 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02318 p->saveconf.confmode = 0;
02319 if (res) {
02320 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02321 return -1;
02322 }
02323 }
02324 ast_debug(1, "Restored conferencing\n");
02325 return 0;
02326 }
02327
02328 static int send_callerid(struct dahdi_pvt *p);
02329
02330 static int send_cwcidspill(struct dahdi_pvt *p)
02331 {
02332 p->callwaitcas = 0;
02333 p->cidcwexpire = 0;
02334 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02335 return -1;
02336 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02337
02338 p->cidlen += READ_SIZE * 4;
02339 p->cidpos = 0;
02340 send_callerid(p);
02341 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02342 return 0;
02343 }
02344
02345 static int has_voicemail(struct dahdi_pvt *p)
02346 {
02347 int new_msgs;
02348 struct ast_event *event;
02349 char *mailbox, *context;
02350
02351 mailbox = context = ast_strdupa(p->mailbox);
02352 strsep(&context, "@");
02353 if (ast_strlen_zero(context))
02354 context = "default";
02355
02356 event = ast_event_get_cached(AST_EVENT_MWI,
02357 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02358 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02359 AST_EVENT_IE_END);
02360
02361 if (event) {
02362 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02363 ast_event_destroy(event);
02364 } else
02365 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02366
02367 return new_msgs;
02368 }
02369
02370 static int send_callerid(struct dahdi_pvt *p)
02371 {
02372
02373 int res;
02374
02375 if (p->subs[SUB_REAL].linear) {
02376 p->subs[SUB_REAL].linear = 0;
02377 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02378 }
02379 while (p->cidpos < p->cidlen) {
02380 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02381 if (res < 0) {
02382 if (errno == EAGAIN)
02383 return 0;
02384 else {
02385 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02386 return -1;
02387 }
02388 }
02389 if (!res)
02390 return 0;
02391 p->cidpos += res;
02392 }
02393 ast_free(p->cidspill);
02394 p->cidspill = NULL;
02395 if (p->callwaitcas) {
02396
02397 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02398 } else
02399 restore_conference(p);
02400 return 0;
02401 }
02402
02403 static int dahdi_callwait(struct ast_channel *ast)
02404 {
02405 struct dahdi_pvt *p = ast->tech_pvt;
02406 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02407 if (p->cidspill) {
02408 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02409 ast_free(p->cidspill);
02410 }
02411 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02412 return -1;
02413 save_conference(p);
02414
02415 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02416 if (!p->callwaitrings && p->callwaitingcallerid) {
02417 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02418 p->callwaitcas = 1;
02419 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02420 } else {
02421 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02422 p->callwaitcas = 0;
02423 p->cidlen = 2400 + READ_SIZE * 4;
02424 }
02425 p->cidpos = 0;
02426 send_callerid(p);
02427
02428 return 0;
02429 }
02430
02431 #ifdef HAVE_SS7
02432 static unsigned char cid_pres2ss7pres(int cid_pres)
02433 {
02434 return (cid_pres >> 5) & 0x03;
02435 }
02436
02437 static unsigned char cid_pres2ss7screen(int cid_pres)
02438 {
02439 return cid_pres & 0x03;
02440 }
02441 #endif
02442
02443 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02444 {
02445 struct dahdi_pvt *p = ast->tech_pvt;
02446 int x, res, idx,mysig;
02447 char *c, *n, *l;
02448 #ifdef HAVE_PRI
02449 char *s = NULL;
02450 #endif
02451 char dest[256];
02452 ast_mutex_lock(&p->lock);
02453 ast_copy_string(dest, rdest, sizeof(dest));
02454 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02455 if ((ast->_state == AST_STATE_BUSY)) {
02456 p->subs[SUB_REAL].needbusy = 1;
02457 ast_mutex_unlock(&p->lock);
02458 return 0;
02459 }
02460 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02461 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02462 ast_mutex_unlock(&p->lock);
02463 return -1;
02464 }
02465 p->dialednone = 0;
02466 if ((p->radio || (p->oprmode < 0)))
02467 {
02468
02469 ast_setstate(ast, AST_STATE_UP);
02470 ast_mutex_unlock(&p->lock);
02471 return 0;
02472 }
02473 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02475 if (res)
02476 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02477 p->outgoing = 1;
02478
02479 if (IS_DIGITAL(ast->transfercapability)){
02480 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02481 } else {
02482 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02483 }
02484
02485 mysig = p->sig;
02486 if (p->outsigmod > -1)
02487 mysig = p->outsigmod;
02488
02489 switch (mysig) {
02490 case SIG_FXOLS:
02491 case SIG_FXOGS:
02492 case SIG_FXOKS:
02493 if (p->owner == ast) {
02494
02495
02496
02497 p->dialing = 1;
02498 if (p->use_callerid) {
02499
02500 if (p->cidspill) {
02501 ast_log(LOG_WARNING, "cidspill already exists??\n");
02502 ast_free(p->cidspill);
02503 }
02504 p->callwaitcas = 0;
02505 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02506 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02507 p->cidpos = 0;
02508 send_callerid(p);
02509 }
02510 }
02511
02512 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02513 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02514 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02515 p->cidrings = cidrings[p->distinctivering - 1];
02516 } else {
02517 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02518 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02519 p->cidrings = p->sendcalleridafter;
02520 }
02521
02522
02523 c = strchr(dest, '/');
02524 if (c)
02525 c++;
02526 if (c && (strlen(c) < p->stripmsd)) {
02527 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02528 c = NULL;
02529 }
02530 if (c) {
02531 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02532 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02533 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
02534 } else {
02535 p->dop.dialstr[0] = '\0';
02536 }
02537 x = DAHDI_RING;
02538 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02539 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02540 ast_mutex_unlock(&p->lock);
02541 return -1;
02542 }
02543 p->dialing = 1;
02544 } else {
02545
02546 p->callwaitrings = 0;
02547 if (ast->cid.cid_num)
02548 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02549 else
02550 p->callwait_num[0] = '\0';
02551 if (ast->cid.cid_name)
02552 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02553 else
02554 p->callwait_name[0] = '\0';
02555
02556 if (dahdi_callwait(ast)) {
02557 ast_mutex_unlock(&p->lock);
02558 return -1;
02559 }
02560
02561 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02562 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02563
02564 }
02565 n = ast->cid.cid_name;
02566 l = ast->cid.cid_num;
02567 if (l)
02568 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02569 else
02570 p->lastcid_num[0] = '\0';
02571 if (n)
02572 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02573 else
02574 p->lastcid_name[0] = '\0';
02575 ast_setstate(ast, AST_STATE_RINGING);
02576 idx = dahdi_get_index(ast, p, 0);
02577 if (idx > -1) {
02578 p->subs[idx].needringing = 1;
02579 }
02580 break;
02581 case SIG_FXSLS:
02582 case SIG_FXSGS:
02583 case SIG_FXSKS:
02584 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02585 ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
02586 p->polaritydelaytv = ast_tvnow();
02587 }
02588
02589 case SIG_EMWINK:
02590 case SIG_EM:
02591 case SIG_EM_E1:
02592 case SIG_FEATD:
02593 case SIG_FEATDMF:
02594 case SIG_E911:
02595 case SIG_FGC_CAMA:
02596 case SIG_FGC_CAMAMF:
02597 case SIG_FEATB:
02598 case SIG_SFWINK:
02599 case SIG_SF:
02600 case SIG_SF_FEATD:
02601 case SIG_SF_FEATDMF:
02602 case SIG_FEATDMF_TA:
02603 case SIG_SF_FEATB:
02604 c = strchr(dest, '/');
02605 if (c)
02606 c++;
02607 else
02608 c = "";
02609 if (strlen(c) < p->stripmsd) {
02610 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02611 ast_mutex_unlock(&p->lock);
02612 return -1;
02613 }
02614 #ifdef HAVE_PRI
02615
02616 if (!p->pri) {
02617 #endif
02618 x = DAHDI_START;
02619 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02620 if (res < 0) {
02621 if (errno != EINPROGRESS) {
02622 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02623 ast_mutex_unlock(&p->lock);
02624 return -1;
02625 }
02626 }
02627 #ifdef HAVE_PRI
02628 }
02629 #endif
02630 ast_debug(1, "Dialing '%s'\n", c);
02631 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02632
02633 c += p->stripmsd;
02634
02635 switch (mysig) {
02636 case SIG_FEATD:
02637 l = ast->cid.cid_num;
02638 if (l)
02639 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02640 else
02641 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02642 break;
02643 case SIG_FEATDMF:
02644 l = ast->cid.cid_num;
02645 if (l)
02646 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02647 else
02648 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02649 break;
02650 case SIG_FEATDMF_TA:
02651 {
02652 const char *cic, *ozz;
02653
02654
02655 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02656 if (!ozz)
02657 ozz = defaultozz;
02658 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02659 if (!cic)
02660 cic = defaultcic;
02661 if (!ozz || !cic) {
02662 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02663 ast_mutex_unlock(&p->lock);
02664 return -1;
02665 }
02666 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02667 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02668 p->whichwink = 0;
02669 }
02670 break;
02671 case SIG_E911:
02672 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02673 break;
02674 case SIG_FGC_CAMA:
02675 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02676 break;
02677 case SIG_FGC_CAMAMF:
02678 case SIG_FEATB:
02679 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02680 break;
02681 default:
02682 if (p->pulse)
02683 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02684 else
02685 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02686 break;
02687 }
02688
02689 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02690 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02691 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02692 p->echorest[sizeof(p->echorest) - 1] = '\0';
02693 p->echobreak = 1;
02694 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02695 } else
02696 p->echobreak = 0;
02697 if (!res) {
02698 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02699 int saveerr = errno;
02700
02701 x = DAHDI_ONHOOK;
02702 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02703 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02704 ast_mutex_unlock(&p->lock);
02705 return -1;
02706 }
02707 } else
02708 ast_debug(1, "Deferring dialing...\n");
02709
02710 p->dialing = 1;
02711 if (ast_strlen_zero(c))
02712 p->dialednone = 1;
02713 ast_setstate(ast, AST_STATE_DIALING);
02714 break;
02715 case 0:
02716
02717 ast_setstate(ast, AST_STATE_UP);
02718 break;
02719 case SIG_PRI:
02720 case SIG_BRI:
02721 case SIG_BRI_PTMP:
02722 case SIG_SS7:
02723
02724 p->dialdest[0] = '\0';
02725 p->dialing = 1;
02726 break;
02727 default:
02728 ast_debug(1, "not yet implemented\n");
02729 ast_mutex_unlock(&p->lock);
02730 return -1;
02731 }
02732 #ifdef HAVE_SS7
02733 if (p->ss7) {
02734 char ss7_called_nai;
02735 int called_nai_strip;
02736 char ss7_calling_nai;
02737 int calling_nai_strip;
02738 const char *charge_str = NULL;
02739 const char *gen_address = NULL;
02740 const char *gen_digits = NULL;
02741 const char *gen_dig_type = NULL;
02742 const char *gen_dig_scheme = NULL;
02743 const char *gen_name = NULL;
02744 const char *jip_digits = NULL;
02745 const char *lspi_ident = NULL;
02746 const char *rlt_flag = NULL;
02747 const char *call_ref_id = NULL;
02748 const char *call_ref_pc = NULL;
02749 const char *send_far = NULL;
02750
02751 c = strchr(dest, '/');
02752 if (c) {
02753 c++;
02754 } else {
02755 c = "";
02756 }
02757 if (strlen(c) < p->stripmsd) {
02758 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02759 ast_mutex_unlock(&p->lock);
02760 return -1;
02761 }
02762
02763 if (!p->hidecallerid) {
02764 l = ast->cid.cid_num;
02765 } else {
02766 l = NULL;
02767 }
02768
02769 if (ss7_grab(p, p->ss7)) {
02770 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02771 ast_mutex_unlock(&p->lock);
02772 return -1;
02773 }
02774 p->digital = IS_DIGITAL(ast->transfercapability);
02775 p->ss7call = isup_new_call(p->ss7->ss7);
02776
02777 if (!p->ss7call) {
02778 ss7_rel(p->ss7);
02779 ast_mutex_unlock(&p->lock);
02780 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02781 return -1;
02782 }
02783
02784 called_nai_strip = 0;
02785 ss7_called_nai = p->ss7->called_nai;
02786 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
02787 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02788 called_nai_strip = strlen(p->ss7->internationalprefix);
02789 ss7_called_nai = SS7_NAI_INTERNATIONAL;
02790 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02791 called_nai_strip = strlen(p->ss7->nationalprefix);
02792 ss7_called_nai = SS7_NAI_NATIONAL;
02793 } else {
02794 ss7_called_nai = SS7_NAI_SUBSCRIBER;
02795 }
02796 }
02797 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02798
02799 calling_nai_strip = 0;
02800 ss7_calling_nai = p->ss7->calling_nai;
02801 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
02802 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02803 calling_nai_strip = strlen(p->ss7->internationalprefix);
02804 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02805 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02806 calling_nai_strip = strlen(p->ss7->nationalprefix);
02807 ss7_calling_nai = SS7_NAI_NATIONAL;
02808 } else {
02809 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02810 }
02811 }
02812 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02813 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02814 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02815
02816 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02817 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02818
02819 ast_channel_lock(ast);
02820
02821 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02822 if (charge_str)
02823 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02824
02825 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02826 if (gen_address)
02827 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);
02828
02829 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02830 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02831 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02832 if (gen_digits)
02833 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
02834
02835 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02836 if (gen_name)
02837 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02838
02839 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02840 if (jip_digits)
02841 isup_set_jip_digits(p->ss7call, jip_digits);
02842
02843 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02844 if (lspi_ident)
02845 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
02846
02847 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02848 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02849 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
02850 }
02851
02852 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02853 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02854 if (call_ref_id && call_ref_pc) {
02855 isup_set_callref(p->ss7call, atoi(call_ref_id),
02856 call_ref_pc ? atoi(call_ref_pc) : 0);
02857 }
02858
02859 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02860 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02861 (isup_far(p->ss7->ss7, p->ss7call));
02862
02863 ast_channel_unlock(ast);
02864
02865 isup_iam(p->ss7->ss7, p->ss7call);
02866 ast_setstate(ast, AST_STATE_DIALING);
02867 ss7_rel(p->ss7);
02868 }
02869 #endif
02870 #ifdef HAVE_PRI
02871 if (p->pri) {
02872 struct pri_sr *sr;
02873 #ifdef SUPPORT_USERUSER
02874 const char *useruser;
02875 #endif
02876 int pridialplan;
02877 int dp_strip;
02878 int prilocaldialplan;
02879 int ldp_strip;
02880 int exclusive;
02881 const char *rr_str;
02882 int redirect_reason;
02883
02884 c = strchr(dest, '/');
02885 if (c) {
02886 c++;
02887 } else {
02888 c = "";
02889 }
02890
02891 l = NULL;
02892 n = NULL;
02893 if (!p->hidecallerid) {
02894 l = ast->cid.cid_num;
02895 if (!p->hidecalleridname) {
02896 n = ast->cid.cid_name;
02897 }
02898 }
02899
02900 if (strlen(c) < p->stripmsd) {
02901 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02902 ast_mutex_unlock(&p->lock);
02903 return -1;
02904 }
02905 if (mysig != SIG_FXSKS) {
02906 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02907 s = strchr(c + p->stripmsd, 'w');
02908 if (s) {
02909 if (strlen(s) > 1)
02910 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02911 else
02912 p->dop.dialstr[0] = '\0';
02913 *s = '\0';
02914 } else {
02915 p->dop.dialstr[0] = '\0';
02916 }
02917 }
02918 if (pri_grab(p, p->pri)) {
02919 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02920 ast_mutex_unlock(&p->lock);
02921 return -1;
02922 }
02923 if (!(p->call = pri_new_call(p->pri->pri))) {
02924 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02925 pri_rel(p->pri);
02926 ast_mutex_unlock(&p->lock);
02927 return -1;
02928 }
02929 if (!(sr = pri_sr_new())) {
02930 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02931 pri_rel(p->pri);
02932 ast_mutex_unlock(&p->lock);
02933 }
02934 if (p->bearer || (mysig == SIG_FXSKS)) {
02935 if (p->bearer) {
02936 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02937 p->bearer->call = p->call;
02938 } else
02939 ast_debug(1, "I'm being setup with no bearer right now...\n");
02940
02941 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02942 }
02943 p->digital = IS_DIGITAL(ast->transfercapability);
02944
02945
02946 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
02947 exclusive = 1;
02948 } else {
02949 exclusive = 0;
02950 }
02951
02952 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02953 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02954 (p->digital ? -1 :
02955 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02956 if (p->pri->facilityenable)
02957 pri_facility_enable(p->pri->pri);
02958
02959 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02960 dp_strip = 0;
02961 pridialplan = p->pri->dialplan - 1;
02962 if (pridialplan == -2 || pridialplan == -3) {
02963 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02964 if (pridialplan == -2) {
02965 dp_strip = strlen(p->pri->internationalprefix);
02966 }
02967 pridialplan = PRI_INTERNATIONAL_ISDN;
02968 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02969 if (pridialplan == -2) {
02970 dp_strip = strlen(p->pri->nationalprefix);
02971 }
02972 pridialplan = PRI_NATIONAL_ISDN;
02973 } else {
02974 pridialplan = PRI_LOCAL_ISDN;
02975 }
02976 }
02977 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02978 switch (c[p->stripmsd]) {
02979 case 'U':
02980 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02981 break;
02982 case 'I':
02983 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
02984 break;
02985 case 'N':
02986 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
02987 break;
02988 case 'L':
02989 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
02990 break;
02991 case 'S':
02992 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
02993 break;
02994 case 'V':
02995 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
02996 break;
02997 case 'R':
02998 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
02999 break;
03000 case 'u':
03001 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03002 break;
03003 case 'e':
03004 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03005 break;
03006 case 'x':
03007 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03008 break;
03009 case 'f':
03010 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03011 break;
03012 case 'n':
03013 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03014 break;
03015 case 'p':
03016 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03017 break;
03018 case 'r':
03019 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03020 break;
03021 default:
03022 if (isalpha(c[p->stripmsd])) {
03023 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03024 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03025 }
03026 break;
03027 }
03028 c++;
03029 }
03030 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03031
03032 ldp_strip = 0;
03033 prilocaldialplan = p->pri->localdialplan - 1;
03034 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03035 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03036 if (prilocaldialplan == -2) {
03037 ldp_strip = strlen(p->pri->internationalprefix);
03038 }
03039 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03040 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03041 if (prilocaldialplan == -2) {
03042 ldp_strip = strlen(p->pri->nationalprefix);
03043 }
03044 prilocaldialplan = PRI_NATIONAL_ISDN;
03045 } else {
03046 prilocaldialplan = PRI_LOCAL_ISDN;
03047 }
03048 }
03049 if (l != NULL) {
03050 while (*l > '9' && *l != '*' && *l != '#') {
03051 switch (*l) {
03052 case 'U':
03053 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03054 break;
03055 case 'I':
03056 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03057 break;
03058 case 'N':
03059 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03060 break;
03061 case 'L':
03062 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03063 break;
03064 case 'S':
03065 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03066 break;
03067 case 'V':
03068 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03069 break;
03070 case 'R':
03071 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03072 break;
03073 case 'u':
03074 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03075 break;
03076 case 'e':
03077 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03078 break;
03079 case 'x':
03080 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03081 break;
03082 case 'f':
03083 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03084 break;
03085 case 'n':
03086 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03087 break;
03088 case 'p':
03089 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03090 break;
03091 case 'r':
03092 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03093 break;
03094 default:
03095 if (isalpha(*l)) {
03096 ast_log(LOG_WARNING,
03097 "Unrecognized prilocaldialplan %s modifier: %c\n",
03098 *l > 'Z' ? "NPI" : "TON", *l);
03099 }
03100 break;
03101 }
03102 l++;
03103 }
03104 }
03105 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03106 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03107 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03108 if (!strcasecmp(rr_str, "UNKNOWN"))
03109 redirect_reason = 0;
03110 else if (!strcasecmp(rr_str, "BUSY"))
03111 redirect_reason = 1;
03112 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03113
03114 redirect_reason = 2;
03115 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03116 redirect_reason = 15;
03117 else
03118 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03119 } else
03120 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03121 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03122
03123 #ifdef SUPPORT_USERUSER
03124
03125 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03126
03127 if (useruser)
03128 pri_sr_set_useruser(sr, useruser);
03129 #endif
03130
03131 if (pri_setup(p->pri->pri, p->call, sr)) {
03132 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03133 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03134 pri_rel(p->pri);
03135 ast_mutex_unlock(&p->lock);
03136 pri_sr_free(sr);
03137 return -1;
03138 }
03139 pri_sr_free(sr);
03140 ast_setstate(ast, AST_STATE_DIALING);
03141 pri_rel(p->pri);
03142 }
03143 #endif
03144 ast_mutex_unlock(&p->lock);
03145 return 0;
03146 }
03147
03148 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03149 {
03150 struct dahdi_pvt *p = *pvt;
03151
03152 if (p->prev)
03153 p->prev->next = p->next;
03154 if (p->next)
03155 p->next->prev = p->prev;
03156 if (p->use_smdi)
03157 ast_smdi_interface_unref(p->smdi_iface);
03158 if (p->mwi_event_sub)
03159 ast_event_unsubscribe(p->mwi_event_sub);
03160 if (p->vars) {
03161 ast_variables_destroy(p->vars);
03162 }
03163 ast_mutex_destroy(&p->lock);
03164 dahdi_close_sub(p, SUB_REAL);
03165 if (p->owner)
03166 p->owner->tech_pvt = NULL;
03167 free(p);
03168 *pvt = NULL;
03169 }
03170
03171 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03172 {
03173 int owned = 0;
03174 int i = 0;
03175
03176 if (!now) {
03177 if (cur->owner) {
03178 owned = 1;
03179 }
03180
03181 for (i = 0; i < 3; i++) {
03182 if (cur->subs[i].owner) {
03183 owned = 1;
03184 }
03185 }
03186 if (!owned) {
03187 if (prev) {
03188 prev->next = cur->next;
03189 if (prev->next)
03190 prev->next->prev = prev;
03191 else
03192 ifend = prev;
03193 } else {
03194 iflist = cur->next;
03195 if (iflist)
03196 iflist->prev = NULL;
03197 else
03198 ifend = NULL;
03199 }
03200 destroy_dahdi_pvt(&cur);
03201 }
03202 } else {
03203 if (prev) {
03204 prev->next = cur->next;
03205 if (prev->next)
03206 prev->next->prev = prev;
03207 else
03208 ifend = prev;
03209 } else {
03210 iflist = cur->next;
03211 if (iflist)
03212 iflist->prev = NULL;
03213 else
03214 ifend = NULL;
03215 }
03216 destroy_dahdi_pvt(&cur);
03217 }
03218 return 0;
03219 }
03220
03221 static void destroy_all_channels(void)
03222 {
03223 int x;
03224 struct dahdi_pvt *p, *pl;
03225
03226 while (num_restart_pending) {
03227 usleep(1);
03228 }
03229
03230 ast_mutex_lock(&iflock);
03231
03232 p = iflist;
03233 while (p) {
03234
03235 if (p->cidspill)
03236 ast_free(p->cidspill);
03237 pl = p;
03238 p = p->next;
03239 x = pl->channel;
03240
03241 if (pl)
03242 destroy_dahdi_pvt(&pl);
03243 if (option_verbose > 2)
03244 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03245 }
03246 iflist = NULL;
03247 ifcount = 0;
03248 ast_mutex_unlock(&iflock);
03249 }
03250
03251 #ifdef HAVE_PRI
03252 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03253
03254 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03255
03256 static char *dahdi_send_keypad_facility_descrip =
03257 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03258 " IE over the current channel.\n";
03259
03260 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03261 {
03262
03263 struct dahdi_pvt *p;
03264 char *digits = (char *) data;
03265
03266 if (ast_strlen_zero(digits)) {
03267 ast_debug(1, "No digit string sent to application!\n");
03268 return -1;
03269 }
03270
03271 p = (struct dahdi_pvt *)chan->tech_pvt;
03272
03273 if (!p) {
03274 ast_debug(1, "Unable to find technology private\n");
03275 return -1;
03276 }
03277
03278 ast_mutex_lock(&p->lock);
03279
03280 if (!p->pri || !p->call) {
03281 ast_debug(1, "Unable to find pri or call on channel!\n");
03282 ast_mutex_unlock(&p->lock);
03283 return -1;
03284 }
03285
03286 if (!pri_grab(p, p->pri)) {
03287 pri_keypad_facility(p->pri->pri, p->call, digits);
03288 pri_rel(p->pri);
03289 } else {
03290 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03291 ast_mutex_unlock(&p->lock);
03292 return -1;
03293 }
03294
03295 ast_mutex_unlock(&p->lock);
03296
03297 return 0;
03298 }
03299
03300 static int pri_is_up(struct dahdi_pri *pri)
03301 {
03302 int x;
03303 for (x = 0; x < NUM_DCHANS; x++) {
03304 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03305 return 1;
03306 }
03307 return 0;
03308 }
03309
03310 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03311 {
03312 bearer->owner = &inuse;
03313 bearer->realcall = crv;
03314 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03315 if (crv->subs[SUB_REAL].owner)
03316 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03317 crv->bearer = bearer;
03318 crv->call = bearer->call;
03319 crv->pri = pri;
03320 return 0;
03321 }
03322
03323 static char *pri_order(int level)
03324 {
03325 switch (level) {
03326 case 0:
03327 return "Primary";
03328 case 1:
03329 return "Secondary";
03330 case 2:
03331 return "Tertiary";
03332 case 3:
03333 return "Quaternary";
03334 default:
03335 return "<Unknown>";
03336 }
03337 }
03338
03339
03340 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03341 {
03342 int x = -1;
03343
03344 for (x = 0; x < NUM_DCHANS; x++) {
03345 if ((pri->dchans[x] == pri->pri))
03346 break;
03347 }
03348
03349 return pri->fds[x];
03350 }
03351
03352 static int pri_find_dchan(struct dahdi_pri *pri)
03353 {
03354 int oldslot = -1;
03355 struct pri *old;
03356 int newslot = -1;
03357 int x;
03358 old = pri->pri;
03359 for (x = 0; x < NUM_DCHANS; x++) {
03360 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03361 newslot = x;
03362 if (pri->dchans[x] == old) {
03363 oldslot = x;
03364 }
03365 }
03366 if (newslot < 0) {
03367 newslot = 0;
03368 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03369 pri->dchannels[newslot]);
03370 }
03371 if (old && (oldslot != newslot))
03372 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03373 pri->dchannels[oldslot], pri->dchannels[newslot]);
03374 pri->pri = pri->dchans[newslot];
03375 return 0;
03376 }
03377 #endif
03378
03379 static int dahdi_hangup(struct ast_channel *ast)
03380 {
03381 int res;
03382 int idx,x, law;
03383
03384 struct dahdi_pvt *p = ast->tech_pvt;
03385 struct dahdi_pvt *tmp = NULL;
03386 struct dahdi_pvt *prev = NULL;
03387 struct dahdi_params par;
03388
03389 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03390 if (!ast->tech_pvt) {
03391 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03392 return 0;
03393 }
03394
03395 ast_mutex_lock(&p->lock);
03396
03397 idx = dahdi_get_index(ast, p, 1);
03398
03399 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03400 x = 1;
03401 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03402 p->cid_num[0] = '\0';
03403 p->cid_name[0] = '\0';
03404 }
03405
03406 x = 0;
03407 dahdi_confmute(p, 0);
03408 p->muting = 0;
03409 restore_gains(p);
03410 if (p->origcid_num) {
03411 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03412 ast_free(p->origcid_num);
03413 p->origcid_num = NULL;
03414 }
03415 if (p->origcid_name) {
03416 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03417 ast_free(p->origcid_name);
03418 p->origcid_name = NULL;
03419 }
03420 if (p->dsp)
03421 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03422 p->exten[0] = '\0';
03423
03424 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03425 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03426 p->ignoredtmf = 0;
03427
03428 if (idx > -1) {
03429
03430 p->subs[idx].owner = NULL;
03431 p->subs[idx].needanswer = 0;
03432 p->subs[idx].needflash = 0;
03433 p->subs[idx].needringing = 0;
03434 p->subs[idx].needbusy = 0;
03435 p->subs[idx].needcongestion = 0;
03436 p->subs[idx].linear = 0;
03437 p->subs[idx].needcallerid = 0;
03438 p->polarity = POLARITY_IDLE;
03439 dahdi_setlinear(p->subs[idx].dfd, 0);
03440 if (idx == SUB_REAL) {
03441 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03442 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03443 if (p->subs[SUB_CALLWAIT].inthreeway) {
03444
03445 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03446
03447 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03448 unalloc_sub(p, SUB_CALLWAIT);
03449 p->owner = NULL;
03450 } else {
03451
03452 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03453 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03454 unalloc_sub(p, SUB_THREEWAY);
03455 if (p->subs[SUB_REAL].inthreeway) {
03456
03457
03458 ast_debug(1, "Call was complete, setting owner to former third call\n");
03459 p->owner = p->subs[SUB_REAL].owner;
03460 } else {
03461
03462 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03463 p->owner = NULL;
03464 }
03465 p->subs[SUB_REAL].inthreeway = 0;
03466 }
03467 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03468
03469 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03470 unalloc_sub(p, SUB_CALLWAIT);
03471 p->owner = p->subs[SUB_REAL].owner;
03472 if (p->owner->_state != AST_STATE_UP)
03473 p->subs[SUB_REAL].needanswer = 1;
03474 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03475 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03476 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03477 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03478 unalloc_sub(p, SUB_THREEWAY);
03479 if (p->subs[SUB_REAL].inthreeway) {
03480
03481
03482 ast_debug(1, "Call was complete, setting owner to former third call\n");
03483 p->owner = p->subs[SUB_REAL].owner;
03484 } else {
03485
03486 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03487 p->owner = NULL;
03488 }
03489 p->subs[SUB_REAL].inthreeway = 0;
03490 }
03491 } else if (idx == SUB_CALLWAIT) {
03492
03493 if (p->subs[SUB_CALLWAIT].inthreeway) {
03494
03495
03496 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03497 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03498 S_OR(p->mohsuggest, NULL),
03499 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03500 }
03501 p->subs[SUB_THREEWAY].inthreeway = 0;
03502
03503 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03504 unalloc_sub(p, SUB_THREEWAY);
03505 } else
03506 unalloc_sub(p, SUB_CALLWAIT);
03507 } else if (idx == SUB_THREEWAY) {
03508 if (p->subs[SUB_CALLWAIT].inthreeway) {
03509
03510
03511 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03512 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03513 S_OR(p->mohsuggest, NULL),
03514 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03515 }
03516 p->subs[SUB_CALLWAIT].inthreeway = 0;
03517 }
03518 p->subs[SUB_REAL].inthreeway = 0;
03519
03520
03521 unalloc_sub(p, SUB_THREEWAY);
03522 } else {
03523
03524 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03525 }
03526 }
03527
03528 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03529 p->owner = NULL;
03530 p->ringt = 0;
03531 p->distinctivering = 0;
03532 p->confirmanswer = 0;
03533 p->cidrings = 1;
03534 p->outgoing = 0;
03535 p->digital = 0;
03536 p->faxhandled = 0;
03537 p->pulsedial = 0;
03538 p->onhooktime = time(NULL);
03539 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03540 p->proceeding = 0;
03541 p->dialing = 0;
03542 p->progress = 0;
03543 p->alerting = 0;
03544 p->setup_ack = 0;
03545 p->rlt = 0;
03546 #endif
03547 if (p->dsp) {
03548 ast_dsp_free(p->dsp);
03549 p->dsp = NULL;
03550 }
03551
03552 law = DAHDI_LAW_DEFAULT;
03553 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03554 if (res < 0)
03555 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03556
03557 #ifdef HAVE_SS7
03558 if (p->ss7) {
03559 if (p->ss7call) {
03560 if (!ss7_grab(p, p->ss7)) {
03561 if (!p->alreadyhungup) {
03562 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03563 int icause = ast->hangupcause ? ast->hangupcause : -1;
03564
03565 if (cause) {
03566 if (atoi(cause))
03567 icause = atoi(cause);
03568 }
03569 isup_rel(p->ss7->ss7, p->ss7call, icause);
03570 ss7_rel(p->ss7);
03571 p->alreadyhungup = 1;
03572 } else
03573 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03574 } else {
03575 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03576 res = -1;
03577 }
03578 }
03579 }
03580 #endif
03581 #ifdef HAVE_PRI
03582 if (p->pri) {
03583 #ifdef SUPPORT_USERUSER
03584 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03585 #endif
03586
03587
03588 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03589 if (!pri_grab(p, p->pri)) {
03590 if (p->alreadyhungup) {
03591 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
03592
03593 #ifdef SUPPORT_USERUSER
03594 pri_call_set_useruser(p->call, useruser);
03595 #endif
03596
03597 pri_hangup(p->pri->pri, p->call, -1);
03598 p->call = NULL;
03599 if (p->bearer)
03600 p->bearer->call = NULL;
03601 } else {
03602 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03603 int icause = ast->hangupcause ? ast->hangupcause : -1;
03604 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03605
03606 #ifdef SUPPORT_USERUSER
03607 pri_call_set_useruser(p->call, useruser);
03608 #endif
03609
03610 p->alreadyhungup = 1;
03611 if (p->bearer)
03612 p->bearer->alreadyhungup = 1;
03613 if (cause) {
03614 if (atoi(cause))
03615 icause = atoi(cause);
03616 }
03617 pri_hangup(p->pri->pri, p->call, icause);
03618 }
03619 if (res < 0)
03620 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03621 pri_rel(p->pri);
03622 } else {
03623 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03624 res = -1;
03625 }
03626 } else {
03627 if (p->bearer)
03628 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03629 p->call = NULL;
03630 res = 0;
03631 }
03632 }
03633 #endif
03634 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03635 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03636 if (res < 0) {
03637 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03638 }
03639 switch (p->sig) {
03640 case SIG_FXOGS:
03641 case SIG_FXOLS:
03642 case SIG_FXOKS:
03643 memset(&par, 0, sizeof(par));
03644 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03645 if (!res) {
03646 #if 0
03647 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03648 #endif
03649
03650 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03651 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03652 else
03653 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03654 }
03655 break;
03656 case SIG_FXSGS:
03657 case SIG_FXSLS:
03658 case SIG_FXSKS:
03659
03660
03661 if (ast->_state != AST_STATE_RESERVED) {
03662 time(&p->guardtime);
03663 p->guardtime += 2;
03664 }
03665 break;
03666 default:
03667 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03668 }
03669 if (p->cidspill)
03670 ast_free(p->cidspill);
03671 if (p->sig)
03672 dahdi_disable_ec(p);
03673 x = 0;
03674 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03675 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03676 p->didtdd = 0;
03677 p->cidspill = NULL;
03678 p->callwaitcas = 0;
03679 p->callwaiting = p->permcallwaiting;
03680 p->hidecallerid = p->permhidecallerid;
03681 p->dialing = 0;
03682 p->rdnis[0] = '\0';
03683 update_conf(p);
03684 reset_conf(p);
03685
03686 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03687 x = 0;
03688 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03689 }
03690 #ifdef HAVE_PRI
03691 if (p->bearer) {
03692 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03693
03694
03695 update_conf(p->bearer);
03696 reset_conf(p->bearer);
03697 p->bearer->owner = NULL;
03698 p->bearer->realcall = NULL;
03699 p->bearer = NULL;
03700 p->subs[SUB_REAL].dfd = -1;
03701 p->pri = NULL;
03702 }
03703 #endif
03704 if (num_restart_pending == 0)
03705 restart_monitor();
03706 }
03707
03708 p->callwaitingrepeat = 0;
03709 p->cidcwexpire = 0;
03710 p->oprmode = 0;
03711 ast->tech_pvt = NULL;
03712 ast_mutex_unlock(&p->lock);
03713 ast_module_unref(ast_module_info->self);
03714 ast_verb(3, "Hungup '%s'\n", ast->name);
03715
03716 ast_mutex_lock(&iflock);
03717
03718 if (p->restartpending) {
03719 num_restart_pending--;
03720 }
03721
03722 tmp = iflist;
03723 prev = NULL;
03724 if (p->destroy) {
03725 while (tmp) {
03726 if (tmp == p) {
03727 destroy_channel(prev, tmp, 0);
03728 break;
03729 } else {
03730 prev = tmp;
03731 tmp = tmp->next;
03732 }
03733 }
03734 }
03735 ast_mutex_unlock(&iflock);
03736 return 0;
03737 }
03738
03739 static int dahdi_answer(struct ast_channel *ast)
03740 {
03741 struct dahdi_pvt *p = ast->tech_pvt;
03742 int res = 0;
03743 int idx;
03744 int oldstate = ast->_state;
03745 ast_setstate(ast, AST_STATE_UP);
03746 ast_mutex_lock(&p->lock);
03747 idx = dahdi_get_index(ast, p, 0);
03748 if (idx < 0)
03749 idx = SUB_REAL;
03750
03751 if ((p->radio || (p->oprmode < 0))) {
03752 ast_mutex_unlock(&p->lock);
03753 return 0;
03754 }
03755 switch (p->sig) {
03756 case SIG_FXSLS:
03757 case SIG_FXSGS:
03758 case SIG_FXSKS:
03759 p->ringt = 0;
03760
03761 case SIG_EM:
03762 case SIG_EM_E1:
03763 case SIG_EMWINK:
03764 case SIG_FEATD:
03765 case SIG_FEATDMF:
03766 case SIG_FEATDMF_TA:
03767 case SIG_E911:
03768 case SIG_FGC_CAMA:
03769 case SIG_FGC_CAMAMF:
03770 case SIG_FEATB:
03771 case SIG_SF:
03772 case SIG_SFWINK:
03773 case SIG_SF_FEATD:
03774 case SIG_SF_FEATDMF:
03775 case SIG_SF_FEATB:
03776 case SIG_FXOLS:
03777 case SIG_FXOGS:
03778 case SIG_FXOKS:
03779
03780 ast_debug(1, "Took %s off hook\n", ast->name);
03781 if (p->hanguponpolarityswitch) {
03782 p->polaritydelaytv = ast_tvnow();
03783 }
03784 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03785 tone_zone_play_tone(p->subs[idx].dfd, -1);
03786 p->dialing = 0;
03787 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03788 if (oldstate == AST_STATE_RINGING) {
03789 ast_debug(1, "Finally swapping real and threeway\n");
03790 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03791 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03792 p->owner = p->subs[SUB_REAL].owner;
03793 }
03794 }
03795 if (p->sig & __DAHDI_SIG_FXS) {
03796 dahdi_enable_ec(p);
03797 dahdi_train_ec(p);
03798 }
03799 break;
03800 #ifdef HAVE_PRI
03801 case SIG_BRI:
03802 case SIG_BRI_PTMP:
03803 case SIG_PRI:
03804
03805 if (!pri_grab(p, p->pri)) {
03806 p->proceeding = 1;
03807 p->dialing = 0;
03808 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03809 pri_rel(p->pri);
03810 } else {
03811 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03812 res = -1;
03813 }
03814 break;
03815 #endif
03816 #ifdef HAVE_SS7
03817 case SIG_SS7:
03818 if (!ss7_grab(p, p->ss7)) {
03819 p->proceeding = 1;
03820 res = isup_anm(p->ss7->ss7, p->ss7call);
03821 ss7_rel(p->ss7);
03822 } else {
03823 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03824 res = -1;
03825 }
03826 break;
03827 #endif
03828 case 0:
03829 ast_mutex_unlock(&p->lock);
03830 return 0;
03831 default:
03832 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03833 res = -1;
03834 }
03835 ast_mutex_unlock(&p->lock);
03836 return res;
03837 }
03838
03839 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03840 {
03841 char *cp;
03842 signed char *scp;
03843 int x;
03844 int idx;
03845 struct dahdi_pvt *p = chan->tech_pvt, *pp;
03846 struct oprmode *oprmode;
03847
03848
03849
03850 if (!data || (datalen < 1)) {
03851 errno = EINVAL;
03852 return -1;
03853 }
03854
03855 switch (option) {
03856 case AST_OPTION_TXGAIN:
03857 scp = (signed char *) data;
03858 idx = dahdi_get_index(chan, p, 0);
03859 if (idx < 0) {
03860 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03861 return -1;
03862 }
03863 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03864 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
03865 case AST_OPTION_RXGAIN:
03866 scp = (signed char *) data;
03867 idx = dahdi_get_index(chan, p, 0);
03868 if (idx < 0) {
03869 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03870 return -1;
03871 }
03872 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03873 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
03874 case AST_OPTION_TONE_VERIFY:
03875 if (!p->dsp)
03876 break;
03877 cp = (char *) data;
03878 switch (*cp) {
03879 case 1:
03880 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03881 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
03882 break;
03883 case 2:
03884 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03885 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
03886 break;
03887 default:
03888 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03889 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03890 break;
03891 }
03892 break;
03893 case AST_OPTION_TDD:
03894
03895 cp = (char *) data;
03896 p->mate = 0;
03897 if (!*cp) {
03898 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03899 if (p->tdd)
03900 tdd_free(p->tdd);
03901 p->tdd = 0;
03902 break;
03903 }
03904 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03905 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03906 dahdi_disable_ec(p);
03907
03908 if (!p->didtdd) {
03909 unsigned char mybuf[41000];
03910 unsigned char *buf;
03911 int size, res, fd, len;
03912 struct pollfd fds[1];
03913
03914 buf = mybuf;
03915 memset(buf, 0x7f, sizeof(mybuf));
03916 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03917 len = 40000;
03918 idx = dahdi_get_index(chan, p, 0);
03919 if (idx < 0) {
03920 ast_log(LOG_WARNING, "No index in TDD?\n");
03921 return -1;
03922 }
03923 fd = p->subs[idx].dfd;
03924 while (len) {
03925 if (ast_check_hangup(chan))
03926 return -1;
03927 size = len;
03928 if (size > READ_SIZE)
03929 size = READ_SIZE;
03930 fds[0].fd = fd;
03931 fds[0].events = POLLPRI | POLLOUT;
03932 fds[0].revents = 0;
03933 res = poll(fds, 1, -1);
03934 if (!res) {
03935 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03936 continue;
03937 }
03938
03939 if (fds[0].revents & POLLPRI)
03940 return -1;
03941 if (!(fds[0].revents & POLLOUT)) {
03942 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03943 continue;
03944 }
03945 res = write(fd, buf, size);
03946 if (res != size) {
03947 if (res == -1) return -1;
03948 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03949 break;
03950 }
03951 len -= size;
03952 buf += size;
03953 }
03954 p->didtdd = 1;
03955 }
03956 if (*cp == 2) {
03957 if (p->tdd)
03958 tdd_free(p->tdd);
03959 p->tdd = 0;
03960 p->mate = 1;
03961 break;
03962 }
03963 if (!p->tdd) {
03964 p->tdd = tdd_new();
03965 }
03966 break;
03967 case AST_OPTION_RELAXDTMF:
03968 if (!p->dsp)
03969 break;
03970 cp = (char *) data;
03971 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03972 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03973 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03974 break;
03975 case AST_OPTION_AUDIO_MODE:
03976 cp = (char *) data;
03977 if (!*cp) {
03978 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03979 x = 0;
03980 dahdi_disable_ec(p);
03981 } else {
03982 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03983 x = 1;
03984 }
03985 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03986 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03987 break;
03988 case AST_OPTION_OPRMODE:
03989 oprmode = (struct oprmode *) data;
03990 pp = oprmode->peer->tech_pvt;
03991 p->oprmode = pp->oprmode = 0;
03992
03993 p->oprpeer = pp;
03994 pp->oprpeer = p;
03995
03996 if (oprmode->mode)
03997 {
03998 pp->oprmode = oprmode->mode;
03999 p->oprmode = -oprmode->mode;
04000 }
04001 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
04002 oprmode->mode, chan->name,oprmode->peer->name);
04003 break;
04004 case AST_OPTION_ECHOCAN:
04005 cp = (char *) data;
04006 if (*cp) {
04007 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
04008 dahdi_enable_ec(p);
04009 } else {
04010 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
04011 dahdi_disable_ec(p);
04012 }
04013 break;
04014 }
04015 errno = 0;
04016
04017 return 0;
04018 }
04019
04020 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
04021 {
04022 struct dahdi_pvt *p = chan->tech_pvt;
04023
04024 if (!strcasecmp(data, "rxgain")) {
04025 ast_mutex_lock(&p->lock);
04026 snprintf(buf, len, "%f", p->rxgain);
04027 ast_mutex_unlock(&p->lock);
04028 } else if (!strcasecmp(data, "txgain")) {
04029 ast_mutex_lock(&p->lock);
04030 snprintf(buf, len, "%f", p->txgain);
04031 ast_mutex_unlock(&p->lock);
04032 } else {
04033 ast_copy_string(buf, "", len);
04034 }
04035 return 0;
04036 }
04037
04038
04039 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04040 {
04041
04042 int x;
04043 int hasslaves;
04044 if (!master)
04045 return;
04046 if (needlock) {
04047 ast_mutex_lock(&master->lock);
04048 if (slave) {
04049 while (ast_mutex_trylock(&slave->lock)) {
04050 DEADLOCK_AVOIDANCE(&master->lock);
04051 }
04052 }
04053 }
04054 hasslaves = 0;
04055 for (x = 0; x < MAX_SLAVES; x++) {
04056 if (master->slaves[x]) {
04057 if (!slave || (master->slaves[x] == slave)) {
04058
04059 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04060 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04061 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04062 master->slaves[x]->master = NULL;
04063 master->slaves[x] = NULL;
04064 } else
04065 hasslaves = 1;
04066 }
04067 if (!hasslaves)
04068 master->inconference = 0;
04069 }
04070 if (!slave) {
04071 if (master->master) {
04072
04073 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04074 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04075 hasslaves = 0;
04076 for (x = 0; x < MAX_SLAVES; x++) {
04077 if (master->master->slaves[x] == master)
04078 master->master->slaves[x] = NULL;
04079 else if (master->master->slaves[x])
04080 hasslaves = 1;
04081 }
04082 if (!hasslaves)
04083 master->master->inconference = 0;
04084 }
04085 master->master = NULL;
04086 }
04087 update_conf(master);
04088 if (needlock) {
04089 if (slave)
04090 ast_mutex_unlock(&slave->lock);
04091 ast_mutex_unlock(&master->lock);
04092 }
04093 }
04094
04095 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04096 int x;
04097 if (!slave || !master) {
04098 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04099 return;
04100 }
04101 for (x = 0; x < MAX_SLAVES; x++) {
04102 if (!master->slaves[x]) {
04103 master->slaves[x] = slave;
04104 break;
04105 }
04106 }
04107 if (x >= MAX_SLAVES) {
04108 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04109 master->slaves[MAX_SLAVES - 1] = slave;
04110 }
04111 if (slave->master)
04112 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04113 slave->master = master;
04114
04115 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04116 }
04117
04118 static void disable_dtmf_detect(struct dahdi_pvt *p)
04119 {
04120 int val;
04121
04122 p->ignoredtmf = 1;
04123
04124 val = 0;
04125 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04126
04127 if (!p->hardwaredtmf && p->dsp) {
04128 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
04129 ast_dsp_set_features(p->dsp, p->dsp_features);
04130 }
04131 }
04132
04133 static void enable_dtmf_detect(struct dahdi_pvt *p)
04134 {
04135 int val;
04136
04137 if (p->channel == CHAN_PSEUDO)
04138 return;
04139
04140 p->ignoredtmf = 0;
04141
04142 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04143 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04144
04145 if (!p->hardwaredtmf && p->dsp) {
04146 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
04147 ast_dsp_set_features(p->dsp, p->dsp_features);
04148 }
04149 }
04150
04151 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)
04152 {
04153 struct ast_channel *who;
04154 struct dahdi_pvt *p0, *p1, *op0, *op1;
04155 struct dahdi_pvt *master = NULL, *slave = NULL;
04156 struct ast_frame *f;
04157 int inconf = 0;
04158 int nothingok = 1;
04159 int ofd0, ofd1;
04160 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04161 int os0 = -1, os1 = -1;
04162 int priority = 0;
04163 struct ast_channel *oc0, *oc1;
04164 enum ast_bridge_result res;
04165
04166 #ifdef PRI_2BCT
04167 int triedtopribridge = 0;
04168 q931_call *q931c0 = NULL, *q931c1 = NULL;
04169 #endif
04170
04171
04172
04173
04174
04175
04176 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04177 return AST_BRIDGE_FAILED_NOWARN;
04178
04179 ast_channel_lock(c0);
04180 while (ast_channel_trylock(c1)) {
04181 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04182 }
04183
04184 p0 = c0->tech_pvt;
04185 p1 = c1->tech_pvt;
04186
04187 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04188 ast_channel_unlock(c0);
04189 ast_channel_unlock(c1);
04190 return AST_BRIDGE_FAILED_NOWARN;
04191 }
04192
04193 oi0 = dahdi_get_index(c0, p0, 0);
04194 oi1 = dahdi_get_index(c1, p1, 0);
04195 if ((oi0 < 0) || (oi1 < 0)) {
04196 ast_channel_unlock(c0);
04197 ast_channel_unlock(c1);
04198 return AST_BRIDGE_FAILED;
04199 }
04200
04201 op0 = p0 = c0->tech_pvt;
04202 op1 = p1 = c1->tech_pvt;
04203 ofd0 = c0->fds[0];
04204 ofd1 = c1->fds[0];
04205 oc0 = p0->owner;
04206 oc1 = p1->owner;
04207
04208 if (ast_mutex_trylock(&p0->lock)) {
04209
04210 ast_channel_unlock(c0);
04211 ast_channel_unlock(c1);
04212 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04213 return AST_BRIDGE_RETRY;
04214 }
04215 if (ast_mutex_trylock(&p1->lock)) {
04216
04217 ast_mutex_unlock(&p0->lock);
04218 ast_channel_unlock(c0);
04219 ast_channel_unlock(c1);
04220 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04221 return AST_BRIDGE_RETRY;
04222 }
04223
04224 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04225 if (p0->owner && p1->owner) {
04226
04227 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04228 master = p0;
04229 slave = p1;
04230 inconf = 1;
04231 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04232 master = p1;
04233 slave = p0;
04234 inconf = 1;
04235 } else {
04236 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04237 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04238 p0->channel,
04239 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04240 p0->subs[SUB_REAL].inthreeway, p0->channel,
04241 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04242 p1->subs[SUB_REAL].inthreeway);
04243 }
04244 nothingok = 0;
04245 }
04246 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04247 if (p1->subs[SUB_THREEWAY].inthreeway) {
04248 master = p1;
04249 slave = p0;
04250 nothingok = 0;
04251 }
04252 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04253 if (p0->subs[SUB_THREEWAY].inthreeway) {
04254 master = p0;
04255 slave = p1;
04256 nothingok = 0;
04257 }
04258 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04259
04260
04261 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04262 master = p1;
04263 slave = p0;
04264 nothingok = 0;
04265 }
04266 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04267
04268 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04269 master = p0;
04270 slave = p1;
04271 nothingok = 0;
04272 }
04273 }
04274 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04275 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04276 if (master && slave) {
04277
04278
04279
04280 if ((oi1 == SUB_THREEWAY) &&
04281 p1->subs[SUB_THREEWAY].inthreeway &&
04282 p1->subs[SUB_REAL].owner &&
04283 p1->subs[SUB_REAL].inthreeway &&
04284 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04285 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04286 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04287 os1 = p1->subs[SUB_REAL].owner->_state;
04288 } else {
04289 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04290 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04291 }
04292 if ((oi0 == SUB_THREEWAY) &&
04293 p0->subs[SUB_THREEWAY].inthreeway &&
04294 p0->subs[SUB_REAL].owner &&
04295 p0->subs[SUB_REAL].inthreeway &&
04296 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04297 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04298 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04299 os0 = p0->subs[SUB_REAL].owner->_state;
04300 } else {
04301 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04302 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04303 }
04304 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04305 if (!p0->echocanbridged || !p1->echocanbridged) {
04306
04307 dahdi_disable_ec(p0);
04308 dahdi_disable_ec(p1);
04309 }
04310 }
04311 dahdi_link(slave, master);
04312 master->inconference = inconf;
04313 } else if (!nothingok)
04314 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04315
04316 update_conf(p0);
04317 update_conf(p1);
04318 t0 = p0->subs[SUB_REAL].inthreeway;
04319 t1 = p1->subs[SUB_REAL].inthreeway;
04320
04321 ast_mutex_unlock(&p0->lock);
04322 ast_mutex_unlock(&p1->lock);
04323
04324 ast_channel_unlock(c0);
04325 ast_channel_unlock(c1);
04326
04327
04328 if ((!master || !slave) && !nothingok) {
04329 dahdi_enable_ec(p0);
04330 dahdi_enable_ec(p1);
04331 return AST_BRIDGE_FAILED;
04332 }
04333
04334 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04335
04336 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04337 disable_dtmf_detect(op0);
04338
04339 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04340 disable_dtmf_detect(op1);
04341
04342 for (;;) {
04343 struct ast_channel *c0_priority[2] = {c0, c1};
04344 struct ast_channel *c1_priority[2] = {c1, c0};
04345
04346
04347
04348
04349 ast_channel_lock(c0);
04350 while (ast_channel_trylock(c1)) {
04351 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04352 }
04353
04354 p0 = c0->tech_pvt;
04355 p1 = c1->tech_pvt;
04356
04357 if (op0 == p0)
04358 i0 = dahdi_get_index(c0, p0, 1);
04359 if (op1 == p1)
04360 i1 = dahdi_get_index(c1, p1, 1);
04361
04362 ast_channel_unlock(c0);
04363 ast_channel_unlock(c1);
04364
04365 if (!timeoutms ||
04366 (op0 != p0) ||
04367 (op1 != p1) ||
04368 (ofd0 != c0->fds[0]) ||
04369 (ofd1 != c1->fds[0]) ||
04370 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04371 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04372 (oc0 != p0->owner) ||
04373 (oc1 != p1->owner) ||
04374 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04375 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04376 (oi0 != i0) ||
04377 (oi1 != i1)) {
04378 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04379 op0->channel, oi0, op1->channel, oi1);
04380 res = AST_BRIDGE_RETRY;
04381 goto return_from_bridge;
04382 }
04383
04384 #ifdef PRI_2BCT
04385 q931c0 = p0->call;
04386 q931c1 = p1->call;
04387 if (p0->transfer && p1->transfer
04388 && q931c0 && q931c1
04389 && !triedtopribridge) {
04390 pri_channel_bridge(q931c0, q931c1);
04391 triedtopribridge = 1;
04392 }
04393 #endif
04394
04395 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04396 if (!who) {
04397 ast_debug(1, "Ooh, empty read...\n");
04398 continue;
04399 }
04400 f = ast_read(who);
04401 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04402 *fo = f;
04403 *rc = who;
04404 res = AST_BRIDGE_COMPLETE;
04405 goto return_from_bridge;
04406 }
04407 if (f->frametype == AST_FRAME_DTMF) {
04408 if ((who == c0) && p0->pulsedial) {
04409 ast_write(c1, f);
04410 } else if ((who == c1) && p1->pulsedial) {
04411 ast_write(c0, f);
04412 } else {
04413 *fo = f;
04414 *rc = who;
04415 res = AST_BRIDGE_COMPLETE;
04416 goto return_from_bridge;
04417 }
04418 }
04419 ast_frfree(f);
04420
04421
04422 priority = !priority;
04423 }
04424
04425 return_from_bridge:
04426 if (op0 == p0)
04427 dahdi_enable_ec(p0);
04428
04429 if (op1 == p1)
04430 dahdi_enable_ec(p1);
04431
04432 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04433 enable_dtmf_detect(op0);
04434
04435 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04436 enable_dtmf_detect(op1);
04437
04438 dahdi_unlink(slave, master, 1);
04439
04440 return res;
04441 }
04442
04443 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04444 {
04445 struct dahdi_pvt *p = newchan->tech_pvt;
04446 int x;
04447 ast_mutex_lock(&p->lock);
04448 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04449 if (p->owner == oldchan) {
04450 p->owner = newchan;
04451 }
04452 for (x = 0; x < 3; x++)
04453 if (p->subs[x].owner == oldchan) {
04454 if (!x)
04455 dahdi_unlink(NULL, p, 0);
04456 p->subs[x].owner = newchan;
04457 }
04458 if (newchan->_state == AST_STATE_RINGING)
04459 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04460 update_conf(p);
04461 ast_mutex_unlock(&p->lock);
04462 return 0;
04463 }
04464
04465 static int dahdi_ring_phone(struct dahdi_pvt *p)
04466 {
04467 int x;
04468 int res;
04469
04470 x = 0;
04471 x = DAHDI_ONHOOK;
04472 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04473 do {
04474 x = DAHDI_RING;
04475 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04476 if (res) {
04477 switch (errno) {
04478 case EBUSY:
04479 case EINTR:
04480
04481 usleep(10000);
04482 continue;
04483 case EINPROGRESS:
04484 res = 0;
04485 break;
04486 default:
04487 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04488 res = 0;
04489 }
04490 }
04491 } while (res);
04492 return res;
04493 }
04494
04495 static void *ss_thread(void *data);
04496
04497 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
04498
04499 static int attempt_transfer(struct dahdi_pvt *p)
04500 {
04501
04502
04503
04504 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04505
04506
04507 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04508 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04509 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04510 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04511 }
04512 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04513 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04514 }
04515 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04516 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04517 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04518 return -1;
04519 }
04520
04521 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04522 unalloc_sub(p, SUB_THREEWAY);
04523 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04524 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04525 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04526 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04527 }
04528 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04529 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04530 }
04531 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04532 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04533 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04534 return -1;
04535 }
04536
04537 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04538 ast_channel_unlock(p->subs[SUB_REAL].owner);
04539 unalloc_sub(p, SUB_THREEWAY);
04540
04541 return 1;
04542 } else {
04543 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04544 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04545 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04546 return -1;
04547 }
04548 return 0;
04549 }
04550
04551 static int check_for_conference(struct dahdi_pvt *p)
04552 {
04553 struct dahdi_confinfo ci;
04554
04555 if (p->master || (p->confno > -1))
04556 return 0;
04557 memset(&ci, 0, sizeof(ci));
04558 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04559 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04560 return 0;
04561 }
04562
04563
04564
04565 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04566 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04567 return 1;
04568 }
04569 return 0;
04570 }
04571
04572
04573
04574
04575
04576
04577 static int get_alarms(struct dahdi_pvt *p)
04578 {
04579 int res;
04580 struct dahdi_spaninfo zi;
04581 struct dahdi_params params;
04582
04583 memset(&zi, 0, sizeof(zi));
04584 zi.spanno = p->span;
04585
04586 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04587 if (zi.alarms != DAHDI_ALARM_NONE)
04588 return zi.alarms;
04589 } else {
04590 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04591 return 0;
04592 }
04593
04594
04595 memset(¶ms, 0, sizeof(params));
04596 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04597 return params.chan_alarms;
04598
04599 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04600
04601 return DAHDI_ALARM_NONE;
04602 }
04603
04604 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
04605 {
04606 struct dahdi_pvt *p = ast->tech_pvt;
04607 struct ast_frame *f = *dest;
04608
04609 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04610
04611 if (p->confirmanswer) {
04612 ast_debug(1, "Confirm answer on %s!\n", ast->name);
04613
04614
04615 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04616 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04617 *dest = &p->subs[idx].f;
04618
04619 p->confirmanswer = 0;
04620 } else if (p->callwaitcas) {
04621 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04622 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04623 if (p->cidspill)
04624 ast_free(p->cidspill);
04625 send_cwcidspill(p);
04626 }
04627 p->callwaitcas = 0;
04628 p->subs[idx].f.frametype = AST_FRAME_NULL;
04629 p->subs[idx].f.subclass = 0;
04630 *dest = &p->subs[idx].f;
04631 } else if (f->subclass == 'f') {
04632
04633 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04634 p->faxhandled = 1;
04635 if (strcmp(ast->exten, "fax")) {
04636 const char *target_context = S_OR(ast->macrocontext, ast->context);
04637
04638
04639
04640
04641
04642 ast_mutex_unlock(&p->lock);
04643 ast_channel_unlock(ast);
04644 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04645 ast_channel_lock(ast);
04646 ast_mutex_lock(&p->lock);
04647 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04648
04649 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04650 if (ast_async_goto(ast, target_context, "fax", 1))
04651 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04652 } else {
04653 ast_channel_lock(ast);
04654 ast_mutex_lock(&p->lock);
04655 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04656 }
04657 } else {
04658 ast_debug(1, "Already in a fax extension, not redirecting\n");
04659 }
04660 } else {
04661 ast_debug(1, "Fax already handled\n");
04662 }
04663 dahdi_confmute(p, 0);
04664 p->subs[idx].f.frametype = AST_FRAME_NULL;
04665 p->subs[idx].f.subclass = 0;
04666 *dest = &p->subs[idx].f;
04667 }
04668 }
04669
04670 static void handle_alarms(struct dahdi_pvt *p, int alms)
04671 {
04672 const char *alarm_str = alarm2str(alms);
04673
04674 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04675 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04676 "Alarm: %s\r\n"
04677 "Channel: %d\r\n",
04678 alarm_str, p->channel);
04679 }
04680
04681 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04682 {
04683 int res, x;
04684 int idx, mysig;
04685 char *c;
04686 struct dahdi_pvt *p = ast->tech_pvt;
04687 pthread_t threadid;
04688 struct ast_channel *chan;
04689 struct ast_frame *f;
04690
04691 idx = dahdi_get_index(ast, p, 0);
04692 mysig = p->sig;
04693 if (p->outsigmod > -1)
04694 mysig = p->outsigmod;
04695 p->subs[idx].f.frametype = AST_FRAME_NULL;
04696 p->subs[idx].f.subclass = 0;
04697 p->subs[idx].f.datalen = 0;
04698 p->subs[idx].f.samples = 0;
04699 p->subs[idx].f.mallocd = 0;
04700 p->subs[idx].f.offset = 0;
04701 p->subs[idx].f.src = "dahdi_handle_event";
04702 p->subs[idx].f.data.ptr = NULL;
04703 f = &p->subs[idx].f;
04704
04705 if (idx < 0)
04706 return &p->subs[idx].f;
04707 if (p->fake_event) {
04708 res = p->fake_event;
04709 p->fake_event = 0;
04710 } else
04711 res = dahdi_get_event(p->subs[idx].dfd);
04712
04713 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
04714
04715 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04716 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04717 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04718 #ifdef HAVE_PRI
04719 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04720
04721 } else {
04722 #endif
04723 dahdi_confmute(p, 0);
04724 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
04725 p->subs[idx].f.subclass = res & 0xff;
04726 #ifdef HAVE_PRI
04727 }
04728 #endif
04729 dahdi_handle_dtmfup(ast, idx, &f);
04730 return f;
04731 }
04732
04733 if (res & DAHDI_EVENT_DTMFDOWN) {
04734 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04735
04736 dahdi_confmute(p, 1);
04737 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
04738 p->subs[idx].f.subclass = res & 0xff;
04739 return &p->subs[idx].f;
04740 }
04741
04742 switch (res) {
04743 case DAHDI_EVENT_EC_DISABLED:
04744 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04745 p->echocanon = 0;
04746 break;
04747 case DAHDI_EVENT_BITSCHANGED:
04748 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
04749 case DAHDI_EVENT_PULSE_START:
04750
04751 if (!ast->pbx)
04752 tone_zone_play_tone(p->subs[idx].dfd, -1);
04753 break;
04754 case DAHDI_EVENT_DIALCOMPLETE:
04755 if (p->inalarm) break;
04756 if ((p->radio || (p->oprmode < 0))) break;
04757 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
04758 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04759 return NULL;
04760 }
04761 if (!x) {
04762 dahdi_enable_ec(p);
04763 if (p->echobreak) {
04764 dahdi_train_ec(p);
04765 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04766 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04767 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04768 p->echobreak = 0;
04769 } else {
04770 p->dialing = 0;
04771 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04772
04773 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04774 ast_setstate(ast, AST_STATE_UP);
04775 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04776 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04777 break;
04778 } else {
04779
04780 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04781 }
04782 }
04783 if (ast->_state == AST_STATE_DIALING) {
04784 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04785 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04786 } 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)))) {
04787 ast_setstate(ast, AST_STATE_RINGING);
04788 } else if (!p->answeronpolarityswitch) {
04789 ast_setstate(ast, AST_STATE_UP);
04790 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04791 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04792
04793 p->polarity = POLARITY_REV;
04794 } else {
04795
04796 p->polarity = POLARITY_IDLE;
04797 }
04798 }
04799 }
04800 }
04801 break;
04802 case DAHDI_EVENT_ALARM:
04803 #ifdef HAVE_PRI
04804 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04805 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04806
04807 if (p->call) {
04808 if (p->pri && p->pri->pri) {
04809 if (!pri_grab(p, p->pri)) {
04810 pri_hangup(p->pri->pri, p->call, -1);
04811 pri_destroycall(p->pri->pri, p->call);
04812 p->call = NULL;
04813 pri_rel(p->pri);
04814 } else
04815 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04816 } else
04817 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04818 }
04819 if (p->owner)
04820 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04821 }
04822 }
04823 if (p->bearer)
04824 p->bearer->inalarm = 1;
04825 else
04826 #endif
04827 p->inalarm = 1;
04828 res = get_alarms(p);
04829 handle_alarms(p, res);
04830 #ifdef HAVE_PRI
04831 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04832
04833 } else {
04834 break;
04835 }
04836 #endif
04837 #ifdef HAVE_SS7
04838 if (p->sig == SIG_SS7)
04839 break;
04840 #endif
04841 case DAHDI_EVENT_ONHOOK:
04842 if (p->radio) {
04843 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04844 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
04845 break;
04846 }
04847 if (p->oprmode < 0)
04848 {
04849 if (p->oprmode != -1) break;
04850 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04851 {
04852
04853 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04854 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04855 save_conference(p->oprpeer);
04856 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04857 }
04858 break;
04859 }
04860 switch (p->sig) {
04861 case SIG_FXOLS:
04862 case SIG_FXOGS:
04863 case SIG_FXOKS:
04864 p->onhooktime = time(NULL);
04865 p->msgstate = -1;
04866
04867 if (idx == SUB_REAL) {
04868
04869 if (p->subs[SUB_CALLWAIT].owner) {
04870
04871 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04872 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04873 unalloc_sub(p, SUB_CALLWAIT);
04874 #if 0
04875 p->subs[idx].needanswer = 0;
04876 p->subs[idx].needringing = 0;
04877 #endif
04878 p->callwaitingrepeat = 0;
04879 p->cidcwexpire = 0;
04880 p->owner = NULL;
04881
04882 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04883 p->dialing = 1;
04884 dahdi_ring_phone(p);
04885 } else if (p->subs[SUB_THREEWAY].owner) {
04886 unsigned int mssinceflash;
04887
04888
04889 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04890
04891 DLA_UNLOCK(&p->lock);
04892 CHANNEL_DEADLOCK_AVOIDANCE(ast);
04893
04894
04895
04896 DLA_LOCK(&p->lock);
04897 if (p->owner != ast) {
04898 ast_log(LOG_WARNING, "This isn't good...\n");
04899 return NULL;
04900 }
04901 }
04902 if (!p->subs[SUB_THREEWAY].owner) {
04903 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04904 return NULL;
04905 }
04906 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04907 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04908 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04909
04910
04911 if (p->subs[SUB_THREEWAY].owner)
04912 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
04913 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04914 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04915 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04916 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04917 if (p->transfer) {
04918
04919 p->subs[SUB_REAL].inthreeway = 0;
04920 p->subs[SUB_THREEWAY].inthreeway = 0;
04921
04922 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04923 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04924
04925 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04926 p->owner = NULL;
04927
04928 dahdi_ring_phone(p);
04929 } else {
04930 if ((res = attempt_transfer(p)) < 0) {
04931 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04932 if (p->subs[SUB_THREEWAY].owner)
04933 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04934 } else if (res) {
04935
04936 if (p->subs[SUB_THREEWAY].owner)
04937 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04938 break;
04939 }
04940 }
04941 } else {
04942 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04943 if (p->subs[SUB_THREEWAY].owner)
04944 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04945 }
04946 } else {
04947 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04948
04949 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04950 p->owner = NULL;
04951
04952 dahdi_ring_phone(p);
04953 }
04954 }
04955 } else {
04956 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
04957 }
04958
04959 default:
04960 dahdi_disable_ec(p);
04961 return NULL;
04962 }
04963 break;
04964 case DAHDI_EVENT_RINGOFFHOOK:
04965 if (p->inalarm) break;
04966 if (p->oprmode < 0)
04967 {
04968 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04969 {
04970
04971 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04972 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04973 restore_conference(p->oprpeer);
04974 }
04975 break;
04976 }
04977 if (p->radio)
04978 {
04979 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04980 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
04981 break;
04982 }
04983
04984
04985 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04986 c = strchr(p->dialdest, '/');
04987 if (c)
04988 c++;
04989 else
04990 c = p->dialdest;
04991 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04992 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04993 if (strlen(p->dop.dialstr) > 4) {
04994 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04995 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04996 p->echorest[sizeof(p->echorest) - 1] = '\0';
04997 p->echobreak = 1;
04998 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04999 } else
05000 p->echobreak = 0;
05001 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05002 int saveerr = errno;
05003
05004 x = DAHDI_ONHOOK;
05005 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05006 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05007 return NULL;
05008 }
05009 p->dialing = 1;
05010 return &p->subs[idx].f;
05011 }
05012 switch (p->sig) {
05013 case SIG_FXOLS:
05014 case SIG_FXOGS:
05015 case SIG_FXOKS:
05016 switch (ast->_state) {
05017 case AST_STATE_RINGING:
05018 dahdi_enable_ec(p);
05019 dahdi_train_ec(p);
05020 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05021 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05022
05023 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05024 ast_debug(1, "channel %d answered\n", p->channel);
05025 if (p->cidspill) {
05026
05027 ast_free(p->cidspill);
05028 p->cidspill = NULL;
05029 }
05030 p->dialing = 0;
05031 p->callwaitcas = 0;
05032 if (p->confirmanswer) {
05033
05034 p->subs[idx].f.frametype = AST_FRAME_NULL;
05035 p->subs[idx].f.subclass = 0;
05036 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05037
05038 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05039 if (res < 0) {
05040 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05041 p->dop.dialstr[0] = '\0';
05042 return NULL;
05043 } else {
05044 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05045 p->subs[idx].f.frametype = AST_FRAME_NULL;
05046 p->subs[idx].f.subclass = 0;
05047 p->dialing = 1;
05048 }
05049 p->dop.dialstr[0] = '\0';
05050 ast_setstate(ast, AST_STATE_DIALING);
05051 } else
05052 ast_setstate(ast, AST_STATE_UP);
05053 return &p->subs[idx].f;
05054 case AST_STATE_DOWN:
05055 ast_setstate(ast, AST_STATE_RING);
05056 ast->rings = 1;
05057 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05058 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
05059 ast_debug(1, "channel %d picked up\n", p->channel);
05060 return &p->subs[idx].f;
05061 case AST_STATE_UP:
05062
05063 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05064
05065 if (ast_bridged_channel(p->owner))
05066 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05067 p->subs[idx].needunhold = 1;
05068 break;
05069 case AST_STATE_RESERVED:
05070
05071 if (has_voicemail(p))
05072 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05073 else
05074 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05075 break;
05076 default:
05077 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05078 }
05079 break;
05080 case SIG_FXSLS:
05081 case SIG_FXSGS:
05082 case SIG_FXSKS:
05083 if (ast->_state == AST_STATE_RING) {
05084 p->ringt = p->ringt_base;
05085 }
05086
05087
05088
05089 ast_debug(1, "Setting IDLE polarity due "
05090 "to ring. Old polarity was %d\n",
05091 p->polarity);
05092 p->polarity = POLARITY_IDLE;
05093
05094
05095 case SIG_EM:
05096 case SIG_EM_E1:
05097 case SIG_EMWINK:
05098 case SIG_FEATD:
05099 case SIG_FEATDMF:
05100 case SIG_FEATDMF_TA:
05101 case SIG_E911:
05102 case SIG_FGC_CAMA:
05103 case SIG_FGC_CAMAMF:
05104 case SIG_FEATB:
05105 case SIG_SF:
05106 case SIG_SFWINK:
05107 case SIG_SF_FEATD:
05108 case SIG_SF_FEATDMF:
05109 case SIG_SF_FEATB:
05110 if (ast->_state == AST_STATE_PRERING)
05111 ast_setstate(ast, AST_STATE_RING);
05112 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05113 ast_debug(1, "Ring detected\n");
05114 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05115 p->subs[idx].f.subclass = AST_CONTROL_RING;
05116 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05117 ast_debug(1, "Line answered\n");
05118 if (p->confirmanswer) {
05119 p->subs[idx].f.frametype = AST_FRAME_NULL;
05120 p->subs[idx].f.subclass = 0;
05121 } else {
05122 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05123 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05124 ast_setstate(ast, AST_STATE_UP);
05125 }
05126 } else if (ast->_state != AST_STATE_RING)
05127 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05128 break;
05129 default:
05130 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05131 }
05132 break;
05133 case DAHDI_EVENT_RINGBEGIN:
05134 switch (p->sig) {
05135 case SIG_FXSLS:
05136 case SIG_FXSGS:
05137 case SIG_FXSKS:
05138 if (ast->_state == AST_STATE_RING) {
05139 p->ringt = p->ringt_base;
05140 }
05141 break;
05142 }
05143 break;
05144 case DAHDI_EVENT_RINGEROFF:
05145 if (p->inalarm) break;
05146 if ((p->radio || (p->oprmode < 0))) break;
05147 ast->rings++;
05148 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05149 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05150 ast_free(p->cidspill);
05151 p->cidspill = NULL;
05152 p->callwaitcas = 0;
05153 }
05154 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05155 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05156 break;
05157 case DAHDI_EVENT_RINGERON:
05158 break;
05159 case DAHDI_EVENT_NOALARM:
05160 p->inalarm = 0;
05161 #ifdef HAVE_PRI
05162
05163 if (p->bearer)
05164 p->bearer->inalarm = 0;
05165 #endif
05166 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05167 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05168 "Channel: %d\r\n", p->channel);
05169 break;
05170 case DAHDI_EVENT_WINKFLASH:
05171 if (p->inalarm) break;
05172 if (p->radio) break;
05173 if (p->oprmode < 0) break;
05174 if (p->oprmode > 1)
05175 {
05176 struct dahdi_params par;
05177
05178 memset(&par, 0, sizeof(par));
05179 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05180 {
05181 if (!par.rxisoffhook)
05182 {
05183
05184 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05185 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05186 save_conference(p);
05187 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05188 }
05189 }
05190 break;
05191 }
05192
05193 p->flashtime = ast_tvnow();
05194 switch (mysig) {
05195 case SIG_FXOLS:
05196 case SIG_FXOGS:
05197 case SIG_FXOKS:
05198 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05199 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05200 p->callwaitcas = 0;
05201
05202 if (idx != SUB_REAL) {
05203 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
05204 goto winkflashdone;
05205 }
05206
05207 if (p->subs[SUB_CALLWAIT].owner) {
05208
05209 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05210 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05211 p->owner = p->subs[SUB_REAL].owner;
05212 ast_debug(1, "Making %s the new owner\n", p->owner->name);
05213 if (p->owner->_state == AST_STATE_RINGING) {
05214 ast_setstate(p->owner, AST_STATE_UP);
05215 p->subs[SUB_REAL].needanswer = 1;
05216 }
05217 p->callwaitingrepeat = 0;
05218 p->cidcwexpire = 0;
05219
05220 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05221 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05222 S_OR(p->mohsuggest, NULL),
05223 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05224 }
05225 p->subs[SUB_CALLWAIT].needhold = 1;
05226 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05227 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05228 S_OR(p->mohsuggest, NULL),
05229 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05230 }
05231 p->subs[SUB_REAL].needunhold = 1;
05232 } else if (!p->subs[SUB_THREEWAY].owner) {
05233 if (!p->threewaycalling) {
05234
05235 p->subs[SUB_REAL].needflash = 1;
05236 goto winkflashdone;
05237 } else if (!check_for_conference(p)) {
05238 char cid_num[256];
05239 char cid_name[256];
05240
05241 cid_num[0] = 0;
05242 cid_name[0] = 0;
05243 if (p->dahditrcallerid && p->owner) {
05244 if (p->owner->cid.cid_num)
05245 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05246 if (p->owner->cid.cid_name)
05247 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05248 }
05249
05250
05251 if (!((ast->pbx) ||
05252 (ast->_state == AST_STATE_UP) ||
05253 (ast->_state == AST_STATE_RING))) {
05254 ast_debug(1, "Flash when call not up or ringing\n");
05255 goto winkflashdone;
05256 }
05257 if (alloc_sub(p, SUB_THREEWAY)) {
05258 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05259 goto winkflashdone;
05260 }
05261
05262 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05263 if (p->dahditrcallerid) {
05264 if (!p->origcid_num)
05265 p->origcid_num = ast_strdup(p->cid_num);
05266 if (!p->origcid_name)
05267 p->origcid_name = ast_strdup(p->cid_name);
05268 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05269 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05270 }
05271
05272 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05273
05274 dahdi_disable_ec(p);
05275 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05276 if (res)
05277 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05278 p->owner = chan;
05279 if (!chan) {
05280 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05281 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05282 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05283 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05284 dahdi_enable_ec(p);
05285 ast_hangup(chan);
05286 } else {
05287 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05288 int way3bridge = 0, cdr3way = 0;
05289
05290 if (!other) {
05291 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05292 } else
05293 way3bridge = 1;
05294
05295 if (p->subs[SUB_THREEWAY].owner->cdr)
05296 cdr3way = 1;
05297
05298 ast_verb(3, "Started three way call on channel %d\n", p->channel);
05299
05300
05301 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05302 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05303 S_OR(p->mohsuggest, NULL),
05304 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05305 }
05306 p->subs[SUB_THREEWAY].needhold = 1;
05307 }
05308 }
05309 } else {
05310
05311 if (p->subs[SUB_THREEWAY].inthreeway) {
05312
05313 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05314
05315 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05316
05317 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05318 p->owner = p->subs[SUB_REAL].owner;
05319 }
05320
05321 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05322 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05323 p->subs[SUB_REAL].inthreeway = 0;
05324 p->subs[SUB_THREEWAY].inthreeway = 0;
05325 } else {
05326
05327 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05328 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05329 int otherindex = SUB_THREEWAY;
05330 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05331 int way3bridge = 0, cdr3way = 0;
05332
05333 if (!other) {
05334 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05335 } else
05336 way3bridge = 1;
05337
05338 if (p->subs[SUB_THREEWAY].owner->cdr)
05339 cdr3way = 1;
05340
05341 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05342
05343 p->subs[SUB_THREEWAY].inthreeway = 1;
05344 p->subs[SUB_REAL].inthreeway = 1;
05345 if (ast->_state == AST_STATE_UP) {
05346 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05347 otherindex = SUB_REAL;
05348 }
05349 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05350 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05351 p->subs[otherindex].needunhold = 1;
05352 p->owner = p->subs[SUB_REAL].owner;
05353 if (ast->_state == AST_STATE_RINGING) {
05354 ast_debug(1, "Enabling ringtone on real and threeway\n");
05355 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05356 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05357 }
05358 } else {
05359 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05360 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05361 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05362 p->owner = p->subs[SUB_REAL].owner;
05363 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05364 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05365 p->subs[SUB_REAL].needunhold = 1;
05366 dahdi_enable_ec(p);
05367 }
05368
05369 }
05370 }
05371 winkflashdone:
05372 update_conf(p);
05373 break;
05374 case SIG_EM:
05375 case SIG_EM_E1:
05376 case SIG_FEATD:
05377 case SIG_SF:
05378 case SIG_SFWINK:
05379 case SIG_SF_FEATD:
05380 case SIG_FXSLS:
05381 case SIG_FXSGS:
05382 if (option_debug) {
05383 if (p->dialing)
05384 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05385 else
05386 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05387 }
05388 break;
05389 case SIG_FEATDMF_TA:
05390 switch (p->whichwink) {
05391 case 0:
05392 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05393 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05394 break;
05395 case 1:
05396 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05397 break;
05398 case 2:
05399 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05400 return NULL;
05401 }
05402 p->whichwink++;
05403
05404 case SIG_FEATDMF:
05405 case SIG_E911:
05406 case SIG_FGC_CAMAMF:
05407 case SIG_FGC_CAMA:
05408 case SIG_FEATB:
05409 case SIG_SF_FEATDMF:
05410 case SIG_SF_FEATB:
05411 case SIG_EMWINK:
05412
05413 if (!ast_strlen_zero(p->dop.dialstr)) {
05414 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05415 if (res < 0) {
05416 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05417 p->dop.dialstr[0] = '\0';
05418 return NULL;
05419 } else
05420 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05421 }
05422 p->dop.dialstr[0] = '\0';
05423 break;
05424 default:
05425 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05426 }
05427 break;
05428 case DAHDI_EVENT_HOOKCOMPLETE:
05429 if (p->inalarm) break;
05430 if ((p->radio || (p->oprmode < 0))) break;
05431 switch (mysig) {
05432 case SIG_FXSLS:
05433 case SIG_FXSGS:
05434 case SIG_FXSKS:
05435 case SIG_EM:
05436 case SIG_EM_E1:
05437 case SIG_EMWINK:
05438 case SIG_FEATD:
05439 case SIG_SF:
05440 case SIG_SFWINK:
05441 case SIG_SF_FEATD:
05442 if (!ast_strlen_zero(p->dop.dialstr)) {
05443 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05444 if (res < 0) {
05445 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05446 p->dop.dialstr[0] = '\0';
05447 return NULL;
05448 } else
05449 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05450 }
05451 p->dop.dialstr[0] = '\0';
05452 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05453 break;
05454 case SIG_FEATDMF:
05455 case SIG_FEATDMF_TA:
05456 case SIG_E911:
05457 case SIG_FGC_CAMA:
05458 case SIG_FGC_CAMAMF:
05459 case SIG_FEATB:
05460 case SIG_SF_FEATDMF:
05461 case SIG_SF_FEATB:
05462 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05463 break;
05464 default:
05465 break;
05466 }
05467 break;
05468 case DAHDI_EVENT_POLARITY:
05469
05470
05471
05472
05473
05474
05475
05476
05477
05478 if (p->polarityonanswerdelay > 0) {
05479
05480 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05481 switch (ast->_state) {
05482 case AST_STATE_DIALING:
05483 case AST_STATE_RINGING:
05484 if (p->answeronpolarityswitch) {
05485 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
05486 ast_setstate(p->owner, AST_STATE_UP);
05487 p->polarity = POLARITY_REV;
05488 if (p->hanguponpolarityswitch) {
05489 p->polaritydelaytv = ast_tvnow();
05490 }
05491 } else {
05492 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
05493 }
05494 break;
05495 case AST_STATE_UP:
05496 case AST_STATE_RING:
05497 if (p->hanguponpolarityswitch) {
05498 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
05499 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05500 p->polarity = POLARITY_IDLE;
05501 } else {
05502 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
05503 }
05504 break;
05505
05506 case AST_STATE_DOWN:
05507 case AST_STATE_RESERVED:
05508 case AST_STATE_OFFHOOK:
05509 case AST_STATE_BUSY:
05510 case AST_STATE_DIALING_OFFHOOK:
05511 case AST_STATE_PRERING:
05512 default:
05513 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05514 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
05515 }
05516
05517 }
05518
05519 } else {
05520
05521 switch (ast->_state) {
05522 case AST_STATE_DIALING:
05523 case AST_STATE_RINGING:
05524 if (p->answeronpolarityswitch) {
05525 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
05526 }
05527 break;
05528
05529 case AST_STATE_UP:
05530 case AST_STATE_RING:
05531 if (p->hanguponpolarityswitch) {
05532 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);
05533 }
05534 break;
05535
05536 default:
05537 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05538 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
05539 }
05540 }
05541 }
05542 }
05543
05544 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) );
05545 break;
05546 default:
05547 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05548 }
05549 return &p->subs[idx].f;
05550 }
05551
05552 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05553 {
05554 struct dahdi_pvt *p = ast->tech_pvt;
05555 int res;
05556 int usedindex=-1;
05557 int idx;
05558 struct ast_frame *f;
05559
05560
05561 idx = dahdi_get_index(ast, p, 1);
05562
05563 p->subs[idx].f.frametype = AST_FRAME_NULL;
05564 p->subs[idx].f.datalen = 0;
05565 p->subs[idx].f.samples = 0;
05566 p->subs[idx].f.mallocd = 0;
05567 p->subs[idx].f.offset = 0;
05568 p->subs[idx].f.subclass = 0;
05569 p->subs[idx].f.delivery = ast_tv(0,0);
05570 p->subs[idx].f.src = "dahdi_exception";
05571 p->subs[idx].f.data.ptr = NULL;
05572
05573
05574 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05575
05576
05577
05578
05579
05580 if (p->fake_event) {
05581 res = p->fake_event;
05582 p->fake_event = 0;
05583 } else
05584 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05585
05586 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05587 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05588 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05589 p->owner = p->subs[SUB_REAL].owner;
05590 if (p->owner && ast_bridged_channel(p->owner))
05591 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05592 p->subs[SUB_REAL].needunhold = 1;
05593 }
05594 switch (res) {
05595 case DAHDI_EVENT_ONHOOK:
05596 dahdi_disable_ec(p);
05597 if (p->owner) {
05598 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05599 dahdi_ring_phone(p);
05600 p->callwaitingrepeat = 0;
05601 p->cidcwexpire = 0;
05602 } else
05603 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05604 update_conf(p);
05605 break;
05606 case DAHDI_EVENT_RINGOFFHOOK:
05607 dahdi_enable_ec(p);
05608 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05609 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05610 p->subs[SUB_REAL].needanswer = 1;
05611 p->dialing = 0;
05612 }
05613 break;
05614 case DAHDI_EVENT_HOOKCOMPLETE:
05615 case DAHDI_EVENT_RINGERON:
05616 case DAHDI_EVENT_RINGEROFF:
05617
05618 break;
05619 case DAHDI_EVENT_WINKFLASH:
05620 p->flashtime = ast_tvnow();
05621 if (p->owner) {
05622 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05623 if (p->owner->_state != AST_STATE_UP) {
05624
05625 usedindex = dahdi_get_index(p->owner, p, 0);
05626 if (usedindex > -1) {
05627 p->subs[usedindex].needanswer = 1;
05628 }
05629 ast_setstate(p->owner, AST_STATE_UP);
05630 }
05631 p->callwaitingrepeat = 0;
05632 p->cidcwexpire = 0;
05633 if (ast_bridged_channel(p->owner))
05634 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05635 p->subs[SUB_REAL].needunhold = 1;
05636 } else
05637 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05638 update_conf(p);
05639 break;
05640 default:
05641 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05642 }
05643 f = &p->subs[idx].f;
05644 return f;
05645 }
05646 if (!(p->radio || (p->oprmode < 0)))
05647 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05648
05649 if (ast != p->owner) {
05650 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05651 f = &p->subs[idx].f;
05652 return f;
05653 }
05654 f = dahdi_handle_event(ast);
05655 return f;
05656 }
05657
05658 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05659 {
05660 struct dahdi_pvt *p = ast->tech_pvt;
05661 struct ast_frame *f;
05662 ast_mutex_lock(&p->lock);
05663 f = __dahdi_exception(ast);
05664 ast_mutex_unlock(&p->lock);
05665 return f;
05666 }
05667
05668 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05669 {
05670 struct dahdi_pvt *p = ast->tech_pvt;
05671 int res;
05672 int idx;
05673 void *readbuf;
05674 struct ast_frame *f;
05675
05676 while (ast_mutex_trylock(&p->lock)) {
05677 CHANNEL_DEADLOCK_AVOIDANCE(ast);
05678 }
05679
05680 idx = dahdi_get_index(ast, p, 0);
05681
05682
05683 if (idx < 0) {
05684 ast_log(LOG_WARNING, "We dont exist?\n");
05685 ast_mutex_unlock(&p->lock);
05686 return NULL;
05687 }
05688
05689 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05690 ast_mutex_unlock(&p->lock);
05691 return NULL;
05692 }
05693
05694 p->subs[idx].f.frametype = AST_FRAME_NULL;
05695 p->subs[idx].f.datalen = 0;
05696 p->subs[idx].f.samples = 0;
05697 p->subs[idx].f.mallocd = 0;
05698 p->subs[idx].f.offset = 0;
05699 p->subs[idx].f.subclass = 0;
05700 p->subs[idx].f.delivery = ast_tv(0,0);
05701 p->subs[idx].f.src = "dahdi_read";
05702 p->subs[idx].f.data.ptr = NULL;
05703
05704
05705 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05706 {
05707 struct dahdi_params ps;
05708
05709 memset(&ps, 0, sizeof(ps));
05710 ps.channo = p->channel;
05711 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05712 ast_mutex_unlock(&p->lock);
05713 return NULL;
05714 }
05715 p->firstradio = 1;
05716 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05717 if (ps.rxisoffhook)
05718 {
05719 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
05720 }
05721 else
05722 {
05723 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05724 }
05725 ast_mutex_unlock(&p->lock);
05726 return &p->subs[idx].f;
05727 }
05728 if (p->ringt == 1) {
05729 ast_mutex_unlock(&p->lock);
05730 return NULL;
05731 }
05732 else if (p->ringt > 0)
05733 p->ringt--;
05734
05735 if (p->subs[idx].needringing) {
05736
05737 p->subs[idx].needringing = 0;
05738 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05739 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05740 ast_setstate(ast, AST_STATE_RINGING);
05741 ast_mutex_unlock(&p->lock);
05742 return &p->subs[idx].f;
05743 }
05744
05745 if (p->subs[idx].needbusy) {
05746
05747 p->subs[idx].needbusy = 0;
05748 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05749 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
05750 ast_mutex_unlock(&p->lock);
05751 return &p->subs[idx].f;
05752 }
05753
05754 if (p->subs[idx].needcongestion) {
05755
05756 p->subs[idx].needcongestion = 0;
05757 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05758 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
05759 ast_mutex_unlock(&p->lock);
05760 return &p->subs[idx].f;
05761 }
05762
05763 if (p->subs[idx].needcallerid) {
05764 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05765 S_OR(p->lastcid_name, NULL),
05766 S_OR(p->lastcid_num, NULL)
05767 );
05768 p->subs[idx].needcallerid = 0;
05769 }
05770
05771 if (p->subs[idx].needanswer) {
05772
05773 p->subs[idx].needanswer = 0;
05774 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05775 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05776 ast_mutex_unlock(&p->lock);
05777 return &p->subs[idx].f;
05778 }
05779
05780 if (p->subs[idx].needflash) {
05781
05782 p->subs[idx].needflash = 0;
05783 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05784 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
05785 ast_mutex_unlock(&p->lock);
05786 return &p->subs[idx].f;
05787 }
05788
05789 if (p->subs[idx].needhold) {
05790
05791 p->subs[idx].needhold = 0;
05792 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05793 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
05794 ast_mutex_unlock(&p->lock);
05795 ast_debug(1, "Sending hold on '%s'\n", ast->name);
05796 return &p->subs[idx].f;
05797 }
05798
05799 if (p->subs[idx].needunhold) {
05800
05801 p->subs[idx].needunhold = 0;
05802 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05803 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
05804 ast_mutex_unlock(&p->lock);
05805 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05806 return &p->subs[idx].f;
05807 }
05808
05809 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05810 if (!p->subs[idx].linear) {
05811 p->subs[idx].linear = 1;
05812 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05813 if (res)
05814 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
05815 }
05816 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05817 (ast->rawreadformat == AST_FORMAT_ALAW)) {
05818 if (p->subs[idx].linear) {
05819 p->subs[idx].linear = 0;
05820 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05821 if (res)
05822 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
05823 }
05824 } else {
05825 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05826 ast_mutex_unlock(&p->lock);
05827 return NULL;
05828 }
05829 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
05830 CHECK_BLOCKING(ast);
05831 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05832 ast_clear_flag(ast, AST_FLAG_BLOCKING);
05833
05834 if (res < 0) {
05835 f = NULL;
05836 if (res == -1) {
05837 if (errno == EAGAIN) {
05838
05839 ast_mutex_unlock(&p->lock);
05840 return &p->subs[idx].f;
05841 } else if (errno == ELAST) {
05842 f = __dahdi_exception(ast);
05843 } else
05844 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05845 }
05846 ast_mutex_unlock(&p->lock);
05847 return f;
05848 }
05849 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
05850 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05851 f = __dahdi_exception(ast);
05852 ast_mutex_unlock(&p->lock);
05853 return f;
05854 }
05855 if (p->tdd) {
05856 int c;
05857
05858 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05859 if (c < 0) {
05860 ast_debug(1,"tdd_feed failed\n");
05861 ast_mutex_unlock(&p->lock);
05862 return NULL;
05863 }
05864 if (c) {
05865 p->subs[idx].f.subclass = 0;
05866 p->subs[idx].f.frametype = AST_FRAME_TEXT;
05867 p->subs[idx].f.mallocd = 0;
05868 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05869 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
05870 p->subs[idx].f.datalen = 1;
05871 *((char *) p->subs[idx].f.data.ptr) = c;
05872 ast_mutex_unlock(&p->lock);
05873 return &p->subs[idx].f;
05874 }
05875 }
05876
05877 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05878 p->callwaitingrepeat--;
05879 }
05880 if (p->cidcwexpire)
05881 p->cidcwexpire--;
05882
05883 if (p->callwaitingrepeat == 1) {
05884 p->callwaitrings++;
05885 dahdi_callwait(ast);
05886 }
05887
05888 if (p->cidcwexpire == 1) {
05889 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05890 restore_conference(p);
05891 }
05892 if (p->subs[idx].linear) {
05893 p->subs[idx].f.datalen = READ_SIZE * 2;
05894 } else
05895 p->subs[idx].f.datalen = READ_SIZE;
05896
05897
05898 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05899 send_callerid(p);
05900 }
05901
05902 p->subs[idx].f.frametype = AST_FRAME_VOICE;
05903 p->subs[idx].f.subclass = ast->rawreadformat;
05904 p->subs[idx].f.samples = READ_SIZE;
05905 p->subs[idx].f.mallocd = 0;
05906 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05907 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
05908 #if 0
05909 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
05910 #endif
05911 if (p->dialing ||
05912 (idx && (ast->_state != AST_STATE_UP)) ||
05913 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05914 ) {
05915
05916
05917 p->subs[idx].f.frametype = AST_FRAME_NULL;
05918 p->subs[idx].f.subclass = 0;
05919 p->subs[idx].f.samples = 0;
05920 p->subs[idx].f.mallocd = 0;
05921 p->subs[idx].f.offset = 0;
05922 p->subs[idx].f.data.ptr = NULL;
05923 p->subs[idx].f.datalen= 0;
05924 }
05925 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) {
05926
05927 int mute;
05928
05929 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
05930
05931
05932 mute = ast_dsp_was_muted(p->dsp);
05933 if (p->muting != mute) {
05934 p->muting = mute;
05935 dahdi_confmute(p, mute);
05936 }
05937
05938 if (f) {
05939 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05940 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05941
05942
05943 f = NULL;
05944 }
05945 } else if (f->frametype == AST_FRAME_DTMF) {
05946 #ifdef HAVE_PRI
05947 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
05948 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05949 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05950
05951 f->frametype = AST_FRAME_NULL;
05952 f->subclass = 0;
05953 }
05954 #endif
05955
05956 p->pulsedial = 0;
05957 }
05958 }
05959 } else
05960 f = &p->subs[idx].f;
05961
05962 if (f && (f->frametype == AST_FRAME_DTMF))
05963 dahdi_handle_dtmfup(ast, idx, &f);
05964
05965
05966 if (p->fake_event)
05967 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05968
05969 ast_mutex_unlock(&p->lock);
05970 return f;
05971 }
05972
05973 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
05974 {
05975 int sent=0;
05976 int size;
05977 int res;
05978 int fd;
05979 fd = p->subs[idx].dfd;
05980 while (len) {
05981 size = len;
05982 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05983 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05984 res = write(fd, buf, size);
05985 if (res != size) {
05986 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05987 return sent;
05988 }
05989 len -= size;
05990 buf += size;
05991 }
05992 return sent;
05993 }
05994
05995 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05996 {
05997 struct dahdi_pvt *p = ast->tech_pvt;
05998 int res;
05999 int idx;
06000 idx = dahdi_get_index(ast, p, 0);
06001 if (idx < 0) {
06002 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06003 return -1;
06004 }
06005
06006 #if 0
06007 #ifdef HAVE_PRI
06008 ast_mutex_lock(&p->lock);
06009 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06010 if (p->pri->pri) {
06011 if (!pri_grab(p, p->pri)) {
06012 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06013 pri_rel(p->pri);
06014 } else
06015 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06016 }
06017 p->proceeding=1;
06018 }
06019 ast_mutex_unlock(&p->lock);
06020 #endif
06021 #endif
06022
06023 if (frame->frametype != AST_FRAME_VOICE) {
06024 if (frame->frametype != AST_FRAME_IMAGE)
06025 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06026 return 0;
06027 }
06028 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06029 (frame->subclass != AST_FORMAT_ULAW) &&
06030 (frame->subclass != AST_FORMAT_ALAW)) {
06031 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06032 return -1;
06033 }
06034 if (p->dialing) {
06035 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06036 return 0;
06037 }
06038 if (!p->owner) {
06039 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06040 return 0;
06041 }
06042 if (p->cidspill) {
06043 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06044 return 0;
06045 }
06046
06047 if (!frame->data.ptr || !frame->datalen)
06048 return 0;
06049
06050 if (frame->subclass == AST_FORMAT_SLINEAR) {
06051 if (!p->subs[idx].linear) {
06052 p->subs[idx].linear = 1;
06053 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06054 if (res)
06055 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06056 }
06057 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
06058 } else {
06059
06060 if (p->subs[idx].linear) {
06061 p->subs[idx].linear = 0;
06062 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06063 if (res)
06064 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06065 }
06066 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
06067 }
06068 if (res < 0) {
06069 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06070 return -1;
06071 }
06072 return 0;
06073 }
06074
06075 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06076 {
06077 struct dahdi_pvt *p = chan->tech_pvt;
06078 int res=-1;
06079 int idx;
06080 int func = DAHDI_FLASH;
06081 ast_mutex_lock(&p->lock);
06082 idx = dahdi_get_index(chan, p, 0);
06083 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06084 if (idx == SUB_REAL) {
06085 switch (condition) {
06086 case AST_CONTROL_BUSY:
06087 #ifdef HAVE_PRI
06088 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06089 chan->hangupcause = AST_CAUSE_USER_BUSY;
06090 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06091 res = 0;
06092 } else if (!p->progress &&
06093 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06094 && p->pri && !p->outgoing) {
06095 if (p->pri->pri) {
06096 if (!pri_grab(p, p->pri)) {
06097 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06098 pri_rel(p->pri);
06099 }
06100 else
06101 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06102 }
06103 p->progress = 1;
06104 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06105 } else
06106 #endif
06107 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06108 break;
06109 case AST_CONTROL_RINGING:
06110 #ifdef HAVE_PRI
06111 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06112 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06113 if (p->pri->pri) {
06114 if (!pri_grab(p, p->pri)) {
06115 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06116 pri_rel(p->pri);
06117 }
06118 else
06119 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06120 }
06121 p->alerting = 1;
06122 }
06123
06124 #endif
06125 #ifdef HAVE_SS7
06126 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06127 if (p->ss7->ss7) {
06128 ss7_grab(p, p->ss7);
06129
06130 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06131 p->rlt = 1;
06132 if (p->rlt != 1)
06133 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06134 p->alerting = 1;
06135 ss7_rel(p->ss7);
06136 }
06137 }
06138 #endif
06139
06140 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
06141
06142 if (chan->_state != AST_STATE_UP) {
06143 if ((chan->_state != AST_STATE_RING) ||
06144 ((p->sig != SIG_FXSKS) &&
06145 (p->sig != SIG_FXSLS) &&
06146 (p->sig != SIG_FXSGS)))
06147 ast_setstate(chan, AST_STATE_RINGING);
06148 }
06149 break;
06150 case AST_CONTROL_PROCEEDING:
06151 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06152 #ifdef HAVE_PRI
06153 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06154 && p->pri && !p->outgoing) {
06155 if (p->pri->pri) {
06156 if (!pri_grab(p, p->pri)) {
06157 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06158 pri_rel(p->pri);
06159 }
06160 else
06161 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06162 }
06163 p->proceeding = 1;
06164 p->dialing = 0;
06165 }
06166 #endif
06167 #ifdef HAVE_SS7
06168
06169 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
06170 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06171 p->rlt = 1;
06172 }
06173
06174 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
06175 if (p->ss7->ss7) {
06176 ss7_grab(p, p->ss7);
06177 isup_acm(p->ss7->ss7, p->ss7call);
06178 p->proceeding = 1;
06179 ss7_rel(p->ss7);
06180
06181 }
06182 }
06183 #endif
06184
06185 res = 0;
06186 break;
06187 case AST_CONTROL_PROGRESS:
06188 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06189 #ifdef HAVE_PRI
06190 p->digital = 0;
06191 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06192 && p->pri && !p->outgoing) {
06193 if (p->pri->pri) {
06194 if (!pri_grab(p, p->pri)) {
06195 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06196 pri_rel(p->pri);
06197 }
06198 else
06199 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06200 }
06201 p->progress = 1;
06202 }
06203 #endif
06204 #ifdef HAVE_SS7
06205 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
06206 if (p->ss7->ss7) {
06207 ss7_grab(p, p->ss7);
06208 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
06209 p->progress = 1;
06210 ss7_rel(p->ss7);
06211
06212 dahdi_enable_ec(p);
06213
06214 }
06215 }
06216 #endif
06217
06218 res = 0;
06219 break;
06220 case AST_CONTROL_CONGESTION:
06221 chan->hangupcause = AST_CAUSE_CONGESTION;
06222 #ifdef HAVE_PRI
06223 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06224 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06225 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06226 res = 0;
06227 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06228 && p->pri && !p->outgoing) {
06229 if (p->pri) {
06230 if (!pri_grab(p, p->pri)) {
06231 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06232 pri_rel(p->pri);
06233 } else
06234 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06235 }
06236 p->progress = 1;
06237 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06238 } else
06239 #endif
06240 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06241 break;
06242 case AST_CONTROL_HOLD:
06243 #ifdef HAVE_PRI
06244 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06245 if (!pri_grab(p, p->pri)) {
06246 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06247 pri_rel(p->pri);
06248 } else
06249 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06250 } else
06251 #endif
06252 ast_moh_start(chan, data, p->mohinterpret);
06253 break;
06254 case AST_CONTROL_UNHOLD:
06255 #ifdef HAVE_PRI
06256 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06257 if (!pri_grab(p, p->pri)) {
06258 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06259 pri_rel(p->pri);
06260 } else
06261 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06262 } else
06263 #endif
06264 ast_moh_stop(chan);
06265 break;
06266 case AST_CONTROL_RADIO_KEY:
06267 if (p->radio)
06268 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06269 res = 0;
06270 break;
06271 case AST_CONTROL_RADIO_UNKEY:
06272 if (p->radio)
06273 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
06274 res = 0;
06275 break;
06276 case AST_CONTROL_FLASH:
06277
06278 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06279
06280 p->dop.dialstr[0] = '\0';
06281 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06282 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06283 chan->name, strerror(errno));
06284 } else
06285 res = 0;
06286 } else
06287 res = 0;
06288 break;
06289 case AST_CONTROL_SRCUPDATE:
06290 res = 0;
06291 break;
06292 case -1:
06293 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06294 break;
06295 }
06296 } else
06297 res = 0;
06298 ast_mutex_unlock(&p->lock);
06299 return res;
06300 }
06301
06302 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
06303 {
06304 struct ast_channel *tmp;
06305 int deflaw;
06306 int res;
06307 int x,y;
06308 int features;
06309 struct ast_str *chan_name;
06310 struct ast_variable *v;
06311 struct dahdi_params ps;
06312 if (i->subs[idx].owner) {
06313 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
06314 return NULL;
06315 }
06316 y = 1;
06317 chan_name = ast_str_alloca(32);
06318 do {
06319 #ifdef HAVE_PRI
06320 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06321 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06322 else
06323 #endif
06324 if (i->channel == CHAN_PSEUDO)
06325 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
06326 else
06327 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
06328 for (x = 0; x < 3; x++) {
06329 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
06330 break;
06331 }
06332 y++;
06333 } while (x < 3);
06334 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);
06335 if (!tmp)
06336 return NULL;
06337 tmp->tech = &dahdi_tech;
06338 memset(&ps, 0, sizeof(ps));
06339 ps.channo = i->channel;
06340 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06341 if (res) {
06342 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06343 ps.curlaw = DAHDI_LAW_MULAW;
06344 }
06345 if (ps.curlaw == DAHDI_LAW_ALAW)
06346 deflaw = AST_FORMAT_ALAW;
06347 else
06348 deflaw = AST_FORMAT_ULAW;
06349 if (law) {
06350 if (law == DAHDI_LAW_ALAW)
06351 deflaw = AST_FORMAT_ALAW;
06352 else
06353 deflaw = AST_FORMAT_ULAW;
06354 }
06355 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
06356 tmp->nativeformats = deflaw;
06357
06358 tmp->rawreadformat = deflaw;
06359 tmp->readformat = deflaw;
06360 tmp->rawwriteformat = deflaw;
06361 tmp->writeformat = deflaw;
06362 i->subs[idx].linear = 0;
06363 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
06364 features = 0;
06365 if (idx == SUB_REAL) {
06366 if (i->busydetect && CANBUSYDETECT(i))
06367 features |= DSP_FEATURE_BUSY_DETECT;
06368 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
06369 features |= DSP_FEATURE_CALL_PROGRESS;
06370 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
06371 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
06372 features |= DSP_FEATURE_FAX_DETECT;
06373 }
06374 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06375 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
06376 i->hardwaredtmf = 0;
06377 features |= DSP_FEATURE_DIGIT_DETECT;
06378 } else if (NEED_MFDETECT(i)) {
06379 i->hardwaredtmf = 1;
06380 features |= DSP_FEATURE_DIGIT_DETECT;
06381 }
06382 }
06383 if (features) {
06384 if (i->dsp) {
06385 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
06386 } else {
06387 if (i->channel != CHAN_PSEUDO)
06388 i->dsp = ast_dsp_new();
06389 else
06390 i->dsp = NULL;
06391 if (i->dsp) {
06392 i->dsp_features = features;
06393 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06394
06395 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
06396
06397
06398 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06399 features = 0;
06400 }
06401 #endif
06402 ast_dsp_set_features(i->dsp, features);
06403 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06404 if (!ast_strlen_zero(progzone))
06405 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06406 if (i->busydetect && CANBUSYDETECT(i)) {
06407 ast_dsp_set_busy_count(i->dsp, i->busycount);
06408 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
06409 }
06410 }
06411 }
06412 }
06413
06414 if (state == AST_STATE_RING)
06415 tmp->rings = 1;
06416 tmp->tech_pvt = i;
06417 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06418
06419 tmp->callgroup = i->callgroup;
06420 tmp->pickupgroup = i->pickupgroup;
06421 }
06422 if (!ast_strlen_zero(i->parkinglot))
06423 ast_string_field_set(tmp, parkinglot, i->parkinglot);
06424 if (!ast_strlen_zero(i->language))
06425 ast_string_field_set(tmp, language, i->language);
06426 if (!i->owner)
06427 i->owner = tmp;
06428 if (!ast_strlen_zero(i->accountcode))
06429 ast_string_field_set(tmp, accountcode, i->accountcode);
06430 if (i->amaflags)
06431 tmp->amaflags = i->amaflags;
06432 i->subs[idx].owner = tmp;
06433 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06434 ast_string_field_set(tmp, call_forward, i->call_forward);
06435
06436 if (!i->adsi)
06437 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06438 if (!ast_strlen_zero(i->exten))
06439 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06440 if (!ast_strlen_zero(i->rdnis))
06441 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06442 if (!ast_strlen_zero(i->dnid))
06443 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06444
06445
06446
06447 #ifdef PRI_ANI
06448 if (!ast_strlen_zero(i->cid_ani))
06449 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06450 else
06451 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06452 #else
06453 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06454 #endif
06455 tmp->cid.cid_pres = i->callingpres;
06456 tmp->cid.cid_ton = i->cid_ton;
06457 tmp->cid.cid_ani2 = i->cid_ani2;
06458 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06459 tmp->transfercapability = transfercapability;
06460 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06461 if (transfercapability & AST_TRANS_CAP_DIGITAL)
06462 i->digital = 1;
06463
06464 i->isidlecall = 0;
06465 i->alreadyhungup = 0;
06466 #endif
06467
06468 i->fake_event = 0;
06469
06470 dahdi_confmute(i, 0);
06471 i->muting = 0;
06472
06473 ast_jb_configure(tmp, &global_jbconf);
06474
06475 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
06476
06477 for (v = i->vars ; v ; v = v->next)
06478 pbx_builtin_setvar_helper(tmp, v->name, v->value);
06479
06480 if (startpbx) {
06481 if (ast_pbx_start(tmp)) {
06482 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06483 ast_hangup(tmp);
06484 i->owner = NULL;
06485 return NULL;
06486 }
06487 }
06488
06489 ast_module_ref(ast_module_info->self);
06490 return tmp;
06491 }
06492
06493
06494 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06495 {
06496 char c;
06497
06498 *str = 0;
06499 for (;;)
06500 {
06501
06502 c = ast_waitfordigit(chan, ms);
06503
06504 if (c < 1)
06505 return c;
06506 *str++ = c;
06507 *str = 0;
06508 if (strchr(term, c))
06509 return 1;
06510 }
06511 }
06512
06513 static int dahdi_wink(struct dahdi_pvt *p, int idx)
06514 {
06515 int j;
06516 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
06517 for (;;)
06518 {
06519
06520 j = DAHDI_IOMUX_SIGEVENT;
06521
06522 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06523
06524 if (j & DAHDI_IOMUX_SIGEVENT) break;
06525 }
06526
06527 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06528 return 0;
06529 }
06530
06531
06532
06533
06534
06535
06536
06537
06538
06539
06540 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
06541 {
06542
06543 dahdichan->dnd = on;
06544 ast_verb(3, "%s DND on channel %d\n",
06545 on? "Enabled" : "Disabled",
06546 dahdichan->channel);
06547 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06548 "Channel: DAHDI/%d\r\n"
06549 "Status: %s\r\n", dahdichan->channel,
06550 on? "enabled" : "disabled");
06551 }
06552
06553 static void *ss_thread(void *data)
06554 {
06555 struct ast_channel *chan = data;
06556 struct dahdi_pvt *p = chan->tech_pvt;
06557 char exten[AST_MAX_EXTENSION] = "";
06558 char exten2[AST_MAX_EXTENSION] = "";
06559 unsigned char buf[256];
06560 char dtmfcid[300];
06561 char dtmfbuf[300];
06562 struct callerid_state *cs = NULL;
06563 char *name = NULL, *number = NULL;
06564 int distMatches;
06565 int curRingData[3];
06566 int receivedRingT;
06567 int counter1;
06568 int counter;
06569 int samples = 0;
06570 struct ast_smdi_md_message *smdi_msg = NULL;
06571 int flags = 0;
06572 int i;
06573 int timeout;
06574 int getforward = 0;
06575 char *s1, *s2;
06576 int len = 0;
06577 int res;
06578 int idx;
06579
06580 ast_mutex_lock(&ss_thread_lock);
06581 ss_thread_count++;
06582 ast_mutex_unlock(&ss_thread_lock);
06583
06584
06585
06586 if (!p) {
06587 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06588 ast_hangup(chan);
06589 goto quit;
06590 }
06591 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
06592 idx = dahdi_get_index(chan, p, 1);
06593 if (idx < 0) {
06594 ast_log(LOG_WARNING, "Huh?\n");
06595 ast_hangup(chan);
06596 goto quit;
06597 }
06598 if (p->dsp)
06599 ast_dsp_digitreset(p->dsp);
06600 switch (p->sig) {
06601 #ifdef HAVE_PRI
06602 case SIG_PRI:
06603 case SIG_BRI:
06604 case SIG_BRI_PTMP:
06605
06606 ast_copy_string(exten, p->exten, sizeof(exten));
06607 len = strlen(exten);
06608 res = 0;
06609 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06610 if (len && !ast_ignore_pattern(chan->context, exten))
06611 tone_zone_play_tone(p->subs[idx].dfd, -1);
06612 else
06613 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06614 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06615 timeout = matchdigittimeout;
06616 else
06617 timeout = gendigittimeout;
06618 res = ast_waitfordigit(chan, timeout);
06619 if (res < 0) {
06620 ast_debug(1, "waitfordigit returned < 0...\n");
06621 ast_hangup(chan);
06622 goto quit;
06623 } else if (res) {
06624 exten[len++] = res;
06625 exten[len] = '\0';
06626 } else
06627 break;
06628 }
06629
06630 if (ast_strlen_zero(exten)) {
06631 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
06632 exten[0] = 's';
06633 exten[1] = '\0';
06634 }
06635 tone_zone_play_tone(p->subs[idx].dfd, -1);
06636 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06637
06638 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06639 if (p->dsp) ast_dsp_digitreset(p->dsp);
06640 dahdi_enable_ec(p);
06641 ast_setstate(chan, AST_STATE_RING);
06642 res = ast_pbx_run(chan);
06643 if (res) {
06644 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06645 }
06646 } else {
06647 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06648 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06649 ast_hangup(chan);
06650 p->exten[0] = '\0';
06651
06652 p->call = NULL;
06653 }
06654 goto quit;
06655 break;
06656 #endif
06657 case SIG_FEATD:
06658 case SIG_FEATDMF:
06659 case SIG_FEATDMF_TA:
06660 case SIG_E911:
06661 case SIG_FGC_CAMAMF:
06662 case SIG_FEATB:
06663 case SIG_EMWINK:
06664 case SIG_SF_FEATD:
06665 case SIG_SF_FEATDMF:
06666 case SIG_SF_FEATB:
06667 case SIG_SFWINK:
06668 if (dahdi_wink(p, idx))
06669 goto quit;
06670
06671 case SIG_EM:
06672 case SIG_EM_E1:
06673 case SIG_SF:
06674 case SIG_FGC_CAMA:
06675 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06676 if (p->dsp)
06677 ast_dsp_digitreset(p->dsp);
06678
06679 if (p->dsp) {
06680 if (NEED_MFDETECT(p))
06681 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06682 else
06683 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06684 }
06685 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06686
06687 if (!p->immediate)
06688
06689 res = ast_waitfordigit(chan, 5000);
06690 else
06691 res = 0;
06692 if (res > 0) {
06693
06694 dtmfbuf[0] = res;
06695 switch (p->sig) {
06696 case SIG_FEATD:
06697 case SIG_SF_FEATD:
06698 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06699 if (res > 0)
06700 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06701 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06702 break;
06703 case SIG_FEATDMF_TA:
06704 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06705 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06706 if (dahdi_wink(p, idx)) goto quit;
06707 dtmfbuf[0] = 0;
06708
06709 res = ast_waitfordigit(chan, 5000);
06710 if (res <= 0) break;
06711 dtmfbuf[0] = res;
06712
06713 case SIG_FEATDMF:
06714 case SIG_E911:
06715 case SIG_FGC_CAMAMF:
06716 case SIG_SF_FEATDMF:
06717 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06718
06719 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06720 {
06721 if (dahdi_wink(p, idx)) goto quit;
06722 dtmfbuf[0] = 0;
06723
06724 res = ast_waitfordigit(chan, 5000);
06725 if (res <= 0) break;
06726 dtmfbuf[0] = res;
06727 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06728 }
06729 if (res > 0) {
06730
06731 if (p->sig == SIG_E911)
06732 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06733 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06734 }
06735 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06736 break;
06737 case SIG_FEATB:
06738 case SIG_SF_FEATB:
06739 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06740 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06741 break;
06742 case SIG_EMWINK:
06743
06744
06745
06746
06747 if (res == '*') {
06748 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06749 if (res > 0)
06750 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06751 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06752 break;
06753 }
06754 default:
06755
06756 len = 1;
06757 dtmfbuf[len] = '\0';
06758 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06759 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06760 timeout = matchdigittimeout;
06761 } else {
06762 timeout = gendigittimeout;
06763 }
06764 res = ast_waitfordigit(chan, timeout);
06765 if (res < 0) {
06766 ast_debug(1, "waitfordigit returned < 0...\n");
06767 ast_hangup(chan);
06768 goto quit;
06769 } else if (res) {
06770 dtmfbuf[len++] = res;
06771 dtmfbuf[len] = '\0';
06772 } else {
06773 break;
06774 }
06775 }
06776 break;
06777 }
06778 }
06779 if (res == -1) {
06780 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06781 ast_hangup(chan);
06782 goto quit;
06783 } else if (res < 0) {
06784 ast_debug(1, "Got hung up before digits finished\n");
06785 ast_hangup(chan);
06786 goto quit;
06787 }
06788
06789 if (p->sig == SIG_FGC_CAMA) {
06790 char anibuf[100];
06791
06792 if (ast_safe_sleep(chan,1000) == -1) {
06793 ast_hangup(chan);
06794 goto quit;
06795 }
06796 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06797 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06798 res = my_getsigstr(chan, anibuf, "#", 10000);
06799 if ((res > 0) && (strlen(anibuf) > 2)) {
06800 if (anibuf[strlen(anibuf) - 1] == '#')
06801 anibuf[strlen(anibuf) - 1] = 0;
06802 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06803 }
06804 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06805 }
06806
06807 ast_copy_string(exten, dtmfbuf, sizeof(exten));
06808 if (ast_strlen_zero(exten))
06809 ast_copy_string(exten, "s", sizeof(exten));
06810 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06811
06812 if (exten[0] == '*') {
06813 char *stringp=NULL;
06814 ast_copy_string(exten2, exten, sizeof(exten2));
06815
06816 stringp=exten2 +1;
06817 s1 = strsep(&stringp, "*");
06818 s2 = strsep(&stringp, "*");
06819 if (s2) {
06820 if (!ast_strlen_zero(p->cid_num))
06821 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06822 else
06823 ast_set_callerid(chan, s1, NULL, s1);
06824 ast_copy_string(exten, s2, sizeof(exten));
06825 } else
06826 ast_copy_string(exten, s1, sizeof(exten));
06827 } else if (p->sig == SIG_FEATD)
06828 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06829 }
06830 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06831 if (exten[0] == '*') {
06832 char *stringp=NULL;
06833 ast_copy_string(exten2, exten, sizeof(exten2));
06834
06835 stringp=exten2 +1;
06836 s1 = strsep(&stringp, "#");
06837 s2 = strsep(&stringp, "#");
06838 if (s2) {
06839 if (!ast_strlen_zero(p->cid_num))
06840 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06841 else
06842 if (*(s1 + 2))
06843 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06844 ast_copy_string(exten, s2 + 1, sizeof(exten));
06845 } else
06846 ast_copy_string(exten, s1 + 2, sizeof(exten));
06847 } else
06848 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06849 }
06850 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06851 if (exten[0] == '*') {
06852 char *stringp=NULL;
06853 ast_copy_string(exten2, exten, sizeof(exten2));
06854
06855 stringp=exten2 +1;
06856 s1 = strsep(&stringp, "#");
06857 s2 = strsep(&stringp, "#");
06858 if (s2 && (*(s2 + 1) == '0')) {
06859 if (*(s2 + 2))
06860 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06861 }
06862 if (s1) ast_copy_string(exten, s1, sizeof(exten));
06863 else ast_copy_string(exten, "911", sizeof(exten));
06864 } else
06865 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
06866 }
06867 if (p->sig == SIG_FEATB) {
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 ast_copy_string(exten, exten2 + 1, sizeof(exten));
06875 } else
06876 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
06877 }
06878 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06879 dahdi_wink(p, idx);
06880
06881
06882
06883 if (ast_safe_sleep(chan,100)) goto quit;
06884 }
06885 dahdi_enable_ec(p);
06886 if (NEED_MFDETECT(p)) {
06887 if (p->dsp) {
06888 if (!p->hardwaredtmf)
06889 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06890 else {
06891 ast_dsp_free(p->dsp);
06892 p->dsp = NULL;
06893 }
06894 }
06895 }
06896
06897 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06898 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06899 if (p->dsp) ast_dsp_digitreset(p->dsp);
06900 res = ast_pbx_run(chan);
06901 if (res) {
06902 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06903 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06904 }
06905 goto quit;
06906 } else {
06907 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06908 sleep(2);
06909 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
06910 if (res < 0)
06911 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06912 else
06913 sleep(1);
06914 res = ast_streamfile(chan, "ss-noservice", chan->language);
06915 if (res >= 0)
06916 ast_waitstream(chan, "");
06917 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06918 ast_hangup(chan);
06919 goto quit;
06920 }
06921 break;
06922 case SIG_FXOLS:
06923 case SIG_FXOGS:
06924 case SIG_FXOKS:
06925
06926 timeout = firstdigittimeout;
06927
06928
06929 if (p->subs[SUB_THREEWAY].owner)
06930 timeout = 999999;
06931 while (len < AST_MAX_EXTENSION-1) {
06932
06933
06934 if (p->immediate)
06935 res = 's';
06936 else
06937 res = ast_waitfordigit(chan, timeout);
06938 timeout = 0;
06939 if (res < 0) {
06940 ast_debug(1, "waitfordigit returned < 0...\n");
06941 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06942 ast_hangup(chan);
06943 goto quit;
06944 } else if (res) {
06945 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
06946 exten[len++]=res;
06947 exten[len] = '\0';
06948 }
06949 if (!ast_ignore_pattern(chan->context, exten))
06950 tone_zone_play_tone(p->subs[idx].dfd, -1);
06951 else
06952 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06953 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06954 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06955 if (getforward) {
06956
06957 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
06958 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06959 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06960 if (res)
06961 break;
06962 usleep(500000);
06963 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06964 sleep(1);
06965 memset(exten, 0, sizeof(exten));
06966 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06967 len = 0;
06968 getforward = 0;
06969 } else {
06970 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06971 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06972 if (!ast_strlen_zero(p->cid_num)) {
06973 if (!p->hidecallerid)
06974 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06975 else
06976 ast_set_callerid(chan, NULL, NULL, p->cid_num);
06977 }
06978 if (!ast_strlen_zero(p->cid_name)) {
06979 if (!p->hidecallerid)
06980 ast_set_callerid(chan, NULL, p->cid_name, NULL);
06981 }
06982 ast_setstate(chan, AST_STATE_RING);
06983 dahdi_enable_ec(p);
06984 res = ast_pbx_run(chan);
06985 if (res) {
06986 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06987 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06988 }
06989 goto quit;
06990 }
06991 } else {
06992
06993
06994 timeout = matchdigittimeout;
06995 }
06996 } else if (res == 0) {
06997 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
06998 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06999 dahdi_wait_event(p->subs[idx].dfd);
07000 ast_hangup(chan);
07001 goto quit;
07002 } else if (p->callwaiting && !strcmp(exten, "*70")) {
07003 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
07004
07005 p->callwaiting = 0;
07006 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07007 if (res) {
07008 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07009 chan->name, strerror(errno));
07010 }
07011 len = 0;
07012 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
07013 memset(exten, 0, sizeof(exten));
07014 timeout = firstdigittimeout;
07015
07016 } else if (!strcmp(exten,ast_pickup_ext())) {
07017
07018
07019
07020
07021 if (idx == SUB_REAL) {
07022
07023 if (p->subs[SUB_THREEWAY].owner) {
07024
07025
07026 alloc_sub(p, SUB_CALLWAIT);
07027 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07028 unalloc_sub(p, SUB_THREEWAY);
07029 }
07030 dahdi_enable_ec(p);
07031 if (ast_pickup_call(chan)) {
07032 ast_debug(1, "No call pickup possible...\n");
07033 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07034 dahdi_wait_event(p->subs[idx].dfd);
07035 }
07036 ast_hangup(chan);
07037 goto quit;
07038 } else {
07039 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07040 ast_hangup(chan);
07041 goto quit;
07042 }
07043
07044 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07045 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
07046
07047 p->hidecallerid = 1;
07048 if (chan->cid.cid_num)
07049 ast_free(chan->cid.cid_num);
07050 chan->cid.cid_num = NULL;
07051 if (chan->cid.cid_name)
07052 ast_free(chan->cid.cid_name);
07053 chan->cid.cid_name = NULL;
07054 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07055 if (res) {
07056 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07057 chan->name, strerror(errno));
07058 }
07059 len = 0;
07060 memset(exten, 0, sizeof(exten));
07061 timeout = firstdigittimeout;
07062 } else if (p->callreturn && !strcmp(exten, "*69")) {
07063 res = 0;
07064 if (!ast_strlen_zero(p->lastcid_num)) {
07065 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07066 }
07067 if (!res)
07068 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07069 break;
07070 } else if (!strcmp(exten, "*78")) {
07071 dahdi_dnd(p, 1);
07072
07073 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07074 getforward = 0;
07075 memset(exten, 0, sizeof(exten));
07076 len = 0;
07077 } else if (!strcmp(exten, "*79")) {
07078 dahdi_dnd(p, 0);
07079
07080 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07081 getforward = 0;
07082 memset(exten, 0, sizeof(exten));
07083 len = 0;
07084 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07085 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07086 getforward = 1;
07087 memset(exten, 0, sizeof(exten));
07088 len = 0;
07089 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07090 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
07091 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07092 memset(p->call_forward, 0, sizeof(p->call_forward));
07093 getforward = 0;
07094 memset(exten, 0, sizeof(exten));
07095 len = 0;
07096 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07097 p->subs[SUB_THREEWAY].owner &&
07098 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07099
07100
07101 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07102 ast_verb(3, "Parking call to '%s'\n", chan->name);
07103 break;
07104 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07105 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
07106 res = ast_db_put("blacklist", p->lastcid_num, "1");
07107 if (!res) {
07108 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07109 memset(exten, 0, sizeof(exten));
07110 len = 0;
07111 }
07112 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07113 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
07114
07115 p->hidecallerid = 0;
07116 if (chan->cid.cid_num)
07117 ast_free(chan->cid.cid_num);
07118 chan->cid.cid_num = NULL;
07119 if (chan->cid.cid_name)
07120 ast_free(chan->cid.cid_name);
07121 chan->cid.cid_name = NULL;
07122 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07123 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07124 if (res) {
07125 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07126 chan->name, strerror(errno));
07127 }
07128 len = 0;
07129 memset(exten, 0, sizeof(exten));
07130 timeout = firstdigittimeout;
07131 } else if (!strcmp(exten, "*0")) {
07132 struct ast_channel *nbridge =
07133 p->subs[SUB_THREEWAY].owner;
07134 struct dahdi_pvt *pbridge = NULL;
07135
07136 if (nbridge && ast_bridged_channel(nbridge))
07137 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07138 if (nbridge && pbridge &&
07139 (nbridge->tech == &dahdi_tech) &&
07140 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
07141 ISTRUNK(pbridge)) {
07142 int func = DAHDI_FLASH;
07143
07144 p->dop.dialstr[0] = '\0';
07145
07146 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07147 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07148 nbridge->name, strerror(errno));
07149 }
07150 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07151 unalloc_sub(p, SUB_THREEWAY);
07152 p->owner = p->subs[SUB_REAL].owner;
07153 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07154 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07155 ast_hangup(chan);
07156 goto quit;
07157 } else {
07158 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07159 dahdi_wait_event(p->subs[idx].dfd);
07160 tone_zone_play_tone(p->subs[idx].dfd, -1);
07161 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07162 unalloc_sub(p, SUB_THREEWAY);
07163 p->owner = p->subs[SUB_REAL].owner;
07164 ast_hangup(chan);
07165 goto quit;
07166 }
07167 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07168 ((exten[0] != '*') || (strlen(exten) > 2))) {
07169 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);
07170 break;
07171 }
07172 if (!timeout)
07173 timeout = gendigittimeout;
07174 if (len && !ast_ignore_pattern(chan->context, exten))
07175 tone_zone_play_tone(p->subs[idx].dfd, -1);
07176 }
07177 break;
07178 case SIG_FXSLS:
07179 case SIG_FXSGS:
07180 case SIG_FXSKS:
07181 #ifdef HAVE_PRI
07182 if (p->pri) {
07183
07184 struct ast_frame *f;
07185 int res;
07186 time_t start;
07187
07188 time(&start);
07189 ast_setstate(chan, AST_STATE_RING);
07190 while (time(NULL) < start + 3) {
07191 res = ast_waitfor(chan, 1000);
07192 if (res) {
07193 f = ast_read(chan);
07194 if (!f) {
07195 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07196 ast_hangup(chan);
07197 goto quit;
07198 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07199 res = 1;
07200 } else
07201 res = 0;
07202 ast_frfree(f);
07203 if (res) {
07204 ast_debug(1, "Got ring!\n");
07205 res = 0;
07206 break;
07207 }
07208 }
07209 }
07210 }
07211 #endif
07212
07213 if (p->use_smdi && p->smdi_iface) {
07214 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07215
07216 if (smdi_msg != NULL) {
07217 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07218
07219 if (smdi_msg->type == 'B')
07220 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07221 else if (smdi_msg->type == 'N')
07222 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07223
07224 ast_debug(1, "Received SMDI message on %s\n", chan->name);
07225 } else {
07226 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07227 }
07228 }
07229
07230 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07231 number = smdi_msg->calling_st;
07232
07233
07234
07235
07236 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
07237
07238 if (p->cid_signalling == CID_SIG_DTMF) {
07239 int k = 0;
07240 cs = NULL;
07241 ast_debug(1, "Receiving DTMF cid on "
07242 "channel %s\n", chan->name);
07243 dahdi_setlinear(p->subs[idx].dfd, 0);
07244 res = 2000;
07245 for (;;) {
07246 struct ast_frame *f;
07247 res = ast_waitfor(chan, res);
07248 if (res <= 0) {
07249 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07250 "Exiting simple switch\n");
07251 ast_hangup(chan);
07252 goto quit;
07253 }
07254 f = ast_read(chan);
07255 if (!f)
07256 break;
07257 if (f->frametype == AST_FRAME_DTMF) {
07258 dtmfbuf[k++] = f->subclass;
07259 ast_debug(1, "CID got digit '%c'\n", f->subclass);
07260 res = 2000;
07261 }
07262 ast_frfree(f);
07263 if (chan->_state == AST_STATE_RING ||
07264 chan->_state == AST_STATE_RINGING)
07265 break;
07266 }
07267 dtmfbuf[k] = '\0';
07268 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07269
07270 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
07271 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07272 ast_debug(1, "CID is '%s', flags %d\n",
07273 dtmfcid, flags);
07274
07275 if (!ast_strlen_zero(dtmfcid))
07276 number = dtmfcid;
07277 else
07278 number = NULL;
07279
07280 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07281 cs = callerid_new(p->cid_signalling);
07282 if (cs) {
07283 samples = 0;
07284 #if 1
07285 bump_gains(p);
07286 #endif
07287
07288 dahdi_setlinear(p->subs[idx].dfd, 0);
07289
07290
07291 for (;;) {
07292 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07293 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07294 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07295 callerid_free(cs);
07296 ast_hangup(chan);
07297 goto quit;
07298 }
07299 if (i & DAHDI_IOMUX_SIGEVENT) {
07300 res = dahdi_get_event(p->subs[idx].dfd);
07301 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07302
07303 if (p->cid_signalling == CID_SIG_V23_JP) {
07304 if (res == DAHDI_EVENT_RINGBEGIN) {
07305 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07306 usleep(1);
07307 }
07308 } else {
07309 res = 0;
07310 break;
07311 }
07312 } else if (i & DAHDI_IOMUX_READ) {
07313 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07314 if (res < 0) {
07315 if (errno != ELAST) {
07316 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07317 callerid_free(cs);
07318 ast_hangup(chan);
07319 goto quit;
07320 }
07321 break;
07322 }
07323 samples += res;
07324
07325 if (p->cid_signalling == CID_SIG_V23_JP) {
07326 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07327 } else {
07328 res = callerid_feed(cs, buf, res, AST_LAW(p));
07329 }
07330
07331 if (res < 0) {
07332 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07333 break;
07334 } else if (res)
07335 break;
07336 else if (samples > (8000 * 10))
07337 break;
07338 }
07339 }
07340 if (res == 1) {
07341 callerid_get(cs, &name, &number, &flags);
07342 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07343 }
07344
07345 if (p->cid_signalling == CID_SIG_V23_JP) {
07346 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07347 usleep(1);
07348 res = 4000;
07349 } else {
07350
07351
07352 res = 2000;
07353 }
07354
07355 for (;;) {
07356 struct ast_frame *f;
07357 res = ast_waitfor(chan, res);
07358 if (res <= 0) {
07359 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07360 "Exiting simple switch\n");
07361 ast_hangup(chan);
07362 goto quit;
07363 }
07364 if (!(f = ast_read(chan))) {
07365 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07366 ast_hangup(chan);
07367 goto quit;
07368 }
07369 ast_frfree(f);
07370 if (chan->_state == AST_STATE_RING ||
07371 chan->_state == AST_STATE_RINGING)
07372 break;
07373 }
07374
07375
07376
07377 if (p->usedistinctiveringdetection) {
07378 len = 0;
07379 distMatches = 0;
07380
07381 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07382 curRingData[receivedRingT] = 0;
07383 receivedRingT = 0;
07384 counter = 0;
07385 counter1 = 0;
07386
07387 if (strcmp(p->context,p->defcontext) != 0) {
07388 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07389 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07390 }
07391
07392 for (;;) {
07393 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07394 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07395 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07396 callerid_free(cs);
07397 ast_hangup(chan);
07398 goto quit;
07399 }
07400 if (i & DAHDI_IOMUX_SIGEVENT) {
07401 res = dahdi_get_event(p->subs[idx].dfd);
07402 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07403 res = 0;
07404
07405
07406 curRingData[receivedRingT] = p->ringt;
07407
07408 if (p->ringt < p->ringt_base/2)
07409 break;
07410
07411
07412 if (++receivedRingT == ARRAY_LEN(curRingData))
07413 break;
07414 } else if (i & DAHDI_IOMUX_READ) {
07415 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07416 if (res < 0) {
07417 if (errno != ELAST) {
07418 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07419 callerid_free(cs);
07420 ast_hangup(chan);
07421 goto quit;
07422 }
07423 break;
07424 }
07425 if (p->ringt)
07426 p->ringt--;
07427 if (p->ringt == 1) {
07428 res = -1;
07429 break;
07430 }
07431 }
07432 }
07433
07434 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07435 for (counter = 0; counter < 3; counter++) {
07436
07437
07438 distMatches = 0;
07439 for (counter1 = 0; counter1 < 3; counter1++) {
07440 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07441 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07442 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07443 curRingData[counter1]);
07444 distMatches++;
07445 }
07446 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07447 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07448 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07449 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07450 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07451 distMatches++;
07452 }
07453 }
07454
07455 if (distMatches == 3) {
07456
07457 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07458 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07459 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07460 break;
07461 }
07462 }
07463 }
07464
07465 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07466 #if 1
07467 restore_gains(p);
07468 #endif
07469 } else
07470 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07471 } else {
07472 ast_log(LOG_WARNING, "Channel %s in prering "
07473 "state, but I have nothing to do. "
07474 "Terminating simple switch, should be "
07475 "restarted by the actual ring.\n",
07476 chan->name);
07477 ast_hangup(chan);
07478 goto quit;
07479 }
07480 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07481 if (p->cid_signalling == CID_SIG_DTMF) {
07482 int k = 0;
07483 cs = NULL;
07484 dahdi_setlinear(p->subs[idx].dfd, 0);
07485 res = 2000;
07486 for (;;) {
07487 struct ast_frame *f;
07488 res = ast_waitfor(chan, res);
07489 if (res <= 0) {
07490 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07491 "Exiting simple switch\n");
07492 ast_hangup(chan);
07493 return NULL;
07494 }
07495 f = ast_read(chan);
07496 if (f->frametype == AST_FRAME_DTMF) {
07497 dtmfbuf[k++] = f->subclass;
07498 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07499 res = 2000;
07500 }
07501 ast_frfree(f);
07502
07503 if (p->ringt_base == p->ringt)
07504 break;
07505
07506 }
07507 dtmfbuf[k] = '\0';
07508 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07509
07510 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07511 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07512 dtmfcid, flags);
07513
07514 if (!ast_strlen_zero(dtmfcid))
07515 number = dtmfcid;
07516 else
07517 number = NULL;
07518
07519 } else {
07520
07521 cs = callerid_new(p->cid_signalling);
07522 if (cs) {
07523 #if 1
07524 bump_gains(p);
07525 #endif
07526 samples = 0;
07527 len = 0;
07528 distMatches = 0;
07529
07530 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07531 curRingData[receivedRingT] = 0;
07532 receivedRingT = 0;
07533 counter = 0;
07534 counter1 = 0;
07535
07536 if (strcmp(p->context,p->defcontext) != 0) {
07537 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07538 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07539 }
07540
07541
07542 dahdi_setlinear(p->subs[idx].dfd, 0);
07543 for (;;) {
07544 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07545 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07546 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07547 callerid_free(cs);
07548 ast_hangup(chan);
07549 goto quit;
07550 }
07551 if (i & DAHDI_IOMUX_SIGEVENT) {
07552 res = dahdi_get_event(p->subs[idx].dfd);
07553 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07554
07555 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07556 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07557 p->polarity = POLARITY_IDLE;
07558 callerid_free(cs);
07559 ast_hangup(chan);
07560 goto quit;
07561 }
07562 res = 0;
07563
07564
07565 curRingData[receivedRingT] = p->ringt;
07566
07567 if (p->ringt < p->ringt_base/2)
07568 break;
07569
07570
07571 if (++receivedRingT == ARRAY_LEN(curRingData))
07572 break;
07573 } else if (i & DAHDI_IOMUX_READ) {
07574 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07575 if (res < 0) {
07576 if (errno != ELAST) {
07577 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07578 callerid_free(cs);
07579 ast_hangup(chan);
07580 goto quit;
07581 }
07582 break;
07583 }
07584 if (p->ringt)
07585 p->ringt--;
07586 if (p->ringt == 1) {
07587 res = -1;
07588 break;
07589 }
07590 samples += res;
07591 res = callerid_feed(cs, buf, res, AST_LAW(p));
07592 if (res < 0) {
07593 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07594 break;
07595 } else if (res)
07596 break;
07597 else if (samples > (8000 * 10))
07598 break;
07599 }
07600 }
07601 if (res == 1) {
07602 callerid_get(cs, &name, &number, &flags);
07603 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07604 }
07605 if (distinctiveringaftercid == 1) {
07606
07607 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07608 curRingData[receivedRingT] = 0;
07609 }
07610 receivedRingT = 0;
07611 ast_verb(3, "Detecting post-CID distinctive ring\n");
07612 for (;;) {
07613 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07614 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07615 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07616 callerid_free(cs);
07617 ast_hangup(chan);
07618 goto quit;
07619 }
07620 if (i & DAHDI_IOMUX_SIGEVENT) {
07621 res = dahdi_get_event(p->subs[idx].dfd);
07622 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
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 }
07652 }
07653 }
07654 if (p->usedistinctiveringdetection) {
07655
07656 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07657
07658 for (counter = 0; counter < 3; counter++) {
07659
07660
07661
07662 ast_verb(3, "Checking %d,%d,%d\n",
07663 p->drings.ringnum[counter].ring[0],
07664 p->drings.ringnum[counter].ring[1],
07665 p->drings.ringnum[counter].ring[2]);
07666 distMatches = 0;
07667 for (counter1 = 0; counter1 < 3; counter1++) {
07668 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07669 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07670 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07671 curRingData[counter1]);
07672 distMatches++;
07673 }
07674 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07675 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07676 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07677 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07678 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07679 distMatches++;
07680 }
07681 }
07682 if (distMatches == 3) {
07683
07684 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07685 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07686 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07687 break;
07688 }
07689 }
07690 }
07691
07692 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07693 #if 1
07694 restore_gains(p);
07695 #endif
07696 if (res < 0) {
07697 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07698 }
07699 } else
07700 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07701 }
07702 }
07703 else
07704 cs = NULL;
07705
07706 if (number)
07707 ast_shrink_phone_number(number);
07708 ast_set_callerid(chan, number, name, number);
07709
07710 if (smdi_msg)
07711 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07712
07713 if (cs)
07714 callerid_free(cs);
07715
07716 if (flags & CID_MSGWAITING) {
07717 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
07718 notify_message(p->mailbox, 1);
07719
07720 if (p->mwimonitor_rpas) {
07721 ast_hangup(chan);
07722 return NULL;
07723 }
07724 } else if (flags & CID_NOMSGWAITING) {
07725 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
07726 notify_message(p->mailbox, 0);
07727
07728 if (p->mwimonitor_rpas) {
07729 ast_hangup(chan);
07730 return NULL;
07731 }
07732 }
07733
07734 ast_setstate(chan, AST_STATE_RING);
07735 chan->rings = 1;
07736 p->ringt = p->ringt_base;
07737 res = ast_pbx_run(chan);
07738 if (res) {
07739 ast_hangup(chan);
07740 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07741 }
07742 goto quit;
07743 default:
07744 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07745 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07746 if (res < 0)
07747 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07748 }
07749 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07750 if (res < 0)
07751 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07752 ast_hangup(chan);
07753 quit:
07754 ast_mutex_lock(&ss_thread_lock);
07755 ss_thread_count--;
07756 ast_cond_signal(&ss_thread_complete);
07757 ast_mutex_unlock(&ss_thread_lock);
07758 return NULL;
07759 }
07760
07761 struct mwi_thread_data {
07762 struct dahdi_pvt *pvt;
07763 unsigned char buf[READ_SIZE];
07764 size_t len;
07765 };
07766
07767 static int calc_energy(const unsigned char *buf, int len, int law)
07768 {
07769 int x;
07770 int sum = 0;
07771
07772 if (!len)
07773 return 0;
07774
07775 for (x = 0; x < len; x++)
07776 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07777
07778 return sum / len;
07779 }
07780
07781 static void *mwi_thread(void *data)
07782 {
07783 struct mwi_thread_data *mtd = data;
07784 struct callerid_state *cs;
07785 pthread_t threadid;
07786 int samples = 0;
07787 char *name, *number;
07788 int flags;
07789 int i, res;
07790 unsigned int spill_done = 0;
07791 int spill_result = -1;
07792
07793 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
07794 mtd->pvt->mwimonitoractive = 0;
07795
07796 return NULL;
07797 }
07798
07799 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
07800
07801 bump_gains(mtd->pvt);
07802
07803 for (;;) {
07804 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07805 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07806 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07807 goto quit;
07808 }
07809
07810 if (i & DAHDI_IOMUX_SIGEVENT) {
07811 struct ast_channel *chan;
07812
07813
07814
07815
07816 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07817
07818 switch (res) {
07819 case DAHDI_EVENT_NEONMWI_ACTIVE:
07820 case DAHDI_EVENT_NEONMWI_INACTIVE:
07821 case DAHDI_EVENT_NONE:
07822 case DAHDI_EVENT_BITSCHANGED:
07823 break;
07824 case DAHDI_EVENT_NOALARM:
07825 mtd->pvt->inalarm = 0;
07826 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
07827 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07828 "Channel: %d\r\n", mtd->pvt->channel);
07829 break;
07830 case DAHDI_EVENT_ALARM:
07831 mtd->pvt->inalarm = 1;
07832 res = get_alarms(mtd->pvt);
07833 handle_alarms(mtd->pvt, res);
07834 break;
07835 default:
07836 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
07837 callerid_free(cs);
07838
07839 restore_gains(mtd->pvt);
07840 mtd->pvt->ringt = mtd->pvt->ringt_base;
07841
07842 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
07843 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07844 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
07845 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07846 if (res < 0)
07847 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
07848 ast_hangup(chan);
07849 goto quit;
07850 }
07851 goto quit_no_clean;
07852
07853 } else {
07854 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
07855 }
07856 }
07857 } else if (i & DAHDI_IOMUX_READ) {
07858 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07859 if (errno != ELAST) {
07860 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07861 goto quit;
07862 }
07863 break;
07864 }
07865 samples += res;
07866 if (!spill_done) {
07867 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
07868 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07869 break;
07870 } else if (spill_result) {
07871 spill_done = 1;
07872 }
07873 } else {
07874
07875
07876
07877 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
07878 break;
07879 }
07880 if (samples > (8000 * 4))
07881 break;
07882 }
07883 }
07884
07885 if (spill_result == 1) {
07886 callerid_get(cs, &name, &number, &flags);
07887 if (flags & CID_MSGWAITING) {
07888 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
07889 notify_message(mtd->pvt->mailbox, 1);
07890 } else if (flags & CID_NOMSGWAITING) {
07891 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
07892 notify_message(mtd->pvt->mailbox, 0);
07893 } else {
07894 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
07895 }
07896 }
07897
07898
07899 quit:
07900 callerid_free(cs);
07901
07902 restore_gains(mtd->pvt);
07903
07904 quit_no_clean:
07905 mtd->pvt->mwimonitoractive = 0;
07906
07907 ast_free(mtd);
07908
07909 return NULL;
07910 }
07911
07912
07913
07914
07915 enum mwisend_states {
07916 MWI_SEND_SA,
07917 MWI_SEND_SA_WAIT,
07918 MWI_SEND_PAUSE,
07919 MWI_SEND_SPILL,
07920 MWI_SEND_CLEANUP,
07921 MWI_SEND_DONE
07922 };
07923
07924 static void *mwi_send_thread(void *data)
07925 {
07926 struct mwi_thread_data *mtd = data;
07927 struct timeval timeout_basis, suspend, now;
07928 int x, i, res;
07929 int num_read;
07930 enum mwisend_states mwi_send_state = MWI_SEND_SPILL;
07931
07932 ast_mutex_lock(&mwi_thread_lock);
07933 mwi_thread_count++;
07934 ast_mutex_unlock(&mwi_thread_lock);
07935
07936
07937 if(mwisend_rpas) {
07938 mwi_send_state = MWI_SEND_SA;
07939 }
07940
07941 gettimeofday(&timeout_basis, NULL);
07942
07943 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
07944 if (!mtd->pvt->cidspill) {
07945 mtd->pvt->mwisendactive = 0;
07946 ast_free(mtd);
07947 return NULL;
07948 }
07949 x = DAHDI_FLUSH_BOTH;
07950 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07951 x = 3000;
07952 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07953 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
07954 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
07955 mtd->pvt->cidpos = 0;
07956
07957 while (MWI_SEND_DONE != mwi_send_state) {
07958 num_read = 0;
07959 gettimeofday(&now, NULL);
07960 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
07961 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
07962 goto quit;
07963 }
07964
07965 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07966 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07967 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07968 goto quit;
07969 }
07970
07971 if (i & DAHDI_IOMUX_SIGEVENT) {
07972
07973
07974
07975 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07976 switch (res) {
07977 case DAHDI_EVENT_RINGEROFF:
07978 if(mwi_send_state == MWI_SEND_SA_WAIT) {
07979 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
07980 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
07981 goto quit;
07982 }
07983 mwi_send_state = MWI_SEND_PAUSE;
07984 gettimeofday(&suspend, NULL);
07985 }
07986 break;
07987 case DAHDI_EVENT_RINGERON:
07988 case DAHDI_EVENT_HOOKCOMPLETE:
07989 break;
07990 default:
07991
07992 if (0 < handle_init_event(mtd->pvt, res)) {
07993
07994 goto quit;
07995 }
07996 break;
07997 }
07998 } else if (i & DAHDI_IOMUX_READ) {
07999 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
08000 if (errno != ELAST) {
08001 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08002 goto quit;
08003 }
08004 break;
08005 }
08006 }
08007
08008 switch ( mwi_send_state) {
08009 case MWI_SEND_SA:
08010
08011 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
08012 if (res) {
08013 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
08014 goto quit;
08015 }
08016 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING);
08017 mwi_send_state = MWI_SEND_SA_WAIT;
08018 break;
08019 case MWI_SEND_SA_WAIT:
08020 break;
08021 case MWI_SEND_PAUSE:
08022 gettimeofday(&now, NULL);
08023 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
08024 mwi_send_state = MWI_SEND_SPILL;
08025 }
08026 break;
08027 case MWI_SEND_SPILL:
08028
08029 if(0 < num_read) {
08030 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
08031 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
08032 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
08033 if (res > 0) {
08034 mtd->pvt->cidpos += res;
08035 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
08036 ast_free(mtd->pvt->cidspill);
08037 mtd->pvt->cidspill = NULL;
08038 mtd->pvt->cidpos = 0;
08039 mtd->pvt->cidlen = 0;
08040 mwi_send_state = MWI_SEND_CLEANUP;
08041 }
08042 } else {
08043 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
08044 goto quit;
08045 }
08046 }
08047 break;
08048 case MWI_SEND_CLEANUP:
08049
08050 mwi_send_state = MWI_SEND_DONE;
08051 break;
08052 default:
08053
08054 goto quit;
08055 break;
08056 }
08057 }
08058
08059 quit:
08060 if(mtd->pvt->cidspill) {
08061 ast_free(mtd->pvt->cidspill);
08062 mtd->pvt->cidspill = NULL;
08063 }
08064 mtd->pvt->mwisendactive = 0;
08065 ast_free(mtd);
08066
08067 ast_mutex_lock(&mwi_thread_lock);
08068 mwi_thread_count--;
08069 ast_cond_signal(&mwi_thread_complete);
08070 ast_mutex_unlock(&mwi_thread_lock);
08071
08072 return NULL;
08073 }
08074
08075
08076
08077 static int dahdi_destroy_channel_bynum(int channel)
08078 {
08079 struct dahdi_pvt *tmp = NULL;
08080 struct dahdi_pvt *prev = NULL;
08081
08082 tmp = iflist;
08083 while (tmp) {
08084 if (tmp->channel == channel) {
08085 int x = DAHDI_FLASH;
08086 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08087 destroy_channel(prev, tmp, 1);
08088 ast_module_unref(ast_module_info->self);
08089 return RESULT_SUCCESS;
08090 }
08091 prev = tmp;
08092 tmp = tmp->next;
08093 }
08094 return RESULT_FAILURE;
08095 }
08096
08097 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
08098 {
08099 int res;
08100 pthread_t threadid;
08101 struct ast_channel *chan;
08102
08103
08104
08105 switch (event) {
08106 case DAHDI_EVENT_NONE:
08107 case DAHDI_EVENT_BITSCHANGED:
08108 break;
08109 case DAHDI_EVENT_WINKFLASH:
08110 case DAHDI_EVENT_RINGOFFHOOK:
08111 if (i->inalarm) break;
08112 if (i->radio) break;
08113
08114 switch (i->sig) {
08115 case SIG_FXOLS:
08116 case SIG_FXOGS:
08117 case SIG_FXOKS:
08118 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08119 if (res && (errno == EBUSY))
08120 break;
08121 if (i->cidspill) {
08122
08123 ast_free(i->cidspill);
08124 i->cidspill = NULL;
08125 }
08126 if (i->immediate) {
08127 dahdi_enable_ec(i);
08128
08129 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08130 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08131 if (!chan) {
08132 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08133 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08134 if (res < 0)
08135 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08136 }
08137 } else {
08138
08139 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08140 if (chan) {
08141 if (has_voicemail(i))
08142 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08143 else
08144 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08145 if (res < 0)
08146 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08147 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08148 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08149 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08150 if (res < 0)
08151 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08152 ast_hangup(chan);
08153 }
08154 } else
08155 ast_log(LOG_WARNING, "Unable to create channel\n");
08156 }
08157 break;
08158 case SIG_FXSLS:
08159 case SIG_FXSGS:
08160 case SIG_FXSKS:
08161 i->ringt = i->ringt_base;
08162
08163 case SIG_EMWINK:
08164 case SIG_FEATD:
08165 case SIG_FEATDMF:
08166 case SIG_FEATDMF_TA:
08167 case SIG_E911:
08168 case SIG_FGC_CAMA:
08169 case SIG_FGC_CAMAMF:
08170 case SIG_FEATB:
08171 case SIG_EM:
08172 case SIG_EM_E1:
08173 case SIG_SFWINK:
08174 case SIG_SF_FEATD:
08175 case SIG_SF_FEATDMF:
08176 case SIG_SF_FEATB:
08177 case SIG_SF:
08178
08179 if (i->cid_start == CID_START_POLARITY_IN) {
08180 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08181 } else {
08182 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08183 }
08184
08185 if (!chan) {
08186 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08187 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08188 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08189 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08190 if (res < 0) {
08191 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08192 }
08193 ast_hangup(chan);
08194 }
08195 break;
08196 default:
08197 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08198 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08199 if (res < 0)
08200 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08201 return NULL;
08202 }
08203 break;
08204 case DAHDI_EVENT_NOALARM:
08205 i->inalarm = 0;
08206 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08207 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08208 "Channel: %d\r\n", i->channel);
08209 break;
08210 case DAHDI_EVENT_ALARM:
08211 i->inalarm = 1;
08212 res = get_alarms(i);
08213 handle_alarms(i, res);
08214
08215 case DAHDI_EVENT_ONHOOK:
08216 if (i->radio)
08217 break;
08218
08219 switch (i->sig) {
08220 case SIG_FXOLS:
08221 case SIG_FXOGS:
08222 case SIG_FEATD:
08223 case SIG_FEATDMF:
08224 case SIG_FEATDMF_TA:
08225 case SIG_E911:
08226 case SIG_FGC_CAMA:
08227 case SIG_FGC_CAMAMF:
08228 case SIG_FEATB:
08229 case SIG_EM:
08230 case SIG_EM_E1:
08231 case SIG_EMWINK:
08232 case SIG_SF_FEATD:
08233 case SIG_SF_FEATDMF:
08234 case SIG_SF_FEATB:
08235 case SIG_SF:
08236 case SIG_SFWINK:
08237 case SIG_FXSLS:
08238 case SIG_FXSGS:
08239 case SIG_FXSKS:
08240 case SIG_GR303FXSKS:
08241 dahdi_disable_ec(i);
08242 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08243 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08244 break;
08245 case SIG_GR303FXOKS:
08246 case SIG_FXOKS:
08247 dahdi_disable_ec(i);
08248
08249 #ifdef ZHONE_HACK
08250 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08251 usleep(1);
08252 #endif
08253 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08254 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08255 break;
08256 case SIG_PRI:
08257 case SIG_SS7:
08258 case SIG_BRI:
08259 case SIG_BRI_PTMP:
08260 dahdi_disable_ec(i);
08261 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08262 break;
08263 default:
08264 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08265 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08266 return NULL;
08267 }
08268 break;
08269 case DAHDI_EVENT_POLARITY:
08270 switch (i->sig) {
08271 case SIG_FXSLS:
08272 case SIG_FXSKS:
08273 case SIG_FXSGS:
08274
08275
08276
08277
08278 if (i->hanguponpolarityswitch)
08279 i->polarity = POLARITY_REV;
08280 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08281 i->polarity = POLARITY_REV;
08282 ast_verb(2, "Starting post polarity "
08283 "CID detection on channel %d\n",
08284 i->channel);
08285 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08286 if (!chan) {
08287 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08288 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08289 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08290 }
08291 }
08292 break;
08293 default:
08294 ast_log(LOG_WARNING, "handle_init_event detected "
08295 "polarity reversal on non-FXO (SIG_FXS) "
08296 "interface %d\n", i->channel);
08297 }
08298 break;
08299 case DAHDI_EVENT_REMOVED:
08300 ast_log(LOG_NOTICE,
08301 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08302 i->channel);
08303 return i;
08304 case DAHDI_EVENT_NEONMWI_ACTIVE:
08305 if (i->mwimonitor_neon) {
08306 notify_message(i->mailbox, 1);
08307 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08308 }
08309 break;
08310 case DAHDI_EVENT_NEONMWI_INACTIVE:
08311 if (i->mwimonitor_neon) {
08312 notify_message(i->mailbox, 0);
08313 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08314 }
08315 break;
08316 }
08317 return NULL;
08318 }
08319
08320 static void *do_monitor(void *data)
08321 {
08322 int count, res, res2, spoint, pollres=0;
08323 struct dahdi_pvt *i;
08324 struct dahdi_pvt *last = NULL;
08325 struct dahdi_pvt *doomed;
08326 time_t thispass = 0, lastpass = 0;
08327 int found;
08328 char buf[1024];
08329 struct pollfd *pfds=NULL;
08330 int lastalloc = -1;
08331
08332
08333
08334 #if 0
08335 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08336 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08337 return NULL;
08338 }
08339 ast_debug(1, "Monitor starting...\n");
08340 #endif
08341 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08342
08343 for (;;) {
08344
08345 ast_mutex_lock(&iflock);
08346 if (!pfds || (lastalloc != ifcount)) {
08347 if (pfds) {
08348 ast_free(pfds);
08349 pfds = NULL;
08350 }
08351 if (ifcount) {
08352 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08353 ast_mutex_unlock(&iflock);
08354 return NULL;
08355 }
08356 }
08357 lastalloc = ifcount;
08358 }
08359
08360
08361 count = 0;
08362 i = iflist;
08363 while (i) {
08364 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08365 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
08366
08367 pfds[count].fd = i->subs[SUB_REAL].dfd;
08368 pfds[count].events = POLLPRI;
08369 pfds[count].revents = 0;
08370
08371
08372 if (i->cidspill || i->mwimonitor_fsk)
08373 pfds[count].events |= POLLIN;
08374 count++;
08375 }
08376 }
08377 i = i->next;
08378 }
08379
08380 ast_mutex_unlock(&iflock);
08381
08382 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08383 pthread_testcancel();
08384
08385 res = poll(pfds, count, 1000);
08386 pthread_testcancel();
08387 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08388
08389
08390 if (res < 0) {
08391 if ((errno != EAGAIN) && (errno != EINTR))
08392 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08393 continue;
08394 }
08395
08396
08397 ast_mutex_lock(&iflock);
08398 found = 0;
08399 spoint = 0;
08400 lastpass = thispass;
08401 thispass = time(NULL);
08402 i = iflist;
08403 doomed = NULL;
08404 for (i = iflist;; i = i->next) {
08405 if (doomed) {
08406 int res;
08407 res = dahdi_destroy_channel_bynum(doomed->channel);
08408 if (!res) {
08409 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08410 }
08411 doomed = NULL;
08412 }
08413 if (!i) {
08414 break;
08415 }
08416
08417 if (thispass != lastpass) {
08418 if (!found && ((i == last) || ((i == iflist) && !last))) {
08419 last = i;
08420 if (last) {
08421 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) {
08422 res = has_voicemail(last);
08423 if (last->msgstate != res) {
08424
08425
08426
08427
08428 pthread_attr_t attr;
08429 pthread_t threadid;
08430 struct mwi_thread_data *mtd;
08431 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08432 if (res2) {
08433
08434 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08435 }
08436 pthread_attr_init(&attr);
08437 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08438 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08439 last->msgstate = res;
08440 mtd->pvt = last;
08441 last->mwisendactive = 1;
08442 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
08443 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
08444 ast_free(mtd);
08445 last->mwisendactive = 0;
08446 }
08447 }
08448 found ++;
08449 }
08450 }
08451 last = last->next;
08452 }
08453 }
08454 }
08455 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08456 if (i->radio && !i->owner)
08457 {
08458 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08459 if (res)
08460 {
08461 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08462
08463 ast_mutex_unlock(&iflock);
08464 doomed = handle_init_event(i, res);
08465 ast_mutex_lock(&iflock);
08466 }
08467 continue;
08468 }
08469 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08470 if (pollres & POLLIN) {
08471 if (i->owner || i->subs[SUB_REAL].owner) {
08472 #ifdef HAVE_PRI
08473 if (!i->pri)
08474 #endif
08475 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08476 continue;
08477 }
08478 if (!i->cidspill && !i->mwimonitor_fsk) {
08479 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08480 continue;
08481 }
08482 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08483 if (res > 0) {
08484 if (i->mwimonitor_fsk) {
08485 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08486 pthread_attr_t attr;
08487 pthread_t threadid;
08488 struct mwi_thread_data *mtd;
08489
08490 pthread_attr_init(&attr);
08491 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08492
08493 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08494 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08495 mtd->pvt = i;
08496 memcpy(mtd->buf, buf, res);
08497 mtd->len = res;
08498 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08499 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08500 ast_free(mtd);
08501 }
08502 i->mwimonitoractive = 1;
08503 }
08504 }
08505 }
08506 } else {
08507 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08508 }
08509 }
08510 if (pollres & POLLPRI) {
08511 if (i->owner || i->subs[SUB_REAL].owner) {
08512 #ifdef HAVE_PRI
08513 if (!i->pri)
08514 #endif
08515 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08516 continue;
08517 }
08518 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08519 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08520
08521 ast_mutex_unlock(&iflock);
08522 doomed = handle_init_event(i, res);
08523 ast_mutex_lock(&iflock);
08524 }
08525 }
08526 }
08527 ast_mutex_unlock(&iflock);
08528 }
08529
08530 return NULL;
08531
08532 }
08533
08534 static int restart_monitor(void)
08535 {
08536
08537 if (monitor_thread == AST_PTHREADT_STOP)
08538 return 0;
08539 ast_mutex_lock(&monlock);
08540 if (monitor_thread == pthread_self()) {
08541 ast_mutex_unlock(&monlock);
08542 ast_log(LOG_WARNING, "Cannot kill myself\n");
08543 return -1;
08544 }
08545 if (monitor_thread != AST_PTHREADT_NULL) {
08546
08547 pthread_kill(monitor_thread, SIGURG);
08548 } else {
08549
08550 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08551 ast_mutex_unlock(&monlock);
08552 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08553 return -1;
08554 }
08555 }
08556 ast_mutex_unlock(&monlock);
08557 return 0;
08558 }
08559
08560 #ifdef HAVE_PRI
08561 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08562 {
08563 int x;
08564 int trunkgroup;
08565
08566 trunkgroup = pris[*span].mastertrunkgroup;
08567 if (trunkgroup) {
08568
08569 for (x = 0; x < NUM_SPANS; x++) {
08570 if (pris[x].trunkgroup == trunkgroup) {
08571 *span = x;
08572 return 0;
08573 }
08574 }
08575 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08576 *span = -1;
08577 } else {
08578 if (pris[*span].trunkgroup) {
08579 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08580 *span = -1;
08581 } else if (pris[*span].mastertrunkgroup) {
08582 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08583 *span = -1;
08584 } else {
08585 if (si->totalchans == 31) {
08586
08587 pris[*span].dchannels[0] = 16 + offset;
08588 } else if (si->totalchans == 24) {
08589
08590 pris[*span].dchannels[0] = 24 + offset;
08591 } else if (si->totalchans == 3) {
08592
08593 pris[*span].dchannels[0] = 3 + offset;
08594 } else {
08595 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);
08596 *span = -1;
08597 return 0;
08598 }
08599 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08600 pris[*span].offset = offset;
08601 pris[*span].span = *span + 1;
08602 }
08603 }
08604 return 0;
08605 }
08606
08607 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08608 {
08609 struct dahdi_spaninfo si;
08610 struct dahdi_params p;
08611 int fd;
08612 int span;
08613 int ospan=0;
08614 int x,y;
08615 for (x = 0; x < NUM_SPANS; x++) {
08616 if (pris[x].trunkgroup == trunkgroup) {
08617 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08618 return -1;
08619 }
08620 }
08621 for (y = 0; y < NUM_DCHANS; y++) {
08622 if (!channels[y])
08623 break;
08624 memset(&si, 0, sizeof(si));
08625 memset(&p, 0, sizeof(p));
08626 fd = open("/dev/dahdi/channel", O_RDWR);
08627 if (fd < 0) {
08628 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08629 return -1;
08630 }
08631 x = channels[y];
08632 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08633 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08634 close(fd);
08635 return -1;
08636 }
08637 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08638 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08639 return -1;
08640 }
08641 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08642 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08643 close(fd);
08644 return -1;
08645 }
08646 span = p.spanno - 1;
08647 if (pris[span].trunkgroup) {
08648 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08649 close(fd);
08650 return -1;
08651 }
08652 if (pris[span].pvts[0]) {
08653 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08654 close(fd);
08655 return -1;
08656 }
08657 if (!y) {
08658 pris[span].trunkgroup = trunkgroup;
08659 pris[span].offset = channels[y] - p.chanpos;
08660 ospan = span;
08661 }
08662 pris[ospan].dchannels[y] = channels[y];
08663 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08664 pris[span].span = span + 1;
08665 close(fd);
08666 }
08667 return 0;
08668 }
08669
08670 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08671 {
08672 if (pris[span].mastertrunkgroup) {
08673 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);
08674 return -1;
08675 }
08676 pris[span].mastertrunkgroup = trunkgroup;
08677 pris[span].prilogicalspan = logicalspan;
08678 return 0;
08679 }
08680
08681 #endif
08682
08683 #ifdef HAVE_SS7
08684
08685 static unsigned int parse_pointcode(const char *pcstring)
08686 {
08687 unsigned int code1, code2, code3;
08688 int numvals;
08689
08690 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
08691 if (numvals == 1)
08692 return code1;
08693 if (numvals == 3)
08694 return (code1 << 16) | (code2 << 8) | code3;
08695
08696 return 0;
08697 }
08698
08699 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
08700 {
08701 if ((linkset < 0) || (linkset >= NUM_SPANS))
08702 return NULL;
08703 else
08704 return &linksets[linkset - 1];
08705 }
08706 #endif
08707
08708
08709
08710
08711
08712
08713 static int sigtype_to_signalling(int sigtype)
08714 {
08715 return sigtype;
08716 }
08717
08718 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08719 {
08720
08721 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08722 char fn[80];
08723 struct dahdi_bufferinfo bi;
08724
08725 int res;
08726 int span = 0;
08727 int here = 0;
08728 int x;
08729 struct dahdi_pvt **wlist;
08730 struct dahdi_pvt **wend;
08731 struct dahdi_params p;
08732
08733 wlist = &iflist;
08734 wend = &ifend;
08735
08736 #ifdef HAVE_PRI
08737 if (pri) {
08738 wlist = &pri->crvs;
08739 wend = &pri->crvend;
08740 }
08741 #endif
08742
08743 tmp2 = *wlist;
08744 prev = NULL;
08745
08746 while (tmp2) {
08747 if (!tmp2->destroy) {
08748 if (tmp2->channel == channel) {
08749 tmp = tmp2;
08750 here = 1;
08751 break;
08752 }
08753 if (tmp2->channel > channel) {
08754 break;
08755 }
08756 }
08757 prev = tmp2;
08758 tmp2 = tmp2->next;
08759 }
08760
08761 if (!here && reloading != 1) {
08762 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08763 if (tmp)
08764 free(tmp);
08765 return NULL;
08766 }
08767 ast_mutex_init(&tmp->lock);
08768 ifcount++;
08769 for (x = 0; x < 3; x++)
08770 tmp->subs[x].dfd = -1;
08771 tmp->channel = channel;
08772 tmp->priindication_oob = conf->chan.priindication_oob;
08773 }
08774
08775 if (tmp) {
08776 int chan_sig = conf->chan.sig;
08777 if (!here) {
08778 if ((channel != CHAN_PSEUDO) && !pri) {
08779 int count = 0;
08780 snprintf(fn, sizeof(fn), "%d", channel);
08781
08782 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08783 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08784 usleep(1);
08785 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08786 count++;
08787 }
08788
08789 if (tmp->subs[SUB_REAL].dfd < 0) {
08790 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);
08791 destroy_dahdi_pvt(&tmp);
08792 return NULL;
08793 }
08794 memset(&p, 0, sizeof(p));
08795 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08796 if (res < 0) {
08797 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08798 destroy_dahdi_pvt(&tmp);
08799 return NULL;
08800 }
08801 if (conf->is_sig_auto)
08802 chan_sig = sigtype_to_signalling(p.sigtype);
08803 if (p.sigtype != (chan_sig & 0x3ffff)) {
08804 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));
08805 destroy_dahdi_pvt(&tmp);
08806 return NULL;
08807 }
08808 tmp->law = p.curlaw;
08809 tmp->span = p.spanno;
08810 span = p.spanno - 1;
08811 } else {
08812 if (channel == CHAN_PSEUDO)
08813 chan_sig = 0;
08814 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08815 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08816 return NULL;
08817 }
08818 }
08819 #ifdef HAVE_SS7
08820 if (chan_sig == SIG_SS7) {
08821 struct dahdi_ss7 *ss7;
08822 int clear = 0;
08823 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08824 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08825 destroy_dahdi_pvt(&tmp);
08826 return NULL;
08827 }
08828
08829 ss7 = ss7_resolve_linkset(cur_linkset);
08830 if (!ss7) {
08831 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08832 destroy_dahdi_pvt(&tmp);
08833 return NULL;
08834 }
08835 if (cur_cicbeginswith < 0) {
08836 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08837 destroy_dahdi_pvt(&tmp);
08838 return NULL;
08839 }
08840
08841 tmp->cic = cur_cicbeginswith++;
08842
08843
08844 tmp->dpc = cur_defaultdpc;
08845
08846 tmp->ss7 = ss7;
08847 tmp->ss7call = NULL;
08848 ss7->pvts[ss7->numchans++] = tmp;
08849
08850 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
08851 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
08852 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
08853 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
08854
08855 ss7->called_nai = conf->ss7.called_nai;
08856 ss7->calling_nai = conf->ss7.calling_nai;
08857 }
08858 #endif
08859 #ifdef HAVE_PRI
08860 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08861 int offset;
08862 int myswitchtype;
08863 int matchesdchan;
08864 int x,y;
08865 offset = 0;
08866 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
08867 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08868 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08869 destroy_dahdi_pvt(&tmp);
08870 return NULL;
08871 }
08872 if (span >= NUM_SPANS) {
08873 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08874 destroy_dahdi_pvt(&tmp);
08875 return NULL;
08876 } else {
08877 struct dahdi_spaninfo si;
08878 si.spanno = 0;
08879 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08880 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08881 destroy_dahdi_pvt(&tmp);
08882 return NULL;
08883 }
08884
08885 tmp->logicalspan = pris[span].prilogicalspan;
08886 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08887 if (span < 0) {
08888 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08889 destroy_dahdi_pvt(&tmp);
08890 return NULL;
08891 }
08892 if ((chan_sig == SIG_PRI) ||
08893 (chan_sig == SIG_BRI) ||
08894 (chan_sig == SIG_BRI_PTMP))
08895 myswitchtype = conf->pri.switchtype;
08896 else
08897 myswitchtype = PRI_SWITCH_GR303_TMC;
08898
08899 matchesdchan=0;
08900 for (x = 0; x < NUM_SPANS; x++) {
08901 for (y = 0; y < NUM_DCHANS; y++) {
08902 if (pris[x].dchannels[y] == tmp->channel) {
08903 matchesdchan = 1;
08904 break;
08905 }
08906 }
08907 }
08908 offset = p.chanpos;
08909 if (!matchesdchan) {
08910 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08911 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08912 destroy_dahdi_pvt(&tmp);
08913 return NULL;
08914 }
08915 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08916 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08917 destroy_dahdi_pvt(&tmp);
08918 return NULL;
08919 }
08920 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08921 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08922 destroy_dahdi_pvt(&tmp);
08923 return NULL;
08924 }
08925 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08926 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08927 destroy_dahdi_pvt(&tmp);
08928 return NULL;
08929 }
08930 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08931 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08932 destroy_dahdi_pvt(&tmp);
08933 return NULL;
08934 }
08935 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08936 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08937 destroy_dahdi_pvt(&tmp);
08938 return NULL;
08939 }
08940 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08941 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08942 destroy_dahdi_pvt(&tmp);
08943 return NULL;
08944 }
08945 if (pris[span].numchans >= MAX_CHANNELS) {
08946 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08947 pris[span].trunkgroup);
08948 destroy_dahdi_pvt(&tmp);
08949 return NULL;
08950 }
08951
08952 pris[span].sig = chan_sig;
08953 pris[span].nodetype = conf->pri.nodetype;
08954 pris[span].switchtype = myswitchtype;
08955 pris[span].nsf = conf->pri.nsf;
08956 pris[span].dialplan = conf->pri.dialplan;
08957 pris[span].localdialplan = conf->pri.localdialplan;
08958 pris[span].pvts[pris[span].numchans++] = tmp;
08959 pris[span].minunused = conf->pri.minunused;
08960 pris[span].minidle = conf->pri.minidle;
08961 pris[span].overlapdial = conf->pri.overlapdial;
08962 #ifdef HAVE_PRI_INBANDDISCONNECT
08963 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08964 #endif
08965 pris[span].facilityenable = conf->pri.facilityenable;
08966 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08967 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08968 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08969 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08970 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08971 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08972 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08973 pris[span].resetinterval = conf->pri.resetinterval;
08974
08975 tmp->pri = &pris[span];
08976 tmp->prioffset = offset;
08977 tmp->call = NULL;
08978 } else {
08979 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08980 destroy_dahdi_pvt(&tmp);
08981 return NULL;
08982 }
08983 }
08984 } else {
08985 tmp->prioffset = 0;
08986 }
08987 #endif
08988 } else {
08989 chan_sig = tmp->sig;
08990 if (tmp->subs[SUB_REAL].dfd > -1) {
08991 memset(&p, 0, sizeof(p));
08992 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08993 }
08994 }
08995
08996 switch (chan_sig) {
08997 case SIG_FXSKS:
08998 case SIG_FXSLS:
08999 case SIG_EM:
09000 case SIG_EM_E1:
09001 case SIG_EMWINK:
09002 case SIG_FEATD:
09003 case SIG_FEATDMF:
09004 case SIG_FEATDMF_TA:
09005 case SIG_FEATB:
09006 case SIG_E911:
09007 case SIG_SF:
09008 case SIG_SFWINK:
09009 case SIG_FGC_CAMA:
09010 case SIG_FGC_CAMAMF:
09011 case SIG_SF_FEATD:
09012 case SIG_SF_FEATDMF:
09013 case SIG_SF_FEATB:
09014 p.starttime = 250;
09015 break;
09016 }
09017
09018 if (tmp->radio) {
09019
09020 p.channo = channel;
09021 p.rxwinktime = 1;
09022 p.rxflashtime = 1;
09023 p.starttime = 1;
09024 p.debouncetime = 5;
09025 }
09026 if (!tmp->radio) {
09027 p.channo = channel;
09028
09029 if (conf->timing.prewinktime >= 0)
09030 p.prewinktime = conf->timing.prewinktime;
09031 if (conf->timing.preflashtime >= 0)
09032 p.preflashtime = conf->timing.preflashtime;
09033 if (conf->timing.winktime >= 0)
09034 p.winktime = conf->timing.winktime;
09035 if (conf->timing.flashtime >= 0)
09036 p.flashtime = conf->timing.flashtime;
09037 if (conf->timing.starttime >= 0)
09038 p.starttime = conf->timing.starttime;
09039 if (conf->timing.rxwinktime >= 0)
09040 p.rxwinktime = conf->timing.rxwinktime;
09041 if (conf->timing.rxflashtime >= 0)
09042 p.rxflashtime = conf->timing.rxflashtime;
09043 if (conf->timing.debouncetime >= 0)
09044 p.debouncetime = conf->timing.debouncetime;
09045 }
09046
09047
09048 if (tmp->subs[SUB_REAL].dfd >= 0)
09049 {
09050 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09051 if (res < 0) {
09052 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09053 destroy_dahdi_pvt(&tmp);
09054 return NULL;
09055 }
09056 }
09057 #if 1
09058 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09059 memset(&bi, 0, sizeof(bi));
09060 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09061 if (!res) {
09062 bi.txbufpolicy = conf->chan.buf_policy;
09063 bi.rxbufpolicy = conf->chan.buf_policy;
09064 bi.numbufs = conf->chan.buf_no;
09065 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09066 if (res < 0) {
09067 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09068 }
09069 } else
09070 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09071 }
09072 #endif
09073 tmp->immediate = conf->chan.immediate;
09074 tmp->transfertobusy = conf->chan.transfertobusy;
09075 if (chan_sig & __DAHDI_SIG_FXS) {
09076 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
09077 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
09078 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
09079 }
09080 tmp->sig = chan_sig;
09081 tmp->outsigmod = conf->chan.outsigmod;
09082 tmp->ringt_base = ringt_base;
09083 tmp->firstradio = 0;
09084 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09085 tmp->permcallwaiting = conf->chan.callwaiting;
09086 else
09087 tmp->permcallwaiting = 0;
09088
09089 tmp->destroy = 0;
09090 tmp->drings = conf->chan.drings;
09091
09092
09093 if (tmp->drings.ringnum[0].range == 0)
09094 tmp->drings.ringnum[0].range = 10;
09095 if (tmp->drings.ringnum[1].range == 0)
09096 tmp->drings.ringnum[1].range = 10;
09097 if (tmp->drings.ringnum[2].range == 0)
09098 tmp->drings.ringnum[2].range = 10;
09099
09100 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
09101 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09102 tmp->threewaycalling = conf->chan.threewaycalling;
09103 tmp->adsi = conf->chan.adsi;
09104 tmp->use_smdi = conf->chan.use_smdi;
09105 tmp->permhidecallerid = conf->chan.hidecallerid;
09106 tmp->callreturn = conf->chan.callreturn;
09107 tmp->echocancel = conf->chan.echocancel;
09108 tmp->echotraining = conf->chan.echotraining;
09109 tmp->pulse = conf->chan.pulse;
09110 if (tmp->echocancel.head.tap_length) {
09111 tmp->echocanbridged = conf->chan.echocanbridged;
09112 } else {
09113 if (conf->chan.echocanbridged)
09114 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09115 tmp->echocanbridged = 0;
09116 }
09117 tmp->busydetect = conf->chan.busydetect;
09118 tmp->busycount = conf->chan.busycount;
09119 tmp->busy_tonelength = conf->chan.busy_tonelength;
09120 tmp->busy_quietlength = conf->chan.busy_quietlength;
09121 tmp->callprogress = conf->chan.callprogress;
09122 tmp->cancallforward = conf->chan.cancallforward;
09123 tmp->dtmfrelax = conf->chan.dtmfrelax;
09124 tmp->callwaiting = tmp->permcallwaiting;
09125 tmp->hidecallerid = tmp->permhidecallerid;
09126 tmp->channel = channel;
09127 tmp->stripmsd = conf->chan.stripmsd;
09128 tmp->use_callerid = conf->chan.use_callerid;
09129 tmp->cid_signalling = conf->chan.cid_signalling;
09130 tmp->cid_start = conf->chan.cid_start;
09131 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09132 tmp->restrictcid = conf->chan.restrictcid;
09133 tmp->use_callingpres = conf->chan.use_callingpres;
09134 tmp->priexclusive = conf->chan.priexclusive;
09135 if (tmp->usedistinctiveringdetection) {
09136 if (!tmp->use_callerid) {
09137 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09138 tmp->use_callerid = 1;
09139 }
09140 }
09141
09142 if (tmp->cid_signalling == CID_SIG_SMDI) {
09143 if (!tmp->use_smdi) {
09144 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09145 tmp->use_smdi = 1;
09146 }
09147 }
09148 if (tmp->use_smdi) {
09149 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09150 if (!(tmp->smdi_iface)) {
09151 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09152 tmp->use_smdi = 0;
09153 }
09154 }
09155
09156 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09157 tmp->amaflags = conf->chan.amaflags;
09158 if (!here) {
09159 tmp->confno = -1;
09160 tmp->propconfno = -1;
09161 }
09162 tmp->canpark = conf->chan.canpark;
09163 tmp->transfer = conf->chan.transfer;
09164 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09165 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09166 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09167 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09168 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09169 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
09170 tmp->cid_ton = 0;
09171 if ((tmp->sig != SIG_PRI) || (tmp->sig != SIG_SS7) || (tmp->sig != SIG_BRI) || (tmp->sig != SIG_BRI_PTMP)) {
09172 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09173 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09174 } else {
09175 tmp->cid_num[0] = '\0';
09176 tmp->cid_name[0] = '\0';
09177 }
09178 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09179 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
09180 char *mailbox, *context;
09181 mailbox = context = ast_strdupa(tmp->mailbox);
09182 strsep(&context, "@");
09183 if (ast_strlen_zero(context))
09184 context = "default";
09185 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
09186 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
09187 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
09188 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
09189 AST_EVENT_IE_END);
09190 }
09191 tmp->msgstate = -1;
09192 tmp->group = conf->chan.group;
09193 tmp->callgroup = conf->chan.callgroup;
09194 tmp->pickupgroup= conf->chan.pickupgroup;
09195 if (conf->chan.vars) {
09196 tmp->vars = ast_variable_new(conf->chan.vars->name, conf->chan.vars->value, "");
09197 }
09198 tmp->cid_rxgain = conf->chan.cid_rxgain;
09199 tmp->rxgain = conf->chan.rxgain;
09200 tmp->txgain = conf->chan.txgain;
09201 tmp->tonezone = conf->chan.tonezone;
09202 tmp->onhooktime = time(NULL);
09203 if (tmp->subs[SUB_REAL].dfd > -1) {
09204 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09205 if (tmp->dsp)
09206 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09207 update_conf(tmp);
09208 if (!here) {
09209 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
09210
09211 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09212 }
09213 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09214 #ifdef HAVE_PRI
09215
09216 if (tmp->pri && !pri_is_up(tmp->pri))
09217 tmp->inalarm = 1;
09218 #endif
09219 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09220 tmp->inalarm = 1;
09221 handle_alarms(tmp, res);
09222 }
09223 }
09224
09225 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09226 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09227 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09228 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09229 if (!here) {
09230 tmp->locallyblocked = tmp->remotelyblocked = 0;
09231 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09232 tmp->inservice = 0;
09233 else
09234 tmp->inservice = 1;
09235 }
09236 }
09237 if (tmp && !here) {
09238
09239 if (!*wlist) {
09240 *wlist = tmp;
09241 tmp->prev = NULL;
09242 tmp->next = NULL;
09243 *wend = tmp;
09244 } else {
09245
09246 struct dahdi_pvt *working = *wlist;
09247
09248
09249 if (working->channel > tmp->channel) {
09250 tmp->next = *wlist;
09251 tmp->prev = NULL;
09252 (*wlist)->prev = tmp;
09253 *wlist = tmp;
09254 } else {
09255
09256 while (working) {
09257
09258 if (working->next) {
09259 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09260 tmp->next = working->next;
09261 tmp->prev = working;
09262 working->next->prev = tmp;
09263 working->next = tmp;
09264 break;
09265 }
09266 } else {
09267
09268 if (working->channel < tmp->channel) {
09269 working->next = tmp;
09270 tmp->next = NULL;
09271 tmp->prev = working;
09272 *wend = tmp;
09273 break;
09274 }
09275 }
09276 working = working->next;
09277 }
09278 }
09279 }
09280 }
09281 return tmp;
09282 }
09283
09284 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09285 {
09286 int res;
09287 struct dahdi_params par;
09288
09289
09290 if (groupmatch) {
09291 if ((p->group & groupmatch) != groupmatch)
09292 return 0;
09293 *groupmatched = 1;
09294 }
09295
09296 if (channelmatch != -1) {
09297 if (p->channel != channelmatch)
09298 return 0;
09299 *channelmatched = 1;
09300 }
09301
09302 if (busy) {
09303 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09304 *busy = 1;
09305 }
09306
09307 if (p->dnd)
09308 return 0;
09309
09310 if (p->guardtime && (time(NULL) < p->guardtime))
09311 return 0;
09312
09313 if (p->locallyblocked || p->remotelyblocked)
09314 return 0;
09315
09316
09317 if (!p->owner) {
09318 #ifdef HAVE_PRI
09319
09320 if (p->pri) {
09321 if (p->resetting || p->call)
09322 return 0;
09323 else
09324 return 1;
09325 }
09326 #endif
09327 #ifdef HAVE_SS7
09328
09329 if (p->ss7) {
09330 if (p->ss7call)
09331 return 0;
09332 else
09333 return 1;
09334 }
09335 #endif
09336 if (!(p->radio || (p->oprmode < 0)))
09337 {
09338 if (!p->sig || (p->sig == SIG_FXSLS))
09339 return 1;
09340
09341 if (p->subs[SUB_REAL].dfd > -1) {
09342 memset(&par, 0, sizeof(par));
09343 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09344 } else {
09345
09346 res = 0;
09347 par.rxisoffhook = 0;
09348 }
09349 if (res) {
09350 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09351 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09352
09353
09354
09355 if (par.rxbits > -1)
09356 return 1;
09357 if (par.rxisoffhook)
09358 return 1;
09359 else
09360 return 0;
09361 } else if (par.rxisoffhook) {
09362 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09363
09364 #ifdef DAHDI_CHECK_HOOKSTATE
09365 return 0;
09366 #else
09367 return 1;
09368 #endif
09369 }
09370 }
09371 return 1;
09372 }
09373
09374
09375 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09376 return 0;
09377
09378 if (!p->callwaiting) {
09379
09380 return 0;
09381 }
09382
09383 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09384
09385 return 0;
09386 }
09387
09388 if ((p->owner->_state != AST_STATE_UP) &&
09389 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09390
09391 return 0;
09392 }
09393 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09394
09395 return 0;
09396 }
09397
09398 return 1;
09399 }
09400
09401 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09402 {
09403 struct dahdi_pvt *p;
09404 struct dahdi_bufferinfo bi;
09405 int res;
09406
09407 if ((p = ast_malloc(sizeof(*p)))) {
09408 memcpy(p, src, sizeof(struct dahdi_pvt));
09409 ast_mutex_init(&p->lock);
09410 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09411
09412 if (p->subs[SUB_REAL].dfd < 0) {
09413 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09414 destroy_dahdi_pvt(&p);
09415 return NULL;
09416 }
09417 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09418 if (!res) {
09419 bi.txbufpolicy = src->buf_policy;
09420 bi.rxbufpolicy = src->buf_policy;
09421 bi.numbufs = src->buf_no;
09422 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09423 if (res < 0) {
09424 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09425 }
09426 } else
09427 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09428 }
09429 p->destroy = 1;
09430 p->next = iflist;
09431 p->prev = NULL;
09432 iflist = p;
09433 if (iflist->next)
09434 iflist->next->prev = p;
09435 return p;
09436 }
09437
09438
09439 #ifdef HAVE_PRI
09440 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09441 {
09442 int x;
09443 if (backwards)
09444 x = pri->numchans;
09445 else
09446 x = 0;
09447 for (;;) {
09448 if (backwards && (x < 0))
09449 break;
09450 if (!backwards && (x >= pri->numchans))
09451 break;
09452 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09453 ast_debug(1, "Found empty available channel %d/%d\n",
09454 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09455 return x;
09456 }
09457 if (backwards)
09458 x--;
09459 else
09460 x++;
09461 }
09462 return -1;
09463 }
09464 #endif
09465
09466 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09467 {
09468 ast_group_t groupmatch = 0;
09469 int channelmatch = -1;
09470 int roundrobin = 0;
09471 int callwait = 0;
09472 int busy = 0;
09473 struct dahdi_pvt *p;
09474 struct ast_channel *tmp = NULL;
09475 char *dest=NULL;
09476 int x;
09477 char *s;
09478 char opt=0;
09479 int res=0, y=0;
09480 int backwards = 0;
09481 #ifdef HAVE_PRI
09482 int crv;
09483 int bearer = -1;
09484 int trunkgroup;
09485 struct dahdi_pri *pri=NULL;
09486 #endif
09487 struct dahdi_pvt *exitpvt, *start, *end;
09488 ast_mutex_t *lock;
09489 int channelmatched = 0;
09490 int groupmatched = 0;
09491
09492
09493
09494
09495
09496
09497
09498
09499
09500
09501
09502
09503
09504
09505
09506
09507
09508
09509
09510 lock = &iflock;
09511 start = iflist;
09512 end = ifend;
09513 if (data) {
09514 dest = ast_strdupa((char *)data);
09515 } else {
09516 ast_log(LOG_WARNING, "Channel requested with no data\n");
09517 return NULL;
09518 }
09519 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09520
09521 char *stringp;
09522
09523 stringp = dest + 1;
09524 s = strsep(&stringp, "/");
09525 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09526 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09527 return NULL;
09528 }
09529 groupmatch = ((ast_group_t) 1 << x);
09530 if (toupper(dest[0]) == 'G') {
09531 if (dest[0] == 'G') {
09532 backwards = 1;
09533 p = ifend;
09534 } else
09535 p = iflist;
09536 } else {
09537 if (dest[0] == 'R') {
09538 backwards = 1;
09539 p = round_robin[x]?round_robin[x]->prev:ifend;
09540 if (!p)
09541 p = ifend;
09542 } else {
09543 p = round_robin[x]?round_robin[x]->next:iflist;
09544 if (!p)
09545 p = iflist;
09546 }
09547 roundrobin = 1;
09548 }
09549 } else {
09550 char *stringp;
09551
09552 stringp = dest;
09553 s = strsep(&stringp, "/");
09554 p = iflist;
09555 if (!strcasecmp(s, "pseudo")) {
09556
09557 x = CHAN_PSEUDO;
09558 channelmatch = x;
09559 }
09560 #ifdef HAVE_PRI
09561 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09562 if ((trunkgroup < 1) || (crv < 1)) {
09563 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09564 return NULL;
09565 }
09566 res--;
09567 for (x = 0; x < NUM_SPANS; x++) {
09568 if (pris[x].trunkgroup == trunkgroup) {
09569 pri = pris + x;
09570 lock = &pri->lock;
09571 start = pri->crvs;
09572 end = pri->crvend;
09573 break;
09574 }
09575 }
09576 if (!pri) {
09577 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09578 return NULL;
09579 }
09580 channelmatch = crv;
09581 p = pris[x].crvs;
09582 }
09583 #endif
09584 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09585 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09586 return NULL;
09587 } else {
09588 channelmatch = x;
09589 }
09590 }
09591
09592 ast_mutex_lock(lock);
09593 exitpvt = p;
09594 while (p && !tmp) {
09595 if (roundrobin)
09596 round_robin[x] = p;
09597 #if 0
09598 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09599 #endif
09600
09601 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09602 ast_debug(1, "Using channel %d\n", p->channel);
09603 if (p->inalarm)
09604 goto next;
09605
09606 callwait = (p->owner != NULL);
09607 #ifdef HAVE_PRI
09608 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09609 if (p->sig != SIG_FXSKS) {
09610
09611
09612 bearer = pri_find_empty_chan(pri, 0);
09613 if (bearer < 0) {
09614 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09615 p = NULL;
09616 break;
09617 }
09618 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09619 } else {
09620 if (alloc_sub(p, 0)) {
09621 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09622 p = NULL;
09623 break;
09624 } else
09625 ast_debug(1, "Allocated placeholder pseudo channel\n");
09626
09627 p->pri = pri;
09628 }
09629 }
09630 #endif
09631 if (p->channel == CHAN_PSEUDO) {
09632 p = chandup(p);
09633 if (!p) {
09634 break;
09635 }
09636 }
09637 if (p->owner) {
09638 if (alloc_sub(p, SUB_CALLWAIT)) {
09639 p = NULL;
09640 break;
09641 }
09642 }
09643 p->outgoing = 1;
09644 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09645 if (!tmp) {
09646 p->outgoing = 0;
09647 }
09648 #ifdef HAVE_PRI
09649 if (p->bearer) {
09650
09651 p->bearer->owner = tmp;
09652 }
09653 #endif
09654
09655 if (res > 1) {
09656 if (opt == 'c') {
09657
09658 p->confirmanswer = 1;
09659 } else if (opt == 'r') {
09660
09661 if (res < 3)
09662 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09663 else
09664 p->distinctivering = y;
09665 } else if (opt == 'd') {
09666
09667 p->digital = 1;
09668 if (tmp)
09669 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09670 } else {
09671 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09672 }
09673 }
09674
09675 if (tmp && callwait)
09676 tmp->cdrflags |= AST_CDR_CALLWAIT;
09677 break;
09678 }
09679 next:
09680 if (backwards) {
09681 p = p->prev;
09682 if (!p)
09683 p = end;
09684 } else {
09685 p = p->next;
09686 if (!p)
09687 p = start;
09688 }
09689
09690 if (p == exitpvt)
09691 break;
09692 }
09693 ast_mutex_unlock(lock);
09694 restart_monitor();
09695 if (callwait)
09696 *cause = AST_CAUSE_BUSY;
09697 else if (!tmp) {
09698 if (channelmatched) {
09699 if (busy)
09700 *cause = AST_CAUSE_BUSY;
09701 } else if (groupmatched) {
09702 *cause = AST_CAUSE_CONGESTION;
09703 }
09704 }
09705
09706 return tmp;
09707 }
09708
09709 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09710 static int dahdi_setlaw(int dfd, int law)
09711 {
09712 return ioctl(dfd, DAHDI_SETLAW, &law);
09713 }
09714 #endif
09715
09716 #ifdef HAVE_SS7
09717
09718 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
09719 {
09720 int i;
09721 int winner = -1;
09722 for (i = 0; i < linkset->numchans; i++) {
09723 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09724 winner = i;
09725 break;
09726 }
09727 }
09728 return winner;
09729 }
09730
09731 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09732 {
09733 unsigned char status[32];
09734 struct dahdi_pvt *p = NULL;
09735 int i, offset;
09736
09737 for (i = 0; i < linkset->numchans; i++) {
09738 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09739 p = linkset->pvts[i];
09740 offset = p->cic - startcic;
09741 status[offset] = 0;
09742 if (p->locallyblocked)
09743 status[offset] |= (1 << 0) | (1 << 4);
09744 if (p->remotelyblocked)
09745 status[offset] |= (1 << 1) | (1 << 5);
09746 if (p->ss7call) {
09747 if (p->outgoing)
09748 status[offset] |= (1 << 3);
09749 else
09750 status[offset] |= (1 << 2);
09751 } else
09752 status[offset] |= 0x3 << 2;
09753 }
09754 }
09755
09756 if (p)
09757 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09758 else
09759 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09760
09761 }
09762
09763 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
09764 {
09765 int i;
09766
09767 for (i = 0; i < linkset->numchans; i++) {
09768 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09769 if (state) {
09770 if (state[i])
09771 linkset->pvts[i]->remotelyblocked = block;
09772 } else
09773 linkset->pvts[i]->remotelyblocked = block;
09774 }
09775 }
09776 }
09777
09778 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09779 {
09780 int i;
09781
09782 for (i = 0; i < linkset->numchans; i++) {
09783 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09784 linkset->pvts[i]->inservice = 1;
09785 }
09786 }
09787
09788 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
09789 {
09790 int i, startcic = -1, endcic, dpc;
09791
09792 if (linkset->numchans <= 0)
09793 return;
09794
09795 startcic = linkset->pvts[0]->cic;
09796
09797 dpc = linkset->pvts[0]->dpc;
09798
09799 for (i = 0; i < linkset->numchans; i++) {
09800 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)) {
09801 continue;
09802 } else {
09803 endcic = linkset->pvts[i]->cic;
09804 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09805 isup_grs(linkset->ss7, startcic, endcic, dpc);
09806
09807
09808 if (linkset->pvts[i+1]) {
09809 startcic = linkset->pvts[i+1]->cic;
09810 dpc = linkset->pvts[i+1]->dpc;
09811 }
09812 }
09813 }
09814 }
09815
09816 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
09817 {
09818 if (p->loopedback != enable) {
09819 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09820 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09821 return;
09822 }
09823 p->loopedback = enable;
09824 }
09825 }
09826
09827
09828 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
09829 {
09830 struct ss7 *ss7 = linkset->ss7;
09831 int res;
09832 int law = 1;
09833 struct ast_channel *c;
09834 char tmp[256];
09835
09836 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09837 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09838
09839 if (linkset->type == SS7_ITU)
09840 law = DAHDI_LAW_ALAW;
09841 else
09842 law = DAHDI_LAW_MULAW;
09843
09844 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09845 if (res < 0)
09846 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09847
09848 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09849 p->proceeding = 1;
09850 isup_acm(ss7, p->ss7call);
09851 }
09852
09853 ast_mutex_unlock(&linkset->lock);
09854 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09855
09856 if (!c) {
09857 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09858
09859 ast_mutex_lock(&linkset->lock);
09860 return;
09861 } else
09862 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09863
09864 dahdi_enable_ec(p);
09865
09866
09867
09868
09869
09870 ast_mutex_unlock(&p->lock);
09871
09872 if (!ast_strlen_zero(p->charge_number)) {
09873 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09874
09875 p->charge_number[0] = 0;
09876 }
09877 if (!ast_strlen_zero(p->gen_add_number)) {
09878 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09879
09880 p->gen_add_number[0] = 0;
09881 }
09882 if (!ast_strlen_zero(p->jip_number)) {
09883 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09884
09885 p->jip_number[0] = 0;
09886 }
09887 if (!ast_strlen_zero(p->gen_dig_number)) {
09888 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09889
09890 p->gen_dig_number[0] = 0;
09891 }
09892 if (!ast_strlen_zero(p->orig_called_num)) {
09893 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09894
09895 p->orig_called_num[0] = 0;
09896 }
09897
09898 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09899 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09900
09901 p->gen_dig_type = 0;
09902
09903 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09904 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09905
09906 p->gen_dig_scheme = 0;
09907
09908 if (!ast_strlen_zero(p->lspi_ident)) {
09909 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
09910
09911 p->lspi_ident[0] = 0;
09912 }
09913
09914 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
09915 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
09916
09917 p->call_ref_ident = 0;
09918
09919 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
09920 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
09921
09922 p->call_ref_pc = 0;
09923
09924 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
09925 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
09926
09927 p->calling_party_cat = 0;
09928
09929 if (!ast_strlen_zero(p->redirecting_num)) {
09930 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
09931
09932 p->redirecting_num[0] = 0;
09933 }
09934 if (!ast_strlen_zero(p->generic_name)) {
09935 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
09936
09937 p->generic_name[0] = 0;
09938 }
09939
09940 ast_mutex_lock(&p->lock);
09941 ast_mutex_lock(&linkset->lock);
09942 }
09943
09944 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
09945 {
09946 if (ast_strlen_zero(number)) {
09947 if (size) {
09948 *buf = '\0';
09949 }
09950 return;
09951 }
09952 switch (nai) {
09953 case SS7_NAI_INTERNATIONAL:
09954 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
09955 break;
09956 case SS7_NAI_NATIONAL:
09957 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
09958 break;
09959 case SS7_NAI_SUBSCRIBER:
09960 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
09961 break;
09962 case SS7_NAI_UNKNOWN:
09963 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
09964 break;
09965 default:
09966 snprintf(buf, size, "%s", number);
09967 break;
09968 }
09969 }
09970 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
09971 {
09972 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
09973 }
09974
09975 static void *ss7_linkset(void *data)
09976 {
09977 int res, i;
09978 struct timeval *next = NULL, tv;
09979 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
09980 struct ss7 *ss7 = linkset->ss7;
09981 ss7_event *e = NULL;
09982 struct dahdi_pvt *p;
09983 int chanpos;
09984 struct pollfd pollers[NUM_DCHANS];
09985 int cic;
09986 unsigned int dpc;
09987 int nextms = 0;
09988
09989 ss7_start(ss7);
09990
09991 while(1) {
09992 ast_mutex_lock(&linkset->lock);
09993 if ((next = ss7_schedule_next(ss7))) {
09994 tv = ast_tvnow();
09995 tv.tv_sec = next->tv_sec - tv.tv_sec;
09996 tv.tv_usec = next->tv_usec - tv.tv_usec;
09997 if (tv.tv_usec < 0) {
09998 tv.tv_usec += 1000000;
09999 tv.tv_sec -= 1;
10000 }
10001 if (tv.tv_sec < 0) {
10002 tv.tv_sec = 0;
10003 tv.tv_usec = 0;
10004 }
10005 nextms = tv.tv_sec * 1000;
10006 nextms += tv.tv_usec / 1000;
10007 }
10008 ast_mutex_unlock(&linkset->lock);
10009
10010 for (i = 0; i < linkset->numsigchans; i++) {
10011 pollers[i].fd = linkset->fds[i];
10012 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
10013 pollers[i].revents = 0;
10014 }
10015
10016 res = poll(pollers, linkset->numsigchans, nextms);
10017 if ((res < 0) && (errno != EINTR)) {
10018 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
10019 } else if (!res) {
10020 ast_mutex_lock(&linkset->lock);
10021 ss7_schedule_run(ss7);
10022 ast_mutex_unlock(&linkset->lock);
10023 continue;
10024 }
10025
10026 ast_mutex_lock(&linkset->lock);
10027 for (i = 0; i < linkset->numsigchans; i++) {
10028 if (pollers[i].revents & POLLPRI) {
10029 int x;
10030 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
10031 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
10032 }
10033 switch (x) {
10034 case DAHDI_EVENT_OVERRUN:
10035 ast_debug(1, "Overrun detected!\n");
10036 break;
10037 case DAHDI_EVENT_BADFCS:
10038 ast_debug(1, "Bad FCS\n");
10039 break;
10040 case DAHDI_EVENT_ABORT:
10041 ast_debug(1, "HDLC Abort\n");
10042 break;
10043 case DAHDI_EVENT_ALARM:
10044 ast_log(LOG_ERROR, "Alarm on link!\n");
10045 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
10046 linkset->linkstate[i] &= ~LINKSTATE_UP;
10047 ss7_link_alarm(ss7, pollers[i].fd);
10048 break;
10049 case DAHDI_EVENT_NOALARM:
10050 ast_log(LOG_ERROR, "Alarm cleared on link\n");
10051 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
10052 linkset->linkstate[i] |= LINKSTATE_STARTING;
10053 ss7_link_noalarm(ss7, pollers[i].fd);
10054 break;
10055 default:
10056 ast_log(LOG_ERROR, "Got exception %d!\n", x);
10057 break;
10058 }
10059 }
10060
10061 if (pollers[i].revents & POLLIN) {
10062 ast_mutex_lock(&linkset->lock);
10063 res = ss7_read(ss7, pollers[i].fd);
10064 ast_mutex_unlock(&linkset->lock);
10065 }
10066
10067 if (pollers[i].revents & POLLOUT) {
10068 ast_mutex_lock(&linkset->lock);
10069 res = ss7_write(ss7, pollers[i].fd);
10070 ast_mutex_unlock(&linkset->lock);
10071 if (res < 0) {
10072 ast_debug(1, "Error in write %s\n", strerror(errno));
10073 }
10074 }
10075 }
10076
10077 while ((e = ss7_check_event(ss7))) {
10078 switch (e->e) {
10079 case SS7_EVENT_UP:
10080 if (linkset->state != LINKSET_STATE_UP) {
10081 ast_verbose("--- SS7 Up ---\n");
10082 ss7_reset_linkset(linkset);
10083 }
10084 linkset->state = LINKSET_STATE_UP;
10085 break;
10086 case SS7_EVENT_DOWN:
10087 ast_verbose("--- SS7 Down ---\n");
10088 linkset->state = LINKSET_STATE_DOWN;
10089 for (i = 0; i < linkset->numchans; i++) {
10090 struct dahdi_pvt *p = linkset->pvts[i];
10091 if (p)
10092 p->inalarm = 1;
10093 }
10094 break;
10095 case MTP2_LINK_UP:
10096 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
10097 break;
10098 case MTP2_LINK_DOWN:
10099 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
10100 break;
10101 case ISUP_EVENT_CPG:
10102 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
10103 if (chanpos < 0) {
10104 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
10105 break;
10106 }
10107 p = linkset->pvts[chanpos];
10108 ast_mutex_lock(&p->lock);
10109 switch (e->cpg.event) {
10110 case CPG_EVENT_ALERTING:
10111 p->alerting = 1;
10112 p->subs[SUB_REAL].needringing = 1;
10113 break;
10114 case CPG_EVENT_PROGRESS:
10115 case CPG_EVENT_INBANDINFO:
10116 {
10117 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10118 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
10119 dahdi_queue_frame(p, &f, linkset);
10120 p->progress = 1;
10121 p->dialing = 0;
10122 if (p->dsp && p->dsp_features) {
10123 ast_dsp_set_features(p->dsp, p->dsp_features);
10124 p->dsp_features = 0;
10125 }
10126 }
10127 break;
10128 default:
10129 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
10130 }
10131
10132 ast_mutex_unlock(&p->lock);
10133 break;
10134 case ISUP_EVENT_RSC:
10135 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
10136 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
10137 if (chanpos < 0) {
10138 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
10139 break;
10140 }
10141 p = linkset->pvts[chanpos];
10142 ast_mutex_lock(&p->lock);
10143 p->inservice = 1;
10144 p->remotelyblocked = 0;
10145 dpc = p->dpc;
10146 isup_set_call_dpc(e->rsc.call, dpc);
10147 if (p->ss7call)
10148 p->ss7call = NULL;
10149 if (p->owner)
10150 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10151 ast_mutex_unlock(&p->lock);
10152 isup_rlc(ss7, e->rsc.call);
10153 break;
10154 case ISUP_EVENT_GRS:
10155 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
10156 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
10157 if (chanpos < 0) {
10158 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
10159 break;
10160 }
10161 p = linkset->pvts[chanpos];
10162 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
10163 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
10164 break;
10165 case ISUP_EVENT_CQM:
10166 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
10167 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
10168 break;
10169 case ISUP_EVENT_GRA:
10170 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
10171 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
10172 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
10173 break;
10174 case ISUP_EVENT_IAM:
10175 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);
10176 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
10177 if (chanpos < 0) {
10178 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
10179 isup_rel(ss7, e->iam.call, -1);
10180 break;
10181 }
10182 p = linkset->pvts[chanpos];
10183 ast_mutex_lock(&p->lock);
10184 if (p->owner) {
10185 if (p->ss7call == e->iam.call) {
10186 ast_mutex_unlock(&p->lock);
10187 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
10188 break;
10189 } else {
10190 ast_mutex_unlock(&p->lock);
10191 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
10192 break;
10193 }
10194 }
10195
10196 dpc = p->dpc;
10197 p->ss7call = e->iam.call;
10198 isup_set_call_dpc(p->ss7call, dpc);
10199
10200 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
10201 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
10202 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
10203 } else
10204 p->cid_num[0] = 0;
10205
10206 if (p->immediate) {
10207 p->exten[0] = 's';
10208 p->exten[1] = '\0';
10209 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
10210 char *st;
10211 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
10212 st = strchr(p->exten, '#');
10213 if (st)
10214 *st = '\0';
10215 } else
10216 p->exten[0] = '\0';
10217
10218 p->cid_ani[0] = '\0';
10219 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
10220 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
10221 else
10222 p->cid_name[0] = '\0';
10223
10224 p->cid_ani2 = e->iam.oli_ani2;
10225 p->cid_ton = 0;
10226 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
10227 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
10228 p->gen_add_type = e->iam.gen_add_type;
10229 p->gen_add_nai = e->iam.gen_add_nai;
10230 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
10231 p->gen_add_num_plan = e->iam.gen_add_num_plan;
10232 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
10233 p->gen_dig_type = e->iam.gen_dig_type;
10234 p->gen_dig_scheme = e->iam.gen_dig_scheme;
10235 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
10236 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
10237 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
10238 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
10239 p->calling_party_cat = e->iam.calling_party_cat;
10240
10241
10242 if (!ast_strlen_zero(e->iam.called_party_num))
10243 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
10244
10245 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
10246
10247 if (e->iam.cot_check_required) {
10248 dahdi_loopback(p, 1);
10249 } else
10250 ss7_start_call(p, linkset);
10251 } else {
10252 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
10253 p->alreadyhungup = 1;
10254 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
10255 }
10256 ast_mutex_unlock(&p->lock);
10257 break;
10258 case ISUP_EVENT_COT:
10259 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
10260 if (chanpos < 0) {
10261 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
10262 isup_rel(ss7, e->cot.call, -1);
10263 break;
10264 }
10265 p = linkset->pvts[chanpos];
10266
10267 ast_mutex_lock(&p->lock);
10268
10269 if (p->loopedback) {
10270 dahdi_loopback(p, 0);
10271 ss7_start_call(p, linkset);
10272 }
10273
10274 ast_mutex_unlock(&p->lock);
10275
10276 break;
10277 case ISUP_EVENT_CCR:
10278 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
10279 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
10280 if (chanpos < 0) {
10281 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
10282 break;
10283 }
10284
10285 p = linkset->pvts[chanpos];
10286
10287 ast_mutex_lock(&p->lock);
10288 dahdi_loopback(p, 1);
10289 ast_mutex_unlock(&p->lock);
10290
10291 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
10292 break;
10293 case ISUP_EVENT_CVT:
10294 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
10295 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
10296 if (chanpos < 0) {
10297 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
10298 break;
10299 }
10300
10301 p = linkset->pvts[chanpos];
10302
10303 ast_mutex_lock(&p->lock);
10304 dahdi_loopback(p, 1);
10305 ast_mutex_unlock(&p->lock);
10306
10307 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
10308 break;
10309 case ISUP_EVENT_REL:
10310 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
10311 if (chanpos < 0) {
10312 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
10313 break;
10314 }
10315 p = linkset->pvts[chanpos];
10316 ast_mutex_lock(&p->lock);
10317 if (p->owner) {
10318 p->owner->hangupcause = e->rel.cause;
10319 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10320 } else if (!p->restartpending)
10321 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
10322
10323
10324 dahdi_loopback(p, 0);
10325
10326 isup_rlc(ss7, e->rel.call);
10327 p->ss7call = NULL;
10328
10329 ast_mutex_unlock(&p->lock);
10330 break;
10331 case ISUP_EVENT_ACM:
10332 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
10333 if (chanpos < 0) {
10334 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
10335 isup_rel(ss7, e->acm.call, -1);
10336 break;
10337 } else {
10338 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10339
10340 p = linkset->pvts[chanpos];
10341
10342 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
10343
10344 if (e->acm.call_ref_ident > 0) {
10345 p->rlt = 1;
10346 }
10347
10348 ast_mutex_lock(&p->lock);
10349 dahdi_queue_frame(p, &f, linkset);
10350 p->proceeding = 1;
10351 p->dialing = 0;
10352
10353 if (e->acm.called_party_status_ind == 1) {
10354 p->alerting = 1;
10355 p->subs[SUB_REAL].needringing = 1;
10356 }
10357 ast_mutex_unlock(&p->lock);
10358 }
10359 break;
10360 case ISUP_EVENT_CGB:
10361 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
10362 if (chanpos < 0) {
10363 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
10364 break;
10365 }
10366 p = linkset->pvts[chanpos];
10367 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
10368 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
10369 break;
10370 case ISUP_EVENT_CGU:
10371 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
10372 if (chanpos < 0) {
10373 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
10374 break;
10375 }
10376 p = linkset->pvts[chanpos];
10377 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
10378 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
10379 break;
10380 case ISUP_EVENT_UCIC:
10381 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
10382 if (chanpos < 0) {
10383 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
10384 break;
10385 }
10386 p = linkset->pvts[chanpos];
10387 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
10388 ast_mutex_lock(&p->lock);
10389 p->remotelyblocked = 1;
10390 p->inservice = 0;
10391 ast_mutex_unlock(&p->lock);
10392 break;
10393 case ISUP_EVENT_BLO:
10394 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
10395 if (chanpos < 0) {
10396 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
10397 break;
10398 }
10399 p = linkset->pvts[chanpos];
10400 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
10401 ast_mutex_lock(&p->lock);
10402 p->remotelyblocked = 1;
10403 ast_mutex_unlock(&p->lock);
10404 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
10405 break;
10406 case ISUP_EVENT_BLA:
10407 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
10408 if (chanpos < 0) {
10409 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
10410 break;
10411 }
10412 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
10413 p = linkset->pvts[chanpos];
10414 ast_mutex_lock(&p->lock);
10415 p->locallyblocked = 1;
10416 ast_mutex_unlock(&p->lock);
10417 break;
10418 case ISUP_EVENT_UBL:
10419 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
10420 if (chanpos < 0) {
10421 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
10422 break;
10423 }
10424 p = linkset->pvts[chanpos];
10425 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
10426 ast_mutex_lock(&p->lock);
10427 p->remotelyblocked = 0;
10428 ast_mutex_unlock(&p->lock);
10429 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
10430 break;
10431 case ISUP_EVENT_UBA:
10432 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
10433 if (chanpos < 0) {
10434 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
10435 break;
10436 }
10437 p = linkset->pvts[chanpos];
10438 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
10439 ast_mutex_lock(&p->lock);
10440 p->locallyblocked = 0;
10441 ast_mutex_unlock(&p->lock);
10442 break;
10443 case ISUP_EVENT_CON:
10444 case ISUP_EVENT_ANM:
10445 if (e->e == ISUP_EVENT_CON)
10446 cic = e->con.cic;
10447 else
10448 cic = e->anm.cic;
10449
10450 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
10451 if (chanpos < 0) {
10452 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
10453 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
10454 break;
10455 } else {
10456 p = linkset->pvts[chanpos];
10457 ast_mutex_lock(&p->lock);
10458 p->subs[SUB_REAL].needanswer = 1;
10459 if (p->dsp && p->dsp_features) {
10460 ast_dsp_set_features(p->dsp, p->dsp_features);
10461 p->dsp_features = 0;
10462 }
10463 dahdi_enable_ec(p);
10464 ast_mutex_unlock(&p->lock);
10465 }
10466 break;
10467 case ISUP_EVENT_RLC:
10468 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
10469 if (chanpos < 0) {
10470 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
10471 break;
10472 } else {
10473 p = linkset->pvts[chanpos];
10474 ast_mutex_lock(&p->lock);
10475 if (p->alreadyhungup)
10476 p->ss7call = NULL;
10477 else
10478 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
10479 ast_mutex_unlock(&p->lock);
10480 }
10481 break;
10482 case ISUP_EVENT_FAA:
10483 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
10484 if (chanpos < 0) {
10485 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
10486 break;
10487 } else {
10488 p = linkset->pvts[chanpos];
10489 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
10490 ast_mutex_lock(&p->lock);
10491 if (p->alreadyhungup){
10492 p->ss7call = NULL;
10493 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
10494 }
10495 ast_mutex_unlock(&p->lock);
10496 }
10497 break;
10498 default:
10499 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
10500 break;
10501 }
10502 }
10503 ast_mutex_unlock(&linkset->lock);
10504 }
10505
10506 return 0;
10507 }
10508
10509 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
10510 {
10511 #if 0
10512 int i;
10513
10514 for (i = 0; i < NUM_SPANS; i++)
10515 if (linksets[i].ss7 == ss7)
10516 break;
10517
10518 ast_verbose("[%d] %s", i+1, s);
10519 #else
10520 ast_verbose("%s", s);
10521 #endif
10522 }
10523
10524 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
10525 {
10526 #if 0
10527 int i;
10528
10529 for (i = 0; i < NUM_SPANS; i++)
10530 if (linksets[i].ss7 == ss7)
10531 break;
10532
10533 #else
10534 ast_log(LOG_ERROR, "%s", s);
10535 #endif
10536 }
10537
10538 #endif
10539
10540 #ifdef HAVE_PRI
10541 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10542 {
10543 struct dahdi_pvt *p;
10544 p = pri->crvs;
10545 while (p) {
10546 if (p->channel == crv)
10547 return p;
10548 p = p->next;
10549 }
10550 return NULL;
10551 }
10552
10553
10554 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10555 {
10556 int x;
10557 int span = PRI_SPAN(channel);
10558 int spanfd;
10559 struct dahdi_params param;
10560 int principle = -1;
10561 int explicit = PRI_EXPLICIT(channel);
10562 channel = PRI_CHANNEL(channel);
10563
10564 if (!explicit) {
10565 spanfd = pri_active_dchan_fd(pri);
10566 memset(¶m, 0, sizeof(param));
10567 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
10568 return -1;
10569 span = pris[param.spanno - 1].prilogicalspan;
10570 }
10571
10572 for (x = 0; x < pri->numchans; x++) {
10573 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10574 principle = x;
10575 break;
10576 }
10577 }
10578
10579 return principle;
10580 }
10581
10582 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10583 {
10584 int x;
10585 struct dahdi_pvt *crv;
10586 if (!c) {
10587 if (principle < 0)
10588 return -1;
10589 return principle;
10590 }
10591 if ((principle > -1) &&
10592 (principle < pri->numchans) &&
10593 (pri->pvts[principle]) &&
10594 (pri->pvts[principle]->call == c))
10595 return principle;
10596
10597 for (x = 0; x < pri->numchans; x++) {
10598 if (!pri->pvts[x])
10599 continue;
10600 if (pri->pvts[x]->call == c) {
10601
10602 if (principle != x) {
10603 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10604
10605 ast_verb(3, "Moving call from channel %d to channel %d\n",
10606 old->channel, new->channel);
10607 if (new->owner) {
10608 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10609 old->channel, new->channel, new->channel);
10610 return -1;
10611 }
10612
10613 new->owner = old->owner;
10614 old->owner = NULL;
10615 if (new->owner) {
10616 ast_string_field_build(new->owner, name,
10617 "DAHDI/%d:%d-%d", pri->trunkgroup,
10618 new->channel, 1);
10619 new->owner->tech_pvt = new;
10620 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10621 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10622 old->subs[SUB_REAL].owner = NULL;
10623 } else
10624 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);
10625 new->call = old->call;
10626 old->call = NULL;
10627
10628
10629 new->dsp = old->dsp;
10630 new->dsp_features = old->dsp_features;
10631 old->dsp = NULL;
10632 old->dsp_features = 0;
10633 }
10634 return principle;
10635 }
10636 }
10637
10638 crv = pri->crvs;
10639 while (crv) {
10640 if (crv->call == c) {
10641
10642 if (crv->bearer)
10643 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10644 else if (pri->pvts[principle]->owner)
10645 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10646 else {
10647
10648
10649 dahdi_close_sub(crv, SUB_REAL);
10650 pri->pvts[principle]->call = crv->call;
10651 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10652 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10653 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10654 pri->trunkgroup, crv->channel);
10655 wakeup_sub(crv, SUB_REAL, pri);
10656 }
10657 return principle;
10658 }
10659 crv = crv->next;
10660 }
10661 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10662 return -1;
10663 }
10664
10665 static void *do_idle_thread(void *vchan)
10666 {
10667 struct ast_channel *chan = vchan;
10668 struct dahdi_pvt *pvt = chan->tech_pvt;
10669 struct ast_frame *f;
10670 char ex[80];
10671
10672 int newms, ms = 30000;
10673 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10674 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10675 if (ast_call(chan, ex, 0)) {
10676 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10677 ast_hangup(chan);
10678 return NULL;
10679 }
10680 while ((newms = ast_waitfor(chan, ms)) > 0) {
10681 f = ast_read(chan);
10682 if (!f) {
10683
10684 break;
10685 }
10686 if (f->frametype == AST_FRAME_CONTROL) {
10687 switch (f->subclass) {
10688 case AST_CONTROL_ANSWER:
10689
10690 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10691 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10692 chan->priority = 1;
10693 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10694 ast_pbx_run(chan);
10695
10696 return NULL;
10697 case AST_CONTROL_BUSY:
10698 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10699 break;
10700 case AST_CONTROL_CONGESTION:
10701 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10702 break;
10703 };
10704 }
10705 ast_frfree(f);
10706 ms = newms;
10707 }
10708
10709 ast_hangup(chan);
10710 return NULL;
10711 }
10712
10713 #ifndef PRI_RESTART
10714 #error "Upgrade your libpri"
10715 #endif
10716 static void dahdi_pri_message(struct pri *pri, char *s)
10717 {
10718 int x, y;
10719 int dchan = -1, span = -1;
10720 int dchancount = 0;
10721
10722 if (pri) {
10723 for (x = 0; x < NUM_SPANS; x++) {
10724 for (y = 0; y < NUM_DCHANS; y++) {
10725 if (pris[x].dchans[y])
10726 dchancount++;
10727
10728 if (pris[x].dchans[y] == pri)
10729 dchan = y;
10730 }
10731 if (dchan >= 0) {
10732 span = x;
10733 break;
10734 }
10735 dchancount = 0;
10736 }
10737 if (dchancount > 1 && (span > -1))
10738 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10739 else
10740 ast_verbose("%s", s);
10741 } else
10742 ast_verbose("%s", s);
10743
10744 ast_mutex_lock(&pridebugfdlock);
10745
10746 if (pridebugfd >= 0) {
10747 if (write(pridebugfd, s, strlen(s)) < 0) {
10748 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10749 }
10750 }
10751
10752 ast_mutex_unlock(&pridebugfdlock);
10753 }
10754
10755 static void dahdi_pri_error(struct pri *pri, char *s)
10756 {
10757 int x, y;
10758 int dchan = -1, span = -1;
10759 int dchancount = 0;
10760
10761 if (pri) {
10762 for (x = 0; x < NUM_SPANS; x++) {
10763 for (y = 0; y < NUM_DCHANS; y++) {
10764 if (pris[x].dchans[y])
10765 dchancount++;
10766
10767 if (pris[x].dchans[y] == pri)
10768 dchan = y;
10769 }
10770 if (dchan >= 0) {
10771 span = x;
10772 break;
10773 }
10774 dchancount = 0;
10775 }
10776 if ((dchancount > 1) && (span > -1))
10777 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10778 else
10779 ast_log(LOG_ERROR, "%s", s);
10780 } else
10781 ast_log(LOG_ERROR, "%s", s);
10782
10783 ast_mutex_lock(&pridebugfdlock);
10784
10785 if (pridebugfd >= 0) {
10786 if (write(pridebugfd, s, strlen(s)) < 0) {
10787 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10788 }
10789 }
10790
10791 ast_mutex_unlock(&pridebugfdlock);
10792 }
10793
10794 static int pri_check_restart(struct dahdi_pri *pri)
10795 {
10796 do {
10797 pri->resetpos++;
10798 } while ((pri->resetpos < pri->numchans) &&
10799 (!pri->pvts[pri->resetpos] ||
10800 pri->pvts[pri->resetpos]->call ||
10801 pri->pvts[pri->resetpos]->resetting));
10802 if (pri->resetpos < pri->numchans) {
10803
10804 pri->pvts[pri->resetpos]->resetting = 1;
10805 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10806 } else {
10807 pri->resetting = 0;
10808 time(&pri->lastreset);
10809 }
10810 return 0;
10811 }
10812
10813 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10814 {
10815 int x;
10816 int redo;
10817 ast_mutex_unlock(&pri->lock);
10818 ast_mutex_lock(&p->lock);
10819 do {
10820 redo = 0;
10821 for (x = 0; x < 3; x++) {
10822 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10823 redo++;
10824 DEADLOCK_AVOIDANCE(&p->lock);
10825 }
10826 if (p->subs[x].owner) {
10827 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10828 ast_channel_unlock(p->subs[x].owner);
10829 }
10830 }
10831 } while (redo);
10832 ast_mutex_unlock(&p->lock);
10833 ast_mutex_lock(&pri->lock);
10834 return 0;
10835 }
10836
10837 static char * redirectingreason2str(int redirectingreason)
10838 {
10839 switch (redirectingreason) {
10840 case 0:
10841 return "UNKNOWN";
10842 case 1:
10843 return "BUSY";
10844 case 2:
10845 return "NO_REPLY";
10846 case 0xF:
10847 return "UNCONDITIONAL";
10848 default:
10849 return "NOREDIRECT";
10850 }
10851 }
10852
10853 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10854 {
10855 if (pri->dialplan == -2) {
10856 snprintf(buf, size, "%s", number);
10857 return;
10858 }
10859 if (ast_strlen_zero(number)) {
10860 if (size) {
10861 *buf = '\0';
10862 }
10863 return;
10864 }
10865 switch (plan) {
10866 case PRI_INTERNATIONAL_ISDN:
10867 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10868 break;
10869 case PRI_NATIONAL_ISDN:
10870 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10871 break;
10872 case PRI_LOCAL_ISDN:
10873 snprintf(buf, size, "%s%s", pri->localprefix, number);
10874 break;
10875 case PRI_PRIVATE:
10876 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10877 break;
10878 case PRI_UNKNOWN:
10879 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10880 break;
10881 default:
10882 snprintf(buf, size, "%s", number);
10883 break;
10884 }
10885 }
10886
10887
10888 static void *pri_dchannel(void *vpri)
10889 {
10890 struct dahdi_pri *pri = vpri;
10891 pri_event *e;
10892 struct pollfd fds[NUM_DCHANS];
10893 int res;
10894 int chanpos = 0;
10895 int x;
10896 int haveidles;
10897 int activeidles;
10898 int nextidle = -1;
10899 struct ast_channel *c;
10900 struct timeval tv, lowest, *next;
10901 struct timeval lastidle = ast_tvnow();
10902 int doidling=0;
10903 char *cc;
10904 char idlen[80];
10905 struct ast_channel *idle;
10906 pthread_t p;
10907 time_t t;
10908 int i, which=-1;
10909 int numdchans;
10910 int cause=0;
10911 struct dahdi_pvt *crv;
10912 pthread_t threadid;
10913 char ani2str[6];
10914 char plancallingnum[256];
10915 char plancallingani[256];
10916 char calledtonstr[10];
10917
10918 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10919
10920 gettimeofday(&lastidle, NULL);
10921 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10922
10923 cc = strchr(pri->idleext, '@');
10924 if (cc) {
10925 *cc = '\0';
10926 cc++;
10927 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10928 #if 0
10929
10930 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10931 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10932 else
10933 #endif
10934 doidling = 1;
10935 } else
10936 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10937 }
10938 for (;;) {
10939 for (i = 0; i < NUM_DCHANS; i++) {
10940 if (!pri->dchannels[i])
10941 break;
10942 fds[i].fd = pri->fds[i];
10943 fds[i].events = POLLIN | POLLPRI;
10944 fds[i].revents = 0;
10945 }
10946 numdchans = i;
10947 time(&t);
10948 ast_mutex_lock(&pri->lock);
10949 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10950 if (pri->resetting && pri_is_up(pri)) {
10951 if (pri->resetpos < 0)
10952 pri_check_restart(pri);
10953 } else {
10954 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10955 pri->resetting = 1;
10956 pri->resetpos = -1;
10957 }
10958 }
10959 }
10960
10961 if (doidling && pri_is_up(pri)) {
10962 nextidle = -1;
10963 haveidles = 0;
10964 activeidles = 0;
10965 for (x = pri->numchans; x >= 0; x--) {
10966 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10967 !pri->pvts[x]->call) {
10968 if (haveidles < pri->minunused) {
10969 haveidles++;
10970 } else if (!pri->pvts[x]->resetting) {
10971 nextidle = x;
10972 break;
10973 }
10974 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10975 activeidles++;
10976 }
10977 if (nextidle > -1) {
10978 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10979
10980 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10981 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
10982 if (idle) {
10983 pri->pvts[nextidle]->isidlecall = 1;
10984 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10985 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10986 dahdi_hangup(idle);
10987 }
10988 } else
10989 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10990 lastidle = ast_tvnow();
10991 }
10992 } else if ((haveidles < pri->minunused) &&
10993 (activeidles > pri->minidle)) {
10994
10995
10996 for (x = pri->numchans; x >= 0; x--) {
10997
10998 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10999 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11000 haveidles++;
11001
11002
11003 if ((haveidles >= pri->minunused) ||
11004 (activeidles <= pri->minidle))
11005 break;
11006 }
11007 }
11008 }
11009 }
11010
11011 lowest = ast_tv(60, 0);
11012 for (i = 0; i < NUM_DCHANS; i++) {
11013
11014 if (!pri->dchannels[i])
11015 break;
11016 if ((next = pri_schedule_next(pri->dchans[i]))) {
11017
11018 tv = ast_tvsub(*next, ast_tvnow());
11019 if (tv.tv_sec < 0) {
11020 tv = ast_tv(0,0);
11021 }
11022 if (doidling || pri->resetting) {
11023 if (tv.tv_sec > 1) {
11024 tv = ast_tv(1, 0);
11025 }
11026 } else {
11027 if (tv.tv_sec > 60) {
11028 tv = ast_tv(60, 0);
11029 }
11030 }
11031 } else if (doidling || pri->resetting) {
11032
11033
11034 tv = ast_tv(1,0);
11035 } else {
11036
11037 tv = ast_tv(60, 0);
11038 }
11039 if (!i || ast_tvcmp(tv, lowest) < 0) {
11040 lowest = tv;
11041 }
11042 }
11043 ast_mutex_unlock(&pri->lock);
11044
11045 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11046 pthread_testcancel();
11047 e = NULL;
11048 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11049 pthread_testcancel();
11050 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11051
11052 ast_mutex_lock(&pri->lock);
11053 if (!res) {
11054 for (which = 0; which < NUM_DCHANS; which++) {
11055 if (!pri->dchans[which])
11056 break;
11057
11058 e = pri_schedule_run(pri->dchans[which]);
11059 if (e)
11060 break;
11061 }
11062 } else if (res > -1) {
11063 for (which = 0; which < NUM_DCHANS; which++) {
11064 if (!pri->dchans[which])
11065 break;
11066 if (fds[which].revents & POLLPRI) {
11067
11068 x = 0;
11069 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11070 if (x) {
11071 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);
11072 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
11073 "PRIEvent: %s\r\n"
11074 "PRIEventCode: %d\r\n"
11075 "D-channel: %s\r\n"
11076 "Span: %d\r\n",
11077 event2str(x),
11078 x,
11079 pri_order(which),
11080 pri->span
11081 );
11082 }
11083
11084 if (x == DAHDI_EVENT_ALARM) {
11085 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11086 pri_find_dchan(pri);
11087 } else if (x == DAHDI_EVENT_NOALARM) {
11088 pri->dchanavail[which] |= DCHAN_NOTINALARM;
11089 pri_restart(pri->dchans[which]);
11090 }
11091
11092 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11093 } else if (fds[which].revents & POLLIN) {
11094 e = pri_check_event(pri->dchans[which]);
11095 }
11096 if (e)
11097 break;
11098 }
11099 } else if (errno != EINTR)
11100 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11101
11102 if (e) {
11103 if (pri->debug)
11104 pri_dump_event(pri->dchans[which], e);
11105
11106 if (e->e != PRI_EVENT_DCHAN_DOWN) {
11107 if (!(pri->dchanavail[which] & DCHAN_UP)) {
11108 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11109 }
11110 pri->dchanavail[which] |= DCHAN_UP;
11111 } else if (pri->sig != SIG_BRI_PTMP) {
11112 if (pri->dchanavail[which] & DCHAN_UP) {
11113 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11114 }
11115 pri->dchanavail[which] &= ~DCHAN_UP;
11116 }
11117
11118 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11119
11120 pri->pri = pri->dchans[which];
11121
11122 switch (e->e) {
11123 case PRI_EVENT_DCHAN_UP:
11124 if (!pri->pri) pri_find_dchan(pri);
11125
11126
11127 time(&pri->lastreset);
11128
11129
11130 if (pri->resetinterval > -1) {
11131 pri->lastreset -= pri->resetinterval;
11132 pri->lastreset += 5;
11133 }
11134 pri->resetting = 0;
11135
11136 for (i = 0; i < pri->numchans; i++)
11137 if (pri->pvts[i]) {
11138 pri->pvts[i]->inalarm = 0;
11139 }
11140 break;
11141 case PRI_EVENT_DCHAN_DOWN:
11142 pri_find_dchan(pri);
11143 if (!pri_is_up(pri)) {
11144 pri->resetting = 0;
11145
11146 for (i = 0; i < pri->numchans; i++) {
11147 struct dahdi_pvt *p = pri->pvts[i];
11148 if (p) {
11149 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11150
11151 if (p->call) {
11152 if (p->pri && p->pri->pri) {
11153 pri_hangup(p->pri->pri, p->call, -1);
11154 pri_destroycall(p->pri->pri, p->call);
11155 p->call = NULL;
11156 } else
11157 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
11158 }
11159 if (p->realcall) {
11160 pri_hangup_all(p->realcall, pri);
11161 } else if (p->owner)
11162 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11163 }
11164 p->inalarm = 1;
11165 }
11166 }
11167 }
11168 break;
11169 case PRI_EVENT_RESTART:
11170 if (e->restart.channel > -1) {
11171 chanpos = pri_find_principle(pri, e->restart.channel);
11172 if (chanpos < 0)
11173 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
11174 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11175 else {
11176 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
11177 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11178 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11179 if (pri->pvts[chanpos]->call) {
11180 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11181 pri->pvts[chanpos]->call = NULL;
11182 }
11183
11184 if (pri->pvts[chanpos]->realcall)
11185 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11186 else if (pri->pvts[chanpos]->owner)
11187 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11188 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11189 }
11190 } else {
11191 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
11192 for (x = 0; x < pri->numchans; x++)
11193 if (pri->pvts[x]) {
11194 ast_mutex_lock(&pri->pvts[x]->lock);
11195 if (pri->pvts[x]->call) {
11196 pri_destroycall(pri->pri, pri->pvts[x]->call);
11197 pri->pvts[x]->call = NULL;
11198 }
11199 if (pri->pvts[x]->realcall)
11200 pri_hangup_all(pri->pvts[x]->realcall, pri);
11201 else if (pri->pvts[x]->owner)
11202 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11203 ast_mutex_unlock(&pri->pvts[x]->lock);
11204 }
11205 }
11206 break;
11207 case PRI_EVENT_KEYPAD_DIGIT:
11208 chanpos = pri_find_principle(pri, e->digit.channel);
11209 if (chanpos < 0) {
11210 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
11211 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
11212 } else {
11213 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
11214 if (chanpos > -1) {
11215 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11216
11217 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
11218
11219 int digitlen = strlen(e->digit.digits);
11220 char digit;
11221 int i;
11222 for (i = 0; i < digitlen; i++) {
11223 digit = e->digit.digits[i];
11224 {
11225 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11226 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11227 }
11228 }
11229 }
11230 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11231 }
11232 }
11233 break;
11234
11235 case PRI_EVENT_INFO_RECEIVED:
11236 chanpos = pri_find_principle(pri, e->ring.channel);
11237 if (chanpos < 0) {
11238 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
11239 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11240 } else {
11241 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
11242 if (chanpos > -1) {
11243 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11244
11245 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
11246
11247 int digitlen = strlen(e->ring.callednum);
11248 char digit;
11249 int i;
11250 for (i = 0; i < digitlen; i++) {
11251 digit = e->ring.callednum[i];
11252 {
11253 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11254 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11255 }
11256 }
11257 }
11258 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11259 }
11260 }
11261 break;
11262 case PRI_EVENT_RING:
11263 crv = NULL;
11264 if (e->ring.channel == -1)
11265 chanpos = pri_find_empty_chan(pri, 1);
11266 else
11267 chanpos = pri_find_principle(pri, e->ring.channel);
11268
11269 if (chanpos < 0) {
11270 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
11271 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11272 } else {
11273 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11274 if (pri->pvts[chanpos]->owner) {
11275 if (pri->pvts[chanpos]->call == e->ring.call) {
11276 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
11277 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11278 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11279 break;
11280 } else {
11281
11282 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
11283 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11284 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11285 chanpos = -1;
11286 }
11287 }
11288 if (chanpos > -1)
11289 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11290 }
11291 if ((chanpos < 0) && (e->ring.flexible))
11292 chanpos = pri_find_empty_chan(pri, 1);
11293 if (chanpos > -1) {
11294 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11295 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11296
11297 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11298 if (crv)
11299 ast_mutex_lock(&crv->lock);
11300 if (!crv || crv->owner) {
11301 pri->pvts[chanpos]->call = NULL;
11302 if (crv) {
11303 if (crv->owner)
11304 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11305 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);
11306 } else
11307 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);
11308 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11309 if (crv)
11310 ast_mutex_unlock(&crv->lock);
11311 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11312 break;
11313 }
11314 }
11315 pri->pvts[chanpos]->call = e->ring.call;
11316 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11317 if (pri->pvts[chanpos]->use_callerid) {
11318 ast_shrink_phone_number(plancallingnum);
11319 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11320 #ifdef PRI_ANI
11321 if (!ast_strlen_zero(e->ring.callingani)) {
11322 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11323 ast_shrink_phone_number(plancallingani);
11324 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11325 } else {
11326 pri->pvts[chanpos]->cid_ani[0] = '\0';
11327 }
11328 #endif
11329 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11330 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
11331 } else {
11332 pri->pvts[chanpos]->cid_num[0] = '\0';
11333 pri->pvts[chanpos]->cid_ani[0] = '\0';
11334 pri->pvts[chanpos]->cid_name[0] = '\0';
11335 pri->pvts[chanpos]->cid_ton = 0;
11336 }
11337 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11338 e->ring.redirectingnum, e->ring.callingplanrdnis);
11339
11340 if (pri->pvts[chanpos]->immediate) {
11341 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
11342 pri->pvts[chanpos]->exten[0] = 's';
11343 pri->pvts[chanpos]->exten[1] = '\0';
11344 }
11345
11346 else if (!ast_strlen_zero(e->ring.callednum)) {
11347 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11348 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11349 } else if (pri->overlapdial)
11350 pri->pvts[chanpos]->exten[0] = '\0';
11351 else {
11352
11353 pri->pvts[chanpos]->exten[0] = 's';
11354 pri->pvts[chanpos]->exten[1] = '\0';
11355 }
11356
11357 if (!ast_strlen_zero(e->ring.callednum))
11358 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11359
11360 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11361 ast_verb(3, "Going to extension s|1 because of Complete received\n");
11362 pri->pvts[chanpos]->exten[0] = 's';
11363 pri->pvts[chanpos]->exten[1] = '\0';
11364 }
11365
11366
11367 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11368 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11369
11370 int law;
11371 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11372
11373 law = 1;
11374 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11375 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11376 }
11377 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11378 law = DAHDI_LAW_ALAW;
11379 else
11380 law = DAHDI_LAW_MULAW;
11381 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11382 if (res < 0)
11383 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11384 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11385 if (res < 0)
11386 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11387 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11388
11389 pri->pvts[chanpos]->proceeding = 1;
11390 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11391 } else {
11392 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
11393 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11394 else
11395 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11396 }
11397
11398 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11399
11400
11401 if (!e->ring.complete
11402 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11403 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11404
11405
11406
11407
11408 ast_mutex_unlock(&pri->lock);
11409 if (crv) {
11410
11411 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11412 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11413 pri->pvts[chanpos]->owner = &inuse;
11414 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11415 } else {
11416 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11417 }
11418 ast_mutex_lock(&pri->lock);
11419 if (c) {
11420 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11421 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11422 }
11423 if (e->ring.ani2 >= 0) {
11424 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11425 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11426 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11427 }
11428
11429 #ifdef SUPPORT_USERUSER
11430 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11431 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11432 }
11433 #endif
11434
11435 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11436 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11437 if (e->ring.redirectingreason >= 0)
11438 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11439 }
11440 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
11441 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11442 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11443 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11444 } else {
11445 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11446 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11447 if (c)
11448 ast_hangup(c);
11449 else {
11450 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11451 pri->pvts[chanpos]->call = NULL;
11452 }
11453 }
11454 } else {
11455
11456
11457
11458
11459 ast_mutex_unlock(&pri->lock);
11460 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
11461 ast_mutex_lock(&pri->lock);
11462 if (c) {
11463
11464
11465
11466
11467
11468
11469
11470
11471 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11472 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11473 }
11474 if (e->ring.ani2 >= 0) {
11475 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11476 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11477 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11478 }
11479
11480 #ifdef SUPPORT_USERUSER
11481 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11482 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11483 }
11484 #endif
11485
11486 if (e->ring.redirectingreason >= 0)
11487 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11488
11489 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11490 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11491 }
11492 if (c && !ast_pbx_start(c)) {
11493 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11494 plancallingnum, pri->pvts[chanpos]->exten,
11495 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11496
11497 dahdi_enable_ec(pri->pvts[chanpos]);
11498 } else {
11499 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11500 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11501 if (c) {
11502 ast_hangup(c);
11503 } else {
11504 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11505 pri->pvts[chanpos]->call = NULL;
11506 }
11507 }
11508 }
11509 } else {
11510 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
11511 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
11512 pri->pvts[chanpos]->prioffset, pri->span);
11513 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11514 pri->pvts[chanpos]->call = NULL;
11515 pri->pvts[chanpos]->exten[0] = '\0';
11516 }
11517 if (crv)
11518 ast_mutex_unlock(&crv->lock);
11519 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11520 } else {
11521 if (e->ring.flexible)
11522 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11523 else
11524 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11525 }
11526 break;
11527 case PRI_EVENT_RINGING:
11528 chanpos = pri_find_principle(pri, e->ringing.channel);
11529 if (chanpos < 0) {
11530 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
11531 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11532 } else {
11533 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
11534 if (chanpos < 0) {
11535 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
11536 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11537 } else {
11538 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11539 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11540 dahdi_enable_ec(pri->pvts[chanpos]);
11541 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11542 pri->pvts[chanpos]->alerting = 1;
11543 } else
11544 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11545
11546 #ifdef PRI_PROGRESS_MASK
11547 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11548 #else
11549 if (e->ringing.progress == 8) {
11550 #endif
11551
11552 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11553
11554 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11555 pri->pvts[chanpos]->dsp_features = 0;
11556 }
11557 }
11558
11559 #ifdef SUPPORT_USERUSER
11560 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11561 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11562 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11563 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11564 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11565 }
11566 #endif
11567
11568 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11569 }
11570 }
11571 break;
11572 case PRI_EVENT_PROGRESS:
11573
11574 chanpos = pri_find_principle(pri, e->proceeding.channel);
11575 if (chanpos > -1) {
11576 #ifdef PRI_PROGRESS_MASK
11577 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11578 #else
11579 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11580 #endif
11581 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11582
11583 if (e->proceeding.cause > -1) {
11584 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11585
11586
11587 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11588 if (pri->pvts[chanpos]->owner) {
11589 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11590
11591 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11592 f.subclass = AST_CONTROL_BUSY;
11593 }
11594 }
11595 }
11596
11597 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11598 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11599 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11600 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11601 #ifdef PRI_PROGRESS_MASK
11602 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11603 #else
11604 if (e->proceeding.progress == 8) {
11605 #endif
11606
11607 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11608 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11609 pri->pvts[chanpos]->dsp_features = 0;
11610 }
11611
11612 f.subclass = AST_CONTROL_PROGRESS;
11613 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11614 }
11615 pri->pvts[chanpos]->progress = 1;
11616 pri->pvts[chanpos]->dialing = 0;
11617 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11618 }
11619 }
11620 break;
11621 case PRI_EVENT_PROCEEDING:
11622 chanpos = pri_find_principle(pri, e->proceeding.channel);
11623 if (chanpos > -1) {
11624 if (!pri->pvts[chanpos]->proceeding) {
11625 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11626
11627 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11628 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11629 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11630 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11631 #ifdef PRI_PROGRESS_MASK
11632 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11633 #else
11634 if (e->proceeding.progress == 8) {
11635 #endif
11636
11637 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11638 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11639 pri->pvts[chanpos]->dsp_features = 0;
11640 }
11641
11642 f.subclass = AST_CONTROL_PROGRESS;
11643 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11644 }
11645 pri->pvts[chanpos]->proceeding = 1;
11646 pri->pvts[chanpos]->dialing = 0;
11647 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11648 }
11649 }
11650 break;
11651 case PRI_EVENT_FACNAME:
11652 chanpos = pri_find_principle(pri, e->facname.channel);
11653 if (chanpos < 0) {
11654 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11655 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11656 } else {
11657 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11658 if (chanpos < 0) {
11659 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
11660 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11661 } else {
11662
11663 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11664 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11665 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11666 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11667 dahdi_enable_ec(pri->pvts[chanpos]);
11668 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11669 }
11670 }
11671 break;
11672 case PRI_EVENT_ANSWER:
11673 chanpos = pri_find_principle(pri, e->answer.channel);
11674 if (chanpos < 0) {
11675 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
11676 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11677 } else {
11678 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11679 if (chanpos < 0) {
11680 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
11681 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11682 } else {
11683 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11684
11685
11686
11687
11688
11689 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11690 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11691 pri->pvts[chanpos]->dsp_features = 0;
11692 }
11693 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11694 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11695 x = DAHDI_START;
11696 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11697 if (res < 0) {
11698 if (errno != EINPROGRESS) {
11699 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11700 }
11701 }
11702 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11703 pri->pvts[chanpos]->dialing = 1;
11704
11705 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11706 if (res < 0) {
11707 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11708 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11709 } else
11710 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11711
11712 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11713 } else if (pri->pvts[chanpos]->confirmanswer) {
11714 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11715 } else {
11716 pri->pvts[chanpos]->dialing = 0;
11717 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11718
11719 dahdi_enable_ec(pri->pvts[chanpos]);
11720 }
11721
11722 #ifdef SUPPORT_USERUSER
11723 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11724 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11725 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11726 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11727 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11728 }
11729 #endif
11730
11731 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11732 }
11733 }
11734 break;
11735 case PRI_EVENT_HANGUP:
11736 chanpos = pri_find_principle(pri, e->hangup.channel);
11737 if (chanpos < 0) {
11738 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
11739 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11740 } else {
11741 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11742 if (chanpos > -1) {
11743 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11744 if (!pri->pvts[chanpos]->alreadyhungup) {
11745
11746 pri->pvts[chanpos]->alreadyhungup = 1;
11747 if (pri->pvts[chanpos]->realcall)
11748 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11749 else if (pri->pvts[chanpos]->owner) {
11750
11751 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11752 switch (pri->pvts[chanpos]->owner->_state) {
11753 case AST_STATE_BUSY:
11754 case AST_STATE_UP:
11755 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11756 break;
11757 default:
11758 switch (e->hangup.cause) {
11759 case PRI_CAUSE_USER_BUSY:
11760 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11761 break;
11762 case PRI_CAUSE_CALL_REJECTED:
11763 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11764 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11765 case PRI_CAUSE_SWITCH_CONGESTION:
11766 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11767 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11768 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11769 break;
11770 default:
11771 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11772 }
11773 break;
11774 }
11775 }
11776 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11777 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11778 } else {
11779 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11780 pri->pvts[chanpos]->call = NULL;
11781 }
11782 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11783 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11784 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11785 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11786 pri->pvts[chanpos]->resetting = 1;
11787 }
11788 if (e->hangup.aoc_units > -1)
11789 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11790 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11791
11792 #ifdef SUPPORT_USERUSER
11793 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11794 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11795 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11796 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11797 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11798 }
11799 #endif
11800
11801 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11802 } else {
11803 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
11804 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11805 }
11806 }
11807 break;
11808 #ifndef PRI_EVENT_HANGUP_REQ
11809 #error please update libpri
11810 #endif
11811 case PRI_EVENT_HANGUP_REQ:
11812 chanpos = pri_find_principle(pri, e->hangup.channel);
11813 if (chanpos < 0) {
11814 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11815 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11816 } else {
11817 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11818 if (chanpos > -1) {
11819 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11820 if (pri->pvts[chanpos]->realcall)
11821 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11822 else if (pri->pvts[chanpos]->owner) {
11823 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11824 switch (pri->pvts[chanpos]->owner->_state) {
11825 case AST_STATE_BUSY:
11826 case AST_STATE_UP:
11827 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11828 break;
11829 default:
11830 switch (e->hangup.cause) {
11831 case PRI_CAUSE_USER_BUSY:
11832 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11833 break;
11834 case PRI_CAUSE_CALL_REJECTED:
11835 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11836 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11837 case PRI_CAUSE_SWITCH_CONGESTION:
11838 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11839 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11840 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11841 break;
11842 default:
11843 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11844 }
11845 break;
11846 }
11847 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);
11848 if (e->hangup.aoc_units > -1)
11849 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11850 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11851 } else {
11852 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11853 pri->pvts[chanpos]->call = NULL;
11854 }
11855 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11856 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11857 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11858 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11859 pri->pvts[chanpos]->resetting = 1;
11860 }
11861
11862 #ifdef SUPPORT_USERUSER
11863 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11864 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11865 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11866 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11867 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11868 }
11869 #endif
11870
11871 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11872 } else {
11873 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);
11874 }
11875 }
11876 break;
11877 case PRI_EVENT_HANGUP_ACK:
11878 chanpos = pri_find_principle(pri, e->hangup.channel);
11879 if (chanpos < 0) {
11880 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11881 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11882 } else {
11883 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11884 if (chanpos > -1) {
11885 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11886 pri->pvts[chanpos]->call = NULL;
11887 pri->pvts[chanpos]->resetting = 0;
11888 if (pri->pvts[chanpos]->owner) {
11889 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11890 }
11891
11892 #ifdef SUPPORT_USERUSER
11893 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11894 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11895 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11896 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11897 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11898 }
11899 #endif
11900
11901 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11902 }
11903 }
11904 break;
11905 case PRI_EVENT_CONFIG_ERR:
11906 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11907 break;
11908 case PRI_EVENT_RESTART_ACK:
11909 chanpos = pri_find_principle(pri, e->restartack.channel);
11910 if (chanpos < 0) {
11911
11912
11913
11914 for (x = 0; x < pri->numchans; x++) {
11915 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11916 chanpos = x;
11917 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11918 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11919 pri->pvts[chanpos]->prioffset, pri->span);
11920 if (pri->pvts[chanpos]->realcall)
11921 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11922 else if (pri->pvts[chanpos]->owner) {
11923 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11924 pri->pvts[chanpos]->prioffset, pri->span);
11925 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11926 }
11927 pri->pvts[chanpos]->resetting = 0;
11928 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11929 pri->pvts[chanpos]->prioffset, pri->span);
11930 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11931 if (pri->resetting)
11932 pri_check_restart(pri);
11933 break;
11934 }
11935 }
11936 if (chanpos < 0) {
11937 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11938 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11939 }
11940 } else {
11941 if (pri->pvts[chanpos]) {
11942 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11943 if (pri->pvts[chanpos]->realcall)
11944 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11945 else if (pri->pvts[chanpos]->owner) {
11946 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11947 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11948 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11949 }
11950 pri->pvts[chanpos]->resetting = 0;
11951 pri->pvts[chanpos]->inservice = 1;
11952 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11953 pri->pvts[chanpos]->prioffset, pri->span);
11954 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11955 if (pri->resetting)
11956 pri_check_restart(pri);
11957 }
11958 }
11959 break;
11960 case PRI_EVENT_SETUP_ACK:
11961 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11962 if (chanpos < 0) {
11963 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11964 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11965 } else {
11966 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11967 if (chanpos > -1) {
11968 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11969 pri->pvts[chanpos]->setup_ack = 1;
11970
11971 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11972 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11973 pri_information(pri->pri, pri->pvts[chanpos]->call,
11974 pri->pvts[chanpos]->dialdest[x]);
11975 }
11976 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11977 } else
11978 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11979 }
11980 break;
11981 case PRI_EVENT_NOTIFY:
11982 chanpos = pri_find_principle(pri, e->notify.channel);
11983 if (chanpos < 0) {
11984 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11985 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11986 } else {
11987 struct ast_frame f = { AST_FRAME_CONTROL, };
11988 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11989 switch (e->notify.info) {
11990 case PRI_NOTIFY_REMOTE_HOLD:
11991 f.subclass = AST_CONTROL_HOLD;
11992 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11993 break;
11994 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11995 f.subclass = AST_CONTROL_UNHOLD;
11996 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11997 break;
11998 }
11999 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12000 }
12001 break;
12002 default:
12003 ast_debug(1, "Event: %d\n", e->e);
12004 }
12005 }
12006 ast_mutex_unlock(&pri->lock);
12007 }
12008
12009 return NULL;
12010 }
12011
12012 static int start_pri(struct dahdi_pri *pri)
12013 {
12014 int res, x;
12015 struct dahdi_params p;
12016 struct dahdi_bufferinfo bi;
12017 struct dahdi_spaninfo si;
12018 int i;
12019
12020 for (i = 0; i < NUM_DCHANS; i++) {
12021 if (!pri->dchannels[i])
12022 break;
12023 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
12024 x = pri->dchannels[i];
12025 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
12026 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12027 return -1;
12028 }
12029 memset(&p, 0, sizeof(p));
12030 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12031 if (res) {
12032 dahdi_close_pri_fd(pri, i);
12033 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12034 return -1;
12035 }
12036 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12037 dahdi_close_pri_fd(pri, i);
12038 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
12039 return -1;
12040 }
12041 memset(&si, 0, sizeof(si));
12042 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12043 if (res) {
12044 dahdi_close_pri_fd(pri, i);
12045 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12046 }
12047 if (!si.alarms)
12048 pri->dchanavail[i] |= DCHAN_NOTINALARM;
12049 else
12050 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12051 memset(&bi, 0, sizeof(bi));
12052 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12053 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12054 bi.numbufs = 32;
12055 bi.bufsize = 1024;
12056 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12057 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12058 dahdi_close_pri_fd(pri, i);
12059 return -1;
12060 }
12061 switch (pri->sig) {
12062 case SIG_BRI:
12063 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12064 break;
12065 case SIG_BRI_PTMP:
12066 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12067 break;
12068 default:
12069 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12070 }
12071
12072 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12073 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12074 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12075 #ifdef HAVE_PRI_INBANDDISCONNECT
12076 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12077 #endif
12078
12079 if (i)
12080 pri_enslave(pri->dchans[0], pri->dchans[i]);
12081 if (!pri->dchans[i]) {
12082 dahdi_close_pri_fd(pri, i);
12083 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12084 return -1;
12085 }
12086 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12087 pri_set_nsf(pri->dchans[i], pri->nsf);
12088 #ifdef PRI_GETSET_TIMERS
12089 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12090 if (pritimers[x] != 0)
12091 pri_set_timer(pri->dchans[i], x, pritimers[x]);
12092 }
12093 #endif
12094 }
12095
12096 pri->pri = pri->dchans[0];
12097 pri->resetpos = -1;
12098 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12099 for (i = 0; i < NUM_DCHANS; i++) {
12100 if (!pri->dchannels[i])
12101 break;
12102 dahdi_close_pri_fd(pri, i);
12103 }
12104 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12105 return -1;
12106 }
12107 return 0;
12108 }
12109
12110 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
12111 {
12112 int which, span;
12113 char *ret = NULL;
12114
12115 if (pos != rpos)
12116 return ret;
12117
12118 for (which = span = 0; span < NUM_SPANS; span++) {
12119 if (pris[span].pri && ++which > state) {
12120 if (asprintf(&ret, "%d", span + 1) < 0) {
12121 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12122 }
12123 break;
12124 }
12125 }
12126 return ret;
12127 }
12128
12129 static char *complete_span_4(const char *line, const char *word, int pos, int state)
12130 {
12131 return complete_span_helper(line,word,pos,state,3);
12132 }
12133
12134 static char *complete_span_5(const char *line, const char *word, int pos, int state)
12135 {
12136 return complete_span_helper(line,word,pos,state,4);
12137 }
12138
12139 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12140 {
12141 switch (cmd) {
12142 case CLI_INIT:
12143 e->command = "pri unset debug file";
12144 e->usage = "Usage: pri unset debug file\n"
12145 " Stop sending debug output to the previously \n"
12146 " specified file\n";
12147 return NULL;
12148 case CLI_GENERATE:
12149 return NULL;
12150 }
12151
12152 ast_mutex_lock(&pridebugfdlock);
12153 close(pridebugfd);
12154 pridebugfd = -1;
12155 ast_cli(a->fd, "PRI debug output to file disabled\n");
12156 ast_mutex_unlock(&pridebugfdlock);
12157 return CLI_SUCCESS;
12158 }
12159
12160 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12161 {
12162 int myfd;
12163 switch (cmd) {
12164 case CLI_INIT:
12165 e->command = "pri set debug file";
12166 e->usage = "Usage: pri set debug file [output-file]\n"
12167 " Sends PRI debug output to the specified output file\n";
12168 return NULL;
12169 case CLI_GENERATE:
12170 return NULL;
12171 }
12172 if (a->argc < 5)
12173 return CLI_SHOWUSAGE;
12174
12175 if (ast_strlen_zero(a->argv[4]))
12176 return CLI_SHOWUSAGE;
12177
12178 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12179 if (myfd < 0) {
12180 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12181 return CLI_SUCCESS;
12182 }
12183
12184 ast_mutex_lock(&pridebugfdlock);
12185
12186 if (pridebugfd >= 0)
12187 close(pridebugfd);
12188
12189 pridebugfd = myfd;
12190 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12191 ast_mutex_unlock(&pridebugfdlock);
12192 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12193 return CLI_SUCCESS;
12194 }
12195
12196 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12197 {
12198 int span;
12199 int x;
12200 switch (cmd) {
12201 case CLI_INIT:
12202 e->command = "pri debug span";
12203 e->usage =
12204 "Usage: pri debug span <span>\n"
12205 " Enables debugging on a given PRI span\n";
12206 return NULL;
12207 case CLI_GENERATE:
12208 return complete_span_4(a->line, a->word, a->pos, a->n);
12209 }
12210 if (a->argc < 4) {
12211 return CLI_SHOWUSAGE;
12212 }
12213 span = atoi(a->argv[3]);
12214 if ((span < 1) || (span > NUM_SPANS)) {
12215 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
12216 return CLI_SUCCESS;
12217 }
12218 if (!pris[span-1].pri) {
12219 ast_cli(a->fd, "No PRI running on span %d\n", span);
12220 return CLI_SUCCESS;
12221 }
12222 for (x = 0; x < NUM_DCHANS; x++) {
12223 if (pris[span-1].dchans[x])
12224 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12225 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12226 PRI_DEBUG_Q921_STATE);
12227 }
12228 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
12229 return CLI_SUCCESS;
12230 }
12231
12232
12233
12234 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12235 {
12236 int span;
12237 int x;
12238 switch (cmd) {
12239 case CLI_INIT:
12240 e->command = "pri no debug span";
12241 e->usage =
12242 "Usage: pri no debug span <span>\n"
12243 " Disables debugging on a given PRI span\n";
12244 return NULL;
12245 case CLI_GENERATE:
12246 return complete_span_5(a->line, a->word, a->pos, a->n);
12247 }
12248 if (a->argc < 5)
12249 return CLI_SHOWUSAGE;
12250
12251 span = atoi(a->argv[4]);
12252 if ((span < 1) || (span > NUM_SPANS)) {
12253 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12254 return CLI_SUCCESS;
12255 }
12256 if (!pris[span-1].pri) {
12257 ast_cli(a->fd, "No PRI running on span %d\n", span);
12258 return CLI_SUCCESS;
12259 }
12260 for (x = 0; x < NUM_DCHANS; x++) {
12261 if (pris[span-1].dchans[x])
12262 pri_set_debug(pris[span-1].dchans[x], 0);
12263 }
12264 ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12265 return CLI_SUCCESS;
12266 }
12267
12268 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12269 {
12270 int span;
12271 int x;
12272 switch (cmd) {
12273 case CLI_INIT:
12274 e->command = "pri intensive debug span";
12275 e->usage =
12276 "Usage: pri intensive debug span <span>\n"
12277 " Enables debugging down to the Q.921 level\n";
12278 return NULL;
12279 case CLI_GENERATE:
12280 return complete_span_5(a->line, a->word, a->pos, a->n);
12281 }
12282
12283 if (a->argc < 5)
12284 return CLI_SHOWUSAGE;
12285 span = atoi(a->argv[4]);
12286 if ((span < 1) || (span > NUM_SPANS)) {
12287 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12288 return CLI_SUCCESS;
12289 }
12290 if (!pris[span-1].pri) {
12291 ast_cli(a->fd, "No PRI running on span %d\n", span);
12292 return CLI_SUCCESS;
12293 }
12294 for (x = 0; x < NUM_DCHANS; x++) {
12295 if (pris[span-1].dchans[x])
12296 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12297 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12298 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12299 }
12300 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12301 return CLI_SUCCESS;
12302 }
12303
12304 static void build_status(char *s, size_t len, int status, int active)
12305 {
12306 if (!s || len < 1) {
12307 return;
12308 }
12309 s[0] = '\0';
12310 if (status & DCHAN_PROVISIONED)
12311 strncat(s, "Provisioned, ", len - strlen(s) - 1);
12312 if (!(status & DCHAN_NOTINALARM))
12313 strncat(s, "In Alarm, ", len - strlen(s) - 1);
12314 if (status & DCHAN_UP)
12315 strncat(s, "Up", len - strlen(s) - 1);
12316 else
12317 strncat(s, "Down", len - strlen(s) - 1);
12318 if (active)
12319 strncat(s, ", Active", len - strlen(s) - 1);
12320 else
12321 strncat(s, ", Standby", len - strlen(s) - 1);
12322 s[len - 1] = '\0';
12323 }
12324
12325 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12326 {
12327 int span;
12328 int x;
12329 char status[256];
12330
12331 switch (cmd) {
12332 case CLI_INIT:
12333 e->command = "pri show spans";
12334 e->usage =
12335 "Usage: pri show spans\n"
12336 " Displays PRI Information\n";
12337 return NULL;
12338 case CLI_GENERATE:
12339 return NULL;
12340 }
12341
12342 if (a->argc != 3)
12343 return CLI_SHOWUSAGE;
12344
12345 for (span = 0; span < NUM_SPANS; span++) {
12346 if (pris[span].pri) {
12347 for (x = 0; x < NUM_DCHANS; x++) {
12348 if (pris[span].dchannels[x]) {
12349 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12350 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12351 }
12352 }
12353 }
12354 }
12355 return CLI_SUCCESS;
12356 }
12357
12358 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12359 {
12360 int span;
12361 int x;
12362 char status[256];
12363 switch (cmd) {
12364 case CLI_INIT:
12365 e->command = "pri show span";
12366 e->usage =
12367 "Usage: pri show span <span>\n"
12368 " Displays PRI Information on a given PRI span\n";
12369 return NULL;
12370 case CLI_GENERATE:
12371 return complete_span_4(a->line, a->word, a->pos, a->n);
12372 }
12373
12374 if (a->argc < 4)
12375 return CLI_SHOWUSAGE;
12376 span = atoi(a->argv[3]);
12377 if ((span < 1) || (span > NUM_SPANS)) {
12378 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12379 return CLI_SUCCESS;
12380 }
12381 if (!pris[span-1].pri) {
12382 ast_cli(a->fd, "No PRI running on span %d\n", span);
12383 return CLI_SUCCESS;
12384 }
12385 for (x = 0; x < NUM_DCHANS; x++) {
12386 if (pris[span-1].dchannels[x]) {
12387 #ifdef PRI_DUMP_INFO_STR
12388 char *info_str = NULL;
12389 #endif
12390 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12391 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12392 ast_cli(a->fd, "Status: %s\n", status);
12393 #ifdef PRI_DUMP_INFO_STR
12394 info_str = pri_dump_info_str(pris[span-1].pri);
12395 if (info_str) {
12396 ast_cli(a->fd, "%s", info_str);
12397 ast_free(info_str);
12398 }
12399 #else
12400 pri_dump_info(pris[span-1].pri);
12401 #endif
12402 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12403 }
12404 }
12405 return CLI_SUCCESS;
12406 }
12407
12408 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12409 {
12410 int x;
12411 int span;
12412 int count=0;
12413 int debug=0;
12414
12415 switch (cmd) {
12416 case CLI_INIT:
12417 e->command = "pri show debug";
12418 e->usage =
12419 "Usage: pri show debug\n"
12420 " Show the debug state of pri spans\n";
12421 return NULL;
12422 case CLI_GENERATE:
12423 return NULL;
12424 }
12425
12426 for (span = 0; span < NUM_SPANS; span++) {
12427 if (pris[span].pri) {
12428 for (x = 0; x < NUM_DCHANS; x++) {
12429 debug = 0;
12430 if (pris[span].dchans[x]) {
12431 debug = pri_get_debug(pris[span].dchans[x]);
12432 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" );
12433 count++;
12434 }
12435 }
12436 }
12437
12438 }
12439 ast_mutex_lock(&pridebugfdlock);
12440 if (pridebugfd >= 0)
12441 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12442 ast_mutex_unlock(&pridebugfdlock);
12443
12444 if (!count)
12445 ast_cli(a->fd, "No debug set or no PRI running\n");
12446 return CLI_SUCCESS;
12447 }
12448
12449 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12450 {
12451 switch (cmd) {
12452 case CLI_INIT:
12453 e->command = "pri show version";
12454 e->usage =
12455 "Usage: pri show version\n"
12456 "Show libpri version information\n";
12457 return NULL;
12458 case CLI_GENERATE:
12459 return NULL;
12460 }
12461
12462 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12463
12464 return CLI_SUCCESS;
12465 }
12466
12467 static struct ast_cli_entry dahdi_pri_cli[] = {
12468 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
12469 AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
12470 AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
12471 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
12472 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
12473 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
12474 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
12475 AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
12476 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
12477 };
12478
12479 #endif
12480
12481 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12482 {
12483 int channel;
12484 int ret;
12485 switch (cmd) {
12486 case CLI_INIT:
12487 e->command = "dahdi destroy channel";
12488 e->usage =
12489 "Usage: dahdi destroy channel <chan num>\n"
12490 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12491 return NULL;
12492 case CLI_GENERATE:
12493 return NULL;
12494 }
12495 if (a->argc != 4)
12496 return CLI_SHOWUSAGE;
12497
12498 channel = atoi(a->argv[3]);
12499 ret = dahdi_destroy_channel_bynum(channel);
12500 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12501 }
12502
12503 static void dahdi_softhangup_all(void)
12504 {
12505 struct dahdi_pvt *p;
12506 retry:
12507 ast_mutex_lock(&iflock);
12508 for (p = iflist; p; p = p->next) {
12509 ast_mutex_lock(&p->lock);
12510 if (p->owner && !p->restartpending) {
12511 if (ast_channel_trylock(p->owner)) {
12512 if (option_debug > 2)
12513 ast_verbose("Avoiding deadlock\n");
12514
12515 ast_mutex_unlock(&p->lock);
12516 ast_mutex_unlock(&iflock);
12517 goto retry;
12518 }
12519 if (option_debug > 2)
12520 ast_verbose("Softhanging up on %s\n", p->owner->name);
12521 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12522 p->restartpending = 1;
12523 num_restart_pending++;
12524 ast_channel_unlock(p->owner);
12525 }
12526 ast_mutex_unlock(&p->lock);
12527 }
12528 ast_mutex_unlock(&iflock);
12529 }
12530
12531 static int setup_dahdi(int reload);
12532 static int dahdi_restart(void)
12533 {
12534 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12535 int i, j;
12536 #endif
12537 int cancel_code;
12538 struct dahdi_pvt *p;
12539
12540 ast_mutex_lock(&restart_lock);
12541
12542 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12543 dahdi_softhangup_all();
12544 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12545
12546 #if defined(HAVE_PRI)
12547 for (i = 0; i < NUM_SPANS; i++) {
12548 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12549 cancel_code = pthread_cancel(pris[i].master);
12550 pthread_kill(pris[i].master, SIGURG);
12551 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12552 pthread_join(pris[i].master, NULL);
12553 ast_debug(4, "Joined thread of span %d\n", i);
12554 }
12555 }
12556 #endif
12557
12558 #if defined(HAVE_SS7)
12559 for (i = 0; i < NUM_SPANS; i++) {
12560 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12561 cancel_code = pthread_cancel(linksets[i].master);
12562 pthread_kill(linksets[i].master, SIGURG);
12563 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12564 pthread_join(linksets[i].master, NULL);
12565 ast_debug(4, "Joined thread of span %d\n", i);
12566 }
12567 }
12568 #endif
12569
12570 ast_mutex_lock(&monlock);
12571 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12572 cancel_code = pthread_cancel(monitor_thread);
12573 pthread_kill(monitor_thread, SIGURG);
12574 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12575 pthread_join(monitor_thread, NULL);
12576 ast_debug(4, "Joined monitor thread\n");
12577 }
12578 monitor_thread = AST_PTHREADT_NULL;
12579
12580 ast_mutex_lock(&mwi_thread_lock);
12581 while (mwi_thread_count > 0) {
12582 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12583 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12584 }
12585 ast_mutex_unlock(&mwi_thread_lock);
12586 ast_mutex_lock(&ss_thread_lock);
12587 while (ss_thread_count > 0) {
12588 int x = DAHDI_FLASH;
12589 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12590
12591 for (p = iflist; p; p = p->next) {
12592 if (p->owner)
12593 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
12594 }
12595 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12596 }
12597
12598
12599 dahdi_softhangup_all();
12600 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12601 destroy_all_channels();
12602 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12603
12604 ast_mutex_unlock(&monlock);
12605
12606 #ifdef HAVE_PRI
12607 for (i = 0; i < NUM_SPANS; i++) {
12608 for (j = 0; j < NUM_DCHANS; j++)
12609 dahdi_close_pri_fd(&(pris[i]), j);
12610 }
12611
12612 memset(pris, 0, sizeof(pris));
12613 for (i = 0; i < NUM_SPANS; i++) {
12614 ast_mutex_init(&pris[i].lock);
12615 pris[i].offset = -1;
12616 pris[i].master = AST_PTHREADT_NULL;
12617 for (j = 0; j < NUM_DCHANS; j++)
12618 pris[i].fds[j] = -1;
12619 }
12620 pri_set_error(dahdi_pri_error);
12621 pri_set_message(dahdi_pri_message);
12622 #endif
12623 #ifdef HAVE_SS7
12624 for (i = 0; i < NUM_SPANS; i++) {
12625 for (j = 0; j < NUM_DCHANS; j++)
12626 dahdi_close_ss7_fd(&(linksets[i]), j);
12627 }
12628
12629 memset(linksets, 0, sizeof(linksets));
12630 for (i = 0; i < NUM_SPANS; i++) {
12631 ast_mutex_init(&linksets[i].lock);
12632 linksets[i].master = AST_PTHREADT_NULL;
12633 for (j = 0; j < NUM_DCHANS; j++)
12634 linksets[i].fds[j] = -1;
12635 }
12636 ss7_set_error(dahdi_ss7_error);
12637 ss7_set_message(dahdi_ss7_message);
12638 #endif
12639
12640 if (setup_dahdi(2) != 0) {
12641 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12642 ast_mutex_unlock(&ss_thread_lock);
12643 return 1;
12644 }
12645 ast_mutex_unlock(&ss_thread_lock);
12646 ast_mutex_unlock(&restart_lock);
12647 return 0;
12648 }
12649
12650 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12651 {
12652 switch (cmd) {
12653 case CLI_INIT:
12654 e->command = "dahdi restart";
12655 e->usage =
12656 "Usage: dahdi restart\n"
12657 " Restarts the DAHDI channels: destroys them all and then\n"
12658 " re-reads them from chan_dahdi.conf.\n"
12659 " Note that this will STOP any running CALL on DAHDI channels.\n"
12660 "";
12661 return NULL;
12662 case CLI_GENERATE:
12663 return NULL;
12664 }
12665 if (a->argc != 2)
12666 return CLI_SHOWUSAGE;
12667
12668 if (dahdi_restart() != 0)
12669 return CLI_FAILURE;
12670 return CLI_SUCCESS;
12671 }
12672
12673 static int action_dahdirestart(struct mansession *s, const struct message *m)
12674 {
12675 if (dahdi_restart() != 0) {
12676 astman_send_error(s, m, "Failed rereading DAHDI configuration");
12677 return 1;
12678 }
12679 astman_send_ack(s, m, "DAHDIRestart: Success");
12680 return 0;
12681 }
12682
12683 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12684 {
12685 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12686 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12687 unsigned int targetnum = 0;
12688 int filtertype = 0;
12689 struct dahdi_pvt *tmp = NULL;
12690 char tmps[20] = "";
12691 char statestr[20] = "";
12692 char blockstr[20] = "";
12693 ast_mutex_t *lock;
12694 struct dahdi_pvt *start;
12695 #ifdef HAVE_PRI
12696 int trunkgroup;
12697 struct dahdi_pri *pri = NULL;
12698 int x;
12699 #endif
12700 switch (cmd) {
12701 case CLI_INIT:
12702 e->command = "dahdi show channels [trunkgroup|group|context]";
12703 e->usage =
12704 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12705 " Shows a list of available channels with optional filtering\n"
12706 " <group> must be a number between 0 and 63\n";
12707 return NULL;
12708 case CLI_GENERATE:
12709 return NULL;
12710 }
12711
12712 lock = &iflock;
12713 start = iflist;
12714
12715
12716
12717 if (!((a->argc == 3) || (a->argc == 5)))
12718 return CLI_SHOWUSAGE;
12719
12720 if (a->argc == 5) {
12721 #ifdef HAVE_PRI
12722 if (!strcasecmp(a->argv[3], "trunkgroup")) {
12723
12724 if ((trunkgroup = atoi(a->argv[4])) < 1)
12725 return CLI_SHOWUSAGE;
12726 for (x = 0; x < NUM_SPANS; x++) {
12727 if (pris[x].trunkgroup == trunkgroup) {
12728 pri = pris + x;
12729 break;
12730 }
12731 }
12732 if (pri) {
12733 start = pri->crvs;
12734 lock = &pri->lock;
12735 } else {
12736 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12737 return CLI_FAILURE;
12738 }
12739 } else
12740 #endif
12741 if (!strcasecmp(a->argv[3], "group")) {
12742 targetnum = atoi(a->argv[4]);
12743 if ((targetnum < 0) || (targetnum > 63))
12744 return CLI_SHOWUSAGE;
12745 targetnum = 1 << targetnum;
12746 filtertype = 1;
12747 } else if (!strcasecmp(a->argv[3], "context")) {
12748 filtertype = 2;
12749 }
12750 }
12751
12752 ast_mutex_lock(lock);
12753 #ifdef HAVE_PRI
12754 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12755 #else
12756 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12757 #endif
12758
12759 tmp = start;
12760 while (tmp) {
12761 if (filtertype) {
12762 switch(filtertype) {
12763 case 1:
12764 if (!(tmp->group & targetnum)) {
12765 tmp = tmp->next;
12766 continue;
12767 }
12768 break;
12769 case 2:
12770 if (strcasecmp(tmp->context, a->argv[4])) {
12771 tmp = tmp->next;
12772 continue;
12773 }
12774 break;
12775 default:
12776 ;
12777 }
12778 }
12779 if (tmp->channel > 0) {
12780 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12781 } else
12782 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12783
12784 if (tmp->locallyblocked)
12785 blockstr[0] = 'L';
12786 else
12787 blockstr[0] = ' ';
12788
12789 if (tmp->remotelyblocked)
12790 blockstr[1] = 'R';
12791 else
12792 blockstr[1] = ' ';
12793
12794 blockstr[2] = '\0';
12795
12796 snprintf(statestr, sizeof(statestr), "%s", "In Service");
12797
12798 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12799 tmp = tmp->next;
12800 }
12801 ast_mutex_unlock(lock);
12802 return CLI_SUCCESS;
12803 #undef FORMAT
12804 #undef FORMAT2
12805 }
12806
12807 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12808 {
12809 int channel;
12810 struct dahdi_pvt *tmp = NULL;
12811 struct dahdi_confinfo ci;
12812 struct dahdi_params ps;
12813 int x;
12814 ast_mutex_t *lock;
12815 struct dahdi_pvt *start;
12816 #ifdef HAVE_PRI
12817 char *c;
12818 int trunkgroup;
12819 struct dahdi_pri *pri=NULL;
12820 #endif
12821 switch (cmd) {
12822 case CLI_INIT:
12823 e->command = "dahdi show channel";
12824 e->usage =
12825 "Usage: dahdi show channel <chan num>\n"
12826 " Detailed information about a given channel\n";
12827 return NULL;
12828 case CLI_GENERATE:
12829 return NULL;
12830 }
12831
12832 lock = &iflock;
12833 start = iflist;
12834
12835 if (a->argc != 4)
12836 return CLI_SHOWUSAGE;
12837 #ifdef HAVE_PRI
12838 if ((c = strchr(a->argv[3], ':'))) {
12839 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12840 return CLI_SHOWUSAGE;
12841 if ((trunkgroup < 1) || (channel < 1))
12842 return CLI_SHOWUSAGE;
12843 for (x = 0; x < NUM_SPANS; x++) {
12844 if (pris[x].trunkgroup == trunkgroup) {
12845 pri = pris + x;
12846 break;
12847 }
12848 }
12849 if (pri) {
12850 start = pri->crvs;
12851 lock = &pri->lock;
12852 } else {
12853 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12854 return CLI_FAILURE;
12855 }
12856 } else
12857 #endif
12858 channel = atoi(a->argv[3]);
12859
12860 ast_mutex_lock(lock);
12861 tmp = start;
12862 while (tmp) {
12863 if (tmp->channel == channel) {
12864 #ifdef HAVE_PRI
12865 if (pri)
12866 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12867 else
12868 #endif
12869 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12870 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12871 ast_cli(a->fd, "Span: %d\n", tmp->span);
12872 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12873 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12874 ast_cli(a->fd, "Context: %s\n", tmp->context);
12875 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12876 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12877 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12878 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12879 if (tmp->vars) {
12880 struct ast_variable *v;
12881 ast_cli(a->fd, "Variables:\n");
12882 for (v = tmp->vars ; v ; v = v->next)
12883 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
12884 }
12885 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12886 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12887 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12888 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12889 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12890 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)" : "");
12891 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)" : "");
12892 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)" : "");
12893 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12894 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12895 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12896 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12897 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12898 if (tmp->busydetect) {
12899 #if defined(BUSYDETECT_TONEONLY)
12900 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12901 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12902 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12903 #endif
12904 #ifdef BUSYDETECT_DEBUG
12905 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
12906 #endif
12907 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
12908 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
12909 }
12910 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12911 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12912 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12913 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12914 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12915 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12916 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12917 ast_cli(a->fd, "Echo Cancellation:\n");
12918
12919 if (tmp->echocancel.head.tap_length) {
12920 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12921 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12922 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12923 }
12924 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12925 } else {
12926 ast_cli(a->fd, "\tnone\n");
12927 }
12928 if (tmp->master)
12929 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12930 for (x = 0; x < MAX_SLAVES; x++) {
12931 if (tmp->slaves[x])
12932 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12933 }
12934 #ifdef HAVE_SS7
12935 if (tmp->ss7) {
12936 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12937 }
12938 #endif
12939 #ifdef HAVE_PRI
12940 if (tmp->pri) {
12941 ast_cli(a->fd, "PRI Flags: ");
12942 if (tmp->resetting)
12943 ast_cli(a->fd, "Resetting ");
12944 if (tmp->call)
12945 ast_cli(a->fd, "Call ");
12946 if (tmp->bearer)
12947 ast_cli(a->fd, "Bearer ");
12948 ast_cli(a->fd, "\n");
12949 if (tmp->logicalspan)
12950 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12951 else
12952 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12953 }
12954
12955 #endif
12956 memset(&ci, 0, sizeof(ci));
12957 ps.channo = tmp->channel;
12958 if (tmp->subs[SUB_REAL].dfd > -1) {
12959 memset(&ci, 0, sizeof(ci));
12960 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12961 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12962 }
12963 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12964 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12965 }
12966 memset(&ps, 0, sizeof(ps));
12967 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12968 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12969 } else {
12970 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12971 }
12972 }
12973 ast_mutex_unlock(lock);
12974 return CLI_SUCCESS;
12975 }
12976 tmp = tmp->next;
12977 }
12978
12979 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12980 ast_mutex_unlock(lock);
12981 return CLI_FAILURE;
12982 }
12983
12984 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12985 {
12986 int i, j;
12987 switch (cmd) {
12988 case CLI_INIT:
12989 e->command = "dahdi show cadences";
12990 e->usage =
12991 "Usage: dahdi show cadences\n"
12992 " Shows all cadences currently defined\n";
12993 return NULL;
12994 case CLI_GENERATE:
12995 return NULL;
12996 }
12997 for (i = 0; i < num_cadence; i++) {
12998 char output[1024];
12999 char tmp[16], tmp2[64];
13000 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
13001 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
13002
13003 for (j = 0; j < 16; j++) {
13004 if (cadences[i].ringcadence[j] == 0)
13005 break;
13006 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
13007 if (cidrings[i] * 2 - 1 == j)
13008 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
13009 else
13010 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
13011 if (j != 0)
13012 strncat(output, ",", sizeof(output) - strlen(output) - 1);
13013 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
13014 }
13015 ast_cli(a->fd,"%s\n",output);
13016 }
13017 return CLI_SUCCESS;
13018 }
13019
13020
13021 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13022 {
13023 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
13024 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
13025 int span;
13026 int res;
13027 char alarmstr[50];
13028
13029 int ctl;
13030 struct dahdi_spaninfo s;
13031
13032 switch (cmd) {
13033 case CLI_INIT:
13034 e->command = "dahdi show status";
13035 e->usage =
13036 "Usage: dahdi show status\n"
13037 " Shows a list of DAHDI cards with status\n";
13038 return NULL;
13039 case CLI_GENERATE:
13040 return NULL;
13041 }
13042 ctl = open("/dev/dahdi/ctl", O_RDWR);
13043 if (ctl < 0) {
13044 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13045 return CLI_FAILURE;
13046 }
13047 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13048
13049 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13050 s.spanno = span;
13051 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13052 if (res) {
13053 continue;
13054 }
13055 alarmstr[0] = '\0';
13056 if (s.alarms > 0) {
13057 if (s.alarms & DAHDI_ALARM_BLUE)
13058 strcat(alarmstr, "BLU/");
13059 if (s.alarms & DAHDI_ALARM_YELLOW)
13060 strcat(alarmstr, "YEL/");
13061 if (s.alarms & DAHDI_ALARM_RED)
13062 strcat(alarmstr, "RED/");
13063 if (s.alarms & DAHDI_ALARM_LOOPBACK)
13064 strcat(alarmstr, "LB/");
13065 if (s.alarms & DAHDI_ALARM_RECOVER)
13066 strcat(alarmstr, "REC/");
13067 if (s.alarms & DAHDI_ALARM_NOTOPEN)
13068 strcat(alarmstr, "NOP/");
13069 if (!strlen(alarmstr))
13070 strcat(alarmstr, "UUU/");
13071 if (strlen(alarmstr)) {
13072
13073 alarmstr[strlen(alarmstr) - 1] = '\0';
13074 }
13075 } else {
13076 if (s.numchans)
13077 strcpy(alarmstr, "OK");
13078 else
13079 strcpy(alarmstr, "UNCONFIGURED");
13080 }
13081
13082 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13083 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13084 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13085 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13086 "CAS"
13087 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13088 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13089 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13090 "Unk"
13091 , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13092 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13093 , lbostr[s.lbo]
13094 );
13095 }
13096 close(ctl);
13097
13098 return CLI_SUCCESS;
13099 #undef FORMAT
13100 #undef FORMAT2
13101 }
13102
13103 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13104 {
13105 int pseudo_fd = -1;
13106 struct dahdi_versioninfo vi;
13107
13108 switch (cmd) {
13109 case CLI_INIT:
13110 e->command = "dahdi show version";
13111 e->usage =
13112 "Usage: dahdi show version\n"
13113 " Shows the DAHDI version in use\n";
13114 return NULL;
13115 case CLI_GENERATE:
13116 return NULL;
13117 }
13118 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13119 ast_cli(a->fd, "Failed to open control file to get version.\n");
13120 return CLI_SUCCESS;
13121 }
13122
13123 strcpy(vi.version, "Unknown");
13124 strcpy(vi.echo_canceller, "Unknown");
13125
13126 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13127 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13128 else
13129 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13130
13131 close(pseudo_fd);
13132
13133 return CLI_SUCCESS;
13134 }
13135
13136 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13137 {
13138 int channel;
13139 int gain;
13140 int tx;
13141 struct dahdi_hwgain hwgain;
13142 struct dahdi_pvt *tmp = NULL;
13143
13144 switch (cmd) {
13145 case CLI_INIT:
13146 e->command = "dahdi set hwgain";
13147 e->usage =
13148 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
13149 " Sets the hardware gain on a a given channel, overriding the\n"
13150 " value provided at module loadtime, whether the channel is in\n"
13151 " use or not. Changes take effect immediately.\n"
13152 " <rx|tx> which direction do you want to change (relative to our module)\n"
13153 " <chan num> is the channel number relative to the device\n"
13154 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13155 return NULL;
13156 case CLI_GENERATE:
13157 return NULL;
13158 }
13159
13160 if (a->argc != 6)
13161 return CLI_SHOWUSAGE;
13162
13163 if (!strcasecmp("rx", a->argv[3]))
13164 tx = 0;
13165 else if (!strcasecmp("tx", a->argv[3]))
13166 tx = 1;
13167 else
13168 return CLI_SHOWUSAGE;
13169
13170 channel = atoi(a->argv[4]);
13171 gain = atof(a->argv[5])*10.0;
13172
13173 ast_mutex_lock(&iflock);
13174
13175 for (tmp = iflist; tmp; tmp = tmp->next) {
13176
13177 if (tmp->channel != channel)
13178 continue;
13179
13180 if (tmp->subs[SUB_REAL].dfd == -1)
13181 break;
13182
13183 hwgain.newgain = gain;
13184 hwgain.tx = tx;
13185 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
13186 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
13187 ast_mutex_unlock(&iflock);
13188 return CLI_FAILURE;
13189 }
13190 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
13191 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
13192 break;
13193 }
13194
13195 ast_mutex_unlock(&iflock);
13196
13197 if (tmp)
13198 return CLI_SUCCESS;
13199
13200 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13201 return CLI_FAILURE;
13202
13203 }
13204
13205 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13206 {
13207 int channel;
13208 float gain;
13209 int tx;
13210 int res;
13211 ast_mutex_t *lock;
13212 struct dahdi_pvt *tmp = NULL;
13213
13214 switch (cmd) {
13215 case CLI_INIT:
13216 e->command = "dahdi set swgain";
13217 e->usage =
13218 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13219 " Sets the software gain on a a given channel, overriding the\n"
13220 " value provided at module loadtime, whether the channel is in\n"
13221 " use or not. Changes take effect immediately.\n"
13222 " <rx|tx> which direction do you want to change (relative to our module)\n"
13223 " <chan num> is the channel number relative to the device\n"
13224 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13225 return NULL;
13226 case CLI_GENERATE:
13227 return NULL;
13228 }
13229
13230 lock = &iflock;
13231
13232 if (a->argc != 6)
13233 return CLI_SHOWUSAGE;
13234
13235 if (!strcasecmp("rx", a->argv[3]))
13236 tx = 0;
13237 else if (!strcasecmp("tx", a->argv[3]))
13238 tx = 1;
13239 else
13240 return CLI_SHOWUSAGE;
13241
13242 channel = atoi(a->argv[4]);
13243 gain = atof(a->argv[5]);
13244
13245 ast_mutex_lock(lock);
13246 for (tmp = iflist; tmp; tmp = tmp->next) {
13247
13248 if (tmp->channel != channel)
13249 continue;
13250
13251 if (tmp->subs[SUB_REAL].dfd == -1)
13252 break;
13253
13254 if (tx)
13255 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13256 else
13257 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13258
13259 if (res) {
13260 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13261 ast_mutex_unlock(lock);
13262 return CLI_FAILURE;
13263 }
13264
13265 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13266 tx ? "tx" : "rx", gain, channel);
13267 break;
13268 }
13269 ast_mutex_unlock(lock);
13270
13271 if (tmp)
13272 return CLI_SUCCESS;
13273
13274 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13275 return CLI_FAILURE;
13276
13277 }
13278
13279 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13280 {
13281 int channel;
13282 int on;
13283 struct dahdi_pvt *dahdi_chan = NULL;
13284
13285 switch (cmd) {
13286 case CLI_INIT:
13287 e->command = "dahdi set dnd";
13288 e->usage =
13289 "Usage: dahdi set dnd <chan#> <on|off>\n"
13290 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13291 " Changes take effect immediately.\n"
13292 " <chan num> is the channel number\n"
13293 " <on|off> Enable or disable DND mode?\n"
13294 ;
13295 return NULL;
13296 case CLI_GENERATE:
13297 return NULL;
13298 }
13299
13300 if (a->argc != 5)
13301 return CLI_SHOWUSAGE;
13302
13303 if ((channel = atoi(a->argv[3])) <= 0) {
13304 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13305 return CLI_SHOWUSAGE;
13306 }
13307
13308 if (ast_true(a->argv[4]))
13309 on = 1;
13310 else if (ast_false(a->argv[4]))
13311 on = 0;
13312 else {
13313 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13314 return CLI_SHOWUSAGE;
13315 }
13316
13317 ast_mutex_lock(&iflock);
13318 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13319 if (dahdi_chan->channel != channel)
13320 continue;
13321
13322
13323 dahdi_dnd(dahdi_chan, on);
13324 break;
13325 }
13326 ast_mutex_unlock(&iflock);
13327
13328 if (!dahdi_chan) {
13329 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13330 return CLI_FAILURE;
13331 }
13332
13333 return CLI_SUCCESS;
13334 }
13335
13336 static struct ast_cli_entry dahdi_cli[] = {
13337 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
13338 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
13339 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
13340 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
13341 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
13342 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
13343 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
13344 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
13345 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
13346 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
13347 };
13348
13349 #define TRANSFER 0
13350 #define HANGUP 1
13351
13352 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13353 {
13354 if (p) {
13355 switch (mode) {
13356 case TRANSFER:
13357 p->fake_event = DAHDI_EVENT_WINKFLASH;
13358 break;
13359 case HANGUP:
13360 p->fake_event = DAHDI_EVENT_ONHOOK;
13361 break;
13362 default:
13363 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
13364 }
13365 }
13366 return 0;
13367 }
13368 static struct dahdi_pvt *find_channel(int channel)
13369 {
13370 struct dahdi_pvt *p = iflist;
13371 while (p) {
13372 if (p->channel == channel) {
13373 break;
13374 }
13375 p = p->next;
13376 }
13377 return p;
13378 }
13379
13380 static int action_dahdidndon(struct mansession *s, const struct message *m)
13381 {
13382 struct dahdi_pvt *p = NULL;
13383 const char *channel = astman_get_header(m, "DAHDIChannel");
13384
13385 if (ast_strlen_zero(channel)) {
13386 astman_send_error(s, m, "No channel specified");
13387 return 0;
13388 }
13389 p = find_channel(atoi(channel));
13390 if (!p) {
13391 astman_send_error(s, m, "No such channel");
13392 return 0;
13393 }
13394 p->dnd = 1;
13395 astman_send_ack(s, m, "DND Enabled");
13396 return 0;
13397 }
13398
13399 static int action_dahdidndoff(struct mansession *s, const struct message *m)
13400 {
13401 struct dahdi_pvt *p = NULL;
13402 const char *channel = astman_get_header(m, "DAHDIChannel");
13403
13404 if (ast_strlen_zero(channel)) {
13405 astman_send_error(s, m, "No channel specified");
13406 return 0;
13407 }
13408 p = find_channel(atoi(channel));
13409 if (!p) {
13410 astman_send_error(s, m, "No such channel");
13411 return 0;
13412 }
13413 p->dnd = 0;
13414 astman_send_ack(s, m, "DND Disabled");
13415 return 0;
13416 }
13417
13418 static int action_transfer(struct mansession *s, const struct message *m)
13419 {
13420 struct dahdi_pvt *p = NULL;
13421 const char *channel = astman_get_header(m, "DAHDIChannel");
13422
13423 if (ast_strlen_zero(channel)) {
13424 astman_send_error(s, m, "No channel specified");
13425 return 0;
13426 }
13427 p = find_channel(atoi(channel));
13428 if (!p) {
13429 astman_send_error(s, m, "No such channel");
13430 return 0;
13431 }
13432 dahdi_fake_event(p,TRANSFER);
13433 astman_send_ack(s, m, "DAHDITransfer");
13434 return 0;
13435 }
13436
13437 static int action_transferhangup(struct mansession *s, const struct message *m)
13438 {
13439 struct dahdi_pvt *p = NULL;
13440 const char *channel = astman_get_header(m, "DAHDIChannel");
13441
13442 if (ast_strlen_zero(channel)) {
13443 astman_send_error(s, m, "No channel specified");
13444 return 0;
13445 }
13446 p = find_channel(atoi(channel));
13447 if (!p) {
13448 astman_send_error(s, m, "No such channel");
13449 return 0;
13450 }
13451 dahdi_fake_event(p,HANGUP);
13452 astman_send_ack(s, m, "DAHDIHangup");
13453 return 0;
13454 }
13455
13456 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
13457 {
13458 struct dahdi_pvt *p = NULL;
13459 const char *channel = astman_get_header(m, "DAHDIChannel");
13460 const char *number = astman_get_header(m, "Number");
13461 int i;
13462
13463 if (ast_strlen_zero(channel)) {
13464 astman_send_error(s, m, "No channel specified");
13465 return 0;
13466 }
13467 if (ast_strlen_zero(number)) {
13468 astman_send_error(s, m, "No number specified");
13469 return 0;
13470 }
13471 p = find_channel(atoi(channel));
13472 if (!p) {
13473 astman_send_error(s, m, "No such channel");
13474 return 0;
13475 }
13476 if (!p->owner) {
13477 astman_send_error(s, m, "Channel does not have it's owner");
13478 return 0;
13479 }
13480 for (i = 0; i < strlen(number); i++) {
13481 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13482 dahdi_queue_frame(p, &f, NULL);
13483 }
13484 astman_send_ack(s, m, "DAHDIDialOffhook");
13485 return 0;
13486 }
13487
13488 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
13489 {
13490 struct dahdi_pvt *tmp = NULL;
13491 const char *id = astman_get_header(m, "ActionID");
13492 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13493 char idText[256] = "";
13494 int channels = 0;
13495 int dahdichanquery = -1;
13496 if (!ast_strlen_zero(dahdichannel)) {
13497 dahdichanquery = atoi(dahdichannel);
13498 }
13499
13500 astman_send_ack(s, m, "DAHDI channel status will follow");
13501 if (!ast_strlen_zero(id))
13502 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13503
13504 ast_mutex_lock(&iflock);
13505
13506 tmp = iflist;
13507 while (tmp) {
13508 if (tmp->channel > 0) {
13509 int alm = get_alarms(tmp);
13510
13511
13512 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13513 continue;
13514
13515 channels++;
13516 if (tmp->owner) {
13517
13518 astman_append(s,
13519 "Event: DAHDIShowChannels\r\n"
13520 "DAHDIChannel: %d\r\n"
13521 "Channel: %s\r\n"
13522 "Uniqueid: %s\r\n"
13523 "AccountCode: %s\r\n"
13524 "Signalling: %s\r\n"
13525 "SignallingCode: %d\r\n"
13526 "Context: %s\r\n"
13527 "DND: %s\r\n"
13528 "Alarm: %s\r\n"
13529 "%s"
13530 "\r\n",
13531 tmp->channel,
13532 tmp->owner->name,
13533 tmp->owner->uniqueid,
13534 tmp->owner->accountcode,
13535 sig2str(tmp->sig),
13536 tmp->sig,
13537 tmp->context,
13538 tmp->dnd ? "Enabled" : "Disabled",
13539 alarm2str(alm), idText);
13540 } else {
13541 astman_append(s,
13542 "Event: DAHDIShowChannels\r\n"
13543 "DAHDIChannel: %d\r\n"
13544 "Signalling: %s\r\n"
13545 "SignallingCode: %d\r\n"
13546 "Context: %s\r\n"
13547 "DND: %s\r\n"
13548 "Alarm: %s\r\n"
13549 "%s"
13550 "\r\n",
13551 tmp->channel, sig2str(tmp->sig), tmp->sig,
13552 tmp->context,
13553 tmp->dnd ? "Enabled" : "Disabled",
13554 alarm2str(alm), idText);
13555 }
13556 }
13557
13558 tmp = tmp->next;
13559 }
13560
13561 ast_mutex_unlock(&iflock);
13562
13563 astman_append(s,
13564 "Event: DAHDIShowChannelsComplete\r\n"
13565 "%s"
13566 "Items: %d\r\n"
13567 "\r\n",
13568 idText,
13569 channels);
13570 return 0;
13571 }
13572
13573 #ifdef HAVE_SS7
13574 static int linkset_addsigchan(int sigchan)
13575 {
13576 struct dahdi_ss7 *link;
13577 int res;
13578 int curfd;
13579 struct dahdi_params p;
13580 struct dahdi_bufferinfo bi;
13581 struct dahdi_spaninfo si;
13582
13583
13584 link = ss7_resolve_linkset(cur_linkset);
13585 if (!link) {
13586 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
13587 return -1;
13588 }
13589
13590 if (cur_ss7type < 0) {
13591 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13592 return -1;
13593 }
13594
13595 if (!link->ss7)
13596 link->ss7 = ss7_new(cur_ss7type);
13597
13598 if (!link->ss7) {
13599 ast_log(LOG_ERROR, "Can't create new SS7!\n");
13600 return -1;
13601 }
13602
13603 link->type = cur_ss7type;
13604
13605 if (cur_pointcode < 0) {
13606 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13607 return -1;
13608 } else
13609 ss7_set_pc(link->ss7, cur_pointcode);
13610
13611 if (sigchan < 0) {
13612 ast_log(LOG_ERROR, "Invalid sigchan!\n");
13613 return -1;
13614 } else {
13615 if (link->numsigchans >= NUM_DCHANS) {
13616 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13617 return -1;
13618 }
13619 curfd = link->numsigchans;
13620
13621 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13622 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13623 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13624 return -1;
13625 }
13626 memset(&p, 0, sizeof(p));
13627 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13628 if (res) {
13629 dahdi_close_ss7_fd(link, curfd);
13630 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13631 return -1;
13632 }
13633 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13634 dahdi_close_ss7_fd(link, curfd);
13635 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13636 return -1;
13637 }
13638
13639 memset(&bi, 0, sizeof(bi));
13640 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13641 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13642 bi.numbufs = 32;
13643 bi.bufsize = 512;
13644
13645 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13646 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13647 dahdi_close_ss7_fd(link, curfd);
13648 return -1;
13649 }
13650
13651 if (p.sigtype == DAHDI_SIG_MTP2)
13652 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13653 else
13654 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13655
13656 link->numsigchans++;
13657
13658 memset(&si, 0, sizeof(si));
13659 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13660 if (res) {
13661 dahdi_close_ss7_fd(link, curfd);
13662 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13663 }
13664
13665 if (!si.alarms) {
13666 link->linkstate[curfd] = LINKSTATE_DOWN;
13667 ss7_link_noalarm(link->ss7, link->fds[curfd]);
13668 } else {
13669 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13670 ss7_link_alarm(link->ss7, link->fds[curfd]);
13671 }
13672 }
13673
13674 if (cur_adjpointcode < 0) {
13675 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13676 return -1;
13677 } else {
13678 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13679 }
13680
13681 if (cur_defaultdpc < 0) {
13682 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13683 return -1;
13684 }
13685
13686 if (cur_networkindicator < 0) {
13687 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13688 return -1;
13689 } else
13690 ss7_set_network_ind(link->ss7, cur_networkindicator);
13691
13692 return 0;
13693 }
13694
13695 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13696 {
13697 int span;
13698 switch (cmd) {
13699 case CLI_INIT:
13700 e->command = "ss7 no debug linkset";
13701 e->usage =
13702 "Usage: ss7 no debug linkset <span>\n"
13703 " Disables debugging on a given SS7 linkset\n";
13704 return NULL;
13705 case CLI_GENERATE:
13706 return NULL;
13707 }
13708 if (a->argc < 5)
13709 return CLI_SHOWUSAGE;
13710 span = atoi(a->argv[4]);
13711 if ((span < 1) || (span > NUM_SPANS)) {
13712 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13713 return CLI_SUCCESS;
13714 }
13715 if (!linksets[span-1].ss7) {
13716 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13717 return CLI_SUCCESS;
13718 }
13719 if (linksets[span-1].ss7)
13720 ss7_set_debug(linksets[span-1].ss7, 0);
13721
13722 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13723 return CLI_SUCCESS;
13724 }
13725
13726 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13727 {
13728 int span;
13729 switch (cmd) {
13730 case CLI_INIT:
13731 e->command = "ss7 debug linkset";
13732 e->usage =
13733 "Usage: ss7 debug linkset <linkset>\n"
13734 " Enables debugging on a given SS7 linkset\n";
13735 return NULL;
13736 case CLI_GENERATE:
13737 return NULL;
13738 }
13739 if (a->argc < 4)
13740 return CLI_SHOWUSAGE;
13741 span = atoi(a->argv[3]);
13742 if ((span < 1) || (span > NUM_SPANS)) {
13743 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13744 return CLI_SUCCESS;
13745 }
13746 if (!linksets[span-1].ss7) {
13747 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13748 return CLI_SUCCESS;
13749 }
13750 if (linksets[span-1].ss7)
13751 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13752
13753 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13754 return CLI_SUCCESS;
13755 }
13756
13757 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13758 {
13759 int linkset, cic;
13760 int blocked = -1, i;
13761 switch (cmd) {
13762 case CLI_INIT:
13763 e->command = "ss7 block cic";
13764 e->usage =
13765 "Usage: ss7 block cic <linkset> <CIC>\n"
13766 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13767 return NULL;
13768 case CLI_GENERATE:
13769 return NULL;
13770 }
13771 if (a->argc == 5)
13772 linkset = atoi(a->argv[3]);
13773 else
13774 return CLI_SHOWUSAGE;
13775
13776 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13777 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13778 return CLI_SUCCESS;
13779 }
13780
13781 if (!linksets[linkset-1].ss7) {
13782 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13783 return CLI_SUCCESS;
13784 }
13785
13786 cic = atoi(a->argv[4]);
13787
13788 if (cic < 1) {
13789 ast_cli(a->fd, "Invalid CIC specified!\n");
13790 return CLI_SUCCESS;
13791 }
13792
13793 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13794 if (linksets[linkset-1].pvts[i]->cic == cic) {
13795 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13796 if (!blocked) {
13797 ast_mutex_lock(&linksets[linkset-1].lock);
13798 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13799 ast_mutex_unlock(&linksets[linkset-1].lock);
13800 }
13801 }
13802 }
13803
13804 if (blocked < 0) {
13805 ast_cli(a->fd, "Invalid CIC specified!\n");
13806 return CLI_SUCCESS;
13807 }
13808
13809 if (!blocked)
13810 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13811 else
13812 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13813
13814
13815 pthread_kill(linksets[linkset-1].master, SIGURG);
13816
13817 return CLI_SUCCESS;
13818 }
13819
13820 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13821 {
13822 int linkset;
13823 int i;
13824 switch (cmd) {
13825 case CLI_INIT:
13826 e->command = "ss7 block linkset";
13827 e->usage =
13828 "Usage: ss7 block linkset <linkset number>\n"
13829 " Sends a remote blocking request for all CICs on the given linkset\n";
13830 return NULL;
13831 case CLI_GENERATE:
13832 return NULL;
13833 }
13834 if (a->argc == 4)
13835 linkset = atoi(a->argv[3]);
13836 else
13837 return CLI_SHOWUSAGE;
13838
13839 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13840 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13841 return CLI_SUCCESS;
13842 }
13843
13844 if (!linksets[linkset-1].ss7) {
13845 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13846 return CLI_SUCCESS;
13847 }
13848
13849 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13850 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13851 ast_mutex_lock(&linksets[linkset-1].lock);
13852 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13853 ast_mutex_unlock(&linksets[linkset-1].lock);
13854 }
13855
13856
13857 pthread_kill(linksets[linkset-1].master, SIGURG);
13858
13859 return CLI_SUCCESS;
13860 }
13861
13862 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13863 {
13864 int linkset, cic;
13865 int i, blocked = -1;
13866 switch (cmd) {
13867 case CLI_INIT:
13868 e->command = "ss7 unblock cic";
13869 e->usage =
13870 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13871 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13872 return NULL;
13873 case CLI_GENERATE:
13874 return NULL;
13875 }
13876
13877 if (a->argc == 5)
13878 linkset = atoi(a->argv[3]);
13879 else
13880 return CLI_SHOWUSAGE;
13881
13882 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13883 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13884 return CLI_SUCCESS;
13885 }
13886
13887 if (!linksets[linkset-1].ss7) {
13888 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13889 return CLI_SUCCESS;
13890 }
13891
13892 cic = atoi(a->argv[4]);
13893
13894 if (cic < 1) {
13895 ast_cli(a->fd, "Invalid CIC specified!\n");
13896 return CLI_SUCCESS;
13897 }
13898
13899 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13900 if (linksets[linkset-1].pvts[i]->cic == cic) {
13901 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13902 if (blocked) {
13903 ast_mutex_lock(&linksets[linkset-1].lock);
13904 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13905 ast_mutex_unlock(&linksets[linkset-1].lock);
13906 }
13907 }
13908 }
13909
13910 if (blocked > 0)
13911 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13912
13913
13914 pthread_kill(linksets[linkset-1].master, SIGURG);
13915
13916 return CLI_SUCCESS;
13917 }
13918
13919 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13920 {
13921 int linkset;
13922 int i;
13923 switch (cmd) {
13924 case CLI_INIT:
13925 e->command = "ss7 unblock linkset";
13926 e->usage =
13927 "Usage: ss7 unblock linkset <linkset number>\n"
13928 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13929 return NULL;
13930 case CLI_GENERATE:
13931 return NULL;
13932 }
13933
13934 if (a->argc == 4)
13935 linkset = atoi(a->argv[3]);
13936 else
13937 return CLI_SHOWUSAGE;
13938
13939 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13940 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13941 return CLI_SUCCESS;
13942 }
13943
13944 if (!linksets[linkset-1].ss7) {
13945 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13946 return CLI_SUCCESS;
13947 }
13948
13949 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13950 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13951 ast_mutex_lock(&linksets[linkset-1].lock);
13952 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13953 ast_mutex_unlock(&linksets[linkset-1].lock);
13954 }
13955
13956
13957 pthread_kill(linksets[linkset-1].master, SIGURG);
13958
13959 return CLI_SUCCESS;
13960 }
13961
13962 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13963 {
13964 int linkset;
13965 struct dahdi_ss7 *ss7;
13966 switch (cmd) {
13967 case CLI_INIT:
13968 e->command = "ss7 show linkset";
13969 e->usage =
13970 "Usage: ss7 show linkset <span>\n"
13971 " Shows the status of an SS7 linkset.\n";
13972 return NULL;
13973 case CLI_GENERATE:
13974 return NULL;
13975 }
13976
13977 if (a->argc < 4)
13978 return CLI_SHOWUSAGE;
13979 linkset = atoi(a->argv[3]);
13980 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13981 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13982 return CLI_SUCCESS;
13983 }
13984 if (!linksets[linkset-1].ss7) {
13985 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13986 return CLI_SUCCESS;
13987 }
13988 if (linksets[linkset-1].ss7)
13989 ss7 = &linksets[linkset-1];
13990
13991 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
13992
13993 return CLI_SUCCESS;
13994 }
13995
13996 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13997 {
13998 switch (cmd) {
13999 case CLI_INIT:
14000 e->command = "ss7 show version";
14001 e->usage =
14002 "Usage: ss7 show version\n"
14003 " Show the libss7 version\n";
14004 return NULL;
14005 case CLI_GENERATE:
14006 return NULL;
14007 }
14008
14009 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
14010
14011 return CLI_SUCCESS;
14012 }
14013
14014 static struct ast_cli_entry dahdi_ss7_cli[] = {
14015 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
14016 AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"),
14017 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
14018 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
14019 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
14020 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
14021 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
14022 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
14023 };
14024 #endif
14025
14026 static int __unload_module(void)
14027 {
14028 struct dahdi_pvt *p;
14029 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14030 int i, j;
14031 #endif
14032
14033 #ifdef HAVE_PRI
14034 for (i = 0; i < NUM_SPANS; i++) {
14035 if (pris[i].master != AST_PTHREADT_NULL)
14036 pthread_cancel(pris[i].master);
14037 }
14038 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14039 ast_unregister_application(dahdi_send_keypad_facility_app);
14040 #endif
14041 #if defined(HAVE_SS7)
14042 for (i = 0; i < NUM_SPANS; i++) {
14043 if (linksets[i].master != AST_PTHREADT_NULL)
14044 pthread_cancel(linksets[i].master);
14045 }
14046 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14047 #endif
14048
14049 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14050 ast_manager_unregister( "DAHDIDialOffhook" );
14051 ast_manager_unregister( "DAHDIHangup" );
14052 ast_manager_unregister( "DAHDITransfer" );
14053 ast_manager_unregister( "DAHDIDNDoff" );
14054 ast_manager_unregister( "DAHDIDNDon" );
14055 ast_manager_unregister("DAHDIShowChannels");
14056 ast_manager_unregister("DAHDIRestart");
14057 ast_channel_unregister(&dahdi_tech);
14058 ast_mutex_lock(&iflock);
14059
14060 p = iflist;
14061 while (p) {
14062 if (p->owner)
14063 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14064 p = p->next;
14065 }
14066 ast_mutex_unlock(&iflock);
14067 ast_mutex_lock(&monlock);
14068 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14069 pthread_cancel(monitor_thread);
14070 pthread_kill(monitor_thread, SIGURG);
14071 pthread_join(monitor_thread, NULL);
14072 }
14073 monitor_thread = AST_PTHREADT_STOP;
14074 ast_mutex_unlock(&monlock);
14075
14076 destroy_all_channels();
14077
14078 #if defined(HAVE_PRI)
14079 for (i = 0; i < NUM_SPANS; i++) {
14080 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14081 pthread_join(pris[i].master, NULL);
14082 for (j = 0; j < NUM_DCHANS; j++) {
14083 dahdi_close_pri_fd(&(pris[i]), j);
14084 }
14085 }
14086 #endif
14087
14088 #if defined(HAVE_SS7)
14089 for (i = 0; i < NUM_SPANS; i++) {
14090 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14091 pthread_join(linksets[i].master, NULL);
14092 for (j = 0; j < NUM_DCHANS; j++) {
14093 dahdi_close_ss7_fd(&(linksets[i]), j);
14094 }
14095 }
14096 #endif
14097
14098 ast_cond_destroy(&mwi_thread_complete);
14099 ast_cond_destroy(&ss_thread_complete);
14100 return 0;
14101 }
14102
14103 static int unload_module(void)
14104 {
14105 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14106 int y;
14107 #endif
14108 #ifdef HAVE_PRI
14109 for (y = 0; y < NUM_SPANS; y++)
14110 ast_mutex_destroy(&pris[y].lock);
14111 #endif
14112 #ifdef HAVE_SS7
14113 for (y = 0; y < NUM_SPANS; y++)
14114 ast_mutex_destroy(&linksets[y].lock);
14115 #endif
14116 return __unload_module();
14117 }
14118
14119 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
14120 {
14121 char *c, *chan;
14122 int x, start, finish;
14123 struct dahdi_pvt *tmp;
14124 #ifdef HAVE_PRI
14125 struct dahdi_pri *pri;
14126 int trunkgroup, y;
14127 #endif
14128
14129 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14130 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14131 return -1;
14132 }
14133
14134 c = ast_strdupa(value);
14135
14136 #ifdef HAVE_PRI
14137 pri = NULL;
14138 if (iscrv) {
14139 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14140 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14141 return -1;
14142 }
14143 if (trunkgroup < 1) {
14144 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14145 return -1;
14146 }
14147 c += y;
14148 for (y = 0; y < NUM_SPANS; y++) {
14149 if (pris[y].trunkgroup == trunkgroup) {
14150 pri = pris + y;
14151 break;
14152 }
14153 }
14154 if (!pri) {
14155 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14156 return -1;
14157 }
14158 }
14159 #endif
14160
14161 while ((chan = strsep(&c, ","))) {
14162 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14163
14164 } else if (sscanf(chan, "%30d", &start)) {
14165
14166 finish = start;
14167 } else if (!strcasecmp(chan, "pseudo")) {
14168 finish = start = CHAN_PSEUDO;
14169 if (found_pseudo)
14170 *found_pseudo = 1;
14171 } else {
14172 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14173 return -1;
14174 }
14175 if (finish < start) {
14176 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14177 x = finish;
14178 finish = start;
14179 start = x;
14180 }
14181
14182 for (x = start; x <= finish; x++) {
14183 #ifdef HAVE_PRI
14184 tmp = mkintf(x, conf, pri, reload);
14185 #else
14186 tmp = mkintf(x, conf, NULL, reload);
14187 #endif
14188
14189 if (tmp) {
14190 #ifdef HAVE_PRI
14191 if (pri)
14192 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14193 else
14194 #endif
14195 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14196 } else {
14197 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14198 (reload == 1) ? "reconfigure" : "register", value);
14199 return -1;
14200 }
14201 }
14202 }
14203
14204 return 0;
14205 }
14206
14207
14208
14209 #define MAX_CHANLIST_LEN 80
14210
14211 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
14212 {
14213 char *parse = ast_strdupa(data);
14214 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14215 unsigned int param_count;
14216 unsigned int x;
14217
14218 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14219 return;
14220
14221 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14222
14223
14224
14225 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14226
14227 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14228 confp->chan.echocancel.head.tap_length = x;
14229 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14230 confp->chan.echocancel.head.tap_length = 128;
14231
14232
14233
14234 for (x = 1; x < param_count; x++) {
14235 struct {
14236 char *name;
14237 char *value;
14238 } param;
14239
14240 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
14241 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14242 continue;
14243 }
14244
14245 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14246 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14247 continue;
14248 }
14249
14250 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14251
14252 if (param.value) {
14253 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14254 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14255 continue;
14256 }
14257 }
14258 confp->chan.echocancel.head.param_count++;
14259 }
14260 }
14261
14262
14263 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
14264
14265 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
14266
14267 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
14268 {
14269 struct dahdi_pvt *tmp;
14270 int y;
14271 int found_pseudo = 0;
14272 char dahdichan[MAX_CHANLIST_LEN] = {};
14273
14274 for (; v; v = v->next) {
14275 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14276 continue;
14277
14278
14279 if (!strcasecmp(v->name, "parkinglot")) {
14280 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
14281 }
14282
14283
14284 if (!strcasecmp(v->name, "channel")
14285 #ifdef HAVE_PRI
14286 || !strcasecmp(v->name, "crv")
14287 #endif
14288 ) {
14289 int iscrv;
14290 if (options & PROC_DAHDI_OPT_NOCHAN) {
14291 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
14292 continue;
14293 }
14294 iscrv = !strcasecmp(v->name, "crv");
14295 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14296 return -1;
14297 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
14298 } else if (!strcasecmp(v->name, "buffers")) {
14299 int res;
14300 char policy[21] = "";
14301
14302 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
14303 if (res != 2) {
14304 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14305 confp->chan.buf_no = numbufs;
14306 continue;
14307 }
14308 if (confp->chan.buf_no < 0)
14309 confp->chan.buf_no = numbufs;
14310 if (!strcasecmp(policy, "full")) {
14311 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14312 } else if (!strcasecmp(policy, "immediate")) {
14313 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14314 } else {
14315 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14316 }
14317 } else if (!strcasecmp(v->name, "dahdichan")) {
14318 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14319 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14320 usedistinctiveringdetection = ast_true(v->value);
14321 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14322 distinctiveringaftercid = ast_true(v->value);
14323 } else if (!strcasecmp(v->name, "dring1context")) {
14324 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14325 } else if (!strcasecmp(v->name, "dring2context")) {
14326 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14327 } else if (!strcasecmp(v->name, "dring3context")) {
14328 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14329 } else if (!strcasecmp(v->name, "dring1range")) {
14330 confp->chan.drings.ringnum[0].range = atoi(v->value);
14331 } else if (!strcasecmp(v->name, "dring2range")) {
14332 confp->chan.drings.ringnum[1].range = atoi(v->value);
14333 } else if (!strcasecmp(v->name, "dring3range")) {
14334 confp->chan.drings.ringnum[2].range = atoi(v->value);
14335 } else if (!strcasecmp(v->name, "dring1")) {
14336 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]);
14337 } else if (!strcasecmp(v->name, "dring2")) {
14338 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]);
14339 } else if (!strcasecmp(v->name, "dring3")) {
14340 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]);
14341 } else if (!strcasecmp(v->name, "usecallerid")) {
14342 confp->chan.use_callerid = ast_true(v->value);
14343 } else if (!strcasecmp(v->name, "cidsignalling")) {
14344 if (!strcasecmp(v->value, "bell"))
14345 confp->chan.cid_signalling = CID_SIG_BELL;
14346 else if (!strcasecmp(v->value, "v23"))
14347 confp->chan.cid_signalling = CID_SIG_V23;
14348 else if (!strcasecmp(v->value, "dtmf"))
14349 confp->chan.cid_signalling = CID_SIG_DTMF;
14350 else if (!strcasecmp(v->value, "smdi"))
14351 confp->chan.cid_signalling = CID_SIG_SMDI;
14352 else if (!strcasecmp(v->value, "v23_jp"))
14353 confp->chan.cid_signalling = CID_SIG_V23_JP;
14354 else if (ast_true(v->value))
14355 confp->chan.cid_signalling = CID_SIG_BELL;
14356 } else if (!strcasecmp(v->name, "cidstart")) {
14357 if (!strcasecmp(v->value, "ring"))
14358 confp->chan.cid_start = CID_START_RING;
14359 else if (!strcasecmp(v->value, "polarity_in"))
14360 confp->chan.cid_start = CID_START_POLARITY_IN;
14361 else if (!strcasecmp(v->value, "polarity"))
14362 confp->chan.cid_start = CID_START_POLARITY;
14363 else if (ast_true(v->value))
14364 confp->chan.cid_start = CID_START_RING;
14365 } else if (!strcasecmp(v->name, "threewaycalling")) {
14366 confp->chan.threewaycalling = ast_true(v->value);
14367 } else if (!strcasecmp(v->name, "cancallforward")) {
14368 confp->chan.cancallforward = ast_true(v->value);
14369 } else if (!strcasecmp(v->name, "relaxdtmf")) {
14370 if (ast_true(v->value))
14371 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14372 else
14373 confp->chan.dtmfrelax = 0;
14374 } else if (!strcasecmp(v->name, "mailbox")) {
14375 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14376 } else if (!strcasecmp(v->name, "hasvoicemail")) {
14377 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14378 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14379 }
14380 } else if (!strcasecmp(v->name, "adsi")) {
14381 confp->chan.adsi = ast_true(v->value);
14382 } else if (!strcasecmp(v->name, "usesmdi")) {
14383 confp->chan.use_smdi = ast_true(v->value);
14384 } else if (!strcasecmp(v->name, "smdiport")) {
14385 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14386 } else if (!strcasecmp(v->name, "transfer")) {
14387 confp->chan.transfer = ast_true(v->value);
14388 } else if (!strcasecmp(v->name, "canpark")) {
14389 confp->chan.canpark = ast_true(v->value);
14390 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14391 confp->chan.echocanbridged = ast_true(v->value);
14392 } else if (!strcasecmp(v->name, "busydetect")) {
14393 confp->chan.busydetect = ast_true(v->value);
14394 } else if (!strcasecmp(v->name, "busycount")) {
14395 confp->chan.busycount = atoi(v->value);
14396 } else if (!strcasecmp(v->name, "busypattern")) {
14397 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
14398 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14399 }
14400 } else if (!strcasecmp(v->name, "callprogress")) {
14401 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14402 if (ast_true(v->value))
14403 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14404 } else if (!strcasecmp(v->name, "faxdetect")) {
14405 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14406 if (!strcasecmp(v->value, "incoming")) {
14407 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14408 } else if (!strcasecmp(v->value, "outgoing")) {
14409 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14410 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14411 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14412 } else if (!strcasecmp(v->name, "echocancel")) {
14413 process_echocancel(confp, v->value, v->lineno);
14414 } else if (!strcasecmp(v->name, "echotraining")) {
14415 if (sscanf(v->value, "%30d", &y) == 1) {
14416 if ((y < 10) || (y > 4000)) {
14417 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
14418 } else {
14419 confp->chan.echotraining = y;
14420 }
14421 } else if (ast_true(v->value)) {
14422 confp->chan.echotraining = 400;
14423 } else
14424 confp->chan.echotraining = 0;
14425 } else if (!strcasecmp(v->name, "hidecallerid")) {
14426 confp->chan.hidecallerid = ast_true(v->value);
14427 } else if (!strcasecmp(v->name, "hidecalleridname")) {
14428 confp->chan.hidecalleridname = ast_true(v->value);
14429 } else if (!strcasecmp(v->name, "pulsedial")) {
14430 confp->chan.pulse = ast_true(v->value);
14431 } else if (!strcasecmp(v->name, "callreturn")) {
14432 confp->chan.callreturn = ast_true(v->value);
14433 } else if (!strcasecmp(v->name, "callwaiting")) {
14434 confp->chan.callwaiting = ast_true(v->value);
14435 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14436 confp->chan.callwaitingcallerid = ast_true(v->value);
14437 } else if (!strcasecmp(v->name, "context")) {
14438 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14439 } else if (!strcasecmp(v->name, "language")) {
14440 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14441 } else if (!strcasecmp(v->name, "progzone")) {
14442 ast_copy_string(progzone, v->value, sizeof(progzone));
14443 } else if (!strcasecmp(v->name, "mohinterpret")
14444 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14445 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14446 } else if (!strcasecmp(v->name, "mohsuggest")) {
14447 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14448 } else if (!strcasecmp(v->name, "parkinglot")) {
14449 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
14450 } else if (!strcasecmp(v->name, "stripmsd")) {
14451 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14452 confp->chan.stripmsd = atoi(v->value);
14453 } else if (!strcasecmp(v->name, "jitterbuffers")) {
14454 numbufs = atoi(v->value);
14455 } else if (!strcasecmp(v->name, "group")) {
14456 confp->chan.group = ast_get_group(v->value);
14457 } else if (!strcasecmp(v->name, "callgroup")) {
14458 if (!strcasecmp(v->value, "none"))
14459 confp->chan.callgroup = 0;
14460 else
14461 confp->chan.callgroup = ast_get_group(v->value);
14462 } else if (!strcasecmp(v->name, "pickupgroup")) {
14463 if (!strcasecmp(v->value, "none"))
14464 confp->chan.pickupgroup = 0;
14465 else
14466 confp->chan.pickupgroup = ast_get_group(v->value);
14467 } else if (!strcasecmp(v->name, "setvar")) {
14468 char *varname = ast_strdupa(v->value), *varval = NULL;
14469 struct ast_variable *tmpvar;
14470 if (varname && (varval = strchr(varname, '='))) {
14471 *varval++ = '\0';
14472 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14473 tmpvar->next = confp->chan.vars;
14474 confp->chan.vars = tmpvar;
14475 }
14476 }
14477 } else if (!strcasecmp(v->name, "immediate")) {
14478 confp->chan.immediate = ast_true(v->value);
14479 } else if (!strcasecmp(v->name, "transfertobusy")) {
14480 confp->chan.transfertobusy = ast_true(v->value);
14481 } else if (!strcasecmp(v->name, "mwimonitor")) {
14482 confp->chan.mwimonitor_neon = 0;
14483 confp->chan.mwimonitor_fsk = 0;
14484 confp->chan.mwimonitor_rpas = 0;
14485 if (strcasestr(v->value, "fsk")) {
14486 confp->chan.mwimonitor_fsk = 1;
14487 }
14488 if (strcasestr(v->value, "rpas")) {
14489 confp->chan.mwimonitor_rpas = 1;
14490 }
14491 if (strcasestr(v->value, "neon")) {
14492 confp->chan.mwimonitor_neon = 1;
14493 }
14494
14495 if (ast_true(v->value)) {
14496 confp->chan.mwimonitor_fsk = 1;
14497 }
14498 } else if (!strcasecmp(v->name, "cid_rxgain")) {
14499 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
14500 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14501 }
14502 } else if (!strcasecmp(v->name, "rxgain")) {
14503 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
14504 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14505 }
14506 } else if (!strcasecmp(v->name, "txgain")) {
14507 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
14508 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14509 }
14510 } else if (!strcasecmp(v->name, "tonezone")) {
14511 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
14512 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14513 }
14514 } else if (!strcasecmp(v->name, "callerid")) {
14515 if (!strcasecmp(v->value, "asreceived")) {
14516 confp->chan.cid_num[0] = '\0';
14517 confp->chan.cid_name[0] = '\0';
14518 } else {
14519 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14520 }
14521 } else if (!strcasecmp(v->name, "fullname")) {
14522 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14523 } else if (!strcasecmp(v->name, "cid_number")) {
14524 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14525 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14526 confp->chan.dahditrcallerid = ast_true(v->value);
14527 } else if (!strcasecmp(v->name, "restrictcid")) {
14528 confp->chan.restrictcid = ast_true(v->value);
14529 } else if (!strcasecmp(v->name, "usecallingpres")) {
14530 confp->chan.use_callingpres = ast_true(v->value);
14531 } else if (!strcasecmp(v->name, "accountcode")) {
14532 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14533 } else if (!strcasecmp(v->name, "amaflags")) {
14534 y = ast_cdr_amaflags2int(v->value);
14535 if (y < 0)
14536 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14537 else
14538 confp->chan.amaflags = y;
14539 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14540 confp->chan.polarityonanswerdelay = atoi(v->value);
14541 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14542 confp->chan.answeronpolarityswitch = ast_true(v->value);
14543 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14544 confp->chan.hanguponpolarityswitch = ast_true(v->value);
14545 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14546 confp->chan.sendcalleridafter = atoi(v->value);
14547 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14548 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14549 } else if (!strcasecmp(v->name, "mwisendtype")) {
14550 if (!strcasecmp(v->value, "rpas")) {
14551 mwisend_rpas = 1;
14552 } else {
14553 mwisend_rpas = 0;
14554 }
14555 } else if (reload != 1) {
14556 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14557 int orig_radio = confp->chan.radio;
14558 int orig_outsigmod = confp->chan.outsigmod;
14559 int orig_auto = confp->is_sig_auto;
14560
14561 confp->chan.radio = 0;
14562 confp->chan.outsigmod = -1;
14563 confp->is_sig_auto = 0;
14564 if (!strcasecmp(v->value, "em")) {
14565 confp->chan.sig = SIG_EM;
14566 } else if (!strcasecmp(v->value, "em_e1")) {
14567 confp->chan.sig = SIG_EM_E1;
14568 } else if (!strcasecmp(v->value, "em_w")) {
14569 confp->chan.sig = SIG_EMWINK;
14570 } else if (!strcasecmp(v->value, "fxs_ls")) {
14571 confp->chan.sig = SIG_FXSLS;
14572 } else if (!strcasecmp(v->value, "fxs_gs")) {
14573 confp->chan.sig = SIG_FXSGS;
14574 } else if (!strcasecmp(v->value, "fxs_ks")) {
14575 confp->chan.sig = SIG_FXSKS;
14576 } else if (!strcasecmp(v->value, "fxo_ls")) {
14577 confp->chan.sig = SIG_FXOLS;
14578 } else if (!strcasecmp(v->value, "fxo_gs")) {
14579 confp->chan.sig = SIG_FXOGS;
14580 } else if (!strcasecmp(v->value, "fxo_ks")) {
14581 confp->chan.sig = SIG_FXOKS;
14582 } else if (!strcasecmp(v->value, "fxs_rx")) {
14583 confp->chan.sig = SIG_FXSKS;
14584 confp->chan.radio = 1;
14585 } else if (!strcasecmp(v->value, "fxo_rx")) {
14586 confp->chan.sig = SIG_FXOLS;
14587 confp->chan.radio = 1;
14588 } else if (!strcasecmp(v->value, "fxs_tx")) {
14589 confp->chan.sig = SIG_FXSLS;
14590 confp->chan.radio = 1;
14591 } else if (!strcasecmp(v->value, "fxo_tx")) {
14592 confp->chan.sig = SIG_FXOGS;
14593 confp->chan.radio = 1;
14594 } else if (!strcasecmp(v->value, "em_rx")) {
14595 confp->chan.sig = SIG_EM;
14596 confp->chan.radio = 1;
14597 } else if (!strcasecmp(v->value, "em_tx")) {
14598 confp->chan.sig = SIG_EM;
14599 confp->chan.radio = 1;
14600 } else if (!strcasecmp(v->value, "em_rxtx")) {
14601 confp->chan.sig = SIG_EM;
14602 confp->chan.radio = 2;
14603 } else if (!strcasecmp(v->value, "em_txrx")) {
14604 confp->chan.sig = SIG_EM;
14605 confp->chan.radio = 2;
14606 } else if (!strcasecmp(v->value, "sf")) {
14607 confp->chan.sig = SIG_SF;
14608 } else if (!strcasecmp(v->value, "sf_w")) {
14609 confp->chan.sig = SIG_SFWINK;
14610 } else if (!strcasecmp(v->value, "sf_featd")) {
14611 confp->chan.sig = SIG_FEATD;
14612 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14613 confp->chan.sig = SIG_FEATDMF;
14614 } else if (!strcasecmp(v->value, "sf_featb")) {
14615 confp->chan.sig = SIG_SF_FEATB;
14616 } else if (!strcasecmp(v->value, "sf")) {
14617 confp->chan.sig = SIG_SF;
14618 } else if (!strcasecmp(v->value, "sf_rx")) {
14619 confp->chan.sig = SIG_SF;
14620 confp->chan.radio = 1;
14621 } else if (!strcasecmp(v->value, "sf_tx")) {
14622 confp->chan.sig = SIG_SF;
14623 confp->chan.radio = 1;
14624 } else if (!strcasecmp(v->value, "sf_rxtx")) {
14625 confp->chan.sig = SIG_SF;
14626 confp->chan.radio = 2;
14627 } else if (!strcasecmp(v->value, "sf_txrx")) {
14628 confp->chan.sig = SIG_SF;
14629 confp->chan.radio = 2;
14630 } else if (!strcasecmp(v->value, "featd")) {
14631 confp->chan.sig = SIG_FEATD;
14632 } else if (!strcasecmp(v->value, "featdmf")) {
14633 confp->chan.sig = SIG_FEATDMF;
14634 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14635 confp->chan.sig = SIG_FEATDMF_TA;
14636 } else if (!strcasecmp(v->value, "e911")) {
14637 confp->chan.sig = SIG_E911;
14638 } else if (!strcasecmp(v->value, "fgccama")) {
14639 confp->chan.sig = SIG_FGC_CAMA;
14640 } else if (!strcasecmp(v->value, "fgccamamf")) {
14641 confp->chan.sig = SIG_FGC_CAMAMF;
14642 } else if (!strcasecmp(v->value, "featb")) {
14643 confp->chan.sig = SIG_FEATB;
14644 #ifdef HAVE_PRI
14645 } else if (!strcasecmp(v->value, "pri_net")) {
14646 confp->chan.sig = SIG_PRI;
14647 confp->pri.nodetype = PRI_NETWORK;
14648 } else if (!strcasecmp(v->value, "pri_cpe")) {
14649 confp->chan.sig = SIG_PRI;
14650 confp->pri.nodetype = PRI_CPE;
14651 } else if (!strcasecmp(v->value, "bri_cpe")) {
14652 confp->chan.sig = SIG_BRI;
14653 confp->pri.nodetype = PRI_CPE;
14654 } else if (!strcasecmp(v->value, "bri_net")) {
14655 confp->chan.sig = SIG_BRI;
14656 confp->pri.nodetype = PRI_NETWORK;
14657 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14658 confp->chan.sig = SIG_BRI_PTMP;
14659 confp->pri.nodetype = PRI_CPE;
14660 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14661 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
14662 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14663 confp->chan.sig = SIG_GR303FXOKS;
14664 confp->pri.nodetype = PRI_NETWORK;
14665 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14666 confp->chan.sig = SIG_GR303FXSKS;
14667 confp->pri.nodetype = PRI_CPE;
14668 #endif
14669 #ifdef HAVE_SS7
14670 } else if (!strcasecmp(v->value, "ss7")) {
14671 confp->chan.sig = SIG_SS7;
14672 #endif
14673 } else if (!strcasecmp(v->value, "auto")) {
14674 confp->is_sig_auto = 1;
14675 } else {
14676 confp->chan.outsigmod = orig_outsigmod;
14677 confp->chan.radio = orig_radio;
14678 confp->is_sig_auto = orig_auto;
14679 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14680 }
14681 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14682 if (!strcasecmp(v->value, "em")) {
14683 confp->chan.outsigmod = SIG_EM;
14684 } else if (!strcasecmp(v->value, "em_e1")) {
14685 confp->chan.outsigmod = SIG_EM_E1;
14686 } else if (!strcasecmp(v->value, "em_w")) {
14687 confp->chan.outsigmod = SIG_EMWINK;
14688 } else if (!strcasecmp(v->value, "sf")) {
14689 confp->chan.outsigmod = SIG_SF;
14690 } else if (!strcasecmp(v->value, "sf_w")) {
14691 confp->chan.outsigmod = SIG_SFWINK;
14692 } else if (!strcasecmp(v->value, "sf_featd")) {
14693 confp->chan.outsigmod = SIG_FEATD;
14694 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14695 confp->chan.outsigmod = SIG_FEATDMF;
14696 } else if (!strcasecmp(v->value, "sf_featb")) {
14697 confp->chan.outsigmod = SIG_SF_FEATB;
14698 } else if (!strcasecmp(v->value, "sf")) {
14699 confp->chan.outsigmod = SIG_SF;
14700 } else if (!strcasecmp(v->value, "featd")) {
14701 confp->chan.outsigmod = SIG_FEATD;
14702 } else if (!strcasecmp(v->value, "featdmf")) {
14703 confp->chan.outsigmod = SIG_FEATDMF;
14704 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14705 confp->chan.outsigmod = SIG_FEATDMF_TA;
14706 } else if (!strcasecmp(v->value, "e911")) {
14707 confp->chan.outsigmod = SIG_E911;
14708 } else if (!strcasecmp(v->value, "fgccama")) {
14709 confp->chan.outsigmod = SIG_FGC_CAMA;
14710 } else if (!strcasecmp(v->value, "fgccamamf")) {
14711 confp->chan.outsigmod = SIG_FGC_CAMAMF;
14712 } else if (!strcasecmp(v->value, "featb")) {
14713 confp->chan.outsigmod = SIG_FEATB;
14714 } else {
14715 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14716 }
14717 #ifdef HAVE_PRI
14718 } else if (!strcasecmp(v->name, "pridialplan")) {
14719 if (!strcasecmp(v->value, "national")) {
14720 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14721 } else if (!strcasecmp(v->value, "unknown")) {
14722 confp->pri.dialplan = PRI_UNKNOWN + 1;
14723 } else if (!strcasecmp(v->value, "private")) {
14724 confp->pri.dialplan = PRI_PRIVATE + 1;
14725 } else if (!strcasecmp(v->value, "international")) {
14726 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14727 } else if (!strcasecmp(v->value, "local")) {
14728 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14729 } else if (!strcasecmp(v->value, "dynamic")) {
14730 confp->pri.dialplan = -1;
14731 } else if (!strcasecmp(v->value, "redundant")) {
14732 confp->pri.dialplan = -2;
14733 } else {
14734 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14735 }
14736 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14737 if (!strcasecmp(v->value, "national")) {
14738 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14739 } else if (!strcasecmp(v->value, "unknown")) {
14740 confp->pri.localdialplan = PRI_UNKNOWN + 1;
14741 } else if (!strcasecmp(v->value, "private")) {
14742 confp->pri.localdialplan = PRI_PRIVATE + 1;
14743 } else if (!strcasecmp(v->value, "international")) {
14744 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14745 } else if (!strcasecmp(v->value, "local")) {
14746 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14747 } else if (!strcasecmp(v->value, "dynamic")) {
14748 confp->pri.localdialplan = -1;
14749 } else if (!strcasecmp(v->value, "redundant")) {
14750 confp->pri.localdialplan = -2;
14751 } else {
14752 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14753 }
14754 } else if (!strcasecmp(v->name, "switchtype")) {
14755 if (!strcasecmp(v->value, "national"))
14756 confp->pri.switchtype = PRI_SWITCH_NI2;
14757 else if (!strcasecmp(v->value, "ni1"))
14758 confp->pri.switchtype = PRI_SWITCH_NI1;
14759 else if (!strcasecmp(v->value, "dms100"))
14760 confp->pri.switchtype = PRI_SWITCH_DMS100;
14761 else if (!strcasecmp(v->value, "4ess"))
14762 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14763 else if (!strcasecmp(v->value, "5ess"))
14764 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14765 else if (!strcasecmp(v->value, "euroisdn"))
14766 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14767 else if (!strcasecmp(v->value, "qsig"))
14768 confp->pri.switchtype = PRI_SWITCH_QSIG;
14769 else {
14770 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14771 return -1;
14772 }
14773 } else if (!strcasecmp(v->name, "nsf")) {
14774 if (!strcasecmp(v->value, "sdn"))
14775 confp->pri.nsf = PRI_NSF_SDN;
14776 else if (!strcasecmp(v->value, "megacom"))
14777 confp->pri.nsf = PRI_NSF_MEGACOM;
14778 else if (!strcasecmp(v->value, "tollfreemegacom"))
14779 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14780 else if (!strcasecmp(v->value, "accunet"))
14781 confp->pri.nsf = PRI_NSF_ACCUNET;
14782 else if (!strcasecmp(v->value, "none"))
14783 confp->pri.nsf = PRI_NSF_NONE;
14784 else {
14785 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14786 confp->pri.nsf = PRI_NSF_NONE;
14787 }
14788 } else if (!strcasecmp(v->name, "priindication")) {
14789 if (!strcasecmp(v->value, "outofband"))
14790 confp->chan.priindication_oob = 1;
14791 else if (!strcasecmp(v->value, "inband"))
14792 confp->chan.priindication_oob = 0;
14793 else
14794 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14795 v->value, v->lineno);
14796 } else if (!strcasecmp(v->name, "priexclusive")) {
14797 confp->chan.priexclusive = ast_true(v->value);
14798 } else if (!strcasecmp(v->name, "internationalprefix")) {
14799 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14800 } else if (!strcasecmp(v->name, "nationalprefix")) {
14801 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14802 } else if (!strcasecmp(v->name, "localprefix")) {
14803 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14804 } else if (!strcasecmp(v->name, "privateprefix")) {
14805 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14806 } else if (!strcasecmp(v->name, "unknownprefix")) {
14807 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14808 } else if (!strcasecmp(v->name, "resetinterval")) {
14809 if (!strcasecmp(v->value, "never"))
14810 confp->pri.resetinterval = -1;
14811 else if (atoi(v->value) >= 60)
14812 confp->pri.resetinterval = atoi(v->value);
14813 else
14814 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14815 v->value, v->lineno);
14816 } else if (!strcasecmp(v->name, "minunused")) {
14817 confp->pri.minunused = atoi(v->value);
14818 } else if (!strcasecmp(v->name, "minidle")) {
14819 confp->pri.minidle = atoi(v->value);
14820 } else if (!strcasecmp(v->name, "idleext")) {
14821 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14822 } else if (!strcasecmp(v->name, "idledial")) {
14823 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14824 } else if (!strcasecmp(v->name, "overlapdial")) {
14825 if (ast_true(v->value)) {
14826 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14827 } else if (!strcasecmp(v->value, "incoming")) {
14828 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14829 } else if (!strcasecmp(v->value, "outgoing")) {
14830 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14831 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14832 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14833 } else {
14834 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14835 }
14836 #ifdef HAVE_PRI_INBANDDISCONNECT
14837 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14838 confp->pri.inbanddisconnect = ast_true(v->value);
14839 #endif
14840 } else if (!strcasecmp(v->name, "pritimer")) {
14841 #ifdef PRI_GETSET_TIMERS
14842 char tmp[20];
14843 char *timerc;
14844 char *c;
14845 int timer;
14846 int timeridx;
14847
14848 ast_copy_string(tmp, v->value, sizeof(tmp));
14849 c = tmp;
14850 timerc = strsep(&c, ",");
14851 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
14852 timeridx = pri_timer2idx(timerc);
14853 timer = atoi(c);
14854 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
14855 ast_log(LOG_WARNING,
14856 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
14857 v->lineno);
14858 } else if (!timer) {
14859 ast_log(LOG_WARNING,
14860 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
14861 c, timerc, v->lineno);
14862 } else {
14863 pritimers[timeridx] = timer;
14864 }
14865 } else {
14866 ast_log(LOG_WARNING,
14867 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
14868 v->value, v->lineno);
14869 }
14870
14871 } else if (!strcasecmp(v->name, "facilityenable")) {
14872 confp->pri.facilityenable = ast_true(v->value);
14873 #endif
14874 #endif
14875 #ifdef HAVE_SS7
14876 } else if (!strcasecmp(v->name, "ss7type")) {
14877 if (!strcasecmp(v->value, "itu")) {
14878 cur_ss7type = SS7_ITU;
14879 } else if (!strcasecmp(v->value, "ansi")) {
14880 cur_ss7type = SS7_ANSI;
14881 } else
14882 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14883 } else if (!strcasecmp(v->name, "linkset")) {
14884 cur_linkset = atoi(v->value);
14885 } else if (!strcasecmp(v->name, "pointcode")) {
14886 cur_pointcode = parse_pointcode(v->value);
14887 } else if (!strcasecmp(v->name, "adjpointcode")) {
14888 cur_adjpointcode = parse_pointcode(v->value);
14889 } else if (!strcasecmp(v->name, "defaultdpc")) {
14890 cur_defaultdpc = parse_pointcode(v->value);
14891 } else if (!strcasecmp(v->name, "cicbeginswith")) {
14892 cur_cicbeginswith = atoi(v->value);
14893 } else if (!strcasecmp(v->name, "networkindicator")) {
14894 if (!strcasecmp(v->value, "national"))
14895 cur_networkindicator = SS7_NI_NAT;
14896 else if (!strcasecmp(v->value, "national_spare"))
14897 cur_networkindicator = SS7_NI_NAT_SPARE;
14898 else if (!strcasecmp(v->value, "international"))
14899 cur_networkindicator = SS7_NI_INT;
14900 else if (!strcasecmp(v->value, "international_spare"))
14901 cur_networkindicator = SS7_NI_INT_SPARE;
14902 else
14903 cur_networkindicator = -1;
14904 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14905 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14906 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14907 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14908 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14909 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14910 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14911 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14912 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14913 if (!strcasecmp(v->value, "national")) {
14914 confp->ss7.called_nai = SS7_NAI_NATIONAL;
14915 } else if (!strcasecmp(v->value, "international")) {
14916 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14917 } else if (!strcasecmp(v->value, "subscriber")) {
14918 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14919 } else if (!strcasecmp(v->value, "dynamic")) {
14920 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14921 } else {
14922 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14923 }
14924 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14925 if (!strcasecmp(v->value, "national")) {
14926 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14927 } else if (!strcasecmp(v->value, "international")) {
14928 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14929 } else if (!strcasecmp(v->value, "subscriber")) {
14930 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14931 } else if (!strcasecmp(v->value, "dynamic")) {
14932 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14933 } else {
14934 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14935 }
14936 } else if (!strcasecmp(v->name, "sigchan")) {
14937 int sigchan, res;
14938 sigchan = atoi(v->value);
14939 res = linkset_addsigchan(sigchan);
14940 if (res < 0)
14941 return -1;
14942
14943 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14944 struct dahdi_ss7 *link;
14945 link = ss7_resolve_linkset(cur_linkset);
14946 if (!link) {
14947 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
14948 return -1;
14949 }
14950 if (ast_true(v->value))
14951 link->flags |= LINKSET_FLAG_EXPLICITACM;
14952
14953 #endif
14954 } else if (!strcasecmp(v->name, "cadence")) {
14955
14956 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14957 int i;
14958 struct dahdi_ring_cadence new_cadence;
14959 int cid_location = -1;
14960 int firstcadencepos = 0;
14961 char original_args[80];
14962 int cadence_is_ok = 1;
14963
14964 ast_copy_string(original_args, v->value, sizeof(original_args));
14965
14966 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]);
14967
14968
14969 if (element_count % 2 == 1) {
14970 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
14971 cadence_is_ok = 0;
14972 }
14973
14974
14975 for (i = 0; i < element_count; i++) {
14976 if (c[i] == 0) {
14977 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
14978 cadence_is_ok = 0;
14979 break;
14980 } else if (c[i] < 0) {
14981 if (i % 2 == 1) {
14982
14983 if (cid_location == -1) {
14984 cid_location = i;
14985 c[i] *= -1;
14986 } else {
14987 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
14988 cadence_is_ok = 0;
14989 break;
14990 }
14991 } else {
14992 if (firstcadencepos == 0) {
14993 firstcadencepos = i;
14994
14995 } else {
14996 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
14997 cadence_is_ok = 0;
14998 break;
14999 }
15000 }
15001 }
15002 }
15003
15004
15005 for (i = 0; i < 16; i++) {
15006 new_cadence.ringcadence[i] = c[i];
15007 }
15008
15009 if (cadence_is_ok) {
15010
15011 if (element_count < 2) {
15012 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
15013 } else {
15014 if (cid_location == -1) {
15015
15016 cid_location = 1;
15017 } else {
15018
15019 cid_location = (cid_location + 1) / 2;
15020 }
15021
15022 if (!user_has_defined_cadences++)
15023
15024 num_cadence = 0;
15025 if ((num_cadence+1) >= NUM_CADENCE_MAX)
15026 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
15027 else {
15028 cadences[num_cadence] = new_cadence;
15029 cidrings[num_cadence++] = cid_location;
15030 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
15031 }
15032 }
15033 }
15034 } else if (!strcasecmp(v->name, "ringtimeout")) {
15035 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
15036 } else if (!strcasecmp(v->name, "prewink")) {
15037 confp->timing.prewinktime = atoi(v->value);
15038 } else if (!strcasecmp(v->name, "preflash")) {
15039 confp->timing.preflashtime = atoi(v->value);
15040 } else if (!strcasecmp(v->name, "wink")) {
15041 confp->timing.winktime = atoi(v->value);
15042 } else if (!strcasecmp(v->name, "flash")) {
15043 confp->timing.flashtime = atoi(v->value);
15044 } else if (!strcasecmp(v->name, "start")) {
15045 confp->timing.starttime = atoi(v->value);
15046 } else if (!strcasecmp(v->name, "rxwink")) {
15047 confp->timing.rxwinktime = atoi(v->value);
15048 } else if (!strcasecmp(v->name, "rxflash")) {
15049 confp->timing.rxflashtime = atoi(v->value);
15050 } else if (!strcasecmp(v->name, "debounce")) {
15051 confp->timing.debouncetime = atoi(v->value);
15052 } else if (!strcasecmp(v->name, "toneduration")) {
15053 int toneduration;
15054 int ctlfd;
15055 int res;
15056 struct dahdi_dialparams dps;
15057
15058 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
15059 if (ctlfd == -1) {
15060 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
15061 return -1;
15062 }
15063
15064 toneduration = atoi(v->value);
15065 if (toneduration > -1) {
15066 memset(&dps, 0, sizeof(dps));
15067
15068 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
15069 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
15070 if (res < 0) {
15071 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
15072 return -1;
15073 }
15074 }
15075 close(ctlfd);
15076 } else if (!strcasecmp(v->name, "defaultcic")) {
15077 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
15078 } else if (!strcasecmp(v->name, "defaultozz")) {
15079 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
15080 } else if (!strcasecmp(v->name, "mwilevel")) {
15081 mwilevel = atoi(v->value);
15082 }
15083 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
15084 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
15085 }
15086 if (dahdichan[0]) {
15087
15088
15089 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
15090 return -1;
15091 }
15092 }
15093
15094
15095 if (!found_pseudo && reload != 1) {
15096
15097
15098
15099
15100 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
15101
15102 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
15103
15104 if (tmp) {
15105 ast_verb(3, "Automatically generated pseudo channel\n");
15106 } else {
15107 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
15108 }
15109 }
15110 return 0;
15111 }
15112
15113 static int setup_dahdi(int reload)
15114 {
15115 struct ast_config *cfg, *ucfg;
15116 struct ast_variable *v;
15117 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
15118 struct dahdi_chan_conf conf;
15119 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
15120 const char *cat;
15121 int res;
15122
15123 #ifdef HAVE_PRI
15124 char *c;
15125 int spanno;
15126 int i;
15127 int logicalspan;
15128 int trunkgroup;
15129 int dchannels[NUM_DCHANS];
15130 #endif
15131
15132 cfg = ast_config_load(config, config_flags);
15133
15134
15135 if (!cfg) {
15136 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
15137 return 0;
15138 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
15139 ucfg = ast_config_load("users.conf", config_flags);
15140 if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
15141 return 0;
15142 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15143 cfg = ast_config_load(config, config_flags);
15144 } else {
15145 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15146 ucfg = ast_config_load("users.conf", config_flags);
15147 }
15148
15149
15150 ast_mutex_lock(&iflock);
15151 #ifdef HAVE_PRI
15152 if (reload != 1) {
15153
15154 v = ast_variable_browse(cfg, "trunkgroups");
15155 while (v) {
15156 if (!strcasecmp(v->name, "trunkgroup")) {
15157 trunkgroup = atoi(v->value);
15158 if (trunkgroup > 0) {
15159 if ((c = strchr(v->value, ','))) {
15160 i = 0;
15161 memset(dchannels, 0, sizeof(dchannels));
15162 while (c && (i < NUM_DCHANS)) {
15163 dchannels[i] = atoi(c + 1);
15164 if (dchannels[i] < 0) {
15165 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);
15166 } else
15167 i++;
15168 c = strchr(c + 1, ',');
15169 }
15170 if (i) {
15171 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
15172 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);
15173 } else
15174 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");
15175 } else
15176 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15177 } else
15178 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15179 } else
15180 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
15181 } else if (!strcasecmp(v->name, "spanmap")) {
15182 spanno = atoi(v->value);
15183 if (spanno > 0) {
15184 if ((c = strchr(v->value, ','))) {
15185 trunkgroup = atoi(c + 1);
15186 if (trunkgroup > 0) {
15187 if ((c = strchr(c + 1, ',')))
15188 logicalspan = atoi(c + 1);
15189 else
15190 logicalspan = 0;
15191 if (logicalspan >= 0) {
15192 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15193 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15194 } else
15195 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15196 } else
15197 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);
15198 } else
15199 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15200 } else
15201 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15202 } else
15203 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15204 } else {
15205 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15206 }
15207 v = v->next;
15208 }
15209 }
15210 #endif
15211
15212
15213 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
15214
15215 mwimonitornotify[0] = '\0';
15216
15217 v = ast_variable_browse(cfg, "channels");
15218 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
15219 ast_mutex_unlock(&iflock);
15220 ast_config_destroy(cfg);
15221 if (ucfg) {
15222 ast_config_destroy(ucfg);
15223 }
15224 return res;
15225 }
15226
15227
15228 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15229
15230
15231
15232 if (!strcasecmp(cat, "general") ||
15233 !strcasecmp(cat, "trunkgroups") ||
15234 !strcasecmp(cat, "globals") ||
15235 !strcasecmp(cat, "channels")) {
15236 continue;
15237 }
15238
15239 memcpy(&conf, &base_conf, sizeof(conf));
15240
15241 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
15242 ast_mutex_unlock(&iflock);
15243 ast_config_destroy(cfg);
15244 if (ucfg) {
15245 ast_config_destroy(cfg);
15246 }
15247 return res;
15248 }
15249 }
15250
15251 ast_config_destroy(cfg);
15252
15253 if (ucfg) {
15254 const char *chans;
15255
15256 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
15257
15258 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15259 if (!strcasecmp(cat, "general")) {
15260 continue;
15261 }
15262
15263 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
15264
15265 if (ast_strlen_zero(chans)) {
15266 continue;
15267 }
15268
15269 memcpy(&conf, &base_conf, sizeof(conf));
15270
15271 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
15272 ast_config_destroy(ucfg);
15273 ast_mutex_unlock(&iflock);
15274 return res;
15275 }
15276 }
15277 ast_config_destroy(ucfg);
15278 }
15279 ast_mutex_unlock(&iflock);
15280
15281 #ifdef HAVE_PRI
15282 if (reload != 1) {
15283 int x;
15284 for (x = 0; x < NUM_SPANS; x++) {
15285 if (pris[x].pvts[0]) {
15286 if (start_pri(pris + x)) {
15287 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15288 return -1;
15289 } else
15290 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
15291 }
15292 }
15293 }
15294 #endif
15295 #ifdef HAVE_SS7
15296 if (reload != 1) {
15297 int x;
15298 for (x = 0; x < NUM_SPANS; x++) {
15299 if (linksets[x].ss7) {
15300 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
15301 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
15302 return -1;
15303 } else
15304 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
15305 }
15306 }
15307 }
15308 #endif
15309
15310 restart_monitor();
15311 return 0;
15312 }
15313
15314 static int load_module(void)
15315 {
15316 int res;
15317 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15318 int y, i;
15319 #endif
15320
15321 #ifdef HAVE_PRI
15322 memset(pris, 0, sizeof(pris));
15323 for (y = 0; y < NUM_SPANS; y++) {
15324 ast_mutex_init(&pris[y].lock);
15325 pris[y].offset = -1;
15326 pris[y].master = AST_PTHREADT_NULL;
15327 for (i = 0; i < NUM_DCHANS; i++)
15328 pris[y].fds[i] = -1;
15329 }
15330 pri_set_error(dahdi_pri_error);
15331 pri_set_message(dahdi_pri_message);
15332 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15333 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15334 #endif
15335 #ifdef HAVE_SS7
15336 memset(linksets, 0, sizeof(linksets));
15337 for (y = 0; y < NUM_SPANS; y++) {
15338 ast_mutex_init(&linksets[y].lock);
15339 linksets[y].master = AST_PTHREADT_NULL;
15340 for (i = 0; i < NUM_DCHANS; i++)
15341 linksets[y].fds[i] = -1;
15342 }
15343 ss7_set_error(dahdi_ss7_error);
15344 ss7_set_message(dahdi_ss7_message);
15345 #endif
15346 res = setup_dahdi(0);
15347
15348 if (res)
15349 return AST_MODULE_LOAD_DECLINE;
15350 if (ast_channel_register(&dahdi_tech)) {
15351 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15352 __unload_module();
15353 return AST_MODULE_LOAD_FAILURE;
15354 }
15355 #ifdef HAVE_PRI
15356 ast_string_field_init(&inuse, 16);
15357 ast_string_field_set(&inuse, name, "GR-303InUse");
15358 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15359 #endif
15360 #ifdef HAVE_SS7
15361 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15362 #endif
15363
15364 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15365
15366 memset(round_robin, 0, sizeof(round_robin));
15367 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15368 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15369 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15370 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15371 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15372 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15373 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15374
15375 ast_cond_init(&mwi_thread_complete, NULL);
15376 ast_cond_init(&ss_thread_complete, NULL);
15377
15378 return res;
15379 }
15380
15381 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15382 {
15383 #define END_SILENCE_LEN 400
15384 #define HEADER_MS 50
15385 #define TRAILER_MS 5
15386 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15387 #define ASCII_BYTES_PER_CHAR 80
15388
15389 unsigned char *buf,*mybuf;
15390 struct dahdi_pvt *p = c->tech_pvt;
15391 struct pollfd fds[1];
15392 int size,res,fd,len,x;
15393 int bytes=0;
15394
15395 float cr = 1.0;
15396 float ci = 0.0;
15397 float scont = 0.0;
15398 int idx;
15399
15400 idx = dahdi_get_index(c, p, 0);
15401 if (idx < 0) {
15402 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
15403 return -1;
15404 }
15405 if (!text[0]) return(0);
15406 if ((!p->tdd) && (!p->mate)) return(0);
15407 if (p->mate)
15408 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15409 else
15410 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15411 if (!buf)
15412 return -1;
15413 mybuf = buf;
15414 if (p->mate) {
15415 int codec = AST_LAW(p);
15416 for (x = 0; x < HEADER_MS; x++) {
15417 PUT_CLID_MARKMS;
15418 }
15419
15420 for (x = 0; text[x]; x++) {
15421 PUT_CLID(text[x]);
15422 }
15423 for (x = 0; x < TRAILER_MS; x++) {
15424 PUT_CLID_MARKMS;
15425 }
15426 len = bytes;
15427 buf = mybuf;
15428 } else {
15429 len = tdd_generate(p->tdd, buf, text);
15430 if (len < 1) {
15431 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15432 ast_free(mybuf);
15433 return -1;
15434 }
15435 }
15436 memset(buf + len, 0x7f, END_SILENCE_LEN);
15437 len += END_SILENCE_LEN;
15438 fd = p->subs[idx].dfd;
15439 while (len) {
15440 if (ast_check_hangup(c)) {
15441 ast_free(mybuf);
15442 return -1;
15443 }
15444 size = len;
15445 if (size > READ_SIZE)
15446 size = READ_SIZE;
15447 fds[0].fd = fd;
15448 fds[0].events = POLLOUT | POLLPRI;
15449 fds[0].revents = 0;
15450 res = poll(fds, 1, -1);
15451 if (!res) {
15452 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15453 continue;
15454 }
15455
15456 if (fds[0].revents & POLLPRI) {
15457 ast_free(mybuf);
15458 return -1;
15459 }
15460 if (!(fds[0].revents & POLLOUT)) {
15461 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15462 continue;
15463 }
15464 res = write(fd, buf, size);
15465 if (res != size) {
15466 if (res == -1) {
15467 ast_free(mybuf);
15468 return -1;
15469 }
15470 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15471 break;
15472 }
15473 len -= size;
15474 buf += size;
15475 }
15476 ast_free(mybuf);
15477 return(0);
15478 }
15479
15480
15481 static int reload(void)
15482 {
15483 int res = 0;
15484
15485 res = setup_dahdi(1);
15486 if (res) {
15487 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15488 return -1;
15489 }
15490 return 0;
15491 }
15492
15493
15494
15495
15496
15497 #ifdef HAVE_PRI
15498 #ifdef HAVE_SS7
15499 #define tdesc "DAHDI Telephony w/PRI & SS7"
15500 #else
15501 #define tdesc "DAHDI Telephony w/PRI"
15502 #endif
15503 #else
15504 #ifdef HAVE_SS7
15505 #define tdesc "DAHDI Telephony w/SS7"
15506 #else
15507 #define tdesc "DAHDI Telephony"
15508 #endif
15509 #endif
15510
15511 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15512 .load = load_module,
15513 .unload = unload_module,
15514 .reload = reload,
15515 );
15516
15517