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: 250483 $")
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 .target_extra = -1,
00125 };
00126 static struct ast_jb_conf global_jbconf;
00127
00128
00129 #undef SUPPORT_USERUSER
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 #define DEFAULT_CIDRINGS 1
00151
00152 #define CHANNEL_PSEUDO -12
00153
00154 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00155
00156
00157
00158 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
00159
00160 static const char tdesc[] = "DAHDI Telephony Driver"
00161 #ifdef HAVE_PRI
00162 " w/PRI"
00163 #endif
00164 #ifdef HAVE_SS7
00165 " w/SS7"
00166 #endif
00167 ;
00168
00169 static const char config[] = "chan_dahdi.conf";
00170
00171 #define SIG_EM DAHDI_SIG_EM
00172 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00173 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00174 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00175 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00176 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00177 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00178 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00179 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00180 #define SIG_FXSLS DAHDI_SIG_FXSLS
00181 #define SIG_FXSGS DAHDI_SIG_FXSGS
00182 #define SIG_FXSKS DAHDI_SIG_FXSKS
00183 #define SIG_FXOLS DAHDI_SIG_FXOLS
00184 #define SIG_FXOGS DAHDI_SIG_FXOGS
00185 #define SIG_FXOKS DAHDI_SIG_FXOKS
00186 #define SIG_PRI DAHDI_SIG_CLEAR
00187 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00188 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00189 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00190 #define SIG_SF DAHDI_SIG_SF
00191 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00192 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00193 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00194 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00195 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00196 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00197 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00198
00199 #ifdef LOTS_OF_SPANS
00200 #define NUM_SPANS DAHDI_MAX_SPANS
00201 #else
00202 #define NUM_SPANS 32
00203 #endif
00204 #define NUM_DCHANS 4
00205 #define MAX_CHANNELS 672
00206
00207 #define CHAN_PSEUDO -2
00208
00209 #define DCHAN_PROVISIONED (1 << 0)
00210 #define DCHAN_NOTINALARM (1 << 1)
00211 #define DCHAN_UP (1 << 2)
00212
00213 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00214
00215
00216 #define DAHDI_OVERLAPDIAL_NONE 0
00217 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00218 #define DAHDI_OVERLAPDIAL_INCOMING 2
00219 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00220
00221
00222 #define CALLPROGRESS_PROGRESS 1
00223 #define CALLPROGRESS_FAX_OUTGOING 2
00224 #define CALLPROGRESS_FAX_INCOMING 4
00225 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00226
00227 static char defaultcic[64] = "";
00228 static char defaultozz[64] = "";
00229
00230 static char parkinglot[AST_MAX_EXTENSION] = "";
00231
00232
00233 static char mwimonitornotify[PATH_MAX] = "";
00234 static int mwisend_rpas = 0;
00235
00236 static char progzone[10] = "";
00237
00238 static int usedistinctiveringdetection = 0;
00239 static int distinctiveringaftercid = 0;
00240
00241 static int numbufs = 4;
00242
00243 static int mwilevel = 512;
00244
00245 #ifdef HAVE_PRI
00246 static struct ast_channel inuse;
00247 #ifdef PRI_GETSET_TIMERS
00248 static int pritimers[PRI_MAX_TIMERS];
00249 #endif
00250 static int pridebugfd = -1;
00251 static char pridebugfilename[1024] = "";
00252 #endif
00253
00254
00255 static int firstdigittimeout = 16000;
00256
00257
00258 static int gendigittimeout = 8000;
00259
00260
00261 static int matchdigittimeout = 3000;
00262
00263
00264 AST_MUTEX_DEFINE_STATIC(iflock);
00265
00266
00267 static int ifcount = 0;
00268
00269 #ifdef HAVE_PRI
00270 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00271 #endif
00272
00273
00274
00275 AST_MUTEX_DEFINE_STATIC(monlock);
00276
00277
00278
00279 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00280 static ast_cond_t mwi_thread_complete;
00281 static ast_cond_t ss_thread_complete;
00282 AST_MUTEX_DEFINE_STATIC(mwi_thread_lock);
00283 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00284 AST_MUTEX_DEFINE_STATIC(restart_lock);
00285 static int mwi_thread_count = 0;
00286 static int ss_thread_count = 0;
00287 static int num_restart_pending = 0;
00288
00289 static int restart_monitor(void);
00290
00291 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00292
00293 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00294
00295 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00296 {
00297
00298
00299
00300
00301 }
00302
00303
00304 static inline int dahdi_get_event(int fd)
00305 {
00306 int j;
00307 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00308 return -1;
00309 return j;
00310 }
00311
00312
00313 static inline int dahdi_wait_event(int fd)
00314 {
00315 int i, j = 0;
00316 i = DAHDI_IOMUX_SIGEVENT;
00317 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00318 return -1;
00319 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00320 return -1;
00321 return j;
00322 }
00323
00324
00325 #define READ_SIZE 160
00326
00327 #define MASK_AVAIL (1 << 0)
00328 #define MASK_INUSE (1 << 1)
00329
00330 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00331 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00332 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00333 #define MIN_MS_SINCE_FLASH ( (2000) )
00334 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00335
00336 struct dahdi_pvt;
00337
00338
00339
00340
00341
00342 static int ringt_base = DEFAULT_RINGT;
00343
00344 #ifdef HAVE_SS7
00345
00346 #define LINKSTATE_INALARM (1 << 0)
00347 #define LINKSTATE_STARTING (1 << 1)
00348 #define LINKSTATE_UP (1 << 2)
00349 #define LINKSTATE_DOWN (1 << 3)
00350
00351 #define SS7_NAI_DYNAMIC -1
00352
00353 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00354
00355 struct dahdi_ss7 {
00356 pthread_t master;
00357 ast_mutex_t lock;
00358 int fds[NUM_DCHANS];
00359 int numsigchans;
00360 int linkstate[NUM_DCHANS];
00361 int numchans;
00362 int type;
00363 enum {
00364 LINKSET_STATE_DOWN = 0,
00365 LINKSET_STATE_UP
00366 } state;
00367 char called_nai;
00368 char calling_nai;
00369 char internationalprefix[10];
00370 char nationalprefix[10];
00371 char subscriberprefix[20];
00372 char unknownprefix[20];
00373 struct ss7 *ss7;
00374 struct dahdi_pvt *pvts[MAX_CHANNELS];
00375 int flags;
00376 };
00377
00378 static struct dahdi_ss7 linksets[NUM_SPANS];
00379
00380 static int cur_ss7type = -1;
00381 static int cur_linkset = -1;
00382 static int cur_pointcode = -1;
00383 static int cur_cicbeginswith = -1;
00384 static int cur_adjpointcode = -1;
00385 static int cur_networkindicator = -1;
00386 static int cur_defaultdpc = -1;
00387 #endif
00388
00389 #ifdef HAVE_PRI
00390
00391 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00392 #define PRI_CHANNEL(p) ((p) & 0xff)
00393 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00394 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00395
00396 struct dahdi_pri {
00397 pthread_t master;
00398 ast_mutex_t lock;
00399 char idleext[AST_MAX_EXTENSION];
00400 char idlecontext[AST_MAX_CONTEXT];
00401 char idledial[AST_MAX_EXTENSION];
00402 int minunused;
00403 int minidle;
00404 int nodetype;
00405 int switchtype;
00406 int nsf;
00407 int dialplan;
00408 int localdialplan;
00409 char internationalprefix[10];
00410 char nationalprefix[10];
00411 char localprefix[20];
00412 char privateprefix[20];
00413 char unknownprefix[20];
00414 int dchannels[NUM_DCHANS];
00415 int trunkgroup;
00416 int mastertrunkgroup;
00417 int prilogicalspan;
00418 int numchans;
00419 int overlapdial;
00420 int facilityenable;
00421 struct pri *dchans[NUM_DCHANS];
00422 int dchanavail[NUM_DCHANS];
00423 struct pri *pri;
00424
00425 int debug;
00426 int fds[NUM_DCHANS];
00427
00428 int offset;
00429
00430 int span;
00431
00432 int resetting;
00433
00434 int resetpos;
00435 #ifdef HAVE_PRI_INBANDDISCONNECT
00436 unsigned int inbanddisconnect:1;
00437 #endif
00438 time_t lastreset;
00439 long resetinterval;
00440
00441 int sig;
00442 struct dahdi_pvt *pvts[MAX_CHANNELS];
00443 struct dahdi_pvt *crvs;
00444 struct dahdi_pvt *crvend;
00445 };
00446
00447
00448 static struct dahdi_pri pris[NUM_SPANS];
00449
00450 #if 0
00451 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00452 #else
00453 #define DEFAULT_PRI_DEBUG 0
00454 #endif
00455
00456 static inline void pri_rel(struct dahdi_pri *pri)
00457 {
00458 ast_mutex_unlock(&pri->lock);
00459 }
00460
00461 #else
00462
00463 struct dahdi_pri;
00464 #endif
00465
00466 #define SUB_REAL 0
00467 #define SUB_CALLWAIT 1
00468 #define SUB_THREEWAY 2
00469
00470
00471 #define POLARITY_IDLE 0
00472 #define POLARITY_REV 1
00473
00474
00475 struct distRingData {
00476 int ring[3];
00477 int range;
00478 };
00479 struct ringContextData {
00480 char contextData[AST_MAX_CONTEXT];
00481 };
00482 struct dahdi_distRings {
00483 struct distRingData ringnum[3];
00484 struct ringContextData ringContext[3];
00485 };
00486
00487 static char *subnames[] = {
00488 "Real",
00489 "Callwait",
00490 "Threeway"
00491 };
00492
00493 struct dahdi_subchannel {
00494 int dfd;
00495 struct ast_channel *owner;
00496 int chan;
00497 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00498 struct ast_frame f;
00499 unsigned int needringing:1;
00500 unsigned int needbusy:1;
00501 unsigned int needcongestion:1;
00502 unsigned int needcallerid:1;
00503 unsigned int needanswer:1;
00504 unsigned int needflash:1;
00505 unsigned int needhold:1;
00506 unsigned int needunhold:1;
00507 unsigned int linear:1;
00508 unsigned int inthreeway:1;
00509 struct dahdi_confinfo curconf;
00510 };
00511
00512 #define CONF_USER_REAL (1 << 0)
00513 #define CONF_USER_THIRDCALL (1 << 1)
00514
00515 #define MAX_SLAVES 4
00516
00517 static struct dahdi_pvt {
00518 ast_mutex_t lock;
00519 struct ast_channel *owner;
00520
00521
00522 struct dahdi_subchannel sub_unused;
00523 struct dahdi_subchannel subs[3];
00524 struct dahdi_confinfo saveconf;
00525
00526 struct dahdi_pvt *slaves[MAX_SLAVES];
00527 struct dahdi_pvt *master;
00528 int inconference;
00529
00530 int buf_no;
00531 int buf_policy;
00532 int sig;
00533
00534
00535
00536
00537 int radio;
00538 int outsigmod;
00539 int oprmode;
00540 struct dahdi_pvt *oprpeer;
00541
00542 float cid_rxgain;
00543
00544 float rxgain;
00545
00546 float txgain;
00547 int tonezone;
00548 struct dahdi_pvt *next;
00549 struct dahdi_pvt *prev;
00550
00551
00552
00553
00554
00555
00556
00557 unsigned int adsi:1;
00558
00559
00560
00561
00562
00563 unsigned int answeronpolarityswitch:1;
00564
00565
00566
00567
00568
00569 unsigned int busydetect:1;
00570
00571
00572
00573
00574
00575 unsigned int callreturn:1;
00576
00577
00578
00579
00580
00581
00582 unsigned int callwaiting:1;
00583
00584
00585
00586
00587 unsigned int callwaitingcallerid:1;
00588
00589
00590
00591
00592
00593
00594 unsigned int cancallforward:1;
00595
00596
00597
00598
00599 unsigned int canpark:1;
00600
00601 unsigned int confirmanswer:1;
00602
00603
00604
00605
00606 unsigned int destroy:1;
00607 unsigned int didtdd:1;
00608
00609 unsigned int dialednone:1;
00610
00611 unsigned int dialing:1;
00612
00613 unsigned int digital:1;
00614
00615 unsigned int dnd:1;
00616
00617 unsigned int echobreak:1;
00618
00619
00620
00621
00622
00623 unsigned int echocanbridged:1;
00624
00625 unsigned int echocanon:1;
00626
00627 unsigned int faxhandled:1;
00628
00629 unsigned int firstradio:1;
00630
00631
00632
00633
00634 unsigned int hanguponpolarityswitch:1;
00635
00636 unsigned int hardwaredtmf:1;
00637
00638
00639
00640
00641
00642
00643 unsigned int hidecallerid:1;
00644
00645
00646
00647
00648
00649 unsigned int hidecalleridname:1;
00650
00651 unsigned int ignoredtmf:1;
00652
00653
00654
00655
00656
00657 unsigned int immediate:1;
00658
00659 unsigned int inalarm:1;
00660
00661 unsigned int mate:1;
00662
00663 unsigned int outgoing:1;
00664
00665
00666
00667
00668
00669
00670 unsigned int permcallwaiting:1;
00671
00672
00673
00674
00675 unsigned int permhidecallerid:1;
00676
00677
00678
00679
00680 unsigned int priindication_oob:1;
00681
00682
00683
00684
00685 unsigned int priexclusive:1;
00686
00687
00688
00689
00690 unsigned int pulse:1;
00691
00692 unsigned int pulsedial:1;
00693 unsigned int restartpending:1;
00694
00695
00696
00697
00698
00699 unsigned int restrictcid:1;
00700
00701
00702
00703
00704 unsigned int threewaycalling:1;
00705
00706
00707
00708
00709
00710
00711
00712
00713 unsigned int transfer:1;
00714
00715
00716
00717
00718
00719
00720
00721 unsigned int use_callerid:1;
00722
00723
00724
00725
00726
00727
00728 unsigned int use_callingpres:1;
00729
00730
00731
00732
00733
00734 unsigned int usedistinctiveringdetection:1;
00735
00736
00737
00738
00739 unsigned int dahditrcallerid:1;
00740
00741
00742
00743
00744 unsigned int transfertobusy:1;
00745
00746
00747
00748
00749 unsigned int mwimonitor_neon:1;
00750
00751
00752
00753
00754 unsigned int mwimonitor_fsk:1;
00755
00756
00757
00758
00759
00760 unsigned int mwimonitor_rpas:1;
00761
00762 unsigned int mwimonitoractive:1;
00763
00764 unsigned int mwisendactive:1;
00765
00766
00767
00768
00769 unsigned int inservice:1;
00770
00771
00772
00773
00774 unsigned int locallyblocked:1;
00775
00776
00777
00778
00779 unsigned int remotelyblocked:1;
00780 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00781
00782
00783
00784
00785 unsigned int rlt:1;
00786
00787 unsigned int alerting:1;
00788
00789 unsigned int alreadyhungup:1;
00790
00791
00792
00793
00794 unsigned int isidlecall:1;
00795
00796
00797
00798
00799 unsigned int proceeding:1;
00800
00801 unsigned int progress:1;
00802
00803
00804
00805
00806 unsigned int resetting:1;
00807
00808
00809
00810
00811 unsigned int setup_ack:1;
00812 #endif
00813
00814
00815
00816
00817 unsigned int use_smdi:1;
00818
00819 struct ast_smdi_interface *smdi_iface;
00820
00821
00822 struct dahdi_distRings drings;
00823
00824
00825
00826
00827
00828 char context[AST_MAX_CONTEXT];
00829
00830
00831
00832 char defcontext[AST_MAX_CONTEXT];
00833
00834 char exten[AST_MAX_EXTENSION];
00835
00836
00837
00838
00839 char language[MAX_LANGUAGE];
00840
00841
00842
00843
00844 char mohinterpret[MAX_MUSICCLASS];
00845
00846
00847
00848
00849 char mohsuggest[MAX_MUSICCLASS];
00850 char parkinglot[AST_MAX_EXTENSION];
00851 #if defined(PRI_ANI) || defined(HAVE_SS7)
00852
00853 char cid_ani[AST_MAX_EXTENSION];
00854 #endif
00855
00856 int cid_ani2;
00857
00858 char cid_num[AST_MAX_EXTENSION];
00859
00860 int cid_ton;
00861
00862 char cid_name[AST_MAX_EXTENSION];
00863
00864 char lastcid_num[AST_MAX_EXTENSION];
00865
00866 char lastcid_name[AST_MAX_EXTENSION];
00867 char *origcid_num;
00868 char *origcid_name;
00869
00870 char callwait_num[AST_MAX_EXTENSION];
00871
00872 char callwait_name[AST_MAX_EXTENSION];
00873
00874 char rdnis[AST_MAX_EXTENSION];
00875
00876 char dnid[AST_MAX_EXTENSION];
00877
00878
00879
00880
00881 ast_group_t group;
00882
00883 int law;
00884 int confno;
00885 int confusers;
00886 int propconfno;
00887
00888
00889
00890
00891 ast_group_t callgroup;
00892
00893
00894
00895
00896 ast_group_t pickupgroup;
00897
00898
00899
00900
00901 struct ast_variable *vars;
00902 int channel;
00903 int span;
00904 time_t guardtime;
00905 int cid_signalling;
00906 int cid_start;
00907 int callingpres;
00908 int callwaitingrepeat;
00909 int cidcwexpire;
00910
00911 unsigned char *cidspill;
00912
00913 int cidpos;
00914
00915 int cidlen;
00916
00917 int ringt;
00918
00919
00920
00921
00922 int ringt_base;
00923
00924
00925
00926
00927
00928
00929 int stripmsd;
00930
00931 int callwaitcas;
00932
00933 int callwaitrings;
00934
00935 struct {
00936 struct dahdi_echocanparams head;
00937 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
00938 } echocancel;
00939
00940
00941
00942
00943 int echotraining;
00944
00945 char echorest[20];
00946
00947
00948
00949
00950 int busycount;
00951
00952
00953
00954
00955 int busy_tonelength;
00956
00957
00958
00959
00960 int busy_quietlength;
00961
00962
00963
00964
00965 int callprogress;
00966 struct timeval flashtime;
00967
00968 struct ast_dsp *dsp;
00969
00970
00971 struct dahdi_dialoperation dop;
00972 int whichwink;
00973
00974 char finaldial[64];
00975 char accountcode[AST_MAX_ACCOUNT_CODE];
00976 int amaflags;
00977 struct tdd_state *tdd;
00978
00979 char call_forward[AST_MAX_EXTENSION];
00980
00981
00982
00983
00984 char mailbox[AST_MAX_EXTENSION];
00985
00986 struct ast_event_sub *mwi_event_sub;
00987
00988 char dialdest[256];
00989
00990 int onhooktime;
00991
00992 int msgstate;
00993 int distinctivering;
00994 int cidrings;
00995 int dtmfrelax;
00996
00997 int fake_event;
00998
00999
01000
01001
01002 int polarityonanswerdelay;
01003
01004 struct timeval polaritydelaytv;
01005
01006
01007
01008
01009 int sendcalleridafter;
01010 #ifdef HAVE_PRI
01011
01012 struct dahdi_pri *pri;
01013
01014 struct dahdi_pvt *bearer;
01015
01016 struct dahdi_pvt *realcall;
01017
01018 q931_call *call;
01019
01020 int prioffset;
01021
01022 int logicalspan;
01023 #endif
01024
01025 int polarity;
01026
01027 int dsp_features;
01028 #ifdef HAVE_SS7
01029
01030 struct dahdi_ss7 *ss7;
01031
01032 struct isup_call *ss7call;
01033 char charge_number[50];
01034 char gen_add_number[50];
01035 char gen_dig_number[50];
01036 char orig_called_num[50];
01037 char redirecting_num[50];
01038 char generic_name[50];
01039 unsigned char gen_add_num_plan;
01040 unsigned char gen_add_nai;
01041 unsigned char gen_add_pres_ind;
01042 unsigned char gen_add_type;
01043 unsigned char gen_dig_type;
01044 unsigned char gen_dig_scheme;
01045 char jip_number[50];
01046 unsigned char lspi_type;
01047 unsigned char lspi_scheme;
01048 unsigned char lspi_context;
01049 char lspi_ident[50];
01050 unsigned int call_ref_ident;
01051 unsigned int call_ref_pc;
01052 unsigned char calling_party_cat;
01053 int transcap;
01054 int cic;
01055 unsigned int dpc;
01056 unsigned int loopedback:1;
01057 #endif
01058
01059 char begindigit;
01060
01061 int muting;
01062 } *iflist = NULL, *ifend = NULL;
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 struct dahdi_chan_conf {
01075 struct dahdi_pvt chan;
01076 #ifdef HAVE_PRI
01077 struct dahdi_pri pri;
01078 #endif
01079
01080 #ifdef HAVE_SS7
01081 struct dahdi_ss7 ss7;
01082 #endif
01083 struct dahdi_params timing;
01084 int is_sig_auto;
01085
01086
01087
01088
01089
01090 char smdi_port[SMDI_MAX_FILENAME_LEN];
01091 };
01092
01093
01094 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01095
01096
01097
01098 struct dahdi_chan_conf conf = {
01099 #ifdef HAVE_PRI
01100 .pri = {
01101 .nsf = PRI_NSF_NONE,
01102 .switchtype = PRI_SWITCH_NI2,
01103 .dialplan = PRI_UNKNOWN + 1,
01104 .localdialplan = PRI_NATIONAL_ISDN + 1,
01105 .nodetype = PRI_CPE,
01106
01107 .minunused = 2,
01108 .idleext = "",
01109 .idledial = "",
01110 .internationalprefix = "",
01111 .nationalprefix = "",
01112 .localprefix = "",
01113 .privateprefix = "",
01114 .unknownprefix = "",
01115 .resetinterval = -1,
01116 },
01117 #endif
01118 #ifdef HAVE_SS7
01119 .ss7 = {
01120 .called_nai = SS7_NAI_NATIONAL,
01121 .calling_nai = SS7_NAI_NATIONAL,
01122 .internationalprefix = "",
01123 .nationalprefix = "",
01124 .subscriberprefix = "",
01125 .unknownprefix = ""
01126 },
01127 #endif
01128 .chan = {
01129 .context = "default",
01130 .cid_num = "",
01131 .cid_name = "",
01132 .mohinterpret = "default",
01133 .mohsuggest = "",
01134 .parkinglot = "",
01135 .transfertobusy = 1,
01136
01137 .cid_signalling = CID_SIG_BELL,
01138 .cid_start = CID_START_RING,
01139 .dahditrcallerid = 0,
01140 .use_callerid = 1,
01141 .sig = -1,
01142 .outsigmod = -1,
01143
01144 .cid_rxgain = +5.0,
01145
01146 .tonezone = -1,
01147
01148 .echocancel.head.tap_length = 1,
01149
01150 .busycount = 3,
01151
01152 .accountcode = "",
01153
01154 .mailbox = "",
01155
01156
01157 .polarityonanswerdelay = 600,
01158
01159 .sendcalleridafter = DEFAULT_CIDRINGS,
01160
01161 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01162 .buf_no = numbufs
01163 },
01164 .timing = {
01165 .prewinktime = -1,
01166 .preflashtime = -1,
01167 .winktime = -1,
01168 .flashtime = -1,
01169 .starttime = -1,
01170 .rxwinktime = -1,
01171 .rxflashtime = -1,
01172 .debouncetime = -1
01173 },
01174 .is_sig_auto = 1,
01175 .smdi_port = "/dev/ttyS0",
01176 };
01177
01178 return conf;
01179 }
01180
01181
01182 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01183 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01184 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01185 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01186 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01187 static int dahdi_hangup(struct ast_channel *ast);
01188 static int dahdi_answer(struct ast_channel *ast);
01189 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01190 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01191 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01192 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01193 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01194 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01195 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01196 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01197
01198 static const struct ast_channel_tech dahdi_tech = {
01199 .type = "DAHDI",
01200 .description = tdesc,
01201 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01202 .requester = dahdi_request,
01203 .send_digit_begin = dahdi_digit_begin,
01204 .send_digit_end = dahdi_digit_end,
01205 .send_text = dahdi_sendtext,
01206 .call = dahdi_call,
01207 .hangup = dahdi_hangup,
01208 .answer = dahdi_answer,
01209 .read = dahdi_read,
01210 .write = dahdi_write,
01211 .bridge = dahdi_bridge,
01212 .exception = dahdi_exception,
01213 .indicate = dahdi_indicate,
01214 .fixup = dahdi_fixup,
01215 .setoption = dahdi_setoption,
01216 .func_channel_read = dahdi_func_read,
01217 };
01218
01219 #ifdef HAVE_PRI
01220 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01221 #else
01222 #define GET_CHANNEL(p) ((p)->channel)
01223 #endif
01224
01225 struct dahdi_pvt *round_robin[32];
01226
01227 #ifdef HAVE_PRI
01228 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01229 {
01230 int res;
01231
01232 do {
01233 res = ast_mutex_trylock(&pri->lock);
01234 if (res) {
01235 DEADLOCK_AVOIDANCE(&pvt->lock);
01236 }
01237 } while (res);
01238
01239 if (pri->master != AST_PTHREADT_NULL)
01240 pthread_kill(pri->master, SIGURG);
01241 return 0;
01242 }
01243 #endif
01244
01245 #ifdef HAVE_SS7
01246 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01247 {
01248 ast_mutex_unlock(&ss7->lock);
01249 }
01250
01251 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01252 {
01253 int res;
01254
01255 do {
01256 res = ast_mutex_trylock(&pri->lock);
01257 if (res) {
01258 DEADLOCK_AVOIDANCE(&pvt->lock);
01259 }
01260 } while (res);
01261
01262 if (pri->master != AST_PTHREADT_NULL)
01263 pthread_kill(pri->master, SIGURG);
01264 return 0;
01265 }
01266 #endif
01267 #define NUM_CADENCE_MAX 25
01268 static int num_cadence = 4;
01269 static int user_has_defined_cadences = 0;
01270
01271 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01272 { { 125, 125, 2000, 4000 } },
01273 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01274 { { 125, 125, 125, 125, 125, 4000 } },
01275 { { 1000, 500, 2500, 5000 } },
01276 };
01277
01278
01279
01280
01281
01282 static int cidrings[NUM_CADENCE_MAX] = {
01283 2,
01284 4,
01285 3,
01286 2,
01287 };
01288
01289
01290 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01291
01292 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01293 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01294
01295 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01296 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01297
01298 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01299 {
01300 int res;
01301 if (p->subs[SUB_REAL].owner == ast)
01302 res = 0;
01303 else if (p->subs[SUB_CALLWAIT].owner == ast)
01304 res = 1;
01305 else if (p->subs[SUB_THREEWAY].owner == ast)
01306 res = 2;
01307 else {
01308 res = -1;
01309 if (!nullok)
01310 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01311 }
01312 return res;
01313 }
01314
01315 #ifdef HAVE_PRI
01316 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01317 #else
01318 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01319 #endif
01320 {
01321 #ifdef HAVE_PRI
01322 if (pri)
01323 ast_mutex_unlock(&pri->lock);
01324 #endif
01325 for (;;) {
01326 if (p->subs[a].owner) {
01327 if (ast_channel_trylock(p->subs[a].owner)) {
01328 DEADLOCK_AVOIDANCE(&p->lock);
01329 } else {
01330 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01331 ast_channel_unlock(p->subs[a].owner);
01332 break;
01333 }
01334 } else
01335 break;
01336 }
01337 #ifdef HAVE_PRI
01338 if (pri)
01339 ast_mutex_lock(&pri->lock);
01340 #endif
01341 }
01342
01343 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01344 {
01345 #ifdef HAVE_PRI
01346 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01347 #endif
01348 #ifdef HAVE_SS7
01349 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01350 #endif
01351
01352 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01353 if (data) {
01354 switch (p->sig) {
01355 #ifdef HAVE_PRI
01356 case SIG_BRI:
01357 case SIG_BRI_PTMP:
01358 case SIG_PRI:
01359 ast_mutex_unlock(&pri->lock);
01360 break;
01361 #endif
01362 #ifdef HAVE_SS7
01363 case SIG_SS7:
01364 ast_mutex_unlock(&ss7->lock);
01365 break;
01366 #endif
01367 default:
01368 break;
01369 }
01370 }
01371 #endif
01372 for (;;) {
01373 if (p->owner) {
01374 if (ast_channel_trylock(p->owner)) {
01375 DEADLOCK_AVOIDANCE(&p->lock);
01376 } else {
01377 ast_queue_frame(p->owner, f);
01378 ast_channel_unlock(p->owner);
01379 break;
01380 }
01381 } else
01382 break;
01383 }
01384 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01385 if (data) {
01386 switch (p->sig) {
01387 #ifdef HAVE_PRI
01388 case SIG_BRI:
01389 case SIG_BRI_PTMP:
01390 case SIG_PRI:
01391 ast_mutex_lock(&pri->lock);
01392 break;
01393 #endif
01394 #ifdef HAVE_SS7
01395 case SIG_SS7:
01396 ast_mutex_lock(&ss7->lock);
01397 break;
01398 #endif
01399 default:
01400 break;
01401 }
01402 }
01403
01404 #endif
01405 }
01406
01407 static int restore_gains(struct dahdi_pvt *p);
01408
01409 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01410 {
01411 int tchan;
01412 int tinthreeway;
01413 struct ast_channel *towner;
01414
01415 ast_debug(1, "Swapping %d and %d\n", a, b);
01416
01417 tchan = p->subs[a].chan;
01418 towner = p->subs[a].owner;
01419 tinthreeway = p->subs[a].inthreeway;
01420
01421 p->subs[a].chan = p->subs[b].chan;
01422 p->subs[a].owner = p->subs[b].owner;
01423 p->subs[a].inthreeway = p->subs[b].inthreeway;
01424
01425 p->subs[b].chan = tchan;
01426 p->subs[b].owner = towner;
01427 p->subs[b].inthreeway = tinthreeway;
01428
01429 if (p->subs[a].owner)
01430 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01431 if (p->subs[b].owner)
01432 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01433 wakeup_sub(p, a, NULL);
01434 wakeup_sub(p, b, NULL);
01435 }
01436
01437 static int dahdi_open(char *fn)
01438 {
01439 int fd;
01440 int isnum;
01441 int chan = 0;
01442 int bs;
01443 int x;
01444 isnum = 1;
01445 for (x = 0; x < strlen(fn); x++) {
01446 if (!isdigit(fn[x])) {
01447 isnum = 0;
01448 break;
01449 }
01450 }
01451 if (isnum) {
01452 chan = atoi(fn);
01453 if (chan < 1) {
01454 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01455 return -1;
01456 }
01457 fn = "/dev/dahdi/channel";
01458 }
01459 fd = open(fn, O_RDWR | O_NONBLOCK);
01460 if (fd < 0) {
01461 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01462 return -1;
01463 }
01464 if (chan) {
01465 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01466 x = errno;
01467 close(fd);
01468 errno = x;
01469 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01470 return -1;
01471 }
01472 }
01473 bs = READ_SIZE;
01474 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01475 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01476 x = errno;
01477 close(fd);
01478 errno = x;
01479 return -1;
01480 }
01481 return fd;
01482 }
01483
01484 static void dahdi_close(int fd)
01485 {
01486 if (fd > 0)
01487 close(fd);
01488 }
01489
01490 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01491 {
01492 dahdi_close(chan_pvt->subs[sub_num].dfd);
01493 chan_pvt->subs[sub_num].dfd = -1;
01494 }
01495
01496 #ifdef HAVE_PRI
01497 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01498 {
01499 dahdi_close(pri->fds[fd_num]);
01500 pri->fds[fd_num] = -1;
01501 }
01502 #endif
01503
01504 #ifdef HAVE_SS7
01505 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
01506 {
01507 dahdi_close(ss7->fds[fd_num]);
01508 ss7->fds[fd_num] = -1;
01509 }
01510 #endif
01511
01512 static int dahdi_setlinear(int dfd, int linear)
01513 {
01514 int res;
01515 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01516 if (res)
01517 return res;
01518 return 0;
01519 }
01520
01521
01522 static int alloc_sub(struct dahdi_pvt *p, int x)
01523 {
01524 struct dahdi_bufferinfo bi;
01525 int res;
01526 if (p->subs[x].dfd >= 0) {
01527 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01528 return -1;
01529 }
01530
01531 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01532 if (p->subs[x].dfd <= -1) {
01533 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01534 return -1;
01535 }
01536
01537 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01538 if (!res) {
01539 bi.txbufpolicy = p->buf_policy;
01540 bi.rxbufpolicy = p->buf_policy;
01541 bi.numbufs = p->buf_no;
01542 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01543 if (res < 0) {
01544 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01545 }
01546 } else
01547 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01548
01549 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01550 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01551 dahdi_close_sub(p, x);
01552 p->subs[x].dfd = -1;
01553 return -1;
01554 }
01555 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01556 return 0;
01557 }
01558
01559 static int unalloc_sub(struct dahdi_pvt *p, int x)
01560 {
01561 if (!x) {
01562 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01563 return -1;
01564 }
01565 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01566 dahdi_close_sub(p, x);
01567 p->subs[x].linear = 0;
01568 p->subs[x].chan = 0;
01569 p->subs[x].owner = NULL;
01570 p->subs[x].inthreeway = 0;
01571 p->polarity = POLARITY_IDLE;
01572 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01573 return 0;
01574 }
01575
01576 static int digit_to_dtmfindex(char digit)
01577 {
01578 if (isdigit(digit))
01579 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01580 else if (digit >= 'A' && digit <= 'D')
01581 return DAHDI_TONE_DTMF_A + (digit - 'A');
01582 else if (digit >= 'a' && digit <= 'd')
01583 return DAHDI_TONE_DTMF_A + (digit - 'a');
01584 else if (digit == '*')
01585 return DAHDI_TONE_DTMF_s;
01586 else if (digit == '#')
01587 return DAHDI_TONE_DTMF_p;
01588 else
01589 return -1;
01590 }
01591
01592 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01593 {
01594 struct dahdi_pvt *pvt;
01595 int idx;
01596 int dtmf = -1;
01597
01598 pvt = chan->tech_pvt;
01599
01600 ast_mutex_lock(&pvt->lock);
01601
01602 idx = dahdi_get_index(chan, pvt, 0);
01603
01604 if ((idx != SUB_REAL) || !pvt->owner)
01605 goto out;
01606
01607 #ifdef HAVE_PRI
01608 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01609 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01610 if (pvt->setup_ack) {
01611 if (!pri_grab(pvt, pvt->pri)) {
01612 pri_information(pvt->pri->pri, pvt->call, digit);
01613 pri_rel(pvt->pri);
01614 } else
01615 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01616 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01617 int res;
01618 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01619 res = strlen(pvt->dialdest);
01620 pvt->dialdest[res++] = digit;
01621 pvt->dialdest[res] = '\0';
01622 }
01623 goto out;
01624 }
01625 #endif
01626 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01627 goto out;
01628
01629 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01630 int res;
01631 struct dahdi_dialoperation zo = {
01632 .op = DAHDI_DIAL_OP_APPEND,
01633 };
01634
01635 zo.dialstr[0] = 'T';
01636 zo.dialstr[1] = digit;
01637 zo.dialstr[2] = '\0';
01638 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01639 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01640 else
01641 pvt->dialing = 1;
01642 } else {
01643 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01644 pvt->dialing = 1;
01645 pvt->begindigit = digit;
01646 }
01647
01648 out:
01649 ast_mutex_unlock(&pvt->lock);
01650
01651 return 0;
01652 }
01653
01654 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01655 {
01656 struct dahdi_pvt *pvt;
01657 int res = 0;
01658 int idx;
01659 int x;
01660
01661 pvt = chan->tech_pvt;
01662
01663 ast_mutex_lock(&pvt->lock);
01664
01665 idx = dahdi_get_index(chan, pvt, 0);
01666
01667 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
01668 goto out;
01669
01670 #ifdef HAVE_PRI
01671
01672 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01673 && !pvt->begindigit)
01674 goto out;
01675 #endif
01676
01677 if (pvt->begindigit) {
01678 x = -1;
01679 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01680 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01681 pvt->dialing = 0;
01682 pvt->begindigit = 0;
01683 }
01684
01685 out:
01686 ast_mutex_unlock(&pvt->lock);
01687
01688 return res;
01689 }
01690
01691 static char *events[] = {
01692 "No event",
01693 "On hook",
01694 "Ring/Answered",
01695 "Wink/Flash",
01696 "Alarm",
01697 "No more alarm",
01698 "HDLC Abort",
01699 "HDLC Overrun",
01700 "HDLC Bad FCS",
01701 "Dial Complete",
01702 "Ringer On",
01703 "Ringer Off",
01704 "Hook Transition Complete",
01705 "Bits Changed",
01706 "Pulse Start",
01707 "Timer Expired",
01708 "Timer Ping",
01709 "Polarity Reversal",
01710 "Ring Begin",
01711 };
01712
01713 static struct {
01714 int alarm;
01715 char *name;
01716 } alarms[] = {
01717 { DAHDI_ALARM_RED, "Red Alarm" },
01718 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01719 { DAHDI_ALARM_BLUE, "Blue Alarm" },
01720 { DAHDI_ALARM_RECOVER, "Recovering" },
01721 { DAHDI_ALARM_LOOPBACK, "Loopback" },
01722 { DAHDI_ALARM_NOTOPEN, "Not Open" },
01723 { DAHDI_ALARM_NONE, "None" },
01724 };
01725
01726 static char *alarm2str(int alm)
01727 {
01728 int x;
01729 for (x = 0; x < ARRAY_LEN(alarms); x++) {
01730 if (alarms[x].alarm & alm)
01731 return alarms[x].name;
01732 }
01733 return alm ? "Unknown Alarm" : "No Alarm";
01734 }
01735
01736 static char *event2str(int event)
01737 {
01738 static char buf[256];
01739 if ((event < (ARRAY_LEN(events))) && (event > -1))
01740 return events[event];
01741 sprintf(buf, "Event %d", event);
01742 return buf;
01743 }
01744
01745 #ifdef HAVE_PRI
01746 static char *dialplan2str(int dialplan)
01747 {
01748 if (dialplan == -1 || dialplan == -2) {
01749 return("Dynamically set dialplan in ISDN");
01750 }
01751 return (pri_plan2str(dialplan));
01752 }
01753 #endif
01754
01755 static char *dahdi_sig2str(int sig)
01756 {
01757 static char buf[256];
01758 switch (sig) {
01759 case SIG_EM:
01760 return "E & M Immediate";
01761 case SIG_EMWINK:
01762 return "E & M Wink";
01763 case SIG_EM_E1:
01764 return "E & M E1";
01765 case SIG_FEATD:
01766 return "Feature Group D (DTMF)";
01767 case SIG_FEATDMF:
01768 return "Feature Group D (MF)";
01769 case SIG_FEATDMF_TA:
01770 return "Feature Groud D (MF) Tandem Access";
01771 case SIG_FEATB:
01772 return "Feature Group B (MF)";
01773 case SIG_E911:
01774 return "E911 (MF)";
01775 case SIG_FGC_CAMA:
01776 return "FGC/CAMA (Dialpulse)";
01777 case SIG_FGC_CAMAMF:
01778 return "FGC/CAMA (MF)";
01779 case SIG_FXSLS:
01780 return "FXS Loopstart";
01781 case SIG_FXSGS:
01782 return "FXS Groundstart";
01783 case SIG_FXSKS:
01784 return "FXS Kewlstart";
01785 case SIG_FXOLS:
01786 return "FXO Loopstart";
01787 case SIG_FXOGS:
01788 return "FXO Groundstart";
01789 case SIG_FXOKS:
01790 return "FXO Kewlstart";
01791 case SIG_PRI:
01792 return "ISDN PRI";
01793 case SIG_BRI:
01794 return "ISDN BRI Point to Point";
01795 case SIG_BRI_PTMP:
01796 return "ISDN BRI Point to MultiPoint";
01797 case SIG_SS7:
01798 return "SS7";
01799 case SIG_SF:
01800 return "SF (Tone) Immediate";
01801 case SIG_SFWINK:
01802 return "SF (Tone) Wink";
01803 case SIG_SF_FEATD:
01804 return "SF (Tone) with Feature Group D (DTMF)";
01805 case SIG_SF_FEATDMF:
01806 return "SF (Tone) with Feature Group D (MF)";
01807 case SIG_SF_FEATB:
01808 return "SF (Tone) with Feature Group B (MF)";
01809 case SIG_GR303FXOKS:
01810 return "GR-303 with FXOKS";
01811 case SIG_GR303FXSKS:
01812 return "GR-303 with FXSKS";
01813 case 0:
01814 return "Pseudo";
01815 default:
01816 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01817 return buf;
01818 }
01819 }
01820
01821 #define sig2str dahdi_sig2str
01822
01823 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
01824 {
01825
01826
01827 struct dahdi_confinfo zi;
01828
01829 memset(&zi, 0, sizeof(zi));
01830 zi.chan = 0;
01831
01832 if (slavechannel > 0) {
01833
01834 zi.confmode = DAHDI_CONF_DIGITALMON;
01835 zi.confno = slavechannel;
01836 } else {
01837 if (!idx) {
01838
01839 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01840 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01841 } else
01842 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01843 zi.confno = p->confno;
01844 }
01845 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01846 return 0;
01847 if (c->dfd < 0)
01848 return 0;
01849 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01850 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01851 return -1;
01852 }
01853 if (slavechannel < 1) {
01854 p->confno = zi.confno;
01855 }
01856 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01857 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01858 return 0;
01859 }
01860
01861 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01862 {
01863
01864 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01865 return 1;
01866
01867 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01868 return 1;
01869 return 0;
01870 }
01871
01872 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
01873 {
01874 struct dahdi_confinfo zi;
01875 if (
01876 (c->dfd < 0) ||
01877
01878 !isourconf(p, c)
01879
01880 ) return 0;
01881 memset(&zi, 0, sizeof(zi));
01882 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01883 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01884 return -1;
01885 }
01886 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01887 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01888 return 0;
01889 }
01890
01891 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01892 {
01893 int x;
01894 int useslavenative;
01895 struct dahdi_pvt *slave = NULL;
01896
01897 useslavenative = 1;
01898
01899 for (x = 0; x < 3; x++) {
01900
01901
01902 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01903 useslavenative = 0;
01904 }
01905
01906
01907 if (useslavenative) {
01908 for (x = 0; x < MAX_SLAVES; x++) {
01909 if (p->slaves[x]) {
01910 if (slave) {
01911
01912
01913 slave = NULL;
01914 useslavenative = 0;
01915 break;
01916 } else {
01917
01918 slave = p->slaves[x];
01919 }
01920 }
01921 }
01922 }
01923
01924 if (!slave)
01925 useslavenative = 0;
01926 else if (slave->law != p->law) {
01927 useslavenative = 0;
01928 slave = NULL;
01929 }
01930 if (out)
01931 *out = slave;
01932 return useslavenative;
01933 }
01934
01935 static int reset_conf(struct dahdi_pvt *p)
01936 {
01937 p->confno = -1;
01938 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01939 if (p->subs[SUB_REAL].dfd > -1) {
01940 struct dahdi_confinfo zi;
01941
01942 memset(&zi, 0, sizeof(zi));
01943 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01944 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01945 }
01946 return 0;
01947 }
01948
01949 static int update_conf(struct dahdi_pvt *p)
01950 {
01951 int needconf = 0;
01952 int x;
01953 int useslavenative;
01954 struct dahdi_pvt *slave = NULL;
01955
01956 useslavenative = isslavenative(p, &slave);
01957
01958 for (x = 0; x < 3; x++) {
01959
01960 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01961 conf_add(p, &p->subs[x], x, 0);
01962 needconf++;
01963 } else {
01964 conf_del(p, &p->subs[x], x);
01965 }
01966 }
01967
01968
01969 for (x = 0; x < MAX_SLAVES; x++) {
01970 if (p->slaves[x]) {
01971 if (useslavenative)
01972 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01973 else {
01974 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01975 needconf++;
01976 }
01977 }
01978 }
01979
01980 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01981 if (useslavenative)
01982 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01983 else {
01984 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01985 needconf++;
01986 }
01987 }
01988
01989 if (p->master) {
01990 if (isslavenative(p->master, NULL)) {
01991 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01992 } else {
01993 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01994 }
01995 }
01996 if (!needconf) {
01997
01998
01999 p->confno = -1;
02000 }
02001 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02002 return 0;
02003 }
02004
02005 static void dahdi_enable_ec(struct dahdi_pvt *p)
02006 {
02007 int x;
02008 int res;
02009 if (!p)
02010 return;
02011 if (p->echocanon) {
02012 ast_debug(1, "Echo cancellation already on\n");
02013 return;
02014 }
02015 if (p->digital) {
02016 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02017 return;
02018 }
02019 if (p->echocancel.head.tap_length) {
02020 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02021 x = 1;
02022 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02023 if (res)
02024 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02025 }
02026 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02027 if (res) {
02028 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02029 } else {
02030 p->echocanon = 1;
02031 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02032 }
02033 } else
02034 ast_debug(1, "No echo cancellation requested\n");
02035 }
02036
02037 static void dahdi_train_ec(struct dahdi_pvt *p)
02038 {
02039 int x;
02040 int res;
02041
02042 if (p && p->echocanon && p->echotraining) {
02043 x = p->echotraining;
02044 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02045 if (res)
02046 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02047 else
02048 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02049 } else {
02050 ast_debug(1, "No echo training requested\n");
02051 }
02052 }
02053
02054 static void dahdi_disable_ec(struct dahdi_pvt *p)
02055 {
02056 int res;
02057
02058 if (p->echocanon) {
02059 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02060
02061 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02062
02063 if (res)
02064 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02065 else
02066 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02067 }
02068
02069 p->echocanon = 0;
02070 }
02071
02072 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02073 {
02074 int j;
02075 int k;
02076 float linear_gain = pow(10.0, gain / 20.0);
02077
02078 switch (law) {
02079 case DAHDI_LAW_ALAW:
02080 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02081 if (gain) {
02082 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02083 if (k > 32767) k = 32767;
02084 if (k < -32767) k = -32767;
02085 g->txgain[j] = AST_LIN2A(k);
02086 } else {
02087 g->txgain[j] = j;
02088 }
02089 }
02090 break;
02091 case DAHDI_LAW_MULAW:
02092 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02093 if (gain) {
02094 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02095 if (k > 32767) k = 32767;
02096 if (k < -32767) k = -32767;
02097 g->txgain[j] = AST_LIN2MU(k);
02098 } else {
02099 g->txgain[j] = j;
02100 }
02101 }
02102 break;
02103 }
02104 }
02105
02106 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02107 {
02108 int j;
02109 int k;
02110 float linear_gain = pow(10.0, gain / 20.0);
02111
02112 switch (law) {
02113 case DAHDI_LAW_ALAW:
02114 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02115 if (gain) {
02116 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02117 if (k > 32767) k = 32767;
02118 if (k < -32767) k = -32767;
02119 g->rxgain[j] = AST_LIN2A(k);
02120 } else {
02121 g->rxgain[j] = j;
02122 }
02123 }
02124 break;
02125 case DAHDI_LAW_MULAW:
02126 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02127 if (gain) {
02128 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02129 if (k > 32767) k = 32767;
02130 if (k < -32767) k = -32767;
02131 g->rxgain[j] = AST_LIN2MU(k);
02132 } else {
02133 g->rxgain[j] = j;
02134 }
02135 }
02136 break;
02137 }
02138 }
02139
02140 static int set_actual_txgain(int fd, int chan, float gain, int law)
02141 {
02142 struct dahdi_gains g;
02143 int res;
02144
02145 memset(&g, 0, sizeof(g));
02146 g.chan = chan;
02147 res = ioctl(fd, DAHDI_GETGAINS, &g);
02148 if (res) {
02149 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02150 return res;
02151 }
02152
02153 fill_txgain(&g, gain, law);
02154
02155 return ioctl(fd, DAHDI_SETGAINS, &g);
02156 }
02157
02158 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02159 {
02160 struct dahdi_gains g;
02161 int res;
02162
02163 memset(&g, 0, sizeof(g));
02164 g.chan = chan;
02165 res = ioctl(fd, DAHDI_GETGAINS, &g);
02166 if (res) {
02167 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02168 return res;
02169 }
02170
02171 fill_rxgain(&g, gain, law);
02172
02173 return ioctl(fd, DAHDI_SETGAINS, &g);
02174 }
02175
02176 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02177 {
02178 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02179 }
02180
02181 static int bump_gains(struct dahdi_pvt *p)
02182 {
02183 int res;
02184
02185
02186 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02187 if (res) {
02188 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02189 return -1;
02190 }
02191
02192 return 0;
02193 }
02194
02195 static int restore_gains(struct dahdi_pvt *p)
02196 {
02197 int res;
02198
02199 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02200 if (res) {
02201 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02202 return -1;
02203 }
02204
02205 return 0;
02206 }
02207
02208 static inline int dahdi_set_hook(int fd, int hs)
02209 {
02210 int x, res;
02211
02212 x = hs;
02213 res = ioctl(fd, DAHDI_HOOK, &x);
02214
02215 if (res < 0) {
02216 if (errno == EINPROGRESS)
02217 return 0;
02218 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02219
02220 }
02221
02222 return res;
02223 }
02224
02225 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02226 {
02227 int x, y, res;
02228 x = muted;
02229 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02230 y = 1;
02231 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02232 if (res)
02233 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02234 }
02235 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02236 if (res < 0)
02237 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02238 return res;
02239 }
02240
02241 static int save_conference(struct dahdi_pvt *p)
02242 {
02243 struct dahdi_confinfo c;
02244 int res;
02245 if (p->saveconf.confmode) {
02246 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02247 return -1;
02248 }
02249 p->saveconf.chan = 0;
02250 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02251 if (res) {
02252 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02253 p->saveconf.confmode = 0;
02254 return -1;
02255 }
02256 memset(&c, 0, sizeof(c));
02257 c.confmode = DAHDI_CONF_NORMAL;
02258 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02259 if (res) {
02260 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02261 return -1;
02262 }
02263 ast_debug(1, "Disabled conferencing\n");
02264 return 0;
02265 }
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285 static void notify_message(char *mailbox_full, int thereornot)
02286 {
02287 char s[sizeof(mwimonitornotify) + 80];
02288 struct ast_event *event;
02289 char *mailbox, *context;
02290
02291
02292 context = mailbox = ast_strdupa(mailbox_full);
02293 strsep(&context, "@");
02294 if (ast_strlen_zero(context))
02295 context = "default";
02296
02297 if (!(event = ast_event_new(AST_EVENT_MWI,
02298 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02299 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02300 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02301 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02302 AST_EVENT_IE_END))) {
02303 return;
02304 }
02305
02306 ast_event_queue_and_cache(event);
02307
02308 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02309 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02310 ast_safe_system(s);
02311 }
02312 }
02313
02314 static int restore_conference(struct dahdi_pvt *p)
02315 {
02316 int res;
02317 if (p->saveconf.confmode) {
02318 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02319 p->saveconf.confmode = 0;
02320 if (res) {
02321 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02322 return -1;
02323 }
02324 }
02325 ast_debug(1, "Restored conferencing\n");
02326 return 0;
02327 }
02328
02329 static int send_callerid(struct dahdi_pvt *p);
02330
02331 static int send_cwcidspill(struct dahdi_pvt *p)
02332 {
02333 p->callwaitcas = 0;
02334 p->cidcwexpire = 0;
02335 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02336 return -1;
02337 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02338
02339 p->cidlen += READ_SIZE * 4;
02340 p->cidpos = 0;
02341 send_callerid(p);
02342 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02343 return 0;
02344 }
02345
02346 static int has_voicemail(struct dahdi_pvt *p)
02347 {
02348 int new_msgs;
02349 struct ast_event *event;
02350 char *mailbox, *context;
02351
02352 mailbox = context = ast_strdupa(p->mailbox);
02353 strsep(&context, "@");
02354 if (ast_strlen_zero(context))
02355 context = "default";
02356
02357 event = ast_event_get_cached(AST_EVENT_MWI,
02358 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02359 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02360 AST_EVENT_IE_END);
02361
02362 if (event) {
02363 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02364 ast_event_destroy(event);
02365 } else
02366 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02367
02368 return new_msgs;
02369 }
02370
02371 static int send_callerid(struct dahdi_pvt *p)
02372 {
02373
02374 int res;
02375
02376 if (p->subs[SUB_REAL].linear) {
02377 p->subs[SUB_REAL].linear = 0;
02378 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02379 }
02380 while (p->cidpos < p->cidlen) {
02381 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02382 if (res < 0) {
02383 if (errno == EAGAIN)
02384 return 0;
02385 else {
02386 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02387 return -1;
02388 }
02389 }
02390 if (!res)
02391 return 0;
02392 p->cidpos += res;
02393 }
02394 ast_free(p->cidspill);
02395 p->cidspill = NULL;
02396 if (p->callwaitcas) {
02397
02398 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02399 } else
02400 restore_conference(p);
02401 return 0;
02402 }
02403
02404 static int dahdi_callwait(struct ast_channel *ast)
02405 {
02406 struct dahdi_pvt *p = ast->tech_pvt;
02407 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02408 if (p->cidspill) {
02409 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02410 ast_free(p->cidspill);
02411 }
02412 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02413 return -1;
02414 save_conference(p);
02415
02416 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02417 if (!p->callwaitrings && p->callwaitingcallerid) {
02418 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02419 p->callwaitcas = 1;
02420 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02421 } else {
02422 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02423 p->callwaitcas = 0;
02424 p->cidlen = 2400 + READ_SIZE * 4;
02425 }
02426 p->cidpos = 0;
02427 send_callerid(p);
02428
02429 return 0;
02430 }
02431
02432 #ifdef HAVE_SS7
02433 static unsigned char cid_pres2ss7pres(int cid_pres)
02434 {
02435 return (cid_pres >> 5) & 0x03;
02436 }
02437
02438 static unsigned char cid_pres2ss7screen(int cid_pres)
02439 {
02440 return cid_pres & 0x03;
02441 }
02442 #endif
02443
02444 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02445 {
02446 struct dahdi_pvt *p = ast->tech_pvt;
02447 int x, res, idx,mysig;
02448 char *c, *n, *l;
02449 #ifdef HAVE_PRI
02450 char *s = NULL;
02451 #endif
02452 char dest[256];
02453 ast_mutex_lock(&p->lock);
02454 ast_copy_string(dest, rdest, sizeof(dest));
02455 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02456 if ((ast->_state == AST_STATE_BUSY)) {
02457 p->subs[SUB_REAL].needbusy = 1;
02458 ast_mutex_unlock(&p->lock);
02459 return 0;
02460 }
02461 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02462 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02463 ast_mutex_unlock(&p->lock);
02464 return -1;
02465 }
02466 p->dialednone = 0;
02467 if ((p->radio || (p->oprmode < 0)))
02468 {
02469
02470 ast_setstate(ast, AST_STATE_UP);
02471 ast_mutex_unlock(&p->lock);
02472 return 0;
02473 }
02474 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02475 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02476 if (res)
02477 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02478 p->outgoing = 1;
02479
02480 if (IS_DIGITAL(ast->transfercapability)){
02481 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02482 } else {
02483 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02484 }
02485
02486 mysig = p->sig;
02487 if (p->outsigmod > -1)
02488 mysig = p->outsigmod;
02489
02490 switch (mysig) {
02491 case SIG_FXOLS:
02492 case SIG_FXOGS:
02493 case SIG_FXOKS:
02494 if (p->owner == ast) {
02495
02496
02497
02498 p->dialing = 1;
02499 if (p->use_callerid) {
02500
02501 if (p->cidspill) {
02502 ast_log(LOG_WARNING, "cidspill already exists??\n");
02503 ast_free(p->cidspill);
02504 }
02505 p->callwaitcas = 0;
02506 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02507 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02508 p->cidpos = 0;
02509 send_callerid(p);
02510 }
02511 }
02512
02513 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02514 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02515 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02516 p->cidrings = cidrings[p->distinctivering - 1];
02517 } else {
02518 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02519 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02520 p->cidrings = p->sendcalleridafter;
02521 }
02522
02523
02524 c = strchr(dest, '/');
02525 if (c)
02526 c++;
02527 if (c && (strlen(c) < p->stripmsd)) {
02528 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02529 c = NULL;
02530 }
02531 if (c) {
02532 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02533 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02534 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
02535 } else {
02536 p->dop.dialstr[0] = '\0';
02537 }
02538 x = DAHDI_RING;
02539 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02540 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02541 ast_mutex_unlock(&p->lock);
02542 return -1;
02543 }
02544 p->dialing = 1;
02545 } else {
02546
02547 p->callwaitrings = 0;
02548 if (ast->cid.cid_num)
02549 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02550 else
02551 p->callwait_num[0] = '\0';
02552 if (ast->cid.cid_name)
02553 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02554 else
02555 p->callwait_name[0] = '\0';
02556
02557 if (dahdi_callwait(ast)) {
02558 ast_mutex_unlock(&p->lock);
02559 return -1;
02560 }
02561
02562 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02563 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02564
02565 }
02566 n = ast->cid.cid_name;
02567 l = ast->cid.cid_num;
02568 if (l)
02569 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02570 else
02571 p->lastcid_num[0] = '\0';
02572 if (n)
02573 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02574 else
02575 p->lastcid_name[0] = '\0';
02576 ast_setstate(ast, AST_STATE_RINGING);
02577 idx = dahdi_get_index(ast, p, 0);
02578 if (idx > -1) {
02579 p->subs[idx].needringing = 1;
02580 }
02581 break;
02582 case SIG_FXSLS:
02583 case SIG_FXSGS:
02584 case SIG_FXSKS:
02585 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02586 ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
02587 p->polaritydelaytv = ast_tvnow();
02588 }
02589
02590 case SIG_EMWINK:
02591 case SIG_EM:
02592 case SIG_EM_E1:
02593 case SIG_FEATD:
02594 case SIG_FEATDMF:
02595 case SIG_E911:
02596 case SIG_FGC_CAMA:
02597 case SIG_FGC_CAMAMF:
02598 case SIG_FEATB:
02599 case SIG_SFWINK:
02600 case SIG_SF:
02601 case SIG_SF_FEATD:
02602 case SIG_SF_FEATDMF:
02603 case SIG_FEATDMF_TA:
02604 case SIG_SF_FEATB:
02605 c = strchr(dest, '/');
02606 if (c)
02607 c++;
02608 else
02609 c = "";
02610 if (strlen(c) < p->stripmsd) {
02611 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02612 ast_mutex_unlock(&p->lock);
02613 return -1;
02614 }
02615 #ifdef HAVE_PRI
02616
02617 if (!p->pri) {
02618 #endif
02619 x = DAHDI_START;
02620 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02621 if (res < 0) {
02622 if (errno != EINPROGRESS) {
02623 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02624 ast_mutex_unlock(&p->lock);
02625 return -1;
02626 }
02627 }
02628 #ifdef HAVE_PRI
02629 }
02630 #endif
02631 ast_debug(1, "Dialing '%s'\n", c);
02632 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02633
02634 c += p->stripmsd;
02635
02636 switch (mysig) {
02637 case SIG_FEATD:
02638 l = ast->cid.cid_num;
02639 if (l)
02640 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02641 else
02642 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02643 break;
02644 case SIG_FEATDMF:
02645 l = ast->cid.cid_num;
02646 if (l)
02647 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02648 else
02649 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02650 break;
02651 case SIG_FEATDMF_TA:
02652 {
02653 const char *cic, *ozz;
02654
02655
02656 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02657 if (!ozz)
02658 ozz = defaultozz;
02659 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02660 if (!cic)
02661 cic = defaultcic;
02662 if (!ozz || !cic) {
02663 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02664 ast_mutex_unlock(&p->lock);
02665 return -1;
02666 }
02667 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02668 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02669 p->whichwink = 0;
02670 }
02671 break;
02672 case SIG_E911:
02673 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02674 break;
02675 case SIG_FGC_CAMA:
02676 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02677 break;
02678 case SIG_FGC_CAMAMF:
02679 case SIG_FEATB:
02680 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02681 break;
02682 default:
02683 if (p->pulse)
02684 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02685 else
02686 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02687 break;
02688 }
02689
02690 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02691 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02692 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02693 p->echorest[sizeof(p->echorest) - 1] = '\0';
02694 p->echobreak = 1;
02695 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02696 } else
02697 p->echobreak = 0;
02698 if (!res) {
02699 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02700 int saveerr = errno;
02701
02702 x = DAHDI_ONHOOK;
02703 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02704 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02705 ast_mutex_unlock(&p->lock);
02706 return -1;
02707 }
02708 } else
02709 ast_debug(1, "Deferring dialing...\n");
02710
02711 p->dialing = 1;
02712 if (ast_strlen_zero(c))
02713 p->dialednone = 1;
02714 ast_setstate(ast, AST_STATE_DIALING);
02715 break;
02716 case 0:
02717
02718 ast_setstate(ast, AST_STATE_UP);
02719 break;
02720 case SIG_PRI:
02721 case SIG_BRI:
02722 case SIG_BRI_PTMP:
02723 case SIG_SS7:
02724
02725 p->dialdest[0] = '\0';
02726 p->dialing = 1;
02727 break;
02728 default:
02729 ast_debug(1, "not yet implemented\n");
02730 ast_mutex_unlock(&p->lock);
02731 return -1;
02732 }
02733 #ifdef HAVE_SS7
02734 if (p->ss7) {
02735 char ss7_called_nai;
02736 int called_nai_strip;
02737 char ss7_calling_nai;
02738 int calling_nai_strip;
02739 const char *charge_str = NULL;
02740 const char *gen_address = NULL;
02741 const char *gen_digits = NULL;
02742 const char *gen_dig_type = NULL;
02743 const char *gen_dig_scheme = NULL;
02744 const char *gen_name = NULL;
02745 const char *jip_digits = NULL;
02746 const char *lspi_ident = NULL;
02747 const char *rlt_flag = NULL;
02748 const char *call_ref_id = NULL;
02749 const char *call_ref_pc = NULL;
02750 const char *send_far = NULL;
02751
02752 c = strchr(dest, '/');
02753 if (c) {
02754 c++;
02755 } else {
02756 c = "";
02757 }
02758 if (strlen(c) < p->stripmsd) {
02759 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02760 ast_mutex_unlock(&p->lock);
02761 return -1;
02762 }
02763
02764 if (!p->hidecallerid) {
02765 l = ast->cid.cid_num;
02766 } else {
02767 l = NULL;
02768 }
02769
02770 if (ss7_grab(p, p->ss7)) {
02771 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02772 ast_mutex_unlock(&p->lock);
02773 return -1;
02774 }
02775 p->digital = IS_DIGITAL(ast->transfercapability);
02776 p->ss7call = isup_new_call(p->ss7->ss7);
02777
02778 if (!p->ss7call) {
02779 ss7_rel(p->ss7);
02780 ast_mutex_unlock(&p->lock);
02781 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02782 return -1;
02783 }
02784
02785 called_nai_strip = 0;
02786 ss7_called_nai = p->ss7->called_nai;
02787 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
02788 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02789 called_nai_strip = strlen(p->ss7->internationalprefix);
02790 ss7_called_nai = SS7_NAI_INTERNATIONAL;
02791 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02792 called_nai_strip = strlen(p->ss7->nationalprefix);
02793 ss7_called_nai = SS7_NAI_NATIONAL;
02794 } else {
02795 ss7_called_nai = SS7_NAI_SUBSCRIBER;
02796 }
02797 }
02798 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02799
02800 calling_nai_strip = 0;
02801 ss7_calling_nai = p->ss7->calling_nai;
02802 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
02803 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02804 calling_nai_strip = strlen(p->ss7->internationalprefix);
02805 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02806 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02807 calling_nai_strip = strlen(p->ss7->nationalprefix);
02808 ss7_calling_nai = SS7_NAI_NATIONAL;
02809 } else {
02810 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02811 }
02812 }
02813 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02814 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02815 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02816
02817 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02818 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02819
02820 ast_channel_lock(ast);
02821
02822 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02823 if (charge_str)
02824 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02825
02826 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02827 if (gen_address)
02828 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);
02829
02830 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02831 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02832 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02833 if (gen_digits)
02834 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
02835
02836 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02837 if (gen_name)
02838 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02839
02840 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02841 if (jip_digits)
02842 isup_set_jip_digits(p->ss7call, jip_digits);
02843
02844 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02845 if (lspi_ident)
02846 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
02847
02848 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02849 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02850 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
02851 }
02852
02853 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02854 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02855 if (call_ref_id && call_ref_pc) {
02856 isup_set_callref(p->ss7call, atoi(call_ref_id),
02857 call_ref_pc ? atoi(call_ref_pc) : 0);
02858 }
02859
02860 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02861 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02862 (isup_far(p->ss7->ss7, p->ss7call));
02863
02864 ast_channel_unlock(ast);
02865
02866 isup_iam(p->ss7->ss7, p->ss7call);
02867 ast_setstate(ast, AST_STATE_DIALING);
02868 ss7_rel(p->ss7);
02869 }
02870 #endif
02871 #ifdef HAVE_PRI
02872 if (p->pri) {
02873 struct pri_sr *sr;
02874 #ifdef SUPPORT_USERUSER
02875 const char *useruser;
02876 #endif
02877 int pridialplan;
02878 int dp_strip;
02879 int prilocaldialplan;
02880 int ldp_strip;
02881 int exclusive;
02882 const char *rr_str;
02883 int redirect_reason;
02884
02885 c = strchr(dest, '/');
02886 if (c) {
02887 c++;
02888 } else {
02889 c = "";
02890 }
02891
02892 l = NULL;
02893 n = NULL;
02894 if (!p->hidecallerid) {
02895 l = ast->cid.cid_num;
02896 if (!p->hidecalleridname) {
02897 n = ast->cid.cid_name;
02898 }
02899 }
02900
02901 if (strlen(c) < p->stripmsd) {
02902 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02903 ast_mutex_unlock(&p->lock);
02904 return -1;
02905 }
02906 if (mysig != SIG_FXSKS) {
02907 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02908 s = strchr(c + p->stripmsd, 'w');
02909 if (s) {
02910 if (strlen(s) > 1)
02911 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02912 else
02913 p->dop.dialstr[0] = '\0';
02914 *s = '\0';
02915 } else {
02916 p->dop.dialstr[0] = '\0';
02917 }
02918 }
02919 if (pri_grab(p, p->pri)) {
02920 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02921 ast_mutex_unlock(&p->lock);
02922 return -1;
02923 }
02924 if (!(p->call = pri_new_call(p->pri->pri))) {
02925 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02926 pri_rel(p->pri);
02927 ast_mutex_unlock(&p->lock);
02928 return -1;
02929 }
02930 if (!(sr = pri_sr_new())) {
02931 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02932 pri_rel(p->pri);
02933 ast_mutex_unlock(&p->lock);
02934 }
02935 if (p->bearer || (mysig == SIG_FXSKS)) {
02936 if (p->bearer) {
02937 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02938 p->bearer->call = p->call;
02939 } else
02940 ast_debug(1, "I'm being setup with no bearer right now...\n");
02941
02942 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02943 }
02944 p->digital = IS_DIGITAL(ast->transfercapability);
02945
02946
02947 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
02948 exclusive = 1;
02949 } else {
02950 exclusive = 0;
02951 }
02952
02953 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02954 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02955 (p->digital ? -1 :
02956 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02957 if (p->pri->facilityenable)
02958 pri_facility_enable(p->pri->pri);
02959
02960 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02961 dp_strip = 0;
02962 pridialplan = p->pri->dialplan - 1;
02963 if (pridialplan == -2 || pridialplan == -3) {
02964 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02965 if (pridialplan == -2) {
02966 dp_strip = strlen(p->pri->internationalprefix);
02967 }
02968 pridialplan = PRI_INTERNATIONAL_ISDN;
02969 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02970 if (pridialplan == -2) {
02971 dp_strip = strlen(p->pri->nationalprefix);
02972 }
02973 pridialplan = PRI_NATIONAL_ISDN;
02974 } else {
02975 pridialplan = PRI_LOCAL_ISDN;
02976 }
02977 }
02978 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02979 switch (c[p->stripmsd]) {
02980 case 'U':
02981 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02982 break;
02983 case 'I':
02984 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
02985 break;
02986 case 'N':
02987 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
02988 break;
02989 case 'L':
02990 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
02991 break;
02992 case 'S':
02993 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
02994 break;
02995 case 'V':
02996 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
02997 break;
02998 case 'R':
02999 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03000 break;
03001 case 'u':
03002 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03003 break;
03004 case 'e':
03005 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03006 break;
03007 case 'x':
03008 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03009 break;
03010 case 'f':
03011 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03012 break;
03013 case 'n':
03014 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03015 break;
03016 case 'p':
03017 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03018 break;
03019 case 'r':
03020 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03021 break;
03022 default:
03023 if (isalpha(c[p->stripmsd])) {
03024 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03025 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03026 }
03027 break;
03028 }
03029 c++;
03030 }
03031 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03032
03033 ldp_strip = 0;
03034 prilocaldialplan = p->pri->localdialplan - 1;
03035 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03036 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03037 if (prilocaldialplan == -2) {
03038 ldp_strip = strlen(p->pri->internationalprefix);
03039 }
03040 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03041 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03042 if (prilocaldialplan == -2) {
03043 ldp_strip = strlen(p->pri->nationalprefix);
03044 }
03045 prilocaldialplan = PRI_NATIONAL_ISDN;
03046 } else {
03047 prilocaldialplan = PRI_LOCAL_ISDN;
03048 }
03049 }
03050 if (l != NULL) {
03051 while (*l > '9' && *l != '*' && *l != '#') {
03052 switch (*l) {
03053 case 'U':
03054 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03055 break;
03056 case 'I':
03057 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03058 break;
03059 case 'N':
03060 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03061 break;
03062 case 'L':
03063 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03064 break;
03065 case 'S':
03066 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03067 break;
03068 case 'V':
03069 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03070 break;
03071 case 'R':
03072 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03073 break;
03074 case 'u':
03075 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03076 break;
03077 case 'e':
03078 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03079 break;
03080 case 'x':
03081 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03082 break;
03083 case 'f':
03084 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03085 break;
03086 case 'n':
03087 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03088 break;
03089 case 'p':
03090 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03091 break;
03092 case 'r':
03093 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03094 break;
03095 default:
03096 if (isalpha(*l)) {
03097 ast_log(LOG_WARNING,
03098 "Unrecognized prilocaldialplan %s modifier: %c\n",
03099 *l > 'Z' ? "NPI" : "TON", *l);
03100 }
03101 break;
03102 }
03103 l++;
03104 }
03105 }
03106 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03107 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03108 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03109 if (!strcasecmp(rr_str, "UNKNOWN"))
03110 redirect_reason = 0;
03111 else if (!strcasecmp(rr_str, "BUSY"))
03112 redirect_reason = 1;
03113 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03114
03115 redirect_reason = 2;
03116 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03117 redirect_reason = 15;
03118 else
03119 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03120 } else
03121 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03122 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03123
03124 #ifdef SUPPORT_USERUSER
03125
03126 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03127
03128 if (useruser)
03129 pri_sr_set_useruser(sr, useruser);
03130 #endif
03131
03132 if (pri_setup(p->pri->pri, p->call, sr)) {
03133 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03134 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03135 pri_rel(p->pri);
03136 ast_mutex_unlock(&p->lock);
03137 pri_sr_free(sr);
03138 return -1;
03139 }
03140 pri_sr_free(sr);
03141 ast_setstate(ast, AST_STATE_DIALING);
03142 pri_rel(p->pri);
03143 }
03144 #endif
03145 ast_mutex_unlock(&p->lock);
03146 return 0;
03147 }
03148
03149 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03150 {
03151 struct dahdi_pvt *p = *pvt;
03152
03153 if (p->prev)
03154 p->prev->next = p->next;
03155 if (p->next)
03156 p->next->prev = p->prev;
03157 if (p->use_smdi)
03158 ast_smdi_interface_unref(p->smdi_iface);
03159 if (p->mwi_event_sub)
03160 ast_event_unsubscribe(p->mwi_event_sub);
03161 if (p->vars) {
03162 ast_variables_destroy(p->vars);
03163 }
03164 ast_mutex_destroy(&p->lock);
03165 dahdi_close_sub(p, SUB_REAL);
03166 if (p->owner)
03167 p->owner->tech_pvt = NULL;
03168 free(p);
03169 *pvt = NULL;
03170 }
03171
03172 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03173 {
03174 int owned = 0;
03175 int i = 0;
03176
03177 if (!now) {
03178 if (cur->owner) {
03179 owned = 1;
03180 }
03181
03182 for (i = 0; i < 3; i++) {
03183 if (cur->subs[i].owner) {
03184 owned = 1;
03185 }
03186 }
03187 if (!owned) {
03188 if (prev) {
03189 prev->next = cur->next;
03190 if (prev->next)
03191 prev->next->prev = prev;
03192 else
03193 ifend = prev;
03194 } else {
03195 iflist = cur->next;
03196 if (iflist)
03197 iflist->prev = NULL;
03198 else
03199 ifend = NULL;
03200 }
03201 destroy_dahdi_pvt(&cur);
03202 }
03203 } else {
03204 if (prev) {
03205 prev->next = cur->next;
03206 if (prev->next)
03207 prev->next->prev = prev;
03208 else
03209 ifend = prev;
03210 } else {
03211 iflist = cur->next;
03212 if (iflist)
03213 iflist->prev = NULL;
03214 else
03215 ifend = NULL;
03216 }
03217 destroy_dahdi_pvt(&cur);
03218 }
03219 return 0;
03220 }
03221
03222 static void destroy_all_channels(void)
03223 {
03224 int x;
03225 struct dahdi_pvt *p, *pl;
03226
03227 while (num_restart_pending) {
03228 usleep(1);
03229 }
03230
03231 ast_mutex_lock(&iflock);
03232
03233 p = iflist;
03234 while (p) {
03235
03236 if (p->cidspill)
03237 ast_free(p->cidspill);
03238 pl = p;
03239 p = p->next;
03240 x = pl->channel;
03241
03242 if (pl)
03243 destroy_dahdi_pvt(&pl);
03244 if (option_verbose > 2)
03245 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03246 }
03247 iflist = NULL;
03248 ifcount = 0;
03249 ast_mutex_unlock(&iflock);
03250 }
03251
03252 #ifdef HAVE_PRI
03253 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03254
03255 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03256
03257 static char *dahdi_send_keypad_facility_descrip =
03258 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03259 " IE over the current channel.\n";
03260
03261 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03262 {
03263
03264 struct dahdi_pvt *p;
03265 char *digits = (char *) data;
03266
03267 if (ast_strlen_zero(digits)) {
03268 ast_debug(1, "No digit string sent to application!\n");
03269 return -1;
03270 }
03271
03272 p = (struct dahdi_pvt *)chan->tech_pvt;
03273
03274 if (!p) {
03275 ast_debug(1, "Unable to find technology private\n");
03276 return -1;
03277 }
03278
03279 ast_mutex_lock(&p->lock);
03280
03281 if (!p->pri || !p->call) {
03282 ast_debug(1, "Unable to find pri or call on channel!\n");
03283 ast_mutex_unlock(&p->lock);
03284 return -1;
03285 }
03286
03287 if (!pri_grab(p, p->pri)) {
03288 pri_keypad_facility(p->pri->pri, p->call, digits);
03289 pri_rel(p->pri);
03290 } else {
03291 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03292 ast_mutex_unlock(&p->lock);
03293 return -1;
03294 }
03295
03296 ast_mutex_unlock(&p->lock);
03297
03298 return 0;
03299 }
03300
03301 static int pri_is_up(struct dahdi_pri *pri)
03302 {
03303 int x;
03304 for (x = 0; x < NUM_DCHANS; x++) {
03305 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03306 return 1;
03307 }
03308 return 0;
03309 }
03310
03311 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03312 {
03313 bearer->owner = &inuse;
03314 bearer->realcall = crv;
03315 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03316 if (crv->subs[SUB_REAL].owner)
03317 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03318 crv->bearer = bearer;
03319 crv->call = bearer->call;
03320 crv->pri = pri;
03321 return 0;
03322 }
03323
03324 static char *pri_order(int level)
03325 {
03326 switch (level) {
03327 case 0:
03328 return "Primary";
03329 case 1:
03330 return "Secondary";
03331 case 2:
03332 return "Tertiary";
03333 case 3:
03334 return "Quaternary";
03335 default:
03336 return "<Unknown>";
03337 }
03338 }
03339
03340
03341 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03342 {
03343 int x = -1;
03344
03345 for (x = 0; x < NUM_DCHANS; x++) {
03346 if ((pri->dchans[x] == pri->pri))
03347 break;
03348 }
03349
03350 return pri->fds[x];
03351 }
03352
03353 static int pri_find_dchan(struct dahdi_pri *pri)
03354 {
03355 int oldslot = -1;
03356 struct pri *old;
03357 int newslot = -1;
03358 int x;
03359 old = pri->pri;
03360 for (x = 0; x < NUM_DCHANS; x++) {
03361 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03362 newslot = x;
03363 if (pri->dchans[x] == old) {
03364 oldslot = x;
03365 }
03366 }
03367 if (newslot < 0) {
03368 newslot = 0;
03369 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03370 pri->dchannels[newslot]);
03371 }
03372 if (old && (oldslot != newslot))
03373 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03374 pri->dchannels[oldslot], pri->dchannels[newslot]);
03375 pri->pri = pri->dchans[newslot];
03376 return 0;
03377 }
03378 #endif
03379
03380 static int dahdi_hangup(struct ast_channel *ast)
03381 {
03382 int res;
03383 int idx,x, law;
03384
03385 struct dahdi_pvt *p = ast->tech_pvt;
03386 struct dahdi_pvt *tmp = NULL;
03387 struct dahdi_pvt *prev = NULL;
03388 struct dahdi_params par;
03389
03390 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03391 if (!ast->tech_pvt) {
03392 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03393 return 0;
03394 }
03395
03396 ast_mutex_lock(&p->lock);
03397
03398 idx = dahdi_get_index(ast, p, 1);
03399
03400 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03401 x = 1;
03402 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03403 p->cid_num[0] = '\0';
03404 p->cid_name[0] = '\0';
03405 }
03406
03407 x = 0;
03408 dahdi_confmute(p, 0);
03409 p->muting = 0;
03410 restore_gains(p);
03411 if (p->origcid_num) {
03412 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03413 ast_free(p->origcid_num);
03414 p->origcid_num = NULL;
03415 }
03416 if (p->origcid_name) {
03417 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03418 ast_free(p->origcid_name);
03419 p->origcid_name = NULL;
03420 }
03421 if (p->dsp)
03422 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03423 p->exten[0] = '\0';
03424
03425 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03426 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03427 p->ignoredtmf = 0;
03428
03429 if (idx > -1) {
03430
03431 p->subs[idx].owner = NULL;
03432 p->subs[idx].needanswer = 0;
03433 p->subs[idx].needflash = 0;
03434 p->subs[idx].needringing = 0;
03435 p->subs[idx].needbusy = 0;
03436 p->subs[idx].needcongestion = 0;
03437 p->subs[idx].linear = 0;
03438 p->subs[idx].needcallerid = 0;
03439 p->polarity = POLARITY_IDLE;
03440 dahdi_setlinear(p->subs[idx].dfd, 0);
03441 if (idx == SUB_REAL) {
03442 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03443 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03444 if (p->subs[SUB_CALLWAIT].inthreeway) {
03445
03446 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03447
03448 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03449 unalloc_sub(p, SUB_CALLWAIT);
03450 p->owner = NULL;
03451 } else {
03452
03453 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03454 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03455 unalloc_sub(p, SUB_THREEWAY);
03456 if (p->subs[SUB_REAL].inthreeway) {
03457
03458
03459 ast_debug(1, "Call was complete, setting owner to former third call\n");
03460 p->owner = p->subs[SUB_REAL].owner;
03461 } else {
03462
03463 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03464 p->owner = NULL;
03465 }
03466 p->subs[SUB_REAL].inthreeway = 0;
03467 }
03468 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03469
03470 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03471 unalloc_sub(p, SUB_CALLWAIT);
03472 p->owner = p->subs[SUB_REAL].owner;
03473 if (p->owner->_state != AST_STATE_UP)
03474 p->subs[SUB_REAL].needanswer = 1;
03475 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03476 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03477 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03478 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03479 unalloc_sub(p, SUB_THREEWAY);
03480 if (p->subs[SUB_REAL].inthreeway) {
03481
03482
03483 ast_debug(1, "Call was complete, setting owner to former third call\n");
03484 p->owner = p->subs[SUB_REAL].owner;
03485 } else {
03486
03487 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03488 p->owner = NULL;
03489 }
03490 p->subs[SUB_REAL].inthreeway = 0;
03491 }
03492 } else if (idx == SUB_CALLWAIT) {
03493
03494 if (p->subs[SUB_CALLWAIT].inthreeway) {
03495
03496
03497 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03498 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03499 S_OR(p->mohsuggest, NULL),
03500 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03501 }
03502 p->subs[SUB_THREEWAY].inthreeway = 0;
03503
03504 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03505 unalloc_sub(p, SUB_THREEWAY);
03506 } else
03507 unalloc_sub(p, SUB_CALLWAIT);
03508 } else if (idx == SUB_THREEWAY) {
03509 if (p->subs[SUB_CALLWAIT].inthreeway) {
03510
03511
03512 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03513 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03514 S_OR(p->mohsuggest, NULL),
03515 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03516 }
03517 p->subs[SUB_CALLWAIT].inthreeway = 0;
03518 }
03519 p->subs[SUB_REAL].inthreeway = 0;
03520
03521
03522 unalloc_sub(p, SUB_THREEWAY);
03523 } else {
03524
03525 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03526 }
03527 }
03528
03529 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03530 p->owner = NULL;
03531 p->ringt = 0;
03532 p->distinctivering = 0;
03533 p->confirmanswer = 0;
03534 p->cidrings = 1;
03535 p->outgoing = 0;
03536 p->digital = 0;
03537 p->faxhandled = 0;
03538 p->pulsedial = 0;
03539 p->onhooktime = time(NULL);
03540 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03541 p->proceeding = 0;
03542 p->dialing = 0;
03543 p->progress = 0;
03544 p->alerting = 0;
03545 p->setup_ack = 0;
03546 p->rlt = 0;
03547 #endif
03548 if (p->dsp) {
03549 ast_dsp_free(p->dsp);
03550 p->dsp = NULL;
03551 }
03552
03553 law = DAHDI_LAW_DEFAULT;
03554 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03555 if (res < 0)
03556 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03557
03558 #ifdef HAVE_SS7
03559 if (p->ss7) {
03560 if (p->ss7call) {
03561 if (!ss7_grab(p, p->ss7)) {
03562 if (!p->alreadyhungup) {
03563 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03564 int icause = ast->hangupcause ? ast->hangupcause : -1;
03565
03566 if (cause) {
03567 if (atoi(cause))
03568 icause = atoi(cause);
03569 }
03570 isup_rel(p->ss7->ss7, p->ss7call, icause);
03571 ss7_rel(p->ss7);
03572 p->alreadyhungup = 1;
03573 } else
03574 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03575 } else {
03576 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03577 res = -1;
03578 }
03579 }
03580 }
03581 #endif
03582 #ifdef HAVE_PRI
03583 if (p->pri) {
03584 #ifdef SUPPORT_USERUSER
03585 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03586 #endif
03587
03588
03589 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03590 if (!pri_grab(p, p->pri)) {
03591 if (p->alreadyhungup) {
03592 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
03593
03594 #ifdef SUPPORT_USERUSER
03595 pri_call_set_useruser(p->call, useruser);
03596 #endif
03597
03598 pri_hangup(p->pri->pri, p->call, -1);
03599 p->call = NULL;
03600 if (p->bearer)
03601 p->bearer->call = NULL;
03602 } else {
03603 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03604 int icause = ast->hangupcause ? ast->hangupcause : -1;
03605 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03606
03607 #ifdef SUPPORT_USERUSER
03608 pri_call_set_useruser(p->call, useruser);
03609 #endif
03610
03611 p->alreadyhungup = 1;
03612 if (p->bearer)
03613 p->bearer->alreadyhungup = 1;
03614 if (cause) {
03615 if (atoi(cause))
03616 icause = atoi(cause);
03617 }
03618 pri_hangup(p->pri->pri, p->call, icause);
03619 }
03620 if (res < 0)
03621 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03622 pri_rel(p->pri);
03623 } else {
03624 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03625 res = -1;
03626 }
03627 } else {
03628 if (p->bearer)
03629 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03630 p->call = NULL;
03631 res = 0;
03632 }
03633 }
03634 #endif
03635 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03636 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03637 if (res < 0) {
03638 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03639 }
03640 switch (p->sig) {
03641 case SIG_FXOGS:
03642 case SIG_FXOLS:
03643 case SIG_FXOKS:
03644 memset(&par, 0, sizeof(par));
03645 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03646 if (!res) {
03647 #if 0
03648 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03649 #endif
03650
03651 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03652 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03653 else
03654 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03655 }
03656 break;
03657 case SIG_FXSGS:
03658 case SIG_FXSLS:
03659 case SIG_FXSKS:
03660
03661
03662 if (ast->_state != AST_STATE_RESERVED) {
03663 time(&p->guardtime);
03664 p->guardtime += 2;
03665 }
03666 break;
03667 default:
03668 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03669 }
03670 if (p->cidspill)
03671 ast_free(p->cidspill);
03672 if (p->sig)
03673 dahdi_disable_ec(p);
03674 x = 0;
03675 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03676 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03677 p->didtdd = 0;
03678 p->cidspill = NULL;
03679 p->callwaitcas = 0;
03680 p->callwaiting = p->permcallwaiting;
03681 p->hidecallerid = p->permhidecallerid;
03682 p->dialing = 0;
03683 p->rdnis[0] = '\0';
03684 update_conf(p);
03685 reset_conf(p);
03686
03687 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03688 x = 0;
03689 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03690 }
03691 #ifdef HAVE_PRI
03692 if (p->bearer) {
03693 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03694
03695
03696 update_conf(p->bearer);
03697 reset_conf(p->bearer);
03698 p->bearer->owner = NULL;
03699 p->bearer->realcall = NULL;
03700 p->bearer = NULL;
03701 p->subs[SUB_REAL].dfd = -1;
03702 p->pri = NULL;
03703 }
03704 #endif
03705 if (num_restart_pending == 0)
03706 restart_monitor();
03707 }
03708
03709 p->callwaitingrepeat = 0;
03710 p->cidcwexpire = 0;
03711 p->oprmode = 0;
03712 ast->tech_pvt = NULL;
03713 ast_mutex_unlock(&p->lock);
03714 ast_module_unref(ast_module_info->self);
03715 ast_verb(3, "Hungup '%s'\n", ast->name);
03716
03717 ast_mutex_lock(&iflock);
03718
03719 if (p->restartpending) {
03720 num_restart_pending--;
03721 }
03722
03723 tmp = iflist;
03724 prev = NULL;
03725 if (p->destroy) {
03726 while (tmp) {
03727 if (tmp == p) {
03728 destroy_channel(prev, tmp, 0);
03729 break;
03730 } else {
03731 prev = tmp;
03732 tmp = tmp->next;
03733 }
03734 }
03735 }
03736 ast_mutex_unlock(&iflock);
03737 return 0;
03738 }
03739
03740 static int dahdi_answer(struct ast_channel *ast)
03741 {
03742 struct dahdi_pvt *p = ast->tech_pvt;
03743 int res = 0;
03744 int idx;
03745 int oldstate = ast->_state;
03746 ast_setstate(ast, AST_STATE_UP);
03747 ast_mutex_lock(&p->lock);
03748 idx = dahdi_get_index(ast, p, 0);
03749 if (idx < 0)
03750 idx = SUB_REAL;
03751
03752 if ((p->radio || (p->oprmode < 0))) {
03753 ast_mutex_unlock(&p->lock);
03754 return 0;
03755 }
03756 switch (p->sig) {
03757 case SIG_FXSLS:
03758 case SIG_FXSGS:
03759 case SIG_FXSKS:
03760 p->ringt = 0;
03761
03762 case SIG_EM:
03763 case SIG_EM_E1:
03764 case SIG_EMWINK:
03765 case SIG_FEATD:
03766 case SIG_FEATDMF:
03767 case SIG_FEATDMF_TA:
03768 case SIG_E911:
03769 case SIG_FGC_CAMA:
03770 case SIG_FGC_CAMAMF:
03771 case SIG_FEATB:
03772 case SIG_SF:
03773 case SIG_SFWINK:
03774 case SIG_SF_FEATD:
03775 case SIG_SF_FEATDMF:
03776 case SIG_SF_FEATB:
03777 case SIG_FXOLS:
03778 case SIG_FXOGS:
03779 case SIG_FXOKS:
03780
03781 ast_debug(1, "Took %s off hook\n", ast->name);
03782 if (p->hanguponpolarityswitch) {
03783 p->polaritydelaytv = ast_tvnow();
03784 }
03785 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03786 tone_zone_play_tone(p->subs[idx].dfd, -1);
03787 p->dialing = 0;
03788 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03789 if (oldstate == AST_STATE_RINGING) {
03790 ast_debug(1, "Finally swapping real and threeway\n");
03791 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03792 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03793 p->owner = p->subs[SUB_REAL].owner;
03794 }
03795 }
03796 if (p->sig & __DAHDI_SIG_FXS) {
03797 dahdi_enable_ec(p);
03798 dahdi_train_ec(p);
03799 }
03800 break;
03801 #ifdef HAVE_PRI
03802 case SIG_BRI:
03803 case SIG_BRI_PTMP:
03804 case SIG_PRI:
03805
03806 if (!pri_grab(p, p->pri)) {
03807 p->proceeding = 1;
03808 p->dialing = 0;
03809 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03810 pri_rel(p->pri);
03811 } else {
03812 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03813 res = -1;
03814 }
03815 break;
03816 #endif
03817 #ifdef HAVE_SS7
03818 case SIG_SS7:
03819 if (!ss7_grab(p, p->ss7)) {
03820 p->proceeding = 1;
03821 res = isup_anm(p->ss7->ss7, p->ss7call);
03822 ss7_rel(p->ss7);
03823 } else {
03824 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03825 res = -1;
03826 }
03827 break;
03828 #endif
03829 case 0:
03830 ast_mutex_unlock(&p->lock);
03831 return 0;
03832 default:
03833 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03834 res = -1;
03835 }
03836 ast_mutex_unlock(&p->lock);
03837 return res;
03838 }
03839
03840 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03841 {
03842 char *cp;
03843 signed char *scp;
03844 int x;
03845 int idx;
03846 struct dahdi_pvt *p = chan->tech_pvt, *pp;
03847 struct oprmode *oprmode;
03848
03849
03850
03851 if (!data || (datalen < 1)) {
03852 errno = EINVAL;
03853 return -1;
03854 }
03855
03856 switch (option) {
03857 case AST_OPTION_TXGAIN:
03858 scp = (signed char *) data;
03859 idx = dahdi_get_index(chan, p, 0);
03860 if (idx < 0) {
03861 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03862 return -1;
03863 }
03864 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03865 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
03866 case AST_OPTION_RXGAIN:
03867 scp = (signed char *) data;
03868 idx = dahdi_get_index(chan, p, 0);
03869 if (idx < 0) {
03870 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03871 return -1;
03872 }
03873 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03874 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
03875 case AST_OPTION_TONE_VERIFY:
03876 if (!p->dsp)
03877 break;
03878 cp = (char *) data;
03879 switch (*cp) {
03880 case 1:
03881 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03882 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
03883 break;
03884 case 2:
03885 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03886 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
03887 break;
03888 default:
03889 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03890 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03891 break;
03892 }
03893 break;
03894 case AST_OPTION_TDD:
03895
03896 cp = (char *) data;
03897 p->mate = 0;
03898 if (!*cp) {
03899 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03900 if (p->tdd)
03901 tdd_free(p->tdd);
03902 p->tdd = 0;
03903 break;
03904 }
03905 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03906 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03907 dahdi_disable_ec(p);
03908
03909 if (!p->didtdd) {
03910 unsigned char mybuf[41000];
03911 unsigned char *buf;
03912 int size, res, fd, len;
03913 struct pollfd fds[1];
03914
03915 buf = mybuf;
03916 memset(buf, 0x7f, sizeof(mybuf));
03917 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03918 len = 40000;
03919 idx = dahdi_get_index(chan, p, 0);
03920 if (idx < 0) {
03921 ast_log(LOG_WARNING, "No index in TDD?\n");
03922 return -1;
03923 }
03924 fd = p->subs[idx].dfd;
03925 while (len) {
03926 if (ast_check_hangup(chan))
03927 return -1;
03928 size = len;
03929 if (size > READ_SIZE)
03930 size = READ_SIZE;
03931 fds[0].fd = fd;
03932 fds[0].events = POLLPRI | POLLOUT;
03933 fds[0].revents = 0;
03934 res = poll(fds, 1, -1);
03935 if (!res) {
03936 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03937 continue;
03938 }
03939
03940 if (fds[0].revents & POLLPRI)
03941 return -1;
03942 if (!(fds[0].revents & POLLOUT)) {
03943 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03944 continue;
03945 }
03946 res = write(fd, buf, size);
03947 if (res != size) {
03948 if (res == -1) return -1;
03949 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03950 break;
03951 }
03952 len -= size;
03953 buf += size;
03954 }
03955 p->didtdd = 1;
03956 }
03957 if (*cp == 2) {
03958 if (p->tdd)
03959 tdd_free(p->tdd);
03960 p->tdd = 0;
03961 p->mate = 1;
03962 break;
03963 }
03964 if (!p->tdd) {
03965 p->tdd = tdd_new();
03966 }
03967 break;
03968 case AST_OPTION_RELAXDTMF:
03969 if (!p->dsp)
03970 break;
03971 cp = (char *) data;
03972 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03973 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03974 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03975 break;
03976 case AST_OPTION_AUDIO_MODE:
03977 cp = (char *) data;
03978 if (!*cp) {
03979 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03980 x = 0;
03981 dahdi_disable_ec(p);
03982 } else {
03983 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03984 x = 1;
03985 }
03986 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03987 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03988 break;
03989 case AST_OPTION_OPRMODE:
03990 oprmode = (struct oprmode *) data;
03991 pp = oprmode->peer->tech_pvt;
03992 p->oprmode = pp->oprmode = 0;
03993
03994 p->oprpeer = pp;
03995 pp->oprpeer = p;
03996
03997 if (oprmode->mode)
03998 {
03999 pp->oprmode = oprmode->mode;
04000 p->oprmode = -oprmode->mode;
04001 }
04002 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
04003 oprmode->mode, chan->name,oprmode->peer->name);
04004 break;
04005 case AST_OPTION_ECHOCAN:
04006 cp = (char *) data;
04007 if (*cp) {
04008 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
04009 dahdi_enable_ec(p);
04010 } else {
04011 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
04012 dahdi_disable_ec(p);
04013 }
04014 break;
04015 }
04016 errno = 0;
04017
04018 return 0;
04019 }
04020
04021 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
04022 {
04023 struct dahdi_pvt *p = chan->tech_pvt;
04024
04025 if (!strcasecmp(data, "rxgain")) {
04026 ast_mutex_lock(&p->lock);
04027 snprintf(buf, len, "%f", p->rxgain);
04028 ast_mutex_unlock(&p->lock);
04029 } else if (!strcasecmp(data, "txgain")) {
04030 ast_mutex_lock(&p->lock);
04031 snprintf(buf, len, "%f", p->txgain);
04032 ast_mutex_unlock(&p->lock);
04033 } else {
04034 ast_copy_string(buf, "", len);
04035 }
04036 return 0;
04037 }
04038
04039
04040 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04041 {
04042
04043 int x;
04044 int hasslaves;
04045 if (!master)
04046 return;
04047 if (needlock) {
04048 ast_mutex_lock(&master->lock);
04049 if (slave) {
04050 while (ast_mutex_trylock(&slave->lock)) {
04051 DEADLOCK_AVOIDANCE(&master->lock);
04052 }
04053 }
04054 }
04055 hasslaves = 0;
04056 for (x = 0; x < MAX_SLAVES; x++) {
04057 if (master->slaves[x]) {
04058 if (!slave || (master->slaves[x] == slave)) {
04059
04060 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04061 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04062 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04063 master->slaves[x]->master = NULL;
04064 master->slaves[x] = NULL;
04065 } else
04066 hasslaves = 1;
04067 }
04068 if (!hasslaves)
04069 master->inconference = 0;
04070 }
04071 if (!slave) {
04072 if (master->master) {
04073
04074 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04075 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04076 hasslaves = 0;
04077 for (x = 0; x < MAX_SLAVES; x++) {
04078 if (master->master->slaves[x] == master)
04079 master->master->slaves[x] = NULL;
04080 else if (master->master->slaves[x])
04081 hasslaves = 1;
04082 }
04083 if (!hasslaves)
04084 master->master->inconference = 0;
04085 }
04086 master->master = NULL;
04087 }
04088 update_conf(master);
04089 if (needlock) {
04090 if (slave)
04091 ast_mutex_unlock(&slave->lock);
04092 ast_mutex_unlock(&master->lock);
04093 }
04094 }
04095
04096 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04097 int x;
04098 if (!slave || !master) {
04099 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04100 return;
04101 }
04102 for (x = 0; x < MAX_SLAVES; x++) {
04103 if (!master->slaves[x]) {
04104 master->slaves[x] = slave;
04105 break;
04106 }
04107 }
04108 if (x >= MAX_SLAVES) {
04109 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04110 master->slaves[MAX_SLAVES - 1] = slave;
04111 }
04112 if (slave->master)
04113 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04114 slave->master = master;
04115
04116 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04117 }
04118
04119 static void disable_dtmf_detect(struct dahdi_pvt *p)
04120 {
04121 int val;
04122
04123 p->ignoredtmf = 1;
04124
04125 val = 0;
04126 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04127
04128 if (!p->hardwaredtmf && p->dsp) {
04129 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
04130 ast_dsp_set_features(p->dsp, p->dsp_features);
04131 }
04132 }
04133
04134 static void enable_dtmf_detect(struct dahdi_pvt *p)
04135 {
04136 int val;
04137
04138 if (p->channel == CHAN_PSEUDO)
04139 return;
04140
04141 p->ignoredtmf = 0;
04142
04143 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04144 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04145
04146 if (!p->hardwaredtmf && p->dsp) {
04147 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
04148 ast_dsp_set_features(p->dsp, p->dsp_features);
04149 }
04150 }
04151
04152 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)
04153 {
04154 struct ast_channel *who;
04155 struct dahdi_pvt *p0, *p1, *op0, *op1;
04156 struct dahdi_pvt *master = NULL, *slave = NULL;
04157 struct ast_frame *f;
04158 int inconf = 0;
04159 int nothingok = 1;
04160 int ofd0, ofd1;
04161 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04162 int os0 = -1, os1 = -1;
04163 int priority = 0;
04164 struct ast_channel *oc0, *oc1;
04165 enum ast_bridge_result res;
04166
04167 #ifdef PRI_2BCT
04168 int triedtopribridge = 0;
04169 q931_call *q931c0 = NULL, *q931c1 = NULL;
04170 #endif
04171
04172
04173
04174
04175
04176
04177 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04178 return AST_BRIDGE_FAILED_NOWARN;
04179
04180 ast_channel_lock(c0);
04181 while (ast_channel_trylock(c1)) {
04182 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04183 }
04184
04185 p0 = c0->tech_pvt;
04186 p1 = c1->tech_pvt;
04187
04188 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04189 ast_channel_unlock(c0);
04190 ast_channel_unlock(c1);
04191 return AST_BRIDGE_FAILED_NOWARN;
04192 }
04193
04194 oi0 = dahdi_get_index(c0, p0, 0);
04195 oi1 = dahdi_get_index(c1, p1, 0);
04196 if ((oi0 < 0) || (oi1 < 0)) {
04197 ast_channel_unlock(c0);
04198 ast_channel_unlock(c1);
04199 return AST_BRIDGE_FAILED;
04200 }
04201
04202 op0 = p0 = c0->tech_pvt;
04203 op1 = p1 = c1->tech_pvt;
04204 ofd0 = c0->fds[0];
04205 ofd1 = c1->fds[0];
04206 oc0 = p0->owner;
04207 oc1 = p1->owner;
04208
04209 if (ast_mutex_trylock(&p0->lock)) {
04210
04211 ast_channel_unlock(c0);
04212 ast_channel_unlock(c1);
04213 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04214 return AST_BRIDGE_RETRY;
04215 }
04216 if (ast_mutex_trylock(&p1->lock)) {
04217
04218 ast_mutex_unlock(&p0->lock);
04219 ast_channel_unlock(c0);
04220 ast_channel_unlock(c1);
04221 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04222 return AST_BRIDGE_RETRY;
04223 }
04224
04225 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04226 if (p0->owner && p1->owner) {
04227
04228 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04229 master = p0;
04230 slave = p1;
04231 inconf = 1;
04232 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04233 master = p1;
04234 slave = p0;
04235 inconf = 1;
04236 } else {
04237 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04238 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04239 p0->channel,
04240 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04241 p0->subs[SUB_REAL].inthreeway, p0->channel,
04242 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04243 p1->subs[SUB_REAL].inthreeway);
04244 }
04245 nothingok = 0;
04246 }
04247 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04248 if (p1->subs[SUB_THREEWAY].inthreeway) {
04249 master = p1;
04250 slave = p0;
04251 nothingok = 0;
04252 }
04253 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04254 if (p0->subs[SUB_THREEWAY].inthreeway) {
04255 master = p0;
04256 slave = p1;
04257 nothingok = 0;
04258 }
04259 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04260
04261
04262 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04263 master = p1;
04264 slave = p0;
04265 nothingok = 0;
04266 }
04267 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04268
04269 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04270 master = p0;
04271 slave = p1;
04272 nothingok = 0;
04273 }
04274 }
04275 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04276 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04277 if (master && slave) {
04278
04279
04280
04281 if ((oi1 == SUB_THREEWAY) &&
04282 p1->subs[SUB_THREEWAY].inthreeway &&
04283 p1->subs[SUB_REAL].owner &&
04284 p1->subs[SUB_REAL].inthreeway &&
04285 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04286 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04287 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04288 os1 = p1->subs[SUB_REAL].owner->_state;
04289 } else {
04290 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04291 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04292 }
04293 if ((oi0 == SUB_THREEWAY) &&
04294 p0->subs[SUB_THREEWAY].inthreeway &&
04295 p0->subs[SUB_REAL].owner &&
04296 p0->subs[SUB_REAL].inthreeway &&
04297 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04298 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04299 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04300 os0 = p0->subs[SUB_REAL].owner->_state;
04301 } else {
04302 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04303 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04304 }
04305 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04306 if (!p0->echocanbridged || !p1->echocanbridged) {
04307
04308 dahdi_disable_ec(p0);
04309 dahdi_disable_ec(p1);
04310 }
04311 }
04312 dahdi_link(slave, master);
04313 master->inconference = inconf;
04314 } else if (!nothingok)
04315 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04316
04317 update_conf(p0);
04318 update_conf(p1);
04319 t0 = p0->subs[SUB_REAL].inthreeway;
04320 t1 = p1->subs[SUB_REAL].inthreeway;
04321
04322 ast_mutex_unlock(&p0->lock);
04323 ast_mutex_unlock(&p1->lock);
04324
04325 ast_channel_unlock(c0);
04326 ast_channel_unlock(c1);
04327
04328
04329 if ((!master || !slave) && !nothingok) {
04330 dahdi_enable_ec(p0);
04331 dahdi_enable_ec(p1);
04332 return AST_BRIDGE_FAILED;
04333 }
04334
04335 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04336
04337 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04338 disable_dtmf_detect(op0);
04339
04340 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04341 disable_dtmf_detect(op1);
04342
04343 for (;;) {
04344 struct ast_channel *c0_priority[2] = {c0, c1};
04345 struct ast_channel *c1_priority[2] = {c1, c0};
04346
04347
04348
04349
04350 ast_channel_lock(c0);
04351 while (ast_channel_trylock(c1)) {
04352 CHANNEL_DEADLOCK_AVOIDANCE(c0);
04353 }
04354
04355 p0 = c0->tech_pvt;
04356 p1 = c1->tech_pvt;
04357
04358 if (op0 == p0)
04359 i0 = dahdi_get_index(c0, p0, 1);
04360 if (op1 == p1)
04361 i1 = dahdi_get_index(c1, p1, 1);
04362
04363 ast_channel_unlock(c0);
04364 ast_channel_unlock(c1);
04365
04366 if (!timeoutms ||
04367 (op0 != p0) ||
04368 (op1 != p1) ||
04369 (ofd0 != c0->fds[0]) ||
04370 (ofd1 != c1->fds[0]) ||
04371 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04372 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04373 (oc0 != p0->owner) ||
04374 (oc1 != p1->owner) ||
04375 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04376 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04377 (oi0 != i0) ||
04378 (oi1 != i1)) {
04379 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04380 op0->channel, oi0, op1->channel, oi1);
04381 res = AST_BRIDGE_RETRY;
04382 goto return_from_bridge;
04383 }
04384
04385 #ifdef PRI_2BCT
04386 q931c0 = p0->call;
04387 q931c1 = p1->call;
04388 if (p0->transfer && p1->transfer
04389 && q931c0 && q931c1
04390 && !triedtopribridge) {
04391 pri_channel_bridge(q931c0, q931c1);
04392 triedtopribridge = 1;
04393 }
04394 #endif
04395
04396 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04397 if (!who) {
04398 ast_debug(1, "Ooh, empty read...\n");
04399 continue;
04400 }
04401 f = ast_read(who);
04402 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04403 *fo = f;
04404 *rc = who;
04405 res = AST_BRIDGE_COMPLETE;
04406 goto return_from_bridge;
04407 }
04408 if (f->frametype == AST_FRAME_DTMF) {
04409 if ((who == c0) && p0->pulsedial) {
04410 ast_write(c1, f);
04411 } else if ((who == c1) && p1->pulsedial) {
04412 ast_write(c0, f);
04413 } else {
04414 *fo = f;
04415 *rc = who;
04416 res = AST_BRIDGE_COMPLETE;
04417 goto return_from_bridge;
04418 }
04419 }
04420 ast_frfree(f);
04421
04422
04423 priority = !priority;
04424 }
04425
04426 return_from_bridge:
04427 if (op0 == p0)
04428 dahdi_enable_ec(p0);
04429
04430 if (op1 == p1)
04431 dahdi_enable_ec(p1);
04432
04433 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04434 enable_dtmf_detect(op0);
04435
04436 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04437 enable_dtmf_detect(op1);
04438
04439 dahdi_unlink(slave, master, 1);
04440
04441 return res;
04442 }
04443
04444 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04445 {
04446 struct dahdi_pvt *p = newchan->tech_pvt;
04447 int x;
04448 ast_mutex_lock(&p->lock);
04449 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04450 if (p->owner == oldchan) {
04451 p->owner = newchan;
04452 }
04453 for (x = 0; x < 3; x++)
04454 if (p->subs[x].owner == oldchan) {
04455 if (!x)
04456 dahdi_unlink(NULL, p, 0);
04457 p->subs[x].owner = newchan;
04458 }
04459 if (newchan->_state == AST_STATE_RINGING)
04460 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04461 update_conf(p);
04462 ast_mutex_unlock(&p->lock);
04463 return 0;
04464 }
04465
04466 static int dahdi_ring_phone(struct dahdi_pvt *p)
04467 {
04468 int x;
04469 int res;
04470
04471 x = 0;
04472 x = DAHDI_ONHOOK;
04473 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04474 do {
04475 x = DAHDI_RING;
04476 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04477 if (res) {
04478 switch (errno) {
04479 case EBUSY:
04480 case EINTR:
04481
04482 usleep(10000);
04483 continue;
04484 case EINPROGRESS:
04485 res = 0;
04486 break;
04487 default:
04488 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04489 res = 0;
04490 }
04491 }
04492 } while (res);
04493 return res;
04494 }
04495
04496 static void *ss_thread(void *data);
04497
04498 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
04499
04500 static int attempt_transfer(struct dahdi_pvt *p)
04501 {
04502
04503
04504
04505 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04506
04507
04508 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04509 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04510 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04511 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04512 }
04513 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04514 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04515 }
04516 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04517 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04518 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04519 return -1;
04520 }
04521
04522 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04523 unalloc_sub(p, SUB_THREEWAY);
04524 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04525 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04526 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04527 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04528 }
04529 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04530 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04531 }
04532 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04533 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04534 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04535 return -1;
04536 }
04537
04538 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04539 ast_channel_unlock(p->subs[SUB_REAL].owner);
04540 unalloc_sub(p, SUB_THREEWAY);
04541
04542 return 1;
04543 } else {
04544 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04545 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04546 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04547 return -1;
04548 }
04549 return 0;
04550 }
04551
04552 static int check_for_conference(struct dahdi_pvt *p)
04553 {
04554 struct dahdi_confinfo ci;
04555
04556 if (p->master || (p->confno > -1))
04557 return 0;
04558 memset(&ci, 0, sizeof(ci));
04559 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04560 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04561 return 0;
04562 }
04563
04564
04565
04566 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04567 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04568 return 1;
04569 }
04570 return 0;
04571 }
04572
04573
04574
04575
04576
04577
04578 static int get_alarms(struct dahdi_pvt *p)
04579 {
04580 int res;
04581 struct dahdi_spaninfo zi;
04582 struct dahdi_params params;
04583
04584 memset(&zi, 0, sizeof(zi));
04585 zi.spanno = p->span;
04586
04587 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04588 if (zi.alarms != DAHDI_ALARM_NONE)
04589 return zi.alarms;
04590 } else {
04591 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04592 return 0;
04593 }
04594
04595
04596 memset(¶ms, 0, sizeof(params));
04597 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04598 return params.chan_alarms;
04599
04600 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04601
04602 return DAHDI_ALARM_NONE;
04603 }
04604
04605 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
04606 {
04607 struct dahdi_pvt *p = ast->tech_pvt;
04608 struct ast_frame *f = *dest;
04609
04610 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04611
04612 if (p->confirmanswer) {
04613 ast_debug(1, "Confirm answer on %s!\n", ast->name);
04614
04615
04616 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04617 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04618 *dest = &p->subs[idx].f;
04619
04620 p->confirmanswer = 0;
04621 } else if (p->callwaitcas) {
04622 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04623 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04624 if (p->cidspill)
04625 ast_free(p->cidspill);
04626 send_cwcidspill(p);
04627 }
04628 p->callwaitcas = 0;
04629 p->subs[idx].f.frametype = AST_FRAME_NULL;
04630 p->subs[idx].f.subclass = 0;
04631 *dest = &p->subs[idx].f;
04632 } else if (f->subclass == 'f') {
04633
04634 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04635 p->faxhandled = 1;
04636 if (strcmp(ast->exten, "fax")) {
04637 const char *target_context = S_OR(ast->macrocontext, ast->context);
04638
04639
04640
04641
04642
04643 ast_mutex_unlock(&p->lock);
04644 ast_channel_unlock(ast);
04645 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04646 ast_channel_lock(ast);
04647 ast_mutex_lock(&p->lock);
04648 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04649
04650 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04651 if (ast_async_goto(ast, target_context, "fax", 1))
04652 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04653 } else {
04654 ast_channel_lock(ast);
04655 ast_mutex_lock(&p->lock);
04656 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04657 }
04658 } else {
04659 ast_debug(1, "Already in a fax extension, not redirecting\n");
04660 }
04661 } else {
04662 ast_debug(1, "Fax already handled\n");
04663 }
04664 dahdi_confmute(p, 0);
04665 p->subs[idx].f.frametype = AST_FRAME_NULL;
04666 p->subs[idx].f.subclass = 0;
04667 *dest = &p->subs[idx].f;
04668 }
04669 }
04670
04671 static void handle_alarms(struct dahdi_pvt *p, int alms)
04672 {
04673 const char *alarm_str = alarm2str(alms);
04674
04675 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04676 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04677 "Alarm: %s\r\n"
04678 "Channel: %d\r\n",
04679 alarm_str, p->channel);
04680 }
04681
04682 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04683 {
04684 int res, x;
04685 int idx, mysig;
04686 char *c;
04687 struct dahdi_pvt *p = ast->tech_pvt;
04688 pthread_t threadid;
04689 struct ast_channel *chan;
04690 struct ast_frame *f;
04691
04692 idx = dahdi_get_index(ast, p, 0);
04693 mysig = p->sig;
04694 if (p->outsigmod > -1)
04695 mysig = p->outsigmod;
04696 p->subs[idx].f.frametype = AST_FRAME_NULL;
04697 p->subs[idx].f.subclass = 0;
04698 p->subs[idx].f.datalen = 0;
04699 p->subs[idx].f.samples = 0;
04700 p->subs[idx].f.mallocd = 0;
04701 p->subs[idx].f.offset = 0;
04702 p->subs[idx].f.src = "dahdi_handle_event";
04703 p->subs[idx].f.data.ptr = NULL;
04704 f = &p->subs[idx].f;
04705
04706 if (idx < 0)
04707 return &p->subs[idx].f;
04708 if (p->fake_event) {
04709 res = p->fake_event;
04710 p->fake_event = 0;
04711 } else
04712 res = dahdi_get_event(p->subs[idx].dfd);
04713
04714 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
04715
04716 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04717 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04718 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04719 #ifdef HAVE_PRI
04720 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04721
04722 } else {
04723 #endif
04724 dahdi_confmute(p, 0);
04725 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
04726 p->subs[idx].f.subclass = res & 0xff;
04727 #ifdef HAVE_PRI
04728 }
04729 #endif
04730 dahdi_handle_dtmfup(ast, idx, &f);
04731 return f;
04732 }
04733
04734 if (res & DAHDI_EVENT_DTMFDOWN) {
04735 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04736
04737 dahdi_confmute(p, 1);
04738 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
04739 p->subs[idx].f.subclass = res & 0xff;
04740 return &p->subs[idx].f;
04741 }
04742
04743 switch (res) {
04744 case DAHDI_EVENT_EC_DISABLED:
04745 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04746 p->echocanon = 0;
04747 break;
04748 case DAHDI_EVENT_BITSCHANGED:
04749 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
04750 case DAHDI_EVENT_PULSE_START:
04751
04752 if (!ast->pbx)
04753 tone_zone_play_tone(p->subs[idx].dfd, -1);
04754 break;
04755 case DAHDI_EVENT_DIALCOMPLETE:
04756 if (p->inalarm) break;
04757 if ((p->radio || (p->oprmode < 0))) break;
04758 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
04759 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04760 return NULL;
04761 }
04762 if (!x) {
04763 dahdi_enable_ec(p);
04764 if (p->echobreak) {
04765 dahdi_train_ec(p);
04766 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04767 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04768 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04769 p->echobreak = 0;
04770 } else {
04771 p->dialing = 0;
04772 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04773
04774 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04775 ast_setstate(ast, AST_STATE_UP);
04776 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04777 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04778 break;
04779 } else {
04780
04781 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04782 }
04783 }
04784 if (ast->_state == AST_STATE_DIALING) {
04785 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04786 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04787 } 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)))) {
04788 ast_setstate(ast, AST_STATE_RINGING);
04789 } else if (!p->answeronpolarityswitch) {
04790 ast_setstate(ast, AST_STATE_UP);
04791 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04792 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04793
04794 p->polarity = POLARITY_REV;
04795 } else {
04796
04797 p->polarity = POLARITY_IDLE;
04798 }
04799 }
04800 }
04801 }
04802 break;
04803 case DAHDI_EVENT_ALARM:
04804 #ifdef HAVE_PRI
04805 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04806 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04807
04808 if (p->call) {
04809 if (p->pri && p->pri->pri) {
04810 if (!pri_grab(p, p->pri)) {
04811 pri_hangup(p->pri->pri, p->call, -1);
04812 pri_destroycall(p->pri->pri, p->call);
04813 p->call = NULL;
04814 pri_rel(p->pri);
04815 } else
04816 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04817 } else
04818 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04819 }
04820 if (p->owner)
04821 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04822 }
04823 }
04824 if (p->bearer)
04825 p->bearer->inalarm = 1;
04826 else
04827 #endif
04828 p->inalarm = 1;
04829 res = get_alarms(p);
04830 handle_alarms(p, res);
04831 #ifdef HAVE_PRI
04832 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04833
04834 } else {
04835 break;
04836 }
04837 #endif
04838 #ifdef HAVE_SS7
04839 if (p->sig == SIG_SS7)
04840 break;
04841 #endif
04842 case DAHDI_EVENT_ONHOOK:
04843 if (p->radio) {
04844 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04845 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
04846 break;
04847 }
04848 if (p->oprmode < 0)
04849 {
04850 if (p->oprmode != -1) break;
04851 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04852 {
04853
04854 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04855 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04856 save_conference(p->oprpeer);
04857 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04858 }
04859 break;
04860 }
04861 switch (p->sig) {
04862 case SIG_FXOLS:
04863 case SIG_FXOGS:
04864 case SIG_FXOKS:
04865 p->onhooktime = time(NULL);
04866 p->msgstate = -1;
04867
04868 if (idx == SUB_REAL) {
04869
04870 if (p->subs[SUB_CALLWAIT].owner) {
04871
04872 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04873 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04874 unalloc_sub(p, SUB_CALLWAIT);
04875 #if 0
04876 p->subs[idx].needanswer = 0;
04877 p->subs[idx].needringing = 0;
04878 #endif
04879 p->callwaitingrepeat = 0;
04880 p->cidcwexpire = 0;
04881 p->owner = NULL;
04882
04883 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04884 p->dialing = 1;
04885 dahdi_ring_phone(p);
04886 } else if (p->subs[SUB_THREEWAY].owner) {
04887 unsigned int mssinceflash;
04888
04889
04890 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04891
04892 DLA_UNLOCK(&p->lock);
04893 CHANNEL_DEADLOCK_AVOIDANCE(ast);
04894
04895
04896
04897 DLA_LOCK(&p->lock);
04898 if (p->owner != ast) {
04899 ast_log(LOG_WARNING, "This isn't good...\n");
04900 return NULL;
04901 }
04902 }
04903 if (!p->subs[SUB_THREEWAY].owner) {
04904 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04905 return NULL;
04906 }
04907 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04908 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04909 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04910
04911
04912 if (p->subs[SUB_THREEWAY].owner)
04913 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
04914 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04915 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04916 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04917 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04918 if (p->transfer) {
04919
04920 p->subs[SUB_REAL].inthreeway = 0;
04921 p->subs[SUB_THREEWAY].inthreeway = 0;
04922
04923 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04924 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04925
04926 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04927 p->owner = NULL;
04928
04929 dahdi_ring_phone(p);
04930 } else {
04931 if ((res = attempt_transfer(p)) < 0) {
04932 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04933 if (p->subs[SUB_THREEWAY].owner)
04934 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04935 } else if (res) {
04936
04937 if (p->subs[SUB_THREEWAY].owner)
04938 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04939 break;
04940 }
04941 }
04942 } else {
04943 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04944 if (p->subs[SUB_THREEWAY].owner)
04945 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04946 }
04947 } else {
04948 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04949
04950 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04951 p->owner = NULL;
04952
04953 dahdi_ring_phone(p);
04954 }
04955 }
04956 } else {
04957 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
04958 }
04959
04960 default:
04961 dahdi_disable_ec(p);
04962 return NULL;
04963 }
04964 break;
04965 case DAHDI_EVENT_RINGOFFHOOK:
04966 if (p->inalarm) break;
04967 if (p->oprmode < 0)
04968 {
04969 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04970 {
04971
04972 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04973 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04974 restore_conference(p->oprpeer);
04975 }
04976 break;
04977 }
04978 if (p->radio)
04979 {
04980 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04981 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
04982 break;
04983 }
04984
04985
04986 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04987 c = strchr(p->dialdest, '/');
04988 if (c)
04989 c++;
04990 else
04991 c = p->dialdest;
04992 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04993 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04994 if (strlen(p->dop.dialstr) > 4) {
04995 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04996 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04997 p->echorest[sizeof(p->echorest) - 1] = '\0';
04998 p->echobreak = 1;
04999 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05000 } else
05001 p->echobreak = 0;
05002 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05003 int saveerr = errno;
05004
05005 x = DAHDI_ONHOOK;
05006 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05007 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05008 return NULL;
05009 }
05010 p->dialing = 1;
05011 return &p->subs[idx].f;
05012 }
05013 switch (p->sig) {
05014 case SIG_FXOLS:
05015 case SIG_FXOGS:
05016 case SIG_FXOKS:
05017 switch (ast->_state) {
05018 case AST_STATE_RINGING:
05019 dahdi_enable_ec(p);
05020 dahdi_train_ec(p);
05021 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05022 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05023
05024 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05025 ast_debug(1, "channel %d answered\n", p->channel);
05026 if (p->cidspill) {
05027
05028 ast_free(p->cidspill);
05029 p->cidspill = NULL;
05030 }
05031 p->dialing = 0;
05032 p->callwaitcas = 0;
05033 if (p->confirmanswer) {
05034
05035 p->subs[idx].f.frametype = AST_FRAME_NULL;
05036 p->subs[idx].f.subclass = 0;
05037 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05038
05039 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05040 if (res < 0) {
05041 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05042 p->dop.dialstr[0] = '\0';
05043 return NULL;
05044 } else {
05045 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05046 p->subs[idx].f.frametype = AST_FRAME_NULL;
05047 p->subs[idx].f.subclass = 0;
05048 p->dialing = 1;
05049 }
05050 p->dop.dialstr[0] = '\0';
05051 ast_setstate(ast, AST_STATE_DIALING);
05052 } else
05053 ast_setstate(ast, AST_STATE_UP);
05054 return &p->subs[idx].f;
05055 case AST_STATE_DOWN:
05056 ast_setstate(ast, AST_STATE_RING);
05057 ast->rings = 1;
05058 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05059 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
05060 ast_debug(1, "channel %d picked up\n", p->channel);
05061 return &p->subs[idx].f;
05062 case AST_STATE_UP:
05063
05064 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05065
05066 if (ast_bridged_channel(p->owner))
05067 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05068 p->subs[idx].needunhold = 1;
05069 break;
05070 case AST_STATE_RESERVED:
05071
05072 if (has_voicemail(p))
05073 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05074 else
05075 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05076 break;
05077 default:
05078 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05079 }
05080 break;
05081 case SIG_FXSLS:
05082 case SIG_FXSGS:
05083 case SIG_FXSKS:
05084 if (ast->_state == AST_STATE_RING) {
05085 p->ringt = p->ringt_base;
05086 }
05087
05088
05089
05090 ast_debug(1, "Setting IDLE polarity due "
05091 "to ring. Old polarity was %d\n",
05092 p->polarity);
05093 p->polarity = POLARITY_IDLE;
05094
05095
05096 case SIG_EM:
05097 case SIG_EM_E1:
05098 case SIG_EMWINK:
05099 case SIG_FEATD:
05100 case SIG_FEATDMF:
05101 case SIG_FEATDMF_TA:
05102 case SIG_E911:
05103 case SIG_FGC_CAMA:
05104 case SIG_FGC_CAMAMF:
05105 case SIG_FEATB:
05106 case SIG_SF:
05107 case SIG_SFWINK:
05108 case SIG_SF_FEATD:
05109 case SIG_SF_FEATDMF:
05110 case SIG_SF_FEATB:
05111 if (ast->_state == AST_STATE_PRERING)
05112 ast_setstate(ast, AST_STATE_RING);
05113 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05114 ast_debug(1, "Ring detected\n");
05115 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05116 p->subs[idx].f.subclass = AST_CONTROL_RING;
05117 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05118 ast_debug(1, "Line answered\n");
05119 if (p->confirmanswer) {
05120 p->subs[idx].f.frametype = AST_FRAME_NULL;
05121 p->subs[idx].f.subclass = 0;
05122 } else {
05123 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05124 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05125 ast_setstate(ast, AST_STATE_UP);
05126 }
05127 } else if (ast->_state != AST_STATE_RING)
05128 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05129 break;
05130 default:
05131 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05132 }
05133 break;
05134 case DAHDI_EVENT_RINGBEGIN:
05135 switch (p->sig) {
05136 case SIG_FXSLS:
05137 case SIG_FXSGS:
05138 case SIG_FXSKS:
05139 if (ast->_state == AST_STATE_RING) {
05140 p->ringt = p->ringt_base;
05141 }
05142 break;
05143 }
05144 break;
05145 case DAHDI_EVENT_RINGEROFF:
05146 if (p->inalarm) break;
05147 if ((p->radio || (p->oprmode < 0))) break;
05148 ast->rings++;
05149 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05150 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05151 ast_free(p->cidspill);
05152 p->cidspill = NULL;
05153 p->callwaitcas = 0;
05154 }
05155 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05156 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05157 break;
05158 case DAHDI_EVENT_RINGERON:
05159 break;
05160 case DAHDI_EVENT_NOALARM:
05161 p->inalarm = 0;
05162 #ifdef HAVE_PRI
05163
05164 if (p->bearer)
05165 p->bearer->inalarm = 0;
05166 #endif
05167 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05168 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05169 "Channel: %d\r\n", p->channel);
05170 break;
05171 case DAHDI_EVENT_WINKFLASH:
05172 if (p->inalarm) break;
05173 if (p->radio) break;
05174 if (p->oprmode < 0) break;
05175 if (p->oprmode > 1)
05176 {
05177 struct dahdi_params par;
05178
05179 memset(&par, 0, sizeof(par));
05180 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05181 {
05182 if (!par.rxisoffhook)
05183 {
05184
05185 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05186 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05187 save_conference(p);
05188 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05189 }
05190 }
05191 break;
05192 }
05193
05194 p->flashtime = ast_tvnow();
05195 switch (mysig) {
05196 case SIG_FXOLS:
05197 case SIG_FXOGS:
05198 case SIG_FXOKS:
05199 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05200 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05201 p->callwaitcas = 0;
05202
05203 if (idx != SUB_REAL) {
05204 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
05205 goto winkflashdone;
05206 }
05207
05208 if (p->subs[SUB_CALLWAIT].owner) {
05209
05210 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05211 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05212 p->owner = p->subs[SUB_REAL].owner;
05213 ast_debug(1, "Making %s the new owner\n", p->owner->name);
05214 if (p->owner->_state == AST_STATE_RINGING) {
05215 ast_setstate(p->owner, AST_STATE_UP);
05216 p->subs[SUB_REAL].needanswer = 1;
05217 }
05218 p->callwaitingrepeat = 0;
05219 p->cidcwexpire = 0;
05220
05221 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05222 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05223 S_OR(p->mohsuggest, NULL),
05224 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05225 }
05226 p->subs[SUB_CALLWAIT].needhold = 1;
05227 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05228 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05229 S_OR(p->mohsuggest, NULL),
05230 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05231 }
05232 p->subs[SUB_REAL].needunhold = 1;
05233 } else if (!p->subs[SUB_THREEWAY].owner) {
05234 if (!p->threewaycalling) {
05235
05236 p->subs[SUB_REAL].needflash = 1;
05237 goto winkflashdone;
05238 } else if (!check_for_conference(p)) {
05239 char cid_num[256];
05240 char cid_name[256];
05241
05242 cid_num[0] = 0;
05243 cid_name[0] = 0;
05244 if (p->dahditrcallerid && p->owner) {
05245 if (p->owner->cid.cid_num)
05246 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05247 if (p->owner->cid.cid_name)
05248 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05249 }
05250
05251
05252 if (!((ast->pbx) ||
05253 (ast->_state == AST_STATE_UP) ||
05254 (ast->_state == AST_STATE_RING))) {
05255 ast_debug(1, "Flash when call not up or ringing\n");
05256 goto winkflashdone;
05257 }
05258 if (alloc_sub(p, SUB_THREEWAY)) {
05259 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05260 goto winkflashdone;
05261 }
05262
05263 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05264 if (p->dahditrcallerid) {
05265 if (!p->origcid_num)
05266 p->origcid_num = ast_strdup(p->cid_num);
05267 if (!p->origcid_name)
05268 p->origcid_name = ast_strdup(p->cid_name);
05269 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05270 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05271 }
05272
05273 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05274
05275 dahdi_disable_ec(p);
05276 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05277 if (res)
05278 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05279 p->owner = chan;
05280 if (!chan) {
05281 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05282 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05283 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05284 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05285 dahdi_enable_ec(p);
05286 ast_hangup(chan);
05287 } else {
05288 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05289 int way3bridge = 0, cdr3way = 0;
05290
05291 if (!other) {
05292 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05293 } else
05294 way3bridge = 1;
05295
05296 if (p->subs[SUB_THREEWAY].owner->cdr)
05297 cdr3way = 1;
05298
05299 ast_verb(3, "Started three way call on channel %d\n", p->channel);
05300
05301
05302 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05303 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05304 S_OR(p->mohsuggest, NULL),
05305 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05306 }
05307 p->subs[SUB_THREEWAY].needhold = 1;
05308 }
05309 }
05310 } else {
05311
05312 if (p->subs[SUB_THREEWAY].inthreeway) {
05313
05314 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05315
05316 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05317
05318 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05319 p->owner = p->subs[SUB_REAL].owner;
05320 }
05321
05322 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05323 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05324 p->subs[SUB_REAL].inthreeway = 0;
05325 p->subs[SUB_THREEWAY].inthreeway = 0;
05326 } else {
05327
05328 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05329 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05330 int otherindex = SUB_THREEWAY;
05331 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05332 int way3bridge = 0, cdr3way = 0;
05333
05334 if (!other) {
05335 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05336 } else
05337 way3bridge = 1;
05338
05339 if (p->subs[SUB_THREEWAY].owner->cdr)
05340 cdr3way = 1;
05341
05342 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05343
05344 p->subs[SUB_THREEWAY].inthreeway = 1;
05345 p->subs[SUB_REAL].inthreeway = 1;
05346 if (ast->_state == AST_STATE_UP) {
05347 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05348 otherindex = SUB_REAL;
05349 }
05350 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05351 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05352 p->subs[otherindex].needunhold = 1;
05353 p->owner = p->subs[SUB_REAL].owner;
05354 if (ast->_state == AST_STATE_RINGING) {
05355 ast_debug(1, "Enabling ringtone on real and threeway\n");
05356 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05357 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05358 }
05359 } else {
05360 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05361 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05362 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05363 p->owner = p->subs[SUB_REAL].owner;
05364 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05365 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05366 p->subs[SUB_REAL].needunhold = 1;
05367 dahdi_enable_ec(p);
05368 }
05369
05370 }
05371 }
05372 winkflashdone:
05373 update_conf(p);
05374 break;
05375 case SIG_EM:
05376 case SIG_EM_E1:
05377 case SIG_FEATD:
05378 case SIG_SF:
05379 case SIG_SFWINK:
05380 case SIG_SF_FEATD:
05381 case SIG_FXSLS:
05382 case SIG_FXSGS:
05383 if (option_debug) {
05384 if (p->dialing)
05385 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05386 else
05387 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05388 }
05389 break;
05390 case SIG_FEATDMF_TA:
05391 switch (p->whichwink) {
05392 case 0:
05393 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05394 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05395 break;
05396 case 1:
05397 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05398 break;
05399 case 2:
05400 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05401 return NULL;
05402 }
05403 p->whichwink++;
05404
05405 case SIG_FEATDMF:
05406 case SIG_E911:
05407 case SIG_FGC_CAMAMF:
05408 case SIG_FGC_CAMA:
05409 case SIG_FEATB:
05410 case SIG_SF_FEATDMF:
05411 case SIG_SF_FEATB:
05412 case SIG_EMWINK:
05413
05414 if (!ast_strlen_zero(p->dop.dialstr)) {
05415 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05416 if (res < 0) {
05417 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05418 p->dop.dialstr[0] = '\0';
05419 return NULL;
05420 } else
05421 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05422 }
05423 p->dop.dialstr[0] = '\0';
05424 break;
05425 default:
05426 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05427 }
05428 break;
05429 case DAHDI_EVENT_HOOKCOMPLETE:
05430 if (p->inalarm) break;
05431 if ((p->radio || (p->oprmode < 0))) break;
05432 switch (mysig) {
05433 case SIG_FXSLS:
05434 case SIG_FXSGS:
05435 case SIG_FXSKS:
05436 case SIG_EM:
05437 case SIG_EM_E1:
05438 case SIG_EMWINK:
05439 case SIG_FEATD:
05440 case SIG_SF:
05441 case SIG_SFWINK:
05442 case SIG_SF_FEATD:
05443 if (!ast_strlen_zero(p->dop.dialstr)) {
05444 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05445 if (res < 0) {
05446 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05447 p->dop.dialstr[0] = '\0';
05448 return NULL;
05449 } else
05450 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05451 }
05452 p->dop.dialstr[0] = '\0';
05453 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05454 break;
05455 case SIG_FEATDMF:
05456 case SIG_FEATDMF_TA:
05457 case SIG_E911:
05458 case SIG_FGC_CAMA:
05459 case SIG_FGC_CAMAMF:
05460 case SIG_FEATB:
05461 case SIG_SF_FEATDMF:
05462 case SIG_SF_FEATB:
05463 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05464 break;
05465 default:
05466 break;
05467 }
05468 break;
05469 case DAHDI_EVENT_POLARITY:
05470
05471
05472
05473
05474
05475
05476
05477
05478
05479 if (p->polarityonanswerdelay > 0) {
05480
05481 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05482 switch (ast->_state) {
05483 case AST_STATE_DIALING:
05484 case AST_STATE_RINGING:
05485 if (p->answeronpolarityswitch) {
05486 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
05487 ast_setstate(p->owner, AST_STATE_UP);
05488 p->polarity = POLARITY_REV;
05489 if (p->hanguponpolarityswitch) {
05490 p->polaritydelaytv = ast_tvnow();
05491 }
05492 } else {
05493 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
05494 }
05495 break;
05496 case AST_STATE_UP:
05497 case AST_STATE_RING:
05498 if (p->hanguponpolarityswitch) {
05499 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
05500 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05501 p->polarity = POLARITY_IDLE;
05502 } else {
05503 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
05504 }
05505 break;
05506
05507 case AST_STATE_DOWN:
05508 case AST_STATE_RESERVED:
05509 case AST_STATE_OFFHOOK:
05510 case AST_STATE_BUSY:
05511 case AST_STATE_DIALING_OFFHOOK:
05512 case AST_STATE_PRERING:
05513 default:
05514 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05515 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
05516 }
05517
05518 }
05519
05520 } else {
05521
05522 switch (ast->_state) {
05523 case AST_STATE_DIALING:
05524 case AST_STATE_RINGING:
05525 if (p->answeronpolarityswitch) {
05526 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
05527 }
05528 break;
05529
05530 case AST_STATE_UP:
05531 case AST_STATE_RING:
05532 if (p->hanguponpolarityswitch) {
05533 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);
05534 }
05535 break;
05536
05537 default:
05538 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05539 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
05540 }
05541 }
05542 }
05543 }
05544
05545 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) );
05546 break;
05547 default:
05548 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05549 }
05550 return &p->subs[idx].f;
05551 }
05552
05553 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05554 {
05555 struct dahdi_pvt *p = ast->tech_pvt;
05556 int res;
05557 int usedindex=-1;
05558 int idx;
05559 struct ast_frame *f;
05560
05561
05562 idx = dahdi_get_index(ast, p, 1);
05563
05564 p->subs[idx].f.frametype = AST_FRAME_NULL;
05565 p->subs[idx].f.datalen = 0;
05566 p->subs[idx].f.samples = 0;
05567 p->subs[idx].f.mallocd = 0;
05568 p->subs[idx].f.offset = 0;
05569 p->subs[idx].f.subclass = 0;
05570 p->subs[idx].f.delivery = ast_tv(0,0);
05571 p->subs[idx].f.src = "dahdi_exception";
05572 p->subs[idx].f.data.ptr = NULL;
05573
05574
05575 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05576
05577
05578
05579
05580
05581 if (p->fake_event) {
05582 res = p->fake_event;
05583 p->fake_event = 0;
05584 } else
05585 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05586
05587 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05588 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05589 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05590 p->owner = p->subs[SUB_REAL].owner;
05591 if (p->owner && ast_bridged_channel(p->owner))
05592 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05593 p->subs[SUB_REAL].needunhold = 1;
05594 }
05595 switch (res) {
05596 case DAHDI_EVENT_ONHOOK:
05597 dahdi_disable_ec(p);
05598 if (p->owner) {
05599 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05600 dahdi_ring_phone(p);
05601 p->callwaitingrepeat = 0;
05602 p->cidcwexpire = 0;
05603 } else
05604 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05605 update_conf(p);
05606 break;
05607 case DAHDI_EVENT_RINGOFFHOOK:
05608 dahdi_enable_ec(p);
05609 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05610 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05611 p->subs[SUB_REAL].needanswer = 1;
05612 p->dialing = 0;
05613 }
05614 break;
05615 case DAHDI_EVENT_HOOKCOMPLETE:
05616 case DAHDI_EVENT_RINGERON:
05617 case DAHDI_EVENT_RINGEROFF:
05618
05619 break;
05620 case DAHDI_EVENT_WINKFLASH:
05621 p->flashtime = ast_tvnow();
05622 if (p->owner) {
05623 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05624 if (p->owner->_state != AST_STATE_UP) {
05625
05626 usedindex = dahdi_get_index(p->owner, p, 0);
05627 if (usedindex > -1) {
05628 p->subs[usedindex].needanswer = 1;
05629 }
05630 ast_setstate(p->owner, AST_STATE_UP);
05631 }
05632 p->callwaitingrepeat = 0;
05633 p->cidcwexpire = 0;
05634 if (ast_bridged_channel(p->owner))
05635 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05636 p->subs[SUB_REAL].needunhold = 1;
05637 } else
05638 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05639 update_conf(p);
05640 break;
05641 default:
05642 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05643 }
05644 f = &p->subs[idx].f;
05645 return f;
05646 }
05647 if (!(p->radio || (p->oprmode < 0)))
05648 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05649
05650 if (ast != p->owner) {
05651 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05652 f = &p->subs[idx].f;
05653 return f;
05654 }
05655 f = dahdi_handle_event(ast);
05656 return f;
05657 }
05658
05659 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05660 {
05661 struct dahdi_pvt *p = ast->tech_pvt;
05662 struct ast_frame *f;
05663 ast_mutex_lock(&p->lock);
05664 f = __dahdi_exception(ast);
05665 ast_mutex_unlock(&p->lock);
05666 return f;
05667 }
05668
05669 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05670 {
05671 struct dahdi_pvt *p = ast->tech_pvt;
05672 int res;
05673 int idx;
05674 void *readbuf;
05675 struct ast_frame *f;
05676
05677 while (ast_mutex_trylock(&p->lock)) {
05678 CHANNEL_DEADLOCK_AVOIDANCE(ast);
05679 }
05680
05681 idx = dahdi_get_index(ast, p, 0);
05682
05683
05684 if (idx < 0) {
05685 ast_log(LOG_WARNING, "We dont exist?\n");
05686 ast_mutex_unlock(&p->lock);
05687 return NULL;
05688 }
05689
05690 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05691 ast_mutex_unlock(&p->lock);
05692 return NULL;
05693 }
05694
05695 p->subs[idx].f.frametype = AST_FRAME_NULL;
05696 p->subs[idx].f.datalen = 0;
05697 p->subs[idx].f.samples = 0;
05698 p->subs[idx].f.mallocd = 0;
05699 p->subs[idx].f.offset = 0;
05700 p->subs[idx].f.subclass = 0;
05701 p->subs[idx].f.delivery = ast_tv(0,0);
05702 p->subs[idx].f.src = "dahdi_read";
05703 p->subs[idx].f.data.ptr = NULL;
05704
05705
05706 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05707 {
05708 struct dahdi_params ps;
05709
05710 memset(&ps, 0, sizeof(ps));
05711 ps.channo = p->channel;
05712 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05713 ast_mutex_unlock(&p->lock);
05714 return NULL;
05715 }
05716 p->firstradio = 1;
05717 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05718 if (ps.rxisoffhook)
05719 {
05720 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
05721 }
05722 else
05723 {
05724 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05725 }
05726 ast_mutex_unlock(&p->lock);
05727 return &p->subs[idx].f;
05728 }
05729 if (p->ringt == 1) {
05730 ast_mutex_unlock(&p->lock);
05731 return NULL;
05732 }
05733 else if (p->ringt > 0)
05734 p->ringt--;
05735
05736 if (p->subs[idx].needringing) {
05737
05738 p->subs[idx].needringing = 0;
05739 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05740 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05741 ast_setstate(ast, AST_STATE_RINGING);
05742 ast_mutex_unlock(&p->lock);
05743 return &p->subs[idx].f;
05744 }
05745
05746 if (p->subs[idx].needbusy) {
05747
05748 p->subs[idx].needbusy = 0;
05749 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05750 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
05751 ast_mutex_unlock(&p->lock);
05752 return &p->subs[idx].f;
05753 }
05754
05755 if (p->subs[idx].needcongestion) {
05756
05757 p->subs[idx].needcongestion = 0;
05758 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05759 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
05760 ast_mutex_unlock(&p->lock);
05761 return &p->subs[idx].f;
05762 }
05763
05764 if (p->subs[idx].needcallerid) {
05765 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05766 S_OR(p->lastcid_name, NULL),
05767 S_OR(p->lastcid_num, NULL)
05768 );
05769 p->subs[idx].needcallerid = 0;
05770 }
05771
05772 if (p->subs[idx].needanswer) {
05773
05774 p->subs[idx].needanswer = 0;
05775 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05776 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05777 ast_mutex_unlock(&p->lock);
05778 return &p->subs[idx].f;
05779 }
05780
05781 if (p->subs[idx].needflash) {
05782
05783 p->subs[idx].needflash = 0;
05784 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05785 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
05786 ast_mutex_unlock(&p->lock);
05787 return &p->subs[idx].f;
05788 }
05789
05790 if (p->subs[idx].needhold) {
05791
05792 p->subs[idx].needhold = 0;
05793 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05794 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
05795 ast_mutex_unlock(&p->lock);
05796 ast_debug(1, "Sending hold on '%s'\n", ast->name);
05797 return &p->subs[idx].f;
05798 }
05799
05800 if (p->subs[idx].needunhold) {
05801
05802 p->subs[idx].needunhold = 0;
05803 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05804 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
05805 ast_mutex_unlock(&p->lock);
05806 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05807 return &p->subs[idx].f;
05808 }
05809
05810 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05811 if (!p->subs[idx].linear) {
05812 p->subs[idx].linear = 1;
05813 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05814 if (res)
05815 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
05816 }
05817 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05818 (ast->rawreadformat == AST_FORMAT_ALAW)) {
05819 if (p->subs[idx].linear) {
05820 p->subs[idx].linear = 0;
05821 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05822 if (res)
05823 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
05824 }
05825 } else {
05826 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05827 ast_mutex_unlock(&p->lock);
05828 return NULL;
05829 }
05830 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
05831 CHECK_BLOCKING(ast);
05832 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05833 ast_clear_flag(ast, AST_FLAG_BLOCKING);
05834
05835 if (res < 0) {
05836 f = NULL;
05837 if (res == -1) {
05838 if (errno == EAGAIN) {
05839
05840 ast_mutex_unlock(&p->lock);
05841 return &p->subs[idx].f;
05842 } else if (errno == ELAST) {
05843 f = __dahdi_exception(ast);
05844 } else
05845 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05846 }
05847 ast_mutex_unlock(&p->lock);
05848 return f;
05849 }
05850 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
05851 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05852 f = __dahdi_exception(ast);
05853 ast_mutex_unlock(&p->lock);
05854 return f;
05855 }
05856 if (p->tdd) {
05857 int c;
05858
05859 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05860 if (c < 0) {
05861 ast_debug(1,"tdd_feed failed\n");
05862 ast_mutex_unlock(&p->lock);
05863 return NULL;
05864 }
05865 if (c) {
05866 p->subs[idx].f.subclass = 0;
05867 p->subs[idx].f.frametype = AST_FRAME_TEXT;
05868 p->subs[idx].f.mallocd = 0;
05869 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05870 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
05871 p->subs[idx].f.datalen = 1;
05872 *((char *) p->subs[idx].f.data.ptr) = c;
05873 ast_mutex_unlock(&p->lock);
05874 return &p->subs[idx].f;
05875 }
05876 }
05877
05878 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05879 p->callwaitingrepeat--;
05880 }
05881 if (p->cidcwexpire)
05882 p->cidcwexpire--;
05883
05884 if (p->callwaitingrepeat == 1) {
05885 p->callwaitrings++;
05886 dahdi_callwait(ast);
05887 }
05888
05889 if (p->cidcwexpire == 1) {
05890 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05891 restore_conference(p);
05892 }
05893 if (p->subs[idx].linear) {
05894 p->subs[idx].f.datalen = READ_SIZE * 2;
05895 } else
05896 p->subs[idx].f.datalen = READ_SIZE;
05897
05898
05899 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05900 send_callerid(p);
05901 }
05902
05903 p->subs[idx].f.frametype = AST_FRAME_VOICE;
05904 p->subs[idx].f.subclass = ast->rawreadformat;
05905 p->subs[idx].f.samples = READ_SIZE;
05906 p->subs[idx].f.mallocd = 0;
05907 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05908 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
05909 #if 0
05910 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
05911 #endif
05912 if (p->dialing ||
05913 (idx && (ast->_state != AST_STATE_UP)) ||
05914 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05915 ) {
05916
05917
05918 p->subs[idx].f.frametype = AST_FRAME_NULL;
05919 p->subs[idx].f.subclass = 0;
05920 p->subs[idx].f.samples = 0;
05921 p->subs[idx].f.mallocd = 0;
05922 p->subs[idx].f.offset = 0;
05923 p->subs[idx].f.data.ptr = NULL;
05924 p->subs[idx].f.datalen= 0;
05925 }
05926 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) {
05927
05928 int mute;
05929
05930 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
05931
05932
05933 mute = ast_dsp_was_muted(p->dsp);
05934 if (p->muting != mute) {
05935 p->muting = mute;
05936 dahdi_confmute(p, mute);
05937 }
05938
05939 if (f) {
05940 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05941 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05942
05943
05944 f = NULL;
05945 }
05946 } else if (f->frametype == AST_FRAME_DTMF) {
05947 #ifdef HAVE_PRI
05948 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
05949 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05950 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05951
05952 f->frametype = AST_FRAME_NULL;
05953 f->subclass = 0;
05954 }
05955 #endif
05956
05957 p->pulsedial = 0;
05958 }
05959 }
05960 } else
05961 f = &p->subs[idx].f;
05962
05963 if (f && (f->frametype == AST_FRAME_DTMF))
05964 dahdi_handle_dtmfup(ast, idx, &f);
05965
05966
05967 if (p->fake_event)
05968 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05969
05970 ast_mutex_unlock(&p->lock);
05971 return f;
05972 }
05973
05974 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
05975 {
05976 int sent=0;
05977 int size;
05978 int res;
05979 int fd;
05980 fd = p->subs[idx].dfd;
05981 while (len) {
05982 size = len;
05983 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05984 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05985 res = write(fd, buf, size);
05986 if (res != size) {
05987 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05988 return sent;
05989 }
05990 len -= size;
05991 buf += size;
05992 }
05993 return sent;
05994 }
05995
05996 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05997 {
05998 struct dahdi_pvt *p = ast->tech_pvt;
05999 int res;
06000 int idx;
06001 idx = dahdi_get_index(ast, p, 0);
06002 if (idx < 0) {
06003 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06004 return -1;
06005 }
06006
06007 #if 0
06008 #ifdef HAVE_PRI
06009 ast_mutex_lock(&p->lock);
06010 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06011 if (p->pri->pri) {
06012 if (!pri_grab(p, p->pri)) {
06013 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06014 pri_rel(p->pri);
06015 } else
06016 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06017 }
06018 p->proceeding=1;
06019 }
06020 ast_mutex_unlock(&p->lock);
06021 #endif
06022 #endif
06023
06024 if (frame->frametype != AST_FRAME_VOICE) {
06025 if (frame->frametype != AST_FRAME_IMAGE)
06026 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06027 return 0;
06028 }
06029 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06030 (frame->subclass != AST_FORMAT_ULAW) &&
06031 (frame->subclass != AST_FORMAT_ALAW)) {
06032 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06033 return -1;
06034 }
06035 if (p->dialing) {
06036 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06037 return 0;
06038 }
06039 if (!p->owner) {
06040 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06041 return 0;
06042 }
06043 if (p->cidspill) {
06044 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06045 return 0;
06046 }
06047
06048 if (!frame->data.ptr || !frame->datalen)
06049 return 0;
06050
06051 if (frame->subclass == AST_FORMAT_SLINEAR) {
06052 if (!p->subs[idx].linear) {
06053 p->subs[idx].linear = 1;
06054 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06055 if (res)
06056 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06057 }
06058 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
06059 } else {
06060
06061 if (p->subs[idx].linear) {
06062 p->subs[idx].linear = 0;
06063 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06064 if (res)
06065 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06066 }
06067 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
06068 }
06069 if (res < 0) {
06070 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06071 return -1;
06072 }
06073 return 0;
06074 }
06075
06076 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06077 {
06078 struct dahdi_pvt *p = chan->tech_pvt;
06079 int res=-1;
06080 int idx;
06081 int func = DAHDI_FLASH;
06082 ast_mutex_lock(&p->lock);
06083 idx = dahdi_get_index(chan, p, 0);
06084 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06085 if (idx == SUB_REAL) {
06086 switch (condition) {
06087 case AST_CONTROL_BUSY:
06088 #ifdef HAVE_PRI
06089 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06090 chan->hangupcause = AST_CAUSE_USER_BUSY;
06091 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06092 res = 0;
06093 } else if (!p->progress &&
06094 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06095 && p->pri && !p->outgoing) {
06096 if (p->pri->pri) {
06097 if (!pri_grab(p, p->pri)) {
06098 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06099 pri_rel(p->pri);
06100 }
06101 else
06102 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06103 }
06104 p->progress = 1;
06105 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06106 } else
06107 #endif
06108 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06109 break;
06110 case AST_CONTROL_RINGING:
06111 #ifdef HAVE_PRI
06112 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06113 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06114 if (p->pri->pri) {
06115 if (!pri_grab(p, p->pri)) {
06116 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06117 pri_rel(p->pri);
06118 }
06119 else
06120 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06121 }
06122 p->alerting = 1;
06123 }
06124
06125 #endif
06126 #ifdef HAVE_SS7
06127 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06128 if (p->ss7->ss7) {
06129 ss7_grab(p, p->ss7);
06130
06131 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06132 p->rlt = 1;
06133 if (p->rlt != 1)
06134 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06135 p->alerting = 1;
06136 ss7_rel(p->ss7);
06137 }
06138 }
06139 #endif
06140
06141 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
06142
06143 if (chan->_state != AST_STATE_UP) {
06144 if ((chan->_state != AST_STATE_RING) ||
06145 ((p->sig != SIG_FXSKS) &&
06146 (p->sig != SIG_FXSLS) &&
06147 (p->sig != SIG_FXSGS)))
06148 ast_setstate(chan, AST_STATE_RINGING);
06149 }
06150 break;
06151 case AST_CONTROL_PROCEEDING:
06152 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06153 #ifdef HAVE_PRI
06154 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06155 && p->pri && !p->outgoing) {
06156 if (p->pri->pri) {
06157 if (!pri_grab(p, p->pri)) {
06158 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06159 pri_rel(p->pri);
06160 }
06161 else
06162 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06163 }
06164 p->proceeding = 1;
06165 p->dialing = 0;
06166 }
06167 #endif
06168 #ifdef HAVE_SS7
06169
06170 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
06171 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06172 p->rlt = 1;
06173 }
06174
06175 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
06176 if (p->ss7->ss7) {
06177 ss7_grab(p, p->ss7);
06178 isup_acm(p->ss7->ss7, p->ss7call);
06179 p->proceeding = 1;
06180 ss7_rel(p->ss7);
06181
06182 }
06183 }
06184 #endif
06185
06186 res = 0;
06187 break;
06188 case AST_CONTROL_PROGRESS:
06189 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06190 #ifdef HAVE_PRI
06191 p->digital = 0;
06192 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06193 && p->pri && !p->outgoing) {
06194 if (p->pri->pri) {
06195 if (!pri_grab(p, p->pri)) {
06196 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06197 pri_rel(p->pri);
06198 }
06199 else
06200 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06201 }
06202 p->progress = 1;
06203 }
06204 #endif
06205 #ifdef HAVE_SS7
06206 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
06207 if (p->ss7->ss7) {
06208 ss7_grab(p, p->ss7);
06209 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
06210 p->progress = 1;
06211 ss7_rel(p->ss7);
06212
06213 dahdi_enable_ec(p);
06214
06215 }
06216 }
06217 #endif
06218
06219 res = 0;
06220 break;
06221 case AST_CONTROL_CONGESTION:
06222 chan->hangupcause = AST_CAUSE_CONGESTION;
06223 #ifdef HAVE_PRI
06224 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06225 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06226 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06227 res = 0;
06228 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06229 && p->pri && !p->outgoing) {
06230 if (p->pri) {
06231 if (!pri_grab(p, p->pri)) {
06232 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06233 pri_rel(p->pri);
06234 } else
06235 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06236 }
06237 p->progress = 1;
06238 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06239 } else
06240 #endif
06241 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06242 break;
06243 case AST_CONTROL_HOLD:
06244 #ifdef HAVE_PRI
06245 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06246 if (!pri_grab(p, p->pri)) {
06247 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06248 pri_rel(p->pri);
06249 } else
06250 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06251 } else
06252 #endif
06253 ast_moh_start(chan, data, p->mohinterpret);
06254 break;
06255 case AST_CONTROL_UNHOLD:
06256 #ifdef HAVE_PRI
06257 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06258 if (!pri_grab(p, p->pri)) {
06259 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06260 pri_rel(p->pri);
06261 } else
06262 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06263 } else
06264 #endif
06265 ast_moh_stop(chan);
06266 break;
06267 case AST_CONTROL_RADIO_KEY:
06268 if (p->radio)
06269 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06270 res = 0;
06271 break;
06272 case AST_CONTROL_RADIO_UNKEY:
06273 if (p->radio)
06274 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
06275 res = 0;
06276 break;
06277 case AST_CONTROL_FLASH:
06278
06279 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06280
06281 p->dop.dialstr[0] = '\0';
06282 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06283 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06284 chan->name, strerror(errno));
06285 } else
06286 res = 0;
06287 } else
06288 res = 0;
06289 break;
06290 case AST_CONTROL_SRCUPDATE:
06291 res = 0;
06292 break;
06293 case -1:
06294 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06295 break;
06296 }
06297 } else
06298 res = 0;
06299 ast_mutex_unlock(&p->lock);
06300 return res;
06301 }
06302
06303 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
06304 {
06305 struct ast_channel *tmp;
06306 int deflaw;
06307 int res;
06308 int x,y;
06309 int features;
06310 struct ast_str *chan_name;
06311 struct ast_variable *v;
06312 struct dahdi_params ps;
06313 if (i->subs[idx].owner) {
06314 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
06315 return NULL;
06316 }
06317 y = 1;
06318 chan_name = ast_str_alloca(32);
06319 do {
06320 #ifdef HAVE_PRI
06321 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06322 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06323 else
06324 #endif
06325 if (i->channel == CHAN_PSEUDO)
06326 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
06327 else
06328 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
06329 for (x = 0; x < 3; x++) {
06330 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
06331 break;
06332 }
06333 y++;
06334 } while (x < 3);
06335 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);
06336 if (!tmp)
06337 return NULL;
06338 tmp->tech = &dahdi_tech;
06339 memset(&ps, 0, sizeof(ps));
06340 ps.channo = i->channel;
06341 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06342 if (res) {
06343 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06344 ps.curlaw = DAHDI_LAW_MULAW;
06345 }
06346 if (ps.curlaw == DAHDI_LAW_ALAW)
06347 deflaw = AST_FORMAT_ALAW;
06348 else
06349 deflaw = AST_FORMAT_ULAW;
06350 if (law) {
06351 if (law == DAHDI_LAW_ALAW)
06352 deflaw = AST_FORMAT_ALAW;
06353 else
06354 deflaw = AST_FORMAT_ULAW;
06355 }
06356 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
06357 tmp->nativeformats = deflaw;
06358
06359 tmp->rawreadformat = deflaw;
06360 tmp->readformat = deflaw;
06361 tmp->rawwriteformat = deflaw;
06362 tmp->writeformat = deflaw;
06363 i->subs[idx].linear = 0;
06364 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
06365 features = 0;
06366 if (idx == SUB_REAL) {
06367 if (i->busydetect && CANBUSYDETECT(i))
06368 features |= DSP_FEATURE_BUSY_DETECT;
06369 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
06370 features |= DSP_FEATURE_CALL_PROGRESS;
06371 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
06372 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
06373 features |= DSP_FEATURE_FAX_DETECT;
06374 }
06375 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06376 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
06377 i->hardwaredtmf = 0;
06378 features |= DSP_FEATURE_DIGIT_DETECT;
06379 } else if (NEED_MFDETECT(i)) {
06380 i->hardwaredtmf = 1;
06381 features |= DSP_FEATURE_DIGIT_DETECT;
06382 }
06383 }
06384 if (features) {
06385 if (i->dsp) {
06386 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
06387 } else {
06388 if (i->channel != CHAN_PSEUDO)
06389 i->dsp = ast_dsp_new();
06390 else
06391 i->dsp = NULL;
06392 if (i->dsp) {
06393 i->dsp_features = features;
06394 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06395
06396 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
06397
06398
06399 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06400 features = 0;
06401 }
06402 #endif
06403 ast_dsp_set_features(i->dsp, features);
06404 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06405 if (!ast_strlen_zero(progzone))
06406 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06407 if (i->busydetect && CANBUSYDETECT(i)) {
06408 ast_dsp_set_busy_count(i->dsp, i->busycount);
06409 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
06410 }
06411 }
06412 }
06413 }
06414
06415 if (state == AST_STATE_RING)
06416 tmp->rings = 1;
06417 tmp->tech_pvt = i;
06418 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06419
06420 tmp->callgroup = i->callgroup;
06421 tmp->pickupgroup = i->pickupgroup;
06422 }
06423 if (!ast_strlen_zero(i->parkinglot))
06424 ast_string_field_set(tmp, parkinglot, i->parkinglot);
06425 if (!ast_strlen_zero(i->language))
06426 ast_string_field_set(tmp, language, i->language);
06427 if (!i->owner)
06428 i->owner = tmp;
06429 if (!ast_strlen_zero(i->accountcode))
06430 ast_string_field_set(tmp, accountcode, i->accountcode);
06431 if (i->amaflags)
06432 tmp->amaflags = i->amaflags;
06433 i->subs[idx].owner = tmp;
06434 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06435 ast_string_field_set(tmp, call_forward, i->call_forward);
06436
06437 if (!i->adsi)
06438 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06439 if (!ast_strlen_zero(i->exten))
06440 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06441 if (!ast_strlen_zero(i->rdnis))
06442 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06443 if (!ast_strlen_zero(i->dnid))
06444 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06445
06446
06447
06448 #ifdef PRI_ANI
06449 if (!ast_strlen_zero(i->cid_ani))
06450 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06451 else
06452 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06453 #else
06454 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06455 #endif
06456 tmp->cid.cid_pres = i->callingpres;
06457 tmp->cid.cid_ton = i->cid_ton;
06458 tmp->cid.cid_ani2 = i->cid_ani2;
06459 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06460 tmp->transfercapability = transfercapability;
06461 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06462 if (transfercapability & AST_TRANS_CAP_DIGITAL)
06463 i->digital = 1;
06464
06465 i->isidlecall = 0;
06466 i->alreadyhungup = 0;
06467 #endif
06468
06469 i->fake_event = 0;
06470
06471 dahdi_confmute(i, 0);
06472 i->muting = 0;
06473
06474 ast_jb_configure(tmp, &global_jbconf);
06475
06476 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
06477
06478 for (v = i->vars ; v ; v = v->next)
06479 pbx_builtin_setvar_helper(tmp, v->name, v->value);
06480
06481 if (startpbx) {
06482 if (ast_pbx_start(tmp)) {
06483 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06484 ast_hangup(tmp);
06485 i->owner = NULL;
06486 return NULL;
06487 }
06488 }
06489
06490 ast_module_ref(ast_module_info->self);
06491 return tmp;
06492 }
06493
06494
06495 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06496 {
06497 char c;
06498
06499 *str = 0;
06500 for (;;)
06501 {
06502
06503 c = ast_waitfordigit(chan, ms);
06504
06505 if (c < 1)
06506 return c;
06507 *str++ = c;
06508 *str = 0;
06509 if (strchr(term, c))
06510 return 1;
06511 }
06512 }
06513
06514 static int dahdi_wink(struct dahdi_pvt *p, int idx)
06515 {
06516 int j;
06517 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
06518 for (;;)
06519 {
06520
06521 j = DAHDI_IOMUX_SIGEVENT;
06522
06523 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06524
06525 if (j & DAHDI_IOMUX_SIGEVENT) break;
06526 }
06527
06528 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06529 return 0;
06530 }
06531
06532
06533
06534
06535
06536
06537
06538
06539
06540
06541 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
06542 {
06543
06544 dahdichan->dnd = on;
06545 ast_verb(3, "%s DND on channel %d\n",
06546 on? "Enabled" : "Disabled",
06547 dahdichan->channel);
06548 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06549 "Channel: DAHDI/%d\r\n"
06550 "Status: %s\r\n", dahdichan->channel,
06551 on? "enabled" : "disabled");
06552 }
06553
06554 static void *ss_thread(void *data)
06555 {
06556 struct ast_channel *chan = data;
06557 struct dahdi_pvt *p = chan->tech_pvt;
06558 char exten[AST_MAX_EXTENSION] = "";
06559 char exten2[AST_MAX_EXTENSION] = "";
06560 unsigned char buf[256];
06561 char dtmfcid[300];
06562 char dtmfbuf[300];
06563 struct callerid_state *cs = NULL;
06564 char *name = NULL, *number = NULL;
06565 int distMatches;
06566 int curRingData[3];
06567 int receivedRingT;
06568 int counter1;
06569 int counter;
06570 int samples = 0;
06571 struct ast_smdi_md_message *smdi_msg = NULL;
06572 int flags = 0;
06573 int i;
06574 int timeout;
06575 int getforward = 0;
06576 char *s1, *s2;
06577 int len = 0;
06578 int res;
06579 int idx;
06580
06581 ast_mutex_lock(&ss_thread_lock);
06582 ss_thread_count++;
06583 ast_mutex_unlock(&ss_thread_lock);
06584
06585
06586
06587 if (!p) {
06588 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06589 ast_hangup(chan);
06590 goto quit;
06591 }
06592 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
06593 idx = dahdi_get_index(chan, p, 1);
06594 if (idx < 0) {
06595 ast_log(LOG_WARNING, "Huh?\n");
06596 ast_hangup(chan);
06597 goto quit;
06598 }
06599 if (p->dsp)
06600 ast_dsp_digitreset(p->dsp);
06601 switch (p->sig) {
06602 #ifdef HAVE_PRI
06603 case SIG_PRI:
06604 case SIG_BRI:
06605 case SIG_BRI_PTMP:
06606
06607 ast_copy_string(exten, p->exten, sizeof(exten));
06608 len = strlen(exten);
06609 res = 0;
06610 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06611 if (len && !ast_ignore_pattern(chan->context, exten))
06612 tone_zone_play_tone(p->subs[idx].dfd, -1);
06613 else
06614 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06615 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06616 timeout = matchdigittimeout;
06617 else
06618 timeout = gendigittimeout;
06619 res = ast_waitfordigit(chan, timeout);
06620 if (res < 0) {
06621 ast_debug(1, "waitfordigit returned < 0...\n");
06622 ast_hangup(chan);
06623 goto quit;
06624 } else if (res) {
06625 exten[len++] = res;
06626 exten[len] = '\0';
06627 } else
06628 break;
06629 }
06630
06631 if (ast_strlen_zero(exten)) {
06632 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
06633 exten[0] = 's';
06634 exten[1] = '\0';
06635 }
06636 tone_zone_play_tone(p->subs[idx].dfd, -1);
06637 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06638
06639 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06640 if (p->dsp) {
06641 ast_dsp_digitreset(p->dsp);
06642 }
06643 if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
06644 if (p->pri->pri) {
06645 if (!pri_grab(p, p->pri)) {
06646 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
06647 p->proceeding = 1;
06648 pri_rel(p->pri);
06649 } else {
06650 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06651 }
06652 }
06653 }
06654 dahdi_enable_ec(p);
06655 ast_setstate(chan, AST_STATE_RING);
06656 res = ast_pbx_run(chan);
06657 if (res) {
06658 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06659 }
06660 } else {
06661 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06662 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06663 ast_hangup(chan);
06664 p->exten[0] = '\0';
06665
06666 p->call = NULL;
06667 }
06668 goto quit;
06669 break;
06670 #endif
06671 case SIG_FEATD:
06672 case SIG_FEATDMF:
06673 case SIG_FEATDMF_TA:
06674 case SIG_E911:
06675 case SIG_FGC_CAMAMF:
06676 case SIG_FEATB:
06677 case SIG_EMWINK:
06678 case SIG_SF_FEATD:
06679 case SIG_SF_FEATDMF:
06680 case SIG_SF_FEATB:
06681 case SIG_SFWINK:
06682 if (dahdi_wink(p, idx))
06683 goto quit;
06684
06685 case SIG_EM:
06686 case SIG_EM_E1:
06687 case SIG_SF:
06688 case SIG_FGC_CAMA:
06689 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06690 if (p->dsp)
06691 ast_dsp_digitreset(p->dsp);
06692
06693 if (p->dsp) {
06694 if (NEED_MFDETECT(p))
06695 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06696 else
06697 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06698 }
06699 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06700
06701 if (!p->immediate)
06702
06703 res = ast_waitfordigit(chan, 5000);
06704 else
06705 res = 0;
06706 if (res > 0) {
06707
06708 dtmfbuf[0] = res;
06709 switch (p->sig) {
06710 case SIG_FEATD:
06711 case SIG_SF_FEATD:
06712 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06713 if (res > 0)
06714 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06715 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06716 break;
06717 case SIG_FEATDMF_TA:
06718 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06719 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06720 if (dahdi_wink(p, idx)) goto quit;
06721 dtmfbuf[0] = 0;
06722
06723 res = ast_waitfordigit(chan, 5000);
06724 if (res <= 0) break;
06725 dtmfbuf[0] = res;
06726
06727 case SIG_FEATDMF:
06728 case SIG_E911:
06729 case SIG_FGC_CAMAMF:
06730 case SIG_SF_FEATDMF:
06731 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06732
06733 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06734 {
06735 if (dahdi_wink(p, idx)) goto quit;
06736 dtmfbuf[0] = 0;
06737
06738 res = ast_waitfordigit(chan, 5000);
06739 if (res <= 0) break;
06740 dtmfbuf[0] = res;
06741 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06742 }
06743 if (res > 0) {
06744
06745 if (p->sig == SIG_E911)
06746 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06747 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06748 }
06749 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06750 break;
06751 case SIG_FEATB:
06752 case SIG_SF_FEATB:
06753 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06754 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06755 break;
06756 case SIG_EMWINK:
06757
06758
06759
06760
06761 if (res == '*') {
06762 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06763 if (res > 0)
06764 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06765 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06766 break;
06767 }
06768 default:
06769
06770 len = 1;
06771 dtmfbuf[len] = '\0';
06772 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06773 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06774 timeout = matchdigittimeout;
06775 } else {
06776 timeout = gendigittimeout;
06777 }
06778 res = ast_waitfordigit(chan, timeout);
06779 if (res < 0) {
06780 ast_debug(1, "waitfordigit returned < 0...\n");
06781 ast_hangup(chan);
06782 goto quit;
06783 } else if (res) {
06784 dtmfbuf[len++] = res;
06785 dtmfbuf[len] = '\0';
06786 } else {
06787 break;
06788 }
06789 }
06790 break;
06791 }
06792 }
06793 if (res == -1) {
06794 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06795 ast_hangup(chan);
06796 goto quit;
06797 } else if (res < 0) {
06798 ast_debug(1, "Got hung up before digits finished\n");
06799 ast_hangup(chan);
06800 goto quit;
06801 }
06802
06803 if (p->sig == SIG_FGC_CAMA) {
06804 char anibuf[100];
06805
06806 if (ast_safe_sleep(chan,1000) == -1) {
06807 ast_hangup(chan);
06808 goto quit;
06809 }
06810 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06811 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06812 res = my_getsigstr(chan, anibuf, "#", 10000);
06813 if ((res > 0) && (strlen(anibuf) > 2)) {
06814 if (anibuf[strlen(anibuf) - 1] == '#')
06815 anibuf[strlen(anibuf) - 1] = 0;
06816 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06817 }
06818 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06819 }
06820
06821 ast_copy_string(exten, dtmfbuf, sizeof(exten));
06822 if (ast_strlen_zero(exten))
06823 ast_copy_string(exten, "s", sizeof(exten));
06824 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06825
06826 if (exten[0] == '*') {
06827 char *stringp=NULL;
06828 ast_copy_string(exten2, exten, sizeof(exten2));
06829
06830 stringp=exten2 +1;
06831 s1 = strsep(&stringp, "*");
06832 s2 = strsep(&stringp, "*");
06833 if (s2) {
06834 if (!ast_strlen_zero(p->cid_num))
06835 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06836 else
06837 ast_set_callerid(chan, s1, NULL, s1);
06838 ast_copy_string(exten, s2, sizeof(exten));
06839 } else
06840 ast_copy_string(exten, s1, sizeof(exten));
06841 } else if (p->sig == SIG_FEATD)
06842 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06843 }
06844 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06845 if (exten[0] == '*') {
06846 char *stringp=NULL;
06847 ast_copy_string(exten2, exten, sizeof(exten2));
06848
06849 stringp=exten2 +1;
06850 s1 = strsep(&stringp, "#");
06851 s2 = strsep(&stringp, "#");
06852 if (s2) {
06853 if (!ast_strlen_zero(p->cid_num))
06854 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06855 else
06856 if (*(s1 + 2))
06857 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06858 ast_copy_string(exten, s2 + 1, sizeof(exten));
06859 } else
06860 ast_copy_string(exten, s1 + 2, sizeof(exten));
06861 } else
06862 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06863 }
06864 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06865 if (exten[0] == '*') {
06866 char *stringp=NULL;
06867 ast_copy_string(exten2, exten, sizeof(exten2));
06868
06869 stringp=exten2 +1;
06870 s1 = strsep(&stringp, "#");
06871 s2 = strsep(&stringp, "#");
06872 if (s2 && (*(s2 + 1) == '0')) {
06873 if (*(s2 + 2))
06874 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06875 }
06876 if (s1) ast_copy_string(exten, s1, sizeof(exten));
06877 else ast_copy_string(exten, "911", sizeof(exten));
06878 } else
06879 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
06880 }
06881 if (p->sig == SIG_FEATB) {
06882 if (exten[0] == '*') {
06883 char *stringp=NULL;
06884 ast_copy_string(exten2, exten, sizeof(exten2));
06885
06886 stringp=exten2 +1;
06887 s1 = strsep(&stringp, "#");
06888 ast_copy_string(exten, exten2 + 1, sizeof(exten));
06889 } else
06890 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
06891 }
06892 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06893 dahdi_wink(p, idx);
06894
06895
06896
06897 if (ast_safe_sleep(chan,100)) goto quit;
06898 }
06899 dahdi_enable_ec(p);
06900 if (NEED_MFDETECT(p)) {
06901 if (p->dsp) {
06902 if (!p->hardwaredtmf)
06903 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06904 else {
06905 ast_dsp_free(p->dsp);
06906 p->dsp = NULL;
06907 }
06908 }
06909 }
06910
06911 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06912 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06913 if (p->dsp) ast_dsp_digitreset(p->dsp);
06914 res = ast_pbx_run(chan);
06915 if (res) {
06916 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06917 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06918 }
06919 goto quit;
06920 } else {
06921 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06922 sleep(2);
06923 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
06924 if (res < 0)
06925 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06926 else
06927 sleep(1);
06928 res = ast_streamfile(chan, "ss-noservice", chan->language);
06929 if (res >= 0)
06930 ast_waitstream(chan, "");
06931 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06932 ast_hangup(chan);
06933 goto quit;
06934 }
06935 break;
06936 case SIG_FXOLS:
06937 case SIG_FXOGS:
06938 case SIG_FXOKS:
06939
06940 timeout = firstdigittimeout;
06941
06942
06943 if (p->subs[SUB_THREEWAY].owner)
06944 timeout = 999999;
06945 while (len < AST_MAX_EXTENSION-1) {
06946
06947
06948 if (p->immediate)
06949 res = 's';
06950 else
06951 res = ast_waitfordigit(chan, timeout);
06952 timeout = 0;
06953 if (res < 0) {
06954 ast_debug(1, "waitfordigit returned < 0...\n");
06955 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06956 ast_hangup(chan);
06957 goto quit;
06958 } else if (res) {
06959 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
06960 exten[len++]=res;
06961 exten[len] = '\0';
06962 }
06963 if (!ast_ignore_pattern(chan->context, exten))
06964 tone_zone_play_tone(p->subs[idx].dfd, -1);
06965 else
06966 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06967 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06968 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06969 if (getforward) {
06970
06971 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
06972 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06973 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06974 if (res)
06975 break;
06976 usleep(500000);
06977 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06978 sleep(1);
06979 memset(exten, 0, sizeof(exten));
06980 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06981 len = 0;
06982 getforward = 0;
06983 } else {
06984 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06985 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06986 if (!ast_strlen_zero(p->cid_num)) {
06987 if (!p->hidecallerid)
06988 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06989 else
06990 ast_set_callerid(chan, NULL, NULL, p->cid_num);
06991 }
06992 if (!ast_strlen_zero(p->cid_name)) {
06993 if (!p->hidecallerid)
06994 ast_set_callerid(chan, NULL, p->cid_name, NULL);
06995 }
06996 ast_setstate(chan, AST_STATE_RING);
06997 dahdi_enable_ec(p);
06998 res = ast_pbx_run(chan);
06999 if (res) {
07000 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07001 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07002 }
07003 goto quit;
07004 }
07005 } else {
07006
07007
07008 timeout = matchdigittimeout;
07009 }
07010 } else if (res == 0) {
07011 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
07012 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07013 dahdi_wait_event(p->subs[idx].dfd);
07014 ast_hangup(chan);
07015 goto quit;
07016 } else if (p->callwaiting && !strcmp(exten, "*70")) {
07017 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
07018
07019 p->callwaiting = 0;
07020 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07021 if (res) {
07022 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07023 chan->name, strerror(errno));
07024 }
07025 len = 0;
07026 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
07027 memset(exten, 0, sizeof(exten));
07028 timeout = firstdigittimeout;
07029
07030 } else if (!strcmp(exten,ast_pickup_ext())) {
07031
07032
07033
07034
07035 if (idx == SUB_REAL) {
07036
07037 if (p->subs[SUB_THREEWAY].owner) {
07038
07039
07040 alloc_sub(p, SUB_CALLWAIT);
07041 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07042 unalloc_sub(p, SUB_THREEWAY);
07043 }
07044 dahdi_enable_ec(p);
07045 if (ast_pickup_call(chan)) {
07046 ast_debug(1, "No call pickup possible...\n");
07047 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07048 dahdi_wait_event(p->subs[idx].dfd);
07049 }
07050 ast_hangup(chan);
07051 goto quit;
07052 } else {
07053 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07054 ast_hangup(chan);
07055 goto quit;
07056 }
07057
07058 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07059 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
07060
07061 p->hidecallerid = 1;
07062 if (chan->cid.cid_num)
07063 ast_free(chan->cid.cid_num);
07064 chan->cid.cid_num = NULL;
07065 if (chan->cid.cid_name)
07066 ast_free(chan->cid.cid_name);
07067 chan->cid.cid_name = NULL;
07068 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07069 if (res) {
07070 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07071 chan->name, strerror(errno));
07072 }
07073 len = 0;
07074 memset(exten, 0, sizeof(exten));
07075 timeout = firstdigittimeout;
07076 } else if (p->callreturn && !strcmp(exten, "*69")) {
07077 res = 0;
07078 if (!ast_strlen_zero(p->lastcid_num)) {
07079 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07080 }
07081 if (!res)
07082 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07083 break;
07084 } else if (!strcmp(exten, "*78")) {
07085 dahdi_dnd(p, 1);
07086
07087 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07088 getforward = 0;
07089 memset(exten, 0, sizeof(exten));
07090 len = 0;
07091 } else if (!strcmp(exten, "*79")) {
07092 dahdi_dnd(p, 0);
07093
07094 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07095 getforward = 0;
07096 memset(exten, 0, sizeof(exten));
07097 len = 0;
07098 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07099 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07100 getforward = 1;
07101 memset(exten, 0, sizeof(exten));
07102 len = 0;
07103 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07104 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
07105 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07106 memset(p->call_forward, 0, sizeof(p->call_forward));
07107 getforward = 0;
07108 memset(exten, 0, sizeof(exten));
07109 len = 0;
07110 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07111 p->subs[SUB_THREEWAY].owner &&
07112 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07113
07114
07115 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07116 ast_verb(3, "Parking call to '%s'\n", chan->name);
07117 break;
07118 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07119 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
07120 res = ast_db_put("blacklist", p->lastcid_num, "1");
07121 if (!res) {
07122 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07123 memset(exten, 0, sizeof(exten));
07124 len = 0;
07125 }
07126 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07127 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
07128
07129 p->hidecallerid = 0;
07130 if (chan->cid.cid_num)
07131 ast_free(chan->cid.cid_num);
07132 chan->cid.cid_num = NULL;
07133 if (chan->cid.cid_name)
07134 ast_free(chan->cid.cid_name);
07135 chan->cid.cid_name = NULL;
07136 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07137 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07138 if (res) {
07139 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07140 chan->name, strerror(errno));
07141 }
07142 len = 0;
07143 memset(exten, 0, sizeof(exten));
07144 timeout = firstdigittimeout;
07145 } else if (!strcmp(exten, "*0")) {
07146 struct ast_channel *nbridge =
07147 p->subs[SUB_THREEWAY].owner;
07148 struct dahdi_pvt *pbridge = NULL;
07149
07150 if (nbridge && ast_bridged_channel(nbridge))
07151 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07152 if (nbridge && pbridge &&
07153 (nbridge->tech == &dahdi_tech) &&
07154 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
07155 ISTRUNK(pbridge)) {
07156 int func = DAHDI_FLASH;
07157
07158 p->dop.dialstr[0] = '\0';
07159
07160 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07161 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07162 nbridge->name, strerror(errno));
07163 }
07164 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07165 unalloc_sub(p, SUB_THREEWAY);
07166 p->owner = p->subs[SUB_REAL].owner;
07167 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07168 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07169 ast_hangup(chan);
07170 goto quit;
07171 } else {
07172 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07173 dahdi_wait_event(p->subs[idx].dfd);
07174 tone_zone_play_tone(p->subs[idx].dfd, -1);
07175 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07176 unalloc_sub(p, SUB_THREEWAY);
07177 p->owner = p->subs[SUB_REAL].owner;
07178 ast_hangup(chan);
07179 goto quit;
07180 }
07181 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07182 ((exten[0] != '*') || (strlen(exten) > 2))) {
07183 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);
07184 break;
07185 }
07186 if (!timeout)
07187 timeout = gendigittimeout;
07188 if (len && !ast_ignore_pattern(chan->context, exten))
07189 tone_zone_play_tone(p->subs[idx].dfd, -1);
07190 }
07191 break;
07192 case SIG_FXSLS:
07193 case SIG_FXSGS:
07194 case SIG_FXSKS:
07195 #ifdef HAVE_PRI
07196 if (p->pri) {
07197
07198 struct ast_frame *f;
07199 int res;
07200 time_t start;
07201
07202 time(&start);
07203 ast_setstate(chan, AST_STATE_RING);
07204 while (time(NULL) < start + 3) {
07205 res = ast_waitfor(chan, 1000);
07206 if (res) {
07207 f = ast_read(chan);
07208 if (!f) {
07209 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07210 ast_hangup(chan);
07211 goto quit;
07212 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07213 res = 1;
07214 } else
07215 res = 0;
07216 ast_frfree(f);
07217 if (res) {
07218 ast_debug(1, "Got ring!\n");
07219 res = 0;
07220 break;
07221 }
07222 }
07223 }
07224 }
07225 #endif
07226
07227 if (p->use_smdi && p->smdi_iface) {
07228 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07229
07230 if (smdi_msg != NULL) {
07231 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07232
07233 if (smdi_msg->type == 'B')
07234 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07235 else if (smdi_msg->type == 'N')
07236 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07237
07238 ast_debug(1, "Received SMDI message on %s\n", chan->name);
07239 } else {
07240 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07241 }
07242 }
07243
07244 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07245 number = smdi_msg->calling_st;
07246
07247
07248
07249
07250 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
07251
07252 if (p->cid_signalling == CID_SIG_DTMF) {
07253 int k = 0;
07254 cs = NULL;
07255 ast_debug(1, "Receiving DTMF cid on "
07256 "channel %s\n", chan->name);
07257 dahdi_setlinear(p->subs[idx].dfd, 0);
07258 res = 2000;
07259 for (;;) {
07260 struct ast_frame *f;
07261 res = ast_waitfor(chan, res);
07262 if (res <= 0) {
07263 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07264 "Exiting simple switch\n");
07265 ast_hangup(chan);
07266 goto quit;
07267 }
07268 f = ast_read(chan);
07269 if (!f)
07270 break;
07271 if (f->frametype == AST_FRAME_DTMF) {
07272 dtmfbuf[k++] = f->subclass;
07273 ast_debug(1, "CID got digit '%c'\n", f->subclass);
07274 res = 2000;
07275 }
07276 ast_frfree(f);
07277 if (chan->_state == AST_STATE_RING ||
07278 chan->_state == AST_STATE_RINGING)
07279 break;
07280 }
07281 dtmfbuf[k] = '\0';
07282 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07283
07284 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
07285 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07286 ast_debug(1, "CID is '%s', flags %d\n",
07287 dtmfcid, flags);
07288
07289 if (!ast_strlen_zero(dtmfcid))
07290 number = dtmfcid;
07291 else
07292 number = NULL;
07293
07294 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07295 cs = callerid_new(p->cid_signalling);
07296 if (cs) {
07297 samples = 0;
07298 #if 1
07299 bump_gains(p);
07300 #endif
07301
07302 dahdi_setlinear(p->subs[idx].dfd, 0);
07303
07304
07305 for (;;) {
07306 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07307 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07308 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07309 callerid_free(cs);
07310 ast_hangup(chan);
07311 goto quit;
07312 }
07313 if (i & DAHDI_IOMUX_SIGEVENT) {
07314 res = dahdi_get_event(p->subs[idx].dfd);
07315 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07316 if (res == DAHDI_EVENT_NOALARM) {
07317 p->inalarm = 0;
07318 }
07319
07320 if (p->cid_signalling == CID_SIG_V23_JP) {
07321 if (res == DAHDI_EVENT_RINGBEGIN) {
07322 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07323 usleep(1);
07324 }
07325 } else {
07326 res = 0;
07327 break;
07328 }
07329 } else if (i & DAHDI_IOMUX_READ) {
07330 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07331 if (res < 0) {
07332 if (errno != ELAST) {
07333 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07334 callerid_free(cs);
07335 ast_hangup(chan);
07336 goto quit;
07337 }
07338 break;
07339 }
07340 samples += res;
07341
07342 if (p->cid_signalling == CID_SIG_V23_JP) {
07343 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07344 } else {
07345 res = callerid_feed(cs, buf, res, AST_LAW(p));
07346 }
07347
07348 if (res < 0) {
07349 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07350 break;
07351 } else if (res)
07352 break;
07353 else if (samples > (8000 * 10))
07354 break;
07355 }
07356 }
07357 if (res == 1) {
07358 callerid_get(cs, &name, &number, &flags);
07359 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07360 }
07361
07362 if (p->cid_signalling == CID_SIG_V23_JP) {
07363 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07364 usleep(1);
07365 res = 4000;
07366 } else {
07367
07368
07369 res = 2000;
07370 }
07371
07372 for (;;) {
07373 struct ast_frame *f;
07374 res = ast_waitfor(chan, res);
07375 if (res <= 0) {
07376 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07377 "Exiting simple switch\n");
07378 ast_hangup(chan);
07379 goto quit;
07380 }
07381 if (!(f = ast_read(chan))) {
07382 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07383 ast_hangup(chan);
07384 goto quit;
07385 }
07386 ast_frfree(f);
07387 if (chan->_state == AST_STATE_RING ||
07388 chan->_state == AST_STATE_RINGING)
07389 break;
07390 }
07391
07392
07393
07394 if (p->usedistinctiveringdetection) {
07395 len = 0;
07396 distMatches = 0;
07397
07398 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07399 curRingData[receivedRingT] = 0;
07400 receivedRingT = 0;
07401 counter = 0;
07402 counter1 = 0;
07403
07404 if (strcmp(p->context,p->defcontext) != 0) {
07405 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07406 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07407 }
07408
07409 for (;;) {
07410 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07411 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07412 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07413 callerid_free(cs);
07414 ast_hangup(chan);
07415 goto quit;
07416 }
07417 if (i & DAHDI_IOMUX_SIGEVENT) {
07418 res = dahdi_get_event(p->subs[idx].dfd);
07419 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07420 if (res == DAHDI_EVENT_NOALARM) {
07421 p->inalarm = 0;
07422 }
07423 res = 0;
07424
07425
07426 curRingData[receivedRingT] = p->ringt;
07427
07428 if (p->ringt < p->ringt_base/2)
07429 break;
07430
07431
07432 if (++receivedRingT == ARRAY_LEN(curRingData))
07433 break;
07434 } else if (i & DAHDI_IOMUX_READ) {
07435 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07436 if (res < 0) {
07437 if (errno != ELAST) {
07438 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07439 callerid_free(cs);
07440 ast_hangup(chan);
07441 goto quit;
07442 }
07443 break;
07444 }
07445 if (p->ringt)
07446 p->ringt--;
07447 if (p->ringt == 1) {
07448 res = -1;
07449 break;
07450 }
07451 }
07452 }
07453
07454 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07455 for (counter = 0; counter < 3; counter++) {
07456
07457
07458 distMatches = 0;
07459 for (counter1 = 0; counter1 < 3; counter1++) {
07460 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07461 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07462 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07463 curRingData[counter1]);
07464 distMatches++;
07465 }
07466 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07467 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07468 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07469 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07470 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07471 distMatches++;
07472 }
07473 }
07474
07475 if (distMatches == 3) {
07476
07477 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07478 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07479 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07480 break;
07481 }
07482 }
07483 }
07484
07485 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07486 #if 1
07487 restore_gains(p);
07488 #endif
07489 } else
07490 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07491 } else {
07492 ast_log(LOG_WARNING, "Channel %s in prering "
07493 "state, but I have nothing to do. "
07494 "Terminating simple switch, should be "
07495 "restarted by the actual ring.\n",
07496 chan->name);
07497 ast_hangup(chan);
07498 goto quit;
07499 }
07500 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07501 if (p->cid_signalling == CID_SIG_DTMF) {
07502 int k = 0;
07503 cs = NULL;
07504 dahdi_setlinear(p->subs[idx].dfd, 0);
07505 res = 2000;
07506 for (;;) {
07507 struct ast_frame *f;
07508 res = ast_waitfor(chan, res);
07509 if (res <= 0) {
07510 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07511 "Exiting simple switch\n");
07512 ast_hangup(chan);
07513 return NULL;
07514 }
07515 f = ast_read(chan);
07516 if (f->frametype == AST_FRAME_DTMF) {
07517 dtmfbuf[k++] = f->subclass;
07518 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07519 res = 2000;
07520 }
07521 ast_frfree(f);
07522
07523 if (p->ringt_base == p->ringt)
07524 break;
07525
07526 }
07527 dtmfbuf[k] = '\0';
07528 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07529
07530 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07531 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07532 dtmfcid, flags);
07533
07534 if (!ast_strlen_zero(dtmfcid))
07535 number = dtmfcid;
07536 else
07537 number = NULL;
07538
07539 } else {
07540
07541 cs = callerid_new(p->cid_signalling);
07542 if (cs) {
07543 #if 1
07544 bump_gains(p);
07545 #endif
07546 samples = 0;
07547 len = 0;
07548 distMatches = 0;
07549
07550 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07551 curRingData[receivedRingT] = 0;
07552 receivedRingT = 0;
07553 counter = 0;
07554 counter1 = 0;
07555
07556 if (strcmp(p->context,p->defcontext) != 0) {
07557 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07558 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07559 }
07560
07561
07562 dahdi_setlinear(p->subs[idx].dfd, 0);
07563 for (;;) {
07564 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07565 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07566 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07567 callerid_free(cs);
07568 ast_hangup(chan);
07569 goto quit;
07570 }
07571 if (i & DAHDI_IOMUX_SIGEVENT) {
07572 res = dahdi_get_event(p->subs[idx].dfd);
07573 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07574 if (res == DAHDI_EVENT_NOALARM) {
07575 p->inalarm = 0;
07576 }
07577
07578 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07579 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07580 p->polarity = POLARITY_IDLE;
07581 callerid_free(cs);
07582 ast_hangup(chan);
07583 goto quit;
07584 }
07585 res = 0;
07586
07587
07588 curRingData[receivedRingT] = p->ringt;
07589
07590 if (p->ringt < p->ringt_base/2)
07591 break;
07592
07593
07594 if (++receivedRingT == ARRAY_LEN(curRingData))
07595 break;
07596 } else if (i & DAHDI_IOMUX_READ) {
07597 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07598 if (res < 0) {
07599 if (errno != ELAST) {
07600 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07601 callerid_free(cs);
07602 ast_hangup(chan);
07603 goto quit;
07604 }
07605 break;
07606 }
07607 if (p->ringt)
07608 p->ringt--;
07609 if (p->ringt == 1) {
07610 res = -1;
07611 break;
07612 }
07613 samples += res;
07614 res = callerid_feed(cs, buf, res, AST_LAW(p));
07615 if (res < 0) {
07616 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07617 break;
07618 } else if (res)
07619 break;
07620 else if (samples > (8000 * 10))
07621 break;
07622 }
07623 }
07624 if (res == 1) {
07625 callerid_get(cs, &name, &number, &flags);
07626 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07627 }
07628 if (distinctiveringaftercid == 1) {
07629
07630 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07631 curRingData[receivedRingT] = 0;
07632 }
07633 receivedRingT = 0;
07634 ast_verb(3, "Detecting post-CID distinctive ring\n");
07635 for (;;) {
07636 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07637 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07638 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07639 callerid_free(cs);
07640 ast_hangup(chan);
07641 goto quit;
07642 }
07643 if (i & DAHDI_IOMUX_SIGEVENT) {
07644 res = dahdi_get_event(p->subs[idx].dfd);
07645 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07646 if (res == DAHDI_EVENT_NOALARM) {
07647 p->inalarm = 0;
07648 }
07649 res = 0;
07650
07651
07652 curRingData[receivedRingT] = p->ringt;
07653
07654 if (p->ringt < p->ringt_base/2)
07655 break;
07656
07657
07658 if (++receivedRingT == ARRAY_LEN(curRingData))
07659 break;
07660 } else if (i & DAHDI_IOMUX_READ) {
07661 res = read(p->subs[idx].dfd, buf, sizeof(buf));
07662 if (res < 0) {
07663 if (errno != ELAST) {
07664 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07665 callerid_free(cs);
07666 ast_hangup(chan);
07667 goto quit;
07668 }
07669 break;
07670 }
07671 if (p->ringt)
07672 p->ringt--;
07673 if (p->ringt == 1) {
07674 res = -1;
07675 break;
07676 }
07677 }
07678 }
07679 }
07680 if (p->usedistinctiveringdetection) {
07681
07682 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07683
07684 for (counter = 0; counter < 3; counter++) {
07685
07686
07687
07688 ast_verb(3, "Checking %d,%d,%d\n",
07689 p->drings.ringnum[counter].ring[0],
07690 p->drings.ringnum[counter].ring[1],
07691 p->drings.ringnum[counter].ring[2]);
07692 distMatches = 0;
07693 for (counter1 = 0; counter1 < 3; counter1++) {
07694 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07695 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07696 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07697 curRingData[counter1]);
07698 distMatches++;
07699 }
07700 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07701 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07702 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07703 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07704 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07705 distMatches++;
07706 }
07707 }
07708 if (distMatches == 3) {
07709
07710 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07711 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07712 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07713 break;
07714 }
07715 }
07716 }
07717
07718 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07719 #if 1
07720 restore_gains(p);
07721 #endif
07722 if (res < 0) {
07723 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07724 }
07725 } else
07726 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07727 }
07728 }
07729 else
07730 cs = NULL;
07731
07732 if (number)
07733 ast_shrink_phone_number(number);
07734 ast_set_callerid(chan, number, name, number);
07735
07736 if (smdi_msg)
07737 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07738
07739 if (cs)
07740 callerid_free(cs);
07741
07742 if (flags & CID_MSGWAITING) {
07743 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
07744 notify_message(p->mailbox, 1);
07745
07746 if (p->mwimonitor_rpas) {
07747 ast_hangup(chan);
07748 return NULL;
07749 }
07750 } else if (flags & CID_NOMSGWAITING) {
07751 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
07752 notify_message(p->mailbox, 0);
07753
07754 if (p->mwimonitor_rpas) {
07755 ast_hangup(chan);
07756 return NULL;
07757 }
07758 }
07759
07760 ast_setstate(chan, AST_STATE_RING);
07761 chan->rings = 1;
07762 p->ringt = p->ringt_base;
07763 res = ast_pbx_run(chan);
07764 if (res) {
07765 ast_hangup(chan);
07766 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07767 }
07768 goto quit;
07769 default:
07770 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07771 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07772 if (res < 0)
07773 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07774 }
07775 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07776 if (res < 0)
07777 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07778 ast_hangup(chan);
07779 quit:
07780 ast_mutex_lock(&ss_thread_lock);
07781 ss_thread_count--;
07782 ast_cond_signal(&ss_thread_complete);
07783 ast_mutex_unlock(&ss_thread_lock);
07784 return NULL;
07785 }
07786
07787 struct mwi_thread_data {
07788 struct dahdi_pvt *pvt;
07789 unsigned char buf[READ_SIZE];
07790 size_t len;
07791 };
07792
07793 static int calc_energy(const unsigned char *buf, int len, int law)
07794 {
07795 int x;
07796 int sum = 0;
07797
07798 if (!len)
07799 return 0;
07800
07801 for (x = 0; x < len; x++)
07802 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07803
07804 return sum / len;
07805 }
07806
07807 static void *mwi_thread(void *data)
07808 {
07809 struct mwi_thread_data *mtd = data;
07810 struct callerid_state *cs;
07811 pthread_t threadid;
07812 int samples = 0;
07813 char *name, *number;
07814 int flags;
07815 int i, res;
07816 unsigned int spill_done = 0;
07817 int spill_result = -1;
07818
07819 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
07820 mtd->pvt->mwimonitoractive = 0;
07821
07822 return NULL;
07823 }
07824
07825 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
07826
07827 bump_gains(mtd->pvt);
07828
07829 for (;;) {
07830 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07831 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07832 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07833 goto quit;
07834 }
07835
07836 if (i & DAHDI_IOMUX_SIGEVENT) {
07837 struct ast_channel *chan;
07838
07839
07840
07841
07842 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07843
07844 switch (res) {
07845 case DAHDI_EVENT_NEONMWI_ACTIVE:
07846 case DAHDI_EVENT_NEONMWI_INACTIVE:
07847 case DAHDI_EVENT_NONE:
07848 case DAHDI_EVENT_BITSCHANGED:
07849 break;
07850 case DAHDI_EVENT_NOALARM:
07851 mtd->pvt->inalarm = 0;
07852 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
07853 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07854 "Channel: %d\r\n", mtd->pvt->channel);
07855 break;
07856 case DAHDI_EVENT_ALARM:
07857 mtd->pvt->inalarm = 1;
07858 res = get_alarms(mtd->pvt);
07859 handle_alarms(mtd->pvt, res);
07860 break;
07861 default:
07862 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
07863 callerid_free(cs);
07864
07865 restore_gains(mtd->pvt);
07866 mtd->pvt->ringt = mtd->pvt->ringt_base;
07867
07868 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
07869 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07870 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
07871 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07872 if (res < 0)
07873 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
07874 ast_hangup(chan);
07875 goto quit;
07876 }
07877 goto quit_no_clean;
07878
07879 } else {
07880 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
07881 }
07882 }
07883 } else if (i & DAHDI_IOMUX_READ) {
07884 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07885 if (errno != ELAST) {
07886 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07887 goto quit;
07888 }
07889 break;
07890 }
07891 samples += res;
07892 if (!spill_done) {
07893 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
07894 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07895 break;
07896 } else if (spill_result) {
07897 spill_done = 1;
07898 }
07899 } else {
07900
07901
07902
07903 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
07904 break;
07905 }
07906 if (samples > (8000 * 4))
07907 break;
07908 }
07909 }
07910
07911 if (spill_result == 1) {
07912 callerid_get(cs, &name, &number, &flags);
07913 if (flags & CID_MSGWAITING) {
07914 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
07915 notify_message(mtd->pvt->mailbox, 1);
07916 } else if (flags & CID_NOMSGWAITING) {
07917 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
07918 notify_message(mtd->pvt->mailbox, 0);
07919 } else {
07920 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
07921 }
07922 }
07923
07924
07925 quit:
07926 callerid_free(cs);
07927
07928 restore_gains(mtd->pvt);
07929
07930 quit_no_clean:
07931 mtd->pvt->mwimonitoractive = 0;
07932
07933 ast_free(mtd);
07934
07935 return NULL;
07936 }
07937
07938
07939
07940
07941 enum mwisend_states {
07942 MWI_SEND_SA,
07943 MWI_SEND_SA_WAIT,
07944 MWI_SEND_PAUSE,
07945 MWI_SEND_SPILL,
07946 MWI_SEND_CLEANUP,
07947 MWI_SEND_DONE
07948 };
07949
07950 static void *mwi_send_thread(void *data)
07951 {
07952 struct mwi_thread_data *mtd = data;
07953 struct timeval timeout_basis, suspend, now;
07954 int x, i, res;
07955 int num_read;
07956 enum mwisend_states mwi_send_state = MWI_SEND_SPILL;
07957
07958 ast_mutex_lock(&mwi_thread_lock);
07959 mwi_thread_count++;
07960 ast_mutex_unlock(&mwi_thread_lock);
07961
07962
07963 if(mwisend_rpas) {
07964 mwi_send_state = MWI_SEND_SA;
07965 }
07966
07967 gettimeofday(&timeout_basis, NULL);
07968
07969 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
07970 if (!mtd->pvt->cidspill) {
07971 mtd->pvt->mwisendactive = 0;
07972 ast_free(mtd);
07973 return NULL;
07974 }
07975 x = DAHDI_FLUSH_BOTH;
07976 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07977 x = 3000;
07978 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07979 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
07980 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
07981 mtd->pvt->cidpos = 0;
07982
07983 while (MWI_SEND_DONE != mwi_send_state) {
07984 num_read = 0;
07985 gettimeofday(&now, NULL);
07986 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
07987 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
07988 goto quit;
07989 }
07990
07991 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07992 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07993 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07994 goto quit;
07995 }
07996
07997 if (i & DAHDI_IOMUX_SIGEVENT) {
07998
07999
08000
08001 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
08002 switch (res) {
08003 case DAHDI_EVENT_RINGEROFF:
08004 if(mwi_send_state == MWI_SEND_SA_WAIT) {
08005 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
08006 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
08007 goto quit;
08008 }
08009 mwi_send_state = MWI_SEND_PAUSE;
08010 gettimeofday(&suspend, NULL);
08011 }
08012 break;
08013 case DAHDI_EVENT_RINGERON:
08014 case DAHDI_EVENT_HOOKCOMPLETE:
08015 break;
08016 default:
08017
08018 if (0 < handle_init_event(mtd->pvt, res)) {
08019
08020 goto quit;
08021 }
08022 break;
08023 }
08024 } else if (i & DAHDI_IOMUX_READ) {
08025 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
08026 if (errno != ELAST) {
08027 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08028 goto quit;
08029 }
08030 break;
08031 }
08032 }
08033
08034 switch ( mwi_send_state) {
08035 case MWI_SEND_SA:
08036
08037 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
08038 if (res) {
08039 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
08040 goto quit;
08041 }
08042 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING);
08043 mwi_send_state = MWI_SEND_SA_WAIT;
08044 break;
08045 case MWI_SEND_SA_WAIT:
08046 break;
08047 case MWI_SEND_PAUSE:
08048 gettimeofday(&now, NULL);
08049 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
08050 mwi_send_state = MWI_SEND_SPILL;
08051 }
08052 break;
08053 case MWI_SEND_SPILL:
08054
08055 if(0 < num_read) {
08056 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
08057 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
08058 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
08059 if (res > 0) {
08060 mtd->pvt->cidpos += res;
08061 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
08062 ast_free(mtd->pvt->cidspill);
08063 mtd->pvt->cidspill = NULL;
08064 mtd->pvt->cidpos = 0;
08065 mtd->pvt->cidlen = 0;
08066 mwi_send_state = MWI_SEND_CLEANUP;
08067 }
08068 } else {
08069 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
08070 goto quit;
08071 }
08072 }
08073 break;
08074 case MWI_SEND_CLEANUP:
08075
08076 mwi_send_state = MWI_SEND_DONE;
08077 break;
08078 default:
08079
08080 goto quit;
08081 break;
08082 }
08083 }
08084
08085 quit:
08086 if(mtd->pvt->cidspill) {
08087 ast_free(mtd->pvt->cidspill);
08088 mtd->pvt->cidspill = NULL;
08089 }
08090 mtd->pvt->mwisendactive = 0;
08091 ast_free(mtd);
08092
08093 ast_mutex_lock(&mwi_thread_lock);
08094 mwi_thread_count--;
08095 ast_cond_signal(&mwi_thread_complete);
08096 ast_mutex_unlock(&mwi_thread_lock);
08097
08098 return NULL;
08099 }
08100
08101
08102
08103 static int dahdi_destroy_channel_bynum(int channel)
08104 {
08105 struct dahdi_pvt *tmp = NULL;
08106 struct dahdi_pvt *prev = NULL;
08107
08108 tmp = iflist;
08109 while (tmp) {
08110 if (tmp->channel == channel) {
08111 int x = DAHDI_FLASH;
08112 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08113 destroy_channel(prev, tmp, 1);
08114 ast_module_unref(ast_module_info->self);
08115 return RESULT_SUCCESS;
08116 }
08117 prev = tmp;
08118 tmp = tmp->next;
08119 }
08120 return RESULT_FAILURE;
08121 }
08122
08123 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
08124 {
08125 int res;
08126 pthread_t threadid;
08127 struct ast_channel *chan;
08128
08129
08130
08131 switch (event) {
08132 case DAHDI_EVENT_NONE:
08133 case DAHDI_EVENT_BITSCHANGED:
08134 break;
08135 case DAHDI_EVENT_WINKFLASH:
08136 case DAHDI_EVENT_RINGOFFHOOK:
08137 if (i->inalarm) break;
08138 if (i->radio) break;
08139
08140 switch (i->sig) {
08141 case SIG_FXOLS:
08142 case SIG_FXOGS:
08143 case SIG_FXOKS:
08144 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08145 if (res && (errno == EBUSY))
08146 break;
08147 if (i->cidspill) {
08148
08149 ast_free(i->cidspill);
08150 i->cidspill = NULL;
08151 }
08152 if (i->immediate) {
08153 dahdi_enable_ec(i);
08154
08155 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08156 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08157 if (!chan) {
08158 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08159 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08160 if (res < 0)
08161 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08162 }
08163 } else {
08164
08165 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08166 if (chan) {
08167 if (has_voicemail(i))
08168 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08169 else
08170 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08171 if (res < 0)
08172 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08173 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08174 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08175 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08176 if (res < 0)
08177 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08178 ast_hangup(chan);
08179 }
08180 } else
08181 ast_log(LOG_WARNING, "Unable to create channel\n");
08182 }
08183 break;
08184 case SIG_FXSLS:
08185 case SIG_FXSGS:
08186 case SIG_FXSKS:
08187 i->ringt = i->ringt_base;
08188
08189 case SIG_EMWINK:
08190 case SIG_FEATD:
08191 case SIG_FEATDMF:
08192 case SIG_FEATDMF_TA:
08193 case SIG_E911:
08194 case SIG_FGC_CAMA:
08195 case SIG_FGC_CAMAMF:
08196 case SIG_FEATB:
08197 case SIG_EM:
08198 case SIG_EM_E1:
08199 case SIG_SFWINK:
08200 case SIG_SF_FEATD:
08201 case SIG_SF_FEATDMF:
08202 case SIG_SF_FEATB:
08203 case SIG_SF:
08204
08205 if (i->cid_start == CID_START_POLARITY_IN) {
08206 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08207 } else {
08208 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08209 }
08210
08211 if (!chan) {
08212 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08213 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08214 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08215 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08216 if (res < 0) {
08217 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08218 }
08219 ast_hangup(chan);
08220 }
08221 break;
08222 default:
08223 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08224 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08225 if (res < 0)
08226 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08227 return NULL;
08228 }
08229 break;
08230 case DAHDI_EVENT_NOALARM:
08231 i->inalarm = 0;
08232 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08233 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08234 "Channel: %d\r\n", i->channel);
08235 break;
08236 case DAHDI_EVENT_ALARM:
08237 i->inalarm = 1;
08238 res = get_alarms(i);
08239 handle_alarms(i, res);
08240
08241 case DAHDI_EVENT_ONHOOK:
08242 if (i->radio)
08243 break;
08244
08245 switch (i->sig) {
08246 case SIG_FXOLS:
08247 case SIG_FXOGS:
08248 case SIG_FEATD:
08249 case SIG_FEATDMF:
08250 case SIG_FEATDMF_TA:
08251 case SIG_E911:
08252 case SIG_FGC_CAMA:
08253 case SIG_FGC_CAMAMF:
08254 case SIG_FEATB:
08255 case SIG_EM:
08256 case SIG_EM_E1:
08257 case SIG_EMWINK:
08258 case SIG_SF_FEATD:
08259 case SIG_SF_FEATDMF:
08260 case SIG_SF_FEATB:
08261 case SIG_SF:
08262 case SIG_SFWINK:
08263 case SIG_FXSLS:
08264 case SIG_FXSGS:
08265 case SIG_FXSKS:
08266 case SIG_GR303FXSKS:
08267 dahdi_disable_ec(i);
08268 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08269 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08270 break;
08271 case SIG_GR303FXOKS:
08272 case SIG_FXOKS:
08273 dahdi_disable_ec(i);
08274
08275 #ifdef ZHONE_HACK
08276 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08277 usleep(1);
08278 #endif
08279 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08280 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08281 break;
08282 case SIG_PRI:
08283 case SIG_SS7:
08284 case SIG_BRI:
08285 case SIG_BRI_PTMP:
08286 dahdi_disable_ec(i);
08287 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08288 break;
08289 default:
08290 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08291 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08292 return NULL;
08293 }
08294 break;
08295 case DAHDI_EVENT_POLARITY:
08296 switch (i->sig) {
08297 case SIG_FXSLS:
08298 case SIG_FXSKS:
08299 case SIG_FXSGS:
08300
08301
08302
08303
08304 if (i->hanguponpolarityswitch)
08305 i->polarity = POLARITY_REV;
08306 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08307 i->polarity = POLARITY_REV;
08308 ast_verb(2, "Starting post polarity "
08309 "CID detection on channel %d\n",
08310 i->channel);
08311 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08312 if (!chan) {
08313 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08314 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08315 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08316 }
08317 }
08318 break;
08319 default:
08320 ast_log(LOG_WARNING, "handle_init_event detected "
08321 "polarity reversal on non-FXO (SIG_FXS) "
08322 "interface %d\n", i->channel);
08323 }
08324 break;
08325 case DAHDI_EVENT_REMOVED:
08326 ast_log(LOG_NOTICE,
08327 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08328 i->channel);
08329 return i;
08330 case DAHDI_EVENT_NEONMWI_ACTIVE:
08331 if (i->mwimonitor_neon) {
08332 notify_message(i->mailbox, 1);
08333 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08334 }
08335 break;
08336 case DAHDI_EVENT_NEONMWI_INACTIVE:
08337 if (i->mwimonitor_neon) {
08338 notify_message(i->mailbox, 0);
08339 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08340 }
08341 break;
08342 }
08343 return NULL;
08344 }
08345
08346 static void *do_monitor(void *data)
08347 {
08348 int count, res, res2, spoint, pollres=0;
08349 struct dahdi_pvt *i;
08350 struct dahdi_pvt *last = NULL;
08351 struct dahdi_pvt *doomed;
08352 time_t thispass = 0, lastpass = 0;
08353 int found;
08354 char buf[1024];
08355 struct pollfd *pfds=NULL;
08356 int lastalloc = -1;
08357
08358
08359
08360 #if 0
08361 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08362 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08363 return NULL;
08364 }
08365 ast_debug(1, "Monitor starting...\n");
08366 #endif
08367 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08368
08369 for (;;) {
08370
08371 ast_mutex_lock(&iflock);
08372 if (!pfds || (lastalloc != ifcount)) {
08373 if (pfds) {
08374 ast_free(pfds);
08375 pfds = NULL;
08376 }
08377 if (ifcount) {
08378 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08379 ast_mutex_unlock(&iflock);
08380 return NULL;
08381 }
08382 }
08383 lastalloc = ifcount;
08384 }
08385
08386
08387 count = 0;
08388 i = iflist;
08389 while (i) {
08390 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08391 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
08392
08393 pfds[count].fd = i->subs[SUB_REAL].dfd;
08394 pfds[count].events = POLLPRI;
08395 pfds[count].revents = 0;
08396
08397
08398 if (i->cidspill || i->mwimonitor_fsk)
08399 pfds[count].events |= POLLIN;
08400 count++;
08401 }
08402 }
08403 i = i->next;
08404 }
08405
08406 ast_mutex_unlock(&iflock);
08407
08408 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08409 pthread_testcancel();
08410
08411 res = poll(pfds, count, 1000);
08412 pthread_testcancel();
08413 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08414
08415
08416 if (res < 0) {
08417 if ((errno != EAGAIN) && (errno != EINTR))
08418 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08419 continue;
08420 }
08421
08422
08423 ast_mutex_lock(&iflock);
08424 found = 0;
08425 spoint = 0;
08426 lastpass = thispass;
08427 thispass = time(NULL);
08428 i = iflist;
08429 doomed = NULL;
08430 for (i = iflist;; i = i->next) {
08431 if (doomed) {
08432 int res;
08433 res = dahdi_destroy_channel_bynum(doomed->channel);
08434 if (!res) {
08435 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08436 }
08437 doomed = NULL;
08438 }
08439 if (!i) {
08440 break;
08441 }
08442
08443 if (thispass != lastpass) {
08444 if (!found && ((i == last) || ((i == iflist) && !last))) {
08445 last = i;
08446 if (last) {
08447 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) {
08448 res = has_voicemail(last);
08449 if (last->msgstate != res) {
08450
08451
08452
08453
08454 pthread_attr_t attr;
08455 pthread_t threadid;
08456 struct mwi_thread_data *mtd;
08457 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08458 if (res2) {
08459
08460 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08461 }
08462 pthread_attr_init(&attr);
08463 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08464 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08465 last->msgstate = res;
08466 mtd->pvt = last;
08467 last->mwisendactive = 1;
08468 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
08469 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
08470 ast_free(mtd);
08471 last->mwisendactive = 0;
08472 }
08473 }
08474 found ++;
08475 }
08476 }
08477 last = last->next;
08478 }
08479 }
08480 }
08481 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08482 if (i->radio && !i->owner)
08483 {
08484 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08485 if (res)
08486 {
08487 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08488
08489 ast_mutex_unlock(&iflock);
08490 doomed = handle_init_event(i, res);
08491 ast_mutex_lock(&iflock);
08492 }
08493 continue;
08494 }
08495 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08496 if (pollres & POLLIN) {
08497 if (i->owner || i->subs[SUB_REAL].owner) {
08498 #ifdef HAVE_PRI
08499 if (!i->pri)
08500 #endif
08501 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08502 continue;
08503 }
08504 if (!i->cidspill && !i->mwimonitor_fsk) {
08505 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08506 continue;
08507 }
08508 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08509 if (res > 0) {
08510 if (i->mwimonitor_fsk) {
08511 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08512 pthread_attr_t attr;
08513 pthread_t threadid;
08514 struct mwi_thread_data *mtd;
08515
08516 pthread_attr_init(&attr);
08517 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08518
08519 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08520 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08521 mtd->pvt = i;
08522 memcpy(mtd->buf, buf, res);
08523 mtd->len = res;
08524 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08525 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08526 ast_free(mtd);
08527 }
08528 i->mwimonitoractive = 1;
08529 }
08530 }
08531 }
08532 } else {
08533 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08534 }
08535 }
08536 if (pollres & POLLPRI) {
08537 if (i->owner || i->subs[SUB_REAL].owner) {
08538 #ifdef HAVE_PRI
08539 if (!i->pri)
08540 #endif
08541 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08542 continue;
08543 }
08544 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08545 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08546
08547 ast_mutex_unlock(&iflock);
08548 doomed = handle_init_event(i, res);
08549 ast_mutex_lock(&iflock);
08550 }
08551 }
08552 }
08553 ast_mutex_unlock(&iflock);
08554 }
08555
08556 return NULL;
08557
08558 }
08559
08560 static int restart_monitor(void)
08561 {
08562
08563 if (monitor_thread == AST_PTHREADT_STOP)
08564 return 0;
08565 ast_mutex_lock(&monlock);
08566 if (monitor_thread == pthread_self()) {
08567 ast_mutex_unlock(&monlock);
08568 ast_log(LOG_WARNING, "Cannot kill myself\n");
08569 return -1;
08570 }
08571 if (monitor_thread != AST_PTHREADT_NULL) {
08572
08573 pthread_kill(monitor_thread, SIGURG);
08574 } else {
08575
08576 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08577 ast_mutex_unlock(&monlock);
08578 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08579 return -1;
08580 }
08581 }
08582 ast_mutex_unlock(&monlock);
08583 return 0;
08584 }
08585
08586 #ifdef HAVE_PRI
08587 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08588 {
08589 int x;
08590 int trunkgroup;
08591
08592 trunkgroup = pris[*span].mastertrunkgroup;
08593 if (trunkgroup) {
08594
08595 for (x = 0; x < NUM_SPANS; x++) {
08596 if (pris[x].trunkgroup == trunkgroup) {
08597 *span = x;
08598 return 0;
08599 }
08600 }
08601 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08602 *span = -1;
08603 } else {
08604 if (pris[*span].trunkgroup) {
08605 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08606 *span = -1;
08607 } else if (pris[*span].mastertrunkgroup) {
08608 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08609 *span = -1;
08610 } else {
08611 if (si->totalchans == 31) {
08612
08613 pris[*span].dchannels[0] = 16 + offset;
08614 } else if (si->totalchans == 24) {
08615
08616 pris[*span].dchannels[0] = 24 + offset;
08617 } else if (si->totalchans == 3) {
08618
08619 pris[*span].dchannels[0] = 3 + offset;
08620 } else {
08621 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);
08622 *span = -1;
08623 return 0;
08624 }
08625 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08626 pris[*span].offset = offset;
08627 pris[*span].span = *span + 1;
08628 }
08629 }
08630 return 0;
08631 }
08632
08633 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08634 {
08635 struct dahdi_spaninfo si;
08636 struct dahdi_params p;
08637 int fd;
08638 int span;
08639 int ospan=0;
08640 int x,y;
08641 for (x = 0; x < NUM_SPANS; x++) {
08642 if (pris[x].trunkgroup == trunkgroup) {
08643 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08644 return -1;
08645 }
08646 }
08647 for (y = 0; y < NUM_DCHANS; y++) {
08648 if (!channels[y])
08649 break;
08650 memset(&si, 0, sizeof(si));
08651 memset(&p, 0, sizeof(p));
08652 fd = open("/dev/dahdi/channel", O_RDWR);
08653 if (fd < 0) {
08654 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08655 return -1;
08656 }
08657 x = channels[y];
08658 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08659 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08660 close(fd);
08661 return -1;
08662 }
08663 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08664 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08665 return -1;
08666 }
08667 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08668 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08669 close(fd);
08670 return -1;
08671 }
08672 span = p.spanno - 1;
08673 if (pris[span].trunkgroup) {
08674 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08675 close(fd);
08676 return -1;
08677 }
08678 if (pris[span].pvts[0]) {
08679 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08680 close(fd);
08681 return -1;
08682 }
08683 if (!y) {
08684 pris[span].trunkgroup = trunkgroup;
08685 pris[span].offset = channels[y] - p.chanpos;
08686 ospan = span;
08687 }
08688 pris[ospan].dchannels[y] = channels[y];
08689 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08690 pris[span].span = span + 1;
08691 close(fd);
08692 }
08693 return 0;
08694 }
08695
08696 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08697 {
08698 if (pris[span].mastertrunkgroup) {
08699 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);
08700 return -1;
08701 }
08702 pris[span].mastertrunkgroup = trunkgroup;
08703 pris[span].prilogicalspan = logicalspan;
08704 return 0;
08705 }
08706
08707 #endif
08708
08709 #ifdef HAVE_SS7
08710
08711 static unsigned int parse_pointcode(const char *pcstring)
08712 {
08713 unsigned int code1, code2, code3;
08714 int numvals;
08715
08716 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
08717 if (numvals == 1)
08718 return code1;
08719 if (numvals == 3)
08720 return (code1 << 16) | (code2 << 8) | code3;
08721
08722 return 0;
08723 }
08724
08725 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
08726 {
08727 if ((linkset < 0) || (linkset >= NUM_SPANS))
08728 return NULL;
08729 else
08730 return &linksets[linkset - 1];
08731 }
08732 #endif
08733
08734
08735
08736
08737
08738
08739 static int sigtype_to_signalling(int sigtype)
08740 {
08741 return sigtype;
08742 }
08743
08744 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08745 {
08746
08747 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08748 char fn[80];
08749 struct dahdi_bufferinfo bi;
08750
08751 int res;
08752 int span = 0;
08753 int here = 0;
08754 int x;
08755 struct dahdi_pvt **wlist;
08756 struct dahdi_pvt **wend;
08757 struct dahdi_params p;
08758
08759 wlist = &iflist;
08760 wend = &ifend;
08761
08762 #ifdef HAVE_PRI
08763 if (pri) {
08764 wlist = &pri->crvs;
08765 wend = &pri->crvend;
08766 }
08767 #endif
08768
08769 tmp2 = *wlist;
08770 prev = NULL;
08771
08772 while (tmp2) {
08773 if (!tmp2->destroy) {
08774 if (tmp2->channel == channel) {
08775 tmp = tmp2;
08776 here = 1;
08777 break;
08778 }
08779 if (tmp2->channel > channel) {
08780 break;
08781 }
08782 }
08783 prev = tmp2;
08784 tmp2 = tmp2->next;
08785 }
08786
08787 if (!here && reloading != 1) {
08788 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08789 if (tmp)
08790 free(tmp);
08791 return NULL;
08792 }
08793 ast_mutex_init(&tmp->lock);
08794 ifcount++;
08795 for (x = 0; x < 3; x++)
08796 tmp->subs[x].dfd = -1;
08797 tmp->channel = channel;
08798 tmp->priindication_oob = conf->chan.priindication_oob;
08799 }
08800
08801 if (tmp) {
08802 int chan_sig = conf->chan.sig;
08803 if (!here) {
08804 if ((channel != CHAN_PSEUDO) && !pri) {
08805 int count = 0;
08806 snprintf(fn, sizeof(fn), "%d", channel);
08807
08808 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08809 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08810 usleep(1);
08811 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08812 count++;
08813 }
08814
08815 if (tmp->subs[SUB_REAL].dfd < 0) {
08816 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);
08817 destroy_dahdi_pvt(&tmp);
08818 return NULL;
08819 }
08820 memset(&p, 0, sizeof(p));
08821 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08822 if (res < 0) {
08823 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08824 destroy_dahdi_pvt(&tmp);
08825 return NULL;
08826 }
08827 if (conf->is_sig_auto)
08828 chan_sig = sigtype_to_signalling(p.sigtype);
08829 if (p.sigtype != (chan_sig & 0x3ffff)) {
08830 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));
08831 destroy_dahdi_pvt(&tmp);
08832 return NULL;
08833 }
08834 tmp->law = p.curlaw;
08835 tmp->span = p.spanno;
08836 span = p.spanno - 1;
08837 } else {
08838 if (channel == CHAN_PSEUDO)
08839 chan_sig = 0;
08840 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08841 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08842 return NULL;
08843 }
08844 }
08845 #ifdef HAVE_SS7
08846 if (chan_sig == SIG_SS7) {
08847 struct dahdi_ss7 *ss7;
08848 int clear = 0;
08849 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08850 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08851 destroy_dahdi_pvt(&tmp);
08852 return NULL;
08853 }
08854
08855 ss7 = ss7_resolve_linkset(cur_linkset);
08856 if (!ss7) {
08857 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08858 destroy_dahdi_pvt(&tmp);
08859 return NULL;
08860 }
08861 if (cur_cicbeginswith < 0) {
08862 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08863 destroy_dahdi_pvt(&tmp);
08864 return NULL;
08865 }
08866
08867 tmp->cic = cur_cicbeginswith++;
08868
08869
08870 tmp->dpc = cur_defaultdpc;
08871
08872 tmp->ss7 = ss7;
08873 tmp->ss7call = NULL;
08874 ss7->pvts[ss7->numchans++] = tmp;
08875
08876 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
08877 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
08878 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
08879 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
08880
08881 ss7->called_nai = conf->ss7.called_nai;
08882 ss7->calling_nai = conf->ss7.calling_nai;
08883 }
08884 #endif
08885 #ifdef HAVE_PRI
08886 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08887 int offset;
08888 int myswitchtype;
08889 int matchesdchan;
08890 int x,y;
08891 offset = 0;
08892 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
08893 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08894 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08895 destroy_dahdi_pvt(&tmp);
08896 return NULL;
08897 }
08898 if (span >= NUM_SPANS) {
08899 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08900 destroy_dahdi_pvt(&tmp);
08901 return NULL;
08902 } else {
08903 struct dahdi_spaninfo si;
08904 si.spanno = 0;
08905 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08906 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08907 destroy_dahdi_pvt(&tmp);
08908 return NULL;
08909 }
08910
08911 tmp->logicalspan = pris[span].prilogicalspan;
08912 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08913 if (span < 0) {
08914 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08915 destroy_dahdi_pvt(&tmp);
08916 return NULL;
08917 }
08918 if ((chan_sig == SIG_PRI) ||
08919 (chan_sig == SIG_BRI) ||
08920 (chan_sig == SIG_BRI_PTMP))
08921 myswitchtype = conf->pri.switchtype;
08922 else
08923 myswitchtype = PRI_SWITCH_GR303_TMC;
08924
08925 matchesdchan=0;
08926 for (x = 0; x < NUM_SPANS; x++) {
08927 for (y = 0; y < NUM_DCHANS; y++) {
08928 if (pris[x].dchannels[y] == tmp->channel) {
08929 matchesdchan = 1;
08930 break;
08931 }
08932 }
08933 }
08934 offset = p.chanpos;
08935 if (!matchesdchan) {
08936 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08937 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08938 destroy_dahdi_pvt(&tmp);
08939 return NULL;
08940 }
08941 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08942 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08943 destroy_dahdi_pvt(&tmp);
08944 return NULL;
08945 }
08946 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08947 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08948 destroy_dahdi_pvt(&tmp);
08949 return NULL;
08950 }
08951 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08952 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08953 destroy_dahdi_pvt(&tmp);
08954 return NULL;
08955 }
08956 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08957 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08958 destroy_dahdi_pvt(&tmp);
08959 return NULL;
08960 }
08961 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08962 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08963 destroy_dahdi_pvt(&tmp);
08964 return NULL;
08965 }
08966 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08967 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08968 destroy_dahdi_pvt(&tmp);
08969 return NULL;
08970 }
08971 if (pris[span].numchans >= MAX_CHANNELS) {
08972 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08973 pris[span].trunkgroup);
08974 destroy_dahdi_pvt(&tmp);
08975 return NULL;
08976 }
08977
08978 pris[span].sig = chan_sig;
08979 pris[span].nodetype = conf->pri.nodetype;
08980 pris[span].switchtype = myswitchtype;
08981 pris[span].nsf = conf->pri.nsf;
08982 pris[span].dialplan = conf->pri.dialplan;
08983 pris[span].localdialplan = conf->pri.localdialplan;
08984 pris[span].pvts[pris[span].numchans++] = tmp;
08985 pris[span].minunused = conf->pri.minunused;
08986 pris[span].minidle = conf->pri.minidle;
08987 pris[span].overlapdial = conf->pri.overlapdial;
08988 #ifdef HAVE_PRI_INBANDDISCONNECT
08989 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08990 #endif
08991 pris[span].facilityenable = conf->pri.facilityenable;
08992 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08993 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08994 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08995 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08996 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08997 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08998 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08999 pris[span].resetinterval = conf->pri.resetinterval;
09000
09001 tmp->pri = &pris[span];
09002 tmp->prioffset = offset;
09003 tmp->call = NULL;
09004 } else {
09005 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
09006 destroy_dahdi_pvt(&tmp);
09007 return NULL;
09008 }
09009 }
09010 } else {
09011 tmp->prioffset = 0;
09012 }
09013 #endif
09014 } else {
09015 chan_sig = tmp->sig;
09016 if (tmp->subs[SUB_REAL].dfd > -1) {
09017 memset(&p, 0, sizeof(p));
09018 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
09019 }
09020 }
09021
09022 switch (chan_sig) {
09023 case SIG_FXSKS:
09024 case SIG_FXSLS:
09025 case SIG_EM:
09026 case SIG_EM_E1:
09027 case SIG_EMWINK:
09028 case SIG_FEATD:
09029 case SIG_FEATDMF:
09030 case SIG_FEATDMF_TA:
09031 case SIG_FEATB:
09032 case SIG_E911:
09033 case SIG_SF:
09034 case SIG_SFWINK:
09035 case SIG_FGC_CAMA:
09036 case SIG_FGC_CAMAMF:
09037 case SIG_SF_FEATD:
09038 case SIG_SF_FEATDMF:
09039 case SIG_SF_FEATB:
09040 p.starttime = 250;
09041 break;
09042 }
09043
09044 if (tmp->radio) {
09045
09046 p.channo = channel;
09047 p.rxwinktime = 1;
09048 p.rxflashtime = 1;
09049 p.starttime = 1;
09050 p.debouncetime = 5;
09051 }
09052 if (!tmp->radio) {
09053 p.channo = channel;
09054
09055 if (conf->timing.prewinktime >= 0)
09056 p.prewinktime = conf->timing.prewinktime;
09057 if (conf->timing.preflashtime >= 0)
09058 p.preflashtime = conf->timing.preflashtime;
09059 if (conf->timing.winktime >= 0)
09060 p.winktime = conf->timing.winktime;
09061 if (conf->timing.flashtime >= 0)
09062 p.flashtime = conf->timing.flashtime;
09063 if (conf->timing.starttime >= 0)
09064 p.starttime = conf->timing.starttime;
09065 if (conf->timing.rxwinktime >= 0)
09066 p.rxwinktime = conf->timing.rxwinktime;
09067 if (conf->timing.rxflashtime >= 0)
09068 p.rxflashtime = conf->timing.rxflashtime;
09069 if (conf->timing.debouncetime >= 0)
09070 p.debouncetime = conf->timing.debouncetime;
09071 }
09072
09073
09074 if (tmp->subs[SUB_REAL].dfd >= 0)
09075 {
09076 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09077 if (res < 0) {
09078 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09079 destroy_dahdi_pvt(&tmp);
09080 return NULL;
09081 }
09082 }
09083 #if 1
09084 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09085 memset(&bi, 0, sizeof(bi));
09086 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09087 if (!res) {
09088 bi.txbufpolicy = conf->chan.buf_policy;
09089 bi.rxbufpolicy = conf->chan.buf_policy;
09090 bi.numbufs = conf->chan.buf_no;
09091 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09092 if (res < 0) {
09093 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09094 }
09095 } else
09096 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09097 }
09098 #endif
09099 tmp->immediate = conf->chan.immediate;
09100 tmp->transfertobusy = conf->chan.transfertobusy;
09101 if (chan_sig & __DAHDI_SIG_FXS) {
09102 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
09103 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
09104 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
09105 }
09106 tmp->sig = chan_sig;
09107 tmp->outsigmod = conf->chan.outsigmod;
09108 tmp->ringt_base = ringt_base;
09109 tmp->firstradio = 0;
09110 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09111 tmp->permcallwaiting = conf->chan.callwaiting;
09112 else
09113 tmp->permcallwaiting = 0;
09114
09115 tmp->destroy = 0;
09116 tmp->drings = conf->chan.drings;
09117
09118
09119 if (tmp->drings.ringnum[0].range == 0)
09120 tmp->drings.ringnum[0].range = 10;
09121 if (tmp->drings.ringnum[1].range == 0)
09122 tmp->drings.ringnum[1].range = 10;
09123 if (tmp->drings.ringnum[2].range == 0)
09124 tmp->drings.ringnum[2].range = 10;
09125
09126 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
09127 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09128 tmp->threewaycalling = conf->chan.threewaycalling;
09129 tmp->adsi = conf->chan.adsi;
09130 tmp->use_smdi = conf->chan.use_smdi;
09131 tmp->permhidecallerid = conf->chan.hidecallerid;
09132 tmp->callreturn = conf->chan.callreturn;
09133 tmp->echocancel = conf->chan.echocancel;
09134 tmp->echotraining = conf->chan.echotraining;
09135 tmp->pulse = conf->chan.pulse;
09136 if (tmp->echocancel.head.tap_length) {
09137 tmp->echocanbridged = conf->chan.echocanbridged;
09138 } else {
09139 if (conf->chan.echocanbridged)
09140 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09141 tmp->echocanbridged = 0;
09142 }
09143 tmp->busydetect = conf->chan.busydetect;
09144 tmp->busycount = conf->chan.busycount;
09145 tmp->busy_tonelength = conf->chan.busy_tonelength;
09146 tmp->busy_quietlength = conf->chan.busy_quietlength;
09147 tmp->callprogress = conf->chan.callprogress;
09148 tmp->cancallforward = conf->chan.cancallforward;
09149 tmp->dtmfrelax = conf->chan.dtmfrelax;
09150 tmp->callwaiting = tmp->permcallwaiting;
09151 tmp->hidecallerid = tmp->permhidecallerid;
09152 tmp->channel = channel;
09153 tmp->stripmsd = conf->chan.stripmsd;
09154 tmp->use_callerid = conf->chan.use_callerid;
09155 tmp->cid_signalling = conf->chan.cid_signalling;
09156 tmp->cid_start = conf->chan.cid_start;
09157 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09158 tmp->restrictcid = conf->chan.restrictcid;
09159 tmp->use_callingpres = conf->chan.use_callingpres;
09160 tmp->priexclusive = conf->chan.priexclusive;
09161 if (tmp->usedistinctiveringdetection) {
09162 if (!tmp->use_callerid) {
09163 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09164 tmp->use_callerid = 1;
09165 }
09166 }
09167
09168 if (tmp->cid_signalling == CID_SIG_SMDI) {
09169 if (!tmp->use_smdi) {
09170 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09171 tmp->use_smdi = 1;
09172 }
09173 }
09174 if (tmp->use_smdi) {
09175 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09176 if (!(tmp->smdi_iface)) {
09177 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09178 tmp->use_smdi = 0;
09179 }
09180 }
09181
09182 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09183 tmp->amaflags = conf->chan.amaflags;
09184 if (!here) {
09185 tmp->confno = -1;
09186 tmp->propconfno = -1;
09187 }
09188 tmp->canpark = conf->chan.canpark;
09189 tmp->transfer = conf->chan.transfer;
09190 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09191 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09192 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09193 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09194 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09195 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
09196 tmp->cid_ton = 0;
09197 if ((tmp->sig != SIG_PRI) || (tmp->sig != SIG_SS7) || (tmp->sig != SIG_BRI) || (tmp->sig != SIG_BRI_PTMP)) {
09198 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09199 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09200 } else {
09201 tmp->cid_num[0] = '\0';
09202 tmp->cid_name[0] = '\0';
09203 }
09204 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09205 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
09206 char *mailbox, *context;
09207 mailbox = context = ast_strdupa(tmp->mailbox);
09208 strsep(&context, "@");
09209 if (ast_strlen_zero(context))
09210 context = "default";
09211 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
09212 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
09213 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
09214 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
09215 AST_EVENT_IE_END);
09216 }
09217 tmp->msgstate = -1;
09218 tmp->group = conf->chan.group;
09219 tmp->callgroup = conf->chan.callgroup;
09220 tmp->pickupgroup= conf->chan.pickupgroup;
09221 if (conf->chan.vars) {
09222 struct ast_variable *v, *tmpvar;
09223 for (v = conf->chan.vars ; v ; v = v->next) {
09224 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
09225 tmpvar->next = tmp->vars;
09226 tmp->vars = tmpvar;
09227 }
09228 }
09229 }
09230 tmp->cid_rxgain = conf->chan.cid_rxgain;
09231 tmp->rxgain = conf->chan.rxgain;
09232 tmp->txgain = conf->chan.txgain;
09233 tmp->tonezone = conf->chan.tonezone;
09234 tmp->onhooktime = time(NULL);
09235 if (tmp->subs[SUB_REAL].dfd > -1) {
09236 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09237 if (tmp->dsp)
09238 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09239 update_conf(tmp);
09240 if (!here) {
09241 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
09242
09243 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09244 }
09245 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09246 #ifdef HAVE_PRI
09247
09248 if (tmp->pri && !pri_is_up(tmp->pri))
09249 tmp->inalarm = 1;
09250 #endif
09251 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09252 tmp->inalarm = 1;
09253 handle_alarms(tmp, res);
09254 }
09255 }
09256
09257 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09258 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09259 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09260 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09261 if (!here) {
09262 tmp->locallyblocked = tmp->remotelyblocked = 0;
09263 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09264 tmp->inservice = 0;
09265 else
09266 tmp->inservice = 1;
09267 }
09268 }
09269 if (tmp && !here) {
09270
09271 if (!*wlist) {
09272 *wlist = tmp;
09273 tmp->prev = NULL;
09274 tmp->next = NULL;
09275 *wend = tmp;
09276 } else {
09277
09278 struct dahdi_pvt *working = *wlist;
09279
09280
09281 if (working->channel > tmp->channel) {
09282 tmp->next = *wlist;
09283 tmp->prev = NULL;
09284 (*wlist)->prev = tmp;
09285 *wlist = tmp;
09286 } else {
09287
09288 while (working) {
09289
09290 if (working->next) {
09291 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09292 tmp->next = working->next;
09293 tmp->prev = working;
09294 working->next->prev = tmp;
09295 working->next = tmp;
09296 break;
09297 }
09298 } else {
09299
09300 if (working->channel < tmp->channel) {
09301 working->next = tmp;
09302 tmp->next = NULL;
09303 tmp->prev = working;
09304 *wend = tmp;
09305 break;
09306 }
09307 }
09308 working = working->next;
09309 }
09310 }
09311 }
09312 }
09313 return tmp;
09314 }
09315
09316 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09317 {
09318 int res;
09319 struct dahdi_params par;
09320
09321
09322 if (groupmatch) {
09323 if ((p->group & groupmatch) != groupmatch)
09324 return 0;
09325 *groupmatched = 1;
09326 }
09327
09328 if (channelmatch != -1) {
09329 if (p->channel != channelmatch)
09330 return 0;
09331 *channelmatched = 1;
09332 }
09333
09334 if (busy) {
09335 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09336 *busy = 1;
09337 }
09338
09339 if (p->dnd)
09340 return 0;
09341
09342 if (p->guardtime && (time(NULL) < p->guardtime))
09343 return 0;
09344
09345 if (p->locallyblocked || p->remotelyblocked)
09346 return 0;
09347
09348
09349 if (!p->owner) {
09350 #ifdef HAVE_PRI
09351
09352 if (p->pri) {
09353 if (p->resetting || p->call)
09354 return 0;
09355 else
09356 return 1;
09357 }
09358 #endif
09359 #ifdef HAVE_SS7
09360
09361 if (p->ss7) {
09362 if (p->ss7call)
09363 return 0;
09364 else
09365 return 1;
09366 }
09367 #endif
09368 if (!(p->radio || (p->oprmode < 0)))
09369 {
09370 if (!p->sig || (p->sig == SIG_FXSLS))
09371 return 1;
09372
09373 if (p->subs[SUB_REAL].dfd > -1) {
09374 memset(&par, 0, sizeof(par));
09375 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09376 } else {
09377
09378 res = 0;
09379 par.rxisoffhook = 0;
09380 }
09381 if (res) {
09382 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09383 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09384
09385
09386
09387 if (par.rxbits > -1)
09388 return 1;
09389 if (par.rxisoffhook)
09390 return 1;
09391 else
09392 return 0;
09393 } else if (par.rxisoffhook) {
09394 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09395
09396 #ifdef DAHDI_CHECK_HOOKSTATE
09397 return 0;
09398 #else
09399 return 1;
09400 #endif
09401 }
09402 }
09403 return 1;
09404 }
09405
09406
09407 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09408 return 0;
09409
09410 if (!p->callwaiting) {
09411
09412 return 0;
09413 }
09414
09415 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09416
09417 return 0;
09418 }
09419
09420 if ((p->owner->_state != AST_STATE_UP) &&
09421 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09422
09423 return 0;
09424 }
09425 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09426
09427 return 0;
09428 }
09429
09430 return 1;
09431 }
09432
09433 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09434 {
09435 struct dahdi_pvt *p;
09436 struct dahdi_bufferinfo bi;
09437 int res;
09438
09439 if ((p = ast_malloc(sizeof(*p)))) {
09440 memcpy(p, src, sizeof(struct dahdi_pvt));
09441 ast_mutex_init(&p->lock);
09442 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09443
09444 if (p->subs[SUB_REAL].dfd < 0) {
09445 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09446 destroy_dahdi_pvt(&p);
09447 return NULL;
09448 }
09449 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09450 if (!res) {
09451 bi.txbufpolicy = src->buf_policy;
09452 bi.rxbufpolicy = src->buf_policy;
09453 bi.numbufs = src->buf_no;
09454 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09455 if (res < 0) {
09456 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09457 }
09458 } else
09459 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09460 }
09461 p->destroy = 1;
09462 p->next = iflist;
09463 p->prev = NULL;
09464 iflist = p;
09465 if (iflist->next)
09466 iflist->next->prev = p;
09467 return p;
09468 }
09469
09470
09471 #ifdef HAVE_PRI
09472 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09473 {
09474 int x;
09475 if (backwards)
09476 x = pri->numchans;
09477 else
09478 x = 0;
09479 for (;;) {
09480 if (backwards && (x < 0))
09481 break;
09482 if (!backwards && (x >= pri->numchans))
09483 break;
09484 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09485 ast_debug(1, "Found empty available channel %d/%d\n",
09486 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09487 return x;
09488 }
09489 if (backwards)
09490 x--;
09491 else
09492 x++;
09493 }
09494 return -1;
09495 }
09496 #endif
09497
09498 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09499 {
09500 ast_group_t groupmatch = 0;
09501 int channelmatch = -1;
09502 int roundrobin = 0;
09503 int callwait = 0;
09504 int busy = 0;
09505 struct dahdi_pvt *p;
09506 struct ast_channel *tmp = NULL;
09507 char *dest=NULL;
09508 int x;
09509 char *s;
09510 char opt=0;
09511 int res=0, y=0;
09512 int backwards = 0;
09513 #ifdef HAVE_PRI
09514 int crv;
09515 int bearer = -1;
09516 int trunkgroup;
09517 struct dahdi_pri *pri=NULL;
09518 #endif
09519 struct dahdi_pvt *exitpvt, *start, *end;
09520 ast_mutex_t *lock;
09521 int channelmatched = 0;
09522 int groupmatched = 0;
09523
09524
09525
09526
09527
09528
09529
09530
09531
09532
09533
09534
09535
09536
09537
09538
09539
09540
09541
09542 lock = &iflock;
09543 start = iflist;
09544 end = ifend;
09545 if (data) {
09546 dest = ast_strdupa((char *)data);
09547 } else {
09548 ast_log(LOG_WARNING, "Channel requested with no data\n");
09549 return NULL;
09550 }
09551 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09552
09553 char *stringp;
09554
09555 stringp = dest + 1;
09556 s = strsep(&stringp, "/");
09557 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09558 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09559 return NULL;
09560 }
09561 groupmatch = ((ast_group_t) 1 << x);
09562 if (toupper(dest[0]) == 'G') {
09563 if (dest[0] == 'G') {
09564 backwards = 1;
09565 p = ifend;
09566 } else
09567 p = iflist;
09568 } else {
09569 if (dest[0] == 'R') {
09570 backwards = 1;
09571 p = round_robin[x]?round_robin[x]->prev:ifend;
09572 if (!p)
09573 p = ifend;
09574 } else {
09575 p = round_robin[x]?round_robin[x]->next:iflist;
09576 if (!p)
09577 p = iflist;
09578 }
09579 roundrobin = 1;
09580 }
09581 } else {
09582 char *stringp;
09583
09584 stringp = dest;
09585 s = strsep(&stringp, "/");
09586 p = iflist;
09587 if (!strcasecmp(s, "pseudo")) {
09588
09589 x = CHAN_PSEUDO;
09590 channelmatch = x;
09591 }
09592 #ifdef HAVE_PRI
09593 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09594 if ((trunkgroup < 1) || (crv < 1)) {
09595 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09596 return NULL;
09597 }
09598 res--;
09599 for (x = 0; x < NUM_SPANS; x++) {
09600 if (pris[x].trunkgroup == trunkgroup) {
09601 pri = pris + x;
09602 lock = &pri->lock;
09603 start = pri->crvs;
09604 end = pri->crvend;
09605 break;
09606 }
09607 }
09608 if (!pri) {
09609 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09610 return NULL;
09611 }
09612 channelmatch = crv;
09613 p = pris[x].crvs;
09614 }
09615 #endif
09616 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09617 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09618 return NULL;
09619 } else {
09620 channelmatch = x;
09621 }
09622 }
09623
09624 ast_mutex_lock(lock);
09625 exitpvt = p;
09626 while (p && !tmp) {
09627 if (roundrobin)
09628 round_robin[x] = p;
09629 #if 0
09630 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09631 #endif
09632
09633 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09634 ast_debug(1, "Using channel %d\n", p->channel);
09635 if (p->inalarm)
09636 goto next;
09637
09638 callwait = (p->owner != NULL);
09639 #ifdef HAVE_PRI
09640 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09641 if (p->sig != SIG_FXSKS) {
09642
09643
09644 bearer = pri_find_empty_chan(pri, 0);
09645 if (bearer < 0) {
09646 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09647 p = NULL;
09648 break;
09649 }
09650 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09651 } else {
09652 if (alloc_sub(p, 0)) {
09653 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09654 p = NULL;
09655 break;
09656 } else
09657 ast_debug(1, "Allocated placeholder pseudo channel\n");
09658
09659 p->pri = pri;
09660 }
09661 }
09662 #endif
09663 if (p->channel == CHAN_PSEUDO) {
09664 p = chandup(p);
09665 if (!p) {
09666 break;
09667 }
09668 }
09669 if (p->owner) {
09670 if (alloc_sub(p, SUB_CALLWAIT)) {
09671 p = NULL;
09672 break;
09673 }
09674 }
09675 p->outgoing = 1;
09676 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09677 if (!tmp) {
09678 p->outgoing = 0;
09679 }
09680 #ifdef HAVE_PRI
09681 if (p->bearer) {
09682
09683 p->bearer->owner = tmp;
09684 }
09685 #endif
09686
09687 if (res > 1) {
09688 if (opt == 'c') {
09689
09690 p->confirmanswer = 1;
09691 } else if (opt == 'r') {
09692
09693 if (res < 3)
09694 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09695 else
09696 p->distinctivering = y;
09697 } else if (opt == 'd') {
09698
09699 p->digital = 1;
09700 if (tmp)
09701 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09702 } else {
09703 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09704 }
09705 }
09706
09707 if (tmp && callwait)
09708 tmp->cdrflags |= AST_CDR_CALLWAIT;
09709 break;
09710 }
09711 next:
09712 if (backwards) {
09713 p = p->prev;
09714 if (!p)
09715 p = end;
09716 } else {
09717 p = p->next;
09718 if (!p)
09719 p = start;
09720 }
09721
09722 if (p == exitpvt)
09723 break;
09724 }
09725 ast_mutex_unlock(lock);
09726 restart_monitor();
09727 if (callwait)
09728 *cause = AST_CAUSE_BUSY;
09729 else if (!tmp) {
09730 if (channelmatched) {
09731 if (busy)
09732 *cause = AST_CAUSE_BUSY;
09733 } else if (groupmatched) {
09734 *cause = AST_CAUSE_CONGESTION;
09735 }
09736 }
09737
09738 return tmp;
09739 }
09740
09741 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09742 static int dahdi_setlaw(int dfd, int law)
09743 {
09744 return ioctl(dfd, DAHDI_SETLAW, &law);
09745 }
09746 #endif
09747
09748 #ifdef HAVE_SS7
09749
09750 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
09751 {
09752 int i;
09753 int winner = -1;
09754 for (i = 0; i < linkset->numchans; i++) {
09755 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09756 winner = i;
09757 break;
09758 }
09759 }
09760 return winner;
09761 }
09762
09763 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09764 {
09765 unsigned char status[32];
09766 struct dahdi_pvt *p = NULL;
09767 int i, offset;
09768
09769 for (i = 0; i < linkset->numchans; i++) {
09770 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09771 p = linkset->pvts[i];
09772 offset = p->cic - startcic;
09773 status[offset] = 0;
09774 if (p->locallyblocked)
09775 status[offset] |= (1 << 0) | (1 << 4);
09776 if (p->remotelyblocked)
09777 status[offset] |= (1 << 1) | (1 << 5);
09778 if (p->ss7call) {
09779 if (p->outgoing)
09780 status[offset] |= (1 << 3);
09781 else
09782 status[offset] |= (1 << 2);
09783 } else
09784 status[offset] |= 0x3 << 2;
09785 }
09786 }
09787
09788 if (p)
09789 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09790 else
09791 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09792
09793 }
09794
09795 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
09796 {
09797 int i;
09798
09799 for (i = 0; i < linkset->numchans; i++) {
09800 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09801 if (state) {
09802 if (state[i])
09803 linkset->pvts[i]->remotelyblocked = block;
09804 } else
09805 linkset->pvts[i]->remotelyblocked = block;
09806 }
09807 }
09808 }
09809
09810 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09811 {
09812 int i;
09813
09814 for (i = 0; i < linkset->numchans; i++) {
09815 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09816 linkset->pvts[i]->inservice = 1;
09817 }
09818 }
09819
09820 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
09821 {
09822 int i, startcic = -1, endcic, dpc;
09823
09824 if (linkset->numchans <= 0)
09825 return;
09826
09827 startcic = linkset->pvts[0]->cic;
09828
09829 dpc = linkset->pvts[0]->dpc;
09830
09831 for (i = 0; i < linkset->numchans; i++) {
09832 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)) {
09833 continue;
09834 } else {
09835 endcic = linkset->pvts[i]->cic;
09836 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09837 isup_grs(linkset->ss7, startcic, endcic, dpc);
09838
09839
09840 if (linkset->pvts[i+1]) {
09841 startcic = linkset->pvts[i+1]->cic;
09842 dpc = linkset->pvts[i+1]->dpc;
09843 }
09844 }
09845 }
09846 }
09847
09848 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
09849 {
09850 if (p->loopedback != enable) {
09851 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09852 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09853 return;
09854 }
09855 p->loopedback = enable;
09856 }
09857 }
09858
09859
09860 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
09861 {
09862 struct ss7 *ss7 = linkset->ss7;
09863 int res;
09864 int law = 1;
09865 struct ast_channel *c;
09866 char tmp[256];
09867
09868 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09869 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09870
09871 if (linkset->type == SS7_ITU)
09872 law = DAHDI_LAW_ALAW;
09873 else
09874 law = DAHDI_LAW_MULAW;
09875
09876 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09877 if (res < 0)
09878 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09879
09880 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09881 p->proceeding = 1;
09882 isup_acm(ss7, p->ss7call);
09883 }
09884
09885 ast_mutex_unlock(&linkset->lock);
09886 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09887
09888 if (!c) {
09889 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09890
09891 ast_mutex_lock(&linkset->lock);
09892 return;
09893 } else
09894 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09895
09896 dahdi_enable_ec(p);
09897
09898
09899
09900
09901
09902 ast_mutex_unlock(&p->lock);
09903
09904 if (!ast_strlen_zero(p->charge_number)) {
09905 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09906
09907 p->charge_number[0] = 0;
09908 }
09909 if (!ast_strlen_zero(p->gen_add_number)) {
09910 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09911
09912 p->gen_add_number[0] = 0;
09913 }
09914 if (!ast_strlen_zero(p->jip_number)) {
09915 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09916
09917 p->jip_number[0] = 0;
09918 }
09919 if (!ast_strlen_zero(p->gen_dig_number)) {
09920 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09921
09922 p->gen_dig_number[0] = 0;
09923 }
09924 if (!ast_strlen_zero(p->orig_called_num)) {
09925 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09926
09927 p->orig_called_num[0] = 0;
09928 }
09929
09930 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09931 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09932
09933 p->gen_dig_type = 0;
09934
09935 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09936 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09937
09938 p->gen_dig_scheme = 0;
09939
09940 if (!ast_strlen_zero(p->lspi_ident)) {
09941 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
09942
09943 p->lspi_ident[0] = 0;
09944 }
09945
09946 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
09947 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
09948
09949 p->call_ref_ident = 0;
09950
09951 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
09952 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
09953
09954 p->call_ref_pc = 0;
09955
09956 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
09957 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
09958
09959 p->calling_party_cat = 0;
09960
09961 if (!ast_strlen_zero(p->redirecting_num)) {
09962 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
09963
09964 p->redirecting_num[0] = 0;
09965 }
09966 if (!ast_strlen_zero(p->generic_name)) {
09967 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
09968
09969 p->generic_name[0] = 0;
09970 }
09971
09972 ast_mutex_lock(&p->lock);
09973 ast_mutex_lock(&linkset->lock);
09974 }
09975
09976 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
09977 {
09978 if (ast_strlen_zero(number)) {
09979 if (size) {
09980 *buf = '\0';
09981 }
09982 return;
09983 }
09984 switch (nai) {
09985 case SS7_NAI_INTERNATIONAL:
09986 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
09987 break;
09988 case SS7_NAI_NATIONAL:
09989 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
09990 break;
09991 case SS7_NAI_SUBSCRIBER:
09992 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
09993 break;
09994 case SS7_NAI_UNKNOWN:
09995 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
09996 break;
09997 default:
09998 snprintf(buf, size, "%s", number);
09999 break;
10000 }
10001 }
10002 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
10003 {
10004 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
10005 }
10006
10007 static void *ss7_linkset(void *data)
10008 {
10009 int res, i;
10010 struct timeval *next = NULL, tv;
10011 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
10012 struct ss7 *ss7 = linkset->ss7;
10013 ss7_event *e = NULL;
10014 struct dahdi_pvt *p;
10015 int chanpos;
10016 struct pollfd pollers[NUM_DCHANS];
10017 int cic;
10018 unsigned int dpc;
10019 int nextms = 0;
10020
10021 ss7_start(ss7);
10022
10023 while(1) {
10024 ast_mutex_lock(&linkset->lock);
10025 if ((next = ss7_schedule_next(ss7))) {
10026 tv = ast_tvnow();
10027 tv.tv_sec = next->tv_sec - tv.tv_sec;
10028 tv.tv_usec = next->tv_usec - tv.tv_usec;
10029 if (tv.tv_usec < 0) {
10030 tv.tv_usec += 1000000;
10031 tv.tv_sec -= 1;
10032 }
10033 if (tv.tv_sec < 0) {
10034 tv.tv_sec = 0;
10035 tv.tv_usec = 0;
10036 }
10037 nextms = tv.tv_sec * 1000;
10038 nextms += tv.tv_usec / 1000;
10039 }
10040 ast_mutex_unlock(&linkset->lock);
10041
10042 for (i = 0; i < linkset->numsigchans; i++) {
10043 pollers[i].fd = linkset->fds[i];
10044 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
10045 pollers[i].revents = 0;
10046 }
10047
10048 res = poll(pollers, linkset->numsigchans, nextms);
10049 if ((res < 0) && (errno != EINTR)) {
10050 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
10051 } else if (!res) {
10052 ast_mutex_lock(&linkset->lock);
10053 ss7_schedule_run(ss7);
10054 ast_mutex_unlock(&linkset->lock);
10055 continue;
10056 }
10057
10058 ast_mutex_lock(&linkset->lock);
10059 for (i = 0; i < linkset->numsigchans; i++) {
10060 if (pollers[i].revents & POLLPRI) {
10061 int x;
10062 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
10063 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
10064 }
10065 switch (x) {
10066 case DAHDI_EVENT_OVERRUN:
10067 ast_debug(1, "Overrun detected!\n");
10068 break;
10069 case DAHDI_EVENT_BADFCS:
10070 ast_debug(1, "Bad FCS\n");
10071 break;
10072 case DAHDI_EVENT_ABORT:
10073 ast_debug(1, "HDLC Abort\n");
10074 break;
10075 case DAHDI_EVENT_ALARM:
10076 ast_log(LOG_ERROR, "Alarm on link!\n");
10077 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
10078 linkset->linkstate[i] &= ~LINKSTATE_UP;
10079 ss7_link_alarm(ss7, pollers[i].fd);
10080 break;
10081 case DAHDI_EVENT_NOALARM:
10082 ast_log(LOG_ERROR, "Alarm cleared on link\n");
10083 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
10084 linkset->linkstate[i] |= LINKSTATE_STARTING;
10085 ss7_link_noalarm(ss7, pollers[i].fd);
10086 break;
10087 default:
10088 ast_log(LOG_ERROR, "Got exception %d!\n", x);
10089 break;
10090 }
10091 }
10092
10093 if (pollers[i].revents & POLLIN) {
10094 ast_mutex_lock(&linkset->lock);
10095 res = ss7_read(ss7, pollers[i].fd);
10096 ast_mutex_unlock(&linkset->lock);
10097 }
10098
10099 if (pollers[i].revents & POLLOUT) {
10100 ast_mutex_lock(&linkset->lock);
10101 res = ss7_write(ss7, pollers[i].fd);
10102 ast_mutex_unlock(&linkset->lock);
10103 if (res < 0) {
10104 ast_debug(1, "Error in write %s\n", strerror(errno));
10105 }
10106 }
10107 }
10108
10109 while ((e = ss7_check_event(ss7))) {
10110 switch (e->e) {
10111 case SS7_EVENT_UP:
10112 if (linkset->state != LINKSET_STATE_UP) {
10113 ast_verbose("--- SS7 Up ---\n");
10114 ss7_reset_linkset(linkset);
10115 }
10116 linkset->state = LINKSET_STATE_UP;
10117 break;
10118 case SS7_EVENT_DOWN:
10119 ast_verbose("--- SS7 Down ---\n");
10120 linkset->state = LINKSET_STATE_DOWN;
10121 for (i = 0; i < linkset->numchans; i++) {
10122 struct dahdi_pvt *p = linkset->pvts[i];
10123 if (p)
10124 p->inalarm = 1;
10125 }
10126 break;
10127 case MTP2_LINK_UP:
10128 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
10129 break;
10130 case MTP2_LINK_DOWN:
10131 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
10132 break;
10133 case ISUP_EVENT_CPG:
10134 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
10135 if (chanpos < 0) {
10136 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
10137 break;
10138 }
10139 p = linkset->pvts[chanpos];
10140 ast_mutex_lock(&p->lock);
10141 switch (e->cpg.event) {
10142 case CPG_EVENT_ALERTING:
10143 p->alerting = 1;
10144 p->subs[SUB_REAL].needringing = 1;
10145 break;
10146 case CPG_EVENT_PROGRESS:
10147 case CPG_EVENT_INBANDINFO:
10148 {
10149 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10150 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
10151 dahdi_queue_frame(p, &f, linkset);
10152 p->progress = 1;
10153 p->dialing = 0;
10154 if (p->dsp && p->dsp_features) {
10155 ast_dsp_set_features(p->dsp, p->dsp_features);
10156 p->dsp_features = 0;
10157 }
10158 }
10159 break;
10160 default:
10161 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
10162 }
10163
10164 ast_mutex_unlock(&p->lock);
10165 break;
10166 case ISUP_EVENT_RSC:
10167 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
10168 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
10169 if (chanpos < 0) {
10170 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
10171 break;
10172 }
10173 p = linkset->pvts[chanpos];
10174 ast_mutex_lock(&p->lock);
10175 p->inservice = 1;
10176 p->remotelyblocked = 0;
10177 dpc = p->dpc;
10178 isup_set_call_dpc(e->rsc.call, dpc);
10179 if (p->ss7call)
10180 p->ss7call = NULL;
10181 if (p->owner)
10182 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10183 ast_mutex_unlock(&p->lock);
10184 isup_rlc(ss7, e->rsc.call);
10185 break;
10186 case ISUP_EVENT_GRS:
10187 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
10188 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
10189 if (chanpos < 0) {
10190 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
10191 break;
10192 }
10193 p = linkset->pvts[chanpos];
10194 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
10195 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
10196 break;
10197 case ISUP_EVENT_CQM:
10198 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
10199 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
10200 break;
10201 case ISUP_EVENT_GRA:
10202 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
10203 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
10204 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
10205 break;
10206 case ISUP_EVENT_IAM:
10207 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);
10208 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
10209 if (chanpos < 0) {
10210 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
10211 isup_rel(ss7, e->iam.call, -1);
10212 break;
10213 }
10214 p = linkset->pvts[chanpos];
10215 ast_mutex_lock(&p->lock);
10216 if (p->owner) {
10217 if (p->ss7call == e->iam.call) {
10218 ast_mutex_unlock(&p->lock);
10219 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
10220 break;
10221 } else {
10222 ast_mutex_unlock(&p->lock);
10223 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
10224 break;
10225 }
10226 }
10227
10228 dpc = p->dpc;
10229 p->ss7call = e->iam.call;
10230 isup_set_call_dpc(p->ss7call, dpc);
10231
10232 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
10233 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
10234 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
10235 } else
10236 p->cid_num[0] = 0;
10237
10238 if (p->immediate) {
10239 p->exten[0] = 's';
10240 p->exten[1] = '\0';
10241 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
10242 char *st;
10243 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
10244 st = strchr(p->exten, '#');
10245 if (st)
10246 *st = '\0';
10247 } else
10248 p->exten[0] = '\0';
10249
10250 p->cid_ani[0] = '\0';
10251 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
10252 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
10253 else
10254 p->cid_name[0] = '\0';
10255
10256 p->cid_ani2 = e->iam.oli_ani2;
10257 p->cid_ton = 0;
10258 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
10259 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
10260 p->gen_add_type = e->iam.gen_add_type;
10261 p->gen_add_nai = e->iam.gen_add_nai;
10262 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
10263 p->gen_add_num_plan = e->iam.gen_add_num_plan;
10264 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
10265 p->gen_dig_type = e->iam.gen_dig_type;
10266 p->gen_dig_scheme = e->iam.gen_dig_scheme;
10267 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
10268 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
10269 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
10270 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
10271 p->calling_party_cat = e->iam.calling_party_cat;
10272
10273
10274 if (!ast_strlen_zero(e->iam.called_party_num))
10275 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
10276
10277 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
10278
10279 if (e->iam.cot_check_required) {
10280 dahdi_loopback(p, 1);
10281 } else
10282 ss7_start_call(p, linkset);
10283 } else {
10284 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
10285 p->alreadyhungup = 1;
10286 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
10287 }
10288 ast_mutex_unlock(&p->lock);
10289 break;
10290 case ISUP_EVENT_COT:
10291 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
10292 if (chanpos < 0) {
10293 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
10294 isup_rel(ss7, e->cot.call, -1);
10295 break;
10296 }
10297 p = linkset->pvts[chanpos];
10298
10299 ast_mutex_lock(&p->lock);
10300
10301 if (p->loopedback) {
10302 dahdi_loopback(p, 0);
10303 ss7_start_call(p, linkset);
10304 }
10305
10306 ast_mutex_unlock(&p->lock);
10307
10308 break;
10309 case ISUP_EVENT_CCR:
10310 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
10311 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
10312 if (chanpos < 0) {
10313 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
10314 break;
10315 }
10316
10317 p = linkset->pvts[chanpos];
10318
10319 ast_mutex_lock(&p->lock);
10320 dahdi_loopback(p, 1);
10321 ast_mutex_unlock(&p->lock);
10322
10323 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
10324 break;
10325 case ISUP_EVENT_CVT:
10326 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
10327 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
10328 if (chanpos < 0) {
10329 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
10330 break;
10331 }
10332
10333 p = linkset->pvts[chanpos];
10334
10335 ast_mutex_lock(&p->lock);
10336 dahdi_loopback(p, 1);
10337 ast_mutex_unlock(&p->lock);
10338
10339 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
10340 break;
10341 case ISUP_EVENT_REL:
10342 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
10343 if (chanpos < 0) {
10344 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
10345 break;
10346 }
10347 p = linkset->pvts[chanpos];
10348 ast_mutex_lock(&p->lock);
10349 if (p->owner) {
10350 p->owner->hangupcause = e->rel.cause;
10351 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10352 } else if (!p->restartpending)
10353 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
10354
10355
10356 dahdi_loopback(p, 0);
10357
10358 isup_rlc(ss7, e->rel.call);
10359 p->ss7call = NULL;
10360
10361 ast_mutex_unlock(&p->lock);
10362 break;
10363 case ISUP_EVENT_ACM:
10364 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
10365 if (chanpos < 0) {
10366 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
10367 isup_rel(ss7, e->acm.call, -1);
10368 break;
10369 } else {
10370 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10371
10372 p = linkset->pvts[chanpos];
10373
10374 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
10375
10376 if (e->acm.call_ref_ident > 0) {
10377 p->rlt = 1;
10378 }
10379
10380 ast_mutex_lock(&p->lock);
10381 dahdi_queue_frame(p, &f, linkset);
10382 p->proceeding = 1;
10383 p->dialing = 0;
10384
10385 if (e->acm.called_party_status_ind == 1) {
10386 p->alerting = 1;
10387 p->subs[SUB_REAL].needringing = 1;
10388 }
10389 ast_mutex_unlock(&p->lock);
10390 }
10391 break;
10392 case ISUP_EVENT_CGB:
10393 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
10394 if (chanpos < 0) {
10395 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
10396 break;
10397 }
10398 p = linkset->pvts[chanpos];
10399 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
10400 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
10401 break;
10402 case ISUP_EVENT_CGU:
10403 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
10404 if (chanpos < 0) {
10405 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
10406 break;
10407 }
10408 p = linkset->pvts[chanpos];
10409 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
10410 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
10411 break;
10412 case ISUP_EVENT_UCIC:
10413 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
10414 if (chanpos < 0) {
10415 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
10416 break;
10417 }
10418 p = linkset->pvts[chanpos];
10419 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
10420 ast_mutex_lock(&p->lock);
10421 p->remotelyblocked = 1;
10422 p->inservice = 0;
10423 ast_mutex_unlock(&p->lock);
10424 break;
10425 case ISUP_EVENT_BLO:
10426 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
10427 if (chanpos < 0) {
10428 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
10429 break;
10430 }
10431 p = linkset->pvts[chanpos];
10432 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
10433 ast_mutex_lock(&p->lock);
10434 p->remotelyblocked = 1;
10435 ast_mutex_unlock(&p->lock);
10436 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
10437 break;
10438 case ISUP_EVENT_BLA:
10439 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
10440 if (chanpos < 0) {
10441 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
10442 break;
10443 }
10444 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
10445 p = linkset->pvts[chanpos];
10446 ast_mutex_lock(&p->lock);
10447 p->locallyblocked = 1;
10448 ast_mutex_unlock(&p->lock);
10449 break;
10450 case ISUP_EVENT_UBL:
10451 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
10452 if (chanpos < 0) {
10453 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
10454 break;
10455 }
10456 p = linkset->pvts[chanpos];
10457 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
10458 ast_mutex_lock(&p->lock);
10459 p->remotelyblocked = 0;
10460 ast_mutex_unlock(&p->lock);
10461 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
10462 break;
10463 case ISUP_EVENT_UBA:
10464 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
10465 if (chanpos < 0) {
10466 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
10467 break;
10468 }
10469 p = linkset->pvts[chanpos];
10470 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
10471 ast_mutex_lock(&p->lock);
10472 p->locallyblocked = 0;
10473 ast_mutex_unlock(&p->lock);
10474 break;
10475 case ISUP_EVENT_CON:
10476 case ISUP_EVENT_ANM:
10477 if (e->e == ISUP_EVENT_CON)
10478 cic = e->con.cic;
10479 else
10480 cic = e->anm.cic;
10481
10482 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
10483 if (chanpos < 0) {
10484 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
10485 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
10486 break;
10487 } else {
10488 p = linkset->pvts[chanpos];
10489 ast_mutex_lock(&p->lock);
10490 p->subs[SUB_REAL].needanswer = 1;
10491 if (p->dsp && p->dsp_features) {
10492 ast_dsp_set_features(p->dsp, p->dsp_features);
10493 p->dsp_features = 0;
10494 }
10495 dahdi_enable_ec(p);
10496 ast_mutex_unlock(&p->lock);
10497 }
10498 break;
10499 case ISUP_EVENT_RLC:
10500 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
10501 if (chanpos < 0) {
10502 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
10503 break;
10504 } else {
10505 p = linkset->pvts[chanpos];
10506 ast_mutex_lock(&p->lock);
10507 if (p->alreadyhungup)
10508 p->ss7call = NULL;
10509 else
10510 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
10511 ast_mutex_unlock(&p->lock);
10512 }
10513 break;
10514 case ISUP_EVENT_FAA:
10515 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
10516 if (chanpos < 0) {
10517 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
10518 break;
10519 } else {
10520 p = linkset->pvts[chanpos];
10521 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
10522 ast_mutex_lock(&p->lock);
10523 if (p->alreadyhungup){
10524 p->ss7call = NULL;
10525 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
10526 }
10527 ast_mutex_unlock(&p->lock);
10528 }
10529 break;
10530 default:
10531 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
10532 break;
10533 }
10534 }
10535 ast_mutex_unlock(&linkset->lock);
10536 }
10537
10538 return 0;
10539 }
10540
10541 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
10542 {
10543 #if 0
10544 int i;
10545
10546 for (i = 0; i < NUM_SPANS; i++)
10547 if (linksets[i].ss7 == ss7)
10548 break;
10549
10550 ast_verbose("[%d] %s", i+1, s);
10551 #else
10552 ast_verbose("%s", s);
10553 #endif
10554 }
10555
10556 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
10557 {
10558 #if 0
10559 int i;
10560
10561 for (i = 0; i < NUM_SPANS; i++)
10562 if (linksets[i].ss7 == ss7)
10563 break;
10564
10565 #else
10566 ast_log(LOG_ERROR, "%s", s);
10567 #endif
10568 }
10569
10570 #endif
10571
10572 #ifdef HAVE_PRI
10573 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10574 {
10575 struct dahdi_pvt *p;
10576 p = pri->crvs;
10577 while (p) {
10578 if (p->channel == crv)
10579 return p;
10580 p = p->next;
10581 }
10582 return NULL;
10583 }
10584
10585
10586 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10587 {
10588 int x;
10589 int span = PRI_SPAN(channel);
10590 int spanfd;
10591 struct dahdi_params param;
10592 int principle = -1;
10593 int explicit = PRI_EXPLICIT(channel);
10594 channel = PRI_CHANNEL(channel);
10595
10596 if (!explicit) {
10597 spanfd = pri_active_dchan_fd(pri);
10598 memset(¶m, 0, sizeof(param));
10599 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
10600 return -1;
10601 span = pris[param.spanno - 1].prilogicalspan;
10602 }
10603
10604 for (x = 0; x < pri->numchans; x++) {
10605 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10606 principle = x;
10607 break;
10608 }
10609 }
10610
10611 return principle;
10612 }
10613
10614 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10615 {
10616 int x;
10617 struct dahdi_pvt *crv;
10618 if (!c) {
10619 if (principle < 0)
10620 return -1;
10621 return principle;
10622 }
10623 if ((principle > -1) &&
10624 (principle < pri->numchans) &&
10625 (pri->pvts[principle]) &&
10626 (pri->pvts[principle]->call == c))
10627 return principle;
10628
10629 for (x = 0; x < pri->numchans; x++) {
10630 if (!pri->pvts[x])
10631 continue;
10632 if (pri->pvts[x]->call == c) {
10633
10634 if (principle != x) {
10635 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10636
10637 ast_verb(3, "Moving call from channel %d to channel %d\n",
10638 old->channel, new->channel);
10639 if (new->owner) {
10640 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10641 old->channel, new->channel, new->channel);
10642 return -1;
10643 }
10644
10645 new->owner = old->owner;
10646 old->owner = NULL;
10647 if (new->owner) {
10648 ast_string_field_build(new->owner, name,
10649 "DAHDI/%d:%d-%d", pri->trunkgroup,
10650 new->channel, 1);
10651 new->owner->tech_pvt = new;
10652 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10653 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10654 old->subs[SUB_REAL].owner = NULL;
10655 } else
10656 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);
10657 new->call = old->call;
10658 old->call = NULL;
10659
10660
10661 new->dsp = old->dsp;
10662 new->dsp_features = old->dsp_features;
10663 old->dsp = NULL;
10664 old->dsp_features = 0;
10665 }
10666 return principle;
10667 }
10668 }
10669
10670 crv = pri->crvs;
10671 while (crv) {
10672 if (crv->call == c) {
10673
10674 if (crv->bearer)
10675 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10676 else if (pri->pvts[principle]->owner)
10677 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10678 else {
10679
10680
10681 dahdi_close_sub(crv, SUB_REAL);
10682 pri->pvts[principle]->call = crv->call;
10683 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10684 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10685 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10686 pri->trunkgroup, crv->channel);
10687 wakeup_sub(crv, SUB_REAL, pri);
10688 }
10689 return principle;
10690 }
10691 crv = crv->next;
10692 }
10693 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10694 return -1;
10695 }
10696
10697 static void *do_idle_thread(void *vchan)
10698 {
10699 struct ast_channel *chan = vchan;
10700 struct dahdi_pvt *pvt = chan->tech_pvt;
10701 struct ast_frame *f;
10702 char ex[80];
10703
10704 int newms, ms = 30000;
10705 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10706 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10707 if (ast_call(chan, ex, 0)) {
10708 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10709 ast_hangup(chan);
10710 return NULL;
10711 }
10712 while ((newms = ast_waitfor(chan, ms)) > 0) {
10713 f = ast_read(chan);
10714 if (!f) {
10715
10716 break;
10717 }
10718 if (f->frametype == AST_FRAME_CONTROL) {
10719 switch (f->subclass) {
10720 case AST_CONTROL_ANSWER:
10721
10722 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10723 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10724 chan->priority = 1;
10725 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10726 ast_pbx_run(chan);
10727
10728 return NULL;
10729 case AST_CONTROL_BUSY:
10730 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10731 break;
10732 case AST_CONTROL_CONGESTION:
10733 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10734 break;
10735 };
10736 }
10737 ast_frfree(f);
10738 ms = newms;
10739 }
10740
10741 ast_hangup(chan);
10742 return NULL;
10743 }
10744
10745 #ifndef PRI_RESTART
10746 #error "Upgrade your libpri"
10747 #endif
10748 static void dahdi_pri_message(struct pri *pri, char *s)
10749 {
10750 int x, y;
10751 int dchan = -1, span = -1;
10752 int dchancount = 0;
10753
10754 if (pri) {
10755 for (x = 0; x < NUM_SPANS; x++) {
10756 for (y = 0; y < NUM_DCHANS; y++) {
10757 if (pris[x].dchans[y])
10758 dchancount++;
10759
10760 if (pris[x].dchans[y] == pri)
10761 dchan = y;
10762 }
10763 if (dchan >= 0) {
10764 span = x;
10765 break;
10766 }
10767 dchancount = 0;
10768 }
10769 if (dchancount > 1 && (span > -1))
10770 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10771 else
10772 ast_verbose("%s", s);
10773 } else
10774 ast_verbose("%s", s);
10775
10776 ast_mutex_lock(&pridebugfdlock);
10777
10778 if (pridebugfd >= 0) {
10779 if (write(pridebugfd, s, strlen(s)) < 0) {
10780 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10781 }
10782 }
10783
10784 ast_mutex_unlock(&pridebugfdlock);
10785 }
10786
10787 static void dahdi_pri_error(struct pri *pri, char *s)
10788 {
10789 int x, y;
10790 int dchan = -1, span = -1;
10791 int dchancount = 0;
10792
10793 if (pri) {
10794 for (x = 0; x < NUM_SPANS; x++) {
10795 for (y = 0; y < NUM_DCHANS; y++) {
10796 if (pris[x].dchans[y])
10797 dchancount++;
10798
10799 if (pris[x].dchans[y] == pri)
10800 dchan = y;
10801 }
10802 if (dchan >= 0) {
10803 span = x;
10804 break;
10805 }
10806 dchancount = 0;
10807 }
10808 if ((dchancount > 1) && (span > -1))
10809 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10810 else
10811 ast_log(LOG_ERROR, "%s", s);
10812 } else
10813 ast_log(LOG_ERROR, "%s", s);
10814
10815 ast_mutex_lock(&pridebugfdlock);
10816
10817 if (pridebugfd >= 0) {
10818 if (write(pridebugfd, s, strlen(s)) < 0) {
10819 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10820 }
10821 }
10822
10823 ast_mutex_unlock(&pridebugfdlock);
10824 }
10825
10826 static int pri_check_restart(struct dahdi_pri *pri)
10827 {
10828 do {
10829 pri->resetpos++;
10830 } while ((pri->resetpos < pri->numchans) &&
10831 (!pri->pvts[pri->resetpos] ||
10832 pri->pvts[pri->resetpos]->call ||
10833 pri->pvts[pri->resetpos]->resetting));
10834 if (pri->resetpos < pri->numchans) {
10835
10836 pri->pvts[pri->resetpos]->resetting = 1;
10837 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10838 } else {
10839 pri->resetting = 0;
10840 time(&pri->lastreset);
10841 }
10842 return 0;
10843 }
10844
10845 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10846 {
10847 int x;
10848 int redo;
10849 ast_mutex_unlock(&pri->lock);
10850 ast_mutex_lock(&p->lock);
10851 do {
10852 redo = 0;
10853 for (x = 0; x < 3; x++) {
10854 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10855 redo++;
10856 DEADLOCK_AVOIDANCE(&p->lock);
10857 }
10858 if (p->subs[x].owner) {
10859 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10860 ast_channel_unlock(p->subs[x].owner);
10861 }
10862 }
10863 } while (redo);
10864 ast_mutex_unlock(&p->lock);
10865 ast_mutex_lock(&pri->lock);
10866 return 0;
10867 }
10868
10869 static char * redirectingreason2str(int redirectingreason)
10870 {
10871 switch (redirectingreason) {
10872 case 0:
10873 return "UNKNOWN";
10874 case 1:
10875 return "BUSY";
10876 case 2:
10877 return "NO_REPLY";
10878 case 0xF:
10879 return "UNCONDITIONAL";
10880 default:
10881 return "NOREDIRECT";
10882 }
10883 }
10884
10885 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10886 {
10887 if (pri->dialplan == -2) {
10888 snprintf(buf, size, "%s", number);
10889 return;
10890 }
10891 if (ast_strlen_zero(number)) {
10892 if (size) {
10893 *buf = '\0';
10894 }
10895 return;
10896 }
10897 switch (plan) {
10898 case PRI_INTERNATIONAL_ISDN:
10899 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10900 break;
10901 case PRI_NATIONAL_ISDN:
10902 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10903 break;
10904 case PRI_LOCAL_ISDN:
10905 snprintf(buf, size, "%s%s", pri->localprefix, number);
10906 break;
10907 case PRI_PRIVATE:
10908 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10909 break;
10910 case PRI_UNKNOWN:
10911 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10912 break;
10913 default:
10914 snprintf(buf, size, "%s", number);
10915 break;
10916 }
10917 }
10918
10919
10920 static void *pri_dchannel(void *vpri)
10921 {
10922 struct dahdi_pri *pri = vpri;
10923 pri_event *e;
10924 struct pollfd fds[NUM_DCHANS];
10925 int res;
10926 int chanpos = 0;
10927 int x;
10928 int haveidles;
10929 int activeidles;
10930 int nextidle = -1;
10931 struct ast_channel *c;
10932 struct timeval tv, lowest, *next;
10933 struct timeval lastidle = ast_tvnow();
10934 int doidling=0;
10935 char *cc;
10936 char idlen[80];
10937 struct ast_channel *idle;
10938 pthread_t p;
10939 time_t t;
10940 int i, which=-1;
10941 int numdchans;
10942 int cause=0;
10943 struct dahdi_pvt *crv;
10944 pthread_t threadid;
10945 char ani2str[6];
10946 char plancallingnum[256];
10947 char plancallingani[256];
10948 char calledtonstr[10];
10949
10950 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10951
10952 gettimeofday(&lastidle, NULL);
10953 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10954
10955 cc = strchr(pri->idleext, '@');
10956 if (cc) {
10957 *cc = '\0';
10958 cc++;
10959 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10960 #if 0
10961
10962 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10963 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10964 else
10965 #endif
10966 doidling = 1;
10967 } else
10968 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10969 }
10970 for (;;) {
10971 for (i = 0; i < NUM_DCHANS; i++) {
10972 if (!pri->dchannels[i])
10973 break;
10974 fds[i].fd = pri->fds[i];
10975 fds[i].events = POLLIN | POLLPRI;
10976 fds[i].revents = 0;
10977 }
10978 numdchans = i;
10979 time(&t);
10980 ast_mutex_lock(&pri->lock);
10981 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10982 if (pri->resetting && pri_is_up(pri)) {
10983 if (pri->resetpos < 0)
10984 pri_check_restart(pri);
10985 } else {
10986 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10987 pri->resetting = 1;
10988 pri->resetpos = -1;
10989 }
10990 }
10991 }
10992
10993 if (doidling && pri_is_up(pri)) {
10994 nextidle = -1;
10995 haveidles = 0;
10996 activeidles = 0;
10997 for (x = pri->numchans; x >= 0; x--) {
10998 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10999 !pri->pvts[x]->call) {
11000 if (haveidles < pri->minunused) {
11001 haveidles++;
11002 } else if (!pri->pvts[x]->resetting) {
11003 nextidle = x;
11004 break;
11005 }
11006 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
11007 activeidles++;
11008 }
11009 if (nextidle > -1) {
11010 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
11011
11012 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
11013 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
11014 if (idle) {
11015 pri->pvts[nextidle]->isidlecall = 1;
11016 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
11017 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
11018 dahdi_hangup(idle);
11019 }
11020 } else
11021 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
11022 lastidle = ast_tvnow();
11023 }
11024 } else if ((haveidles < pri->minunused) &&
11025 (activeidles > pri->minidle)) {
11026
11027
11028 for (x = pri->numchans; x >= 0; x--) {
11029
11030 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
11031 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11032 haveidles++;
11033
11034
11035 if ((haveidles >= pri->minunused) ||
11036 (activeidles <= pri->minidle))
11037 break;
11038 }
11039 }
11040 }
11041 }
11042
11043 lowest = ast_tv(60, 0);
11044 for (i = 0; i < NUM_DCHANS; i++) {
11045
11046 if (!pri->dchannels[i])
11047 break;
11048 if ((next = pri_schedule_next(pri->dchans[i]))) {
11049
11050 tv = ast_tvsub(*next, ast_tvnow());
11051 if (tv.tv_sec < 0) {
11052 tv = ast_tv(0,0);
11053 }
11054 if (doidling || pri->resetting) {
11055 if (tv.tv_sec > 1) {
11056 tv = ast_tv(1, 0);
11057 }
11058 } else {
11059 if (tv.tv_sec > 60) {
11060 tv = ast_tv(60, 0);
11061 }
11062 }
11063 } else if (doidling || pri->resetting) {
11064
11065
11066 tv = ast_tv(1,0);
11067 } else {
11068
11069 tv = ast_tv(60, 0);
11070 }
11071 if (!i || ast_tvcmp(tv, lowest) < 0) {
11072 lowest = tv;
11073 }
11074 }
11075 ast_mutex_unlock(&pri->lock);
11076
11077 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11078 pthread_testcancel();
11079 e = NULL;
11080 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11081 pthread_testcancel();
11082 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11083
11084 ast_mutex_lock(&pri->lock);
11085 if (!res) {
11086 for (which = 0; which < NUM_DCHANS; which++) {
11087 if (!pri->dchans[which])
11088 break;
11089
11090 e = pri_schedule_run(pri->dchans[which]);
11091 if (e)
11092 break;
11093 }
11094 } else if (res > -1) {
11095 for (which = 0; which < NUM_DCHANS; which++) {
11096 if (!pri->dchans[which])
11097 break;
11098 if (fds[which].revents & POLLPRI) {
11099
11100 x = 0;
11101 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11102 if (x) {
11103 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);
11104 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
11105 "PRIEvent: %s\r\n"
11106 "PRIEventCode: %d\r\n"
11107 "D-channel: %s\r\n"
11108 "Span: %d\r\n",
11109 event2str(x),
11110 x,
11111 pri_order(which),
11112 pri->span
11113 );
11114 }
11115
11116 if (x == DAHDI_EVENT_ALARM) {
11117 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11118 pri_find_dchan(pri);
11119 } else if (x == DAHDI_EVENT_NOALARM) {
11120 pri->dchanavail[which] |= DCHAN_NOTINALARM;
11121 pri_restart(pri->dchans[which]);
11122 }
11123
11124 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11125 } else if (fds[which].revents & POLLIN) {
11126 e = pri_check_event(pri->dchans[which]);
11127 }
11128 if (e)
11129 break;
11130 }
11131 } else if (errno != EINTR)
11132 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11133
11134 if (e) {
11135 if (pri->debug)
11136 pri_dump_event(pri->dchans[which], e);
11137
11138 if (e->e != PRI_EVENT_DCHAN_DOWN) {
11139 if (!(pri->dchanavail[which] & DCHAN_UP)) {
11140 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11141 }
11142 pri->dchanavail[which] |= DCHAN_UP;
11143 } else if (pri->sig != SIG_BRI_PTMP) {
11144 if (pri->dchanavail[which] & DCHAN_UP) {
11145 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11146 }
11147 pri->dchanavail[which] &= ~DCHAN_UP;
11148 }
11149
11150 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11151
11152 pri->pri = pri->dchans[which];
11153
11154 switch (e->e) {
11155 case PRI_EVENT_DCHAN_UP:
11156 if (!pri->pri) pri_find_dchan(pri);
11157
11158
11159 time(&pri->lastreset);
11160
11161
11162 if (pri->resetinterval > -1) {
11163 pri->lastreset -= pri->resetinterval;
11164 pri->lastreset += 5;
11165 }
11166 pri->resetting = 0;
11167
11168 for (i = 0; i < pri->numchans; i++)
11169 if (pri->pvts[i]) {
11170 pri->pvts[i]->inalarm = 0;
11171 }
11172 break;
11173 case PRI_EVENT_DCHAN_DOWN:
11174 pri_find_dchan(pri);
11175 if (!pri_is_up(pri)) {
11176 pri->resetting = 0;
11177
11178 for (i = 0; i < pri->numchans; i++) {
11179 struct dahdi_pvt *p = pri->pvts[i];
11180 if (p) {
11181 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11182
11183 if (p->call) {
11184 if (p->pri && p->pri->pri) {
11185 pri_hangup(p->pri->pri, p->call, -1);
11186 pri_destroycall(p->pri->pri, p->call);
11187 p->call = NULL;
11188 } else
11189 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
11190 }
11191 if (p->realcall) {
11192 pri_hangup_all(p->realcall, pri);
11193 } else if (p->owner)
11194 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11195 }
11196 p->inalarm = 1;
11197 }
11198 }
11199 }
11200 break;
11201 case PRI_EVENT_RESTART:
11202 if (e->restart.channel > -1) {
11203 chanpos = pri_find_principle(pri, e->restart.channel);
11204 if (chanpos < 0)
11205 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
11206 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11207 else {
11208 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
11209 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11210 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11211 if (pri->pvts[chanpos]->call) {
11212 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11213 pri->pvts[chanpos]->call = NULL;
11214 }
11215
11216 if (pri->pvts[chanpos]->realcall)
11217 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11218 else if (pri->pvts[chanpos]->owner)
11219 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11220 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11221 }
11222 } else {
11223 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
11224 for (x = 0; x < pri->numchans; x++)
11225 if (pri->pvts[x]) {
11226 ast_mutex_lock(&pri->pvts[x]->lock);
11227 if (pri->pvts[x]->call) {
11228 pri_destroycall(pri->pri, pri->pvts[x]->call);
11229 pri->pvts[x]->call = NULL;
11230 }
11231 if (pri->pvts[x]->realcall)
11232 pri_hangup_all(pri->pvts[x]->realcall, pri);
11233 else if (pri->pvts[x]->owner)
11234 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11235 ast_mutex_unlock(&pri->pvts[x]->lock);
11236 }
11237 }
11238 break;
11239 case PRI_EVENT_KEYPAD_DIGIT:
11240 chanpos = pri_find_principle(pri, e->digit.channel);
11241 if (chanpos < 0) {
11242 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
11243 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
11244 } else {
11245 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
11246 if (chanpos > -1) {
11247 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11248
11249 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
11250
11251 int digitlen = strlen(e->digit.digits);
11252 char digit;
11253 int i;
11254 for (i = 0; i < digitlen; i++) {
11255 digit = e->digit.digits[i];
11256 {
11257 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11258 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11259 }
11260 }
11261 }
11262 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11263 }
11264 }
11265 break;
11266
11267 case PRI_EVENT_INFO_RECEIVED:
11268 chanpos = pri_find_principle(pri, e->ring.channel);
11269 if (chanpos < 0) {
11270 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
11271 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11272 } else {
11273 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
11274 if (chanpos > -1) {
11275 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11276
11277 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
11278
11279 int digitlen = strlen(e->ring.callednum);
11280 char digit;
11281 int i;
11282 for (i = 0; i < digitlen; i++) {
11283 digit = e->ring.callednum[i];
11284 {
11285 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11286 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11287 }
11288 }
11289 }
11290 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11291 }
11292 }
11293 break;
11294 case PRI_EVENT_RING:
11295 crv = NULL;
11296 if (e->ring.channel == -1)
11297 chanpos = pri_find_empty_chan(pri, 1);
11298 else
11299 chanpos = pri_find_principle(pri, e->ring.channel);
11300
11301 if (chanpos < 0) {
11302 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
11303 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11304 } else {
11305 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11306 if (pri->pvts[chanpos]->owner) {
11307 if (pri->pvts[chanpos]->call == e->ring.call) {
11308 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
11309 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11310 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11311 break;
11312 } else {
11313
11314 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
11315 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11316 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11317 chanpos = -1;
11318 }
11319 }
11320 if (chanpos > -1)
11321 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11322 }
11323 if ((chanpos < 0) && (e->ring.flexible))
11324 chanpos = pri_find_empty_chan(pri, 1);
11325 if (chanpos > -1) {
11326 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11327 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11328
11329 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11330 if (crv)
11331 ast_mutex_lock(&crv->lock);
11332 if (!crv || crv->owner) {
11333 pri->pvts[chanpos]->call = NULL;
11334 if (crv) {
11335 if (crv->owner)
11336 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11337 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);
11338 } else
11339 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);
11340 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11341 if (crv)
11342 ast_mutex_unlock(&crv->lock);
11343 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11344 break;
11345 }
11346 }
11347 pri->pvts[chanpos]->call = e->ring.call;
11348 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11349 if (pri->pvts[chanpos]->use_callerid) {
11350 ast_shrink_phone_number(plancallingnum);
11351 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11352 #ifdef PRI_ANI
11353 if (!ast_strlen_zero(e->ring.callingani)) {
11354 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11355 ast_shrink_phone_number(plancallingani);
11356 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11357 } else {
11358 pri->pvts[chanpos]->cid_ani[0] = '\0';
11359 }
11360 #endif
11361 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11362 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
11363 } else {
11364 pri->pvts[chanpos]->cid_num[0] = '\0';
11365 pri->pvts[chanpos]->cid_ani[0] = '\0';
11366 pri->pvts[chanpos]->cid_name[0] = '\0';
11367 pri->pvts[chanpos]->cid_ton = 0;
11368 }
11369 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11370 e->ring.redirectingnum, e->ring.callingplanrdnis);
11371
11372 if (pri->pvts[chanpos]->immediate) {
11373 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
11374 pri->pvts[chanpos]->exten[0] = 's';
11375 pri->pvts[chanpos]->exten[1] = '\0';
11376 }
11377
11378 else if (!ast_strlen_zero(e->ring.callednum)) {
11379 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11380 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11381 } else if (pri->overlapdial)
11382 pri->pvts[chanpos]->exten[0] = '\0';
11383 else {
11384
11385 pri->pvts[chanpos]->exten[0] = 's';
11386 pri->pvts[chanpos]->exten[1] = '\0';
11387 }
11388
11389 if (!ast_strlen_zero(e->ring.callednum))
11390 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11391
11392 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11393 ast_verb(3, "Going to extension s|1 because of Complete received\n");
11394 pri->pvts[chanpos]->exten[0] = 's';
11395 pri->pvts[chanpos]->exten[1] = '\0';
11396 }
11397
11398
11399 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11400 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11401
11402 int law;
11403 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11404
11405 law = 1;
11406 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11407 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11408 }
11409 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11410 law = DAHDI_LAW_ALAW;
11411 else
11412 law = DAHDI_LAW_MULAW;
11413 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11414 if (res < 0)
11415 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11416 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11417 if (res < 0)
11418 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11419 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11420
11421 pri->pvts[chanpos]->proceeding = 1;
11422 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11423 } else {
11424 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
11425 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11426 else
11427 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11428 }
11429
11430 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11431
11432
11433 if (!e->ring.complete
11434 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11435 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11436
11437
11438
11439
11440 ast_mutex_unlock(&pri->lock);
11441 if (crv) {
11442
11443 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11444 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11445 pri->pvts[chanpos]->owner = &inuse;
11446 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11447 } else {
11448 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11449 }
11450 ast_mutex_lock(&pri->lock);
11451 if (c) {
11452 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11453 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11454 }
11455 if (e->ring.ani2 >= 0) {
11456 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11457 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11458 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11459 }
11460
11461 #ifdef SUPPORT_USERUSER
11462 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11463 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11464 }
11465 #endif
11466
11467 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11468 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11469 if (e->ring.redirectingreason >= 0)
11470 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11471 }
11472 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
11473 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11474 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11475 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11476 } else {
11477 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11478 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11479 if (c)
11480 ast_hangup(c);
11481 else {
11482 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11483 pri->pvts[chanpos]->call = NULL;
11484 }
11485 }
11486 } else {
11487
11488
11489
11490
11491 ast_mutex_unlock(&pri->lock);
11492 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
11493 ast_mutex_lock(&pri->lock);
11494 if (c) {
11495
11496
11497
11498
11499
11500
11501
11502
11503 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11504 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11505 }
11506 if (e->ring.ani2 >= 0) {
11507 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11508 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11509 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11510 }
11511
11512 #ifdef SUPPORT_USERUSER
11513 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11514 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11515 }
11516 #endif
11517
11518 if (e->ring.redirectingreason >= 0)
11519 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11520
11521 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11522 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11523 }
11524 if (c && !ast_pbx_start(c)) {
11525 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11526 plancallingnum, pri->pvts[chanpos]->exten,
11527 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11528
11529 dahdi_enable_ec(pri->pvts[chanpos]);
11530 } else {
11531 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11532 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11533 if (c) {
11534 ast_hangup(c);
11535 } else {
11536 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11537 pri->pvts[chanpos]->call = NULL;
11538 }
11539 }
11540 }
11541 } else {
11542 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
11543 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
11544 pri->pvts[chanpos]->prioffset, pri->span);
11545 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11546 pri->pvts[chanpos]->call = NULL;
11547 pri->pvts[chanpos]->exten[0] = '\0';
11548 }
11549 if (crv)
11550 ast_mutex_unlock(&crv->lock);
11551 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11552 } else {
11553 if (e->ring.flexible)
11554 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11555 else
11556 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11557 }
11558 break;
11559 case PRI_EVENT_RINGING:
11560 chanpos = pri_find_principle(pri, e->ringing.channel);
11561 if (chanpos < 0) {
11562 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
11563 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11564 } else {
11565 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
11566 if (chanpos < 0) {
11567 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
11568 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11569 } else {
11570 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11571 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11572 dahdi_enable_ec(pri->pvts[chanpos]);
11573 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11574 pri->pvts[chanpos]->alerting = 1;
11575 } else
11576 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11577
11578 #ifdef PRI_PROGRESS_MASK
11579 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11580 #else
11581 if (e->ringing.progress == 8) {
11582 #endif
11583
11584 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11585
11586 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11587 pri->pvts[chanpos]->dsp_features = 0;
11588 }
11589 }
11590
11591 #ifdef SUPPORT_USERUSER
11592 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11593 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11594 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11595 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11596 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11597 }
11598 #endif
11599
11600 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11601 }
11602 }
11603 break;
11604 case PRI_EVENT_PROGRESS:
11605
11606 chanpos = pri_find_principle(pri, e->proceeding.channel);
11607 if (chanpos > -1) {
11608 #ifdef PRI_PROGRESS_MASK
11609 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11610 #else
11611 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11612 #endif
11613 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11614
11615 if (e->proceeding.cause > -1) {
11616 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11617
11618
11619 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11620 if (pri->pvts[chanpos]->owner) {
11621 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11622
11623 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11624 f.subclass = AST_CONTROL_BUSY;
11625 }
11626 }
11627 }
11628
11629 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11630 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11631 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11632 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11633 #ifdef PRI_PROGRESS_MASK
11634 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11635 #else
11636 if (e->proceeding.progress == 8) {
11637 #endif
11638
11639 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11640 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11641 pri->pvts[chanpos]->dsp_features = 0;
11642 }
11643
11644 f.subclass = AST_CONTROL_PROGRESS;
11645 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11646 }
11647 pri->pvts[chanpos]->progress = 1;
11648 pri->pvts[chanpos]->dialing = 0;
11649 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11650 }
11651 }
11652 break;
11653 case PRI_EVENT_PROCEEDING:
11654 chanpos = pri_find_principle(pri, e->proceeding.channel);
11655 if (chanpos > -1) {
11656 if (!pri->pvts[chanpos]->proceeding) {
11657 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11658
11659 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11660 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11661 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11662 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11663 #ifdef PRI_PROGRESS_MASK
11664 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11665 #else
11666 if (e->proceeding.progress == 8) {
11667 #endif
11668
11669 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11670 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11671 pri->pvts[chanpos]->dsp_features = 0;
11672 }
11673
11674 f.subclass = AST_CONTROL_PROGRESS;
11675 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11676 }
11677 pri->pvts[chanpos]->proceeding = 1;
11678 pri->pvts[chanpos]->dialing = 0;
11679 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11680 }
11681 }
11682 break;
11683 case PRI_EVENT_FACNAME:
11684 chanpos = pri_find_principle(pri, e->facname.channel);
11685 if (chanpos < 0) {
11686 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11687 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11688 } else {
11689 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11690 if (chanpos < 0) {
11691 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
11692 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11693 } else {
11694
11695 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11696 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11697 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11698 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11699 dahdi_enable_ec(pri->pvts[chanpos]);
11700 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11701 }
11702 }
11703 break;
11704 case PRI_EVENT_ANSWER:
11705 chanpos = pri_find_principle(pri, e->answer.channel);
11706 if (chanpos < 0) {
11707 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
11708 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11709 } else {
11710 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11711 if (chanpos < 0) {
11712 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
11713 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11714 } else {
11715 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11716
11717
11718
11719
11720
11721 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11722 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11723 pri->pvts[chanpos]->dsp_features = 0;
11724 }
11725 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11726 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11727 x = DAHDI_START;
11728 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11729 if (res < 0) {
11730 if (errno != EINPROGRESS) {
11731 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11732 }
11733 }
11734 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11735 pri->pvts[chanpos]->dialing = 1;
11736
11737 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11738 if (res < 0) {
11739 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11740 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11741 } else
11742 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11743
11744 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11745 } else if (pri->pvts[chanpos]->confirmanswer) {
11746 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11747 } else {
11748 pri->pvts[chanpos]->dialing = 0;
11749 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11750
11751 dahdi_enable_ec(pri->pvts[chanpos]);
11752 }
11753
11754 #ifdef SUPPORT_USERUSER
11755 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11756 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11757 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11758 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11759 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11760 }
11761 #endif
11762
11763 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11764 }
11765 }
11766 break;
11767 case PRI_EVENT_HANGUP:
11768 chanpos = pri_find_principle(pri, e->hangup.channel);
11769 if (chanpos < 0) {
11770 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
11771 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11772 } else {
11773 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11774 if (chanpos > -1) {
11775 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11776 if (!pri->pvts[chanpos]->alreadyhungup) {
11777
11778 pri->pvts[chanpos]->alreadyhungup = 1;
11779 if (pri->pvts[chanpos]->realcall)
11780 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11781 else if (pri->pvts[chanpos]->owner) {
11782
11783 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11784 switch (pri->pvts[chanpos]->owner->_state) {
11785 case AST_STATE_BUSY:
11786 case AST_STATE_UP:
11787 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11788 break;
11789 default:
11790 switch (e->hangup.cause) {
11791 case PRI_CAUSE_USER_BUSY:
11792 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11793 break;
11794 case PRI_CAUSE_CALL_REJECTED:
11795 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11796 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11797 case PRI_CAUSE_SWITCH_CONGESTION:
11798 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11799 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11800 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11801 break;
11802 default:
11803 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11804 }
11805 break;
11806 }
11807 }
11808 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11809 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11810 } else {
11811 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11812 pri->pvts[chanpos]->call = NULL;
11813 }
11814 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11815 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11816 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11817 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11818 pri->pvts[chanpos]->resetting = 1;
11819 }
11820 if (e->hangup.aoc_units > -1)
11821 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11822 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11823
11824 #ifdef SUPPORT_USERUSER
11825 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11826 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11827 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11828 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11829 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11830 }
11831 #endif
11832
11833 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11834 } else {
11835 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
11836 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11837 }
11838 }
11839 break;
11840 #ifndef PRI_EVENT_HANGUP_REQ
11841 #error please update libpri
11842 #endif
11843 case PRI_EVENT_HANGUP_REQ:
11844 chanpos = pri_find_principle(pri, e->hangup.channel);
11845 if (chanpos < 0) {
11846 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11847 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11848 } else {
11849 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11850 if (chanpos > -1) {
11851 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11852 if (pri->pvts[chanpos]->realcall)
11853 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11854 else if (pri->pvts[chanpos]->owner) {
11855 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11856 switch (pri->pvts[chanpos]->owner->_state) {
11857 case AST_STATE_BUSY:
11858 case AST_STATE_UP:
11859 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11860 break;
11861 default:
11862 switch (e->hangup.cause) {
11863 case PRI_CAUSE_USER_BUSY:
11864 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11865 break;
11866 case PRI_CAUSE_CALL_REJECTED:
11867 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11868 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11869 case PRI_CAUSE_SWITCH_CONGESTION:
11870 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11871 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11872 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11873 break;
11874 default:
11875 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11876 }
11877 break;
11878 }
11879 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);
11880 if (e->hangup.aoc_units > -1)
11881 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11882 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11883 } else {
11884 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11885 pri->pvts[chanpos]->call = NULL;
11886 }
11887 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11888 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11889 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11890 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11891 pri->pvts[chanpos]->resetting = 1;
11892 }
11893
11894 #ifdef SUPPORT_USERUSER
11895 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11896 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11897 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11898 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11899 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11900 }
11901 #endif
11902
11903 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11904 } else {
11905 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);
11906 }
11907 }
11908 break;
11909 case PRI_EVENT_HANGUP_ACK:
11910 chanpos = pri_find_principle(pri, e->hangup.channel);
11911 if (chanpos < 0) {
11912 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11913 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11914 } else {
11915 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11916 if (chanpos > -1) {
11917 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11918 pri->pvts[chanpos]->call = NULL;
11919 pri->pvts[chanpos]->resetting = 0;
11920 if (pri->pvts[chanpos]->owner) {
11921 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11922 }
11923
11924 #ifdef SUPPORT_USERUSER
11925 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11926 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11927 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11928 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11929 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11930 }
11931 #endif
11932
11933 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11934 }
11935 }
11936 break;
11937 case PRI_EVENT_CONFIG_ERR:
11938 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11939 break;
11940 case PRI_EVENT_RESTART_ACK:
11941 chanpos = pri_find_principle(pri, e->restartack.channel);
11942 if (chanpos < 0) {
11943
11944
11945
11946 for (x = 0; x < pri->numchans; x++) {
11947 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11948 chanpos = x;
11949 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11950 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11951 pri->pvts[chanpos]->prioffset, pri->span);
11952 if (pri->pvts[chanpos]->realcall)
11953 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11954 else if (pri->pvts[chanpos]->owner) {
11955 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11956 pri->pvts[chanpos]->prioffset, pri->span);
11957 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11958 }
11959 pri->pvts[chanpos]->resetting = 0;
11960 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11961 pri->pvts[chanpos]->prioffset, pri->span);
11962 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11963 if (pri->resetting)
11964 pri_check_restart(pri);
11965 break;
11966 }
11967 }
11968 if (chanpos < 0) {
11969 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11970 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11971 }
11972 } else {
11973 if (pri->pvts[chanpos]) {
11974 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11975 if (pri->pvts[chanpos]->realcall)
11976 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11977 else if (pri->pvts[chanpos]->owner) {
11978 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11979 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11980 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11981 }
11982 pri->pvts[chanpos]->resetting = 0;
11983 pri->pvts[chanpos]->inservice = 1;
11984 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11985 pri->pvts[chanpos]->prioffset, pri->span);
11986 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11987 if (pri->resetting)
11988 pri_check_restart(pri);
11989 }
11990 }
11991 break;
11992 case PRI_EVENT_SETUP_ACK:
11993 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11994 if (chanpos < 0) {
11995 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11996 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11997 } else {
11998 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11999 if (chanpos > -1) {
12000 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12001 pri->pvts[chanpos]->setup_ack = 1;
12002
12003 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
12004 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
12005 pri_information(pri->pri, pri->pvts[chanpos]->call,
12006 pri->pvts[chanpos]->dialdest[x]);
12007 }
12008 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12009 } else
12010 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
12011 }
12012 break;
12013 case PRI_EVENT_NOTIFY:
12014 chanpos = pri_find_principle(pri, e->notify.channel);
12015 if (chanpos < 0) {
12016 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
12017 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
12018 } else {
12019 struct ast_frame f = { AST_FRAME_CONTROL, };
12020 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12021 switch (e->notify.info) {
12022 case PRI_NOTIFY_REMOTE_HOLD:
12023 f.subclass = AST_CONTROL_HOLD;
12024 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12025 break;
12026 case PRI_NOTIFY_REMOTE_RETRIEVAL:
12027 f.subclass = AST_CONTROL_UNHOLD;
12028 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12029 break;
12030 }
12031 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12032 }
12033 break;
12034 default:
12035 ast_debug(1, "Event: %d\n", e->e);
12036 }
12037 }
12038 ast_mutex_unlock(&pri->lock);
12039 }
12040
12041 return NULL;
12042 }
12043
12044 static int start_pri(struct dahdi_pri *pri)
12045 {
12046 int res, x;
12047 struct dahdi_params p;
12048 struct dahdi_bufferinfo bi;
12049 struct dahdi_spaninfo si;
12050 int i;
12051
12052 for (i = 0; i < NUM_DCHANS; i++) {
12053 if (!pri->dchannels[i])
12054 break;
12055 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
12056 x = pri->dchannels[i];
12057 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
12058 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12059 return -1;
12060 }
12061 memset(&p, 0, sizeof(p));
12062 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12063 if (res) {
12064 dahdi_close_pri_fd(pri, i);
12065 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12066 return -1;
12067 }
12068 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12069 dahdi_close_pri_fd(pri, i);
12070 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
12071 return -1;
12072 }
12073 memset(&si, 0, sizeof(si));
12074 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12075 if (res) {
12076 dahdi_close_pri_fd(pri, i);
12077 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12078 }
12079 if (!si.alarms)
12080 pri->dchanavail[i] |= DCHAN_NOTINALARM;
12081 else
12082 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12083 memset(&bi, 0, sizeof(bi));
12084 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12085 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12086 bi.numbufs = 32;
12087 bi.bufsize = 1024;
12088 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12089 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12090 dahdi_close_pri_fd(pri, i);
12091 return -1;
12092 }
12093 switch (pri->sig) {
12094 case SIG_BRI:
12095 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12096 break;
12097 case SIG_BRI_PTMP:
12098 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12099 break;
12100 default:
12101 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12102 }
12103
12104 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12105 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12106 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12107 #ifdef HAVE_PRI_INBANDDISCONNECT
12108 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12109 #endif
12110
12111 if (i)
12112 pri_enslave(pri->dchans[0], pri->dchans[i]);
12113 if (!pri->dchans[i]) {
12114 dahdi_close_pri_fd(pri, i);
12115 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12116 return -1;
12117 }
12118 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12119 pri_set_nsf(pri->dchans[i], pri->nsf);
12120 #ifdef PRI_GETSET_TIMERS
12121 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12122 if (pritimers[x] != 0)
12123 pri_set_timer(pri->dchans[i], x, pritimers[x]);
12124 }
12125 #endif
12126 }
12127
12128 pri->pri = pri->dchans[0];
12129 pri->resetpos = -1;
12130 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12131 for (i = 0; i < NUM_DCHANS; i++) {
12132 if (!pri->dchannels[i])
12133 break;
12134 dahdi_close_pri_fd(pri, i);
12135 }
12136 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12137 return -1;
12138 }
12139 return 0;
12140 }
12141
12142 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
12143 {
12144 int which, span;
12145 char *ret = NULL;
12146
12147 if (pos != rpos)
12148 return ret;
12149
12150 for (which = span = 0; span < NUM_SPANS; span++) {
12151 if (pris[span].pri && ++which > state) {
12152 if (asprintf(&ret, "%d", span + 1) < 0) {
12153 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12154 }
12155 break;
12156 }
12157 }
12158 return ret;
12159 }
12160
12161 static char *complete_span_4(const char *line, const char *word, int pos, int state)
12162 {
12163 return complete_span_helper(line,word,pos,state,3);
12164 }
12165
12166 static char *complete_span_5(const char *line, const char *word, int pos, int state)
12167 {
12168 return complete_span_helper(line,word,pos,state,4);
12169 }
12170
12171 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12172 {
12173 switch (cmd) {
12174 case CLI_INIT:
12175 e->command = "pri unset debug file";
12176 e->usage = "Usage: pri unset debug file\n"
12177 " Stop sending debug output to the previously \n"
12178 " specified file\n";
12179 return NULL;
12180 case CLI_GENERATE:
12181 return NULL;
12182 }
12183
12184 ast_mutex_lock(&pridebugfdlock);
12185 close(pridebugfd);
12186 pridebugfd = -1;
12187 ast_cli(a->fd, "PRI debug output to file disabled\n");
12188 ast_mutex_unlock(&pridebugfdlock);
12189 return CLI_SUCCESS;
12190 }
12191
12192 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12193 {
12194 int myfd;
12195 switch (cmd) {
12196 case CLI_INIT:
12197 e->command = "pri set debug file";
12198 e->usage = "Usage: pri set debug file [output-file]\n"
12199 " Sends PRI debug output to the specified output file\n";
12200 return NULL;
12201 case CLI_GENERATE:
12202 return NULL;
12203 }
12204 if (a->argc < 5)
12205 return CLI_SHOWUSAGE;
12206
12207 if (ast_strlen_zero(a->argv[4]))
12208 return CLI_SHOWUSAGE;
12209
12210 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12211 if (myfd < 0) {
12212 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12213 return CLI_SUCCESS;
12214 }
12215
12216 ast_mutex_lock(&pridebugfdlock);
12217
12218 if (pridebugfd >= 0)
12219 close(pridebugfd);
12220
12221 pridebugfd = myfd;
12222 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12223 ast_mutex_unlock(&pridebugfdlock);
12224 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12225 return CLI_SUCCESS;
12226 }
12227
12228 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12229 {
12230 int span;
12231 int x;
12232 switch (cmd) {
12233 case CLI_INIT:
12234 e->command = "pri debug span";
12235 e->usage =
12236 "Usage: pri debug span <span>\n"
12237 " Enables debugging on a given PRI span\n";
12238 return NULL;
12239 case CLI_GENERATE:
12240 return complete_span_4(a->line, a->word, a->pos, a->n);
12241 }
12242 if (a->argc < 4) {
12243 return CLI_SHOWUSAGE;
12244 }
12245 span = atoi(a->argv[3]);
12246 if ((span < 1) || (span > NUM_SPANS)) {
12247 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
12248 return CLI_SUCCESS;
12249 }
12250 if (!pris[span-1].pri) {
12251 ast_cli(a->fd, "No PRI running on span %d\n", span);
12252 return CLI_SUCCESS;
12253 }
12254 for (x = 0; x < NUM_DCHANS; x++) {
12255 if (pris[span-1].dchans[x])
12256 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12257 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12258 PRI_DEBUG_Q921_STATE);
12259 }
12260 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
12261 return CLI_SUCCESS;
12262 }
12263
12264
12265
12266 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12267 {
12268 int span;
12269 int x;
12270 switch (cmd) {
12271 case CLI_INIT:
12272 e->command = "pri no debug span";
12273 e->usage =
12274 "Usage: pri no debug span <span>\n"
12275 " Disables debugging on a given PRI span\n";
12276 return NULL;
12277 case CLI_GENERATE:
12278 return complete_span_5(a->line, a->word, a->pos, a->n);
12279 }
12280 if (a->argc < 5)
12281 return CLI_SHOWUSAGE;
12282
12283 span = atoi(a->argv[4]);
12284 if ((span < 1) || (span > NUM_SPANS)) {
12285 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12286 return CLI_SUCCESS;
12287 }
12288 if (!pris[span-1].pri) {
12289 ast_cli(a->fd, "No PRI running on span %d\n", span);
12290 return CLI_SUCCESS;
12291 }
12292 for (x = 0; x < NUM_DCHANS; x++) {
12293 if (pris[span-1].dchans[x])
12294 pri_set_debug(pris[span-1].dchans[x], 0);
12295 }
12296 ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12297 return CLI_SUCCESS;
12298 }
12299
12300 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12301 {
12302 int span;
12303 int x;
12304 switch (cmd) {
12305 case CLI_INIT:
12306 e->command = "pri intensive debug span";
12307 e->usage =
12308 "Usage: pri intensive debug span <span>\n"
12309 " Enables debugging down to the Q.921 level\n";
12310 return NULL;
12311 case CLI_GENERATE:
12312 return complete_span_5(a->line, a->word, a->pos, a->n);
12313 }
12314
12315 if (a->argc < 5)
12316 return CLI_SHOWUSAGE;
12317 span = atoi(a->argv[4]);
12318 if ((span < 1) || (span > NUM_SPANS)) {
12319 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12320 return CLI_SUCCESS;
12321 }
12322 if (!pris[span-1].pri) {
12323 ast_cli(a->fd, "No PRI running on span %d\n", span);
12324 return CLI_SUCCESS;
12325 }
12326 for (x = 0; x < NUM_DCHANS; x++) {
12327 if (pris[span-1].dchans[x])
12328 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12329 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12330 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12331 }
12332 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12333 return CLI_SUCCESS;
12334 }
12335
12336 static void build_status(char *s, size_t len, int status, int active)
12337 {
12338 if (!s || len < 1) {
12339 return;
12340 }
12341 s[0] = '\0';
12342 if (status & DCHAN_PROVISIONED)
12343 strncat(s, "Provisioned, ", len - strlen(s) - 1);
12344 if (!(status & DCHAN_NOTINALARM))
12345 strncat(s, "In Alarm, ", len - strlen(s) - 1);
12346 if (status & DCHAN_UP)
12347 strncat(s, "Up", len - strlen(s) - 1);
12348 else
12349 strncat(s, "Down", len - strlen(s) - 1);
12350 if (active)
12351 strncat(s, ", Active", len - strlen(s) - 1);
12352 else
12353 strncat(s, ", Standby", len - strlen(s) - 1);
12354 s[len - 1] = '\0';
12355 }
12356
12357 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12358 {
12359 int span;
12360 int x;
12361 char status[256];
12362
12363 switch (cmd) {
12364 case CLI_INIT:
12365 e->command = "pri show spans";
12366 e->usage =
12367 "Usage: pri show spans\n"
12368 " Displays PRI Information\n";
12369 return NULL;
12370 case CLI_GENERATE:
12371 return NULL;
12372 }
12373
12374 if (a->argc != 3)
12375 return CLI_SHOWUSAGE;
12376
12377 for (span = 0; span < NUM_SPANS; span++) {
12378 if (pris[span].pri) {
12379 for (x = 0; x < NUM_DCHANS; x++) {
12380 if (pris[span].dchannels[x]) {
12381 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12382 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12383 }
12384 }
12385 }
12386 }
12387 return CLI_SUCCESS;
12388 }
12389
12390 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12391 {
12392 int span;
12393 int x;
12394 char status[256];
12395 switch (cmd) {
12396 case CLI_INIT:
12397 e->command = "pri show span";
12398 e->usage =
12399 "Usage: pri show span <span>\n"
12400 " Displays PRI Information on a given PRI span\n";
12401 return NULL;
12402 case CLI_GENERATE:
12403 return complete_span_4(a->line, a->word, a->pos, a->n);
12404 }
12405
12406 if (a->argc < 4)
12407 return CLI_SHOWUSAGE;
12408 span = atoi(a->argv[3]);
12409 if ((span < 1) || (span > NUM_SPANS)) {
12410 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12411 return CLI_SUCCESS;
12412 }
12413 if (!pris[span-1].pri) {
12414 ast_cli(a->fd, "No PRI running on span %d\n", span);
12415 return CLI_SUCCESS;
12416 }
12417 for (x = 0; x < NUM_DCHANS; x++) {
12418 if (pris[span-1].dchannels[x]) {
12419 #ifdef PRI_DUMP_INFO_STR
12420 char *info_str = NULL;
12421 #endif
12422 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12423 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12424 ast_cli(a->fd, "Status: %s\n", status);
12425 #ifdef PRI_DUMP_INFO_STR
12426 info_str = pri_dump_info_str(pris[span-1].pri);
12427 if (info_str) {
12428 ast_cli(a->fd, "%s", info_str);
12429 ast_free(info_str);
12430 }
12431 #else
12432 pri_dump_info(pris[span-1].pri);
12433 #endif
12434 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12435 }
12436 }
12437 return CLI_SUCCESS;
12438 }
12439
12440 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12441 {
12442 int x;
12443 int span;
12444 int count=0;
12445 int debug=0;
12446
12447 switch (cmd) {
12448 case CLI_INIT:
12449 e->command = "pri show debug";
12450 e->usage =
12451 "Usage: pri show debug\n"
12452 " Show the debug state of pri spans\n";
12453 return NULL;
12454 case CLI_GENERATE:
12455 return NULL;
12456 }
12457
12458 for (span = 0; span < NUM_SPANS; span++) {
12459 if (pris[span].pri) {
12460 for (x = 0; x < NUM_DCHANS; x++) {
12461 debug = 0;
12462 if (pris[span].dchans[x]) {
12463 debug = pri_get_debug(pris[span].dchans[x]);
12464 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" );
12465 count++;
12466 }
12467 }
12468 }
12469
12470 }
12471 ast_mutex_lock(&pridebugfdlock);
12472 if (pridebugfd >= 0)
12473 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12474 ast_mutex_unlock(&pridebugfdlock);
12475
12476 if (!count)
12477 ast_cli(a->fd, "No debug set or no PRI running\n");
12478 return CLI_SUCCESS;
12479 }
12480
12481 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12482 {
12483 switch (cmd) {
12484 case CLI_INIT:
12485 e->command = "pri show version";
12486 e->usage =
12487 "Usage: pri show version\n"
12488 "Show libpri version information\n";
12489 return NULL;
12490 case CLI_GENERATE:
12491 return NULL;
12492 }
12493
12494 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12495
12496 return CLI_SUCCESS;
12497 }
12498
12499 static struct ast_cli_entry dahdi_pri_cli[] = {
12500 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
12501 AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
12502 AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
12503 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
12504 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
12505 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
12506 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
12507 AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
12508 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
12509 };
12510
12511 #endif
12512
12513 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12514 {
12515 int channel;
12516 int ret;
12517 switch (cmd) {
12518 case CLI_INIT:
12519 e->command = "dahdi destroy channel";
12520 e->usage =
12521 "Usage: dahdi destroy channel <chan num>\n"
12522 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12523 return NULL;
12524 case CLI_GENERATE:
12525 return NULL;
12526 }
12527 if (a->argc != 4)
12528 return CLI_SHOWUSAGE;
12529
12530 channel = atoi(a->argv[3]);
12531 ret = dahdi_destroy_channel_bynum(channel);
12532 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12533 }
12534
12535 static void dahdi_softhangup_all(void)
12536 {
12537 struct dahdi_pvt *p;
12538 retry:
12539 ast_mutex_lock(&iflock);
12540 for (p = iflist; p; p = p->next) {
12541 ast_mutex_lock(&p->lock);
12542 if (p->owner && !p->restartpending) {
12543 if (ast_channel_trylock(p->owner)) {
12544 if (option_debug > 2)
12545 ast_verbose("Avoiding deadlock\n");
12546
12547 ast_mutex_unlock(&p->lock);
12548 ast_mutex_unlock(&iflock);
12549 goto retry;
12550 }
12551 if (option_debug > 2)
12552 ast_verbose("Softhanging up on %s\n", p->owner->name);
12553 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12554 p->restartpending = 1;
12555 num_restart_pending++;
12556 ast_channel_unlock(p->owner);
12557 }
12558 ast_mutex_unlock(&p->lock);
12559 }
12560 ast_mutex_unlock(&iflock);
12561 }
12562
12563 static int setup_dahdi(int reload);
12564 static int dahdi_restart(void)
12565 {
12566 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12567 int i, j;
12568 #endif
12569 int cancel_code;
12570 struct dahdi_pvt *p;
12571
12572 ast_mutex_lock(&restart_lock);
12573
12574 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12575 dahdi_softhangup_all();
12576 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12577
12578 #if defined(HAVE_PRI)
12579 for (i = 0; i < NUM_SPANS; i++) {
12580 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12581 cancel_code = pthread_cancel(pris[i].master);
12582 pthread_kill(pris[i].master, SIGURG);
12583 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12584 pthread_join(pris[i].master, NULL);
12585 ast_debug(4, "Joined thread of span %d\n", i);
12586 }
12587 }
12588 #endif
12589
12590 #if defined(HAVE_SS7)
12591 for (i = 0; i < NUM_SPANS; i++) {
12592 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12593 cancel_code = pthread_cancel(linksets[i].master);
12594 pthread_kill(linksets[i].master, SIGURG);
12595 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12596 pthread_join(linksets[i].master, NULL);
12597 ast_debug(4, "Joined thread of span %d\n", i);
12598 }
12599 }
12600 #endif
12601
12602 ast_mutex_lock(&monlock);
12603 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12604 cancel_code = pthread_cancel(monitor_thread);
12605 pthread_kill(monitor_thread, SIGURG);
12606 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12607 pthread_join(monitor_thread, NULL);
12608 ast_debug(4, "Joined monitor thread\n");
12609 }
12610 monitor_thread = AST_PTHREADT_NULL;
12611
12612 ast_mutex_lock(&mwi_thread_lock);
12613 while (mwi_thread_count > 0) {
12614 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12615 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12616 }
12617 ast_mutex_unlock(&mwi_thread_lock);
12618 ast_mutex_lock(&ss_thread_lock);
12619 while (ss_thread_count > 0) {
12620 int x = DAHDI_FLASH;
12621 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12622
12623 for (p = iflist; p; p = p->next) {
12624 if (p->owner)
12625 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
12626 }
12627 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12628 }
12629
12630
12631 dahdi_softhangup_all();
12632 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12633 destroy_all_channels();
12634 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12635
12636 ast_mutex_unlock(&monlock);
12637
12638 #ifdef HAVE_PRI
12639 for (i = 0; i < NUM_SPANS; i++) {
12640 for (j = 0; j < NUM_DCHANS; j++)
12641 dahdi_close_pri_fd(&(pris[i]), j);
12642 }
12643
12644 memset(pris, 0, sizeof(pris));
12645 for (i = 0; i < NUM_SPANS; i++) {
12646 ast_mutex_init(&pris[i].lock);
12647 pris[i].offset = -1;
12648 pris[i].master = AST_PTHREADT_NULL;
12649 for (j = 0; j < NUM_DCHANS; j++)
12650 pris[i].fds[j] = -1;
12651 }
12652 pri_set_error(dahdi_pri_error);
12653 pri_set_message(dahdi_pri_message);
12654 #endif
12655 #ifdef HAVE_SS7
12656 for (i = 0; i < NUM_SPANS; i++) {
12657 for (j = 0; j < NUM_DCHANS; j++)
12658 dahdi_close_ss7_fd(&(linksets[i]), j);
12659 }
12660
12661 memset(linksets, 0, sizeof(linksets));
12662 for (i = 0; i < NUM_SPANS; i++) {
12663 ast_mutex_init(&linksets[i].lock);
12664 linksets[i].master = AST_PTHREADT_NULL;
12665 for (j = 0; j < NUM_DCHANS; j++)
12666 linksets[i].fds[j] = -1;
12667 }
12668 ss7_set_error(dahdi_ss7_error);
12669 ss7_set_message(dahdi_ss7_message);
12670 #endif
12671
12672 if (setup_dahdi(2) != 0) {
12673 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12674 ast_mutex_unlock(&ss_thread_lock);
12675 return 1;
12676 }
12677 ast_mutex_unlock(&ss_thread_lock);
12678 ast_mutex_unlock(&restart_lock);
12679 return 0;
12680 }
12681
12682 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12683 {
12684 switch (cmd) {
12685 case CLI_INIT:
12686 e->command = "dahdi restart";
12687 e->usage =
12688 "Usage: dahdi restart\n"
12689 " Restarts the DAHDI channels: destroys them all and then\n"
12690 " re-reads them from chan_dahdi.conf.\n"
12691 " Note that this will STOP any running CALL on DAHDI channels.\n"
12692 "";
12693 return NULL;
12694 case CLI_GENERATE:
12695 return NULL;
12696 }
12697 if (a->argc != 2)
12698 return CLI_SHOWUSAGE;
12699
12700 if (dahdi_restart() != 0)
12701 return CLI_FAILURE;
12702 return CLI_SUCCESS;
12703 }
12704
12705 static int action_dahdirestart(struct mansession *s, const struct message *m)
12706 {
12707 if (dahdi_restart() != 0) {
12708 astman_send_error(s, m, "Failed rereading DAHDI configuration");
12709 return 1;
12710 }
12711 astman_send_ack(s, m, "DAHDIRestart: Success");
12712 return 0;
12713 }
12714
12715 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12716 {
12717 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12718 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12719 unsigned int targetnum = 0;
12720 int filtertype = 0;
12721 struct dahdi_pvt *tmp = NULL;
12722 char tmps[20] = "";
12723 char statestr[20] = "";
12724 char blockstr[20] = "";
12725 ast_mutex_t *lock;
12726 struct dahdi_pvt *start;
12727 #ifdef HAVE_PRI
12728 int trunkgroup;
12729 struct dahdi_pri *pri = NULL;
12730 int x;
12731 #endif
12732 switch (cmd) {
12733 case CLI_INIT:
12734 e->command = "dahdi show channels [trunkgroup|group|context]";
12735 e->usage =
12736 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12737 " Shows a list of available channels with optional filtering\n"
12738 " <group> must be a number between 0 and 63\n";
12739 return NULL;
12740 case CLI_GENERATE:
12741 return NULL;
12742 }
12743
12744 lock = &iflock;
12745 start = iflist;
12746
12747
12748
12749 if (!((a->argc == 3) || (a->argc == 5)))
12750 return CLI_SHOWUSAGE;
12751
12752 if (a->argc == 5) {
12753 #ifdef HAVE_PRI
12754 if (!strcasecmp(a->argv[3], "trunkgroup")) {
12755
12756 if ((trunkgroup = atoi(a->argv[4])) < 1)
12757 return CLI_SHOWUSAGE;
12758 for (x = 0; x < NUM_SPANS; x++) {
12759 if (pris[x].trunkgroup == trunkgroup) {
12760 pri = pris + x;
12761 break;
12762 }
12763 }
12764 if (pri) {
12765 start = pri->crvs;
12766 lock = &pri->lock;
12767 } else {
12768 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12769 return CLI_FAILURE;
12770 }
12771 } else
12772 #endif
12773 if (!strcasecmp(a->argv[3], "group")) {
12774 targetnum = atoi(a->argv[4]);
12775 if ((targetnum < 0) || (targetnum > 63))
12776 return CLI_SHOWUSAGE;
12777 targetnum = 1 << targetnum;
12778 filtertype = 1;
12779 } else if (!strcasecmp(a->argv[3], "context")) {
12780 filtertype = 2;
12781 }
12782 }
12783
12784 ast_mutex_lock(lock);
12785 #ifdef HAVE_PRI
12786 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12787 #else
12788 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12789 #endif
12790
12791 tmp = start;
12792 while (tmp) {
12793 if (filtertype) {
12794 switch(filtertype) {
12795 case 1:
12796 if (!(tmp->group & targetnum)) {
12797 tmp = tmp->next;
12798 continue;
12799 }
12800 break;
12801 case 2:
12802 if (strcasecmp(tmp->context, a->argv[4])) {
12803 tmp = tmp->next;
12804 continue;
12805 }
12806 break;
12807 default:
12808 ;
12809 }
12810 }
12811 if (tmp->channel > 0) {
12812 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12813 } else
12814 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12815
12816 if (tmp->locallyblocked)
12817 blockstr[0] = 'L';
12818 else
12819 blockstr[0] = ' ';
12820
12821 if (tmp->remotelyblocked)
12822 blockstr[1] = 'R';
12823 else
12824 blockstr[1] = ' ';
12825
12826 blockstr[2] = '\0';
12827
12828 snprintf(statestr, sizeof(statestr), "%s", "In Service");
12829
12830 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12831 tmp = tmp->next;
12832 }
12833 ast_mutex_unlock(lock);
12834 return CLI_SUCCESS;
12835 #undef FORMAT
12836 #undef FORMAT2
12837 }
12838
12839 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12840 {
12841 int channel;
12842 struct dahdi_pvt *tmp = NULL;
12843 struct dahdi_confinfo ci;
12844 struct dahdi_params ps;
12845 int x;
12846 ast_mutex_t *lock;
12847 struct dahdi_pvt *start;
12848 #ifdef HAVE_PRI
12849 char *c;
12850 int trunkgroup;
12851 struct dahdi_pri *pri=NULL;
12852 #endif
12853 switch (cmd) {
12854 case CLI_INIT:
12855 e->command = "dahdi show channel";
12856 e->usage =
12857 "Usage: dahdi show channel <chan num>\n"
12858 " Detailed information about a given channel\n";
12859 return NULL;
12860 case CLI_GENERATE:
12861 return NULL;
12862 }
12863
12864 lock = &iflock;
12865 start = iflist;
12866
12867 if (a->argc != 4)
12868 return CLI_SHOWUSAGE;
12869 #ifdef HAVE_PRI
12870 if ((c = strchr(a->argv[3], ':'))) {
12871 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12872 return CLI_SHOWUSAGE;
12873 if ((trunkgroup < 1) || (channel < 1))
12874 return CLI_SHOWUSAGE;
12875 for (x = 0; x < NUM_SPANS; x++) {
12876 if (pris[x].trunkgroup == trunkgroup) {
12877 pri = pris + x;
12878 break;
12879 }
12880 }
12881 if (pri) {
12882 start = pri->crvs;
12883 lock = &pri->lock;
12884 } else {
12885 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12886 return CLI_FAILURE;
12887 }
12888 } else
12889 #endif
12890 channel = atoi(a->argv[3]);
12891
12892 ast_mutex_lock(lock);
12893 tmp = start;
12894 while (tmp) {
12895 if (tmp->channel == channel) {
12896 #ifdef HAVE_PRI
12897 if (pri)
12898 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12899 else
12900 #endif
12901 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12902 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12903 ast_cli(a->fd, "Span: %d\n", tmp->span);
12904 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12905 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12906 ast_cli(a->fd, "Context: %s\n", tmp->context);
12907 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12908 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12909 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12910 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12911 if (tmp->vars) {
12912 struct ast_variable *v;
12913 ast_cli(a->fd, "Variables:\n");
12914 for (v = tmp->vars ; v ; v = v->next)
12915 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
12916 }
12917 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12918 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12919 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12920 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12921 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12922 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)" : "");
12923 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)" : "");
12924 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)" : "");
12925 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12926 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12927 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12928 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12929 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12930 if (tmp->busydetect) {
12931 #if defined(BUSYDETECT_TONEONLY)
12932 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12933 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12934 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12935 #endif
12936 #ifdef BUSYDETECT_DEBUG
12937 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
12938 #endif
12939 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
12940 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
12941 }
12942 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12943 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12944 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12945 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12946 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12947 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12948 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12949 ast_cli(a->fd, "Echo Cancellation:\n");
12950
12951 if (tmp->echocancel.head.tap_length) {
12952 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12953 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12954 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12955 }
12956 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12957 } else {
12958 ast_cli(a->fd, "\tnone\n");
12959 }
12960 if (tmp->master)
12961 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12962 for (x = 0; x < MAX_SLAVES; x++) {
12963 if (tmp->slaves[x])
12964 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12965 }
12966 #ifdef HAVE_SS7
12967 if (tmp->ss7) {
12968 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12969 }
12970 #endif
12971 #ifdef HAVE_PRI
12972 if (tmp->pri) {
12973 ast_cli(a->fd, "PRI Flags: ");
12974 if (tmp->resetting)
12975 ast_cli(a->fd, "Resetting ");
12976 if (tmp->call)
12977 ast_cli(a->fd, "Call ");
12978 if (tmp->bearer)
12979 ast_cli(a->fd, "Bearer ");
12980 ast_cli(a->fd, "\n");
12981 if (tmp->logicalspan)
12982 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12983 else
12984 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12985 }
12986
12987 #endif
12988 memset(&ci, 0, sizeof(ci));
12989 ps.channo = tmp->channel;
12990 if (tmp->subs[SUB_REAL].dfd > -1) {
12991 memset(&ci, 0, sizeof(ci));
12992 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12993 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12994 }
12995 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12996 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12997 }
12998 memset(&ps, 0, sizeof(ps));
12999 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
13000 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
13001 } else {
13002 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
13003 }
13004 }
13005 ast_mutex_unlock(lock);
13006 return CLI_SUCCESS;
13007 }
13008 tmp = tmp->next;
13009 }
13010
13011 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13012 ast_mutex_unlock(lock);
13013 return CLI_FAILURE;
13014 }
13015
13016 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13017 {
13018 int i, j;
13019 switch (cmd) {
13020 case CLI_INIT:
13021 e->command = "dahdi show cadences";
13022 e->usage =
13023 "Usage: dahdi show cadences\n"
13024 " Shows all cadences currently defined\n";
13025 return NULL;
13026 case CLI_GENERATE:
13027 return NULL;
13028 }
13029 for (i = 0; i < num_cadence; i++) {
13030 char output[1024];
13031 char tmp[16], tmp2[64];
13032 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
13033 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
13034
13035 for (j = 0; j < 16; j++) {
13036 if (cadences[i].ringcadence[j] == 0)
13037 break;
13038 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
13039 if (cidrings[i] * 2 - 1 == j)
13040 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
13041 else
13042 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
13043 if (j != 0)
13044 strncat(output, ",", sizeof(output) - strlen(output) - 1);
13045 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
13046 }
13047 ast_cli(a->fd,"%s\n",output);
13048 }
13049 return CLI_SUCCESS;
13050 }
13051
13052
13053 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13054 {
13055 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
13056 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
13057 int span;
13058 int res;
13059 char alarmstr[50];
13060
13061 int ctl;
13062 struct dahdi_spaninfo s;
13063
13064 switch (cmd) {
13065 case CLI_INIT:
13066 e->command = "dahdi show status";
13067 e->usage =
13068 "Usage: dahdi show status\n"
13069 " Shows a list of DAHDI cards with status\n";
13070 return NULL;
13071 case CLI_GENERATE:
13072 return NULL;
13073 }
13074 ctl = open("/dev/dahdi/ctl", O_RDWR);
13075 if (ctl < 0) {
13076 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13077 return CLI_FAILURE;
13078 }
13079 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13080
13081 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13082 s.spanno = span;
13083 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13084 if (res) {
13085 continue;
13086 }
13087 alarmstr[0] = '\0';
13088 if (s.alarms > 0) {
13089 if (s.alarms & DAHDI_ALARM_BLUE)
13090 strcat(alarmstr, "BLU/");
13091 if (s.alarms & DAHDI_ALARM_YELLOW)
13092 strcat(alarmstr, "YEL/");
13093 if (s.alarms & DAHDI_ALARM_RED)
13094 strcat(alarmstr, "RED/");
13095 if (s.alarms & DAHDI_ALARM_LOOPBACK)
13096 strcat(alarmstr, "LB/");
13097 if (s.alarms & DAHDI_ALARM_RECOVER)
13098 strcat(alarmstr, "REC/");
13099 if (s.alarms & DAHDI_ALARM_NOTOPEN)
13100 strcat(alarmstr, "NOP/");
13101 if (!strlen(alarmstr))
13102 strcat(alarmstr, "UUU/");
13103 if (strlen(alarmstr)) {
13104
13105 alarmstr[strlen(alarmstr) - 1] = '\0';
13106 }
13107 } else {
13108 if (s.numchans)
13109 strcpy(alarmstr, "OK");
13110 else
13111 strcpy(alarmstr, "UNCONFIGURED");
13112 }
13113
13114 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13115 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13116 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13117 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13118 "CAS"
13119 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13120 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13121 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13122 "Unk"
13123 , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13124 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13125 , lbostr[s.lbo]
13126 );
13127 }
13128 close(ctl);
13129
13130 return CLI_SUCCESS;
13131 #undef FORMAT
13132 #undef FORMAT2
13133 }
13134
13135 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13136 {
13137 int pseudo_fd = -1;
13138 struct dahdi_versioninfo vi;
13139
13140 switch (cmd) {
13141 case CLI_INIT:
13142 e->command = "dahdi show version";
13143 e->usage =
13144 "Usage: dahdi show version\n"
13145 " Shows the DAHDI version in use\n";
13146 return NULL;
13147 case CLI_GENERATE:
13148 return NULL;
13149 }
13150 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13151 ast_cli(a->fd, "Failed to open control file to get version.\n");
13152 return CLI_SUCCESS;
13153 }
13154
13155 strcpy(vi.version, "Unknown");
13156 strcpy(vi.echo_canceller, "Unknown");
13157
13158 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13159 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13160 else
13161 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13162
13163 close(pseudo_fd);
13164
13165 return CLI_SUCCESS;
13166 }
13167
13168 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13169 {
13170 int channel;
13171 int gain;
13172 int tx;
13173 struct dahdi_hwgain hwgain;
13174 struct dahdi_pvt *tmp = NULL;
13175
13176 switch (cmd) {
13177 case CLI_INIT:
13178 e->command = "dahdi set hwgain";
13179 e->usage =
13180 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
13181 " Sets the hardware gain on a a given channel, overriding the\n"
13182 " value provided at module loadtime, whether the channel is in\n"
13183 " use or not. Changes take effect immediately.\n"
13184 " <rx|tx> which direction do you want to change (relative to our module)\n"
13185 " <chan num> is the channel number relative to the device\n"
13186 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13187 return NULL;
13188 case CLI_GENERATE:
13189 return NULL;
13190 }
13191
13192 if (a->argc != 6)
13193 return CLI_SHOWUSAGE;
13194
13195 if (!strcasecmp("rx", a->argv[3]))
13196 tx = 0;
13197 else if (!strcasecmp("tx", a->argv[3]))
13198 tx = 1;
13199 else
13200 return CLI_SHOWUSAGE;
13201
13202 channel = atoi(a->argv[4]);
13203 gain = atof(a->argv[5])*10.0;
13204
13205 ast_mutex_lock(&iflock);
13206
13207 for (tmp = iflist; tmp; tmp = tmp->next) {
13208
13209 if (tmp->channel != channel)
13210 continue;
13211
13212 if (tmp->subs[SUB_REAL].dfd == -1)
13213 break;
13214
13215 hwgain.newgain = gain;
13216 hwgain.tx = tx;
13217 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
13218 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
13219 ast_mutex_unlock(&iflock);
13220 return CLI_FAILURE;
13221 }
13222 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
13223 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
13224 break;
13225 }
13226
13227 ast_mutex_unlock(&iflock);
13228
13229 if (tmp)
13230 return CLI_SUCCESS;
13231
13232 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13233 return CLI_FAILURE;
13234
13235 }
13236
13237 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13238 {
13239 int channel;
13240 float gain;
13241 int tx;
13242 int res;
13243 ast_mutex_t *lock;
13244 struct dahdi_pvt *tmp = NULL;
13245
13246 switch (cmd) {
13247 case CLI_INIT:
13248 e->command = "dahdi set swgain";
13249 e->usage =
13250 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13251 " Sets the software gain on a a given channel, overriding the\n"
13252 " value provided at module loadtime, whether the channel is in\n"
13253 " use or not. Changes take effect immediately.\n"
13254 " <rx|tx> which direction do you want to change (relative to our module)\n"
13255 " <chan num> is the channel number relative to the device\n"
13256 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13257 return NULL;
13258 case CLI_GENERATE:
13259 return NULL;
13260 }
13261
13262 lock = &iflock;
13263
13264 if (a->argc != 6)
13265 return CLI_SHOWUSAGE;
13266
13267 if (!strcasecmp("rx", a->argv[3]))
13268 tx = 0;
13269 else if (!strcasecmp("tx", a->argv[3]))
13270 tx = 1;
13271 else
13272 return CLI_SHOWUSAGE;
13273
13274 channel = atoi(a->argv[4]);
13275 gain = atof(a->argv[5]);
13276
13277 ast_mutex_lock(lock);
13278 for (tmp = iflist; tmp; tmp = tmp->next) {
13279
13280 if (tmp->channel != channel)
13281 continue;
13282
13283 if (tmp->subs[SUB_REAL].dfd == -1)
13284 break;
13285
13286 if (tx)
13287 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13288 else
13289 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13290
13291 if (res) {
13292 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13293 ast_mutex_unlock(lock);
13294 return CLI_FAILURE;
13295 }
13296
13297 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13298 tx ? "tx" : "rx", gain, channel);
13299 break;
13300 }
13301 ast_mutex_unlock(lock);
13302
13303 if (tmp)
13304 return CLI_SUCCESS;
13305
13306 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13307 return CLI_FAILURE;
13308
13309 }
13310
13311 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13312 {
13313 int channel;
13314 int on;
13315 struct dahdi_pvt *dahdi_chan = NULL;
13316
13317 switch (cmd) {
13318 case CLI_INIT:
13319 e->command = "dahdi set dnd";
13320 e->usage =
13321 "Usage: dahdi set dnd <chan#> <on|off>\n"
13322 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13323 " Changes take effect immediately.\n"
13324 " <chan num> is the channel number\n"
13325 " <on|off> Enable or disable DND mode?\n"
13326 ;
13327 return NULL;
13328 case CLI_GENERATE:
13329 return NULL;
13330 }
13331
13332 if (a->argc != 5)
13333 return CLI_SHOWUSAGE;
13334
13335 if ((channel = atoi(a->argv[3])) <= 0) {
13336 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13337 return CLI_SHOWUSAGE;
13338 }
13339
13340 if (ast_true(a->argv[4]))
13341 on = 1;
13342 else if (ast_false(a->argv[4]))
13343 on = 0;
13344 else {
13345 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13346 return CLI_SHOWUSAGE;
13347 }
13348
13349 ast_mutex_lock(&iflock);
13350 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13351 if (dahdi_chan->channel != channel)
13352 continue;
13353
13354
13355 dahdi_dnd(dahdi_chan, on);
13356 break;
13357 }
13358 ast_mutex_unlock(&iflock);
13359
13360 if (!dahdi_chan) {
13361 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13362 return CLI_FAILURE;
13363 }
13364
13365 return CLI_SUCCESS;
13366 }
13367
13368 static struct ast_cli_entry dahdi_cli[] = {
13369 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
13370 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
13371 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
13372 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
13373 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
13374 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
13375 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
13376 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
13377 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
13378 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
13379 };
13380
13381 #define TRANSFER 0
13382 #define HANGUP 1
13383
13384 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13385 {
13386 if (p) {
13387 switch (mode) {
13388 case TRANSFER:
13389 p->fake_event = DAHDI_EVENT_WINKFLASH;
13390 break;
13391 case HANGUP:
13392 p->fake_event = DAHDI_EVENT_ONHOOK;
13393 break;
13394 default:
13395 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
13396 }
13397 }
13398 return 0;
13399 }
13400 static struct dahdi_pvt *find_channel(int channel)
13401 {
13402 struct dahdi_pvt *p = iflist;
13403 while (p) {
13404 if (p->channel == channel) {
13405 break;
13406 }
13407 p = p->next;
13408 }
13409 return p;
13410 }
13411
13412 static int action_dahdidndon(struct mansession *s, const struct message *m)
13413 {
13414 struct dahdi_pvt *p = NULL;
13415 const char *channel = astman_get_header(m, "DAHDIChannel");
13416
13417 if (ast_strlen_zero(channel)) {
13418 astman_send_error(s, m, "No channel specified");
13419 return 0;
13420 }
13421 p = find_channel(atoi(channel));
13422 if (!p) {
13423 astman_send_error(s, m, "No such channel");
13424 return 0;
13425 }
13426 p->dnd = 1;
13427 astman_send_ack(s, m, "DND Enabled");
13428 return 0;
13429 }
13430
13431 static int action_dahdidndoff(struct mansession *s, const struct message *m)
13432 {
13433 struct dahdi_pvt *p = NULL;
13434 const char *channel = astman_get_header(m, "DAHDIChannel");
13435
13436 if (ast_strlen_zero(channel)) {
13437 astman_send_error(s, m, "No channel specified");
13438 return 0;
13439 }
13440 p = find_channel(atoi(channel));
13441 if (!p) {
13442 astman_send_error(s, m, "No such channel");
13443 return 0;
13444 }
13445 p->dnd = 0;
13446 astman_send_ack(s, m, "DND Disabled");
13447 return 0;
13448 }
13449
13450 static int action_transfer(struct mansession *s, const struct message *m)
13451 {
13452 struct dahdi_pvt *p = NULL;
13453 const char *channel = astman_get_header(m, "DAHDIChannel");
13454
13455 if (ast_strlen_zero(channel)) {
13456 astman_send_error(s, m, "No channel specified");
13457 return 0;
13458 }
13459 p = find_channel(atoi(channel));
13460 if (!p) {
13461 astman_send_error(s, m, "No such channel");
13462 return 0;
13463 }
13464 dahdi_fake_event(p,TRANSFER);
13465 astman_send_ack(s, m, "DAHDITransfer");
13466 return 0;
13467 }
13468
13469 static int action_transferhangup(struct mansession *s, const struct message *m)
13470 {
13471 struct dahdi_pvt *p = NULL;
13472 const char *channel = astman_get_header(m, "DAHDIChannel");
13473
13474 if (ast_strlen_zero(channel)) {
13475 astman_send_error(s, m, "No channel specified");
13476 return 0;
13477 }
13478 p = find_channel(atoi(channel));
13479 if (!p) {
13480 astman_send_error(s, m, "No such channel");
13481 return 0;
13482 }
13483 dahdi_fake_event(p,HANGUP);
13484 astman_send_ack(s, m, "DAHDIHangup");
13485 return 0;
13486 }
13487
13488 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
13489 {
13490 struct dahdi_pvt *p = NULL;
13491 const char *channel = astman_get_header(m, "DAHDIChannel");
13492 const char *number = astman_get_header(m, "Number");
13493 int i;
13494
13495 if (ast_strlen_zero(channel)) {
13496 astman_send_error(s, m, "No channel specified");
13497 return 0;
13498 }
13499 if (ast_strlen_zero(number)) {
13500 astman_send_error(s, m, "No number specified");
13501 return 0;
13502 }
13503 p = find_channel(atoi(channel));
13504 if (!p) {
13505 astman_send_error(s, m, "No such channel");
13506 return 0;
13507 }
13508 if (!p->owner) {
13509 astman_send_error(s, m, "Channel does not have it's owner");
13510 return 0;
13511 }
13512 for (i = 0; i < strlen(number); i++) {
13513 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13514 dahdi_queue_frame(p, &f, NULL);
13515 }
13516 astman_send_ack(s, m, "DAHDIDialOffhook");
13517 return 0;
13518 }
13519
13520 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
13521 {
13522 struct dahdi_pvt *tmp = NULL;
13523 const char *id = astman_get_header(m, "ActionID");
13524 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13525 char idText[256] = "";
13526 int channels = 0;
13527 int dahdichanquery = -1;
13528 if (!ast_strlen_zero(dahdichannel)) {
13529 dahdichanquery = atoi(dahdichannel);
13530 }
13531
13532 astman_send_ack(s, m, "DAHDI channel status will follow");
13533 if (!ast_strlen_zero(id))
13534 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13535
13536 ast_mutex_lock(&iflock);
13537
13538 tmp = iflist;
13539 while (tmp) {
13540 if (tmp->channel > 0) {
13541 int alm = get_alarms(tmp);
13542
13543
13544 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13545 continue;
13546
13547 channels++;
13548 if (tmp->owner) {
13549
13550 astman_append(s,
13551 "Event: DAHDIShowChannels\r\n"
13552 "DAHDIChannel: %d\r\n"
13553 "Channel: %s\r\n"
13554 "Uniqueid: %s\r\n"
13555 "AccountCode: %s\r\n"
13556 "Signalling: %s\r\n"
13557 "SignallingCode: %d\r\n"
13558 "Context: %s\r\n"
13559 "DND: %s\r\n"
13560 "Alarm: %s\r\n"
13561 "%s"
13562 "\r\n",
13563 tmp->channel,
13564 tmp->owner->name,
13565 tmp->owner->uniqueid,
13566 tmp->owner->accountcode,
13567 sig2str(tmp->sig),
13568 tmp->sig,
13569 tmp->context,
13570 tmp->dnd ? "Enabled" : "Disabled",
13571 alarm2str(alm), idText);
13572 } else {
13573 astman_append(s,
13574 "Event: DAHDIShowChannels\r\n"
13575 "DAHDIChannel: %d\r\n"
13576 "Signalling: %s\r\n"
13577 "SignallingCode: %d\r\n"
13578 "Context: %s\r\n"
13579 "DND: %s\r\n"
13580 "Alarm: %s\r\n"
13581 "%s"
13582 "\r\n",
13583 tmp->channel, sig2str(tmp->sig), tmp->sig,
13584 tmp->context,
13585 tmp->dnd ? "Enabled" : "Disabled",
13586 alarm2str(alm), idText);
13587 }
13588 }
13589
13590 tmp = tmp->next;
13591 }
13592
13593 ast_mutex_unlock(&iflock);
13594
13595 astman_append(s,
13596 "Event: DAHDIShowChannelsComplete\r\n"
13597 "%s"
13598 "Items: %d\r\n"
13599 "\r\n",
13600 idText,
13601 channels);
13602 return 0;
13603 }
13604
13605 #ifdef HAVE_SS7
13606 static int linkset_addsigchan(int sigchan)
13607 {
13608 struct dahdi_ss7 *link;
13609 int res;
13610 int curfd;
13611 struct dahdi_params p;
13612 struct dahdi_bufferinfo bi;
13613 struct dahdi_spaninfo si;
13614
13615
13616 link = ss7_resolve_linkset(cur_linkset);
13617 if (!link) {
13618 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
13619 return -1;
13620 }
13621
13622 if (cur_ss7type < 0) {
13623 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13624 return -1;
13625 }
13626
13627 if (!link->ss7)
13628 link->ss7 = ss7_new(cur_ss7type);
13629
13630 if (!link->ss7) {
13631 ast_log(LOG_ERROR, "Can't create new SS7!\n");
13632 return -1;
13633 }
13634
13635 link->type = cur_ss7type;
13636
13637 if (cur_pointcode < 0) {
13638 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13639 return -1;
13640 } else
13641 ss7_set_pc(link->ss7, cur_pointcode);
13642
13643 if (sigchan < 0) {
13644 ast_log(LOG_ERROR, "Invalid sigchan!\n");
13645 return -1;
13646 } else {
13647 if (link->numsigchans >= NUM_DCHANS) {
13648 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13649 return -1;
13650 }
13651 curfd = link->numsigchans;
13652
13653 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13654 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13655 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13656 return -1;
13657 }
13658 memset(&p, 0, sizeof(p));
13659 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13660 if (res) {
13661 dahdi_close_ss7_fd(link, curfd);
13662 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13663 return -1;
13664 }
13665 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13666 dahdi_close_ss7_fd(link, curfd);
13667 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13668 return -1;
13669 }
13670
13671 memset(&bi, 0, sizeof(bi));
13672 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13673 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13674 bi.numbufs = 32;
13675 bi.bufsize = 512;
13676
13677 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13678 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13679 dahdi_close_ss7_fd(link, curfd);
13680 return -1;
13681 }
13682
13683 if (p.sigtype == DAHDI_SIG_MTP2)
13684 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13685 else
13686 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13687
13688 link->numsigchans++;
13689
13690 memset(&si, 0, sizeof(si));
13691 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13692 if (res) {
13693 dahdi_close_ss7_fd(link, curfd);
13694 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13695 }
13696
13697 if (!si.alarms) {
13698 link->linkstate[curfd] = LINKSTATE_DOWN;
13699 ss7_link_noalarm(link->ss7, link->fds[curfd]);
13700 } else {
13701 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13702 ss7_link_alarm(link->ss7, link->fds[curfd]);
13703 }
13704 }
13705
13706 if (cur_adjpointcode < 0) {
13707 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13708 return -1;
13709 } else {
13710 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13711 }
13712
13713 if (cur_defaultdpc < 0) {
13714 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13715 return -1;
13716 }
13717
13718 if (cur_networkindicator < 0) {
13719 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13720 return -1;
13721 } else
13722 ss7_set_network_ind(link->ss7, cur_networkindicator);
13723
13724 return 0;
13725 }
13726
13727 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13728 {
13729 int span;
13730 switch (cmd) {
13731 case CLI_INIT:
13732 e->command = "ss7 no debug linkset";
13733 e->usage =
13734 "Usage: ss7 no debug linkset <span>\n"
13735 " Disables debugging on a given SS7 linkset\n";
13736 return NULL;
13737 case CLI_GENERATE:
13738 return NULL;
13739 }
13740 if (a->argc < 5)
13741 return CLI_SHOWUSAGE;
13742 span = atoi(a->argv[4]);
13743 if ((span < 1) || (span > NUM_SPANS)) {
13744 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13745 return CLI_SUCCESS;
13746 }
13747 if (!linksets[span-1].ss7) {
13748 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13749 return CLI_SUCCESS;
13750 }
13751 if (linksets[span-1].ss7)
13752 ss7_set_debug(linksets[span-1].ss7, 0);
13753
13754 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13755 return CLI_SUCCESS;
13756 }
13757
13758 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13759 {
13760 int span;
13761 switch (cmd) {
13762 case CLI_INIT:
13763 e->command = "ss7 debug linkset";
13764 e->usage =
13765 "Usage: ss7 debug linkset <linkset>\n"
13766 " Enables debugging on a given SS7 linkset\n";
13767 return NULL;
13768 case CLI_GENERATE:
13769 return NULL;
13770 }
13771 if (a->argc < 4)
13772 return CLI_SHOWUSAGE;
13773 span = atoi(a->argv[3]);
13774 if ((span < 1) || (span > NUM_SPANS)) {
13775 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13776 return CLI_SUCCESS;
13777 }
13778 if (!linksets[span-1].ss7) {
13779 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13780 return CLI_SUCCESS;
13781 }
13782 if (linksets[span-1].ss7)
13783 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13784
13785 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13786 return CLI_SUCCESS;
13787 }
13788
13789 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13790 {
13791 int linkset, cic;
13792 int blocked = -1, i;
13793 switch (cmd) {
13794 case CLI_INIT:
13795 e->command = "ss7 block cic";
13796 e->usage =
13797 "Usage: ss7 block cic <linkset> <CIC>\n"
13798 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13799 return NULL;
13800 case CLI_GENERATE:
13801 return NULL;
13802 }
13803 if (a->argc == 5)
13804 linkset = atoi(a->argv[3]);
13805 else
13806 return CLI_SHOWUSAGE;
13807
13808 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13809 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13810 return CLI_SUCCESS;
13811 }
13812
13813 if (!linksets[linkset-1].ss7) {
13814 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13815 return CLI_SUCCESS;
13816 }
13817
13818 cic = atoi(a->argv[4]);
13819
13820 if (cic < 1) {
13821 ast_cli(a->fd, "Invalid CIC specified!\n");
13822 return CLI_SUCCESS;
13823 }
13824
13825 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13826 if (linksets[linkset-1].pvts[i]->cic == cic) {
13827 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13828 if (!blocked) {
13829 ast_mutex_lock(&linksets[linkset-1].lock);
13830 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13831 ast_mutex_unlock(&linksets[linkset-1].lock);
13832 }
13833 }
13834 }
13835
13836 if (blocked < 0) {
13837 ast_cli(a->fd, "Invalid CIC specified!\n");
13838 return CLI_SUCCESS;
13839 }
13840
13841 if (!blocked)
13842 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13843 else
13844 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13845
13846
13847 pthread_kill(linksets[linkset-1].master, SIGURG);
13848
13849 return CLI_SUCCESS;
13850 }
13851
13852 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13853 {
13854 int linkset;
13855 int i;
13856 switch (cmd) {
13857 case CLI_INIT:
13858 e->command = "ss7 block linkset";
13859 e->usage =
13860 "Usage: ss7 block linkset <linkset number>\n"
13861 " Sends a remote blocking request for all CICs on the given linkset\n";
13862 return NULL;
13863 case CLI_GENERATE:
13864 return NULL;
13865 }
13866 if (a->argc == 4)
13867 linkset = atoi(a->argv[3]);
13868 else
13869 return CLI_SHOWUSAGE;
13870
13871 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13872 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13873 return CLI_SUCCESS;
13874 }
13875
13876 if (!linksets[linkset-1].ss7) {
13877 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13878 return CLI_SUCCESS;
13879 }
13880
13881 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13882 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13883 ast_mutex_lock(&linksets[linkset-1].lock);
13884 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13885 ast_mutex_unlock(&linksets[linkset-1].lock);
13886 }
13887
13888
13889 pthread_kill(linksets[linkset-1].master, SIGURG);
13890
13891 return CLI_SUCCESS;
13892 }
13893
13894 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13895 {
13896 int linkset, cic;
13897 int i, blocked = -1;
13898 switch (cmd) {
13899 case CLI_INIT:
13900 e->command = "ss7 unblock cic";
13901 e->usage =
13902 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13903 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13904 return NULL;
13905 case CLI_GENERATE:
13906 return NULL;
13907 }
13908
13909 if (a->argc == 5)
13910 linkset = atoi(a->argv[3]);
13911 else
13912 return CLI_SHOWUSAGE;
13913
13914 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13915 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13916 return CLI_SUCCESS;
13917 }
13918
13919 if (!linksets[linkset-1].ss7) {
13920 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13921 return CLI_SUCCESS;
13922 }
13923
13924 cic = atoi(a->argv[4]);
13925
13926 if (cic < 1) {
13927 ast_cli(a->fd, "Invalid CIC specified!\n");
13928 return CLI_SUCCESS;
13929 }
13930
13931 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13932 if (linksets[linkset-1].pvts[i]->cic == cic) {
13933 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13934 if (blocked) {
13935 ast_mutex_lock(&linksets[linkset-1].lock);
13936 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13937 ast_mutex_unlock(&linksets[linkset-1].lock);
13938 }
13939 }
13940 }
13941
13942 if (blocked > 0)
13943 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13944
13945
13946 pthread_kill(linksets[linkset-1].master, SIGURG);
13947
13948 return CLI_SUCCESS;
13949 }
13950
13951 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13952 {
13953 int linkset;
13954 int i;
13955 switch (cmd) {
13956 case CLI_INIT:
13957 e->command = "ss7 unblock linkset";
13958 e->usage =
13959 "Usage: ss7 unblock linkset <linkset number>\n"
13960 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13961 return NULL;
13962 case CLI_GENERATE:
13963 return NULL;
13964 }
13965
13966 if (a->argc == 4)
13967 linkset = atoi(a->argv[3]);
13968 else
13969 return CLI_SHOWUSAGE;
13970
13971 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13972 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13973 return CLI_SUCCESS;
13974 }
13975
13976 if (!linksets[linkset-1].ss7) {
13977 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13978 return CLI_SUCCESS;
13979 }
13980
13981 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13982 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13983 ast_mutex_lock(&linksets[linkset-1].lock);
13984 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13985 ast_mutex_unlock(&linksets[linkset-1].lock);
13986 }
13987
13988
13989 pthread_kill(linksets[linkset-1].master, SIGURG);
13990
13991 return CLI_SUCCESS;
13992 }
13993
13994 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13995 {
13996 int linkset;
13997 struct dahdi_ss7 *ss7;
13998 switch (cmd) {
13999 case CLI_INIT:
14000 e->command = "ss7 show linkset";
14001 e->usage =
14002 "Usage: ss7 show linkset <span>\n"
14003 " Shows the status of an SS7 linkset.\n";
14004 return NULL;
14005 case CLI_GENERATE:
14006 return NULL;
14007 }
14008
14009 if (a->argc < 4)
14010 return CLI_SHOWUSAGE;
14011 linkset = atoi(a->argv[3]);
14012 if ((linkset < 1) || (linkset > NUM_SPANS)) {
14013 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
14014 return CLI_SUCCESS;
14015 }
14016 if (!linksets[linkset-1].ss7) {
14017 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
14018 return CLI_SUCCESS;
14019 }
14020 if (linksets[linkset-1].ss7)
14021 ss7 = &linksets[linkset-1];
14022
14023 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
14024
14025 return CLI_SUCCESS;
14026 }
14027
14028 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14029 {
14030 switch (cmd) {
14031 case CLI_INIT:
14032 e->command = "ss7 show version";
14033 e->usage =
14034 "Usage: ss7 show version\n"
14035 " Show the libss7 version\n";
14036 return NULL;
14037 case CLI_GENERATE:
14038 return NULL;
14039 }
14040
14041 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
14042
14043 return CLI_SUCCESS;
14044 }
14045
14046 static struct ast_cli_entry dahdi_ss7_cli[] = {
14047 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
14048 AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"),
14049 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
14050 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
14051 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
14052 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
14053 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
14054 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
14055 };
14056 #endif
14057
14058 static int __unload_module(void)
14059 {
14060 struct dahdi_pvt *p;
14061 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14062 int i, j;
14063 #endif
14064
14065 #ifdef HAVE_PRI
14066 for (i = 0; i < NUM_SPANS; i++) {
14067 if (pris[i].master != AST_PTHREADT_NULL)
14068 pthread_cancel(pris[i].master);
14069 }
14070 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14071 ast_unregister_application(dahdi_send_keypad_facility_app);
14072 #endif
14073 #if defined(HAVE_SS7)
14074 for (i = 0; i < NUM_SPANS; i++) {
14075 if (linksets[i].master != AST_PTHREADT_NULL)
14076 pthread_cancel(linksets[i].master);
14077 }
14078 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14079 #endif
14080
14081 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14082 ast_manager_unregister( "DAHDIDialOffhook" );
14083 ast_manager_unregister( "DAHDIHangup" );
14084 ast_manager_unregister( "DAHDITransfer" );
14085 ast_manager_unregister( "DAHDIDNDoff" );
14086 ast_manager_unregister( "DAHDIDNDon" );
14087 ast_manager_unregister("DAHDIShowChannels");
14088 ast_manager_unregister("DAHDIRestart");
14089 ast_channel_unregister(&dahdi_tech);
14090 ast_mutex_lock(&iflock);
14091
14092 p = iflist;
14093 while (p) {
14094 if (p->owner)
14095 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14096 p = p->next;
14097 }
14098 ast_mutex_unlock(&iflock);
14099 ast_mutex_lock(&monlock);
14100 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14101 pthread_cancel(monitor_thread);
14102 pthread_kill(monitor_thread, SIGURG);
14103 pthread_join(monitor_thread, NULL);
14104 }
14105 monitor_thread = AST_PTHREADT_STOP;
14106 ast_mutex_unlock(&monlock);
14107
14108 destroy_all_channels();
14109
14110 #if defined(HAVE_PRI)
14111 for (i = 0; i < NUM_SPANS; i++) {
14112 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14113 pthread_join(pris[i].master, NULL);
14114 for (j = 0; j < NUM_DCHANS; j++) {
14115 dahdi_close_pri_fd(&(pris[i]), j);
14116 }
14117 }
14118 #endif
14119
14120 #if defined(HAVE_SS7)
14121 for (i = 0; i < NUM_SPANS; i++) {
14122 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14123 pthread_join(linksets[i].master, NULL);
14124 for (j = 0; j < NUM_DCHANS; j++) {
14125 dahdi_close_ss7_fd(&(linksets[i]), j);
14126 }
14127 }
14128 #endif
14129
14130 ast_cond_destroy(&mwi_thread_complete);
14131 ast_cond_destroy(&ss_thread_complete);
14132 return 0;
14133 }
14134
14135 static int unload_module(void)
14136 {
14137 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14138 int y;
14139 #endif
14140 #ifdef HAVE_PRI
14141 for (y = 0; y < NUM_SPANS; y++)
14142 ast_mutex_destroy(&pris[y].lock);
14143 #endif
14144 #ifdef HAVE_SS7
14145 for (y = 0; y < NUM_SPANS; y++)
14146 ast_mutex_destroy(&linksets[y].lock);
14147 #endif
14148 return __unload_module();
14149 }
14150
14151 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
14152 {
14153 char *c, *chan;
14154 int x, start, finish;
14155 struct dahdi_pvt *tmp;
14156 #ifdef HAVE_PRI
14157 struct dahdi_pri *pri;
14158 int trunkgroup, y;
14159 #endif
14160
14161 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14162 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14163 return -1;
14164 }
14165
14166 c = ast_strdupa(value);
14167
14168 #ifdef HAVE_PRI
14169 pri = NULL;
14170 if (iscrv) {
14171 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14172 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14173 return -1;
14174 }
14175 if (trunkgroup < 1) {
14176 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14177 return -1;
14178 }
14179 c += y;
14180 for (y = 0; y < NUM_SPANS; y++) {
14181 if (pris[y].trunkgroup == trunkgroup) {
14182 pri = pris + y;
14183 break;
14184 }
14185 }
14186 if (!pri) {
14187 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14188 return -1;
14189 }
14190 }
14191 #endif
14192
14193 while ((chan = strsep(&c, ","))) {
14194 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14195
14196 } else if (sscanf(chan, "%30d", &start)) {
14197
14198 finish = start;
14199 } else if (!strcasecmp(chan, "pseudo")) {
14200 finish = start = CHAN_PSEUDO;
14201 if (found_pseudo)
14202 *found_pseudo = 1;
14203 } else {
14204 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14205 return -1;
14206 }
14207 if (finish < start) {
14208 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14209 x = finish;
14210 finish = start;
14211 start = x;
14212 }
14213
14214 for (x = start; x <= finish; x++) {
14215 #ifdef HAVE_PRI
14216 tmp = mkintf(x, conf, pri, reload);
14217 #else
14218 tmp = mkintf(x, conf, NULL, reload);
14219 #endif
14220
14221 if (tmp) {
14222 #ifdef HAVE_PRI
14223 if (pri)
14224 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14225 else
14226 #endif
14227 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14228 } else {
14229 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14230 (reload == 1) ? "reconfigure" : "register", value);
14231 return -1;
14232 }
14233 }
14234 }
14235
14236 return 0;
14237 }
14238
14239
14240
14241 #define MAX_CHANLIST_LEN 80
14242
14243 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
14244 {
14245 char *parse = ast_strdupa(data);
14246 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14247 unsigned int param_count;
14248 unsigned int x;
14249
14250 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14251 return;
14252
14253 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14254
14255
14256
14257 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14258
14259 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14260 confp->chan.echocancel.head.tap_length = x;
14261 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14262 confp->chan.echocancel.head.tap_length = 128;
14263
14264
14265
14266 for (x = 1; x < param_count; x++) {
14267 struct {
14268 char *name;
14269 char *value;
14270 } param;
14271
14272 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
14273 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14274 continue;
14275 }
14276
14277 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14278 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14279 continue;
14280 }
14281
14282 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14283
14284 if (param.value) {
14285 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14286 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14287 continue;
14288 }
14289 }
14290 confp->chan.echocancel.head.param_count++;
14291 }
14292 }
14293
14294
14295 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
14296
14297 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
14298
14299 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
14300 {
14301 struct dahdi_pvt *tmp;
14302 int y;
14303 int found_pseudo = 0;
14304 char dahdichan[MAX_CHANLIST_LEN] = {};
14305
14306 for (; v; v = v->next) {
14307 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14308 continue;
14309
14310
14311 if (!strcasecmp(v->name, "parkinglot")) {
14312 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
14313 }
14314
14315
14316 if (!strcasecmp(v->name, "channel")
14317 #ifdef HAVE_PRI
14318 || !strcasecmp(v->name, "crv")
14319 #endif
14320 ) {
14321 int iscrv;
14322 if (options & PROC_DAHDI_OPT_NOCHAN) {
14323 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
14324 continue;
14325 }
14326 iscrv = !strcasecmp(v->name, "crv");
14327 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14328 return -1;
14329 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
14330 } else if (!strcasecmp(v->name, "buffers")) {
14331 int res;
14332 char policy[21] = "";
14333
14334 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
14335 if (res != 2) {
14336 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14337 confp->chan.buf_no = numbufs;
14338 continue;
14339 }
14340 if (confp->chan.buf_no < 0)
14341 confp->chan.buf_no = numbufs;
14342 if (!strcasecmp(policy, "full")) {
14343 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14344 } else if (!strcasecmp(policy, "immediate")) {
14345 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14346 } else {
14347 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14348 }
14349 } else if (!strcasecmp(v->name, "dahdichan")) {
14350 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14351 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14352 usedistinctiveringdetection = ast_true(v->value);
14353 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14354 distinctiveringaftercid = ast_true(v->value);
14355 } else if (!strcasecmp(v->name, "dring1context")) {
14356 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14357 } else if (!strcasecmp(v->name, "dring2context")) {
14358 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14359 } else if (!strcasecmp(v->name, "dring3context")) {
14360 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14361 } else if (!strcasecmp(v->name, "dring1range")) {
14362 confp->chan.drings.ringnum[0].range = atoi(v->value);
14363 } else if (!strcasecmp(v->name, "dring2range")) {
14364 confp->chan.drings.ringnum[1].range = atoi(v->value);
14365 } else if (!strcasecmp(v->name, "dring3range")) {
14366 confp->chan.drings.ringnum[2].range = atoi(v->value);
14367 } else if (!strcasecmp(v->name, "dring1")) {
14368 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]);
14369 } else if (!strcasecmp(v->name, "dring2")) {
14370 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]);
14371 } else if (!strcasecmp(v->name, "dring3")) {
14372 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]);
14373 } else if (!strcasecmp(v->name, "usecallerid")) {
14374 confp->chan.use_callerid = ast_true(v->value);
14375 } else if (!strcasecmp(v->name, "cidsignalling")) {
14376 if (!strcasecmp(v->value, "bell"))
14377 confp->chan.cid_signalling = CID_SIG_BELL;
14378 else if (!strcasecmp(v->value, "v23"))
14379 confp->chan.cid_signalling = CID_SIG_V23;
14380 else if (!strcasecmp(v->value, "dtmf"))
14381 confp->chan.cid_signalling = CID_SIG_DTMF;
14382 else if (!strcasecmp(v->value, "smdi"))
14383 confp->chan.cid_signalling = CID_SIG_SMDI;
14384 else if (!strcasecmp(v->value, "v23_jp"))
14385 confp->chan.cid_signalling = CID_SIG_V23_JP;
14386 else if (ast_true(v->value))
14387 confp->chan.cid_signalling = CID_SIG_BELL;
14388 } else if (!strcasecmp(v->name, "cidstart")) {
14389 if (!strcasecmp(v->value, "ring"))
14390 confp->chan.cid_start = CID_START_RING;
14391 else if (!strcasecmp(v->value, "polarity_in"))
14392 confp->chan.cid_start = CID_START_POLARITY_IN;
14393 else if (!strcasecmp(v->value, "polarity"))
14394 confp->chan.cid_start = CID_START_POLARITY;
14395 else if (ast_true(v->value))
14396 confp->chan.cid_start = CID_START_RING;
14397 } else if (!strcasecmp(v->name, "threewaycalling")) {
14398 confp->chan.threewaycalling = ast_true(v->value);
14399 } else if (!strcasecmp(v->name, "cancallforward")) {
14400 confp->chan.cancallforward = ast_true(v->value);
14401 } else if (!strcasecmp(v->name, "relaxdtmf")) {
14402 if (ast_true(v->value))
14403 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14404 else
14405 confp->chan.dtmfrelax = 0;
14406 } else if (!strcasecmp(v->name, "mailbox")) {
14407 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14408 } else if (!strcasecmp(v->name, "hasvoicemail")) {
14409 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14410 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14411 }
14412 } else if (!strcasecmp(v->name, "adsi")) {
14413 confp->chan.adsi = ast_true(v->value);
14414 } else if (!strcasecmp(v->name, "usesmdi")) {
14415 confp->chan.use_smdi = ast_true(v->value);
14416 } else if (!strcasecmp(v->name, "smdiport")) {
14417 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14418 } else if (!strcasecmp(v->name, "transfer")) {
14419 confp->chan.transfer = ast_true(v->value);
14420 } else if (!strcasecmp(v->name, "canpark")) {
14421 confp->chan.canpark = ast_true(v->value);
14422 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14423 confp->chan.echocanbridged = ast_true(v->value);
14424 } else if (!strcasecmp(v->name, "busydetect")) {
14425 confp->chan.busydetect = ast_true(v->value);
14426 } else if (!strcasecmp(v->name, "busycount")) {
14427 confp->chan.busycount = atoi(v->value);
14428 } else if (!strcasecmp(v->name, "busypattern")) {
14429 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
14430 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14431 }
14432 } else if (!strcasecmp(v->name, "callprogress")) {
14433 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14434 if (ast_true(v->value))
14435 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14436 } else if (!strcasecmp(v->name, "faxdetect")) {
14437 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14438 if (!strcasecmp(v->value, "incoming")) {
14439 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14440 } else if (!strcasecmp(v->value, "outgoing")) {
14441 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14442 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14443 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14444 } else if (!strcasecmp(v->name, "echocancel")) {
14445 process_echocancel(confp, v->value, v->lineno);
14446 } else if (!strcasecmp(v->name, "echotraining")) {
14447 if (sscanf(v->value, "%30d", &y) == 1) {
14448 if ((y < 10) || (y > 4000)) {
14449 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
14450 } else {
14451 confp->chan.echotraining = y;
14452 }
14453 } else if (ast_true(v->value)) {
14454 confp->chan.echotraining = 400;
14455 } else
14456 confp->chan.echotraining = 0;
14457 } else if (!strcasecmp(v->name, "hidecallerid")) {
14458 confp->chan.hidecallerid = ast_true(v->value);
14459 } else if (!strcasecmp(v->name, "hidecalleridname")) {
14460 confp->chan.hidecalleridname = ast_true(v->value);
14461 } else if (!strcasecmp(v->name, "pulsedial")) {
14462 confp->chan.pulse = ast_true(v->value);
14463 } else if (!strcasecmp(v->name, "callreturn")) {
14464 confp->chan.callreturn = ast_true(v->value);
14465 } else if (!strcasecmp(v->name, "callwaiting")) {
14466 confp->chan.callwaiting = ast_true(v->value);
14467 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14468 confp->chan.callwaitingcallerid = ast_true(v->value);
14469 } else if (!strcasecmp(v->name, "context")) {
14470 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14471 } else if (!strcasecmp(v->name, "language")) {
14472 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14473 } else if (!strcasecmp(v->name, "progzone")) {
14474 ast_copy_string(progzone, v->value, sizeof(progzone));
14475 } else if (!strcasecmp(v->name, "mohinterpret")
14476 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14477 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14478 } else if (!strcasecmp(v->name, "mohsuggest")) {
14479 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14480 } else if (!strcasecmp(v->name, "parkinglot")) {
14481 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
14482 } else if (!strcasecmp(v->name, "stripmsd")) {
14483 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14484 confp->chan.stripmsd = atoi(v->value);
14485 } else if (!strcasecmp(v->name, "jitterbuffers")) {
14486 numbufs = atoi(v->value);
14487 } else if (!strcasecmp(v->name, "group")) {
14488 confp->chan.group = ast_get_group(v->value);
14489 } else if (!strcasecmp(v->name, "callgroup")) {
14490 if (!strcasecmp(v->value, "none"))
14491 confp->chan.callgroup = 0;
14492 else
14493 confp->chan.callgroup = ast_get_group(v->value);
14494 } else if (!strcasecmp(v->name, "pickupgroup")) {
14495 if (!strcasecmp(v->value, "none"))
14496 confp->chan.pickupgroup = 0;
14497 else
14498 confp->chan.pickupgroup = ast_get_group(v->value);
14499 } else if (!strcasecmp(v->name, "setvar")) {
14500 char *varname = ast_strdupa(v->value), *varval = NULL;
14501 struct ast_variable *tmpvar;
14502 if (varname && (varval = strchr(varname, '='))) {
14503 *varval++ = '\0';
14504 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14505 tmpvar->next = confp->chan.vars;
14506 confp->chan.vars = tmpvar;
14507 }
14508 }
14509 } else if (!strcasecmp(v->name, "immediate")) {
14510 confp->chan.immediate = ast_true(v->value);
14511 } else if (!strcasecmp(v->name, "transfertobusy")) {
14512 confp->chan.transfertobusy = ast_true(v->value);
14513 } else if (!strcasecmp(v->name, "mwimonitor")) {
14514 confp->chan.mwimonitor_neon = 0;
14515 confp->chan.mwimonitor_fsk = 0;
14516 confp->chan.mwimonitor_rpas = 0;
14517 if (strcasestr(v->value, "fsk")) {
14518 confp->chan.mwimonitor_fsk = 1;
14519 }
14520 if (strcasestr(v->value, "rpas")) {
14521 confp->chan.mwimonitor_rpas = 1;
14522 }
14523 if (strcasestr(v->value, "neon")) {
14524 confp->chan.mwimonitor_neon = 1;
14525 }
14526
14527 if (ast_true(v->value)) {
14528 confp->chan.mwimonitor_fsk = 1;
14529 }
14530 } else if (!strcasecmp(v->name, "cid_rxgain")) {
14531 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
14532 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14533 }
14534 } else if (!strcasecmp(v->name, "rxgain")) {
14535 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
14536 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14537 }
14538 } else if (!strcasecmp(v->name, "txgain")) {
14539 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
14540 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14541 }
14542 } else if (!strcasecmp(v->name, "tonezone")) {
14543 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
14544 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14545 }
14546 } else if (!strcasecmp(v->name, "callerid")) {
14547 if (!strcasecmp(v->value, "asreceived")) {
14548 confp->chan.cid_num[0] = '\0';
14549 confp->chan.cid_name[0] = '\0';
14550 } else {
14551 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14552 }
14553 } else if (!strcasecmp(v->name, "fullname")) {
14554 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14555 } else if (!strcasecmp(v->name, "cid_number")) {
14556 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14557 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14558 confp->chan.dahditrcallerid = ast_true(v->value);
14559 } else if (!strcasecmp(v->name, "restrictcid")) {
14560 confp->chan.restrictcid = ast_true(v->value);
14561 } else if (!strcasecmp(v->name, "usecallingpres")) {
14562 confp->chan.use_callingpres = ast_true(v->value);
14563 } else if (!strcasecmp(v->name, "accountcode")) {
14564 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14565 } else if (!strcasecmp(v->name, "amaflags")) {
14566 y = ast_cdr_amaflags2int(v->value);
14567 if (y < 0)
14568 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14569 else
14570 confp->chan.amaflags = y;
14571 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14572 confp->chan.polarityonanswerdelay = atoi(v->value);
14573 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14574 confp->chan.answeronpolarityswitch = ast_true(v->value);
14575 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14576 confp->chan.hanguponpolarityswitch = ast_true(v->value);
14577 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14578 confp->chan.sendcalleridafter = atoi(v->value);
14579 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14580 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14581 } else if (!strcasecmp(v->name, "mwisendtype")) {
14582 if (!strcasecmp(v->value, "rpas")) {
14583 mwisend_rpas = 1;
14584 } else {
14585 mwisend_rpas = 0;
14586 }
14587 } else if (reload != 1) {
14588 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14589 int orig_radio = confp->chan.radio;
14590 int orig_outsigmod = confp->chan.outsigmod;
14591 int orig_auto = confp->is_sig_auto;
14592
14593 confp->chan.radio = 0;
14594 confp->chan.outsigmod = -1;
14595 confp->is_sig_auto = 0;
14596 if (!strcasecmp(v->value, "em")) {
14597 confp->chan.sig = SIG_EM;
14598 } else if (!strcasecmp(v->value, "em_e1")) {
14599 confp->chan.sig = SIG_EM_E1;
14600 } else if (!strcasecmp(v->value, "em_w")) {
14601 confp->chan.sig = SIG_EMWINK;
14602 } else if (!strcasecmp(v->value, "fxs_ls")) {
14603 confp->chan.sig = SIG_FXSLS;
14604 } else if (!strcasecmp(v->value, "fxs_gs")) {
14605 confp->chan.sig = SIG_FXSGS;
14606 } else if (!strcasecmp(v->value, "fxs_ks")) {
14607 confp->chan.sig = SIG_FXSKS;
14608 } else if (!strcasecmp(v->value, "fxo_ls")) {
14609 confp->chan.sig = SIG_FXOLS;
14610 } else if (!strcasecmp(v->value, "fxo_gs")) {
14611 confp->chan.sig = SIG_FXOGS;
14612 } else if (!strcasecmp(v->value, "fxo_ks")) {
14613 confp->chan.sig = SIG_FXOKS;
14614 } else if (!strcasecmp(v->value, "fxs_rx")) {
14615 confp->chan.sig = SIG_FXSKS;
14616 confp->chan.radio = 1;
14617 } else if (!strcasecmp(v->value, "fxo_rx")) {
14618 confp->chan.sig = SIG_FXOLS;
14619 confp->chan.radio = 1;
14620 } else if (!strcasecmp(v->value, "fxs_tx")) {
14621 confp->chan.sig = SIG_FXSLS;
14622 confp->chan.radio = 1;
14623 } else if (!strcasecmp(v->value, "fxo_tx")) {
14624 confp->chan.sig = SIG_FXOGS;
14625 confp->chan.radio = 1;
14626 } else if (!strcasecmp(v->value, "em_rx")) {
14627 confp->chan.sig = SIG_EM;
14628 confp->chan.radio = 1;
14629 } else if (!strcasecmp(v->value, "em_tx")) {
14630 confp->chan.sig = SIG_EM;
14631 confp->chan.radio = 1;
14632 } else if (!strcasecmp(v->value, "em_rxtx")) {
14633 confp->chan.sig = SIG_EM;
14634 confp->chan.radio = 2;
14635 } else if (!strcasecmp(v->value, "em_txrx")) {
14636 confp->chan.sig = SIG_EM;
14637 confp->chan.radio = 2;
14638 } else if (!strcasecmp(v->value, "sf")) {
14639 confp->chan.sig = SIG_SF;
14640 } else if (!strcasecmp(v->value, "sf_w")) {
14641 confp->chan.sig = SIG_SFWINK;
14642 } else if (!strcasecmp(v->value, "sf_featd")) {
14643 confp->chan.sig = SIG_FEATD;
14644 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14645 confp->chan.sig = SIG_FEATDMF;
14646 } else if (!strcasecmp(v->value, "sf_featb")) {
14647 confp->chan.sig = SIG_SF_FEATB;
14648 } else if (!strcasecmp(v->value, "sf")) {
14649 confp->chan.sig = SIG_SF;
14650 } else if (!strcasecmp(v->value, "sf_rx")) {
14651 confp->chan.sig = SIG_SF;
14652 confp->chan.radio = 1;
14653 } else if (!strcasecmp(v->value, "sf_tx")) {
14654 confp->chan.sig = SIG_SF;
14655 confp->chan.radio = 1;
14656 } else if (!strcasecmp(v->value, "sf_rxtx")) {
14657 confp->chan.sig = SIG_SF;
14658 confp->chan.radio = 2;
14659 } else if (!strcasecmp(v->value, "sf_txrx")) {
14660 confp->chan.sig = SIG_SF;
14661 confp->chan.radio = 2;
14662 } else if (!strcasecmp(v->value, "featd")) {
14663 confp->chan.sig = SIG_FEATD;
14664 } else if (!strcasecmp(v->value, "featdmf")) {
14665 confp->chan.sig = SIG_FEATDMF;
14666 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14667 confp->chan.sig = SIG_FEATDMF_TA;
14668 } else if (!strcasecmp(v->value, "e911")) {
14669 confp->chan.sig = SIG_E911;
14670 } else if (!strcasecmp(v->value, "fgccama")) {
14671 confp->chan.sig = SIG_FGC_CAMA;
14672 } else if (!strcasecmp(v->value, "fgccamamf")) {
14673 confp->chan.sig = SIG_FGC_CAMAMF;
14674 } else if (!strcasecmp(v->value, "featb")) {
14675 confp->chan.sig = SIG_FEATB;
14676 #ifdef HAVE_PRI
14677 } else if (!strcasecmp(v->value, "pri_net")) {
14678 confp->chan.sig = SIG_PRI;
14679 confp->pri.nodetype = PRI_NETWORK;
14680 } else if (!strcasecmp(v->value, "pri_cpe")) {
14681 confp->chan.sig = SIG_PRI;
14682 confp->pri.nodetype = PRI_CPE;
14683 } else if (!strcasecmp(v->value, "bri_cpe")) {
14684 confp->chan.sig = SIG_BRI;
14685 confp->pri.nodetype = PRI_CPE;
14686 } else if (!strcasecmp(v->value, "bri_net")) {
14687 confp->chan.sig = SIG_BRI;
14688 confp->pri.nodetype = PRI_NETWORK;
14689 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14690 confp->chan.sig = SIG_BRI_PTMP;
14691 confp->pri.nodetype = PRI_CPE;
14692 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14693 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
14694 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14695 confp->chan.sig = SIG_GR303FXOKS;
14696 confp->pri.nodetype = PRI_NETWORK;
14697 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14698 confp->chan.sig = SIG_GR303FXSKS;
14699 confp->pri.nodetype = PRI_CPE;
14700 #endif
14701 #ifdef HAVE_SS7
14702 } else if (!strcasecmp(v->value, "ss7")) {
14703 confp->chan.sig = SIG_SS7;
14704 #endif
14705 } else if (!strcasecmp(v->value, "auto")) {
14706 confp->is_sig_auto = 1;
14707 } else {
14708 confp->chan.outsigmod = orig_outsigmod;
14709 confp->chan.radio = orig_radio;
14710 confp->is_sig_auto = orig_auto;
14711 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14712 }
14713 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14714 if (!strcasecmp(v->value, "em")) {
14715 confp->chan.outsigmod = SIG_EM;
14716 } else if (!strcasecmp(v->value, "em_e1")) {
14717 confp->chan.outsigmod = SIG_EM_E1;
14718 } else if (!strcasecmp(v->value, "em_w")) {
14719 confp->chan.outsigmod = SIG_EMWINK;
14720 } else if (!strcasecmp(v->value, "sf")) {
14721 confp->chan.outsigmod = SIG_SF;
14722 } else if (!strcasecmp(v->value, "sf_w")) {
14723 confp->chan.outsigmod = SIG_SFWINK;
14724 } else if (!strcasecmp(v->value, "sf_featd")) {
14725 confp->chan.outsigmod = SIG_FEATD;
14726 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14727 confp->chan.outsigmod = SIG_FEATDMF;
14728 } else if (!strcasecmp(v->value, "sf_featb")) {
14729 confp->chan.outsigmod = SIG_SF_FEATB;
14730 } else if (!strcasecmp(v->value, "sf")) {
14731 confp->chan.outsigmod = SIG_SF;
14732 } else if (!strcasecmp(v->value, "featd")) {
14733 confp->chan.outsigmod = SIG_FEATD;
14734 } else if (!strcasecmp(v->value, "featdmf")) {
14735 confp->chan.outsigmod = SIG_FEATDMF;
14736 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14737 confp->chan.outsigmod = SIG_FEATDMF_TA;
14738 } else if (!strcasecmp(v->value, "e911")) {
14739 confp->chan.outsigmod = SIG_E911;
14740 } else if (!strcasecmp(v->value, "fgccama")) {
14741 confp->chan.outsigmod = SIG_FGC_CAMA;
14742 } else if (!strcasecmp(v->value, "fgccamamf")) {
14743 confp->chan.outsigmod = SIG_FGC_CAMAMF;
14744 } else if (!strcasecmp(v->value, "featb")) {
14745 confp->chan.outsigmod = SIG_FEATB;
14746 } else {
14747 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14748 }
14749 #ifdef HAVE_PRI
14750 } else if (!strcasecmp(v->name, "pridialplan")) {
14751 if (!strcasecmp(v->value, "national")) {
14752 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14753 } else if (!strcasecmp(v->value, "unknown")) {
14754 confp->pri.dialplan = PRI_UNKNOWN + 1;
14755 } else if (!strcasecmp(v->value, "private")) {
14756 confp->pri.dialplan = PRI_PRIVATE + 1;
14757 } else if (!strcasecmp(v->value, "international")) {
14758 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14759 } else if (!strcasecmp(v->value, "local")) {
14760 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14761 } else if (!strcasecmp(v->value, "dynamic")) {
14762 confp->pri.dialplan = -1;
14763 } else if (!strcasecmp(v->value, "redundant")) {
14764 confp->pri.dialplan = -2;
14765 } else {
14766 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14767 }
14768 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14769 if (!strcasecmp(v->value, "national")) {
14770 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14771 } else if (!strcasecmp(v->value, "unknown")) {
14772 confp->pri.localdialplan = PRI_UNKNOWN + 1;
14773 } else if (!strcasecmp(v->value, "private")) {
14774 confp->pri.localdialplan = PRI_PRIVATE + 1;
14775 } else if (!strcasecmp(v->value, "international")) {
14776 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14777 } else if (!strcasecmp(v->value, "local")) {
14778 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14779 } else if (!strcasecmp(v->value, "dynamic")) {
14780 confp->pri.localdialplan = -1;
14781 } else if (!strcasecmp(v->value, "redundant")) {
14782 confp->pri.localdialplan = -2;
14783 } else {
14784 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14785 }
14786 } else if (!strcasecmp(v->name, "switchtype")) {
14787 if (!strcasecmp(v->value, "national"))
14788 confp->pri.switchtype = PRI_SWITCH_NI2;
14789 else if (!strcasecmp(v->value, "ni1"))
14790 confp->pri.switchtype = PRI_SWITCH_NI1;
14791 else if (!strcasecmp(v->value, "dms100"))
14792 confp->pri.switchtype = PRI_SWITCH_DMS100;
14793 else if (!strcasecmp(v->value, "4ess"))
14794 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14795 else if (!strcasecmp(v->value, "5ess"))
14796 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14797 else if (!strcasecmp(v->value, "euroisdn"))
14798 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14799 else if (!strcasecmp(v->value, "qsig"))
14800 confp->pri.switchtype = PRI_SWITCH_QSIG;
14801 else {
14802 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14803 return -1;
14804 }
14805 } else if (!strcasecmp(v->name, "nsf")) {
14806 if (!strcasecmp(v->value, "sdn"))
14807 confp->pri.nsf = PRI_NSF_SDN;
14808 else if (!strcasecmp(v->value, "megacom"))
14809 confp->pri.nsf = PRI_NSF_MEGACOM;
14810 else if (!strcasecmp(v->value, "tollfreemegacom"))
14811 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14812 else if (!strcasecmp(v->value, "accunet"))
14813 confp->pri.nsf = PRI_NSF_ACCUNET;
14814 else if (!strcasecmp(v->value, "none"))
14815 confp->pri.nsf = PRI_NSF_NONE;
14816 else {
14817 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14818 confp->pri.nsf = PRI_NSF_NONE;
14819 }
14820 } else if (!strcasecmp(v->name, "priindication")) {
14821 if (!strcasecmp(v->value, "outofband"))
14822 confp->chan.priindication_oob = 1;
14823 else if (!strcasecmp(v->value, "inband"))
14824 confp->chan.priindication_oob = 0;
14825 else
14826 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14827 v->value, v->lineno);
14828 } else if (!strcasecmp(v->name, "priexclusive")) {
14829 confp->chan.priexclusive = ast_true(v->value);
14830 } else if (!strcasecmp(v->name, "internationalprefix")) {
14831 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14832 } else if (!strcasecmp(v->name, "nationalprefix")) {
14833 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14834 } else if (!strcasecmp(v->name, "localprefix")) {
14835 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14836 } else if (!strcasecmp(v->name, "privateprefix")) {
14837 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14838 } else if (!strcasecmp(v->name, "unknownprefix")) {
14839 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14840 } else if (!strcasecmp(v->name, "resetinterval")) {
14841 if (!strcasecmp(v->value, "never"))
14842 confp->pri.resetinterval = -1;
14843 else if (atoi(v->value) >= 60)
14844 confp->pri.resetinterval = atoi(v->value);
14845 else
14846 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14847 v->value, v->lineno);
14848 } else if (!strcasecmp(v->name, "minunused")) {
14849 confp->pri.minunused = atoi(v->value);
14850 } else if (!strcasecmp(v->name, "minidle")) {
14851 confp->pri.minidle = atoi(v->value);
14852 } else if (!strcasecmp(v->name, "idleext")) {
14853 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14854 } else if (!strcasecmp(v->name, "idledial")) {
14855 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14856 } else if (!strcasecmp(v->name, "overlapdial")) {
14857 if (ast_true(v->value)) {
14858 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14859 } else if (!strcasecmp(v->value, "incoming")) {
14860 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14861 } else if (!strcasecmp(v->value, "outgoing")) {
14862 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14863 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14864 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14865 } else {
14866 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14867 }
14868 #ifdef HAVE_PRI_INBANDDISCONNECT
14869 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14870 confp->pri.inbanddisconnect = ast_true(v->value);
14871 #endif
14872 } else if (!strcasecmp(v->name, "pritimer")) {
14873 #ifdef PRI_GETSET_TIMERS
14874 char tmp[20];
14875 char *timerc;
14876 char *c;
14877 int timer;
14878 int timeridx;
14879
14880 ast_copy_string(tmp, v->value, sizeof(tmp));
14881 c = tmp;
14882 timerc = strsep(&c, ",");
14883 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
14884 timeridx = pri_timer2idx(timerc);
14885 timer = atoi(c);
14886 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
14887 ast_log(LOG_WARNING,
14888 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
14889 v->lineno);
14890 } else if (!timer) {
14891 ast_log(LOG_WARNING,
14892 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
14893 c, timerc, v->lineno);
14894 } else {
14895 pritimers[timeridx] = timer;
14896 }
14897 } else {
14898 ast_log(LOG_WARNING,
14899 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
14900 v->value, v->lineno);
14901 }
14902
14903 } else if (!strcasecmp(v->name, "facilityenable")) {
14904 confp->pri.facilityenable = ast_true(v->value);
14905 #endif
14906 #endif
14907 #ifdef HAVE_SS7
14908 } else if (!strcasecmp(v->name, "ss7type")) {
14909 if (!strcasecmp(v->value, "itu")) {
14910 cur_ss7type = SS7_ITU;
14911 } else if (!strcasecmp(v->value, "ansi")) {
14912 cur_ss7type = SS7_ANSI;
14913 } else
14914 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14915 } else if (!strcasecmp(v->name, "linkset")) {
14916 cur_linkset = atoi(v->value);
14917 } else if (!strcasecmp(v->name, "pointcode")) {
14918 cur_pointcode = parse_pointcode(v->value);
14919 } else if (!strcasecmp(v->name, "adjpointcode")) {
14920 cur_adjpointcode = parse_pointcode(v->value);
14921 } else if (!strcasecmp(v->name, "defaultdpc")) {
14922 cur_defaultdpc = parse_pointcode(v->value);
14923 } else if (!strcasecmp(v->name, "cicbeginswith")) {
14924 cur_cicbeginswith = atoi(v->value);
14925 } else if (!strcasecmp(v->name, "networkindicator")) {
14926 if (!strcasecmp(v->value, "national"))
14927 cur_networkindicator = SS7_NI_NAT;
14928 else if (!strcasecmp(v->value, "national_spare"))
14929 cur_networkindicator = SS7_NI_NAT_SPARE;
14930 else if (!strcasecmp(v->value, "international"))
14931 cur_networkindicator = SS7_NI_INT;
14932 else if (!strcasecmp(v->value, "international_spare"))
14933 cur_networkindicator = SS7_NI_INT_SPARE;
14934 else
14935 cur_networkindicator = -1;
14936 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14937 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14938 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14939 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14940 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14941 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14942 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14943 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14944 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14945 if (!strcasecmp(v->value, "national")) {
14946 confp->ss7.called_nai = SS7_NAI_NATIONAL;
14947 } else if (!strcasecmp(v->value, "international")) {
14948 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14949 } else if (!strcasecmp(v->value, "subscriber")) {
14950 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14951 } else if (!strcasecmp(v->value, "dynamic")) {
14952 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14953 } else {
14954 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14955 }
14956 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14957 if (!strcasecmp(v->value, "national")) {
14958 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14959 } else if (!strcasecmp(v->value, "international")) {
14960 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14961 } else if (!strcasecmp(v->value, "subscriber")) {
14962 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14963 } else if (!strcasecmp(v->value, "dynamic")) {
14964 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14965 } else {
14966 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14967 }
14968 } else if (!strcasecmp(v->name, "sigchan")) {
14969 int sigchan, res;
14970 sigchan = atoi(v->value);
14971 res = linkset_addsigchan(sigchan);
14972 if (res < 0)
14973 return -1;
14974
14975 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14976 struct dahdi_ss7 *link;
14977 link = ss7_resolve_linkset(cur_linkset);
14978 if (!link) {
14979 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
14980 return -1;
14981 }
14982 if (ast_true(v->value))
14983 link->flags |= LINKSET_FLAG_EXPLICITACM;
14984
14985 #endif
14986 } else if (!strcasecmp(v->name, "cadence")) {
14987
14988 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14989 int i;
14990 struct dahdi_ring_cadence new_cadence;
14991 int cid_location = -1;
14992 int firstcadencepos = 0;
14993 char original_args[80];
14994 int cadence_is_ok = 1;
14995
14996 ast_copy_string(original_args, v->value, sizeof(original_args));
14997
14998 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]);
14999
15000
15001 if (element_count % 2 == 1) {
15002 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
15003 cadence_is_ok = 0;
15004 }
15005
15006
15007 for (i = 0; i < element_count; i++) {
15008 if (c[i] == 0) {
15009 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
15010 cadence_is_ok = 0;
15011 break;
15012 } else if (c[i] < 0) {
15013 if (i % 2 == 1) {
15014
15015 if (cid_location == -1) {
15016 cid_location = i;
15017 c[i] *= -1;
15018 } else {
15019 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
15020 cadence_is_ok = 0;
15021 break;
15022 }
15023 } else {
15024 if (firstcadencepos == 0) {
15025 firstcadencepos = i;
15026
15027 } else {
15028 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
15029 cadence_is_ok = 0;
15030 break;
15031 }
15032 }
15033 }
15034 }
15035
15036
15037 for (i = 0; i < 16; i++) {
15038 new_cadence.ringcadence[i] = c[i];
15039 }
15040
15041 if (cadence_is_ok) {
15042
15043 if (element_count < 2) {
15044 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
15045 } else {
15046 if (cid_location == -1) {
15047
15048 cid_location = 1;
15049 } else {
15050
15051 cid_location = (cid_location + 1) / 2;
15052 }
15053
15054 if (!user_has_defined_cadences++)
15055
15056 num_cadence = 0;
15057 if ((num_cadence+1) >= NUM_CADENCE_MAX)
15058 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
15059 else {
15060 cadences[num_cadence] = new_cadence;
15061 cidrings[num_cadence++] = cid_location;
15062 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
15063 }
15064 }
15065 }
15066 } else if (!strcasecmp(v->name, "ringtimeout")) {
15067 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
15068 } else if (!strcasecmp(v->name, "prewink")) {
15069 confp->timing.prewinktime = atoi(v->value);
15070 } else if (!strcasecmp(v->name, "preflash")) {
15071 confp->timing.preflashtime = atoi(v->value);
15072 } else if (!strcasecmp(v->name, "wink")) {
15073 confp->timing.winktime = atoi(v->value);
15074 } else if (!strcasecmp(v->name, "flash")) {
15075 confp->timing.flashtime = atoi(v->value);
15076 } else if (!strcasecmp(v->name, "start")) {
15077 confp->timing.starttime = atoi(v->value);
15078 } else if (!strcasecmp(v->name, "rxwink")) {
15079 confp->timing.rxwinktime = atoi(v->value);
15080 } else if (!strcasecmp(v->name, "rxflash")) {
15081 confp->timing.rxflashtime = atoi(v->value);
15082 } else if (!strcasecmp(v->name, "debounce")) {
15083 confp->timing.debouncetime = atoi(v->value);
15084 } else if (!strcasecmp(v->name, "toneduration")) {
15085 int toneduration;
15086 int ctlfd;
15087 int res;
15088 struct dahdi_dialparams dps;
15089
15090 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
15091 if (ctlfd == -1) {
15092 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
15093 return -1;
15094 }
15095
15096 toneduration = atoi(v->value);
15097 if (toneduration > -1) {
15098 memset(&dps, 0, sizeof(dps));
15099
15100 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
15101 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
15102 if (res < 0) {
15103 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
15104 return -1;
15105 }
15106 }
15107 close(ctlfd);
15108 } else if (!strcasecmp(v->name, "defaultcic")) {
15109 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
15110 } else if (!strcasecmp(v->name, "defaultozz")) {
15111 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
15112 } else if (!strcasecmp(v->name, "mwilevel")) {
15113 mwilevel = atoi(v->value);
15114 }
15115 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
15116 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
15117 }
15118 if (dahdichan[0]) {
15119
15120
15121 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
15122 return -1;
15123 }
15124 }
15125
15126
15127 if (!found_pseudo && reload != 1) {
15128
15129
15130
15131
15132 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
15133
15134 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
15135
15136 if (tmp) {
15137 ast_verb(3, "Automatically generated pseudo channel\n");
15138 } else {
15139 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
15140 }
15141 }
15142 return 0;
15143 }
15144
15145 static int setup_dahdi(int reload)
15146 {
15147 struct ast_config *cfg, *ucfg;
15148 struct ast_variable *v;
15149 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
15150 struct dahdi_chan_conf conf;
15151 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
15152 const char *cat;
15153 int res;
15154
15155 #ifdef HAVE_PRI
15156 char *c;
15157 int spanno;
15158 int i;
15159 int logicalspan;
15160 int trunkgroup;
15161 int dchannels[NUM_DCHANS];
15162 #endif
15163
15164 cfg = ast_config_load(config, config_flags);
15165
15166
15167 if (!cfg) {
15168 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
15169 return 0;
15170 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
15171 ucfg = ast_config_load("users.conf", config_flags);
15172 if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
15173 return 0;
15174 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15175 cfg = ast_config_load(config, config_flags);
15176 } else {
15177 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15178 ucfg = ast_config_load("users.conf", config_flags);
15179 }
15180
15181
15182 ast_mutex_lock(&iflock);
15183 #ifdef HAVE_PRI
15184 if (reload != 1) {
15185
15186 v = ast_variable_browse(cfg, "trunkgroups");
15187 while (v) {
15188 if (!strcasecmp(v->name, "trunkgroup")) {
15189 trunkgroup = atoi(v->value);
15190 if (trunkgroup > 0) {
15191 if ((c = strchr(v->value, ','))) {
15192 i = 0;
15193 memset(dchannels, 0, sizeof(dchannels));
15194 while (c && (i < NUM_DCHANS)) {
15195 dchannels[i] = atoi(c + 1);
15196 if (dchannels[i] < 0) {
15197 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);
15198 } else
15199 i++;
15200 c = strchr(c + 1, ',');
15201 }
15202 if (i) {
15203 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
15204 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);
15205 } else
15206 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");
15207 } else
15208 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15209 } else
15210 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15211 } else
15212 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
15213 } else if (!strcasecmp(v->name, "spanmap")) {
15214 spanno = atoi(v->value);
15215 if (spanno > 0) {
15216 if ((c = strchr(v->value, ','))) {
15217 trunkgroup = atoi(c + 1);
15218 if (trunkgroup > 0) {
15219 if ((c = strchr(c + 1, ',')))
15220 logicalspan = atoi(c + 1);
15221 else
15222 logicalspan = 0;
15223 if (logicalspan >= 0) {
15224 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15225 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15226 } else
15227 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15228 } else
15229 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);
15230 } else
15231 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15232 } else
15233 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15234 } else
15235 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15236 } else {
15237 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15238 }
15239 v = v->next;
15240 }
15241 }
15242 #endif
15243
15244
15245 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
15246
15247 mwimonitornotify[0] = '\0';
15248
15249 v = ast_variable_browse(cfg, "channels");
15250 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
15251 ast_mutex_unlock(&iflock);
15252 ast_config_destroy(cfg);
15253 if (ucfg) {
15254 ast_config_destroy(ucfg);
15255 }
15256 return res;
15257 }
15258
15259
15260 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15261
15262
15263
15264 if (!strcasecmp(cat, "general") ||
15265 !strcasecmp(cat, "trunkgroups") ||
15266 !strcasecmp(cat, "globals") ||
15267 !strcasecmp(cat, "channels")) {
15268 continue;
15269 }
15270
15271 memcpy(&conf, &base_conf, sizeof(conf));
15272
15273 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
15274 ast_mutex_unlock(&iflock);
15275 ast_config_destroy(cfg);
15276 if (ucfg) {
15277 ast_config_destroy(cfg);
15278 }
15279 return res;
15280 }
15281 }
15282
15283 ast_config_destroy(cfg);
15284
15285 if (ucfg) {
15286 const char *chans;
15287
15288 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
15289
15290 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15291 if (!strcasecmp(cat, "general")) {
15292 continue;
15293 }
15294
15295 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
15296
15297 if (ast_strlen_zero(chans)) {
15298 continue;
15299 }
15300
15301 memcpy(&conf, &base_conf, sizeof(conf));
15302
15303 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
15304 ast_config_destroy(ucfg);
15305 ast_mutex_unlock(&iflock);
15306 return res;
15307 }
15308 }
15309 ast_config_destroy(ucfg);
15310 }
15311 ast_mutex_unlock(&iflock);
15312
15313 #ifdef HAVE_PRI
15314 if (reload != 1) {
15315 int x;
15316 for (x = 0; x < NUM_SPANS; x++) {
15317 if (pris[x].pvts[0]) {
15318 if (start_pri(pris + x)) {
15319 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15320 return -1;
15321 } else
15322 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
15323 }
15324 }
15325 }
15326 #endif
15327 #ifdef HAVE_SS7
15328 if (reload != 1) {
15329 int x;
15330 for (x = 0; x < NUM_SPANS; x++) {
15331 if (linksets[x].ss7) {
15332 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
15333 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
15334 return -1;
15335 } else
15336 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
15337 }
15338 }
15339 }
15340 #endif
15341
15342 restart_monitor();
15343 return 0;
15344 }
15345
15346 static int load_module(void)
15347 {
15348 int res;
15349 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15350 int y, i;
15351 #endif
15352
15353 #ifdef HAVE_PRI
15354 memset(pris, 0, sizeof(pris));
15355 for (y = 0; y < NUM_SPANS; y++) {
15356 ast_mutex_init(&pris[y].lock);
15357 pris[y].offset = -1;
15358 pris[y].master = AST_PTHREADT_NULL;
15359 for (i = 0; i < NUM_DCHANS; i++)
15360 pris[y].fds[i] = -1;
15361 }
15362 pri_set_error(dahdi_pri_error);
15363 pri_set_message(dahdi_pri_message);
15364 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15365 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15366 #endif
15367 #ifdef HAVE_SS7
15368 memset(linksets, 0, sizeof(linksets));
15369 for (y = 0; y < NUM_SPANS; y++) {
15370 ast_mutex_init(&linksets[y].lock);
15371 linksets[y].master = AST_PTHREADT_NULL;
15372 for (i = 0; i < NUM_DCHANS; i++)
15373 linksets[y].fds[i] = -1;
15374 }
15375 ss7_set_error(dahdi_ss7_error);
15376 ss7_set_message(dahdi_ss7_message);
15377 #endif
15378 res = setup_dahdi(0);
15379
15380 if (res)
15381 return AST_MODULE_LOAD_DECLINE;
15382 if (ast_channel_register(&dahdi_tech)) {
15383 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15384 __unload_module();
15385 return AST_MODULE_LOAD_FAILURE;
15386 }
15387 #ifdef HAVE_PRI
15388 ast_string_field_init(&inuse, 16);
15389 ast_string_field_set(&inuse, name, "GR-303InUse");
15390 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15391 #endif
15392 #ifdef HAVE_SS7
15393 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15394 #endif
15395
15396 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15397
15398 memset(round_robin, 0, sizeof(round_robin));
15399 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15400 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15401 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15402 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15403 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15404 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15405 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15406
15407 ast_cond_init(&mwi_thread_complete, NULL);
15408 ast_cond_init(&ss_thread_complete, NULL);
15409
15410 return res;
15411 }
15412
15413 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15414 {
15415 #define END_SILENCE_LEN 400
15416 #define HEADER_MS 50
15417 #define TRAILER_MS 5
15418 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15419 #define ASCII_BYTES_PER_CHAR 80
15420
15421 unsigned char *buf,*mybuf;
15422 struct dahdi_pvt *p = c->tech_pvt;
15423 struct pollfd fds[1];
15424 int size,res,fd,len,x;
15425 int bytes=0;
15426
15427 float cr = 1.0;
15428 float ci = 0.0;
15429 float scont = 0.0;
15430 int idx;
15431
15432 idx = dahdi_get_index(c, p, 0);
15433 if (idx < 0) {
15434 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
15435 return -1;
15436 }
15437 if (!text[0]) return(0);
15438 if ((!p->tdd) && (!p->mate)) return(0);
15439 if (p->mate)
15440 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15441 else
15442 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15443 if (!buf)
15444 return -1;
15445 mybuf = buf;
15446 if (p->mate) {
15447 int codec = AST_LAW(p);
15448 for (x = 0; x < HEADER_MS; x++) {
15449 PUT_CLID_MARKMS;
15450 }
15451
15452 for (x = 0; text[x]; x++) {
15453 PUT_CLID(text[x]);
15454 }
15455 for (x = 0; x < TRAILER_MS; x++) {
15456 PUT_CLID_MARKMS;
15457 }
15458 len = bytes;
15459 buf = mybuf;
15460 } else {
15461 len = tdd_generate(p->tdd, buf, text);
15462 if (len < 1) {
15463 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15464 ast_free(mybuf);
15465 return -1;
15466 }
15467 }
15468 memset(buf + len, 0x7f, END_SILENCE_LEN);
15469 len += END_SILENCE_LEN;
15470 fd = p->subs[idx].dfd;
15471 while (len) {
15472 if (ast_check_hangup(c)) {
15473 ast_free(mybuf);
15474 return -1;
15475 }
15476 size = len;
15477 if (size > READ_SIZE)
15478 size = READ_SIZE;
15479 fds[0].fd = fd;
15480 fds[0].events = POLLOUT | POLLPRI;
15481 fds[0].revents = 0;
15482 res = poll(fds, 1, -1);
15483 if (!res) {
15484 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15485 continue;
15486 }
15487
15488 if (fds[0].revents & POLLPRI) {
15489 ast_free(mybuf);
15490 return -1;
15491 }
15492 if (!(fds[0].revents & POLLOUT)) {
15493 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15494 continue;
15495 }
15496 res = write(fd, buf, size);
15497 if (res != size) {
15498 if (res == -1) {
15499 ast_free(mybuf);
15500 return -1;
15501 }
15502 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15503 break;
15504 }
15505 len -= size;
15506 buf += size;
15507 }
15508 ast_free(mybuf);
15509 return(0);
15510 }
15511
15512
15513 static int reload(void)
15514 {
15515 int res = 0;
15516
15517 res = setup_dahdi(1);
15518 if (res) {
15519 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15520 return -1;
15521 }
15522 return 0;
15523 }
15524
15525
15526
15527
15528
15529 #ifdef HAVE_PRI
15530 #ifdef HAVE_SS7
15531 #define tdesc "DAHDI Telephony w/PRI & SS7"
15532 #else
15533 #define tdesc "DAHDI Telephony w/PRI"
15534 #endif
15535 #else
15536 #ifdef HAVE_SS7
15537 #define tdesc "DAHDI Telephony w/SS7"
15538 #else
15539 #define tdesc "DAHDI Telephony"
15540 #endif
15541 #endif
15542
15543 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15544 .load = load_module,
15545 .unload = unload_module,
15546 .reload = reload,
15547 );
15548
15549