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: 202763 $")
00051
00052 #ifdef __NetBSD__
00053 #include <pthread.h>
00054 #include <signal.h>
00055 #else
00056 #include <sys/signal.h>
00057 #endif
00058 #include <sys/ioctl.h>
00059 #include <math.h>
00060 #include <ctype.h>
00061
00062 #include <dahdi/user.h>
00063 #include <dahdi/tonezone.h>
00064
00065 #ifdef HAVE_PRI
00066 #include <libpri.h>
00067 #endif
00068
00069 #ifdef HAVE_SS7
00070 #include <libss7.h>
00071 #endif
00072
00073 #include "asterisk/lock.h"
00074 #include "asterisk/channel.h"
00075 #include "asterisk/config.h"
00076 #include "asterisk/module.h"
00077 #include "asterisk/pbx.h"
00078 #include "asterisk/file.h"
00079 #include "asterisk/ulaw.h"
00080 #include "asterisk/alaw.h"
00081 #include "asterisk/callerid.h"
00082 #include "asterisk/adsi.h"
00083 #include "asterisk/cli.h"
00084 #include "asterisk/cdr.h"
00085 #include "asterisk/features.h"
00086 #include "asterisk/musiconhold.h"
00087 #include "asterisk/say.h"
00088 #include "asterisk/tdd.h"
00089 #include "asterisk/app.h"
00090 #include "asterisk/dsp.h"
00091 #include "asterisk/astdb.h"
00092 #include "asterisk/manager.h"
00093 #include "asterisk/causes.h"
00094 #include "asterisk/term.h"
00095 #include "asterisk/utils.h"
00096 #include "asterisk/transcap.h"
00097 #include "asterisk/stringfields.h"
00098 #include "asterisk/abstract_jb.h"
00099 #include "asterisk/smdi.h"
00100 #include "asterisk/astobj.h"
00101 #include "asterisk/event.h"
00102 #include "asterisk/devicestate.h"
00103
00104 #define SMDI_MD_WAIT_TIMEOUT 1500
00105
00106 static const char *lbostr[] = {
00107 "0 db (CSU)/0-133 feet (DSX-1)",
00108 "133-266 feet (DSX-1)",
00109 "266-399 feet (DSX-1)",
00110 "399-533 feet (DSX-1)",
00111 "533-655 feet (DSX-1)",
00112 "-7.5db (CSU)",
00113 "-15db (CSU)",
00114 "-22.5db (CSU)"
00115 };
00116
00117
00118 static struct ast_jb_conf default_jbconf =
00119 {
00120 .flags = 0,
00121 .max_size = -1,
00122 .resync_threshold = -1,
00123 .impl = ""
00124 };
00125 static struct ast_jb_conf global_jbconf;
00126
00127
00128 #undef SUPPORT_USERUSER
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 #define DEFAULT_CIDRINGS 1
00150
00151 #define CHANNEL_PSEUDO -12
00152
00153 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00154
00155
00156
00157 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
00158
00159 static const char tdesc[] = "DAHDI Telephony Driver"
00160 #ifdef HAVE_PRI
00161 " w/PRI"
00162 #endif
00163 #ifdef HAVE_SS7
00164 " w/SS7"
00165 #endif
00166 ;
00167
00168 static const char config[] = "chan_dahdi.conf";
00169
00170 #define SIG_EM DAHDI_SIG_EM
00171 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00173 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00174 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00175 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00176 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00177 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00178 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00179 #define SIG_FXSLS DAHDI_SIG_FXSLS
00180 #define SIG_FXSGS DAHDI_SIG_FXSGS
00181 #define SIG_FXSKS DAHDI_SIG_FXSKS
00182 #define SIG_FXOLS DAHDI_SIG_FXOLS
00183 #define SIG_FXOGS DAHDI_SIG_FXOGS
00184 #define SIG_FXOKS DAHDI_SIG_FXOKS
00185 #define SIG_PRI DAHDI_SIG_CLEAR
00186 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00187 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00188 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00189 #define SIG_SF DAHDI_SIG_SF
00190 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00191 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00192 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00193 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00194 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00195 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00196 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00197
00198 #ifdef LOTS_OF_SPANS
00199 #define NUM_SPANS DAHDI_MAX_SPANS
00200 #else
00201 #define NUM_SPANS 32
00202 #endif
00203 #define NUM_DCHANS 4
00204 #define MAX_CHANNELS 672
00205
00206 #define CHAN_PSEUDO -2
00207
00208 #define DCHAN_PROVISIONED (1 << 0)
00209 #define DCHAN_NOTINALARM (1 << 1)
00210 #define DCHAN_UP (1 << 2)
00211
00212 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00213
00214
00215 #define DAHDI_OVERLAPDIAL_NONE 0
00216 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00217 #define DAHDI_OVERLAPDIAL_INCOMING 2
00218 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00219
00220
00221 #define CALLPROGRESS_PROGRESS 1
00222 #define CALLPROGRESS_FAX_OUTGOING 2
00223 #define CALLPROGRESS_FAX_INCOMING 4
00224 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00225
00226 static char defaultcic[64] = "";
00227 static char defaultozz[64] = "";
00228
00229
00230 static char mwimonitornotify[PATH_MAX] = "";
00231
00232 static char progzone[10] = "";
00233
00234 static int usedistinctiveringdetection = 0;
00235 static int distinctiveringaftercid = 0;
00236
00237 static int numbufs = 4;
00238
00239 static int mwilevel = 512;
00240
00241 #ifdef HAVE_PRI
00242 static struct ast_channel inuse;
00243 #ifdef PRI_GETSET_TIMERS
00244 static int pritimers[PRI_MAX_TIMERS];
00245 #endif
00246 static int pridebugfd = -1;
00247 static char pridebugfilename[1024] = "";
00248 #endif
00249
00250
00251 static int firstdigittimeout = 16000;
00252
00253
00254 static int gendigittimeout = 8000;
00255
00256
00257 static int matchdigittimeout = 3000;
00258
00259
00260 AST_MUTEX_DEFINE_STATIC(iflock);
00261
00262
00263 static int ifcount = 0;
00264
00265 #ifdef HAVE_PRI
00266 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00267 #endif
00268
00269
00270
00271 AST_MUTEX_DEFINE_STATIC(monlock);
00272
00273
00274
00275 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00276 static ast_cond_t ss_thread_complete;
00277 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00278 AST_MUTEX_DEFINE_STATIC(restart_lock);
00279 static int ss_thread_count = 0;
00280 static int num_restart_pending = 0;
00281
00282 static int restart_monitor(void);
00283
00284 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);
00285
00286 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00287
00288 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00289 {
00290
00291
00292
00293
00294 }
00295
00296
00297 static inline int dahdi_get_event(int fd)
00298 {
00299 int j;
00300 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00301 return -1;
00302 return j;
00303 }
00304
00305
00306 static inline int dahdi_wait_event(int fd)
00307 {
00308 int i, j = 0;
00309 i = DAHDI_IOMUX_SIGEVENT;
00310 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00311 return -1;
00312 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00313 return -1;
00314 return j;
00315 }
00316
00317
00318 #define READ_SIZE 160
00319
00320 #define MASK_AVAIL (1 << 0)
00321 #define MASK_INUSE (1 << 1)
00322
00323 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00324 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00325 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00326 #define MIN_MS_SINCE_FLASH ( (2000) )
00327 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00328
00329 struct dahdi_pvt;
00330
00331
00332
00333
00334
00335 static int ringt_base = DEFAULT_RINGT;
00336
00337 #ifdef HAVE_SS7
00338
00339 #define LINKSTATE_INALARM (1 << 0)
00340 #define LINKSTATE_STARTING (1 << 1)
00341 #define LINKSTATE_UP (1 << 2)
00342 #define LINKSTATE_DOWN (1 << 3)
00343
00344 #define SS7_NAI_DYNAMIC -1
00345
00346 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00347
00348 struct dahdi_ss7 {
00349 pthread_t master;
00350 ast_mutex_t lock;
00351 int fds[NUM_DCHANS];
00352 int numsigchans;
00353 int linkstate[NUM_DCHANS];
00354 int numchans;
00355 int type;
00356 enum {
00357 LINKSET_STATE_DOWN = 0,
00358 LINKSET_STATE_UP
00359 } state;
00360 char called_nai;
00361 char calling_nai;
00362 char internationalprefix[10];
00363 char nationalprefix[10];
00364 char subscriberprefix[20];
00365 char unknownprefix[20];
00366 struct ss7 *ss7;
00367 struct dahdi_pvt *pvts[MAX_CHANNELS];
00368 int flags;
00369 };
00370
00371 static struct dahdi_ss7 linksets[NUM_SPANS];
00372
00373 static int cur_ss7type = -1;
00374 static int cur_linkset = -1;
00375 static int cur_pointcode = -1;
00376 static int cur_cicbeginswith = -1;
00377 static int cur_adjpointcode = -1;
00378 static int cur_networkindicator = -1;
00379 static int cur_defaultdpc = -1;
00380 #endif
00381
00382 #ifdef HAVE_PRI
00383
00384 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00385 #define PRI_CHANNEL(p) ((p) & 0xff)
00386 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00387 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00388
00389 struct dahdi_pri {
00390 pthread_t master;
00391 ast_mutex_t lock;
00392 char idleext[AST_MAX_EXTENSION];
00393 char idlecontext[AST_MAX_CONTEXT];
00394 char idledial[AST_MAX_EXTENSION];
00395 int minunused;
00396 int minidle;
00397 int nodetype;
00398 int switchtype;
00399 int nsf;
00400 int dialplan;
00401 int localdialplan;
00402 char internationalprefix[10];
00403 char nationalprefix[10];
00404 char localprefix[20];
00405 char privateprefix[20];
00406 char unknownprefix[20];
00407 int dchannels[NUM_DCHANS];
00408 int trunkgroup;
00409 int mastertrunkgroup;
00410 int prilogicalspan;
00411 int numchans;
00412 int overlapdial;
00413 int facilityenable;
00414 struct pri *dchans[NUM_DCHANS];
00415 int dchanavail[NUM_DCHANS];
00416 struct pri *pri;
00417
00418 int debug;
00419 int fds[NUM_DCHANS];
00420
00421 int offset;
00422
00423 int span;
00424
00425 int resetting;
00426
00427 int resetpos;
00428 #ifdef HAVE_PRI_INBANDDISCONNECT
00429 unsigned int inbanddisconnect:1;
00430 #endif
00431 time_t lastreset;
00432 long resetinterval;
00433
00434 int sig;
00435 struct dahdi_pvt *pvts[MAX_CHANNELS];
00436 struct dahdi_pvt *crvs;
00437 struct dahdi_pvt *crvend;
00438 };
00439
00440
00441 static struct dahdi_pri pris[NUM_SPANS];
00442
00443 #if 0
00444 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00445 #else
00446 #define DEFAULT_PRI_DEBUG 0
00447 #endif
00448
00449 static inline void pri_rel(struct dahdi_pri *pri)
00450 {
00451 ast_mutex_unlock(&pri->lock);
00452 }
00453
00454 #else
00455
00456 struct dahdi_pri;
00457 #endif
00458
00459 #define SUB_REAL 0
00460 #define SUB_CALLWAIT 1
00461 #define SUB_THREEWAY 2
00462
00463
00464 #define POLARITY_IDLE 0
00465 #define POLARITY_REV 1
00466
00467
00468 struct distRingData {
00469 int ring[3];
00470 int range;
00471 };
00472 struct ringContextData {
00473 char contextData[AST_MAX_CONTEXT];
00474 };
00475 struct dahdi_distRings {
00476 struct distRingData ringnum[3];
00477 struct ringContextData ringContext[3];
00478 };
00479
00480 static char *subnames[] = {
00481 "Real",
00482 "Callwait",
00483 "Threeway"
00484 };
00485
00486 struct dahdi_subchannel {
00487 int dfd;
00488 struct ast_channel *owner;
00489 int chan;
00490 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00491 struct ast_frame f;
00492 unsigned int needringing:1;
00493 unsigned int needbusy:1;
00494 unsigned int needcongestion:1;
00495 unsigned int needcallerid:1;
00496 unsigned int needanswer:1;
00497 unsigned int needflash:1;
00498 unsigned int needhold:1;
00499 unsigned int needunhold:1;
00500 unsigned int linear:1;
00501 unsigned int inthreeway:1;
00502 struct dahdi_confinfo curconf;
00503 };
00504
00505 #define CONF_USER_REAL (1 << 0)
00506 #define CONF_USER_THIRDCALL (1 << 1)
00507
00508 #define MAX_SLAVES 4
00509
00510 static struct dahdi_pvt {
00511 ast_mutex_t lock;
00512 struct ast_channel *owner;
00513
00514
00515 struct dahdi_subchannel sub_unused;
00516 struct dahdi_subchannel subs[3];
00517 struct dahdi_confinfo saveconf;
00518
00519 struct dahdi_pvt *slaves[MAX_SLAVES];
00520 struct dahdi_pvt *master;
00521 int inconference;
00522
00523 int buf_no;
00524 int buf_policy;
00525 int sig;
00526
00527
00528
00529
00530 int radio;
00531 int outsigmod;
00532 int oprmode;
00533 struct dahdi_pvt *oprpeer;
00534
00535 float cid_rxgain;
00536
00537 float rxgain;
00538
00539 float txgain;
00540 int tonezone;
00541 struct dahdi_pvt *next;
00542 struct dahdi_pvt *prev;
00543
00544
00545
00546
00547
00548
00549
00550 unsigned int adsi:1;
00551
00552
00553
00554
00555
00556 unsigned int answeronpolarityswitch:1;
00557
00558
00559
00560
00561
00562 unsigned int busydetect:1;
00563
00564
00565
00566
00567
00568 unsigned int callreturn:1;
00569
00570
00571
00572
00573
00574
00575 unsigned int callwaiting:1;
00576
00577
00578
00579
00580 unsigned int callwaitingcallerid:1;
00581
00582
00583
00584
00585
00586
00587 unsigned int cancallforward:1;
00588
00589
00590
00591
00592 unsigned int canpark:1;
00593
00594 unsigned int confirmanswer:1;
00595
00596
00597
00598
00599 unsigned int destroy:1;
00600 unsigned int didtdd:1;
00601
00602 unsigned int dialednone:1;
00603
00604 unsigned int dialing:1;
00605
00606 unsigned int digital:1;
00607
00608 unsigned int dnd:1;
00609
00610 unsigned int echobreak:1;
00611
00612
00613
00614
00615
00616 unsigned int echocanbridged:1;
00617
00618 unsigned int echocanon:1;
00619
00620 unsigned int faxhandled:1;
00621
00622 unsigned int firstradio:1;
00623
00624
00625
00626
00627 unsigned int hanguponpolarityswitch:1;
00628
00629 unsigned int hardwaredtmf:1;
00630
00631
00632
00633
00634
00635
00636 unsigned int hidecallerid:1;
00637
00638
00639
00640
00641
00642 unsigned int hidecalleridname:1;
00643
00644 unsigned int ignoredtmf:1;
00645
00646
00647
00648
00649
00650 unsigned int immediate:1;
00651
00652 unsigned int inalarm:1;
00653
00654 unsigned int mate:1;
00655
00656 unsigned int outgoing:1;
00657
00658
00659
00660
00661
00662
00663 unsigned int permcallwaiting:1;
00664
00665
00666
00667
00668 unsigned int permhidecallerid:1;
00669
00670
00671
00672
00673 unsigned int priindication_oob:1;
00674
00675
00676
00677
00678 unsigned int priexclusive:1;
00679
00680
00681
00682
00683 unsigned int pulse:1;
00684
00685 unsigned int pulsedial:1;
00686 unsigned int restartpending:1;
00687
00688
00689
00690
00691
00692 unsigned int restrictcid:1;
00693
00694
00695
00696
00697 unsigned int threewaycalling:1;
00698
00699
00700
00701
00702
00703
00704
00705
00706 unsigned int transfer:1;
00707
00708
00709
00710
00711
00712
00713
00714 unsigned int use_callerid:1;
00715
00716
00717
00718
00719
00720
00721 unsigned int use_callingpres:1;
00722
00723
00724
00725
00726
00727 unsigned int usedistinctiveringdetection:1;
00728
00729
00730
00731
00732 unsigned int dahditrcallerid:1;
00733
00734
00735
00736
00737 unsigned int transfertobusy:1;
00738
00739
00740
00741
00742 unsigned int mwimonitor_neon:1;
00743
00744
00745
00746
00747 unsigned int mwimonitor_fsk:1;
00748
00749 unsigned int mwimonitoractive:1;
00750
00751
00752
00753
00754 unsigned int inservice:1;
00755
00756
00757
00758
00759 unsigned int locallyblocked:1;
00760
00761
00762
00763
00764 unsigned int remotelyblocked:1;
00765 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00766
00767
00768
00769
00770 unsigned int rlt:1;
00771
00772 unsigned int alerting:1;
00773
00774 unsigned int alreadyhungup:1;
00775
00776
00777
00778
00779 unsigned int isidlecall:1;
00780
00781
00782
00783
00784 unsigned int proceeding:1;
00785
00786 unsigned int progress:1;
00787
00788
00789
00790
00791 unsigned int resetting:1;
00792
00793
00794
00795
00796 unsigned int setup_ack:1;
00797 #endif
00798
00799
00800
00801
00802 unsigned int use_smdi:1;
00803
00804 struct ast_smdi_interface *smdi_iface;
00805
00806
00807 struct dahdi_distRings drings;
00808
00809
00810
00811
00812
00813 char context[AST_MAX_CONTEXT];
00814
00815
00816
00817 char defcontext[AST_MAX_CONTEXT];
00818
00819 char exten[AST_MAX_EXTENSION];
00820
00821
00822
00823
00824 char language[MAX_LANGUAGE];
00825
00826
00827
00828
00829 char mohinterpret[MAX_MUSICCLASS];
00830
00831
00832
00833
00834 char mohsuggest[MAX_MUSICCLASS];
00835 #if defined(PRI_ANI) || defined(HAVE_SS7)
00836
00837 char cid_ani[AST_MAX_EXTENSION];
00838 #endif
00839
00840 int cid_ani2;
00841
00842 char cid_num[AST_MAX_EXTENSION];
00843
00844 int cid_ton;
00845
00846 char cid_name[AST_MAX_EXTENSION];
00847
00848 char lastcid_num[AST_MAX_EXTENSION];
00849
00850 char lastcid_name[AST_MAX_EXTENSION];
00851 char *origcid_num;
00852 char *origcid_name;
00853
00854 char callwait_num[AST_MAX_EXTENSION];
00855
00856 char callwait_name[AST_MAX_EXTENSION];
00857
00858 char rdnis[AST_MAX_EXTENSION];
00859
00860 char dnid[AST_MAX_EXTENSION];
00861
00862
00863
00864
00865 ast_group_t group;
00866
00867 int law;
00868 int confno;
00869 int confusers;
00870 int propconfno;
00871
00872
00873
00874
00875 ast_group_t callgroup;
00876
00877
00878
00879
00880 ast_group_t pickupgroup;
00881
00882
00883
00884
00885 struct ast_variable *vars;
00886 int channel;
00887 int span;
00888 time_t guardtime;
00889 int cid_signalling;
00890 int cid_start;
00891 int callingpres;
00892 int callwaitingrepeat;
00893 int cidcwexpire;
00894
00895 unsigned char *cidspill;
00896
00897 int cidpos;
00898
00899 int cidlen;
00900
00901 int ringt;
00902
00903
00904
00905
00906 int ringt_base;
00907
00908
00909
00910
00911
00912
00913 int stripmsd;
00914
00915 int callwaitcas;
00916
00917 int callwaitrings;
00918
00919 struct {
00920 struct dahdi_echocanparams head;
00921 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
00922 } echocancel;
00923
00924
00925
00926
00927 int echotraining;
00928
00929 char echorest[20];
00930
00931
00932
00933
00934 int busycount;
00935
00936
00937
00938
00939 int busycompare;
00940
00941
00942
00943
00944 int busytonelength;
00945
00946
00947
00948
00949 int busyquietlength;
00950
00951
00952
00953
00954 int busyfuzziness;
00955
00956
00957
00958
00959 int silencethreshold;
00960
00961
00962
00963
00964 int callprogress;
00965 struct timeval flashtime;
00966
00967 struct ast_dsp *dsp;
00968
00969
00970 struct dahdi_dialoperation dop;
00971 int whichwink;
00972
00973 char finaldial[64];
00974 char accountcode[AST_MAX_ACCOUNT_CODE];
00975 int amaflags;
00976 struct tdd_state *tdd;
00977
00978 char call_forward[AST_MAX_EXTENSION];
00979
00980
00981
00982
00983 char mailbox[AST_MAX_EXTENSION];
00984
00985 struct ast_event_sub *mwi_event_sub;
00986
00987 char dialdest[256];
00988
00989 int onhooktime;
00990
00991 int msgstate;
00992 int distinctivering;
00993 int cidrings;
00994 int dtmfrelax;
00995
00996 int fake_event;
00997
00998
00999
01000
01001 int polarityonanswerdelay;
01002
01003 struct timeval polaritydelaytv;
01004
01005
01006
01007
01008 int sendcalleridafter;
01009 #ifdef HAVE_PRI
01010
01011 struct dahdi_pri *pri;
01012
01013 struct dahdi_pvt *bearer;
01014
01015 struct dahdi_pvt *realcall;
01016
01017 q931_call *call;
01018
01019 int prioffset;
01020
01021 int logicalspan;
01022 #endif
01023
01024 int polarity;
01025
01026 int dsp_features;
01027 #ifdef HAVE_SS7
01028
01029 struct dahdi_ss7 *ss7;
01030
01031 struct isup_call *ss7call;
01032 char charge_number[50];
01033 char gen_add_number[50];
01034 char gen_dig_number[50];
01035 char orig_called_num[50];
01036 char redirecting_num[50];
01037 char generic_name[50];
01038 unsigned char gen_add_num_plan;
01039 unsigned char gen_add_nai;
01040 unsigned char gen_add_pres_ind;
01041 unsigned char gen_add_type;
01042 unsigned char gen_dig_type;
01043 unsigned char gen_dig_scheme;
01044 char jip_number[50];
01045 unsigned char lspi_type;
01046 unsigned char lspi_scheme;
01047 unsigned char lspi_context;
01048 char lspi_ident[50];
01049 unsigned int call_ref_ident;
01050 unsigned int call_ref_pc;
01051 unsigned char calling_party_cat;
01052 int transcap;
01053 int cic;
01054 unsigned int dpc;
01055 unsigned int loopedback:1;
01056 #endif
01057
01058 char begindigit;
01059 } *iflist = NULL, *ifend = NULL;
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071 struct dahdi_chan_conf {
01072 struct dahdi_pvt chan;
01073 #ifdef HAVE_PRI
01074 struct dahdi_pri pri;
01075 #endif
01076
01077 #ifdef HAVE_SS7
01078 struct dahdi_ss7 ss7;
01079 #endif
01080 struct dahdi_params timing;
01081 int is_sig_auto;
01082
01083
01084
01085
01086
01087 char smdi_port[SMDI_MAX_FILENAME_LEN];
01088 };
01089
01090
01091 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01092
01093
01094
01095 struct dahdi_chan_conf conf = {
01096 #ifdef HAVE_PRI
01097 .pri = {
01098 .nsf = PRI_NSF_NONE,
01099 .switchtype = PRI_SWITCH_NI2,
01100 .dialplan = PRI_NATIONAL_ISDN + 1,
01101 .localdialplan = PRI_NATIONAL_ISDN + 1,
01102 .nodetype = PRI_CPE,
01103
01104 .minunused = 2,
01105 .idleext = "",
01106 .idledial = "",
01107 .internationalprefix = "",
01108 .nationalprefix = "",
01109 .localprefix = "",
01110 .privateprefix = "",
01111 .unknownprefix = "",
01112 .resetinterval = -1,
01113 },
01114 #endif
01115 #ifdef HAVE_SS7
01116 .ss7 = {
01117 .called_nai = SS7_NAI_NATIONAL,
01118 .calling_nai = SS7_NAI_NATIONAL,
01119 .internationalprefix = "",
01120 .nationalprefix = "",
01121 .subscriberprefix = "",
01122 .unknownprefix = ""
01123 },
01124 #endif
01125 .chan = {
01126 .context = "default",
01127 .cid_num = "",
01128 .cid_name = "",
01129 .mohinterpret = "default",
01130 .mohsuggest = "",
01131 .transfertobusy = 1,
01132
01133 .cid_signalling = CID_SIG_BELL,
01134 .cid_start = CID_START_RING,
01135 .dahditrcallerid = 0,
01136 .use_callerid = 1,
01137 .sig = -1,
01138 .outsigmod = -1,
01139
01140 .cid_rxgain = +5.0,
01141
01142 .tonezone = -1,
01143
01144 .echocancel.head.tap_length = 1,
01145
01146 .busycount = 3,
01147 .busycompare = 0,
01148 .busytonelength = 0,
01149 .busyquietlength = 0,
01150 .busyfuzziness = 0,
01151 .silencethreshold = 0,
01152
01153 .accountcode = "",
01154
01155 .mailbox = "",
01156
01157
01158 .polarityonanswerdelay = 600,
01159
01160 .sendcalleridafter = DEFAULT_CIDRINGS,
01161
01162 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01163 .buf_no = numbufs
01164 },
01165 .timing = {
01166 .prewinktime = -1,
01167 .preflashtime = -1,
01168 .winktime = -1,
01169 .flashtime = -1,
01170 .starttime = -1,
01171 .rxwinktime = -1,
01172 .rxflashtime = -1,
01173 .debouncetime = -1
01174 },
01175 .is_sig_auto = 1,
01176 .smdi_port = "/dev/ttyS0",
01177 };
01178
01179 return conf;
01180 }
01181
01182
01183 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01184 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01185 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01186 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01187 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01188 static int dahdi_hangup(struct ast_channel *ast);
01189 static int dahdi_answer(struct ast_channel *ast);
01190 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01191 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01192 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01193 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01194 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01195 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01196 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
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 ast_mutex_unlock(&pvt->lock);
01259
01260 usleep(1);
01261 ast_mutex_lock(&pvt->lock);
01262 }
01263 } while (res);
01264
01265 if (pri->master != AST_PTHREADT_NULL)
01266 pthread_kill(pri->master, SIGURG);
01267 return 0;
01268 }
01269 #endif
01270 #define NUM_CADENCE_MAX 25
01271 static int num_cadence = 4;
01272 static int user_has_defined_cadences = 0;
01273
01274 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01275 { { 125, 125, 2000, 4000 } },
01276 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01277 { { 125, 125, 125, 125, 125, 4000 } },
01278 { { 1000, 500, 2500, 5000 } },
01279 };
01280
01281
01282
01283
01284
01285 static int cidrings[NUM_CADENCE_MAX] = {
01286 2,
01287 4,
01288 3,
01289 2,
01290 };
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 index;
01596 int dtmf = -1;
01597
01598 pvt = chan->tech_pvt;
01599
01600 ast_mutex_lock(&pvt->lock);
01601
01602 index = dahdi_get_index(chan, pvt, 0);
01603
01604 if ((index != 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 index;
01659 int x;
01660
01661 pvt = chan->tech_pvt;
01662
01663 ast_mutex_lock(&pvt->lock);
01664
01665 index = dahdi_get_index(chan, pvt, 0);
01666
01667 if ((index != 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 alarm)
01727 {
01728 int x;
01729 for (x = 0; x < ARRAY_LEN(alarms); x++) {
01730 if (alarms[x].alarm & alarm)
01731 return alarms[x].name;
01732 }
01733 return alarm ? "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 index, 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 (!index) {
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 index)
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 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
02308 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
02309 AST_EVENT_IE_END);
02310
02311 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02312 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02313 ast_safe_system(s);
02314 }
02315 }
02316
02317 static int restore_conference(struct dahdi_pvt *p)
02318 {
02319 int res;
02320 if (p->saveconf.confmode) {
02321 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02322 p->saveconf.confmode = 0;
02323 if (res) {
02324 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02325 return -1;
02326 }
02327 }
02328 ast_debug(1, "Restored conferencing\n");
02329 return 0;
02330 }
02331
02332 static int send_callerid(struct dahdi_pvt *p);
02333
02334 static int send_cwcidspill(struct dahdi_pvt *p)
02335 {
02336 p->callwaitcas = 0;
02337 p->cidcwexpire = 0;
02338 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02339 return -1;
02340 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02341
02342 p->cidlen += READ_SIZE * 4;
02343 p->cidpos = 0;
02344 send_callerid(p);
02345 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02346 return 0;
02347 }
02348
02349 static int has_voicemail(struct dahdi_pvt *p)
02350 {
02351 int new_msgs;
02352 struct ast_event *event;
02353 char *mailbox, *context;
02354
02355 mailbox = context = ast_strdupa(p->mailbox);
02356 strsep(&context, "@");
02357 if (ast_strlen_zero(context))
02358 context = "default";
02359
02360 event = ast_event_get_cached(AST_EVENT_MWI,
02361 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02362 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02363 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
02364 AST_EVENT_IE_END);
02365
02366 if (event) {
02367 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02368 ast_event_destroy(event);
02369 } else
02370 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02371
02372 return new_msgs;
02373 }
02374
02375 static int send_callerid(struct dahdi_pvt *p)
02376 {
02377
02378 int res;
02379
02380 if (p->subs[SUB_REAL].linear) {
02381 p->subs[SUB_REAL].linear = 0;
02382 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02383 }
02384 while (p->cidpos < p->cidlen) {
02385 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02386 if (res < 0) {
02387 if (errno == EAGAIN)
02388 return 0;
02389 else {
02390 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02391 return -1;
02392 }
02393 }
02394 if (!res)
02395 return 0;
02396 p->cidpos += res;
02397 }
02398 ast_free(p->cidspill);
02399 p->cidspill = NULL;
02400 if (p->callwaitcas) {
02401
02402 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02403 } else
02404 restore_conference(p);
02405 return 0;
02406 }
02407
02408 static int dahdi_callwait(struct ast_channel *ast)
02409 {
02410 struct dahdi_pvt *p = ast->tech_pvt;
02411 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02412 if (p->cidspill) {
02413 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02414 ast_free(p->cidspill);
02415 }
02416 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02417 return -1;
02418 save_conference(p);
02419
02420 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02421 if (!p->callwaitrings && p->callwaitingcallerid) {
02422 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02423 p->callwaitcas = 1;
02424 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02425 } else {
02426 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02427 p->callwaitcas = 0;
02428 p->cidlen = 2400 + READ_SIZE * 4;
02429 }
02430 p->cidpos = 0;
02431 send_callerid(p);
02432
02433 return 0;
02434 }
02435
02436 #ifdef HAVE_SS7
02437 static unsigned char cid_pres2ss7pres(int cid_pres)
02438 {
02439 return (cid_pres >> 5) & 0x03;
02440 }
02441
02442 static unsigned char cid_pres2ss7screen(int cid_pres)
02443 {
02444 return cid_pres & 0x03;
02445 }
02446 #endif
02447
02448 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02449 {
02450 struct dahdi_pvt *p = ast->tech_pvt;
02451 int x, res, index,mysig;
02452 char *c, *n, *l;
02453 #ifdef HAVE_PRI
02454 char *s = NULL;
02455 #endif
02456 char dest[256];
02457 ast_mutex_lock(&p->lock);
02458 ast_copy_string(dest, rdest, sizeof(dest));
02459 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02460 if ((ast->_state == AST_STATE_BUSY)) {
02461 p->subs[SUB_REAL].needbusy = 1;
02462 ast_mutex_unlock(&p->lock);
02463 return 0;
02464 }
02465 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02466 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02467 ast_mutex_unlock(&p->lock);
02468 return -1;
02469 }
02470 p->dialednone = 0;
02471 if ((p->radio || (p->oprmode < 0)))
02472 {
02473
02474 ast_setstate(ast, AST_STATE_UP);
02475 ast_mutex_unlock(&p->lock);
02476 return 0;
02477 }
02478 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02479 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02480 if (res)
02481 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02482 p->outgoing = 1;
02483
02484 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
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 index = dahdi_get_index(ast, p, 0);
02578 if (index > -1) {
02579 p->subs[index].needringing = 1;
02580 }
02581 break;
02582 case SIG_FXSLS:
02583 case SIG_FXSGS:
02584 case SIG_FXSKS:
02585 case SIG_EMWINK:
02586 case SIG_EM:
02587 case SIG_EM_E1:
02588 case SIG_FEATD:
02589 case SIG_FEATDMF:
02590 case SIG_E911:
02591 case SIG_FGC_CAMA:
02592 case SIG_FGC_CAMAMF:
02593 case SIG_FEATB:
02594 case SIG_SFWINK:
02595 case SIG_SF:
02596 case SIG_SF_FEATD:
02597 case SIG_SF_FEATDMF:
02598 case SIG_FEATDMF_TA:
02599 case SIG_SF_FEATB:
02600 c = strchr(dest, '/');
02601 if (c)
02602 c++;
02603 else
02604 c = "";
02605 if (strlen(c) < p->stripmsd) {
02606 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02607 ast_mutex_unlock(&p->lock);
02608 return -1;
02609 }
02610 #ifdef HAVE_PRI
02611
02612 if (!p->pri) {
02613 #endif
02614 x = DAHDI_START;
02615 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02616 if (res < 0) {
02617 if (errno != EINPROGRESS) {
02618 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02619 ast_mutex_unlock(&p->lock);
02620 return -1;
02621 }
02622 }
02623 #ifdef HAVE_PRI
02624 }
02625 #endif
02626 ast_debug(1, "Dialing '%s'\n", c);
02627 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02628
02629 c += p->stripmsd;
02630
02631 switch (mysig) {
02632 case SIG_FEATD:
02633 l = ast->cid.cid_num;
02634 if (l)
02635 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02636 else
02637 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02638 break;
02639 case SIG_FEATDMF:
02640 l = ast->cid.cid_num;
02641 if (l)
02642 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02643 else
02644 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02645 break;
02646 case SIG_FEATDMF_TA:
02647 {
02648 const char *cic, *ozz;
02649
02650
02651 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02652 if (!ozz)
02653 ozz = defaultozz;
02654 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02655 if (!cic)
02656 cic = defaultcic;
02657 if (!ozz || !cic) {
02658 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02659 ast_mutex_unlock(&p->lock);
02660 return -1;
02661 }
02662 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02663 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02664 p->whichwink = 0;
02665 }
02666 break;
02667 case SIG_E911:
02668 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02669 break;
02670 case SIG_FGC_CAMA:
02671 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02672 break;
02673 case SIG_FGC_CAMAMF:
02674 case SIG_FEATB:
02675 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02676 break;
02677 default:
02678 if (p->pulse)
02679 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02680 else
02681 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02682 break;
02683 }
02684
02685 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02686 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02687 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02688 p->echorest[sizeof(p->echorest) - 1] = '\0';
02689 p->echobreak = 1;
02690 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02691 } else
02692 p->echobreak = 0;
02693 if (!res) {
02694 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02695 int saveerr = errno;
02696
02697 x = DAHDI_ONHOOK;
02698 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02699 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02700 ast_mutex_unlock(&p->lock);
02701 return -1;
02702 }
02703 } else
02704 ast_debug(1, "Deferring dialing...\n");
02705
02706 p->dialing = 1;
02707 if (ast_strlen_zero(c))
02708 p->dialednone = 1;
02709 ast_setstate(ast, AST_STATE_DIALING);
02710 break;
02711 case 0:
02712
02713 ast_setstate(ast, AST_STATE_UP);
02714 break;
02715 case SIG_PRI:
02716 case SIG_BRI:
02717 case SIG_BRI_PTMP:
02718 case SIG_SS7:
02719
02720 p->dialdest[0] = '\0';
02721 p->dialing = 1;
02722 break;
02723 default:
02724 ast_debug(1, "not yet implemented\n");
02725 ast_mutex_unlock(&p->lock);
02726 return -1;
02727 }
02728 #ifdef HAVE_SS7
02729 if (p->ss7) {
02730 char ss7_called_nai;
02731 int called_nai_strip;
02732 char ss7_calling_nai;
02733 int calling_nai_strip;
02734 const char *charge_str = NULL;
02735 const char *gen_address = NULL;
02736 const char *gen_digits = NULL;
02737 const char *gen_dig_type = NULL;
02738 const char *gen_dig_scheme = NULL;
02739 const char *gen_name = NULL;
02740 const char *jip_digits = NULL;
02741 const char *lspi_ident = NULL;
02742 const char *rlt_flag = NULL;
02743 const char *call_ref_id = NULL;
02744 const char *call_ref_pc = NULL;
02745 const char *send_far = NULL;
02746
02747 c = strchr(dest, '/');
02748 if (c) {
02749 c++;
02750 } else {
02751 c = "";
02752 }
02753 if (strlen(c) < p->stripmsd) {
02754 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02755 ast_mutex_unlock(&p->lock);
02756 return -1;
02757 }
02758
02759 if (!p->hidecallerid) {
02760 l = ast->cid.cid_num;
02761 } else {
02762 l = NULL;
02763 }
02764
02765 if (ss7_grab(p, p->ss7)) {
02766 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02767 ast_mutex_unlock(&p->lock);
02768 return -1;
02769 }
02770 p->digital = IS_DIGITAL(ast->transfercapability);
02771 p->ss7call = isup_new_call(p->ss7->ss7);
02772
02773 if (!p->ss7call) {
02774 ss7_rel(p->ss7);
02775 ast_mutex_unlock(&p->lock);
02776 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02777 return -1;
02778 }
02779
02780 called_nai_strip = 0;
02781 ss7_called_nai = p->ss7->called_nai;
02782 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
02783 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02784 called_nai_strip = strlen(p->ss7->internationalprefix);
02785 ss7_called_nai = SS7_NAI_INTERNATIONAL;
02786 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02787 called_nai_strip = strlen(p->ss7->nationalprefix);
02788 ss7_called_nai = SS7_NAI_NATIONAL;
02789 } else {
02790 ss7_called_nai = SS7_NAI_SUBSCRIBER;
02791 }
02792 }
02793 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02794
02795 calling_nai_strip = 0;
02796 ss7_calling_nai = p->ss7->calling_nai;
02797 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
02798 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02799 calling_nai_strip = strlen(p->ss7->internationalprefix);
02800 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02801 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02802 calling_nai_strip = strlen(p->ss7->nationalprefix);
02803 ss7_calling_nai = SS7_NAI_NATIONAL;
02804 } else {
02805 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02806 }
02807 }
02808 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02809 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02810 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02811
02812 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02813 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02814
02815 ast_channel_lock(ast);
02816
02817 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02818 if (charge_str)
02819 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02820
02821 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02822 if (gen_address)
02823 isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type);
02824
02825 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02826 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02827 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02828 if (gen_digits)
02829 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
02830
02831 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02832 if (gen_name)
02833 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02834
02835 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02836 if (jip_digits)
02837 isup_set_jip_digits(p->ss7call, jip_digits);
02838
02839 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02840 if (lspi_ident)
02841 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
02842
02843 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02844 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02845 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
02846 }
02847
02848 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02849 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02850 if (call_ref_id && call_ref_pc) {
02851 isup_set_callref(p->ss7call, atoi(call_ref_id),
02852 call_ref_pc ? atoi(call_ref_pc) : 0);
02853 }
02854
02855 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02856 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02857 (isup_far(p->ss7->ss7, p->ss7call));
02858
02859 ast_channel_unlock(ast);
02860
02861 isup_iam(p->ss7->ss7, p->ss7call);
02862 ast_setstate(ast, AST_STATE_DIALING);
02863 ss7_rel(p->ss7);
02864 }
02865 #endif
02866 #ifdef HAVE_PRI
02867 if (p->pri) {
02868 struct pri_sr *sr;
02869 #ifdef SUPPORT_USERUSER
02870 const char *useruser;
02871 #endif
02872 int pridialplan;
02873 int dp_strip;
02874 int prilocaldialplan;
02875 int ldp_strip;
02876 int exclusive;
02877 const char *rr_str;
02878 int redirect_reason;
02879
02880 c = strchr(dest, '/');
02881 if (c) {
02882 c++;
02883 } else {
02884 c = "";
02885 }
02886
02887 l = NULL;
02888 n = NULL;
02889 if (!p->hidecallerid) {
02890 l = ast->cid.cid_num;
02891 if (!p->hidecalleridname) {
02892 n = ast->cid.cid_name;
02893 }
02894 }
02895
02896 if (strlen(c) < p->stripmsd) {
02897 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02898 ast_mutex_unlock(&p->lock);
02899 return -1;
02900 }
02901 if (mysig != SIG_FXSKS) {
02902 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02903 s = strchr(c + p->stripmsd, 'w');
02904 if (s) {
02905 if (strlen(s) > 1)
02906 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02907 else
02908 p->dop.dialstr[0] = '\0';
02909 *s = '\0';
02910 } else {
02911 p->dop.dialstr[0] = '\0';
02912 }
02913 }
02914 if (pri_grab(p, p->pri)) {
02915 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02916 ast_mutex_unlock(&p->lock);
02917 return -1;
02918 }
02919 if (!(p->call = pri_new_call(p->pri->pri))) {
02920 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02921 pri_rel(p->pri);
02922 ast_mutex_unlock(&p->lock);
02923 return -1;
02924 }
02925 if (!(sr = pri_sr_new())) {
02926 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02927 pri_rel(p->pri);
02928 ast_mutex_unlock(&p->lock);
02929 }
02930 if (p->bearer || (mysig == SIG_FXSKS)) {
02931 if (p->bearer) {
02932 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02933 p->bearer->call = p->call;
02934 } else
02935 ast_debug(1, "I'm being setup with no bearer right now...\n");
02936
02937 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02938 }
02939 p->digital = IS_DIGITAL(ast->transfercapability);
02940
02941 if (p->priexclusive)
02942 exclusive = 1;
02943 else {
02944
02945 if (p->pri->nodetype == PRI_NETWORK)
02946 exclusive = 0;
02947 else
02948 exclusive = 1;
02949 }
02950
02951 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02952 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02953 (p->digital ? -1 :
02954 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02955 if (p->pri->facilityenable)
02956 pri_facility_enable(p->pri->pri);
02957
02958 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02959 dp_strip = 0;
02960 pridialplan = p->pri->dialplan - 1;
02961 if (pridialplan == -2 || pridialplan == -3) {
02962 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02963 if (pridialplan == -2) {
02964 dp_strip = strlen(p->pri->internationalprefix);
02965 }
02966 pridialplan = PRI_INTERNATIONAL_ISDN;
02967 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02968 if (pridialplan == -2) {
02969 dp_strip = strlen(p->pri->nationalprefix);
02970 }
02971 pridialplan = PRI_NATIONAL_ISDN;
02972 } else {
02973 pridialplan = PRI_LOCAL_ISDN;
02974 }
02975 }
02976 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02977 switch (c[p->stripmsd]) {
02978 case 'U':
02979 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02980 break;
02981 case 'I':
02982 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
02983 break;
02984 case 'N':
02985 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
02986 break;
02987 case 'L':
02988 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
02989 break;
02990 case 'S':
02991 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
02992 break;
02993 case 'V':
02994 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
02995 break;
02996 case 'R':
02997 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
02998 break;
02999 case 'u':
03000 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03001 break;
03002 case 'e':
03003 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03004 break;
03005 case 'x':
03006 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03007 break;
03008 case 'f':
03009 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03010 break;
03011 case 'n':
03012 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03013 break;
03014 case 'p':
03015 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03016 break;
03017 case 'r':
03018 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03019 break;
03020 default:
03021 if (isalpha(c[p->stripmsd])) {
03022 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03023 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03024 }
03025 break;
03026 }
03027 c++;
03028 }
03029 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03030
03031 ldp_strip = 0;
03032 prilocaldialplan = p->pri->localdialplan - 1;
03033 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03034 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03035 if (prilocaldialplan == -2) {
03036 ldp_strip = strlen(p->pri->internationalprefix);
03037 }
03038 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03039 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03040 if (prilocaldialplan == -2) {
03041 ldp_strip = strlen(p->pri->nationalprefix);
03042 }
03043 prilocaldialplan = PRI_NATIONAL_ISDN;
03044 } else {
03045 prilocaldialplan = PRI_LOCAL_ISDN;
03046 }
03047 }
03048 if (l != NULL) {
03049 while (*l > '9' && *l != '*' && *l != '#') {
03050 switch (*l) {
03051 case 'U':
03052 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03053 break;
03054 case 'I':
03055 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03056 break;
03057 case 'N':
03058 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03059 break;
03060 case 'L':
03061 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03062 break;
03063 case 'S':
03064 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03065 break;
03066 case 'V':
03067 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03068 break;
03069 case 'R':
03070 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03071 break;
03072 case 'u':
03073 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03074 break;
03075 case 'e':
03076 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03077 break;
03078 case 'x':
03079 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03080 break;
03081 case 'f':
03082 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03083 break;
03084 case 'n':
03085 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03086 break;
03087 case 'p':
03088 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03089 break;
03090 case 'r':
03091 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03092 break;
03093 default:
03094 if (isalpha(*l)) {
03095 ast_log(LOG_WARNING,
03096 "Unrecognized prilocaldialplan %s modifier: %c\n",
03097 *l > 'Z' ? "NPI" : "TON", *l);
03098 }
03099 break;
03100 }
03101 l++;
03102 }
03103 }
03104 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03105 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03106 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03107 if (!strcasecmp(rr_str, "UNKNOWN"))
03108 redirect_reason = 0;
03109 else if (!strcasecmp(rr_str, "BUSY"))
03110 redirect_reason = 1;
03111 else if (!strcasecmp(rr_str, "NO_REPLY"))
03112 redirect_reason = 2;
03113 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03114 redirect_reason = 15;
03115 else
03116 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03117 } else
03118 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03119 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03120
03121 #ifdef SUPPORT_USERUSER
03122
03123 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03124
03125 if (useruser)
03126 pri_sr_set_useruser(sr, useruser);
03127 #endif
03128
03129 if (pri_setup(p->pri->pri, p->call, sr)) {
03130 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03131 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03132 pri_rel(p->pri);
03133 ast_mutex_unlock(&p->lock);
03134 pri_sr_free(sr);
03135 return -1;
03136 }
03137 pri_sr_free(sr);
03138 ast_setstate(ast, AST_STATE_DIALING);
03139 pri_rel(p->pri);
03140 }
03141 #endif
03142 ast_mutex_unlock(&p->lock);
03143 return 0;
03144 }
03145
03146 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03147 {
03148 struct dahdi_pvt *p = *pvt;
03149
03150 if (p->prev)
03151 p->prev->next = p->next;
03152 if (p->next)
03153 p->next->prev = p->prev;
03154 if (p->use_smdi)
03155 ast_smdi_interface_unref(p->smdi_iface);
03156 if (p->mwi_event_sub)
03157 ast_event_unsubscribe(p->mwi_event_sub);
03158 if (p->vars)
03159 ast_variables_destroy(p->vars);
03160 ast_mutex_destroy(&p->lock);
03161 dahdi_close_sub(p, SUB_REAL);
03162 if (p->owner)
03163 p->owner->tech_pvt = NULL;
03164 free(p);
03165 *pvt = NULL;
03166 }
03167
03168 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03169 {
03170 int owned = 0;
03171 int i = 0;
03172
03173 if (!now) {
03174 if (cur->owner) {
03175 owned = 1;
03176 }
03177
03178 for (i = 0; i < 3; i++) {
03179 if (cur->subs[i].owner) {
03180 owned = 1;
03181 }
03182 }
03183 if (!owned) {
03184 if (prev) {
03185 prev->next = cur->next;
03186 if (prev->next)
03187 prev->next->prev = prev;
03188 else
03189 ifend = prev;
03190 } else {
03191 iflist = cur->next;
03192 if (iflist)
03193 iflist->prev = NULL;
03194 else
03195 ifend = NULL;
03196 }
03197 destroy_dahdi_pvt(&cur);
03198 }
03199 } else {
03200 if (prev) {
03201 prev->next = cur->next;
03202 if (prev->next)
03203 prev->next->prev = prev;
03204 else
03205 ifend = prev;
03206 } else {
03207 iflist = cur->next;
03208 if (iflist)
03209 iflist->prev = NULL;
03210 else
03211 ifend = NULL;
03212 }
03213 destroy_dahdi_pvt(&cur);
03214 }
03215 return 0;
03216 }
03217
03218 static void destroy_all_channels(void)
03219 {
03220 int x;
03221 struct dahdi_pvt *p, *pl;
03222
03223 while (num_restart_pending) {
03224 usleep(1);
03225 }
03226
03227 ast_mutex_lock(&iflock);
03228
03229 p = iflist;
03230 while (p) {
03231
03232 if (p->cidspill)
03233 ast_free(p->cidspill);
03234 pl = p;
03235 p = p->next;
03236 x = pl->channel;
03237
03238 if (pl)
03239 destroy_dahdi_pvt(&pl);
03240 if (option_verbose > 2)
03241 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03242 }
03243 iflist = NULL;
03244 ifcount = 0;
03245 ast_mutex_unlock(&iflock);
03246 }
03247
03248 #ifdef HAVE_PRI
03249 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03250
03251 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03252
03253 static char *dahdi_send_keypad_facility_descrip =
03254 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03255 " IE over the current channel.\n";
03256
03257 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03258 {
03259
03260 struct dahdi_pvt *p;
03261 char *digits = (char *) data;
03262
03263 if (ast_strlen_zero(digits)) {
03264 ast_debug(1, "No digit string sent to application!\n");
03265 return -1;
03266 }
03267
03268 p = (struct dahdi_pvt *)chan->tech_pvt;
03269
03270 if (!p) {
03271 ast_debug(1, "Unable to find technology private\n");
03272 return -1;
03273 }
03274
03275 ast_mutex_lock(&p->lock);
03276
03277 if (!p->pri || !p->call) {
03278 ast_debug(1, "Unable to find pri or call on channel!\n");
03279 ast_mutex_unlock(&p->lock);
03280 return -1;
03281 }
03282
03283 if (!pri_grab(p, p->pri)) {
03284 pri_keypad_facility(p->pri->pri, p->call, digits);
03285 pri_rel(p->pri);
03286 } else {
03287 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03288 ast_mutex_unlock(&p->lock);
03289 return -1;
03290 }
03291
03292 ast_mutex_unlock(&p->lock);
03293
03294 return 0;
03295 }
03296
03297 static int pri_is_up(struct dahdi_pri *pri)
03298 {
03299 int x;
03300 for (x = 0; x < NUM_DCHANS; x++) {
03301 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03302 return 1;
03303 }
03304 return 0;
03305 }
03306
03307 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03308 {
03309 bearer->owner = &inuse;
03310 bearer->realcall = crv;
03311 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03312 if (crv->subs[SUB_REAL].owner)
03313 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03314 crv->bearer = bearer;
03315 crv->call = bearer->call;
03316 crv->pri = pri;
03317 return 0;
03318 }
03319
03320 static char *pri_order(int level)
03321 {
03322 switch (level) {
03323 case 0:
03324 return "Primary";
03325 case 1:
03326 return "Secondary";
03327 case 2:
03328 return "Tertiary";
03329 case 3:
03330 return "Quaternary";
03331 default:
03332 return "<Unknown>";
03333 }
03334 }
03335
03336
03337 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03338 {
03339 int x = -1;
03340
03341 for (x = 0; x < NUM_DCHANS; x++) {
03342 if ((pri->dchans[x] == pri->pri))
03343 break;
03344 }
03345
03346 return pri->fds[x];
03347 }
03348
03349 static int pri_find_dchan(struct dahdi_pri *pri)
03350 {
03351 int oldslot = -1;
03352 struct pri *old;
03353 int newslot = -1;
03354 int x;
03355 old = pri->pri;
03356 for (x = 0; x < NUM_DCHANS; x++) {
03357 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03358 newslot = x;
03359 if (pri->dchans[x] == old) {
03360 oldslot = x;
03361 }
03362 }
03363 if (newslot < 0) {
03364 newslot = 0;
03365 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03366 pri->dchannels[newslot]);
03367 }
03368 if (old && (oldslot != newslot))
03369 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03370 pri->dchannels[oldslot], pri->dchannels[newslot]);
03371 pri->pri = pri->dchans[newslot];
03372 return 0;
03373 }
03374 #endif
03375
03376 static int dahdi_hangup(struct ast_channel *ast)
03377 {
03378 int res;
03379 int index,x, law;
03380
03381 struct dahdi_pvt *p = ast->tech_pvt;
03382 struct dahdi_pvt *tmp = NULL;
03383 struct dahdi_pvt *prev = NULL;
03384 struct dahdi_params par;
03385
03386 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03387 if (!ast->tech_pvt) {
03388 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03389 return 0;
03390 }
03391
03392 ast_mutex_lock(&p->lock);
03393
03394 index = dahdi_get_index(ast, p, 1);
03395
03396 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03397 x = 1;
03398 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03399 }
03400
03401 x = 0;
03402 dahdi_confmute(p, 0);
03403 restore_gains(p);
03404 if (p->origcid_num) {
03405 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03406 ast_free(p->origcid_num);
03407 p->origcid_num = NULL;
03408 }
03409 if (p->origcid_name) {
03410 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03411 ast_free(p->origcid_name);
03412 p->origcid_name = NULL;
03413 }
03414 if (p->dsp)
03415 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03416 p->exten[0] = '\0';
03417
03418 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03419 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03420 p->ignoredtmf = 0;
03421
03422 if (index > -1) {
03423
03424 p->subs[index].owner = NULL;
03425 p->subs[index].needanswer = 0;
03426 p->subs[index].needflash = 0;
03427 p->subs[index].needringing = 0;
03428 p->subs[index].needbusy = 0;
03429 p->subs[index].needcongestion = 0;
03430 p->subs[index].linear = 0;
03431 p->subs[index].needcallerid = 0;
03432 p->polarity = POLARITY_IDLE;
03433 dahdi_setlinear(p->subs[index].dfd, 0);
03434 if (index == SUB_REAL) {
03435 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03436 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03437 if (p->subs[SUB_CALLWAIT].inthreeway) {
03438
03439 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03440
03441 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03442 unalloc_sub(p, SUB_CALLWAIT);
03443 p->owner = NULL;
03444 } else {
03445
03446 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03447 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03448 unalloc_sub(p, SUB_THREEWAY);
03449 if (p->subs[SUB_REAL].inthreeway) {
03450
03451
03452 ast_debug(1, "Call was complete, setting owner to former third call\n");
03453 p->owner = p->subs[SUB_REAL].owner;
03454 } else {
03455
03456 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03457 p->owner = NULL;
03458 }
03459 p->subs[SUB_REAL].inthreeway = 0;
03460 }
03461 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03462
03463 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03464 unalloc_sub(p, SUB_CALLWAIT);
03465 p->owner = p->subs[SUB_REAL].owner;
03466 if (p->owner->_state != AST_STATE_UP)
03467 p->subs[SUB_REAL].needanswer = 1;
03468 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03469 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03470 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03471 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03472 unalloc_sub(p, SUB_THREEWAY);
03473 if (p->subs[SUB_REAL].inthreeway) {
03474
03475
03476 ast_debug(1, "Call was complete, setting owner to former third call\n");
03477 p->owner = p->subs[SUB_REAL].owner;
03478 } else {
03479
03480 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03481 p->owner = NULL;
03482 }
03483 p->subs[SUB_REAL].inthreeway = 0;
03484 }
03485 } else if (index == SUB_CALLWAIT) {
03486
03487 if (p->subs[SUB_CALLWAIT].inthreeway) {
03488
03489
03490 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03491 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03492 S_OR(p->mohsuggest, NULL),
03493 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03494 }
03495 p->subs[SUB_THREEWAY].inthreeway = 0;
03496
03497 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03498 unalloc_sub(p, SUB_THREEWAY);
03499 } else
03500 unalloc_sub(p, SUB_CALLWAIT);
03501 } else if (index == SUB_THREEWAY) {
03502 if (p->subs[SUB_CALLWAIT].inthreeway) {
03503
03504
03505 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03506 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03507 S_OR(p->mohsuggest, NULL),
03508 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03509 }
03510 p->subs[SUB_CALLWAIT].inthreeway = 0;
03511 }
03512 p->subs[SUB_REAL].inthreeway = 0;
03513
03514
03515 unalloc_sub(p, SUB_THREEWAY);
03516 } else {
03517
03518 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03519 }
03520 }
03521
03522 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03523 p->owner = NULL;
03524 p->ringt = 0;
03525 p->distinctivering = 0;
03526 p->confirmanswer = 0;
03527 p->cidrings = 1;
03528 p->outgoing = 0;
03529 p->digital = 0;
03530 p->faxhandled = 0;
03531 p->pulsedial = 0;
03532 p->onhooktime = time(NULL);
03533 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03534 p->proceeding = 0;
03535 p->dialing = 0;
03536 p->progress = 0;
03537 p->alerting = 0;
03538 p->setup_ack = 0;
03539 p->rlt = 0;
03540 #endif
03541 if (p->dsp) {
03542 ast_dsp_free(p->dsp);
03543 p->dsp = NULL;
03544 }
03545
03546 law = DAHDI_LAW_DEFAULT;
03547 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03548 if (res < 0)
03549 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03550
03551 #ifdef HAVE_SS7
03552 if (p->ss7) {
03553 if (p->ss7call) {
03554 if (!ss7_grab(p, p->ss7)) {
03555 if (!p->alreadyhungup) {
03556 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03557 int icause = ast->hangupcause ? ast->hangupcause : -1;
03558
03559 if (cause) {
03560 if (atoi(cause))
03561 icause = atoi(cause);
03562 }
03563 isup_rel(p->ss7->ss7, p->ss7call, icause);
03564 ss7_rel(p->ss7);
03565 p->alreadyhungup = 1;
03566 } else
03567 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03568 } else {
03569 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03570 res = -1;
03571 }
03572 }
03573 }
03574 #endif
03575 #ifdef HAVE_PRI
03576 if (p->pri) {
03577 #ifdef SUPPORT_USERUSER
03578 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03579 #endif
03580
03581
03582 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03583 if (!pri_grab(p, p->pri)) {
03584 if (p->alreadyhungup) {
03585 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
03586
03587 #ifdef SUPPORT_USERUSER
03588 pri_call_set_useruser(p->call, useruser);
03589 #endif
03590
03591 pri_hangup(p->pri->pri, p->call, -1);
03592 p->call = NULL;
03593 if (p->bearer)
03594 p->bearer->call = NULL;
03595 } else {
03596 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03597 int icause = ast->hangupcause ? ast->hangupcause : -1;
03598 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03599
03600 #ifdef SUPPORT_USERUSER
03601 pri_call_set_useruser(p->call, useruser);
03602 #endif
03603
03604 p->alreadyhungup = 1;
03605 if (p->bearer)
03606 p->bearer->alreadyhungup = 1;
03607 if (cause) {
03608 if (atoi(cause))
03609 icause = atoi(cause);
03610 }
03611 pri_hangup(p->pri->pri, p->call, icause);
03612 }
03613 if (res < 0)
03614 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03615 pri_rel(p->pri);
03616 } else {
03617 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03618 res = -1;
03619 }
03620 } else {
03621 if (p->bearer)
03622 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03623 p->call = NULL;
03624 res = 0;
03625 }
03626 }
03627 #endif
03628 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03629 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03630 if (res < 0) {
03631 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03632 }
03633 switch (p->sig) {
03634 case SIG_FXOGS:
03635 case SIG_FXOLS:
03636 case SIG_FXOKS:
03637 memset(&par, 0, sizeof(par));
03638 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03639 if (!res) {
03640 #if 0
03641 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03642 #endif
03643
03644 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03645 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03646 else
03647 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03648 }
03649 break;
03650 case SIG_FXSGS:
03651 case SIG_FXSLS:
03652 case SIG_FXSKS:
03653
03654
03655 if (ast->_state != AST_STATE_RESERVED) {
03656 time(&p->guardtime);
03657 p->guardtime += 2;
03658 }
03659 break;
03660 default:
03661 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03662 }
03663 if (p->cidspill)
03664 ast_free(p->cidspill);
03665 if (p->sig)
03666 dahdi_disable_ec(p);
03667 x = 0;
03668 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03669 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03670 p->didtdd = 0;
03671 p->cidspill = NULL;
03672 p->callwaitcas = 0;
03673 p->callwaiting = p->permcallwaiting;
03674 p->hidecallerid = p->permhidecallerid;
03675 p->dialing = 0;
03676 p->rdnis[0] = '\0';
03677 update_conf(p);
03678 reset_conf(p);
03679
03680 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03681 x = 0;
03682 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03683 }
03684 #ifdef HAVE_PRI
03685 if (p->bearer) {
03686 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03687
03688
03689 update_conf(p->bearer);
03690 reset_conf(p->bearer);
03691 p->bearer->owner = NULL;
03692 p->bearer->realcall = NULL;
03693 p->bearer = NULL;
03694 p->subs[SUB_REAL].dfd = -1;
03695 p->pri = NULL;
03696 }
03697 #endif
03698 if (num_restart_pending == 0)
03699 restart_monitor();
03700 }
03701
03702 p->callwaitingrepeat = 0;
03703 p->cidcwexpire = 0;
03704 p->oprmode = 0;
03705 ast->tech_pvt = NULL;
03706 ast_mutex_unlock(&p->lock);
03707 ast_module_unref(ast_module_info->self);
03708 ast_verb(3, "Hungup '%s'\n", ast->name);
03709
03710 ast_mutex_lock(&iflock);
03711
03712 if (p->restartpending) {
03713 num_restart_pending--;
03714 }
03715
03716 tmp = iflist;
03717 prev = NULL;
03718 if (p->destroy) {
03719 while (tmp) {
03720 if (tmp == p) {
03721 destroy_channel(prev, tmp, 0);
03722 break;
03723 } else {
03724 prev = tmp;
03725 tmp = tmp->next;
03726 }
03727 }
03728 }
03729 ast_mutex_unlock(&iflock);
03730 return 0;
03731 }
03732
03733 static int dahdi_answer(struct ast_channel *ast)
03734 {
03735 struct dahdi_pvt *p = ast->tech_pvt;
03736 int res = 0;
03737 int index;
03738 int oldstate = ast->_state;
03739 ast_setstate(ast, AST_STATE_UP);
03740 ast_mutex_lock(&p->lock);
03741 index = dahdi_get_index(ast, p, 0);
03742 if (index < 0)
03743 index = SUB_REAL;
03744
03745 if ((p->radio || (p->oprmode < 0))) {
03746 ast_mutex_unlock(&p->lock);
03747 return 0;
03748 }
03749 switch (p->sig) {
03750 case SIG_FXSLS:
03751 case SIG_FXSGS:
03752 case SIG_FXSKS:
03753 p->ringt = 0;
03754
03755 case SIG_EM:
03756 case SIG_EM_E1:
03757 case SIG_EMWINK:
03758 case SIG_FEATD:
03759 case SIG_FEATDMF:
03760 case SIG_FEATDMF_TA:
03761 case SIG_E911:
03762 case SIG_FGC_CAMA:
03763 case SIG_FGC_CAMAMF:
03764 case SIG_FEATB:
03765 case SIG_SF:
03766 case SIG_SFWINK:
03767 case SIG_SF_FEATD:
03768 case SIG_SF_FEATDMF:
03769 case SIG_SF_FEATB:
03770 case SIG_FXOLS:
03771 case SIG_FXOGS:
03772 case SIG_FXOKS:
03773
03774 ast_debug(1, "Took %s off hook\n", ast->name);
03775 if (p->hanguponpolarityswitch) {
03776 p->polaritydelaytv = ast_tvnow();
03777 }
03778 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03779 tone_zone_play_tone(p->subs[index].dfd, -1);
03780 p->dialing = 0;
03781 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03782 if (oldstate == AST_STATE_RINGING) {
03783 ast_debug(1, "Finally swapping real and threeway\n");
03784 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03785 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03786 p->owner = p->subs[SUB_REAL].owner;
03787 }
03788 }
03789 if (p->sig & __DAHDI_SIG_FXS) {
03790 dahdi_enable_ec(p);
03791 dahdi_train_ec(p);
03792 }
03793 break;
03794 #ifdef HAVE_PRI
03795 case SIG_BRI:
03796 case SIG_BRI_PTMP:
03797 case SIG_PRI:
03798
03799 if (!pri_grab(p, p->pri)) {
03800 p->proceeding = 1;
03801 p->dialing = 0;
03802 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03803 pri_rel(p->pri);
03804 } else {
03805 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03806 res = -1;
03807 }
03808 break;
03809 #endif
03810 #ifdef HAVE_SS7
03811 case SIG_SS7:
03812 if (!ss7_grab(p, p->ss7)) {
03813 p->proceeding = 1;
03814 res = isup_anm(p->ss7->ss7, p->ss7call);
03815 ss7_rel(p->ss7);
03816 } else {
03817 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03818 res = -1;
03819 }
03820 break;
03821 #endif
03822 case 0:
03823 ast_mutex_unlock(&p->lock);
03824 return 0;
03825 default:
03826 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03827 res = -1;
03828 }
03829 ast_mutex_unlock(&p->lock);
03830 return res;
03831 }
03832
03833 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03834 {
03835 char *cp;
03836 signed char *scp;
03837 int x;
03838 int index;
03839 struct dahdi_pvt *p = chan->tech_pvt, *pp;
03840 struct oprmode *oprmode;
03841
03842
03843
03844 if (!data || (datalen < 1)) {
03845 errno = EINVAL;
03846 return -1;
03847 }
03848
03849 switch (option) {
03850 case AST_OPTION_TXGAIN:
03851 scp = (signed char *) data;
03852 index = dahdi_get_index(chan, p, 0);
03853 if (index < 0) {
03854 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03855 return -1;
03856 }
03857 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03858 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
03859 case AST_OPTION_RXGAIN:
03860 scp = (signed char *) data;
03861 index = dahdi_get_index(chan, p, 0);
03862 if (index < 0) {
03863 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03864 return -1;
03865 }
03866 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03867 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
03868 case AST_OPTION_TONE_VERIFY:
03869 if (!p->dsp)
03870 break;
03871 cp = (char *) data;
03872 switch (*cp) {
03873 case 1:
03874 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03875 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
03876 break;
03877 case 2:
03878 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03879 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
03880 break;
03881 default:
03882 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03883 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03884 break;
03885 }
03886 break;
03887 case AST_OPTION_TDD:
03888
03889 cp = (char *) data;
03890 p->mate = 0;
03891 if (!*cp) {
03892 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03893 if (p->tdd)
03894 tdd_free(p->tdd);
03895 p->tdd = 0;
03896 break;
03897 }
03898 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03899 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03900 dahdi_disable_ec(p);
03901
03902 if (!p->didtdd) {
03903 unsigned char mybuf[41000];
03904 unsigned char *buf;
03905 int size, res, fd, len;
03906 struct pollfd fds[1];
03907
03908 buf = mybuf;
03909 memset(buf, 0x7f, sizeof(mybuf));
03910 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03911 len = 40000;
03912 index = dahdi_get_index(chan, p, 0);
03913 if (index < 0) {
03914 ast_log(LOG_WARNING, "No index in TDD?\n");
03915 return -1;
03916 }
03917 fd = p->subs[index].dfd;
03918 while (len) {
03919 if (ast_check_hangup(chan))
03920 return -1;
03921 size = len;
03922 if (size > READ_SIZE)
03923 size = READ_SIZE;
03924 fds[0].fd = fd;
03925 fds[0].events = POLLPRI | POLLOUT;
03926 fds[0].revents = 0;
03927 res = poll(fds, 1, -1);
03928 if (!res) {
03929 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03930 continue;
03931 }
03932
03933 if (fds[0].revents & POLLPRI)
03934 return -1;
03935 if (!(fds[0].revents & POLLOUT)) {
03936 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03937 continue;
03938 }
03939 res = write(fd, buf, size);
03940 if (res != size) {
03941 if (res == -1) return -1;
03942 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03943 break;
03944 }
03945 len -= size;
03946 buf += size;
03947 }
03948 p->didtdd = 1;
03949 }
03950 if (*cp == 2) {
03951 if (p->tdd)
03952 tdd_free(p->tdd);
03953 p->tdd = 0;
03954 p->mate = 1;
03955 break;
03956 }
03957 if (!p->tdd) {
03958 p->tdd = tdd_new();
03959 }
03960 break;
03961 case AST_OPTION_RELAXDTMF:
03962 if (!p->dsp)
03963 break;
03964 cp = (char *) data;
03965 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03966 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03967 ast_dsp_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03968 break;
03969 case AST_OPTION_AUDIO_MODE:
03970 cp = (char *) data;
03971 if (!*cp) {
03972 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03973 x = 0;
03974 dahdi_disable_ec(p);
03975 } else {
03976 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03977 x = 1;
03978 }
03979 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03980 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03981 break;
03982 case AST_OPTION_OPRMODE:
03983 oprmode = (struct oprmode *) data;
03984 pp = oprmode->peer->tech_pvt;
03985 p->oprmode = pp->oprmode = 0;
03986
03987 p->oprpeer = pp;
03988 pp->oprpeer = p;
03989
03990 if (oprmode->mode)
03991 {
03992 pp->oprmode = oprmode->mode;
03993 p->oprmode = -oprmode->mode;
03994 }
03995 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
03996 oprmode->mode, chan->name,oprmode->peer->name);
03997 break;
03998 case AST_OPTION_ECHOCAN:
03999 cp = (char *) data;
04000 if (*cp) {
04001 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
04002 dahdi_enable_ec(p);
04003 } else {
04004 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
04005 dahdi_disable_ec(p);
04006 }
04007 break;
04008 }
04009 errno = 0;
04010
04011 return 0;
04012 }
04013
04014 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
04015 {
04016 struct dahdi_pvt *p = chan->tech_pvt;
04017
04018 if (!strcasecmp(data, "rxgain")) {
04019 ast_mutex_lock(&p->lock);
04020 snprintf(buf, len, "%f", p->rxgain);
04021 ast_mutex_unlock(&p->lock);
04022 } else if (!strcasecmp(data, "txgain")) {
04023 ast_mutex_lock(&p->lock);
04024 snprintf(buf, len, "%f", p->txgain);
04025 ast_mutex_unlock(&p->lock);
04026 } else {
04027 ast_copy_string(buf, "", len);
04028 }
04029 return 0;
04030 }
04031
04032
04033 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04034 {
04035
04036 int x;
04037 int hasslaves;
04038 if (!master)
04039 return;
04040 if (needlock) {
04041 ast_mutex_lock(&master->lock);
04042 if (slave) {
04043 while (ast_mutex_trylock(&slave->lock)) {
04044 DEADLOCK_AVOIDANCE(&master->lock);
04045 }
04046 }
04047 }
04048 hasslaves = 0;
04049 for (x = 0; x < MAX_SLAVES; x++) {
04050 if (master->slaves[x]) {
04051 if (!slave || (master->slaves[x] == slave)) {
04052
04053 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04054 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04055 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04056 master->slaves[x]->master = NULL;
04057 master->slaves[x] = NULL;
04058 } else
04059 hasslaves = 1;
04060 }
04061 if (!hasslaves)
04062 master->inconference = 0;
04063 }
04064 if (!slave) {
04065 if (master->master) {
04066
04067 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04068 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04069 hasslaves = 0;
04070 for (x = 0; x < MAX_SLAVES; x++) {
04071 if (master->master->slaves[x] == master)
04072 master->master->slaves[x] = NULL;
04073 else if (master->master->slaves[x])
04074 hasslaves = 1;
04075 }
04076 if (!hasslaves)
04077 master->master->inconference = 0;
04078 }
04079 master->master = NULL;
04080 }
04081 update_conf(master);
04082 if (needlock) {
04083 if (slave)
04084 ast_mutex_unlock(&slave->lock);
04085 ast_mutex_unlock(&master->lock);
04086 }
04087 }
04088
04089 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04090 int x;
04091 if (!slave || !master) {
04092 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04093 return;
04094 }
04095 for (x = 0; x < MAX_SLAVES; x++) {
04096 if (!master->slaves[x]) {
04097 master->slaves[x] = slave;
04098 break;
04099 }
04100 }
04101 if (x >= MAX_SLAVES) {
04102 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04103 master->slaves[MAX_SLAVES - 1] = slave;
04104 }
04105 if (slave->master)
04106 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04107 slave->master = master;
04108
04109 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04110 }
04111
04112 static void disable_dtmf_detect(struct dahdi_pvt *p)
04113 {
04114 int val;
04115
04116 p->ignoredtmf = 1;
04117
04118 val = 0;
04119 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04120
04121 if (!p->hardwaredtmf && p->dsp) {
04122 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04123 ast_dsp_set_features(p->dsp, p->dsp_features);
04124 }
04125 }
04126
04127 static void enable_dtmf_detect(struct dahdi_pvt *p)
04128 {
04129 int val;
04130
04131 if (p->channel == CHAN_PSEUDO)
04132 return;
04133
04134 p->ignoredtmf = 0;
04135
04136 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04137 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04138
04139 if (!p->hardwaredtmf && p->dsp) {
04140 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04141 ast_dsp_set_features(p->dsp, p->dsp_features);
04142 }
04143 }
04144
04145 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)
04146 {
04147 struct ast_channel *who;
04148 struct dahdi_pvt *p0, *p1, *op0, *op1;
04149 struct dahdi_pvt *master = NULL, *slave = NULL;
04150 struct ast_frame *f;
04151 int inconf = 0;
04152 int nothingok = 1;
04153 int ofd0, ofd1;
04154 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04155 int os0 = -1, os1 = -1;
04156 int priority = 0;
04157 struct ast_channel *oc0, *oc1;
04158 enum ast_bridge_result res;
04159
04160 #ifdef PRI_2BCT
04161 int triedtopribridge = 0;
04162 q931_call *q931c0 = NULL, *q931c1 = NULL;
04163 #endif
04164
04165
04166
04167
04168
04169
04170 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04171 return AST_BRIDGE_FAILED_NOWARN;
04172
04173 ast_channel_lock(c0);
04174 while (ast_channel_trylock(c1)) {
04175 ast_channel_unlock(c0);
04176 usleep(1);
04177 ast_channel_lock(c0);
04178 }
04179
04180 p0 = c0->tech_pvt;
04181 p1 = c1->tech_pvt;
04182
04183 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04184 ast_channel_unlock(c0);
04185 ast_channel_unlock(c1);
04186 return AST_BRIDGE_FAILED_NOWARN;
04187 }
04188
04189 oi0 = dahdi_get_index(c0, p0, 0);
04190 oi1 = dahdi_get_index(c1, p1, 0);
04191 if ((oi0 < 0) || (oi1 < 0)) {
04192 ast_channel_unlock(c0);
04193 ast_channel_unlock(c1);
04194 return AST_BRIDGE_FAILED;
04195 }
04196
04197 op0 = p0 = c0->tech_pvt;
04198 op1 = p1 = c1->tech_pvt;
04199 ofd0 = c0->fds[0];
04200 ofd1 = c1->fds[0];
04201 oc0 = p0->owner;
04202 oc1 = p1->owner;
04203
04204 if (ast_mutex_trylock(&p0->lock)) {
04205
04206 ast_channel_unlock(c0);
04207 ast_channel_unlock(c1);
04208 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04209 return AST_BRIDGE_RETRY;
04210 }
04211 if (ast_mutex_trylock(&p1->lock)) {
04212
04213 ast_mutex_unlock(&p0->lock);
04214 ast_channel_unlock(c0);
04215 ast_channel_unlock(c1);
04216 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04217 return AST_BRIDGE_RETRY;
04218 }
04219
04220 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04221 if (p0->owner && p1->owner) {
04222
04223 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04224 master = p0;
04225 slave = p1;
04226 inconf = 1;
04227 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04228 master = p1;
04229 slave = p0;
04230 inconf = 1;
04231 } else {
04232 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04233 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04234 p0->channel,
04235 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04236 p0->subs[SUB_REAL].inthreeway, p0->channel,
04237 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04238 p1->subs[SUB_REAL].inthreeway);
04239 }
04240 nothingok = 0;
04241 }
04242 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04243 if (p1->subs[SUB_THREEWAY].inthreeway) {
04244 master = p1;
04245 slave = p0;
04246 nothingok = 0;
04247 }
04248 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04249 if (p0->subs[SUB_THREEWAY].inthreeway) {
04250 master = p0;
04251 slave = p1;
04252 nothingok = 0;
04253 }
04254 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04255
04256
04257 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04258 master = p1;
04259 slave = p0;
04260 nothingok = 0;
04261 }
04262 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04263
04264 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04265 master = p0;
04266 slave = p1;
04267 nothingok = 0;
04268 }
04269 }
04270 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04271 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04272 if (master && slave) {
04273
04274
04275
04276 if ((oi1 == SUB_THREEWAY) &&
04277 p1->subs[SUB_THREEWAY].inthreeway &&
04278 p1->subs[SUB_REAL].owner &&
04279 p1->subs[SUB_REAL].inthreeway &&
04280 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04281 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04282 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04283 os1 = p1->subs[SUB_REAL].owner->_state;
04284 } else {
04285 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04286 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04287 }
04288 if ((oi0 == SUB_THREEWAY) &&
04289 p0->subs[SUB_THREEWAY].inthreeway &&
04290 p0->subs[SUB_REAL].owner &&
04291 p0->subs[SUB_REAL].inthreeway &&
04292 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04293 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04294 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04295 os0 = p0->subs[SUB_REAL].owner->_state;
04296 } else {
04297 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04298 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04299 }
04300 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04301 if (!p0->echocanbridged || !p1->echocanbridged) {
04302
04303 dahdi_disable_ec(p0);
04304 dahdi_disable_ec(p1);
04305 }
04306 }
04307 dahdi_link(slave, master);
04308 master->inconference = inconf;
04309 } else if (!nothingok)
04310 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04311
04312 update_conf(p0);
04313 update_conf(p1);
04314 t0 = p0->subs[SUB_REAL].inthreeway;
04315 t1 = p1->subs[SUB_REAL].inthreeway;
04316
04317 ast_mutex_unlock(&p0->lock);
04318 ast_mutex_unlock(&p1->lock);
04319
04320 ast_channel_unlock(c0);
04321 ast_channel_unlock(c1);
04322
04323
04324 if ((!master || !slave) && !nothingok) {
04325 dahdi_enable_ec(p0);
04326 dahdi_enable_ec(p1);
04327 return AST_BRIDGE_FAILED;
04328 }
04329
04330 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04331
04332 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04333 disable_dtmf_detect(op0);
04334
04335 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04336 disable_dtmf_detect(op1);
04337
04338 for (;;) {
04339 struct ast_channel *c0_priority[2] = {c0, c1};
04340 struct ast_channel *c1_priority[2] = {c1, c0};
04341
04342
04343
04344
04345 ast_channel_lock(c0);
04346 while (ast_channel_trylock(c1)) {
04347 ast_channel_unlock(c0);
04348 usleep(1);
04349 ast_channel_lock(c0);
04350 }
04351
04352 p0 = c0->tech_pvt;
04353 p1 = c1->tech_pvt;
04354
04355 if (op0 == p0)
04356 i0 = dahdi_get_index(c0, p0, 1);
04357 if (op1 == p1)
04358 i1 = dahdi_get_index(c1, p1, 1);
04359
04360 ast_channel_unlock(c0);
04361 ast_channel_unlock(c1);
04362
04363 if (!timeoutms ||
04364 (op0 != p0) ||
04365 (op1 != p1) ||
04366 (ofd0 != c0->fds[0]) ||
04367 (ofd1 != c1->fds[0]) ||
04368 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04369 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04370 (oc0 != p0->owner) ||
04371 (oc1 != p1->owner) ||
04372 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04373 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04374 (oi0 != i0) ||
04375 (oi1 != i1)) {
04376 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04377 op0->channel, oi0, op1->channel, oi1);
04378 res = AST_BRIDGE_RETRY;
04379 goto return_from_bridge;
04380 }
04381
04382 #ifdef PRI_2BCT
04383 q931c0 = p0->call;
04384 q931c1 = p1->call;
04385 if (p0->transfer && p1->transfer
04386 && q931c0 && q931c1
04387 && !triedtopribridge) {
04388 pri_channel_bridge(q931c0, q931c1);
04389 triedtopribridge = 1;
04390 }
04391 #endif
04392
04393 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04394 if (!who) {
04395 ast_debug(1, "Ooh, empty read...\n");
04396 continue;
04397 }
04398 f = ast_read(who);
04399 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04400 *fo = f;
04401 *rc = who;
04402 res = AST_BRIDGE_COMPLETE;
04403 goto return_from_bridge;
04404 }
04405 if (f->frametype == AST_FRAME_DTMF) {
04406 if ((who == c0) && p0->pulsedial) {
04407 ast_write(c1, f);
04408 } else if ((who == c1) && p1->pulsedial) {
04409 ast_write(c0, f);
04410 } else {
04411 *fo = f;
04412 *rc = who;
04413 res = AST_BRIDGE_COMPLETE;
04414 goto return_from_bridge;
04415 }
04416 }
04417 ast_frfree(f);
04418
04419
04420 priority = !priority;
04421 }
04422
04423 return_from_bridge:
04424 if (op0 == p0)
04425 dahdi_enable_ec(p0);
04426
04427 if (op1 == p1)
04428 dahdi_enable_ec(p1);
04429
04430 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04431 enable_dtmf_detect(op0);
04432
04433 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04434 enable_dtmf_detect(op1);
04435
04436 dahdi_unlink(slave, master, 1);
04437
04438 return res;
04439 }
04440
04441 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04442 {
04443 struct dahdi_pvt *p = newchan->tech_pvt;
04444 int x;
04445 ast_mutex_lock(&p->lock);
04446 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04447 if (p->owner == oldchan) {
04448 p->owner = newchan;
04449 }
04450 for (x = 0; x < 3; x++)
04451 if (p->subs[x].owner == oldchan) {
04452 if (!x)
04453 dahdi_unlink(NULL, p, 0);
04454 p->subs[x].owner = newchan;
04455 }
04456 if (newchan->_state == AST_STATE_RINGING)
04457 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04458 update_conf(p);
04459 ast_mutex_unlock(&p->lock);
04460 return 0;
04461 }
04462
04463 static int dahdi_ring_phone(struct dahdi_pvt *p)
04464 {
04465 int x;
04466 int res;
04467
04468 x = 0;
04469 x = DAHDI_ONHOOK;
04470 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04471 do {
04472 x = DAHDI_RING;
04473 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04474 if (res) {
04475 switch (errno) {
04476 case EBUSY:
04477 case EINTR:
04478
04479 usleep(10000);
04480 continue;
04481 case EINPROGRESS:
04482 res = 0;
04483 break;
04484 default:
04485 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04486 res = 0;
04487 }
04488 }
04489 } while (res);
04490 return res;
04491 }
04492
04493 static void *ss_thread(void *data);
04494
04495 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
04496
04497 static int attempt_transfer(struct dahdi_pvt *p)
04498 {
04499
04500
04501
04502 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04503
04504
04505 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04506 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04507 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04508 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04509 }
04510 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04511 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04512 }
04513 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04514 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04515 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04516 return -1;
04517 }
04518
04519 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04520 unalloc_sub(p, SUB_THREEWAY);
04521 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04522 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04523 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04524 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04525 }
04526 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04527 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04528 }
04529 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04530 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04531 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04532 return -1;
04533 }
04534
04535 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04536 ast_channel_unlock(p->subs[SUB_REAL].owner);
04537 unalloc_sub(p, SUB_THREEWAY);
04538
04539 return 1;
04540 } else {
04541 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04542 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04543 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04544 return -1;
04545 }
04546 return 0;
04547 }
04548
04549 static int check_for_conference(struct dahdi_pvt *p)
04550 {
04551 struct dahdi_confinfo ci;
04552
04553 if (p->master || (p->confno > -1))
04554 return 0;
04555 memset(&ci, 0, sizeof(ci));
04556 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04557 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04558 return 0;
04559 }
04560
04561
04562
04563 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04564 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04565 return 1;
04566 }
04567 return 0;
04568 }
04569
04570
04571
04572
04573
04574
04575 static int get_alarms(struct dahdi_pvt *p)
04576 {
04577 int res;
04578 struct dahdi_spaninfo zi;
04579 struct dahdi_params params;
04580
04581 memset(&zi, 0, sizeof(zi));
04582 zi.spanno = p->span;
04583
04584 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04585 if (zi.alarms != DAHDI_ALARM_NONE)
04586 return zi.alarms;
04587 } else {
04588 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04589 return 0;
04590 }
04591
04592
04593 memset(¶ms, 0, sizeof(params));
04594 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04595 return params.chan_alarms;
04596
04597 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04598
04599 return DAHDI_ALARM_NONE;
04600 }
04601
04602 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04603 {
04604 struct dahdi_pvt *p = ast->tech_pvt;
04605 struct ast_frame *f = *dest;
04606
04607 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04608
04609 if (p->confirmanswer) {
04610 ast_debug(1, "Confirm answer on %s!\n", ast->name);
04611
04612
04613 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04614 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04615 *dest = &p->subs[index].f;
04616
04617 p->confirmanswer = 0;
04618 } else if (p->callwaitcas) {
04619 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04620 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04621 if (p->cidspill)
04622 ast_free(p->cidspill);
04623 send_cwcidspill(p);
04624 }
04625 if ((f->subclass != 'm') && (f->subclass != 'u'))
04626 p->callwaitcas = 0;
04627 p->subs[index].f.frametype = AST_FRAME_NULL;
04628 p->subs[index].f.subclass = 0;
04629 *dest = &p->subs[index].f;
04630 } else if (f->subclass == 'f') {
04631
04632 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04633 p->faxhandled = 1;
04634 if (strcmp(ast->exten, "fax")) {
04635 const char *target_context = S_OR(ast->macrocontext, ast->context);
04636
04637
04638
04639
04640
04641 ast_mutex_unlock(&p->lock);
04642 ast_channel_unlock(ast);
04643 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04644 ast_channel_lock(ast);
04645 ast_mutex_lock(&p->lock);
04646 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04647
04648 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04649 if (ast_async_goto(ast, target_context, "fax", 1))
04650 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04651 } else {
04652 ast_channel_lock(ast);
04653 ast_mutex_lock(&p->lock);
04654 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04655 }
04656 } else {
04657 ast_debug(1, "Already in a fax extension, not redirecting\n");
04658 }
04659 } else {
04660 ast_debug(1, "Fax already handled\n");
04661 }
04662 dahdi_confmute(p, 0);
04663 p->subs[index].f.frametype = AST_FRAME_NULL;
04664 p->subs[index].f.subclass = 0;
04665 *dest = &p->subs[index].f;
04666 } else if (f->subclass == 'm') {
04667
04668 dahdi_confmute(p, 1);
04669 p->subs[index].f.frametype = AST_FRAME_NULL;
04670 p->subs[index].f.subclass = 0;
04671 *dest = &p->subs[index].f;
04672 } else if (f->subclass == 'u') {
04673
04674 dahdi_confmute(p, 0);
04675 p->subs[index].f.frametype = AST_FRAME_NULL;
04676 p->subs[index].f.subclass = 0;
04677 *dest = &p->subs[index].f;
04678 } else
04679 dahdi_confmute(p, 0);
04680 }
04681
04682 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04683 {
04684 const char *alarm_str = alarm2str(alarms);
04685
04686 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04687 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04688 "Alarm: %s\r\n"
04689 "Channel: %d\r\n",
04690 alarm_str, p->channel);
04691 }
04692
04693 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04694 {
04695 int res, x;
04696 int index, mysig;
04697 char *c;
04698 struct dahdi_pvt *p = ast->tech_pvt;
04699 pthread_t threadid;
04700 struct ast_channel *chan;
04701 struct ast_frame *f;
04702
04703 index = dahdi_get_index(ast, p, 0);
04704 mysig = p->sig;
04705 if (p->outsigmod > -1)
04706 mysig = p->outsigmod;
04707 p->subs[index].f.frametype = AST_FRAME_NULL;
04708 p->subs[index].f.subclass = 0;
04709 p->subs[index].f.datalen = 0;
04710 p->subs[index].f.samples = 0;
04711 p->subs[index].f.mallocd = 0;
04712 p->subs[index].f.offset = 0;
04713 p->subs[index].f.src = "dahdi_handle_event";
04714 p->subs[index].f.data = NULL;
04715 f = &p->subs[index].f;
04716
04717 if (index < 0)
04718 return &p->subs[index].f;
04719 if (p->fake_event) {
04720 res = p->fake_event;
04721 p->fake_event = 0;
04722 } else
04723 res = dahdi_get_event(p->subs[index].dfd);
04724
04725 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04726
04727 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04728 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04729 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04730 #ifdef HAVE_PRI
04731 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04732
04733 } else {
04734 #endif
04735 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04736 p->subs[index].f.subclass = res & 0xff;
04737 #ifdef HAVE_PRI
04738 }
04739 #endif
04740 dahdi_handle_dtmfup(ast, index, &f);
04741 return f;
04742 }
04743
04744 if (res & DAHDI_EVENT_DTMFDOWN) {
04745 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04746
04747 dahdi_confmute(p, 1);
04748 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04749 p->subs[index].f.subclass = res & 0xff;
04750 return &p->subs[index].f;
04751 }
04752
04753 switch (res) {
04754 case DAHDI_EVENT_EC_DISABLED:
04755 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04756 p->echocanon = 0;
04757 break;
04758 case DAHDI_EVENT_BITSCHANGED:
04759 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04760 case DAHDI_EVENT_PULSE_START:
04761
04762 if (!ast->pbx)
04763 tone_zone_play_tone(p->subs[index].dfd, -1);
04764 break;
04765 case DAHDI_EVENT_DIALCOMPLETE:
04766 if (p->inalarm) break;
04767 if ((p->radio || (p->oprmode < 0))) break;
04768 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
04769 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04770 return NULL;
04771 }
04772 if (!x) {
04773 dahdi_enable_ec(p);
04774 if (p->echobreak) {
04775 dahdi_train_ec(p);
04776 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04777 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04778 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04779 p->echobreak = 0;
04780 } else {
04781 p->dialing = 0;
04782 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04783
04784 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04785 ast_setstate(ast, AST_STATE_UP);
04786 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04787 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04788 break;
04789 } else {
04790
04791 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04792 }
04793 }
04794 if (ast->_state == AST_STATE_DIALING) {
04795 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04796 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04797 } 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)))) {
04798 ast_setstate(ast, AST_STATE_RINGING);
04799 } else if (!p->answeronpolarityswitch) {
04800 ast_setstate(ast, AST_STATE_UP);
04801 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04802 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04803
04804 p->polarity = POLARITY_REV;
04805 } else {
04806
04807 p->polarity = POLARITY_IDLE;
04808 }
04809 }
04810 }
04811 }
04812 break;
04813 case DAHDI_EVENT_ALARM:
04814 #ifdef HAVE_PRI
04815 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04816 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04817
04818 if (p->call) {
04819 if (p->pri && p->pri->pri) {
04820 if (!pri_grab(p, p->pri)) {
04821 pri_hangup(p->pri->pri, p->call, -1);
04822 pri_destroycall(p->pri->pri, p->call);
04823 p->call = NULL;
04824 pri_rel(p->pri);
04825 } else
04826 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04827 } else
04828 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04829 }
04830 if (p->owner)
04831 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04832 }
04833 }
04834 if (p->bearer)
04835 p->bearer->inalarm = 1;
04836 else
04837 #endif
04838 p->inalarm = 1;
04839 res = get_alarms(p);
04840 handle_alarms(p, res);
04841 #ifdef HAVE_PRI
04842 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04843
04844 } else {
04845 break;
04846 }
04847 #endif
04848 #ifdef HAVE_SS7
04849 if (p->sig == SIG_SS7)
04850 break;
04851 #endif
04852 case DAHDI_EVENT_ONHOOK:
04853 if (p->radio) {
04854 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04855 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04856 break;
04857 }
04858 if (p->oprmode < 0)
04859 {
04860 if (p->oprmode != -1) break;
04861 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04862 {
04863
04864 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04865 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04866 save_conference(p->oprpeer);
04867 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04868 }
04869 break;
04870 }
04871 switch (p->sig) {
04872 case SIG_FXOLS:
04873 case SIG_FXOGS:
04874 case SIG_FXOKS:
04875 p->onhooktime = time(NULL);
04876 p->msgstate = -1;
04877
04878 if (index == SUB_REAL) {
04879
04880 if (p->subs[SUB_CALLWAIT].owner) {
04881
04882 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04883 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04884 unalloc_sub(p, SUB_CALLWAIT);
04885 #if 0
04886 p->subs[index].needanswer = 0;
04887 p->subs[index].needringing = 0;
04888 #endif
04889 p->callwaitingrepeat = 0;
04890 p->cidcwexpire = 0;
04891 p->owner = NULL;
04892
04893 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04894 p->dialing = 1;
04895 dahdi_ring_phone(p);
04896 } else if (p->subs[SUB_THREEWAY].owner) {
04897 unsigned int mssinceflash;
04898
04899
04900 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04901
04902 ast_mutex_unlock(&p->lock);
04903 ast_channel_unlock(ast);
04904 usleep(1);
04905
04906
04907
04908 ast_channel_lock(ast);
04909 ast_mutex_lock(&p->lock);
04910 if (p->owner != ast) {
04911 ast_log(LOG_WARNING, "This isn't good...\n");
04912 return NULL;
04913 }
04914 }
04915 if (!p->subs[SUB_THREEWAY].owner) {
04916 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04917 return NULL;
04918 }
04919 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04920 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04921 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04922
04923
04924 if (p->subs[SUB_THREEWAY].owner)
04925 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04926 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04927 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04928 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04929 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04930 if (p->transfer) {
04931
04932 p->subs[SUB_REAL].inthreeway = 0;
04933 p->subs[SUB_THREEWAY].inthreeway = 0;
04934
04935 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04936 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04937
04938 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04939 p->owner = NULL;
04940
04941 dahdi_ring_phone(p);
04942 } else {
04943 if ((res = attempt_transfer(p)) < 0) {
04944 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04945 if (p->subs[SUB_THREEWAY].owner)
04946 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04947 } else if (res) {
04948
04949 if (p->subs[SUB_THREEWAY].owner)
04950 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04951 break;
04952 }
04953 }
04954 } else {
04955 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04956 if (p->subs[SUB_THREEWAY].owner)
04957 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04958 }
04959 } else {
04960 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04961
04962 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04963 p->owner = NULL;
04964
04965 dahdi_ring_phone(p);
04966 }
04967 }
04968 } else {
04969 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04970 }
04971
04972 default:
04973 dahdi_disable_ec(p);
04974 return NULL;
04975 }
04976 break;
04977 case DAHDI_EVENT_RINGOFFHOOK:
04978 if (p->inalarm) break;
04979 if (p->oprmode < 0)
04980 {
04981 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04982 {
04983
04984 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04985 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04986 restore_conference(p->oprpeer);
04987 }
04988 break;
04989 }
04990 if (p->radio)
04991 {
04992 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04993 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04994 break;
04995 }
04996
04997
04998 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04999 c = strchr(p->dialdest, '/');
05000 if (c)
05001 c++;
05002 else
05003 c = p->dialdest;
05004 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05005 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05006 if (strlen(p->dop.dialstr) > 4) {
05007 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05008 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05009 p->echorest[sizeof(p->echorest) - 1] = '\0';
05010 p->echobreak = 1;
05011 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05012 } else
05013 p->echobreak = 0;
05014 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05015 int saveerr = errno;
05016
05017 x = DAHDI_ONHOOK;
05018 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05019 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05020 return NULL;
05021 }
05022 p->dialing = 1;
05023 return &p->subs[index].f;
05024 }
05025 switch (p->sig) {
05026 case SIG_FXOLS:
05027 case SIG_FXOGS:
05028 case SIG_FXOKS:
05029 switch (ast->_state) {
05030 case AST_STATE_RINGING:
05031 dahdi_enable_ec(p);
05032 dahdi_train_ec(p);
05033 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05034 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05035
05036 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05037 ast_debug(1, "channel %d answered\n", p->channel);
05038 if (p->cidspill) {
05039
05040 ast_free(p->cidspill);
05041 p->cidspill = NULL;
05042 }
05043 p->dialing = 0;
05044 p->callwaitcas = 0;
05045 if (p->confirmanswer) {
05046
05047 p->subs[index].f.frametype = AST_FRAME_NULL;
05048 p->subs[index].f.subclass = 0;
05049 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05050
05051 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05052 if (res < 0) {
05053 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05054 p->dop.dialstr[0] = '\0';
05055 return NULL;
05056 } else {
05057 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05058 p->subs[index].f.frametype = AST_FRAME_NULL;
05059 p->subs[index].f.subclass = 0;
05060 p->dialing = 1;
05061 }
05062 p->dop.dialstr[0] = '\0';
05063 ast_setstate(ast, AST_STATE_DIALING);
05064 } else
05065 ast_setstate(ast, AST_STATE_UP);
05066 return &p->subs[index].f;
05067 case AST_STATE_DOWN:
05068 ast_setstate(ast, AST_STATE_RING);
05069 ast->rings = 1;
05070 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05071 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05072 ast_debug(1, "channel %d picked up\n", p->channel);
05073 return &p->subs[index].f;
05074 case AST_STATE_UP:
05075
05076 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05077
05078 if (ast_bridged_channel(p->owner))
05079 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05080 p->subs[index].needunhold = 1;
05081 break;
05082 case AST_STATE_RESERVED:
05083
05084 if (has_voicemail(p))
05085 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05086 else
05087 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05088 break;
05089 default:
05090 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05091 }
05092 break;
05093 case SIG_FXSLS:
05094 case SIG_FXSGS:
05095 case SIG_FXSKS:
05096 if (ast->_state == AST_STATE_RING) {
05097 p->ringt = p->ringt_base;
05098 }
05099
05100
05101
05102 ast_debug(1, "Setting IDLE polarity due "
05103 "to ring. Old polarity was %d\n",
05104 p->polarity);
05105 p->polarity = POLARITY_IDLE;
05106
05107
05108 case SIG_EM:
05109 case SIG_EM_E1:
05110 case SIG_EMWINK:
05111 case SIG_FEATD:
05112 case SIG_FEATDMF:
05113 case SIG_FEATDMF_TA:
05114 case SIG_E911:
05115 case SIG_FGC_CAMA:
05116 case SIG_FGC_CAMAMF:
05117 case SIG_FEATB:
05118 case SIG_SF:
05119 case SIG_SFWINK:
05120 case SIG_SF_FEATD:
05121 case SIG_SF_FEATDMF:
05122 case SIG_SF_FEATB:
05123 if (ast->_state == AST_STATE_PRERING)
05124 ast_setstate(ast, AST_STATE_RING);
05125 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05126 ast_debug(1, "Ring detected\n");
05127 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05128 p->subs[index].f.subclass = AST_CONTROL_RING;
05129 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05130 ast_debug(1, "Line answered\n");
05131 if (p->confirmanswer) {
05132 p->subs[index].f.frametype = AST_FRAME_NULL;
05133 p->subs[index].f.subclass = 0;
05134 } else {
05135 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05136 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05137 ast_setstate(ast, AST_STATE_UP);
05138 }
05139 } else if (ast->_state != AST_STATE_RING)
05140 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05141 break;
05142 default:
05143 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05144 }
05145 break;
05146 case DAHDI_EVENT_RINGBEGIN:
05147 switch (p->sig) {
05148 case SIG_FXSLS:
05149 case SIG_FXSGS:
05150 case SIG_FXSKS:
05151 if (ast->_state == AST_STATE_RING) {
05152 p->ringt = p->ringt_base;
05153 }
05154 break;
05155 }
05156 break;
05157 case DAHDI_EVENT_RINGEROFF:
05158 if (p->inalarm) break;
05159 if ((p->radio || (p->oprmode < 0))) break;
05160 ast->rings++;
05161 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05162 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05163 ast_free(p->cidspill);
05164 p->cidspill = NULL;
05165 p->callwaitcas = 0;
05166 }
05167 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05168 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05169 break;
05170 case DAHDI_EVENT_RINGERON:
05171 break;
05172 case DAHDI_EVENT_NOALARM:
05173 p->inalarm = 0;
05174 #ifdef HAVE_PRI
05175
05176 if (p->bearer)
05177 p->bearer->inalarm = 0;
05178 #endif
05179 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05180 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05181 "Channel: %d\r\n", p->channel);
05182 break;
05183 case DAHDI_EVENT_WINKFLASH:
05184 if (p->inalarm) break;
05185 if (p->radio) break;
05186 if (p->oprmode < 0) break;
05187 if (p->oprmode > 1)
05188 {
05189 struct dahdi_params par;
05190
05191 memset(&par, 0, sizeof(par));
05192 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05193 {
05194 if (!par.rxisoffhook)
05195 {
05196
05197 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05198 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05199 save_conference(p);
05200 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05201 }
05202 }
05203 break;
05204 }
05205
05206 p->flashtime = ast_tvnow();
05207 switch (mysig) {
05208 case SIG_FXOLS:
05209 case SIG_FXOGS:
05210 case SIG_FXOKS:
05211 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05212 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05213 p->callwaitcas = 0;
05214
05215 if (index != SUB_REAL) {
05216 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05217 goto winkflashdone;
05218 }
05219
05220 if (p->subs[SUB_CALLWAIT].owner) {
05221
05222 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05223 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05224 p->owner = p->subs[SUB_REAL].owner;
05225 ast_debug(1, "Making %s the new owner\n", p->owner->name);
05226 if (p->owner->_state == AST_STATE_RINGING) {
05227 ast_setstate(p->owner, AST_STATE_UP);
05228 p->subs[SUB_REAL].needanswer = 1;
05229 }
05230 p->callwaitingrepeat = 0;
05231 p->cidcwexpire = 0;
05232
05233 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05234 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05235 S_OR(p->mohsuggest, NULL),
05236 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05237 }
05238 p->subs[SUB_CALLWAIT].needhold = 1;
05239 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05240 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05241 S_OR(p->mohsuggest, NULL),
05242 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05243 }
05244 p->subs[SUB_REAL].needunhold = 1;
05245 } else if (!p->subs[SUB_THREEWAY].owner) {
05246 if (!p->threewaycalling) {
05247
05248 p->subs[SUB_REAL].needflash = 1;
05249 goto winkflashdone;
05250 } else if (!check_for_conference(p)) {
05251 char cid_num[256];
05252 char cid_name[256];
05253
05254 cid_num[0] = 0;
05255 cid_name[0] = 0;
05256 if (p->dahditrcallerid && p->owner) {
05257 if (p->owner->cid.cid_num)
05258 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05259 if (p->owner->cid.cid_name)
05260 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05261 }
05262
05263
05264 if (!((ast->pbx) ||
05265 (ast->_state == AST_STATE_UP) ||
05266 (ast->_state == AST_STATE_RING))) {
05267 ast_debug(1, "Flash when call not up or ringing\n");
05268 goto winkflashdone;
05269 }
05270 if (alloc_sub(p, SUB_THREEWAY)) {
05271 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05272 goto winkflashdone;
05273 }
05274
05275 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05276 if (p->dahditrcallerid) {
05277 if (!p->origcid_num)
05278 p->origcid_num = ast_strdup(p->cid_num);
05279 if (!p->origcid_name)
05280 p->origcid_name = ast_strdup(p->cid_name);
05281 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05282 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05283 }
05284
05285 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05286
05287 dahdi_disable_ec(p);
05288 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05289 if (res)
05290 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05291 p->owner = chan;
05292 if (!chan) {
05293 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05294 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05295 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05296 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05297 dahdi_enable_ec(p);
05298 ast_hangup(chan);
05299 } else {
05300 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05301 int way3bridge = 0, cdr3way = 0;
05302
05303 if (!other) {
05304 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05305 } else
05306 way3bridge = 1;
05307
05308 if (p->subs[SUB_THREEWAY].owner->cdr)
05309 cdr3way = 1;
05310
05311 ast_verb(3, "Started three way call on channel %d\n", p->channel);
05312
05313
05314 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05315 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05316 S_OR(p->mohsuggest, NULL),
05317 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05318 }
05319 p->subs[SUB_THREEWAY].needhold = 1;
05320 }
05321 }
05322 } else {
05323
05324 if (p->subs[SUB_THREEWAY].inthreeway) {
05325
05326 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05327
05328 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05329
05330 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05331 p->owner = p->subs[SUB_REAL].owner;
05332 }
05333
05334 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05335 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05336 p->subs[SUB_REAL].inthreeway = 0;
05337 p->subs[SUB_THREEWAY].inthreeway = 0;
05338 } else {
05339
05340 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05341 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05342 int otherindex = SUB_THREEWAY;
05343 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05344 int way3bridge = 0, cdr3way = 0;
05345
05346 if (!other) {
05347 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05348 } else
05349 way3bridge = 1;
05350
05351 if (p->subs[SUB_THREEWAY].owner->cdr)
05352 cdr3way = 1;
05353
05354 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05355
05356 p->subs[SUB_THREEWAY].inthreeway = 1;
05357 p->subs[SUB_REAL].inthreeway = 1;
05358 if (ast->_state == AST_STATE_UP) {
05359 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05360 otherindex = SUB_REAL;
05361 }
05362 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05363 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05364 p->subs[otherindex].needunhold = 1;
05365 p->owner = p->subs[SUB_REAL].owner;
05366 if (ast->_state == AST_STATE_RINGING) {
05367 ast_debug(1, "Enabling ringtone on real and threeway\n");
05368 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05369 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05370 }
05371 } else {
05372 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05373 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05374 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05375 p->owner = p->subs[SUB_REAL].owner;
05376 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05377 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05378 p->subs[SUB_REAL].needunhold = 1;
05379 dahdi_enable_ec(p);
05380 }
05381
05382 }
05383 }
05384 winkflashdone:
05385 update_conf(p);
05386 break;
05387 case SIG_EM:
05388 case SIG_EM_E1:
05389 case SIG_EMWINK:
05390 case SIG_FEATD:
05391 case SIG_SF:
05392 case SIG_SFWINK:
05393 case SIG_SF_FEATD:
05394 case SIG_FXSLS:
05395 case SIG_FXSGS:
05396 if (option_debug) {
05397 if (p->dialing)
05398 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05399 else
05400 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05401 }
05402 break;
05403 case SIG_FEATDMF_TA:
05404 switch (p->whichwink) {
05405 case 0:
05406 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05407 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05408 break;
05409 case 1:
05410 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05411 break;
05412 case 2:
05413 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05414 return NULL;
05415 }
05416 p->whichwink++;
05417
05418 case SIG_FEATDMF:
05419 case SIG_E911:
05420 case SIG_FGC_CAMAMF:
05421 case SIG_FGC_CAMA:
05422 case SIG_FEATB:
05423 case SIG_SF_FEATDMF:
05424 case SIG_SF_FEATB:
05425
05426 if (!ast_strlen_zero(p->dop.dialstr)) {
05427 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05428 if (res < 0) {
05429 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05430 p->dop.dialstr[0] = '\0';
05431 return NULL;
05432 } else
05433 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05434 }
05435 p->dop.dialstr[0] = '\0';
05436 break;
05437 default:
05438 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
05439 }
05440 break;
05441 case DAHDI_EVENT_HOOKCOMPLETE:
05442 if (p->inalarm) break;
05443 if ((p->radio || (p->oprmode < 0))) break;
05444 switch (mysig) {
05445 case SIG_FXSLS:
05446 case SIG_FXSGS:
05447 case SIG_FXSKS:
05448 case SIG_EM:
05449 case SIG_EM_E1:
05450 case SIG_EMWINK:
05451 case SIG_FEATD:
05452 case SIG_SF:
05453 case SIG_SFWINK:
05454 case SIG_SF_FEATD:
05455 if (!ast_strlen_zero(p->dop.dialstr)) {
05456 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05457 if (res < 0) {
05458 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05459 p->dop.dialstr[0] = '\0';
05460 return NULL;
05461 } else
05462 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05463 }
05464 p->dop.dialstr[0] = '\0';
05465 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05466 break;
05467 case SIG_FEATDMF:
05468 case SIG_FEATDMF_TA:
05469 case SIG_E911:
05470 case SIG_FGC_CAMA:
05471 case SIG_FGC_CAMAMF:
05472 case SIG_FEATB:
05473 case SIG_SF_FEATDMF:
05474 case SIG_SF_FEATB:
05475 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05476 break;
05477 default:
05478 break;
05479 }
05480 break;
05481 case DAHDI_EVENT_POLARITY:
05482
05483
05484
05485
05486
05487
05488 if (p->polarity == POLARITY_IDLE) {
05489 p->polarity = POLARITY_REV;
05490 if (p->answeronpolarityswitch &&
05491 ((ast->_state == AST_STATE_DIALING) ||
05492 (ast->_state == AST_STATE_RINGING))) {
05493 ast_debug(1, "Answering on polarity switch!\n");
05494 ast_setstate(p->owner, AST_STATE_UP);
05495 if (p->hanguponpolarityswitch) {
05496 p->polaritydelaytv = ast_tvnow();
05497 }
05498 } else
05499 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
05500
05501 }
05502
05503
05504 if (p->hanguponpolarityswitch &&
05505 (p->polarityonanswerdelay > 0) &&
05506 (p->polarity == POLARITY_REV) &&
05507 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
05508
05509 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
05510
05511 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05512 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
05513 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05514 p->polarity = POLARITY_IDLE;
05515 } else
05516 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
05517
05518 } else {
05519 p->polarity = POLARITY_IDLE;
05520 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
05521 }
05522
05523 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) );
05524 break;
05525 default:
05526 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05527 }
05528 return &p->subs[index].f;
05529 }
05530
05531 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05532 {
05533 struct dahdi_pvt *p = ast->tech_pvt;
05534 int res;
05535 int usedindex=-1;
05536 int index;
05537 struct ast_frame *f;
05538
05539
05540 index = dahdi_get_index(ast, p, 1);
05541
05542 p->subs[index].f.frametype = AST_FRAME_NULL;
05543 p->subs[index].f.datalen = 0;
05544 p->subs[index].f.samples = 0;
05545 p->subs[index].f.mallocd = 0;
05546 p->subs[index].f.offset = 0;
05547 p->subs[index].f.subclass = 0;
05548 p->subs[index].f.delivery = ast_tv(0,0);
05549 p->subs[index].f.src = "dahdi_exception";
05550 p->subs[index].f.data = NULL;
05551
05552
05553 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05554
05555
05556
05557
05558
05559 if (p->fake_event) {
05560 res = p->fake_event;
05561 p->fake_event = 0;
05562 } else
05563 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05564
05565 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05566 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05567 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05568 p->owner = p->subs[SUB_REAL].owner;
05569 if (p->owner && ast_bridged_channel(p->owner))
05570 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05571 p->subs[SUB_REAL].needunhold = 1;
05572 }
05573 switch (res) {
05574 case DAHDI_EVENT_ONHOOK:
05575 dahdi_disable_ec(p);
05576 if (p->owner) {
05577 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05578 dahdi_ring_phone(p);
05579 p->callwaitingrepeat = 0;
05580 p->cidcwexpire = 0;
05581 } else
05582 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05583 update_conf(p);
05584 break;
05585 case DAHDI_EVENT_RINGOFFHOOK:
05586 dahdi_enable_ec(p);
05587 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05588 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05589 p->subs[SUB_REAL].needanswer = 1;
05590 p->dialing = 0;
05591 }
05592 break;
05593 case DAHDI_EVENT_HOOKCOMPLETE:
05594 case DAHDI_EVENT_RINGERON:
05595 case DAHDI_EVENT_RINGEROFF:
05596
05597 break;
05598 case DAHDI_EVENT_WINKFLASH:
05599 p->flashtime = ast_tvnow();
05600 if (p->owner) {
05601 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05602 if (p->owner->_state != AST_STATE_UP) {
05603
05604 usedindex = dahdi_get_index(p->owner, p, 0);
05605 if (usedindex > -1) {
05606 p->subs[usedindex].needanswer = 1;
05607 }
05608 ast_setstate(p->owner, AST_STATE_UP);
05609 }
05610 p->callwaitingrepeat = 0;
05611 p->cidcwexpire = 0;
05612 if (ast_bridged_channel(p->owner))
05613 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05614 p->subs[SUB_REAL].needunhold = 1;
05615 } else
05616 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05617 update_conf(p);
05618 break;
05619 default:
05620 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05621 }
05622 f = &p->subs[index].f;
05623 return f;
05624 }
05625 if (!(p->radio || (p->oprmode < 0)))
05626 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05627
05628 if (ast != p->owner) {
05629 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05630 f = &p->subs[index].f;
05631 return f;
05632 }
05633 f = dahdi_handle_event(ast);
05634 return f;
05635 }
05636
05637 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05638 {
05639 struct dahdi_pvt *p = ast->tech_pvt;
05640 struct ast_frame *f;
05641 ast_mutex_lock(&p->lock);
05642 f = __dahdi_exception(ast);
05643 ast_mutex_unlock(&p->lock);
05644 return f;
05645 }
05646
05647 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05648 {
05649 struct dahdi_pvt *p = ast->tech_pvt;
05650 int res;
05651 int index;
05652 void *readbuf;
05653 struct ast_frame *f;
05654
05655 while (ast_mutex_trylock(&p->lock)) {
05656 CHANNEL_DEADLOCK_AVOIDANCE(ast);
05657 }
05658
05659 index = dahdi_get_index(ast, p, 0);
05660
05661
05662 if (index < 0) {
05663 ast_log(LOG_WARNING, "We dont exist?\n");
05664 ast_mutex_unlock(&p->lock);
05665 return NULL;
05666 }
05667
05668 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
05669
05670 p->subs[index].f.frametype = AST_FRAME_NULL;
05671 p->subs[index].f.datalen = 0;
05672 p->subs[index].f.samples = 0;
05673 p->subs[index].f.mallocd = 0;
05674 p->subs[index].f.offset = 0;
05675 p->subs[index].f.subclass = 0;
05676 p->subs[index].f.delivery = ast_tv(0,0);
05677 p->subs[index].f.src = "dahdi_read";
05678 p->subs[index].f.data = NULL;
05679
05680
05681 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05682 {
05683 struct dahdi_params ps;
05684
05685 memset(&ps, 0, sizeof(ps));
05686 ps.channo = p->channel;
05687 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05688 ast_mutex_unlock(&p->lock);
05689 return NULL;
05690 }
05691 p->firstradio = 1;
05692 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05693 if (ps.rxisoffhook)
05694 {
05695 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05696 }
05697 else
05698 {
05699 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05700 }
05701 ast_mutex_unlock(&p->lock);
05702 return &p->subs[index].f;
05703 }
05704 if (p->ringt == 1) {
05705 ast_mutex_unlock(&p->lock);
05706 return NULL;
05707 }
05708 else if (p->ringt > 0)
05709 p->ringt--;
05710
05711 if (p->subs[index].needringing) {
05712
05713 p->subs[index].needringing = 0;
05714 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05715 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05716 ast_setstate(ast, AST_STATE_RINGING);
05717 ast_mutex_unlock(&p->lock);
05718 return &p->subs[index].f;
05719 }
05720
05721 if (p->subs[index].needbusy) {
05722
05723 p->subs[index].needbusy = 0;
05724 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05725 p->subs[index].f.subclass = AST_CONTROL_BUSY;
05726 ast_mutex_unlock(&p->lock);
05727 return &p->subs[index].f;
05728 }
05729
05730 if (p->subs[index].needcongestion) {
05731
05732 p->subs[index].needcongestion = 0;
05733 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05734 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
05735 ast_mutex_unlock(&p->lock);
05736 return &p->subs[index].f;
05737 }
05738
05739 if (p->subs[index].needcallerid) {
05740 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05741 S_OR(p->lastcid_name, NULL),
05742 S_OR(p->lastcid_num, NULL)
05743 );
05744 p->subs[index].needcallerid = 0;
05745 }
05746
05747 if (p->subs[index].needanswer) {
05748
05749 p->subs[index].needanswer = 0;
05750 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05751 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05752 ast_mutex_unlock(&p->lock);
05753 return &p->subs[index].f;
05754 }
05755
05756 if (p->subs[index].needflash) {
05757
05758 p->subs[index].needflash = 0;
05759 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05760 p->subs[index].f.subclass = AST_CONTROL_FLASH;
05761 ast_mutex_unlock(&p->lock);
05762 return &p->subs[index].f;
05763 }
05764
05765 if (p->subs[index].needhold) {
05766
05767 p->subs[index].needhold = 0;
05768 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05769 p->subs[index].f.subclass = AST_CONTROL_HOLD;
05770 ast_mutex_unlock(&p->lock);
05771 ast_debug(1, "Sending hold on '%s'\n", ast->name);
05772 return &p->subs[index].f;
05773 }
05774
05775 if (p->subs[index].needunhold) {
05776
05777 p->subs[index].needunhold = 0;
05778 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05779 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
05780 ast_mutex_unlock(&p->lock);
05781 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05782 return &p->subs[index].f;
05783 }
05784
05785 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05786 if (!p->subs[index].linear) {
05787 p->subs[index].linear = 1;
05788 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05789 if (res)
05790 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
05791 }
05792 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05793 (ast->rawreadformat == AST_FORMAT_ALAW)) {
05794 if (p->subs[index].linear) {
05795 p->subs[index].linear = 0;
05796 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05797 if (res)
05798 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
05799 }
05800 } else {
05801 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05802 ast_mutex_unlock(&p->lock);
05803 return NULL;
05804 }
05805 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
05806 CHECK_BLOCKING(ast);
05807 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05808 ast_clear_flag(ast, AST_FLAG_BLOCKING);
05809
05810 if (res < 0) {
05811 f = NULL;
05812 if (res == -1) {
05813 if (errno == EAGAIN) {
05814
05815 ast_mutex_unlock(&p->lock);
05816 return &p->subs[index].f;
05817 } else if (errno == ELAST) {
05818 f = __dahdi_exception(ast);
05819 } else
05820 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05821 }
05822 ast_mutex_unlock(&p->lock);
05823 return f;
05824 }
05825 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
05826 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05827 f = __dahdi_exception(ast);
05828 ast_mutex_unlock(&p->lock);
05829 return f;
05830 }
05831 if (p->tdd) {
05832 int c;
05833
05834 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05835 if (c < 0) {
05836 ast_debug(1,"tdd_feed failed\n");
05837 ast_mutex_unlock(&p->lock);
05838 return NULL;
05839 }
05840 if (c) {
05841 p->subs[index].f.subclass = 0;
05842 p->subs[index].f.frametype = AST_FRAME_TEXT;
05843 p->subs[index].f.mallocd = 0;
05844 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05845 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
05846 p->subs[index].f.datalen = 1;
05847 *((char *) p->subs[index].f.data) = c;
05848 ast_mutex_unlock(&p->lock);
05849 return &p->subs[index].f;
05850 }
05851 }
05852
05853 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05854 p->callwaitingrepeat--;
05855 }
05856 if (p->cidcwexpire)
05857 p->cidcwexpire--;
05858
05859 if (p->callwaitingrepeat == 1) {
05860 p->callwaitrings++;
05861 dahdi_callwait(ast);
05862 }
05863
05864 if (p->cidcwexpire == 1) {
05865 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05866 restore_conference(p);
05867 }
05868 if (p->subs[index].linear) {
05869 p->subs[index].f.datalen = READ_SIZE * 2;
05870 } else
05871 p->subs[index].f.datalen = READ_SIZE;
05872
05873
05874 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05875 send_callerid(p);
05876 }
05877
05878 p->subs[index].f.frametype = AST_FRAME_VOICE;
05879 p->subs[index].f.subclass = ast->rawreadformat;
05880 p->subs[index].f.samples = READ_SIZE;
05881 p->subs[index].f.mallocd = 0;
05882 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05883 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
05884 #if 0
05885 ast_debug(1, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
05886 #endif
05887 if (p->dialing ||
05888 (index && (ast->_state != AST_STATE_UP)) ||
05889 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05890 ) {
05891
05892
05893 p->subs[index].f.frametype = AST_FRAME_NULL;
05894 p->subs[index].f.subclass = 0;
05895 p->subs[index].f.samples = 0;
05896 p->subs[index].f.mallocd = 0;
05897 p->subs[index].f.offset = 0;
05898 p->subs[index].f.data = NULL;
05899 p->subs[index].f.datalen= 0;
05900 }
05901 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
05902
05903 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05904 if (f) {
05905 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05906 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05907
05908
05909 f = NULL;
05910 }
05911 } else if (f->frametype == AST_FRAME_DTMF) {
05912 #ifdef HAVE_PRI
05913 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
05914 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05915 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05916
05917 f->frametype = AST_FRAME_NULL;
05918 f->subclass = 0;
05919 }
05920 #endif
05921
05922 p->pulsedial = 0;
05923 }
05924 }
05925 } else
05926 f = &p->subs[index].f;
05927
05928 if (f && (f->frametype == AST_FRAME_DTMF))
05929 dahdi_handle_dtmfup(ast, index, &f);
05930
05931
05932 if (p->fake_event)
05933 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05934
05935 ast_mutex_unlock(&p->lock);
05936 return f;
05937 }
05938
05939 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
05940 {
05941 int sent=0;
05942 int size;
05943 int res;
05944 int fd;
05945 fd = p->subs[index].dfd;
05946 while (len) {
05947 size = len;
05948 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05949 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05950 res = write(fd, buf, size);
05951 if (res != size) {
05952 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05953 return sent;
05954 }
05955 len -= size;
05956 buf += size;
05957 }
05958 return sent;
05959 }
05960
05961 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05962 {
05963 struct dahdi_pvt *p = ast->tech_pvt;
05964 int res;
05965 int index;
05966 index = dahdi_get_index(ast, p, 0);
05967 if (index < 0) {
05968 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05969 return -1;
05970 }
05971
05972 #if 0
05973 #ifdef HAVE_PRI
05974 ast_mutex_lock(&p->lock);
05975 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05976 if (p->pri->pri) {
05977 if (!pri_grab(p, p->pri)) {
05978 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05979 pri_rel(p->pri);
05980 } else
05981 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05982 }
05983 p->proceeding=1;
05984 }
05985 ast_mutex_unlock(&p->lock);
05986 #endif
05987 #endif
05988
05989 if (frame->frametype != AST_FRAME_VOICE) {
05990 if (frame->frametype != AST_FRAME_IMAGE)
05991 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05992 return 0;
05993 }
05994 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
05995 (frame->subclass != AST_FORMAT_ULAW) &&
05996 (frame->subclass != AST_FORMAT_ALAW)) {
05997 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05998 return -1;
05999 }
06000 if (p->dialing) {
06001 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06002 return 0;
06003 }
06004 if (!p->owner) {
06005 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06006 return 0;
06007 }
06008 if (p->cidspill) {
06009 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06010 return 0;
06011 }
06012
06013 if (!frame->data || !frame->datalen)
06014 return 0;
06015
06016 if (frame->subclass == AST_FORMAT_SLINEAR) {
06017 if (!p->subs[index].linear) {
06018 p->subs[index].linear = 1;
06019 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06020 if (res)
06021 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06022 }
06023 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06024 } else {
06025
06026 if (p->subs[index].linear) {
06027 p->subs[index].linear = 0;
06028 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06029 if (res)
06030 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06031 }
06032 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06033 }
06034 if (res < 0) {
06035 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06036 return -1;
06037 }
06038 return 0;
06039 }
06040
06041 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06042 {
06043 struct dahdi_pvt *p = chan->tech_pvt;
06044 int res=-1;
06045 int index;
06046 int func = DAHDI_FLASH;
06047 ast_mutex_lock(&p->lock);
06048 index = dahdi_get_index(chan, p, 0);
06049 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06050 if (index == SUB_REAL) {
06051 switch (condition) {
06052 case AST_CONTROL_BUSY:
06053 #ifdef HAVE_PRI
06054 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06055 chan->hangupcause = AST_CAUSE_USER_BUSY;
06056 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06057 res = 0;
06058 } else if (!p->progress &&
06059 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06060 && p->pri && !p->outgoing) {
06061 if (p->pri->pri) {
06062 if (!pri_grab(p, p->pri)) {
06063 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06064 pri_rel(p->pri);
06065 }
06066 else
06067 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06068 }
06069 p->progress = 1;
06070 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06071 } else
06072 #endif
06073 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06074 break;
06075 case AST_CONTROL_RINGING:
06076 #ifdef HAVE_PRI
06077 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06078 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06079 if (p->pri->pri) {
06080 if (!pri_grab(p, p->pri)) {
06081 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06082 pri_rel(p->pri);
06083 }
06084 else
06085 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06086 }
06087 p->alerting = 1;
06088 }
06089
06090 #endif
06091 #ifdef HAVE_SS7
06092 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06093 if (p->ss7->ss7) {
06094 ss7_grab(p, p->ss7);
06095
06096 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06097 p->rlt = 1;
06098 if (p->rlt != 1)
06099 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06100 p->alerting = 1;
06101 ss7_rel(p->ss7);
06102 }
06103 }
06104 #endif
06105
06106 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06107
06108 if (chan->_state != AST_STATE_UP) {
06109 if ((chan->_state != AST_STATE_RING) ||
06110 ((p->sig != SIG_FXSKS) &&
06111 (p->sig != SIG_FXSLS) &&
06112 (p->sig != SIG_FXSGS)))
06113 ast_setstate(chan, AST_STATE_RINGING);
06114 }
06115 break;
06116 case AST_CONTROL_PROCEEDING:
06117 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06118 #ifdef HAVE_PRI
06119 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06120 && p->pri && !p->outgoing) {
06121 if (p->pri->pri) {
06122 if (!pri_grab(p, p->pri)) {
06123 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06124 pri_rel(p->pri);
06125 }
06126 else
06127 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06128 }
06129 p->proceeding = 1;
06130 p->dialing = 0;
06131 }
06132 #endif
06133 #ifdef HAVE_SS7
06134
06135 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
06136 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06137 p->rlt = 1;
06138 }
06139
06140 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
06141 if (p->ss7->ss7) {
06142 ss7_grab(p, p->ss7);
06143 isup_acm(p->ss7->ss7, p->ss7call);
06144 p->proceeding = 1;
06145 ss7_rel(p->ss7);
06146
06147 }
06148 }
06149 #endif
06150
06151 res = 0;
06152 break;
06153 case AST_CONTROL_PROGRESS:
06154 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06155 #ifdef HAVE_PRI
06156 p->digital = 0;
06157 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06158 && p->pri && !p->outgoing) {
06159 if (p->pri->pri) {
06160 if (!pri_grab(p, p->pri)) {
06161 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06162 pri_rel(p->pri);
06163 }
06164 else
06165 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06166 }
06167 p->progress = 1;
06168 }
06169 #endif
06170 #ifdef HAVE_SS7
06171 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
06172 if (p->ss7->ss7) {
06173 ss7_grab(p, p->ss7);
06174 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
06175 p->progress = 1;
06176 ss7_rel(p->ss7);
06177
06178 dahdi_enable_ec(p);
06179
06180 }
06181 }
06182 #endif
06183
06184 res = 0;
06185 break;
06186 case AST_CONTROL_CONGESTION:
06187 chan->hangupcause = AST_CAUSE_CONGESTION;
06188 #ifdef HAVE_PRI
06189 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06190 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06191 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06192 res = 0;
06193 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06194 && p->pri && !p->outgoing) {
06195 if (p->pri) {
06196 if (!pri_grab(p, p->pri)) {
06197 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06198 pri_rel(p->pri);
06199 } else
06200 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06201 }
06202 p->progress = 1;
06203 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06204 } else
06205 #endif
06206 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06207 break;
06208 case AST_CONTROL_HOLD:
06209 #ifdef HAVE_PRI
06210 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06211 if (!pri_grab(p, p->pri)) {
06212 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06213 pri_rel(p->pri);
06214 } else
06215 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06216 } else
06217 #endif
06218 ast_moh_start(chan, data, p->mohinterpret);
06219 break;
06220 case AST_CONTROL_UNHOLD:
06221 #ifdef HAVE_PRI
06222 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06223 if (!pri_grab(p, p->pri)) {
06224 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06225 pri_rel(p->pri);
06226 } else
06227 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06228 } else
06229 #endif
06230 ast_moh_stop(chan);
06231 break;
06232 case AST_CONTROL_RADIO_KEY:
06233 if (p->radio)
06234 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06235 res = 0;
06236 break;
06237 case AST_CONTROL_RADIO_UNKEY:
06238 if (p->radio)
06239 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06240 res = 0;
06241 break;
06242 case AST_CONTROL_FLASH:
06243
06244 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06245
06246 p->dop.dialstr[0] = '\0';
06247 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06248 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06249 chan->name, strerror(errno));
06250 } else
06251 res = 0;
06252 } else
06253 res = 0;
06254 break;
06255 case AST_CONTROL_SRCUPDATE:
06256 res = 0;
06257 break;
06258 case -1:
06259 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06260 break;
06261 }
06262 } else
06263 res = 0;
06264 ast_mutex_unlock(&p->lock);
06265 return res;
06266 }
06267
06268 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
06269 {
06270 struct ast_channel *tmp;
06271 int deflaw;
06272 int res;
06273 int x,y;
06274 int features;
06275 struct ast_str *chan_name;
06276 struct ast_variable *v;
06277 struct dahdi_params ps;
06278 if (i->subs[index].owner) {
06279 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
06280 return NULL;
06281 }
06282 y = 1;
06283 chan_name = ast_str_alloca(32);
06284 do {
06285 #ifdef HAVE_PRI
06286 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06287 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06288 else
06289 #endif
06290 if (i->channel == CHAN_PSEUDO)
06291 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
06292 else
06293 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
06294 for (x = 0; x < 3; x++) {
06295 if ((index != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
06296 break;
06297 }
06298 y++;
06299 } while (x < 3);
06300 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);
06301 if (!tmp)
06302 return NULL;
06303 tmp->tech = &dahdi_tech;
06304 memset(&ps, 0, sizeof(ps));
06305 ps.channo = i->channel;
06306 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06307 if (res) {
06308 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06309 ps.curlaw = DAHDI_LAW_MULAW;
06310 }
06311 if (ps.curlaw == DAHDI_LAW_ALAW)
06312 deflaw = AST_FORMAT_ALAW;
06313 else
06314 deflaw = AST_FORMAT_ULAW;
06315 if (law) {
06316 if (law == DAHDI_LAW_ALAW)
06317 deflaw = AST_FORMAT_ALAW;
06318 else
06319 deflaw = AST_FORMAT_ULAW;
06320 }
06321 ast_channel_set_fd(tmp, 0, i->subs[index].dfd);
06322 tmp->nativeformats = deflaw;
06323
06324 tmp->rawreadformat = deflaw;
06325 tmp->readformat = deflaw;
06326 tmp->rawwriteformat = deflaw;
06327 tmp->writeformat = deflaw;
06328 i->subs[index].linear = 0;
06329 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
06330 features = 0;
06331 if (index == SUB_REAL) {
06332 if (i->busydetect && CANBUSYDETECT(i))
06333 features |= DSP_FEATURE_BUSY_DETECT;
06334 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
06335 features |= DSP_FEATURE_CALL_PROGRESS;
06336 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
06337 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
06338 features |= DSP_FEATURE_FAX_DETECT;
06339 }
06340 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06341 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
06342 i->hardwaredtmf = 0;
06343 features |= DSP_FEATURE_DTMF_DETECT;
06344 } else if (NEED_MFDETECT(i)) {
06345 i->hardwaredtmf = 1;
06346 features |= DSP_FEATURE_DTMF_DETECT;
06347 }
06348 }
06349 if (features) {
06350 if (i->dsp) {
06351 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
06352 } else {
06353 if (i->channel != CHAN_PSEUDO)
06354 i->dsp = ast_dsp_new();
06355 else
06356 i->dsp = NULL;
06357 if (i->dsp) {
06358 i->dsp_features = features;
06359 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06360
06361 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
06362
06363
06364 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06365 features = 0;
06366 }
06367 #endif
06368 ast_dsp_set_features(i->dsp, features);
06369 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06370 if (!ast_strlen_zero(progzone))
06371 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06372 if (i->busydetect && CANBUSYDETECT(i)) {
06373 if(i->silencethreshold > 0)
06374 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06375 ast_dsp_set_busy_count(i->dsp, i->busycount);
06376 if(i->busytonelength > 0)
06377 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06378 if((i->busytonelength == i->busyquietlength) && i->busycompare)
06379 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06380 }
06381 }
06382 }
06383 }
06384
06385 if (state == AST_STATE_RING)
06386 tmp->rings = 1;
06387 tmp->tech_pvt = i;
06388 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06389
06390 tmp->callgroup = i->callgroup;
06391 tmp->pickupgroup = i->pickupgroup;
06392 }
06393 if (!ast_strlen_zero(i->language))
06394 ast_string_field_set(tmp, language, i->language);
06395 if (!i->owner)
06396 i->owner = tmp;
06397 if (!ast_strlen_zero(i->accountcode))
06398 ast_string_field_set(tmp, accountcode, i->accountcode);
06399 if (i->amaflags)
06400 tmp->amaflags = i->amaflags;
06401 i->subs[index].owner = tmp;
06402 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06403 ast_string_field_set(tmp, call_forward, i->call_forward);
06404
06405 if (!i->adsi)
06406 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06407 if (!ast_strlen_zero(i->exten))
06408 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06409 if (!ast_strlen_zero(i->rdnis))
06410 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06411 if (!ast_strlen_zero(i->dnid))
06412 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06413
06414
06415
06416 #ifdef PRI_ANI
06417 if (!ast_strlen_zero(i->cid_ani))
06418 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06419 else
06420 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06421 #else
06422 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06423 #endif
06424 tmp->cid.cid_pres = i->callingpres;
06425 tmp->cid.cid_ton = i->cid_ton;
06426 tmp->cid.cid_ani2 = i->cid_ani2;
06427 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06428 tmp->transfercapability = transfercapability;
06429 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06430 if (transfercapability & AST_TRANS_CAP_DIGITAL)
06431 i->digital = 1;
06432
06433 i->isidlecall = 0;
06434 i->alreadyhungup = 0;
06435 #endif
06436
06437 i->fake_event = 0;
06438
06439 dahdi_confmute(i, 0);
06440
06441 ast_jb_configure(tmp, &global_jbconf);
06442
06443 ast_device_state_changed_literal(tmp->name);
06444
06445 for (v = i->vars ; v ; v = v->next)
06446 pbx_builtin_setvar_helper(tmp, v->name, v->value);
06447
06448 if (startpbx) {
06449 if (ast_pbx_start(tmp)) {
06450 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06451 ast_hangup(tmp);
06452 i->owner = NULL;
06453 return NULL;
06454 }
06455 }
06456
06457 ast_module_ref(ast_module_info->self);
06458 return tmp;
06459 }
06460
06461
06462 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06463 {
06464 char c;
06465
06466 *str = 0;
06467 for (;;)
06468 {
06469
06470 c = ast_waitfordigit(chan, ms);
06471
06472 if (c < 1)
06473 return c;
06474 *str++ = c;
06475 *str = 0;
06476 if (strchr(term, c))
06477 return 1;
06478 }
06479 }
06480
06481 static int dahdi_wink(struct dahdi_pvt *p, int index)
06482 {
06483 int j;
06484 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06485 for (;;)
06486 {
06487
06488 j = DAHDI_IOMUX_SIGEVENT;
06489
06490 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06491
06492 if (j & DAHDI_IOMUX_SIGEVENT) break;
06493 }
06494
06495 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06496 return 0;
06497 }
06498
06499
06500
06501
06502
06503
06504
06505
06506
06507
06508 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
06509 {
06510
06511 dahdichan->dnd = on;
06512 ast_verb(3, "%s DND on channel %d\n",
06513 on? "Enabled" : "Disabled",
06514 dahdichan->channel);
06515 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06516 "Channel: DAHDI/%d\r\n"
06517 "Status: %s\r\n", dahdichan->channel,
06518 on? "enabled" : "disabled");
06519 }
06520
06521 static void *ss_thread(void *data)
06522 {
06523 struct ast_channel *chan = data;
06524 struct dahdi_pvt *p = chan->tech_pvt;
06525 char exten[AST_MAX_EXTENSION] = "";
06526 char exten2[AST_MAX_EXTENSION] = "";
06527 unsigned char buf[256];
06528 char dtmfcid[300];
06529 char dtmfbuf[300];
06530 struct callerid_state *cs = NULL;
06531 char *name = NULL, *number = NULL;
06532 int distMatches;
06533 int curRingData[3];
06534 int receivedRingT;
06535 int counter1;
06536 int counter;
06537 int samples = 0;
06538 struct ast_smdi_md_message *smdi_msg = NULL;
06539 int flags;
06540 int i;
06541 int timeout;
06542 int getforward = 0;
06543 char *s1, *s2;
06544 int len = 0;
06545 int res;
06546 int index;
06547
06548 ast_mutex_lock(&ss_thread_lock);
06549 ss_thread_count++;
06550 ast_mutex_unlock(&ss_thread_lock);
06551
06552
06553
06554 if (!p) {
06555 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06556 ast_hangup(chan);
06557 goto quit;
06558 }
06559 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
06560 index = dahdi_get_index(chan, p, 1);
06561 if (index < 0) {
06562 ast_log(LOG_WARNING, "Huh?\n");
06563 ast_hangup(chan);
06564 goto quit;
06565 }
06566 if (p->dsp)
06567 ast_dsp_digitreset(p->dsp);
06568 switch (p->sig) {
06569 #ifdef HAVE_PRI
06570 case SIG_PRI:
06571 case SIG_BRI:
06572 case SIG_BRI_PTMP:
06573
06574 ast_copy_string(exten, p->exten, sizeof(exten));
06575 len = strlen(exten);
06576 res = 0;
06577 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06578 if (len && !ast_ignore_pattern(chan->context, exten))
06579 tone_zone_play_tone(p->subs[index].dfd, -1);
06580 else
06581 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06582 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06583 timeout = matchdigittimeout;
06584 else
06585 timeout = gendigittimeout;
06586 res = ast_waitfordigit(chan, timeout);
06587 if (res < 0) {
06588 ast_debug(1, "waitfordigit returned < 0...\n");
06589 ast_hangup(chan);
06590 goto quit;
06591 } else if (res) {
06592 exten[len++] = res;
06593 exten[len] = '\0';
06594 } else
06595 break;
06596 }
06597
06598 if (ast_strlen_zero(exten)) {
06599 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
06600 exten[0] = 's';
06601 exten[1] = '\0';
06602 }
06603 tone_zone_play_tone(p->subs[index].dfd, -1);
06604 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06605
06606 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06607 if (p->dsp) ast_dsp_digitreset(p->dsp);
06608 dahdi_enable_ec(p);
06609 ast_setstate(chan, AST_STATE_RING);
06610 res = ast_pbx_run(chan);
06611 if (res) {
06612 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06613 }
06614 } else {
06615 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06616 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06617 ast_hangup(chan);
06618 p->exten[0] = '\0';
06619
06620 p->call = NULL;
06621 }
06622 goto quit;
06623 break;
06624 #endif
06625 case SIG_FEATD:
06626 case SIG_FEATDMF:
06627 case SIG_FEATDMF_TA:
06628 case SIG_E911:
06629 case SIG_FGC_CAMAMF:
06630 case SIG_FEATB:
06631 case SIG_EMWINK:
06632 case SIG_SF_FEATD:
06633 case SIG_SF_FEATDMF:
06634 case SIG_SF_FEATB:
06635 case SIG_SFWINK:
06636 if (dahdi_wink(p, index))
06637 goto quit;
06638
06639 case SIG_EM:
06640 case SIG_EM_E1:
06641 case SIG_SF:
06642 case SIG_FGC_CAMA:
06643 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06644 if (p->dsp)
06645 ast_dsp_digitreset(p->dsp);
06646
06647 if (p->dsp) {
06648 if (NEED_MFDETECT(p))
06649 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06650 else
06651 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06652 }
06653 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06654
06655 if (!p->immediate)
06656
06657 res = ast_waitfordigit(chan, 5000);
06658 else
06659 res = 0;
06660 if (res > 0) {
06661
06662 dtmfbuf[0] = res;
06663 switch (p->sig) {
06664 case SIG_FEATD:
06665 case SIG_SF_FEATD:
06666 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06667 if (res > 0)
06668 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06669 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06670 break;
06671 case SIG_FEATDMF_TA:
06672 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06673 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06674 if (dahdi_wink(p, index)) return NULL;
06675 dtmfbuf[0] = 0;
06676
06677 res = ast_waitfordigit(chan, 5000);
06678 if (res <= 0) break;
06679 dtmfbuf[0] = res;
06680
06681 case SIG_FEATDMF:
06682 case SIG_E911:
06683 case SIG_FGC_CAMAMF:
06684 case SIG_SF_FEATDMF:
06685 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06686
06687 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06688 {
06689 if (dahdi_wink(p, index)) return NULL;
06690 dtmfbuf[0] = 0;
06691
06692 res = ast_waitfordigit(chan, 5000);
06693 if (res <= 0) break;
06694 dtmfbuf[0] = res;
06695 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06696 }
06697 if (res > 0) {
06698
06699 if (p->sig == SIG_E911)
06700 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06701 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06702 }
06703 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06704 break;
06705 case SIG_FEATB:
06706 case SIG_SF_FEATB:
06707 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06708 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06709 break;
06710 case SIG_EMWINK:
06711
06712
06713
06714
06715 if (res == '*') {
06716 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06717 if (res > 0)
06718 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06719 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06720 break;
06721 }
06722 default:
06723
06724 len = 1;
06725 dtmfbuf[len] = '\0';
06726 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06727 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06728 timeout = matchdigittimeout;
06729 } else {
06730 timeout = gendigittimeout;
06731 }
06732 res = ast_waitfordigit(chan, timeout);
06733 if (res < 0) {
06734 ast_debug(1, "waitfordigit returned < 0...\n");
06735 ast_hangup(chan);
06736 goto quit;
06737 } else if (res) {
06738 dtmfbuf[len++] = res;
06739 dtmfbuf[len] = '\0';
06740 } else {
06741 break;
06742 }
06743 }
06744 break;
06745 }
06746 }
06747 if (res == -1) {
06748 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06749 ast_hangup(chan);
06750 goto quit;
06751 } else if (res < 0) {
06752 ast_debug(1, "Got hung up before digits finished\n");
06753 ast_hangup(chan);
06754 goto quit;
06755 }
06756
06757 if (p->sig == SIG_FGC_CAMA) {
06758 char anibuf[100];
06759
06760 if (ast_safe_sleep(chan,1000) == -1) {
06761 ast_hangup(chan);
06762 goto quit;
06763 }
06764 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06765 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06766 res = my_getsigstr(chan, anibuf, "#", 10000);
06767 if ((res > 0) && (strlen(anibuf) > 2)) {
06768 if (anibuf[strlen(anibuf) - 1] == '#')
06769 anibuf[strlen(anibuf) - 1] = 0;
06770 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06771 }
06772 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06773 }
06774
06775 ast_copy_string(exten, dtmfbuf, sizeof(exten));
06776 if (ast_strlen_zero(exten))
06777 ast_copy_string(exten, "s", sizeof(exten));
06778 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06779
06780 if (exten[0] == '*') {
06781 char *stringp=NULL;
06782 ast_copy_string(exten2, exten, sizeof(exten2));
06783
06784 stringp=exten2 +1;
06785 s1 = strsep(&stringp, "*");
06786 s2 = strsep(&stringp, "*");
06787 if (s2) {
06788 if (!ast_strlen_zero(p->cid_num))
06789 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06790 else
06791 ast_set_callerid(chan, s1, NULL, s1);
06792 ast_copy_string(exten, s2, sizeof(exten));
06793 } else
06794 ast_copy_string(exten, s1, sizeof(exten));
06795 } else if (p->sig == SIG_FEATD)
06796 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06797 }
06798 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06799 if (exten[0] == '*') {
06800 char *stringp=NULL;
06801 ast_copy_string(exten2, exten, sizeof(exten2));
06802
06803 stringp=exten2 +1;
06804 s1 = strsep(&stringp, "#");
06805 s2 = strsep(&stringp, "#");
06806 if (s2) {
06807 if (!ast_strlen_zero(p->cid_num))
06808 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06809 else
06810 if (*(s1 + 2))
06811 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06812 ast_copy_string(exten, s2 + 1, sizeof(exten));
06813 } else
06814 ast_copy_string(exten, s1 + 2, sizeof(exten));
06815 } else
06816 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06817 }
06818 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06819 if (exten[0] == '*') {
06820 char *stringp=NULL;
06821 ast_copy_string(exten2, exten, sizeof(exten2));
06822
06823 stringp=exten2 +1;
06824 s1 = strsep(&stringp, "#");
06825 s2 = strsep(&stringp, "#");
06826 if (s2 && (*(s2 + 1) == '0')) {
06827 if (*(s2 + 2))
06828 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06829 }
06830 if (s1) ast_copy_string(exten, s1, sizeof(exten));
06831 else ast_copy_string(exten, "911", sizeof(exten));
06832 } else
06833 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
06834 }
06835 if (p->sig == SIG_FEATB) {
06836 if (exten[0] == '*') {
06837 char *stringp=NULL;
06838 ast_copy_string(exten2, exten, sizeof(exten2));
06839
06840 stringp=exten2 +1;
06841 s1 = strsep(&stringp, "#");
06842 ast_copy_string(exten, exten2 + 1, sizeof(exten));
06843 } else
06844 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
06845 }
06846 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06847 dahdi_wink(p, index);
06848
06849
06850
06851 if (ast_safe_sleep(chan,100)) goto quit;
06852 }
06853 dahdi_enable_ec(p);
06854 if (NEED_MFDETECT(p)) {
06855 if (p->dsp) {
06856 if (!p->hardwaredtmf)
06857 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06858 else {
06859 ast_dsp_free(p->dsp);
06860 p->dsp = NULL;
06861 }
06862 }
06863 }
06864
06865 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06866 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06867 if (p->dsp) ast_dsp_digitreset(p->dsp);
06868 res = ast_pbx_run(chan);
06869 if (res) {
06870 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06871 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06872 }
06873 goto quit;
06874 } else {
06875 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06876 sleep(2);
06877 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
06878 if (res < 0)
06879 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06880 else
06881 sleep(1);
06882 res = ast_streamfile(chan, "ss-noservice", chan->language);
06883 if (res >= 0)
06884 ast_waitstream(chan, "");
06885 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06886 ast_hangup(chan);
06887 goto quit;
06888 }
06889 break;
06890 case SIG_FXOLS:
06891 case SIG_FXOGS:
06892 case SIG_FXOKS:
06893
06894 timeout = firstdigittimeout;
06895
06896
06897 if (p->subs[SUB_THREEWAY].owner)
06898 timeout = 999999;
06899 while (len < AST_MAX_EXTENSION-1) {
06900
06901
06902 if (p->immediate)
06903 res = 's';
06904 else
06905 res = ast_waitfordigit(chan, timeout);
06906 timeout = 0;
06907 if (res < 0) {
06908 ast_debug(1, "waitfordigit returned < 0...\n");
06909 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06910 ast_hangup(chan);
06911 goto quit;
06912 } else if (res) {
06913 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
06914 exten[len++]=res;
06915 exten[len] = '\0';
06916 }
06917 if (!ast_ignore_pattern(chan->context, exten))
06918 tone_zone_play_tone(p->subs[index].dfd, -1);
06919 else
06920 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06921 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06922 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06923 if (getforward) {
06924
06925 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
06926 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06927 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06928 if (res)
06929 break;
06930 usleep(500000);
06931 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06932 sleep(1);
06933 memset(exten, 0, sizeof(exten));
06934 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06935 len = 0;
06936 getforward = 0;
06937 } else {
06938 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06939 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06940 if (!ast_strlen_zero(p->cid_num)) {
06941 if (!p->hidecallerid)
06942 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06943 else
06944 ast_set_callerid(chan, NULL, NULL, p->cid_num);
06945 }
06946 if (!ast_strlen_zero(p->cid_name)) {
06947 if (!p->hidecallerid)
06948 ast_set_callerid(chan, NULL, p->cid_name, NULL);
06949 }
06950 ast_setstate(chan, AST_STATE_RING);
06951 dahdi_enable_ec(p);
06952 res = ast_pbx_run(chan);
06953 if (res) {
06954 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06955 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06956 }
06957 goto quit;
06958 }
06959 } else {
06960
06961
06962 timeout = matchdigittimeout;
06963 }
06964 } else if (res == 0) {
06965 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
06966 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06967 dahdi_wait_event(p->subs[index].dfd);
06968 ast_hangup(chan);
06969 goto quit;
06970 } else if (p->callwaiting && !strcmp(exten, "*70")) {
06971 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
06972
06973 p->callwaiting = 0;
06974 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06975 if (res) {
06976 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06977 chan->name, strerror(errno));
06978 }
06979 len = 0;
06980 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06981 memset(exten, 0, sizeof(exten));
06982 timeout = firstdigittimeout;
06983
06984 } else if (!strcmp(exten,ast_pickup_ext())) {
06985
06986
06987
06988
06989 if (index == SUB_REAL) {
06990
06991 if (p->subs[SUB_THREEWAY].owner) {
06992
06993
06994 alloc_sub(p, SUB_CALLWAIT);
06995 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06996 unalloc_sub(p, SUB_THREEWAY);
06997 }
06998 dahdi_enable_ec(p);
06999 if (ast_pickup_call(chan)) {
07000 ast_debug(1, "No call pickup possible...\n");
07001 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07002 dahdi_wait_event(p->subs[index].dfd);
07003 }
07004 ast_hangup(chan);
07005 goto quit;
07006 } else {
07007 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07008 ast_hangup(chan);
07009 goto quit;
07010 }
07011
07012 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07013 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
07014
07015 p->hidecallerid = 1;
07016 if (chan->cid.cid_num)
07017 ast_free(chan->cid.cid_num);
07018 chan->cid.cid_num = NULL;
07019 if (chan->cid.cid_name)
07020 ast_free(chan->cid.cid_name);
07021 chan->cid.cid_name = NULL;
07022 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07023 if (res) {
07024 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07025 chan->name, strerror(errno));
07026 }
07027 len = 0;
07028 memset(exten, 0, sizeof(exten));
07029 timeout = firstdigittimeout;
07030 } else if (p->callreturn && !strcmp(exten, "*69")) {
07031 res = 0;
07032 if (!ast_strlen_zero(p->lastcid_num)) {
07033 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07034 }
07035 if (!res)
07036 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07037 break;
07038 } else if (!strcmp(exten, "*78")) {
07039 dahdi_dnd(p, 1);
07040
07041 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07042 getforward = 0;
07043 memset(exten, 0, sizeof(exten));
07044 len = 0;
07045 } else if (!strcmp(exten, "*79")) {
07046 dahdi_dnd(p, 0);
07047
07048 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07049 getforward = 0;
07050 memset(exten, 0, sizeof(exten));
07051 len = 0;
07052 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07053 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07054 getforward = 1;
07055 memset(exten, 0, sizeof(exten));
07056 len = 0;
07057 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07058 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
07059 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07060 memset(p->call_forward, 0, sizeof(p->call_forward));
07061 getforward = 0;
07062 memset(exten, 0, sizeof(exten));
07063 len = 0;
07064 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07065 p->subs[SUB_THREEWAY].owner &&
07066 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07067
07068
07069 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07070 ast_verb(3, "Parking call to '%s'\n", chan->name);
07071 break;
07072 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07073 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
07074 res = ast_db_put("blacklist", p->lastcid_num, "1");
07075 if (!res) {
07076 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07077 memset(exten, 0, sizeof(exten));
07078 len = 0;
07079 }
07080 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07081 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
07082
07083 p->hidecallerid = 0;
07084 if (chan->cid.cid_num)
07085 ast_free(chan->cid.cid_num);
07086 chan->cid.cid_num = NULL;
07087 if (chan->cid.cid_name)
07088 ast_free(chan->cid.cid_name);
07089 chan->cid.cid_name = NULL;
07090 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07091 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07092 if (res) {
07093 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07094 chan->name, strerror(errno));
07095 }
07096 len = 0;
07097 memset(exten, 0, sizeof(exten));
07098 timeout = firstdigittimeout;
07099 } else if (!strcmp(exten, "*0")) {
07100 struct ast_channel *nbridge =
07101 p->subs[SUB_THREEWAY].owner;
07102 struct dahdi_pvt *pbridge = NULL;
07103
07104 if (nbridge && ast_bridged_channel(nbridge))
07105 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07106 if (nbridge && pbridge &&
07107 (nbridge->tech == &dahdi_tech) &&
07108 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
07109 ISTRUNK(pbridge)) {
07110 int func = DAHDI_FLASH;
07111
07112 p->dop.dialstr[0] = '\0';
07113
07114 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07115 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07116 nbridge->name, strerror(errno));
07117 }
07118 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07119 unalloc_sub(p, SUB_THREEWAY);
07120 p->owner = p->subs[SUB_REAL].owner;
07121 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07122 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07123 ast_hangup(chan);
07124 goto quit;
07125 } else {
07126 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07127 dahdi_wait_event(p->subs[index].dfd);
07128 tone_zone_play_tone(p->subs[index].dfd, -1);
07129 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07130 unalloc_sub(p, SUB_THREEWAY);
07131 p->owner = p->subs[SUB_REAL].owner;
07132 ast_hangup(chan);
07133 goto quit;
07134 }
07135 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07136 ((exten[0] != '*') || (strlen(exten) > 2))) {
07137 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);
07138 break;
07139 }
07140 if (!timeout)
07141 timeout = gendigittimeout;
07142 if (len && !ast_ignore_pattern(chan->context, exten))
07143 tone_zone_play_tone(p->subs[index].dfd, -1);
07144 }
07145 break;
07146 case SIG_FXSLS:
07147 case SIG_FXSGS:
07148 case SIG_FXSKS:
07149 #ifdef HAVE_PRI
07150 if (p->pri) {
07151
07152 struct ast_frame *f;
07153 int res;
07154 time_t start;
07155
07156 time(&start);
07157 ast_setstate(chan, AST_STATE_RING);
07158 while (time(NULL) < start + 3) {
07159 res = ast_waitfor(chan, 1000);
07160 if (res) {
07161 f = ast_read(chan);
07162 if (!f) {
07163 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07164 ast_hangup(chan);
07165 goto quit;
07166 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07167 res = 1;
07168 } else
07169 res = 0;
07170 ast_frfree(f);
07171 if (res) {
07172 ast_debug(1, "Got ring!\n");
07173 res = 0;
07174 break;
07175 }
07176 }
07177 }
07178 }
07179 #endif
07180
07181 if (p->use_smdi && p->smdi_iface) {
07182 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07183
07184 if (smdi_msg != NULL) {
07185 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07186
07187 if (smdi_msg->type == 'B')
07188 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07189 else if (smdi_msg->type == 'N')
07190 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07191
07192 ast_debug(1, "Recieved SMDI message on %s\n", chan->name);
07193 } else {
07194 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07195 }
07196 }
07197
07198 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07199 number = smdi_msg->calling_st;
07200
07201
07202
07203
07204 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
07205
07206 if (p->cid_signalling == CID_SIG_DTMF) {
07207 int i = 0;
07208 cs = NULL;
07209 ast_debug(1, "Receiving DTMF cid on "
07210 "channel %s\n", chan->name);
07211 dahdi_setlinear(p->subs[index].dfd, 0);
07212 res = 2000;
07213 for (;;) {
07214 struct ast_frame *f;
07215 res = ast_waitfor(chan, res);
07216 if (res <= 0) {
07217 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07218 "Exiting simple switch\n");
07219 ast_hangup(chan);
07220 goto quit;
07221 }
07222 f = ast_read(chan);
07223 if (!f)
07224 break;
07225 if (f->frametype == AST_FRAME_DTMF) {
07226 dtmfbuf[i++] = f->subclass;
07227 ast_debug(1, "CID got digit '%c'\n", f->subclass);
07228 res = 2000;
07229 }
07230 ast_frfree(f);
07231 if (chan->_state == AST_STATE_RING ||
07232 chan->_state == AST_STATE_RINGING)
07233 break;
07234 }
07235 dtmfbuf[i] = '\0';
07236 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07237
07238 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
07239 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07240 ast_debug(1, "CID is '%s', flags %d\n",
07241 dtmfcid, flags);
07242
07243 if (!ast_strlen_zero(dtmfcid))
07244 number = dtmfcid;
07245 else
07246 number = NULL;
07247
07248 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07249 cs = callerid_new(p->cid_signalling);
07250 if (cs) {
07251 samples = 0;
07252 #if 1
07253 bump_gains(p);
07254 #endif
07255
07256 dahdi_setlinear(p->subs[index].dfd, 0);
07257
07258
07259 for (;;) {
07260 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07261 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07262 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07263 callerid_free(cs);
07264 ast_hangup(chan);
07265 goto quit;
07266 }
07267 if (i & DAHDI_IOMUX_SIGEVENT) {
07268 res = dahdi_get_event(p->subs[index].dfd);
07269 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07270
07271 if (p->cid_signalling == CID_SIG_V23_JP) {
07272 if (res == DAHDI_EVENT_RINGBEGIN) {
07273 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07274 usleep(1);
07275 }
07276 } else {
07277 res = 0;
07278 break;
07279 }
07280 } else if (i & DAHDI_IOMUX_READ) {
07281 res = read(p->subs[index].dfd, buf, sizeof(buf));
07282 if (res < 0) {
07283 if (errno != ELAST) {
07284 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07285 callerid_free(cs);
07286 ast_hangup(chan);
07287 goto quit;
07288 }
07289 break;
07290 }
07291 samples += res;
07292
07293 if (p->cid_signalling == CID_SIG_V23_JP) {
07294 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07295 } else {
07296 res = callerid_feed(cs, buf, res, AST_LAW(p));
07297 }
07298
07299 if (res < 0) {
07300 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07301 break;
07302 } else if (res)
07303 break;
07304 else if (samples > (8000 * 10))
07305 break;
07306 }
07307 }
07308 if (res == 1) {
07309 callerid_get(cs, &name, &number, &flags);
07310 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07311 }
07312
07313 if (p->cid_signalling == CID_SIG_V23_JP) {
07314 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07315 usleep(1);
07316 res = 4000;
07317 } else {
07318
07319
07320 res = 2000;
07321 }
07322
07323 for (;;) {
07324 struct ast_frame *f;
07325 res = ast_waitfor(chan, res);
07326 if (res <= 0) {
07327 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07328 "Exiting simple switch\n");
07329 ast_hangup(chan);
07330 goto quit;
07331 }
07332 if (!(f = ast_read(chan))) {
07333 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07334 ast_hangup(chan);
07335 goto quit;
07336 }
07337 ast_frfree(f);
07338 if (chan->_state == AST_STATE_RING ||
07339 chan->_state == AST_STATE_RINGING)
07340 break;
07341 }
07342
07343
07344
07345 if (p->usedistinctiveringdetection) {
07346 len = 0;
07347 distMatches = 0;
07348
07349 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07350 curRingData[receivedRingT] = 0;
07351 receivedRingT = 0;
07352 counter = 0;
07353 counter1 = 0;
07354
07355 if (strcmp(p->context,p->defcontext) != 0) {
07356 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07357 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07358 }
07359
07360 for (;;) {
07361 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07362 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07363 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07364 callerid_free(cs);
07365 ast_hangup(chan);
07366 goto quit;
07367 }
07368 if (i & DAHDI_IOMUX_SIGEVENT) {
07369 res = dahdi_get_event(p->subs[index].dfd);
07370 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07371 res = 0;
07372
07373
07374 curRingData[receivedRingT] = p->ringt;
07375
07376 if (p->ringt < p->ringt_base/2)
07377 break;
07378
07379
07380 if (++receivedRingT == ARRAY_LEN(curRingData))
07381 break;
07382 } else if (i & DAHDI_IOMUX_READ) {
07383 res = read(p->subs[index].dfd, buf, sizeof(buf));
07384 if (res < 0) {
07385 if (errno != ELAST) {
07386 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07387 callerid_free(cs);
07388 ast_hangup(chan);
07389 goto quit;
07390 }
07391 break;
07392 }
07393 if (p->ringt)
07394 p->ringt--;
07395 if (p->ringt == 1) {
07396 res = -1;
07397 break;
07398 }
07399 }
07400 }
07401
07402 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07403 for (counter = 0; counter < 3; counter++) {
07404
07405
07406 distMatches = 0;
07407 for (counter1 = 0; counter1 < 3; counter1++) {
07408 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07409 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07410 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07411 curRingData[counter1]);
07412 distMatches++;
07413 }
07414 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07415 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07416 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07417 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07418 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07419 distMatches++;
07420 }
07421 }
07422
07423 if (distMatches == 3) {
07424
07425 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07426 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07427 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07428 break;
07429 }
07430 }
07431 }
07432
07433 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07434 #if 1
07435 restore_gains(p);
07436 #endif
07437 } else
07438 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07439 } else {
07440 ast_log(LOG_WARNING, "Channel %s in prering "
07441 "state, but I have nothing to do. "
07442 "Terminating simple switch, should be "
07443 "restarted by the actual ring.\n",
07444 chan->name);
07445 ast_hangup(chan);
07446 goto quit;
07447 }
07448 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07449 if (p->cid_signalling == CID_SIG_DTMF) {
07450 int i = 0;
07451 cs = NULL;
07452 dahdi_setlinear(p->subs[index].dfd, 0);
07453 res = 2000;
07454 for (;;) {
07455 struct ast_frame *f;
07456 res = ast_waitfor(chan, res);
07457 if (res <= 0) {
07458 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07459 "Exiting simple switch\n");
07460 ast_hangup(chan);
07461 return NULL;
07462 }
07463 f = ast_read(chan);
07464 if (f->frametype == AST_FRAME_DTMF) {
07465 dtmfbuf[i++] = f->subclass;
07466 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07467 res = 2000;
07468 }
07469 ast_frfree(f);
07470
07471 if (p->ringt_base == p->ringt)
07472 break;
07473
07474 }
07475 dtmfbuf[i] = '\0';
07476 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07477
07478 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07479 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07480 dtmfcid, flags);
07481
07482 if (!ast_strlen_zero(dtmfcid))
07483 number = dtmfcid;
07484 else
07485 number = NULL;
07486
07487 } else {
07488
07489 cs = callerid_new(p->cid_signalling);
07490 if (cs) {
07491 #if 1
07492 bump_gains(p);
07493 #endif
07494 samples = 0;
07495 len = 0;
07496 distMatches = 0;
07497
07498 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07499 curRingData[receivedRingT] = 0;
07500 receivedRingT = 0;
07501 counter = 0;
07502 counter1 = 0;
07503
07504 if (strcmp(p->context,p->defcontext) != 0) {
07505 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07506 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07507 }
07508
07509
07510 dahdi_setlinear(p->subs[index].dfd, 0);
07511 for (;;) {
07512 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07513 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07514 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07515 callerid_free(cs);
07516 ast_hangup(chan);
07517 goto quit;
07518 }
07519 if (i & DAHDI_IOMUX_SIGEVENT) {
07520 res = dahdi_get_event(p->subs[index].dfd);
07521 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07522
07523 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07524 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07525 p->polarity = POLARITY_IDLE;
07526 callerid_free(cs);
07527 ast_hangup(chan);
07528 goto quit;
07529 }
07530 res = 0;
07531
07532
07533 curRingData[receivedRingT] = p->ringt;
07534
07535 if (p->ringt < p->ringt_base/2)
07536 break;
07537
07538
07539 if (++receivedRingT == ARRAY_LEN(curRingData))
07540 break;
07541 } else if (i & DAHDI_IOMUX_READ) {
07542 res = read(p->subs[index].dfd, buf, sizeof(buf));
07543 if (res < 0) {
07544 if (errno != ELAST) {
07545 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07546 callerid_free(cs);
07547 ast_hangup(chan);
07548 goto quit;
07549 }
07550 break;
07551 }
07552 if (p->ringt)
07553 p->ringt--;
07554 if (p->ringt == 1) {
07555 res = -1;
07556 break;
07557 }
07558 samples += res;
07559 res = callerid_feed(cs, buf, res, AST_LAW(p));
07560 if (res < 0) {
07561 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07562 break;
07563 } else if (res)
07564 break;
07565 else if (samples > (8000 * 10))
07566 break;
07567 }
07568 }
07569 if (res == 1) {
07570 callerid_get(cs, &name, &number, &flags);
07571 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07572 }
07573 if (distinctiveringaftercid == 1) {
07574
07575 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07576 curRingData[receivedRingT] = 0;
07577 }
07578 receivedRingT = 0;
07579 ast_verb(3, "Detecting post-CID distinctive ring\n");
07580 for (;;) {
07581 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07582 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07583 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07584 callerid_free(cs);
07585 ast_hangup(chan);
07586 goto quit;
07587 }
07588 if (i & DAHDI_IOMUX_SIGEVENT) {
07589 res = dahdi_get_event(p->subs[index].dfd);
07590 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07591 res = 0;
07592
07593
07594 curRingData[receivedRingT] = p->ringt;
07595
07596 if (p->ringt < p->ringt_base/2)
07597 break;
07598
07599
07600 if (++receivedRingT == ARRAY_LEN(curRingData))
07601 break;
07602 } else if (i & DAHDI_IOMUX_READ) {
07603 res = read(p->subs[index].dfd, buf, sizeof(buf));
07604 if (res < 0) {
07605 if (errno != ELAST) {
07606 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07607 callerid_free(cs);
07608 ast_hangup(chan);
07609 goto quit;
07610 }
07611 break;
07612 }
07613 if (p->ringt)
07614 p->ringt--;
07615 if (p->ringt == 1) {
07616 res = -1;
07617 break;
07618 }
07619 }
07620 }
07621 }
07622 if (p->usedistinctiveringdetection) {
07623
07624 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07625
07626 for (counter = 0; counter < 3; counter++) {
07627
07628
07629
07630 ast_verb(3, "Checking %d,%d,%d\n",
07631 p->drings.ringnum[counter].ring[0],
07632 p->drings.ringnum[counter].ring[1],
07633 p->drings.ringnum[counter].ring[2]);
07634 distMatches = 0;
07635 for (counter1 = 0; counter1 < 3; counter1++) {
07636 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07637 if (p->drings.ringnum[counter].ring[counter1] == -1) {
07638 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07639 curRingData[counter1]);
07640 distMatches++;
07641 }
07642 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07643 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07644 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07645 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07646 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07647 distMatches++;
07648 }
07649 }
07650 if (distMatches == 3) {
07651
07652 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07653 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07654 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07655 break;
07656 }
07657 }
07658 }
07659
07660 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07661 #if 1
07662 restore_gains(p);
07663 #endif
07664 if (res < 0) {
07665 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07666 }
07667 } else
07668 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07669 }
07670 }
07671 else
07672 cs = NULL;
07673
07674 if (number)
07675 ast_shrink_phone_number(number);
07676 ast_set_callerid(chan, number, name, number);
07677
07678 if (smdi_msg)
07679 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07680
07681 if (cs)
07682 callerid_free(cs);
07683
07684 ast_setstate(chan, AST_STATE_RING);
07685 chan->rings = 1;
07686 p->ringt = p->ringt_base;
07687 res = ast_pbx_run(chan);
07688 if (res) {
07689 ast_hangup(chan);
07690 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07691 }
07692 goto quit;
07693 default:
07694 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07695 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07696 if (res < 0)
07697 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07698 }
07699 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07700 if (res < 0)
07701 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07702 ast_hangup(chan);
07703 quit:
07704 ast_mutex_lock(&ss_thread_lock);
07705 ss_thread_count--;
07706 ast_cond_signal(&ss_thread_complete);
07707 ast_mutex_unlock(&ss_thread_lock);
07708 return NULL;
07709 }
07710
07711 struct mwi_thread_data {
07712 struct dahdi_pvt *pvt;
07713 unsigned char buf[READ_SIZE];
07714 size_t len;
07715 };
07716
07717 static int calc_energy(const unsigned char *buf, int len, int law)
07718 {
07719 int x;
07720 int sum = 0;
07721
07722 if (!len)
07723 return 0;
07724
07725 for (x = 0; x < len; x++)
07726 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07727
07728 return sum / len;
07729 }
07730
07731 static void *mwi_thread(void *data)
07732 {
07733 struct mwi_thread_data *mtd = data;
07734 struct callerid_state *cs;
07735 pthread_t threadid;
07736 int samples = 0;
07737 char *name, *number;
07738 int flags;
07739 int i, res;
07740 unsigned int spill_done = 0;
07741 int spill_result = -1;
07742
07743 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
07744 mtd->pvt->mwimonitoractive = 0;
07745
07746 return NULL;
07747 }
07748
07749 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
07750
07751 bump_gains(mtd->pvt);
07752
07753 for (;;) {
07754 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07755 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07756 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07757 goto quit;
07758 }
07759
07760 if (i & DAHDI_IOMUX_SIGEVENT) {
07761 struct ast_channel *chan;
07762
07763
07764
07765
07766 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07767
07768 switch (res) {
07769 case DAHDI_EVENT_NEONMWI_ACTIVE:
07770 case DAHDI_EVENT_NEONMWI_INACTIVE:
07771 case DAHDI_EVENT_NONE:
07772 case DAHDI_EVENT_BITSCHANGED:
07773 break;
07774 case DAHDI_EVENT_NOALARM:
07775 mtd->pvt->inalarm = 0;
07776 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
07777 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07778 "Channel: %d\r\n", mtd->pvt->channel);
07779 break;
07780 case DAHDI_EVENT_ALARM:
07781 mtd->pvt->inalarm = 1;
07782 res = get_alarms(mtd->pvt);
07783 handle_alarms(mtd->pvt, res);
07784 break;
07785 default:
07786 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
07787 callerid_free(cs);
07788
07789 restore_gains(mtd->pvt);
07790 mtd->pvt->ringt = mtd->pvt->ringt_base;
07791
07792 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
07793 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07794 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
07795 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07796 if (res < 0)
07797 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
07798 ast_hangup(chan);
07799 goto quit;
07800 }
07801 goto quit_no_clean;
07802
07803 } else {
07804 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
07805 }
07806 }
07807 } else if (i & DAHDI_IOMUX_READ) {
07808 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07809 if (errno != ELAST) {
07810 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07811 goto quit;
07812 }
07813 break;
07814 }
07815 samples += res;
07816 if (!spill_done) {
07817 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
07818 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07819 break;
07820 } else if (spill_result) {
07821 spill_done = 1;
07822 }
07823 } else {
07824
07825
07826
07827 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
07828 break;
07829 }
07830 if (samples > (8000 * 4))
07831 break;
07832 }
07833 }
07834
07835 if (spill_result == 1) {
07836 callerid_get(cs, &name, &number, &flags);
07837 if (flags & CID_MSGWAITING) {
07838 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
07839 notify_message(mtd->pvt->mailbox, 1);
07840 } else if (flags & CID_NOMSGWAITING) {
07841 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
07842 notify_message(mtd->pvt->mailbox, 0);
07843 } else {
07844 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
07845 }
07846 }
07847
07848
07849 quit:
07850 callerid_free(cs);
07851
07852 restore_gains(mtd->pvt);
07853
07854 quit_no_clean:
07855 mtd->pvt->mwimonitoractive = 0;
07856
07857 ast_free(mtd);
07858
07859 return NULL;
07860 }
07861
07862
07863 static int dahdi_destroy_channel_bynum(int channel)
07864 {
07865 struct dahdi_pvt *tmp = NULL;
07866 struct dahdi_pvt *prev = NULL;
07867
07868 tmp = iflist;
07869 while (tmp) {
07870 if (tmp->channel == channel) {
07871 int x = DAHDI_FLASH;
07872 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07873 destroy_channel(prev, tmp, 1);
07874 ast_module_unref(ast_module_info->self);
07875 return RESULT_SUCCESS;
07876 }
07877 prev = tmp;
07878 tmp = tmp->next;
07879 }
07880 return RESULT_FAILURE;
07881 }
07882
07883 static int handle_init_event(struct dahdi_pvt *i, int event)
07884 {
07885 int res;
07886 pthread_t threadid;
07887 struct ast_channel *chan;
07888
07889
07890
07891 switch (event) {
07892 case DAHDI_EVENT_NONE:
07893 case DAHDI_EVENT_BITSCHANGED:
07894 break;
07895 case DAHDI_EVENT_WINKFLASH:
07896 case DAHDI_EVENT_RINGOFFHOOK:
07897 if (i->inalarm) break;
07898 if (i->radio) break;
07899
07900 switch (i->sig) {
07901 case SIG_FXOLS:
07902 case SIG_FXOGS:
07903 case SIG_FXOKS:
07904 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07905 if (res && (errno == EBUSY))
07906 break;
07907 if (i->cidspill) {
07908
07909 ast_free(i->cidspill);
07910 i->cidspill = NULL;
07911 }
07912 if (i->immediate) {
07913 dahdi_enable_ec(i);
07914
07915 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07916 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07917 if (!chan) {
07918 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07919 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07920 if (res < 0)
07921 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07922 }
07923 } else {
07924
07925 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07926 if (chan) {
07927 if (has_voicemail(i))
07928 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07929 else
07930 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07931 if (res < 0)
07932 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
07933 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07934 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07935 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07936 if (res < 0)
07937 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07938 ast_hangup(chan);
07939 }
07940 } else
07941 ast_log(LOG_WARNING, "Unable to create channel\n");
07942 }
07943 break;
07944 case SIG_FXSLS:
07945 case SIG_FXSGS:
07946 case SIG_FXSKS:
07947 i->ringt = i->ringt_base;
07948
07949 case SIG_EMWINK:
07950 case SIG_FEATD:
07951 case SIG_FEATDMF:
07952 case SIG_FEATDMF_TA:
07953 case SIG_E911:
07954 case SIG_FGC_CAMA:
07955 case SIG_FGC_CAMAMF:
07956 case SIG_FEATB:
07957 case SIG_EM:
07958 case SIG_EM_E1:
07959 case SIG_SFWINK:
07960 case SIG_SF_FEATD:
07961 case SIG_SF_FEATDMF:
07962 case SIG_SF_FEATB:
07963 case SIG_SF:
07964
07965 if (i->cid_start == CID_START_POLARITY_IN) {
07966 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
07967 } else {
07968 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
07969 }
07970 if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07971 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07972 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07973 if (res < 0)
07974 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07975 ast_hangup(chan);
07976 } else if (!chan) {
07977 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
07978 }
07979 break;
07980 default:
07981 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07982 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07983 if (res < 0)
07984 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07985 return -1;
07986 }
07987 break;
07988 case DAHDI_EVENT_NOALARM:
07989 i->inalarm = 0;
07990 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
07991 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07992 "Channel: %d\r\n", i->channel);
07993 break;
07994 case DAHDI_EVENT_ALARM:
07995 i->inalarm = 1;
07996 res = get_alarms(i);
07997 handle_alarms(i, res);
07998
07999 case DAHDI_EVENT_ONHOOK:
08000 if (i->radio)
08001 break;
08002
08003 switch (i->sig) {
08004 case SIG_FXOLS:
08005 case SIG_FXOGS:
08006 case SIG_FEATD:
08007 case SIG_FEATDMF:
08008 case SIG_FEATDMF_TA:
08009 case SIG_E911:
08010 case SIG_FGC_CAMA:
08011 case SIG_FGC_CAMAMF:
08012 case SIG_FEATB:
08013 case SIG_EM:
08014 case SIG_EM_E1:
08015 case SIG_EMWINK:
08016 case SIG_SF_FEATD:
08017 case SIG_SF_FEATDMF:
08018 case SIG_SF_FEATB:
08019 case SIG_SF:
08020 case SIG_SFWINK:
08021 case SIG_FXSLS:
08022 case SIG_FXSGS:
08023 case SIG_FXSKS:
08024 case SIG_GR303FXSKS:
08025 dahdi_disable_ec(i);
08026 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08027 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08028 break;
08029 case SIG_GR303FXOKS:
08030 case SIG_FXOKS:
08031 dahdi_disable_ec(i);
08032
08033 #ifdef ZHONE_HACK
08034 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08035 usleep(1);
08036 #endif
08037 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08038 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08039 break;
08040 case SIG_PRI:
08041 case SIG_SS7:
08042 case SIG_BRI:
08043 case SIG_BRI_PTMP:
08044 dahdi_disable_ec(i);
08045 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08046 break;
08047 default:
08048 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08049 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08050 return -1;
08051 }
08052 break;
08053 case DAHDI_EVENT_POLARITY:
08054 switch (i->sig) {
08055 case SIG_FXSLS:
08056 case SIG_FXSKS:
08057 case SIG_FXSGS:
08058
08059
08060
08061
08062 if (i->hanguponpolarityswitch)
08063 i->polarity = POLARITY_REV;
08064 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08065 i->polarity = POLARITY_REV;
08066 ast_verb(2, "Starting post polarity "
08067 "CID detection on channel %d\n",
08068 i->channel);
08069 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08070 if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08071 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08072 }
08073 }
08074 break;
08075 default:
08076 ast_log(LOG_WARNING, "handle_init_event detected "
08077 "polarity reversal on non-FXO (SIG_FXS) "
08078 "interface %d\n", i->channel);
08079 }
08080 break;
08081 case DAHDI_EVENT_REMOVED:
08082 ast_log(LOG_NOTICE,
08083 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08084 i->channel);
08085 dahdi_destroy_channel_bynum(i->channel);
08086 break;
08087 case DAHDI_EVENT_NEONMWI_ACTIVE:
08088 if (i->mwimonitor_neon) {
08089 notify_message(i->mailbox, 1);
08090 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08091 }
08092 break;
08093 case DAHDI_EVENT_NEONMWI_INACTIVE:
08094 if (i->mwimonitor_neon) {
08095 notify_message(i->mailbox, 0);
08096 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08097 }
08098 break;
08099 }
08100 return 0;
08101 }
08102
08103 static void *do_monitor(void *data)
08104 {
08105 int count, res, res2, spoint, pollres=0;
08106 struct dahdi_pvt *i;
08107 struct dahdi_pvt *last = NULL;
08108 time_t thispass = 0, lastpass = 0;
08109 int found;
08110 char buf[1024];
08111 struct pollfd *pfds=NULL;
08112 int lastalloc = -1;
08113
08114
08115
08116 #if 0
08117 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08118 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08119 return NULL;
08120 }
08121 ast_debug(1, "Monitor starting...\n");
08122 #endif
08123 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08124
08125 for (;;) {
08126
08127 ast_mutex_lock(&iflock);
08128 if (!pfds || (lastalloc != ifcount)) {
08129 if (pfds) {
08130 ast_free(pfds);
08131 pfds = NULL;
08132 }
08133 if (ifcount) {
08134 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08135 ast_mutex_unlock(&iflock);
08136 return NULL;
08137 }
08138 }
08139 lastalloc = ifcount;
08140 }
08141
08142
08143 count = 0;
08144 i = iflist;
08145 while (i) {
08146 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08147 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive) {
08148
08149 pfds[count].fd = i->subs[SUB_REAL].dfd;
08150 pfds[count].events = POLLPRI;
08151 pfds[count].revents = 0;
08152
08153
08154 if (i->cidspill || i->mwimonitor_fsk)
08155 pfds[count].events |= POLLIN;
08156 count++;
08157 }
08158 }
08159 i = i->next;
08160 }
08161
08162 ast_mutex_unlock(&iflock);
08163
08164 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08165 pthread_testcancel();
08166
08167 res = poll(pfds, count, 1000);
08168 pthread_testcancel();
08169 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08170
08171
08172 if (res < 0) {
08173 if ((errno != EAGAIN) && (errno != EINTR))
08174 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08175 continue;
08176 }
08177
08178
08179 ast_mutex_lock(&iflock);
08180 found = 0;
08181 spoint = 0;
08182 lastpass = thispass;
08183 thispass = time(NULL);
08184 i = iflist;
08185 while (i) {
08186 if (thispass != lastpass) {
08187 if (!found && ((i == last) || ((i == iflist) && !last))) {
08188 last = i;
08189 if (last) {
08190 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08191 (last->sig & __DAHDI_SIG_FXO)) {
08192 res = has_voicemail(last);
08193 if (last->msgstate != res) {
08194 int x;
08195 ast_debug(1, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08196 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08197 if (res2)
08198
08199 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08200 x = DAHDI_FLUSH_BOTH;
08201 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08202 if (res2)
08203 ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel);
08204 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08205
08206 x = 4000;
08207 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08208 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08209 last->cidpos = 0;
08210 last->msgstate = res;
08211 last->onhooktime = thispass;
08212 }
08213 found ++;
08214 }
08215 }
08216 last = last->next;
08217 }
08218 }
08219 }
08220 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08221 if (i->radio && !i->owner)
08222 {
08223 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08224 if (res)
08225 {
08226 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08227
08228 ast_mutex_unlock(&iflock);
08229 handle_init_event(i, res);
08230 ast_mutex_lock(&iflock);
08231 }
08232 i = i->next;
08233 continue;
08234 }
08235 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08236 if (pollres & POLLIN) {
08237 if (i->owner || i->subs[SUB_REAL].owner) {
08238 #ifdef HAVE_PRI
08239 if (!i->pri)
08240 #endif
08241 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08242 i = i->next;
08243 continue;
08244 }
08245 if (!i->cidspill && !i->mwimonitor_fsk) {
08246 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08247 i = i->next;
08248 continue;
08249 }
08250 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08251 if (res > 0) {
08252 if (i->mwimonitor_fsk) {
08253 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08254 pthread_attr_t attr;
08255 pthread_t threadid;
08256 struct mwi_thread_data *mtd;
08257
08258 pthread_attr_init(&attr);
08259 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08260
08261 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08262 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08263 mtd->pvt = i;
08264 memcpy(mtd->buf, buf, res);
08265 mtd->len = res;
08266 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08267 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08268 ast_free(mtd);
08269 }
08270 i->mwimonitoractive = 1;
08271 }
08272 }
08273 } else if (i->cidspill) {
08274
08275 if (res > i->cidlen - i->cidpos)
08276 res = i->cidlen - i->cidpos;
08277 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
08278 if (res2 > 0) {
08279 i->cidpos += res2;
08280 if (i->cidpos >= i->cidlen) {
08281 free(i->cidspill);
08282 i->cidspill = 0;
08283 i->cidpos = 0;
08284 i->cidlen = 0;
08285 }
08286 } else {
08287 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
08288 i->msgstate = -1;
08289 }
08290 }
08291 } else {
08292 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08293 }
08294 }
08295 if (pollres & POLLPRI) {
08296 if (i->owner || i->subs[SUB_REAL].owner) {
08297 #ifdef HAVE_PRI
08298 if (!i->pri)
08299 #endif
08300 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08301 i = i->next;
08302 continue;
08303 }
08304 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08305 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08306
08307 ast_mutex_unlock(&iflock);
08308 handle_init_event(i, res);
08309 ast_mutex_lock(&iflock);
08310 }
08311 }
08312 i=i->next;
08313 }
08314 ast_mutex_unlock(&iflock);
08315 }
08316
08317 return NULL;
08318
08319 }
08320
08321 static int restart_monitor(void)
08322 {
08323
08324 if (monitor_thread == AST_PTHREADT_STOP)
08325 return 0;
08326 ast_mutex_lock(&monlock);
08327 if (monitor_thread == pthread_self()) {
08328 ast_mutex_unlock(&monlock);
08329 ast_log(LOG_WARNING, "Cannot kill myself\n");
08330 return -1;
08331 }
08332 if (monitor_thread != AST_PTHREADT_NULL) {
08333
08334 pthread_kill(monitor_thread, SIGURG);
08335 } else {
08336
08337 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08338 ast_mutex_unlock(&monlock);
08339 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08340 return -1;
08341 }
08342 }
08343 ast_mutex_unlock(&monlock);
08344 return 0;
08345 }
08346
08347 #ifdef HAVE_PRI
08348 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08349 {
08350 int x;
08351 int trunkgroup;
08352
08353 trunkgroup = pris[*span].mastertrunkgroup;
08354 if (trunkgroup) {
08355
08356 for (x = 0; x < NUM_SPANS; x++) {
08357 if (pris[x].trunkgroup == trunkgroup) {
08358 *span = x;
08359 return 0;
08360 }
08361 }
08362 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08363 *span = -1;
08364 } else {
08365 if (pris[*span].trunkgroup) {
08366 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08367 *span = -1;
08368 } else if (pris[*span].mastertrunkgroup) {
08369 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08370 *span = -1;
08371 } else {
08372 if (si->totalchans == 31) {
08373
08374 pris[*span].dchannels[0] = 16 + offset;
08375 } else if (si->totalchans == 24) {
08376
08377 pris[*span].dchannels[0] = 24 + offset;
08378 } else if (si->totalchans == 3) {
08379
08380 pris[*span].dchannels[0] = 3 + offset;
08381 } else {
08382 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);
08383 *span = -1;
08384 return 0;
08385 }
08386 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08387 pris[*span].offset = offset;
08388 pris[*span].span = *span + 1;
08389 }
08390 }
08391 return 0;
08392 }
08393
08394 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08395 {
08396 struct dahdi_spaninfo si;
08397 struct dahdi_params p;
08398 int fd;
08399 int span;
08400 int ospan=0;
08401 int x,y;
08402 for (x = 0; x < NUM_SPANS; x++) {
08403 if (pris[x].trunkgroup == trunkgroup) {
08404 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08405 return -1;
08406 }
08407 }
08408 for (y = 0; y < NUM_DCHANS; y++) {
08409 if (!channels[y])
08410 break;
08411 memset(&si, 0, sizeof(si));
08412 memset(&p, 0, sizeof(p));
08413 fd = open("/dev/dahdi/channel", O_RDWR);
08414 if (fd < 0) {
08415 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08416 return -1;
08417 }
08418 x = channels[y];
08419 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08420 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08421 close(fd);
08422 return -1;
08423 }
08424 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08425 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08426 return -1;
08427 }
08428 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08429 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08430 close(fd);
08431 return -1;
08432 }
08433 span = p.spanno - 1;
08434 if (pris[span].trunkgroup) {
08435 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08436 close(fd);
08437 return -1;
08438 }
08439 if (pris[span].pvts[0]) {
08440 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08441 close(fd);
08442 return -1;
08443 }
08444 if (!y) {
08445 pris[span].trunkgroup = trunkgroup;
08446 pris[span].offset = channels[y] - p.chanpos;
08447 ospan = span;
08448 }
08449 pris[ospan].dchannels[y] = channels[y];
08450 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08451 pris[span].span = span + 1;
08452 close(fd);
08453 }
08454 return 0;
08455 }
08456
08457 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08458 {
08459 if (pris[span].mastertrunkgroup) {
08460 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);
08461 return -1;
08462 }
08463 pris[span].mastertrunkgroup = trunkgroup;
08464 pris[span].prilogicalspan = logicalspan;
08465 return 0;
08466 }
08467
08468 #endif
08469
08470 #ifdef HAVE_SS7
08471
08472 static unsigned int parse_pointcode(const char *pcstring)
08473 {
08474 unsigned int code1, code2, code3;
08475 int numvals;
08476
08477 numvals = sscanf(pcstring, "%d-%d-%d", &code1, &code2, &code3);
08478 if (numvals == 1)
08479 return code1;
08480 if (numvals == 3)
08481 return (code1 << 16) | (code2 << 8) | code3;
08482
08483 return 0;
08484 }
08485
08486 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
08487 {
08488 if ((linkset < 0) || (linkset >= NUM_SPANS))
08489 return NULL;
08490 else
08491 return &linksets[linkset - 1];
08492 }
08493 #endif
08494
08495
08496
08497
08498
08499
08500 static int sigtype_to_signalling(int sigtype)
08501 {
08502 return sigtype;
08503 }
08504
08505 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08506 {
08507
08508 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08509 char fn[80];
08510 struct dahdi_bufferinfo bi;
08511 int res;
08512 int span = 0;
08513 int here = 0;
08514 int x;
08515 struct dahdi_pvt **wlist;
08516 struct dahdi_pvt **wend;
08517 struct dahdi_params p;
08518
08519 wlist = &iflist;
08520 wend = &ifend;
08521
08522 #ifdef HAVE_PRI
08523 if (pri) {
08524 wlist = &pri->crvs;
08525 wend = &pri->crvend;
08526 }
08527 #endif
08528
08529 tmp2 = *wlist;
08530 prev = NULL;
08531
08532 while (tmp2) {
08533 if (!tmp2->destroy) {
08534 if (tmp2->channel == channel) {
08535 tmp = tmp2;
08536 here = 1;
08537 break;
08538 }
08539 if (tmp2->channel > channel) {
08540 break;
08541 }
08542 }
08543 prev = tmp2;
08544 tmp2 = tmp2->next;
08545 }
08546
08547 if (!here && reloading != 1) {
08548 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08549 if (tmp)
08550 free(tmp);
08551 return NULL;
08552 }
08553 ast_mutex_init(&tmp->lock);
08554 ifcount++;
08555 for (x = 0; x < 3; x++)
08556 tmp->subs[x].dfd = -1;
08557 tmp->channel = channel;
08558 }
08559
08560 if (tmp) {
08561 int chan_sig = conf->chan.sig;
08562 if (!here) {
08563 if ((channel != CHAN_PSEUDO) && !pri) {
08564 int count = 0;
08565 snprintf(fn, sizeof(fn), "%d", channel);
08566
08567 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08568 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08569 usleep(1);
08570 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08571 count++;
08572 }
08573
08574 if (tmp->subs[SUB_REAL].dfd < 0) {
08575 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);
08576 destroy_dahdi_pvt(&tmp);
08577 return NULL;
08578 }
08579 memset(&p, 0, sizeof(p));
08580 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08581 if (res < 0) {
08582 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08583 destroy_dahdi_pvt(&tmp);
08584 return NULL;
08585 }
08586 if (conf->is_sig_auto)
08587 chan_sig = sigtype_to_signalling(p.sigtype);
08588 if (p.sigtype != (chan_sig & 0x3ffff)) {
08589 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));
08590 destroy_dahdi_pvt(&tmp);
08591 return NULL;
08592 }
08593 tmp->law = p.curlaw;
08594 tmp->span = p.spanno;
08595 span = p.spanno - 1;
08596 } else {
08597 if (channel == CHAN_PSEUDO)
08598 chan_sig = 0;
08599 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08600 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08601 return NULL;
08602 }
08603 }
08604 #ifdef HAVE_SS7
08605 if (chan_sig == SIG_SS7) {
08606 struct dahdi_ss7 *ss7;
08607 int clear = 0;
08608 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08609 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08610 destroy_dahdi_pvt(&tmp);
08611 return NULL;
08612 }
08613
08614 ss7 = ss7_resolve_linkset(cur_linkset);
08615 if (!ss7) {
08616 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08617 destroy_dahdi_pvt(&tmp);
08618 return NULL;
08619 }
08620 if (cur_cicbeginswith < 0) {
08621 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08622 destroy_dahdi_pvt(&tmp);
08623 return NULL;
08624 }
08625
08626 tmp->cic = cur_cicbeginswith++;
08627
08628
08629 tmp->dpc = cur_defaultdpc;
08630
08631 tmp->ss7 = ss7;
08632 tmp->ss7call = NULL;
08633 ss7->pvts[ss7->numchans++] = tmp;
08634
08635 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
08636 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
08637 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
08638 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
08639
08640 ss7->called_nai = conf->ss7.called_nai;
08641 ss7->calling_nai = conf->ss7.calling_nai;
08642 }
08643 #endif
08644 #ifdef HAVE_PRI
08645 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08646 int offset;
08647 int myswitchtype;
08648 int matchesdchan;
08649 int x,y;
08650 offset = 0;
08651 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
08652 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08653 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08654 destroy_dahdi_pvt(&tmp);
08655 return NULL;
08656 }
08657 if (span >= NUM_SPANS) {
08658 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08659 destroy_dahdi_pvt(&tmp);
08660 return NULL;
08661 } else {
08662 struct dahdi_spaninfo si;
08663 si.spanno = 0;
08664 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08665 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08666 destroy_dahdi_pvt(&tmp);
08667 return NULL;
08668 }
08669
08670 tmp->logicalspan = pris[span].prilogicalspan;
08671 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08672 if (span < 0) {
08673 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08674 destroy_dahdi_pvt(&tmp);
08675 return NULL;
08676 }
08677 if ((chan_sig == SIG_PRI) ||
08678 (chan_sig == SIG_BRI) ||
08679 (chan_sig == SIG_BRI_PTMP))
08680 myswitchtype = conf->pri.switchtype;
08681 else
08682 myswitchtype = PRI_SWITCH_GR303_TMC;
08683
08684 matchesdchan=0;
08685 for (x = 0; x < NUM_SPANS; x++) {
08686 for (y = 0; y < NUM_DCHANS; y++) {
08687 if (pris[x].dchannels[y] == tmp->channel) {
08688 matchesdchan = 1;
08689 break;
08690 }
08691 }
08692 }
08693 offset = p.chanpos;
08694 if (!matchesdchan) {
08695 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08696 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08697 destroy_dahdi_pvt(&tmp);
08698 return NULL;
08699 }
08700 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08701 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08702 destroy_dahdi_pvt(&tmp);
08703 return NULL;
08704 }
08705 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08706 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08707 destroy_dahdi_pvt(&tmp);
08708 return NULL;
08709 }
08710 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08711 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08712 destroy_dahdi_pvt(&tmp);
08713 return NULL;
08714 }
08715 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08716 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08717 destroy_dahdi_pvt(&tmp);
08718 return NULL;
08719 }
08720 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08721 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08722 destroy_dahdi_pvt(&tmp);
08723 return NULL;
08724 }
08725 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08726 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08727 destroy_dahdi_pvt(&tmp);
08728 return NULL;
08729 }
08730 if (pris[span].numchans >= MAX_CHANNELS) {
08731 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08732 pris[span].trunkgroup);
08733 destroy_dahdi_pvt(&tmp);
08734 return NULL;
08735 }
08736
08737 pris[span].sig = chan_sig;
08738 pris[span].nodetype = conf->pri.nodetype;
08739 pris[span].switchtype = myswitchtype;
08740 pris[span].nsf = conf->pri.nsf;
08741 pris[span].dialplan = conf->pri.dialplan;
08742 pris[span].localdialplan = conf->pri.localdialplan;
08743 pris[span].pvts[pris[span].numchans++] = tmp;
08744 pris[span].minunused = conf->pri.minunused;
08745 pris[span].minidle = conf->pri.minidle;
08746 pris[span].overlapdial = conf->pri.overlapdial;
08747 #ifdef HAVE_PRI_INBANDDISCONNECT
08748 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08749 #endif
08750 pris[span].facilityenable = conf->pri.facilityenable;
08751 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08752 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08753 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08754 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08755 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08756 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08757 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08758 pris[span].resetinterval = conf->pri.resetinterval;
08759
08760 tmp->pri = &pris[span];
08761 tmp->prioffset = offset;
08762 tmp->call = NULL;
08763 } else {
08764 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08765 destroy_dahdi_pvt(&tmp);
08766 return NULL;
08767 }
08768 }
08769 } else {
08770 tmp->prioffset = 0;
08771 }
08772 #endif
08773 } else {
08774 chan_sig = tmp->sig;
08775 if (tmp->subs[SUB_REAL].dfd > -1) {
08776 memset(&p, 0, sizeof(p));
08777 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08778 }
08779 }
08780
08781 switch (chan_sig) {
08782 case SIG_FXSKS:
08783 case SIG_FXSLS:
08784 case SIG_EM:
08785 case SIG_EM_E1:
08786 case SIG_EMWINK:
08787 case SIG_FEATD:
08788 case SIG_FEATDMF:
08789 case SIG_FEATDMF_TA:
08790 case SIG_FEATB:
08791 case SIG_E911:
08792 case SIG_SF:
08793 case SIG_SFWINK:
08794 case SIG_FGC_CAMA:
08795 case SIG_FGC_CAMAMF:
08796 case SIG_SF_FEATD:
08797 case SIG_SF_FEATDMF:
08798 case SIG_SF_FEATB:
08799 p.starttime = 250;
08800 break;
08801 }
08802
08803 if (tmp->radio) {
08804
08805 p.channo = channel;
08806 p.rxwinktime = 1;
08807 p.rxflashtime = 1;
08808 p.starttime = 1;
08809 p.debouncetime = 5;
08810 }
08811 if (!tmp->radio) {
08812 p.channo = channel;
08813
08814 if (conf->timing.prewinktime >= 0)
08815 p.prewinktime = conf->timing.prewinktime;
08816 if (conf->timing.preflashtime >= 0)
08817 p.preflashtime = conf->timing.preflashtime;
08818 if (conf->timing.winktime >= 0)
08819 p.winktime = conf->timing.winktime;
08820 if (conf->timing.flashtime >= 0)
08821 p.flashtime = conf->timing.flashtime;
08822 if (conf->timing.starttime >= 0)
08823 p.starttime = conf->timing.starttime;
08824 if (conf->timing.rxwinktime >= 0)
08825 p.rxwinktime = conf->timing.rxwinktime;
08826 if (conf->timing.rxflashtime >= 0)
08827 p.rxflashtime = conf->timing.rxflashtime;
08828 if (conf->timing.debouncetime >= 0)
08829 p.debouncetime = conf->timing.debouncetime;
08830 }
08831
08832
08833 if (tmp->subs[SUB_REAL].dfd >= 0)
08834 {
08835 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
08836 if (res < 0) {
08837 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
08838 destroy_dahdi_pvt(&tmp);
08839 return NULL;
08840 }
08841 }
08842 #if 1
08843 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
08844 memset(&bi, 0, sizeof(bi));
08845 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08846 if (!res) {
08847 bi.txbufpolicy = conf->chan.buf_policy;
08848 bi.rxbufpolicy = conf->chan.buf_policy;
08849 bi.numbufs = conf->chan.buf_no;
08850 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08851 if (res < 0) {
08852 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
08853 }
08854 } else
08855 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
08856 }
08857 #endif
08858 tmp->immediate = conf->chan.immediate;
08859 tmp->transfertobusy = conf->chan.transfertobusy;
08860 if (chan_sig & __DAHDI_SIG_FXS) {
08861 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
08862 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
08863 }
08864 tmp->sig = chan_sig;
08865 tmp->outsigmod = conf->chan.outsigmod;
08866 tmp->ringt_base = ringt_base;
08867 tmp->firstradio = 0;
08868 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
08869 tmp->permcallwaiting = conf->chan.callwaiting;
08870 else
08871 tmp->permcallwaiting = 0;
08872
08873 tmp->destroy = 0;
08874 tmp->drings = conf->chan.drings;
08875
08876
08877 if (tmp->drings.ringnum[0].range == 0)
08878 tmp->drings.ringnum[0].range = 10;
08879 if (tmp->drings.ringnum[1].range == 0)
08880 tmp->drings.ringnum[1].range = 10;
08881 if (tmp->drings.ringnum[2].range == 0)
08882 tmp->drings.ringnum[2].range = 10;
08883
08884 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
08885 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
08886 tmp->threewaycalling = conf->chan.threewaycalling;
08887 tmp->adsi = conf->chan.adsi;
08888 tmp->use_smdi = conf->chan.use_smdi;
08889 tmp->permhidecallerid = conf->chan.hidecallerid;
08890 tmp->callreturn = conf->chan.callreturn;
08891 tmp->echocancel = conf->chan.echocancel;
08892 tmp->echotraining = conf->chan.echotraining;
08893 tmp->pulse = conf->chan.pulse;
08894 if (tmp->echocancel.head.tap_length) {
08895 tmp->echocanbridged = conf->chan.echocanbridged;
08896 } else {
08897 if (conf->chan.echocanbridged)
08898 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
08899 tmp->echocanbridged = 0;
08900 }
08901 tmp->busydetect = conf->chan.busydetect;
08902 tmp->busycount = conf->chan.busycount;
08903 tmp->busycompare = conf->chan.busycompare;
08904 tmp->busytonelength = conf->chan.busytonelength;
08905 tmp->busyquietlength = conf->chan.busyquietlength;
08906 tmp->busyfuzziness = conf->chan.busyfuzziness;
08907 tmp->silencethreshold = conf->chan.silencethreshold;
08908 tmp->callprogress = conf->chan.callprogress;
08909 tmp->cancallforward = conf->chan.cancallforward;
08910 tmp->dtmfrelax = conf->chan.dtmfrelax;
08911 tmp->callwaiting = tmp->permcallwaiting;
08912 tmp->hidecallerid = tmp->permhidecallerid;
08913 tmp->channel = channel;
08914 tmp->stripmsd = conf->chan.stripmsd;
08915 tmp->use_callerid = conf->chan.use_callerid;
08916 tmp->cid_signalling = conf->chan.cid_signalling;
08917 tmp->cid_start = conf->chan.cid_start;
08918 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
08919 tmp->restrictcid = conf->chan.restrictcid;
08920 tmp->use_callingpres = conf->chan.use_callingpres;
08921 tmp->priindication_oob = conf->chan.priindication_oob;
08922 tmp->priexclusive = conf->chan.priexclusive;
08923 if (tmp->usedistinctiveringdetection) {
08924 if (!tmp->use_callerid) {
08925 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
08926 tmp->use_callerid = 1;
08927 }
08928 }
08929
08930 if (tmp->cid_signalling == CID_SIG_SMDI) {
08931 if (!tmp->use_smdi) {
08932 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
08933 tmp->use_smdi = 1;
08934 }
08935 }
08936 if (tmp->use_smdi) {
08937 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
08938 if (!(tmp->smdi_iface)) {
08939 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
08940 tmp->use_smdi = 0;
08941 }
08942 }
08943
08944 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
08945 tmp->amaflags = conf->chan.amaflags;
08946 if (!here) {
08947 tmp->confno = -1;
08948 tmp->propconfno = -1;
08949 }
08950 tmp->canpark = conf->chan.canpark;
08951 tmp->transfer = conf->chan.transfer;
08952 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
08953 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
08954 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
08955 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
08956 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
08957 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
08958 tmp->cid_ton = 0;
08959 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
08960 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
08961 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
08962 char *mailbox, *context;
08963 mailbox = context = ast_strdupa(tmp->mailbox);
08964 strsep(&context, "@");
08965 if (ast_strlen_zero(context))
08966 context = "default";
08967 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
08968 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
08969 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
08970 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
08971 AST_EVENT_IE_END);
08972 }
08973 tmp->msgstate = -1;
08974 tmp->group = conf->chan.group;
08975 tmp->callgroup = conf->chan.callgroup;
08976 tmp->pickupgroup= conf->chan.pickupgroup;
08977 if (conf->chan.vars) {
08978 tmp->vars = conf->chan.vars;
08979 }
08980 tmp->cid_rxgain = conf->chan.cid_rxgain;
08981 tmp->rxgain = conf->chan.rxgain;
08982 tmp->txgain = conf->chan.txgain;
08983 tmp->tonezone = conf->chan.tonezone;
08984 tmp->onhooktime = time(NULL);
08985 if (tmp->subs[SUB_REAL].dfd > -1) {
08986 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
08987 if (tmp->dsp)
08988 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
08989 update_conf(tmp);
08990 if (!here) {
08991 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
08992
08993 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08994 }
08995 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
08996 #ifdef HAVE_PRI
08997
08998 if (tmp->pri && !pri_is_up(tmp->pri))
08999 tmp->inalarm = 1;
09000 #endif
09001 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09002 tmp->inalarm = 1;
09003 handle_alarms(tmp, res);
09004 }
09005 }
09006
09007 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09008 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09009 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09010 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09011 if (!here) {
09012 tmp->locallyblocked = tmp->remotelyblocked = 0;
09013 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09014 tmp->inservice = 0;
09015 else
09016 tmp->inservice = 1;
09017 }
09018 }
09019 if (tmp && !here) {
09020
09021 if (!*wlist) {
09022 *wlist = tmp;
09023 tmp->prev = NULL;
09024 tmp->next = NULL;
09025 *wend = tmp;
09026 } else {
09027
09028 struct dahdi_pvt *working = *wlist;
09029
09030
09031 if (working->channel > tmp->channel) {
09032 tmp->next = *wlist;
09033 tmp->prev = NULL;
09034 (*wlist)->prev = tmp;
09035 *wlist = tmp;
09036 } else {
09037
09038 while (working) {
09039
09040 if (working->next) {
09041 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09042 tmp->next = working->next;
09043 tmp->prev = working;
09044 working->next->prev = tmp;
09045 working->next = tmp;
09046 break;
09047 }
09048 } else {
09049
09050 if (working->channel < tmp->channel) {
09051 working->next = tmp;
09052 tmp->next = NULL;
09053 tmp->prev = working;
09054 *wend = tmp;
09055 break;
09056 }
09057 }
09058 working = working->next;
09059 }
09060 }
09061 }
09062 }
09063 return tmp;
09064 }
09065
09066 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09067 {
09068 int res;
09069 struct dahdi_params par;
09070
09071
09072 if (groupmatch) {
09073 if ((p->group & groupmatch) != groupmatch)
09074 return 0;
09075 *groupmatched = 1;
09076 }
09077
09078 if (channelmatch != -1) {
09079 if (p->channel != channelmatch)
09080 return 0;
09081 *channelmatched = 1;
09082 }
09083
09084 if (busy) {
09085 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09086 *busy = 1;
09087 }
09088
09089 if (p->dnd)
09090 return 0;
09091
09092 if (p->guardtime && (time(NULL) < p->guardtime))
09093 return 0;
09094
09095 if (p->locallyblocked || p->remotelyblocked)
09096 return 0;
09097
09098
09099 if (!p->owner) {
09100 #ifdef HAVE_PRI
09101
09102 if (p->pri) {
09103 if (p->resetting || p->call)
09104 return 0;
09105 else
09106 return 1;
09107 }
09108 #endif
09109 #ifdef HAVE_SS7
09110
09111 if (p->ss7) {
09112 if (p->ss7call)
09113 return 0;
09114 else
09115 return 1;
09116 }
09117 #endif
09118 if (!(p->radio || (p->oprmode < 0)))
09119 {
09120 if (!p->sig || (p->sig == SIG_FXSLS))
09121 return 1;
09122
09123 if (p->subs[SUB_REAL].dfd > -1) {
09124 memset(&par, 0, sizeof(par));
09125 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09126 } else {
09127
09128 res = 0;
09129 par.rxisoffhook = 0;
09130 }
09131 if (res) {
09132 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09133 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09134
09135
09136
09137 if (par.rxbits > -1)
09138 return 1;
09139 if (par.rxisoffhook)
09140 return 1;
09141 else
09142 return 0;
09143 } else if (par.rxisoffhook) {
09144 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09145
09146 #ifdef DAHDI_CHECK_HOOKSTATE
09147 return 0;
09148 #else
09149 return 1;
09150 #endif
09151 }
09152 }
09153 return 1;
09154 }
09155
09156
09157 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09158 return 0;
09159
09160 if (!p->callwaiting) {
09161
09162 return 0;
09163 }
09164
09165 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09166
09167 return 0;
09168 }
09169
09170 if ((p->owner->_state != AST_STATE_UP) &&
09171 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09172
09173 return 0;
09174 }
09175 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09176
09177 return 0;
09178 }
09179
09180 return 1;
09181 }
09182
09183 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09184 {
09185 struct dahdi_pvt *p;
09186 struct dahdi_bufferinfo bi;
09187 int res;
09188
09189 if ((p = ast_malloc(sizeof(*p)))) {
09190 memcpy(p, src, sizeof(struct dahdi_pvt));
09191 ast_mutex_init(&p->lock);
09192 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09193
09194 if (p->subs[SUB_REAL].dfd < 0) {
09195 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09196 destroy_dahdi_pvt(&p);
09197 return NULL;
09198 }
09199 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09200 if (!res) {
09201 bi.txbufpolicy = src->buf_policy;
09202 bi.rxbufpolicy = src->buf_policy;
09203 bi.numbufs = src->buf_no;
09204 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09205 if (res < 0) {
09206 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09207 }
09208 } else
09209 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09210 }
09211 p->destroy = 1;
09212 p->next = iflist;
09213 p->prev = NULL;
09214 iflist = p;
09215 if (iflist->next)
09216 iflist->next->prev = p;
09217 return p;
09218 }
09219
09220
09221 #ifdef HAVE_PRI
09222 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09223 {
09224 int x;
09225 if (backwards)
09226 x = pri->numchans;
09227 else
09228 x = 0;
09229 for (;;) {
09230 if (backwards && (x < 0))
09231 break;
09232 if (!backwards && (x >= pri->numchans))
09233 break;
09234 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09235 ast_debug(1, "Found empty available channel %d/%d\n",
09236 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09237 return x;
09238 }
09239 if (backwards)
09240 x--;
09241 else
09242 x++;
09243 }
09244 return -1;
09245 }
09246 #endif
09247
09248 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09249 {
09250 ast_group_t groupmatch = 0;
09251 int channelmatch = -1;
09252 int roundrobin = 0;
09253 int callwait = 0;
09254 int busy = 0;
09255 struct dahdi_pvt *p;
09256 struct ast_channel *tmp = NULL;
09257 char *dest=NULL;
09258 int x;
09259 char *s;
09260 char opt=0;
09261 int res=0, y=0;
09262 int backwards = 0;
09263 #ifdef HAVE_PRI
09264 int crv;
09265 int bearer = -1;
09266 int trunkgroup;
09267 struct dahdi_pri *pri=NULL;
09268 #endif
09269 struct dahdi_pvt *exit, *start, *end;
09270 ast_mutex_t *lock;
09271 int channelmatched = 0;
09272 int groupmatched = 0;
09273
09274
09275
09276
09277
09278
09279
09280
09281
09282
09283
09284
09285
09286
09287
09288
09289
09290
09291
09292 lock = &iflock;
09293 start = iflist;
09294 end = ifend;
09295 if (data) {
09296 dest = ast_strdupa((char *)data);
09297 } else {
09298 ast_log(LOG_WARNING, "Channel requested with no data\n");
09299 return NULL;
09300 }
09301 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09302
09303 char *stringp;
09304
09305 stringp = dest + 1;
09306 s = strsep(&stringp, "/");
09307 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
09308 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09309 return NULL;
09310 }
09311 groupmatch = ((ast_group_t) 1 << x);
09312 if (toupper(dest[0]) == 'G') {
09313 if (dest[0] == 'G') {
09314 backwards = 1;
09315 p = ifend;
09316 } else
09317 p = iflist;
09318 } else {
09319 if (dest[0] == 'R') {
09320 backwards = 1;
09321 p = round_robin[x]?round_robin[x]->prev:ifend;
09322 if (!p)
09323 p = ifend;
09324 } else {
09325 p = round_robin[x]?round_robin[x]->next:iflist;
09326 if (!p)
09327 p = iflist;
09328 }
09329 roundrobin = 1;
09330 }
09331 } else {
09332 char *stringp;
09333
09334 stringp = dest;
09335 s = strsep(&stringp, "/");
09336 p = iflist;
09337 if (!strcasecmp(s, "pseudo")) {
09338
09339 x = CHAN_PSEUDO;
09340 channelmatch = x;
09341 }
09342 #ifdef HAVE_PRI
09343 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
09344 if ((trunkgroup < 1) || (crv < 1)) {
09345 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09346 return NULL;
09347 }
09348 res--;
09349 for (x = 0; x < NUM_SPANS; x++) {
09350 if (pris[x].trunkgroup == trunkgroup) {
09351 pri = pris + x;
09352 lock = &pri->lock;
09353 start = pri->crvs;
09354 end = pri->crvend;
09355 break;
09356 }
09357 }
09358 if (!pri) {
09359 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09360 return NULL;
09361 }
09362 channelmatch = crv;
09363 p = pris[x].crvs;
09364 }
09365 #endif
09366 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
09367 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09368 return NULL;
09369 } else {
09370 channelmatch = x;
09371 }
09372 }
09373
09374 ast_mutex_lock(lock);
09375 exit = p;
09376 while (p && !tmp) {
09377 if (roundrobin)
09378 round_robin[x] = p;
09379 #if 0
09380 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09381 #endif
09382
09383 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09384 ast_debug(1, "Using channel %d\n", p->channel);
09385 if (p->inalarm)
09386 goto next;
09387
09388 callwait = (p->owner != NULL);
09389 #ifdef HAVE_PRI
09390 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09391 if (p->sig != SIG_FXSKS) {
09392
09393
09394 bearer = pri_find_empty_chan(pri, 0);
09395 if (bearer < 0) {
09396 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09397 p = NULL;
09398 break;
09399 }
09400 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09401 } else {
09402 if (alloc_sub(p, 0)) {
09403 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09404 p = NULL;
09405 break;
09406 } else
09407 ast_debug(1, "Allocated placeholder pseudo channel\n");
09408
09409 p->pri = pri;
09410 }
09411 }
09412 #endif
09413 if (p->channel == CHAN_PSEUDO) {
09414 p = chandup(p);
09415 if (!p) {
09416 break;
09417 }
09418 }
09419 if (p->owner) {
09420 if (alloc_sub(p, SUB_CALLWAIT)) {
09421 p = NULL;
09422 break;
09423 }
09424 }
09425 p->outgoing = 1;
09426 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09427 #ifdef HAVE_PRI
09428 if (p->bearer) {
09429
09430 p->bearer->owner = tmp;
09431 }
09432 #endif
09433
09434 if (res > 1) {
09435 if (opt == 'c') {
09436
09437 p->confirmanswer = 1;
09438 } else if (opt == 'r') {
09439
09440 if (res < 3)
09441 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09442 else
09443 p->distinctivering = y;
09444 } else if (opt == 'd') {
09445
09446 p->digital = 1;
09447 if (tmp)
09448 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09449 } else {
09450 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09451 }
09452 }
09453
09454 if (tmp && callwait)
09455 tmp->cdrflags |= AST_CDR_CALLWAIT;
09456 break;
09457 }
09458 next:
09459 if (backwards) {
09460 p = p->prev;
09461 if (!p)
09462 p = end;
09463 } else {
09464 p = p->next;
09465 if (!p)
09466 p = start;
09467 }
09468
09469 if (p == exit)
09470 break;
09471 }
09472 ast_mutex_unlock(lock);
09473 restart_monitor();
09474 if (callwait)
09475 *cause = AST_CAUSE_BUSY;
09476 else if (!tmp) {
09477 if (channelmatched) {
09478 if (busy)
09479 *cause = AST_CAUSE_BUSY;
09480 } else if (groupmatched) {
09481 *cause = AST_CAUSE_CONGESTION;
09482 }
09483 }
09484
09485 return tmp;
09486 }
09487
09488 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09489 static int dahdi_setlaw(int dfd, int law)
09490 {
09491 return ioctl(dfd, DAHDI_SETLAW, &law);
09492 }
09493 #endif
09494
09495 #ifdef HAVE_SS7
09496
09497 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
09498 {
09499 int i;
09500 int winner = -1;
09501 for (i = 0; i < linkset->numchans; i++) {
09502 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09503 winner = i;
09504 break;
09505 }
09506 }
09507 return winner;
09508 }
09509
09510 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09511 {
09512 unsigned char status[32];
09513 struct dahdi_pvt *p = NULL;
09514 int i, offset;
09515
09516 for (i = 0; i < linkset->numchans; i++) {
09517 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09518 p = linkset->pvts[i];
09519 offset = p->cic - startcic;
09520 status[offset] = 0;
09521 if (p->locallyblocked)
09522 status[offset] |= (1 << 0) | (1 << 4);
09523 if (p->remotelyblocked)
09524 status[offset] |= (1 << 1) | (1 << 5);
09525 if (p->ss7call) {
09526 if (p->outgoing)
09527 status[offset] |= (1 << 3);
09528 else
09529 status[offset] |= (1 << 2);
09530 } else
09531 status[offset] |= 0x3 << 2;
09532 }
09533 }
09534
09535 if (p)
09536 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09537 else
09538 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09539
09540 }
09541
09542 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
09543 {
09544 int i;
09545
09546 for (i = 0; i < linkset->numchans; i++) {
09547 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09548 if (state) {
09549 if (state[i])
09550 linkset->pvts[i]->remotelyblocked = block;
09551 } else
09552 linkset->pvts[i]->remotelyblocked = block;
09553 }
09554 }
09555 }
09556
09557 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09558 {
09559 int i;
09560
09561 for (i = 0; i < linkset->numchans; i++) {
09562 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09563 linkset->pvts[i]->inservice = 1;
09564 }
09565 }
09566
09567 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
09568 {
09569 int i, startcic = -1, endcic, dpc;
09570
09571 if (linkset->numchans <= 0)
09572 return;
09573
09574 startcic = linkset->pvts[0]->cic;
09575
09576 dpc = linkset->pvts[0]->dpc;
09577
09578 for (i = 0; i < linkset->numchans; i++) {
09579 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)) {
09580 continue;
09581 } else {
09582 endcic = linkset->pvts[i]->cic;
09583 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09584 isup_grs(linkset->ss7, startcic, endcic, dpc);
09585
09586
09587 if (linkset->pvts[i+1]) {
09588 startcic = linkset->pvts[i+1]->cic;
09589 dpc = linkset->pvts[i+1]->dpc;
09590 }
09591 }
09592 }
09593 }
09594
09595 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
09596 {
09597 if (p->loopedback != enable) {
09598 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09599 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09600 return;
09601 }
09602 p->loopedback = enable;
09603 }
09604 }
09605
09606
09607 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
09608 {
09609 struct ss7 *ss7 = linkset->ss7;
09610 int res;
09611 int law = 1;
09612 struct ast_channel *c;
09613 char tmp[256];
09614
09615 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09616 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09617
09618 if (linkset->type == SS7_ITU)
09619 law = DAHDI_LAW_ALAW;
09620 else
09621 law = DAHDI_LAW_MULAW;
09622
09623 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09624 if (res < 0)
09625 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09626
09627 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09628 p->proceeding = 1;
09629 isup_acm(ss7, p->ss7call);
09630 }
09631
09632 ast_mutex_unlock(&linkset->lock);
09633 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09634
09635 if (!c) {
09636 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09637
09638 ast_mutex_lock(&linkset->lock);
09639 return;
09640 } else
09641 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09642
09643 dahdi_enable_ec(p);
09644
09645
09646
09647
09648
09649 ast_mutex_unlock(&p->lock);
09650
09651 if (!ast_strlen_zero(p->charge_number)) {
09652 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09653
09654 p->charge_number[0] = 0;
09655 }
09656 if (!ast_strlen_zero(p->gen_add_number)) {
09657 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09658
09659 p->gen_add_number[0] = 0;
09660 }
09661 if (!ast_strlen_zero(p->jip_number)) {
09662 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09663
09664 p->jip_number[0] = 0;
09665 }
09666 if (!ast_strlen_zero(p->gen_dig_number)) {
09667 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09668
09669 p->gen_dig_number[0] = 0;
09670 }
09671 if (!ast_strlen_zero(p->orig_called_num)) {
09672 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09673
09674 p->orig_called_num[0] = 0;
09675 }
09676
09677 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09678 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09679
09680 p->gen_dig_type = 0;
09681
09682 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09683 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09684
09685 p->gen_dig_scheme = 0;
09686
09687 if (!ast_strlen_zero(p->lspi_ident)) {
09688 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
09689
09690 p->lspi_ident[0] = 0;
09691 }
09692
09693 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
09694 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
09695
09696 p->call_ref_ident = 0;
09697
09698 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
09699 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
09700
09701 p->call_ref_pc = 0;
09702
09703 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
09704 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
09705
09706 p->calling_party_cat = 0;
09707
09708 if (!ast_strlen_zero(p->redirecting_num)) {
09709 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
09710
09711 p->redirecting_num[0] = 0;
09712 }
09713 if (!ast_strlen_zero(p->generic_name)) {
09714 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
09715
09716 p->generic_name[0] = 0;
09717 }
09718
09719 ast_mutex_lock(&p->lock);
09720 ast_mutex_lock(&linkset->lock);
09721 }
09722
09723 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
09724 {
09725 if (ast_strlen_zero(number)) {
09726 if (size) {
09727 *buf = '\0';
09728 }
09729 return;
09730 }
09731 switch (nai) {
09732 case SS7_NAI_INTERNATIONAL:
09733 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
09734 break;
09735 case SS7_NAI_NATIONAL:
09736 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
09737 break;
09738 case SS7_NAI_SUBSCRIBER:
09739 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
09740 break;
09741 case SS7_NAI_UNKNOWN:
09742 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
09743 break;
09744 default:
09745 snprintf(buf, size, "%s", number);
09746 break;
09747 }
09748 }
09749 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
09750 {
09751 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
09752 }
09753
09754 static void *ss7_linkset(void *data)
09755 {
09756 int res, i;
09757 struct timeval *next = NULL, tv;
09758 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
09759 struct ss7 *ss7 = linkset->ss7;
09760 ss7_event *e = NULL;
09761 struct dahdi_pvt *p;
09762 int chanpos;
09763 struct pollfd pollers[NUM_DCHANS];
09764 int cic;
09765 unsigned int dpc;
09766 int nextms = 0;
09767
09768 ss7_start(ss7);
09769
09770 while(1) {
09771 ast_mutex_lock(&linkset->lock);
09772 if ((next = ss7_schedule_next(ss7))) {
09773 tv = ast_tvnow();
09774 tv.tv_sec = next->tv_sec - tv.tv_sec;
09775 tv.tv_usec = next->tv_usec - tv.tv_usec;
09776 if (tv.tv_usec < 0) {
09777 tv.tv_usec += 1000000;
09778 tv.tv_sec -= 1;
09779 }
09780 if (tv.tv_sec < 0) {
09781 tv.tv_sec = 0;
09782 tv.tv_usec = 0;
09783 }
09784 nextms = tv.tv_sec * 1000;
09785 nextms += tv.tv_usec / 1000;
09786 }
09787 ast_mutex_unlock(&linkset->lock);
09788
09789 for (i = 0; i < linkset->numsigchans; i++) {
09790 pollers[i].fd = linkset->fds[i];
09791 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
09792 pollers[i].revents = 0;
09793 }
09794
09795 res = poll(pollers, linkset->numsigchans, nextms);
09796 if ((res < 0) && (errno != EINTR)) {
09797 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
09798 } else if (!res) {
09799 ast_mutex_lock(&linkset->lock);
09800 ss7_schedule_run(ss7);
09801 ast_mutex_unlock(&linkset->lock);
09802 continue;
09803 }
09804
09805 ast_mutex_lock(&linkset->lock);
09806 for (i = 0; i < linkset->numsigchans; i++) {
09807 if (pollers[i].revents & POLLPRI) {
09808 int x;
09809 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
09810 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
09811 }
09812 switch (x) {
09813 case DAHDI_EVENT_OVERRUN:
09814 ast_debug(1, "Overrun detected!\n");
09815 break;
09816 case DAHDI_EVENT_BADFCS:
09817 ast_debug(1, "Bad FCS\n");
09818 break;
09819 case DAHDI_EVENT_ABORT:
09820 ast_debug(1, "HDLC Abort\n");
09821 break;
09822 case DAHDI_EVENT_ALARM:
09823 ast_log(LOG_ERROR, "Alarm on link!\n");
09824 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
09825 linkset->linkstate[i] &= ~LINKSTATE_UP;
09826 ss7_link_alarm(ss7, pollers[i].fd);
09827 break;
09828 case DAHDI_EVENT_NOALARM:
09829 ast_log(LOG_ERROR, "Alarm cleared on link\n");
09830 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
09831 linkset->linkstate[i] |= LINKSTATE_STARTING;
09832 ss7_link_noalarm(ss7, pollers[i].fd);
09833 break;
09834 default:
09835 ast_log(LOG_ERROR, "Got exception %d!\n", x);
09836 break;
09837 }
09838 }
09839
09840 if (pollers[i].revents & POLLIN) {
09841 ast_mutex_lock(&linkset->lock);
09842 res = ss7_read(ss7, pollers[i].fd);
09843 ast_mutex_unlock(&linkset->lock);
09844 }
09845
09846 if (pollers[i].revents & POLLOUT) {
09847 ast_mutex_lock(&linkset->lock);
09848 res = ss7_write(ss7, pollers[i].fd);
09849 ast_mutex_unlock(&linkset->lock);
09850 if (res < 0) {
09851 ast_debug(1, "Error in write %s\n", strerror(errno));
09852 }
09853 }
09854 }
09855
09856 while ((e = ss7_check_event(ss7))) {
09857 switch (e->e) {
09858 case SS7_EVENT_UP:
09859 if (linkset->state != LINKSET_STATE_UP) {
09860 ast_verbose("--- SS7 Up ---\n");
09861 ss7_reset_linkset(linkset);
09862 }
09863 linkset->state = LINKSET_STATE_UP;
09864 break;
09865 case SS7_EVENT_DOWN:
09866 ast_verbose("--- SS7 Down ---\n");
09867 linkset->state = LINKSET_STATE_DOWN;
09868 for (i = 0; i < linkset->numchans; i++) {
09869 struct dahdi_pvt *p = linkset->pvts[i];
09870 if (p)
09871 p->inalarm = 1;
09872 }
09873 break;
09874 case MTP2_LINK_UP:
09875 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
09876 break;
09877 case MTP2_LINK_DOWN:
09878 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
09879 break;
09880 case ISUP_EVENT_CPG:
09881 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
09882 if (chanpos < 0) {
09883 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
09884 break;
09885 }
09886 p = linkset->pvts[chanpos];
09887 ast_mutex_lock(&p->lock);
09888 switch (e->cpg.event) {
09889 case CPG_EVENT_ALERTING:
09890 p->alerting = 1;
09891 p->subs[SUB_REAL].needringing = 1;
09892 break;
09893 case CPG_EVENT_PROGRESS:
09894 case CPG_EVENT_INBANDINFO:
09895 {
09896 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
09897 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
09898 dahdi_queue_frame(p, &f, linkset);
09899 p->progress = 1;
09900 p->dialing = 0;
09901 if (p->dsp && p->dsp_features) {
09902 ast_dsp_set_features(p->dsp, p->dsp_features);
09903 p->dsp_features = 0;
09904 }
09905 }
09906 break;
09907 default:
09908 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
09909 }
09910
09911 ast_mutex_unlock(&p->lock);
09912 break;
09913 case ISUP_EVENT_RSC:
09914 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
09915 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
09916 if (chanpos < 0) {
09917 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
09918 break;
09919 }
09920 p = linkset->pvts[chanpos];
09921 ast_mutex_lock(&p->lock);
09922
09923 p->inservice = 1;
09924 p->remotelyblocked = 0;
09925 dpc = p->dpc;
09926 isup_set_call_dpc(e->rsc.call, dpc);
09927 if (p->ss7call)
09928 p->ss7call = NULL;
09929 if (p->owner)
09930 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09931
09932 ast_mutex_unlock(&p->lock);
09933
09934 isup_rlc(ss7, e->rsc.call);
09935 break;
09936 case ISUP_EVENT_GRS:
09937 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
09938 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
09939 if (chanpos < 0) {
09940 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
09941 break;
09942 }
09943 p = linkset->pvts[chanpos];
09944 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
09945 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
09946 break;
09947 case ISUP_EVENT_CQM:
09948 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
09949 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
09950 break;
09951 case ISUP_EVENT_GRA:
09952 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
09953 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
09954 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
09955 break;
09956 case ISUP_EVENT_IAM:
09957 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);
09958 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
09959 if (chanpos < 0) {
09960 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
09961 isup_rel(ss7, e->iam.call, -1);
09962 break;
09963 }
09964 p = linkset->pvts[chanpos];
09965 ast_mutex_lock(&p->lock);
09966 if (p->owner) {
09967 if (p->ss7call == e->iam.call) {
09968 ast_mutex_unlock(&p->lock);
09969 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
09970 break;
09971 } else {
09972 ast_mutex_unlock(&p->lock);
09973 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
09974 break;
09975 }
09976 }
09977
09978 dpc = p->dpc;
09979 p->ss7call = e->iam.call;
09980 isup_set_call_dpc(p->ss7call, dpc);
09981
09982 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
09983 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
09984 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
09985 } else
09986 p->cid_num[0] = 0;
09987
09988 if (p->immediate) {
09989 p->exten[0] = 's';
09990 p->exten[1] = '\0';
09991 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
09992 char *st;
09993 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
09994 st = strchr(p->exten, '#');
09995 if (st)
09996 *st = '\0';
09997 } else
09998 p->exten[0] = '\0';
09999
10000 p->cid_ani[0] = '\0';
10001 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
10002 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
10003 else
10004 p->cid_name[0] = '\0';
10005
10006 p->cid_ani2 = e->iam.oli_ani2;
10007 p->cid_ton = 0;
10008 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
10009 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
10010 p->gen_add_type = e->iam.gen_add_type;
10011 p->gen_add_nai = e->iam.gen_add_nai;
10012 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
10013 p->gen_add_num_plan = e->iam.gen_add_num_plan;
10014 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
10015 p->gen_dig_type = e->iam.gen_dig_type;
10016 p->gen_dig_scheme = e->iam.gen_dig_scheme;
10017 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
10018 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
10019 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
10020 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
10021 p->calling_party_cat = e->iam.calling_party_cat;
10022
10023
10024 if (!ast_strlen_zero(e->iam.called_party_num))
10025 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
10026
10027 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
10028
10029 if (e->iam.cot_check_required) {
10030 dahdi_loopback(p, 1);
10031 } else
10032 ss7_start_call(p, linkset);
10033 } else {
10034 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
10035 isup_rel(ss7, e->iam.call, -1);
10036 }
10037 ast_mutex_unlock(&p->lock);
10038 break;
10039 case ISUP_EVENT_COT:
10040 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
10041 if (chanpos < 0) {
10042 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
10043 isup_rel(ss7, e->cot.call, -1);
10044 break;
10045 }
10046 p = linkset->pvts[chanpos];
10047
10048 ast_mutex_lock(&p->lock);
10049
10050 if (p->loopedback) {
10051 dahdi_loopback(p, 0);
10052 ss7_start_call(p, linkset);
10053 }
10054
10055 ast_mutex_unlock(&p->lock);
10056
10057 break;
10058 case ISUP_EVENT_CCR:
10059 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
10060 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
10061 if (chanpos < 0) {
10062 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
10063 break;
10064 }
10065
10066 p = linkset->pvts[chanpos];
10067
10068 ast_mutex_lock(&p->lock);
10069 dahdi_loopback(p, 1);
10070 ast_mutex_unlock(&p->lock);
10071
10072 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
10073 break;
10074 case ISUP_EVENT_CVT:
10075 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
10076 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
10077 if (chanpos < 0) {
10078 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
10079 break;
10080 }
10081
10082 p = linkset->pvts[chanpos];
10083
10084 ast_mutex_lock(&p->lock);
10085 dahdi_loopback(p, 1);
10086 ast_mutex_unlock(&p->lock);
10087
10088 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
10089 break;
10090 case ISUP_EVENT_REL:
10091 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
10092 if (chanpos < 0) {
10093 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
10094 break;
10095 }
10096 p = linkset->pvts[chanpos];
10097 ast_mutex_lock(&p->lock);
10098 if (p->owner) {
10099 p->owner->hangupcause = e->rel.cause;
10100 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10101 } else if (!p->restartpending)
10102 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
10103
10104
10105 dahdi_loopback(p, 0);
10106
10107 isup_rlc(ss7, e->rel.call);
10108 p->ss7call = NULL;
10109
10110 ast_mutex_unlock(&p->lock);
10111 break;
10112 case ISUP_EVENT_ACM:
10113 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
10114 if (chanpos < 0) {
10115 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
10116 isup_rel(ss7, e->acm.call, -1);
10117 break;
10118 } else {
10119 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10120
10121 p = linkset->pvts[chanpos];
10122
10123 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
10124
10125 if (e->acm.call_ref_ident > 0) {
10126 p->rlt = 1;
10127 }
10128
10129 ast_mutex_lock(&p->lock);
10130 dahdi_queue_frame(p, &f, linkset);
10131 p->proceeding = 1;
10132 p->dialing = 0;
10133
10134 if (e->acm.called_party_status_ind == 1) {
10135 p->alerting = 1;
10136 p->subs[SUB_REAL].needringing = 1;
10137 }
10138 ast_mutex_unlock(&p->lock);
10139 }
10140 break;
10141 case ISUP_EVENT_CGB:
10142 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
10143 if (chanpos < 0) {
10144 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
10145 break;
10146 }
10147 p = linkset->pvts[chanpos];
10148 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
10149 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
10150 break;
10151 case ISUP_EVENT_CGU:
10152 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
10153 if (chanpos < 0) {
10154 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
10155 break;
10156 }
10157 p = linkset->pvts[chanpos];
10158 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
10159 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
10160 break;
10161 case ISUP_EVENT_UCIC:
10162 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
10163 if (chanpos < 0) {
10164 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
10165 break;
10166 }
10167 p = linkset->pvts[chanpos];
10168 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
10169 ast_mutex_lock(&p->lock);
10170 p->remotelyblocked = 1;
10171 p->inservice = 0;
10172 ast_mutex_unlock(&p->lock);
10173 break;
10174 case ISUP_EVENT_BLO:
10175 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
10176 if (chanpos < 0) {
10177 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
10178 break;
10179 }
10180 p = linkset->pvts[chanpos];
10181 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
10182 ast_mutex_lock(&p->lock);
10183 p->remotelyblocked = 1;
10184 ast_mutex_unlock(&p->lock);
10185 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
10186 break;
10187 case ISUP_EVENT_BLA:
10188 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
10189 if (chanpos < 0) {
10190 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
10191 break;
10192 }
10193 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
10194 p = linkset->pvts[chanpos];
10195 ast_mutex_lock(&p->lock);
10196 p->locallyblocked = 1;
10197 ast_mutex_unlock(&p->lock);
10198 break;
10199 case ISUP_EVENT_UBL:
10200 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
10201 if (chanpos < 0) {
10202 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
10203 break;
10204 }
10205 p = linkset->pvts[chanpos];
10206 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
10207 ast_mutex_lock(&p->lock);
10208 p->remotelyblocked = 0;
10209 ast_mutex_unlock(&p->lock);
10210 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
10211 break;
10212 case ISUP_EVENT_UBA:
10213 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
10214 if (chanpos < 0) {
10215 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
10216 break;
10217 }
10218 p = linkset->pvts[chanpos];
10219 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
10220 ast_mutex_lock(&p->lock);
10221 p->locallyblocked = 0;
10222 ast_mutex_unlock(&p->lock);
10223 break;
10224 case ISUP_EVENT_CON:
10225 case ISUP_EVENT_ANM:
10226 if (e->e == ISUP_EVENT_CON)
10227 cic = e->con.cic;
10228 else
10229 cic = e->anm.cic;
10230
10231 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
10232 if (chanpos < 0) {
10233 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
10234 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
10235 break;
10236 } else {
10237 p = linkset->pvts[chanpos];
10238 ast_mutex_lock(&p->lock);
10239 p->subs[SUB_REAL].needanswer = 1;
10240 if (p->dsp && p->dsp_features) {
10241 ast_dsp_set_features(p->dsp, p->dsp_features);
10242 p->dsp_features = 0;
10243 }
10244 dahdi_enable_ec(p);
10245 ast_mutex_unlock(&p->lock);
10246 }
10247 break;
10248 case ISUP_EVENT_RLC:
10249 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
10250 if (chanpos < 0) {
10251 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
10252 break;
10253 } else {
10254 p = linkset->pvts[chanpos];
10255 ast_mutex_lock(&p->lock);
10256 if (p->alreadyhungup)
10257 p->ss7call = NULL;
10258 else
10259 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
10260 ast_mutex_unlock(&p->lock);
10261 }
10262 break;
10263 case ISUP_EVENT_FAA:
10264 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
10265 if (chanpos < 0) {
10266 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
10267 break;
10268 } else {
10269 p = linkset->pvts[chanpos];
10270 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
10271 ast_mutex_lock(&p->lock);
10272 if (p->alreadyhungup){
10273 p->ss7call = NULL;
10274 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
10275 }
10276 ast_mutex_unlock(&p->lock);
10277 }
10278 break;
10279 default:
10280 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
10281 break;
10282 }
10283 }
10284 ast_mutex_unlock(&linkset->lock);
10285 }
10286
10287 return 0;
10288 }
10289
10290 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
10291 {
10292 #if 0
10293 int i;
10294
10295 for (i = 0; i < NUM_SPANS; i++)
10296 if (linksets[i].ss7 == ss7)
10297 break;
10298
10299 ast_verbose("[%d] %s", i+1, s);
10300 #else
10301 ast_verbose("%s", s);
10302 #endif
10303 }
10304
10305 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
10306 {
10307 #if 0
10308 int i;
10309
10310 for (i = 0; i < NUM_SPANS; i++)
10311 if (linksets[i].ss7 == ss7)
10312 break;
10313
10314 #else
10315 ast_log(LOG_ERROR, "%s", s);
10316 #endif
10317 }
10318
10319 #endif
10320
10321 #ifdef HAVE_PRI
10322 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10323 {
10324 struct dahdi_pvt *p;
10325 p = pri->crvs;
10326 while (p) {
10327 if (p->channel == crv)
10328 return p;
10329 p = p->next;
10330 }
10331 return NULL;
10332 }
10333
10334
10335 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10336 {
10337 int x;
10338 int span = PRI_SPAN(channel);
10339 int spanfd;
10340 struct dahdi_params param;
10341 int principle = -1;
10342 int explicit = PRI_EXPLICIT(channel);
10343 channel = PRI_CHANNEL(channel);
10344
10345 if (!explicit) {
10346 spanfd = pri_active_dchan_fd(pri);
10347 memset(¶m, 0, sizeof(param));
10348 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
10349 return -1;
10350 span = pris[param.spanno - 1].prilogicalspan;
10351 }
10352
10353 for (x = 0; x < pri->numchans; x++) {
10354 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10355 principle = x;
10356 break;
10357 }
10358 }
10359
10360 return principle;
10361 }
10362
10363 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10364 {
10365 int x;
10366 struct dahdi_pvt *crv;
10367 if (!c) {
10368 if (principle < 0)
10369 return -1;
10370 return principle;
10371 }
10372 if ((principle > -1) &&
10373 (principle < pri->numchans) &&
10374 (pri->pvts[principle]) &&
10375 (pri->pvts[principle]->call == c))
10376 return principle;
10377
10378 for (x = 0; x < pri->numchans; x++) {
10379 if (!pri->pvts[x])
10380 continue;
10381 if (pri->pvts[x]->call == c) {
10382
10383 if (principle != x) {
10384 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10385
10386 ast_verb(3, "Moving call from channel %d to channel %d\n",
10387 old->channel, new->channel);
10388 if (new->owner) {
10389 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10390 old->channel, new->channel, new->channel);
10391 return -1;
10392 }
10393
10394 new->owner = old->owner;
10395 old->owner = NULL;
10396 if (new->owner) {
10397 ast_string_field_build(new->owner, name,
10398 "DAHDI/%d:%d-%d", pri->trunkgroup,
10399 new->channel, 1);
10400 new->owner->tech_pvt = new;
10401 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10402 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10403 old->subs[SUB_REAL].owner = NULL;
10404 } else
10405 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);
10406 new->call = old->call;
10407 old->call = NULL;
10408
10409
10410 new->dsp = old->dsp;
10411 new->dsp_features = old->dsp_features;
10412 old->dsp = NULL;
10413 old->dsp_features = 0;
10414 }
10415 return principle;
10416 }
10417 }
10418
10419 crv = pri->crvs;
10420 while (crv) {
10421 if (crv->call == c) {
10422
10423 if (crv->bearer)
10424 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10425 else if (pri->pvts[principle]->owner)
10426 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10427 else {
10428
10429
10430 dahdi_close_sub(crv, SUB_REAL);
10431 pri->pvts[principle]->call = crv->call;
10432 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10433 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10434 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10435 pri->trunkgroup, crv->channel);
10436 wakeup_sub(crv, SUB_REAL, pri);
10437 }
10438 return principle;
10439 }
10440 crv = crv->next;
10441 }
10442 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10443 return -1;
10444 }
10445
10446 static void *do_idle_thread(void *vchan)
10447 {
10448 struct ast_channel *chan = vchan;
10449 struct dahdi_pvt *pvt = chan->tech_pvt;
10450 struct ast_frame *f;
10451 char ex[80];
10452
10453 int newms, ms = 30000;
10454 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10455 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10456 if (ast_call(chan, ex, 0)) {
10457 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10458 ast_hangup(chan);
10459 return NULL;
10460 }
10461 while ((newms = ast_waitfor(chan, ms)) > 0) {
10462 f = ast_read(chan);
10463 if (!f) {
10464
10465 break;
10466 }
10467 if (f->frametype == AST_FRAME_CONTROL) {
10468 switch (f->subclass) {
10469 case AST_CONTROL_ANSWER:
10470
10471 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10472 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10473 chan->priority = 1;
10474 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10475 ast_pbx_run(chan);
10476
10477 return NULL;
10478 case AST_CONTROL_BUSY:
10479 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10480 break;
10481 case AST_CONTROL_CONGESTION:
10482 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10483 break;
10484 };
10485 }
10486 ast_frfree(f);
10487 ms = newms;
10488 }
10489
10490 ast_hangup(chan);
10491 return NULL;
10492 }
10493
10494 #ifndef PRI_RESTART
10495 #error "Upgrade your libpri"
10496 #endif
10497 static void dahdi_pri_message(struct pri *pri, char *s)
10498 {
10499 int x, y;
10500 int dchan = -1, span = -1;
10501 int dchancount = 0;
10502
10503 if (pri) {
10504 for (x = 0; x < NUM_SPANS; x++) {
10505 for (y = 0; y < NUM_DCHANS; y++) {
10506 if (pris[x].dchans[y])
10507 dchancount++;
10508
10509 if (pris[x].dchans[y] == pri)
10510 dchan = y;
10511 }
10512 if (dchan >= 0) {
10513 span = x;
10514 break;
10515 }
10516 dchancount = 0;
10517 }
10518 if (dchancount > 1 && (span > -1))
10519 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10520 else
10521 ast_verbose("%s", s);
10522 } else
10523 ast_verbose("%s", s);
10524
10525 ast_mutex_lock(&pridebugfdlock);
10526
10527 if (pridebugfd >= 0) {
10528 if (write(pridebugfd, s, strlen(s)) < 0) {
10529 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10530 }
10531 }
10532
10533 ast_mutex_unlock(&pridebugfdlock);
10534 }
10535
10536 static void dahdi_pri_error(struct pri *pri, char *s)
10537 {
10538 int x, y;
10539 int dchan = -1, span = -1;
10540 int dchancount = 0;
10541
10542 if (pri) {
10543 for (x = 0; x < NUM_SPANS; x++) {
10544 for (y = 0; y < NUM_DCHANS; y++) {
10545 if (pris[x].dchans[y])
10546 dchancount++;
10547
10548 if (pris[x].dchans[y] == pri)
10549 dchan = y;
10550 }
10551 if (dchan >= 0) {
10552 span = x;
10553 break;
10554 }
10555 dchancount = 0;
10556 }
10557 if ((dchancount > 1) && (span > -1))
10558 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10559 else
10560 ast_log(LOG_ERROR, "%s", s);
10561 } else
10562 ast_log(LOG_ERROR, "%s", s);
10563
10564 ast_mutex_lock(&pridebugfdlock);
10565
10566 if (pridebugfd >= 0) {
10567 if (write(pridebugfd, s, strlen(s)) < 0) {
10568 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10569 }
10570 }
10571
10572 ast_mutex_unlock(&pridebugfdlock);
10573 }
10574
10575 static int pri_check_restart(struct dahdi_pri *pri)
10576 {
10577 do {
10578 pri->resetpos++;
10579 } while ((pri->resetpos < pri->numchans) &&
10580 (!pri->pvts[pri->resetpos] ||
10581 pri->pvts[pri->resetpos]->call ||
10582 pri->pvts[pri->resetpos]->resetting));
10583 if (pri->resetpos < pri->numchans) {
10584
10585 pri->pvts[pri->resetpos]->resetting = 1;
10586 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10587 } else {
10588 pri->resetting = 0;
10589 time(&pri->lastreset);
10590 }
10591 return 0;
10592 }
10593
10594 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10595 {
10596 int x;
10597 int redo;
10598 ast_mutex_unlock(&pri->lock);
10599 ast_mutex_lock(&p->lock);
10600 do {
10601 redo = 0;
10602 for (x = 0; x < 3; x++) {
10603 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10604 redo++;
10605 DEADLOCK_AVOIDANCE(&p->lock);
10606 }
10607 if (p->subs[x].owner) {
10608 ast_queue_hangup(p->subs[x].owner);
10609 ast_channel_unlock(p->subs[x].owner);
10610 }
10611 }
10612 } while (redo);
10613 ast_mutex_unlock(&p->lock);
10614 ast_mutex_lock(&pri->lock);
10615 return 0;
10616 }
10617
10618 static char * redirectingreason2str(int redirectingreason)
10619 {
10620 switch (redirectingreason) {
10621 case 0:
10622 return "UNKNOWN";
10623 case 1:
10624 return "BUSY";
10625 case 2:
10626 return "NO_REPLY";
10627 case 0xF:
10628 return "UNCONDITIONAL";
10629 default:
10630 return "NOREDIRECT";
10631 }
10632 }
10633
10634 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10635 {
10636 if (pri->dialplan == -2) {
10637 snprintf(buf, size, "%s", number);
10638 return;
10639 }
10640 if (ast_strlen_zero(number)) {
10641 if (size) {
10642 *buf = '\0';
10643 }
10644 return;
10645 }
10646 switch (plan) {
10647 case PRI_INTERNATIONAL_ISDN:
10648 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10649 break;
10650 case PRI_NATIONAL_ISDN:
10651 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10652 break;
10653 case PRI_LOCAL_ISDN:
10654 snprintf(buf, size, "%s%s", pri->localprefix, number);
10655 break;
10656 case PRI_PRIVATE:
10657 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10658 break;
10659 case PRI_UNKNOWN:
10660 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10661 break;
10662 default:
10663 snprintf(buf, size, "%s", number);
10664 break;
10665 }
10666 }
10667
10668
10669 static void *pri_dchannel(void *vpri)
10670 {
10671 struct dahdi_pri *pri = vpri;
10672 pri_event *e;
10673 struct pollfd fds[NUM_DCHANS];
10674 int res;
10675 int chanpos = 0;
10676 int x;
10677 int haveidles;
10678 int activeidles;
10679 int nextidle = -1;
10680 struct ast_channel *c;
10681 struct timeval tv, lowest, *next;
10682 struct timeval lastidle = ast_tvnow();
10683 int doidling=0;
10684 char *cc;
10685 char idlen[80];
10686 struct ast_channel *idle;
10687 pthread_t p;
10688 time_t t;
10689 int i, which=-1;
10690 int numdchans;
10691 int cause=0;
10692 struct dahdi_pvt *crv;
10693 pthread_t threadid;
10694 char ani2str[6];
10695 char plancallingnum[256];
10696 char plancallingani[256];
10697 char calledtonstr[10];
10698
10699 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10700
10701 gettimeofday(&lastidle, NULL);
10702 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10703
10704 cc = strchr(pri->idleext, '@');
10705 if (cc) {
10706 *cc = '\0';
10707 cc++;
10708 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10709 #if 0
10710
10711 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10712 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10713 else
10714 #endif
10715 doidling = 1;
10716 } else
10717 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10718 }
10719 for (;;) {
10720 for (i = 0; i < NUM_DCHANS; i++) {
10721 if (!pri->dchannels[i])
10722 break;
10723 fds[i].fd = pri->fds[i];
10724 fds[i].events = POLLIN | POLLPRI;
10725 fds[i].revents = 0;
10726 }
10727 numdchans = i;
10728 time(&t);
10729 ast_mutex_lock(&pri->lock);
10730 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10731 if (pri->resetting && pri_is_up(pri)) {
10732 if (pri->resetpos < 0)
10733 pri_check_restart(pri);
10734 } else {
10735 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10736 pri->resetting = 1;
10737 pri->resetpos = -1;
10738 }
10739 }
10740 }
10741
10742 if (doidling && pri_is_up(pri)) {
10743 nextidle = -1;
10744 haveidles = 0;
10745 activeidles = 0;
10746 for (x = pri->numchans; x >= 0; x--) {
10747 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10748 !pri->pvts[x]->call) {
10749 if (haveidles < pri->minunused) {
10750 haveidles++;
10751 } else if (!pri->pvts[x]->resetting) {
10752 nextidle = x;
10753 break;
10754 }
10755 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10756 activeidles++;
10757 }
10758 if (nextidle > -1) {
10759 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10760
10761 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10762 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
10763 if (idle) {
10764 pri->pvts[nextidle]->isidlecall = 1;
10765 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10766 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10767 dahdi_hangup(idle);
10768 }
10769 } else
10770 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10771 lastidle = ast_tvnow();
10772 }
10773 } else if ((haveidles < pri->minunused) &&
10774 (activeidles > pri->minidle)) {
10775
10776
10777 for (x = pri->numchans; x >= 0; x--) {
10778
10779 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10780 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10781 haveidles++;
10782
10783
10784 if ((haveidles >= pri->minunused) ||
10785 (activeidles <= pri->minidle))
10786 break;
10787 }
10788 }
10789 }
10790 }
10791
10792 lowest = ast_tv(60, 0);
10793 for (i = 0; i < NUM_DCHANS; i++) {
10794
10795 if (!pri->dchannels[i])
10796 break;
10797 if ((next = pri_schedule_next(pri->dchans[i]))) {
10798
10799 tv = ast_tvsub(*next, ast_tvnow());
10800 if (tv.tv_sec < 0) {
10801 tv = ast_tv(0,0);
10802 }
10803 if (doidling || pri->resetting) {
10804 if (tv.tv_sec > 1) {
10805 tv = ast_tv(1, 0);
10806 }
10807 } else {
10808 if (tv.tv_sec > 60) {
10809 tv = ast_tv(60, 0);
10810 }
10811 }
10812 } else if (doidling || pri->resetting) {
10813
10814
10815 tv = ast_tv(1,0);
10816 } else {
10817
10818 tv = ast_tv(60, 0);
10819 }
10820 if (!i || ast_tvcmp(tv, lowest) < 0) {
10821 lowest = tv;
10822 }
10823 }
10824 ast_mutex_unlock(&pri->lock);
10825
10826 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10827 pthread_testcancel();
10828 e = NULL;
10829 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10830 pthread_testcancel();
10831 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10832
10833 ast_mutex_lock(&pri->lock);
10834 if (!res) {
10835 for (which = 0; which < NUM_DCHANS; which++) {
10836 if (!pri->dchans[which])
10837 break;
10838
10839 e = pri_schedule_run(pri->dchans[which]);
10840 if (e)
10841 break;
10842 }
10843 } else if (res > -1) {
10844 for (which = 0; which < NUM_DCHANS; which++) {
10845 if (!pri->dchans[which])
10846 break;
10847 if (fds[which].revents & POLLPRI) {
10848
10849 x = 0;
10850 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10851 if (x) {
10852 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);
10853 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
10854 "PRIEvent: %s\r\n"
10855 "PRIEventCode: %d\r\n"
10856 "D-channel: %s\r\n"
10857 "Span: %d\r\n",
10858 event2str(x),
10859 x,
10860 pri_order(which),
10861 pri->span
10862 );
10863 }
10864
10865 if (x == DAHDI_EVENT_ALARM) {
10866 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10867 pri_find_dchan(pri);
10868 } else if (x == DAHDI_EVENT_NOALARM) {
10869 pri->dchanavail[which] |= DCHAN_NOTINALARM;
10870 pri_restart(pri->dchans[which]);
10871 }
10872
10873 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10874 } else if (fds[which].revents & POLLIN) {
10875 e = pri_check_event(pri->dchans[which]);
10876 }
10877 if (e)
10878 break;
10879 }
10880 } else if (errno != EINTR)
10881 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10882
10883 if (e) {
10884 if (pri->debug)
10885 pri_dump_event(pri->dchans[which], e);
10886
10887 if (e->e != PRI_EVENT_DCHAN_DOWN) {
10888 if (!(pri->dchanavail[which] & DCHAN_UP)) {
10889 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10890 }
10891 pri->dchanavail[which] |= DCHAN_UP;
10892 } else if (pri->sig != SIG_BRI_PTMP) {
10893 if (pri->dchanavail[which] & DCHAN_UP) {
10894 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10895 }
10896 pri->dchanavail[which] &= ~DCHAN_UP;
10897 }
10898
10899 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10900
10901 pri->pri = pri->dchans[which];
10902
10903 switch (e->e) {
10904 case PRI_EVENT_DCHAN_UP:
10905 if (!pri->pri) pri_find_dchan(pri);
10906
10907
10908 time(&pri->lastreset);
10909
10910
10911 if (pri->resetinterval > -1) {
10912 pri->lastreset -= pri->resetinterval;
10913 pri->lastreset += 5;
10914 }
10915 pri->resetting = 0;
10916
10917 for (i = 0; i < pri->numchans; i++)
10918 if (pri->pvts[i]) {
10919 pri->pvts[i]->inalarm = 0;
10920 }
10921 break;
10922 case PRI_EVENT_DCHAN_DOWN:
10923 pri_find_dchan(pri);
10924 if (!pri_is_up(pri)) {
10925 pri->resetting = 0;
10926
10927 for (i = 0; i < pri->numchans; i++) {
10928 struct dahdi_pvt *p = pri->pvts[i];
10929 if (p) {
10930 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10931
10932 if (p->call) {
10933 if (p->pri && p->pri->pri) {
10934 pri_hangup(p->pri->pri, p->call, -1);
10935 pri_destroycall(p->pri->pri, p->call);
10936 p->call = NULL;
10937 } else
10938 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10939 }
10940 if (p->realcall) {
10941 pri_hangup_all(p->realcall, pri);
10942 } else if (p->owner)
10943 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10944 }
10945
10946
10947 if (p->sig != SIG_BRI_PTMP) {
10948 p->inalarm = 1;
10949 }
10950 }
10951 }
10952 }
10953 break;
10954 case PRI_EVENT_RESTART:
10955 if (e->restart.channel > -1) {
10956 chanpos = pri_find_principle(pri, e->restart.channel);
10957 if (chanpos < 0)
10958 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10959 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10960 else {
10961 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
10962 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10963 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10964 if (pri->pvts[chanpos]->call) {
10965 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10966 pri->pvts[chanpos]->call = NULL;
10967 }
10968
10969 if (pri->pvts[chanpos]->realcall)
10970 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10971 else if (pri->pvts[chanpos]->owner)
10972 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10973 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10974 }
10975 } else {
10976 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
10977 for (x = 0; x < pri->numchans; x++)
10978 if (pri->pvts[x]) {
10979 ast_mutex_lock(&pri->pvts[x]->lock);
10980 if (pri->pvts[x]->call) {
10981 pri_destroycall(pri->pri, pri->pvts[x]->call);
10982 pri->pvts[x]->call = NULL;
10983 }
10984 if (pri->pvts[chanpos]->realcall)
10985 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10986 else if (pri->pvts[x]->owner)
10987 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10988 ast_mutex_unlock(&pri->pvts[x]->lock);
10989 }
10990 }
10991 break;
10992 case PRI_EVENT_KEYPAD_DIGIT:
10993 chanpos = pri_find_principle(pri, e->digit.channel);
10994 if (chanpos < 0) {
10995 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10996 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10997 } else {
10998 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10999 if (chanpos > -1) {
11000 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11001
11002 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
11003
11004 int digitlen = strlen(e->digit.digits);
11005 char digit;
11006 int i;
11007 for (i = 0; i < digitlen; i++) {
11008 digit = e->digit.digits[i];
11009 {
11010 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11011 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11012 }
11013 }
11014 }
11015 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11016 }
11017 }
11018 break;
11019
11020 case PRI_EVENT_INFO_RECEIVED:
11021 chanpos = pri_find_principle(pri, e->ring.channel);
11022 if (chanpos < 0) {
11023 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
11024 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11025 } else {
11026 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
11027 if (chanpos > -1) {
11028 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11029
11030 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
11031
11032 int digitlen = strlen(e->ring.callednum);
11033 char digit;
11034 int i;
11035 for (i = 0; i < digitlen; i++) {
11036 digit = e->ring.callednum[i];
11037 {
11038 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11039 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11040 }
11041 }
11042 }
11043 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11044 }
11045 }
11046 break;
11047 case PRI_EVENT_RING:
11048 crv = NULL;
11049 if (e->ring.channel == -1)
11050 chanpos = pri_find_empty_chan(pri, 1);
11051 else
11052 chanpos = pri_find_principle(pri, e->ring.channel);
11053
11054 if (chanpos < 0) {
11055 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
11056 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11057 } else {
11058 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11059 if (pri->pvts[chanpos]->owner) {
11060 if (pri->pvts[chanpos]->call == e->ring.call) {
11061 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
11062 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11063 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11064 break;
11065 } else {
11066
11067 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
11068 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11069 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11070 chanpos = -1;
11071 }
11072 }
11073 if (chanpos > -1)
11074 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11075 }
11076 if ((chanpos < 0) && (e->ring.flexible))
11077 chanpos = pri_find_empty_chan(pri, 1);
11078 if (chanpos > -1) {
11079 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11080 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11081
11082 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11083 if (crv)
11084 ast_mutex_lock(&crv->lock);
11085 if (!crv || crv->owner) {
11086 pri->pvts[chanpos]->call = NULL;
11087 if (crv) {
11088 if (crv->owner)
11089 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11090 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);
11091 } else
11092 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);
11093 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11094 if (crv)
11095 ast_mutex_unlock(&crv->lock);
11096 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11097 break;
11098 }
11099 }
11100 pri->pvts[chanpos]->call = e->ring.call;
11101 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11102 if (pri->pvts[chanpos]->use_callerid) {
11103 ast_shrink_phone_number(plancallingnum);
11104 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11105 #ifdef PRI_ANI
11106 if (!ast_strlen_zero(e->ring.callingani)) {
11107 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11108 ast_shrink_phone_number(plancallingani);
11109 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11110 } else {
11111 pri->pvts[chanpos]->cid_ani[0] = '\0';
11112 }
11113 #endif
11114 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11115 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
11116 } else {
11117 pri->pvts[chanpos]->cid_num[0] = '\0';
11118 pri->pvts[chanpos]->cid_ani[0] = '\0';
11119 pri->pvts[chanpos]->cid_name[0] = '\0';
11120 pri->pvts[chanpos]->cid_ton = 0;
11121 }
11122 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11123 e->ring.redirectingnum, e->ring.callingplanrdnis);
11124
11125 if (pri->pvts[chanpos]->immediate) {
11126 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
11127 pri->pvts[chanpos]->exten[0] = 's';
11128 pri->pvts[chanpos]->exten[1] = '\0';
11129 }
11130
11131 else if (!ast_strlen_zero(e->ring.callednum)) {
11132 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11133 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11134 } else if (pri->overlapdial)
11135 pri->pvts[chanpos]->exten[0] = '\0';
11136 else {
11137
11138 pri->pvts[chanpos]->exten[0] = 's';
11139 pri->pvts[chanpos]->exten[1] = '\0';
11140 }
11141
11142 if (!ast_strlen_zero(e->ring.callednum))
11143 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11144
11145 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11146 ast_verb(3, "Going to extension s|1 because of Complete received\n");
11147 pri->pvts[chanpos]->exten[0] = 's';
11148 pri->pvts[chanpos]->exten[1] = '\0';
11149 }
11150
11151 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11152 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11153
11154 int law;
11155 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11156
11157 law = 1;
11158 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11159 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11160 }
11161 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11162 law = DAHDI_LAW_ALAW;
11163 else
11164 law = DAHDI_LAW_MULAW;
11165 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11166 if (res < 0)
11167 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11168 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11169 if (res < 0)
11170 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11171 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11172
11173 pri->pvts[chanpos]->proceeding = 1;
11174 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11175 } else {
11176 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
11177 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11178 else
11179 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11180 }
11181
11182 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11183
11184
11185 if (!e->ring.complete && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11186
11187 ast_mutex_unlock(&pri->lock);
11188 if (crv) {
11189
11190 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11191 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11192 pri->pvts[chanpos]->owner = &inuse;
11193 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11194 } else {
11195 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11196 }
11197
11198 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11199
11200 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11201 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11202 }
11203 if (e->ring.ani2 >= 0) {
11204 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
11205 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11206 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11207 }
11208
11209 #ifdef SUPPORT_USERUSER
11210 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11211 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11212 }
11213 #endif
11214
11215 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11216 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11217 if (e->ring.redirectingreason >= 0)
11218 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11219
11220 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11221 ast_mutex_lock(&pri->lock);
11222 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
11223 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11224 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11225 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11226 } else {
11227 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11228 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11229 if (c)
11230 ast_hangup(c);
11231 else {
11232 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11233 pri->pvts[chanpos]->call = NULL;
11234 }
11235 }
11236 } else {
11237 ast_mutex_unlock(&pri->lock);
11238
11239 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
11240 if (c) {
11241 char calledtonstr[10];
11242
11243 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11244
11245 if (e->ring.ani2 >= 0) {
11246 snprintf(ani2str, 5, "%d", e->ring.ani2);
11247 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11248 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11249 }
11250
11251 #ifdef SUPPORT_USERUSER
11252 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11253 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11254 }
11255 #endif
11256
11257 if (e->ring.redirectingreason >= 0)
11258 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11259
11260 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11261 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11262
11263 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11264 ast_mutex_lock(&pri->lock);
11265
11266 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11267 plancallingnum, pri->pvts[chanpos]->exten,
11268 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11269
11270 dahdi_enable_ec(pri->pvts[chanpos]);
11271 } else {
11272
11273 ast_mutex_lock(&pri->lock);
11274
11275 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11276 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11277 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11278 pri->pvts[chanpos]->call = NULL;
11279 }
11280 }
11281 } else {
11282 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
11283 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
11284 pri->pvts[chanpos]->prioffset, pri->span);
11285 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11286 pri->pvts[chanpos]->call = NULL;
11287 pri->pvts[chanpos]->exten[0] = '\0';
11288 }
11289 if (crv)
11290 ast_mutex_unlock(&crv->lock);
11291 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11292 } else {
11293 if (e->ring.flexible)
11294 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11295 else
11296 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11297 }
11298 break;
11299 case PRI_EVENT_RINGING:
11300 chanpos = pri_find_principle(pri, e->ringing.channel);
11301 if (chanpos < 0) {
11302 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
11303 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11304 } else {
11305 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
11306 if (chanpos < 0) {
11307 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
11308 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11309 } else {
11310 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11311 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11312 dahdi_enable_ec(pri->pvts[chanpos]);
11313 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11314 pri->pvts[chanpos]->alerting = 1;
11315 } else
11316 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11317
11318 #ifdef PRI_PROGRESS_MASK
11319 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11320 #else
11321 if (e->ringing.progress == 8) {
11322 #endif
11323
11324 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11325
11326 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11327 pri->pvts[chanpos]->dsp_features = 0;
11328 }
11329 }
11330
11331 #ifdef SUPPORT_USERUSER
11332 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11333 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11334 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11335 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11336 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11337 }
11338 #endif
11339
11340 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11341 }
11342 }
11343 break;
11344 case PRI_EVENT_PROGRESS:
11345
11346 chanpos = pri_find_principle(pri, e->proceeding.channel);
11347 if (chanpos > -1) {
11348 #ifdef PRI_PROGRESS_MASK
11349 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11350 #else
11351 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11352 #endif
11353 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11354
11355 if (e->proceeding.cause > -1) {
11356 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11357
11358
11359 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11360 if (pri->pvts[chanpos]->owner) {
11361 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11362
11363 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11364 f.subclass = AST_CONTROL_BUSY;
11365 }
11366 }
11367 }
11368
11369 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11370 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11371 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11372 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11373 #ifdef PRI_PROGRESS_MASK
11374 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11375 #else
11376 if (e->proceeding.progress == 8) {
11377 #endif
11378
11379 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11380 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11381 pri->pvts[chanpos]->dsp_features = 0;
11382 }
11383
11384 f.subclass = AST_CONTROL_PROGRESS;
11385 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11386 }
11387 pri->pvts[chanpos]->progress = 1;
11388 pri->pvts[chanpos]->dialing = 0;
11389 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11390 }
11391 }
11392 break;
11393 case PRI_EVENT_PROCEEDING:
11394 chanpos = pri_find_principle(pri, e->proceeding.channel);
11395 if (chanpos > -1) {
11396 if (!pri->pvts[chanpos]->proceeding) {
11397 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11398
11399 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11400 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11401 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11402 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11403 #ifdef PRI_PROGRESS_MASK
11404 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11405 #else
11406 if (e->proceeding.progress == 8) {
11407 #endif
11408
11409 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11410 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11411 pri->pvts[chanpos]->dsp_features = 0;
11412 }
11413
11414 f.subclass = AST_CONTROL_PROGRESS;
11415 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11416 }
11417 pri->pvts[chanpos]->proceeding = 1;
11418 pri->pvts[chanpos]->dialing = 0;
11419 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11420 }
11421 }
11422 break;
11423 case PRI_EVENT_FACNAME:
11424 chanpos = pri_find_principle(pri, e->facname.channel);
11425 if (chanpos < 0) {
11426 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11427 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11428 } else {
11429 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11430 if (chanpos < 0) {
11431 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
11432 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11433 } else {
11434
11435 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11436 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11437 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11438 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11439 dahdi_enable_ec(pri->pvts[chanpos]);
11440 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11441 }
11442 }
11443 break;
11444 case PRI_EVENT_ANSWER:
11445 chanpos = pri_find_principle(pri, e->answer.channel);
11446 if (chanpos < 0) {
11447 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
11448 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11449 } else {
11450 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11451 if (chanpos < 0) {
11452 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
11453 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11454 } else {
11455 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11456
11457
11458
11459
11460
11461 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11462 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11463 pri->pvts[chanpos]->dsp_features = 0;
11464 }
11465 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11466 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11467 x = DAHDI_START;
11468 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11469 if (res < 0) {
11470 if (errno != EINPROGRESS) {
11471 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11472 }
11473 }
11474 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11475 pri->pvts[chanpos]->dialing = 1;
11476
11477 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11478 if (res < 0) {
11479 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11480 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11481 } else
11482 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11483
11484 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11485 } else if (pri->pvts[chanpos]->confirmanswer) {
11486 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11487 } else {
11488 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11489
11490 dahdi_enable_ec(pri->pvts[chanpos]);
11491 }
11492
11493 #ifdef SUPPORT_USERUSER
11494 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11495 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11496 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11497 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11498 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11499 }
11500 #endif
11501
11502 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11503 }
11504 }
11505 break;
11506 case PRI_EVENT_HANGUP:
11507 chanpos = pri_find_principle(pri, e->hangup.channel);
11508 if (chanpos < 0) {
11509 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
11510 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11511 } else {
11512 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11513 if (chanpos > -1) {
11514 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11515 if (!pri->pvts[chanpos]->alreadyhungup) {
11516
11517 pri->pvts[chanpos]->alreadyhungup = 1;
11518 if (pri->pvts[chanpos]->realcall)
11519 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11520 else if (pri->pvts[chanpos]->owner) {
11521
11522 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11523 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11524 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11525 else {
11526 switch (e->hangup.cause) {
11527 case PRI_CAUSE_USER_BUSY:
11528 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11529 break;
11530 case PRI_CAUSE_CALL_REJECTED:
11531 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11532 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11533 case PRI_CAUSE_SWITCH_CONGESTION:
11534 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11535 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11536 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11537 break;
11538 default:
11539 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11540 }
11541 }
11542 }
11543 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11544 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11545 } else {
11546 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11547 pri->pvts[chanpos]->call = NULL;
11548 }
11549 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11550 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11551 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11552 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11553 pri->pvts[chanpos]->resetting = 1;
11554 }
11555 if (e->hangup.aoc_units > -1)
11556 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11557 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11558
11559 #ifdef SUPPORT_USERUSER
11560 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11561 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11562 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11563 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11564 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11565 }
11566 #endif
11567
11568 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11569 } else {
11570 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
11571 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11572 }
11573 }
11574 break;
11575 #ifndef PRI_EVENT_HANGUP_REQ
11576 #error please update libpri
11577 #endif
11578 case PRI_EVENT_HANGUP_REQ:
11579 chanpos = pri_find_principle(pri, e->hangup.channel);
11580 if (chanpos < 0) {
11581 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11582 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11583 } else {
11584 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11585 if (chanpos > -1) {
11586 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11587 if (pri->pvts[chanpos]->realcall)
11588 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11589 else if (pri->pvts[chanpos]->owner) {
11590 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11591 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11592 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11593 else {
11594 switch (e->hangup.cause) {
11595 case PRI_CAUSE_USER_BUSY:
11596 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11597 break;
11598 case PRI_CAUSE_CALL_REJECTED:
11599 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11600 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11601 case PRI_CAUSE_SWITCH_CONGESTION:
11602 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11603 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11604 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11605 break;
11606 default:
11607 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11608 }
11609 }
11610 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);
11611 if (e->hangup.aoc_units > -1)
11612 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11613 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11614 } else {
11615 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11616 pri->pvts[chanpos]->call = NULL;
11617 }
11618 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11619 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11620 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11621 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11622 pri->pvts[chanpos]->resetting = 1;
11623 }
11624
11625 #ifdef SUPPORT_USERUSER
11626 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11627 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11628 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11629 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11630 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11631 }
11632 #endif
11633
11634 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11635 } else {
11636 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);
11637 }
11638 }
11639 break;
11640 case PRI_EVENT_HANGUP_ACK:
11641 chanpos = pri_find_principle(pri, e->hangup.channel);
11642 if (chanpos < 0) {
11643 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11644 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11645 } else {
11646 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11647 if (chanpos > -1) {
11648 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11649 pri->pvts[chanpos]->call = NULL;
11650 pri->pvts[chanpos]->resetting = 0;
11651 if (pri->pvts[chanpos]->owner) {
11652 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11653 }
11654
11655 #ifdef SUPPORT_USERUSER
11656 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11657 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11658 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11659 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11660 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11661 }
11662 #endif
11663
11664 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11665 }
11666 }
11667 break;
11668 case PRI_EVENT_CONFIG_ERR:
11669 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11670 break;
11671 case PRI_EVENT_RESTART_ACK:
11672 chanpos = pri_find_principle(pri, e->restartack.channel);
11673 if (chanpos < 0) {
11674
11675
11676
11677 for (x = 0; x < pri->numchans; x++) {
11678 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11679 chanpos = x;
11680 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11681 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11682 pri->pvts[chanpos]->prioffset, pri->span);
11683 if (pri->pvts[chanpos]->realcall)
11684 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11685 else if (pri->pvts[chanpos]->owner) {
11686 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11687 pri->pvts[chanpos]->prioffset, pri->span);
11688 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11689 }
11690 pri->pvts[chanpos]->resetting = 0;
11691 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11692 pri->pvts[chanpos]->prioffset, pri->span);
11693 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11694 if (pri->resetting)
11695 pri_check_restart(pri);
11696 break;
11697 }
11698 }
11699 if (chanpos < 0) {
11700 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11701 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11702 }
11703 } else {
11704 if (pri->pvts[chanpos]) {
11705 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11706 if (pri->pvts[chanpos]->realcall)
11707 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11708 else if (pri->pvts[chanpos]->owner) {
11709 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11710 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11711 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11712 }
11713 pri->pvts[chanpos]->resetting = 0;
11714 pri->pvts[chanpos]->inservice = 1;
11715 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11716 pri->pvts[chanpos]->prioffset, pri->span);
11717 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11718 if (pri->resetting)
11719 pri_check_restart(pri);
11720 }
11721 }
11722 break;
11723 case PRI_EVENT_SETUP_ACK:
11724 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11725 if (chanpos < 0) {
11726 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11727 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11728 } else {
11729 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11730 if (chanpos > -1) {
11731 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11732 pri->pvts[chanpos]->setup_ack = 1;
11733
11734 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11735 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11736 pri_information(pri->pri, pri->pvts[chanpos]->call,
11737 pri->pvts[chanpos]->dialdest[x]);
11738 }
11739 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11740 } else
11741 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11742 }
11743 break;
11744 case PRI_EVENT_NOTIFY:
11745 chanpos = pri_find_principle(pri, e->notify.channel);
11746 if (chanpos < 0) {
11747 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11748 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11749 } else {
11750 struct ast_frame f = { AST_FRAME_CONTROL, };
11751 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11752 switch (e->notify.info) {
11753 case PRI_NOTIFY_REMOTE_HOLD:
11754 f.subclass = AST_CONTROL_HOLD;
11755 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11756 break;
11757 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11758 f.subclass = AST_CONTROL_UNHOLD;
11759 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11760 break;
11761 }
11762 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11763 }
11764 break;
11765 default:
11766 ast_debug(1, "Event: %d\n", e->e);
11767 }
11768 }
11769 ast_mutex_unlock(&pri->lock);
11770 }
11771
11772 return NULL;
11773 }
11774
11775 static int start_pri(struct dahdi_pri *pri)
11776 {
11777 int res, x;
11778 struct dahdi_params p;
11779 struct dahdi_bufferinfo bi;
11780 struct dahdi_spaninfo si;
11781 int i;
11782
11783 for (i = 0; i < NUM_DCHANS; i++) {
11784 if (!pri->dchannels[i])
11785 break;
11786 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
11787 x = pri->dchannels[i];
11788 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11789 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11790 return -1;
11791 }
11792 memset(&p, 0, sizeof(p));
11793 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11794 if (res) {
11795 dahdi_close_pri_fd(pri, i);
11796 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11797 return -1;
11798 }
11799 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11800 dahdi_close_pri_fd(pri, i);
11801 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
11802 return -1;
11803 }
11804 memset(&si, 0, sizeof(si));
11805 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11806 if (res) {
11807 dahdi_close_pri_fd(pri, i);
11808 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11809 }
11810 if (!si.alarms)
11811 pri->dchanavail[i] |= DCHAN_NOTINALARM;
11812 else
11813 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11814 memset(&bi, 0, sizeof(bi));
11815 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11816 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11817 bi.numbufs = 32;
11818 bi.bufsize = 1024;
11819 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11820 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11821 dahdi_close_pri_fd(pri, i);
11822 return -1;
11823 }
11824 switch (pri->sig) {
11825 case SIG_BRI:
11826 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
11827 break;
11828 case SIG_BRI_PTMP:
11829 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
11830 break;
11831 default:
11832 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11833 }
11834
11835 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11836 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11837 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11838 #ifdef HAVE_PRI_INBANDDISCONNECT
11839 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11840 #endif
11841
11842 if (i)
11843 pri_enslave(pri->dchans[0], pri->dchans[i]);
11844 if (!pri->dchans[i]) {
11845 dahdi_close_pri_fd(pri, i);
11846 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11847 return -1;
11848 }
11849 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11850 pri_set_nsf(pri->dchans[i], pri->nsf);
11851 #ifdef PRI_GETSET_TIMERS
11852 for (x = 0; x < PRI_MAX_TIMERS; x++) {
11853 if (pritimers[x] != 0)
11854 pri_set_timer(pri->dchans[i], x, pritimers[x]);
11855 }
11856 #endif
11857 }
11858
11859 pri->pri = pri->dchans[0];
11860 pri->resetpos = -1;
11861 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11862 for (i = 0; i < NUM_DCHANS; i++) {
11863 if (!pri->dchannels[i])
11864 break;
11865 dahdi_close_pri_fd(pri, i);
11866 }
11867 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11868 return -1;
11869 }
11870 return 0;
11871 }
11872
11873 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
11874 {
11875 int which, span;
11876 char *ret = NULL;
11877
11878 if (pos != rpos)
11879 return ret;
11880
11881 for (which = span = 0; span < NUM_SPANS; span++) {
11882 if (pris[span].pri && ++which > state) {
11883 if (asprintf(&ret, "%d", span + 1) < 0) {
11884 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11885 }
11886 break;
11887 }
11888 }
11889 return ret;
11890 }
11891
11892 static char *complete_span_4(const char *line, const char *word, int pos, int state)
11893 {
11894 return complete_span_helper(line,word,pos,state,3);
11895 }
11896
11897 static char *complete_span_5(const char *line, const char *word, int pos, int state)
11898 {
11899 return complete_span_helper(line,word,pos,state,4);
11900 }
11901
11902 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11903 {
11904 switch (cmd) {
11905 case CLI_INIT:
11906 e->command = "pri unset debug file";
11907 e->usage = "Usage: pri unset debug file\n"
11908 " Stop sending debug output to the previously \n"
11909 " specified file\n";
11910 return NULL;
11911 case CLI_GENERATE:
11912 return NULL;
11913 }
11914
11915 ast_mutex_lock(&pridebugfdlock);
11916 close(pridebugfd);
11917 pridebugfd = -1;
11918 ast_cli(a->fd, "PRI debug output to file disabled\n");
11919 ast_mutex_unlock(&pridebugfdlock);
11920 return CLI_SUCCESS;
11921 }
11922
11923 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11924 {
11925 int myfd;
11926 switch (cmd) {
11927 case CLI_INIT:
11928 e->command = "pri set debug file";
11929 e->usage = "Usage: pri set debug file [output-file]\n"
11930 " Sends PRI debug output to the specified output file\n";
11931 return NULL;
11932 case CLI_GENERATE:
11933 return NULL;
11934 }
11935 if (a->argc < 5)
11936 return CLI_SHOWUSAGE;
11937
11938 if (ast_strlen_zero(a->argv[4]))
11939 return CLI_SHOWUSAGE;
11940
11941 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
11942 if (myfd < 0) {
11943 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
11944 return CLI_SUCCESS;
11945 }
11946
11947 ast_mutex_lock(&pridebugfdlock);
11948
11949 if (pridebugfd >= 0)
11950 close(pridebugfd);
11951
11952 pridebugfd = myfd;
11953 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
11954 ast_mutex_unlock(&pridebugfdlock);
11955 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
11956 return CLI_SUCCESS;
11957 }
11958
11959 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11960 {
11961 int span;
11962 int x;
11963 switch (cmd) {
11964 case CLI_INIT:
11965 e->command = "pri debug span";
11966 e->usage =
11967 "Usage: pri debug span <span>\n"
11968 " Enables debugging on a given PRI span\n";
11969 return NULL;
11970 case CLI_GENERATE:
11971 return complete_span_4(a->line, a->word, a->pos, a->n);
11972 }
11973 if (a->argc < 4) {
11974 return CLI_SHOWUSAGE;
11975 }
11976 span = atoi(a->argv[3]);
11977 if ((span < 1) || (span > NUM_SPANS)) {
11978 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
11979 return CLI_SUCCESS;
11980 }
11981 if (!pris[span-1].pri) {
11982 ast_cli(a->fd, "No PRI running on span %d\n", span);
11983 return CLI_SUCCESS;
11984 }
11985 for (x = 0; x < NUM_DCHANS; x++) {
11986 if (pris[span-1].dchans[x])
11987 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11988 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11989 PRI_DEBUG_Q921_STATE);
11990 }
11991 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
11992 return CLI_SUCCESS;
11993 }
11994
11995
11996
11997 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11998 {
11999 int span;
12000 int x;
12001 switch (cmd) {
12002 case CLI_INIT:
12003 e->command = "pri no debug span";
12004 e->usage =
12005 "Usage: pri no debug span <span>\n"
12006 " Disables debugging on a given PRI span\n";
12007 return NULL;
12008 case CLI_GENERATE:
12009 return complete_span_5(a->line, a->word, a->pos, a->n);
12010 }
12011 if (a->argc < 5)
12012 return CLI_SHOWUSAGE;
12013
12014 span = atoi(a->argv[4]);
12015 if ((span < 1) || (span > NUM_SPANS)) {
12016 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12017 return CLI_SUCCESS;
12018 }
12019 if (!pris[span-1].pri) {
12020 ast_cli(a->fd, "No PRI running on span %d\n", span);
12021 return CLI_SUCCESS;
12022 }
12023 for (x = 0; x < NUM_DCHANS; x++) {
12024 if (pris[span-1].dchans[x])
12025 pri_set_debug(pris[span-1].dchans[x], 0);
12026 }
12027 ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12028 return CLI_SUCCESS;
12029 }
12030
12031 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12032 {
12033 int span;
12034 int x;
12035 switch (cmd) {
12036 case CLI_INIT:
12037 e->command = "pri intensive debug span";
12038 e->usage =
12039 "Usage: pri intensive debug span <span>\n"
12040 " Enables debugging down to the Q.921 level\n";
12041 return NULL;
12042 case CLI_GENERATE:
12043 return complete_span_5(a->line, a->word, a->pos, a->n);
12044 }
12045
12046 if (a->argc < 5)
12047 return CLI_SHOWUSAGE;
12048 span = atoi(a->argv[4]);
12049 if ((span < 1) || (span > NUM_SPANS)) {
12050 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12051 return CLI_SUCCESS;
12052 }
12053 if (!pris[span-1].pri) {
12054 ast_cli(a->fd, "No PRI running on span %d\n", span);
12055 return CLI_SUCCESS;
12056 }
12057 for (x = 0; x < NUM_DCHANS; x++) {
12058 if (pris[span-1].dchans[x])
12059 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12060 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12061 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12062 }
12063 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12064 return CLI_SUCCESS;
12065 }
12066
12067 static void build_status(char *s, size_t len, int status, int active)
12068 {
12069 if (!s || len < 1) {
12070 return;
12071 }
12072 s[0] = '\0';
12073 if (status & DCHAN_PROVISIONED)
12074 strncat(s, "Provisioned, ", len - strlen(s) - 1);
12075 if (!(status & DCHAN_NOTINALARM))
12076 strncat(s, "In Alarm, ", len - strlen(s) - 1);
12077 if (status & DCHAN_UP)
12078 strncat(s, "Up", len - strlen(s) - 1);
12079 else
12080 strncat(s, "Down", len - strlen(s) - 1);
12081 if (active)
12082 strncat(s, ", Active", len - strlen(s) - 1);
12083 else
12084 strncat(s, ", Standby", len - strlen(s) - 1);
12085 s[len - 1] = '\0';
12086 }
12087
12088 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12089 {
12090 int span;
12091 int x;
12092 char status[256];
12093
12094 switch (cmd) {
12095 case CLI_INIT:
12096 e->command = "pri show spans";
12097 e->usage =
12098 "Usage: pri show spans\n"
12099 " Displays PRI Information\n";
12100 return NULL;
12101 case CLI_GENERATE:
12102 return NULL;
12103 }
12104
12105 if (a->argc != 3)
12106 return CLI_SHOWUSAGE;
12107
12108 for (span = 0; span < NUM_SPANS; span++) {
12109 if (pris[span].pri) {
12110 for (x = 0; x < NUM_DCHANS; x++) {
12111 if (pris[span].dchannels[x]) {
12112 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12113 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12114 }
12115 }
12116 }
12117 }
12118 return CLI_SUCCESS;
12119 }
12120
12121 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12122 {
12123 int span;
12124 int x;
12125 char status[256];
12126 switch (cmd) {
12127 case CLI_INIT:
12128 e->command = "pri show span";
12129 e->usage =
12130 "Usage: pri show span <span>\n"
12131 " Displays PRI Information on a given PRI span\n";
12132 return NULL;
12133 case CLI_GENERATE:
12134 return complete_span_4(a->line, a->word, a->pos, a->n);
12135 }
12136
12137 if (a->argc < 4)
12138 return CLI_SHOWUSAGE;
12139 span = atoi(a->argv[3]);
12140 if ((span < 1) || (span > NUM_SPANS)) {
12141 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12142 return CLI_SUCCESS;
12143 }
12144 if (!pris[span-1].pri) {
12145 ast_cli(a->fd, "No PRI running on span %d\n", span);
12146 return CLI_SUCCESS;
12147 }
12148 for (x = 0; x < NUM_DCHANS; x++) {
12149 if (pris[span-1].dchannels[x]) {
12150 #ifdef PRI_DUMP_INFO_STR
12151 char *info_str = NULL;
12152 #endif
12153 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12154 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12155 ast_cli(a->fd, "Status: %s\n", status);
12156 #ifdef PRI_DUMP_INFO_STR
12157 info_str = pri_dump_info_str(pris[span-1].pri);
12158 if (info_str) {
12159 ast_cli(a->fd, "%s", info_str);
12160 ast_free(info_str);
12161 }
12162 #else
12163 pri_dump_info(pris[span-1].pri);
12164 #endif
12165 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12166 }
12167 }
12168 return CLI_SUCCESS;
12169 }
12170
12171 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12172 {
12173 int x;
12174 int span;
12175 int count=0;
12176 int debug=0;
12177
12178 switch (cmd) {
12179 case CLI_INIT:
12180 e->command = "pri show debug";
12181 return NULL;
12182 case CLI_GENERATE:
12183 return NULL;
12184 }
12185
12186 for (span = 0; span < NUM_SPANS; span++) {
12187 if (pris[span].pri) {
12188 for (x = 0; x < NUM_DCHANS; x++) {
12189 debug = 0;
12190 if (pris[span].dchans[x]) {
12191 debug = pri_get_debug(pris[span].dchans[x]);
12192 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" );
12193 count++;
12194 }
12195 }
12196 }
12197
12198 }
12199 ast_mutex_lock(&pridebugfdlock);
12200 if (pridebugfd >= 0)
12201 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12202 ast_mutex_unlock(&pridebugfdlock);
12203
12204 if (!count)
12205 ast_cli(a->fd, "No debug set or no PRI running\n");
12206 return CLI_SUCCESS;
12207 }
12208
12209 static struct ast_cli_entry dahdi_pri_cli[] = {
12210 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
12211 AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
12212 AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
12213 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
12214 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
12215 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
12216 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
12217 AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
12218 };
12219
12220 #endif
12221
12222 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12223 {
12224 int channel;
12225 int ret;
12226 switch (cmd) {
12227 case CLI_INIT:
12228 e->command = "dahdi destroy channel";
12229 e->usage =
12230 "Usage: dahdi destroy channel <chan num>\n"
12231 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12232 return NULL;
12233 case CLI_GENERATE:
12234 return NULL;
12235 }
12236 if (a->argc != 4)
12237 return CLI_SHOWUSAGE;
12238
12239 channel = atoi(a->argv[3]);
12240 ret = dahdi_destroy_channel_bynum(channel);
12241 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12242 }
12243
12244 static void dahdi_softhangup_all(void)
12245 {
12246 struct dahdi_pvt *p;
12247 retry:
12248 ast_mutex_lock(&iflock);
12249 for (p = iflist; p; p = p->next) {
12250 ast_mutex_lock(&p->lock);
12251 if (p->owner && !p->restartpending) {
12252 if (ast_channel_trylock(p->owner)) {
12253 if (option_debug > 2)
12254 ast_verbose("Avoiding deadlock\n");
12255
12256 ast_mutex_unlock(&p->lock);
12257 ast_mutex_unlock(&iflock);
12258 goto retry;
12259 }
12260 if (option_debug > 2)
12261 ast_verbose("Softhanging up on %s\n", p->owner->name);
12262 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12263 p->restartpending = 1;
12264 num_restart_pending++;
12265 ast_channel_unlock(p->owner);
12266 }
12267 ast_mutex_unlock(&p->lock);
12268 }
12269 ast_mutex_unlock(&iflock);
12270 }
12271
12272 static int setup_dahdi(int reload);
12273 static int dahdi_restart(void)
12274 {
12275 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12276 int i, j;
12277 #endif
12278 int cancel_code;
12279 struct dahdi_pvt *p;
12280
12281 ast_mutex_lock(&restart_lock);
12282
12283 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12284 dahdi_softhangup_all();
12285 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12286
12287 #if defined(HAVE_PRI)
12288 for (i = 0; i < NUM_SPANS; i++) {
12289 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12290 cancel_code = pthread_cancel(pris[i].master);
12291 pthread_kill(pris[i].master, SIGURG);
12292 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12293 pthread_join(pris[i].master, NULL);
12294 ast_debug(4, "Joined thread of span %d\n", i);
12295 }
12296 }
12297 #endif
12298
12299 #if defined(HAVE_SS7)
12300 for (i = 0; i < NUM_SPANS; i++) {
12301 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12302 cancel_code = pthread_cancel(linksets[i].master);
12303 pthread_kill(linksets[i].master, SIGURG);
12304 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12305 pthread_join(linksets[i].master, NULL);
12306 ast_debug(4, "Joined thread of span %d\n", i);
12307 }
12308 }
12309 #endif
12310
12311 ast_mutex_lock(&monlock);
12312 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12313 cancel_code = pthread_cancel(monitor_thread);
12314 pthread_kill(monitor_thread, SIGURG);
12315 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12316 pthread_join(monitor_thread, NULL);
12317 ast_debug(4, "Joined monitor thread\n");
12318 }
12319 monitor_thread = AST_PTHREADT_NULL;
12320
12321 ast_mutex_lock(&ss_thread_lock);
12322 while (ss_thread_count > 0) {
12323 int x = DAHDI_FLASH;
12324 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12325
12326 for (p = iflist; p; p = p->next) {
12327 if (p->owner)
12328 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
12329 }
12330 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12331 }
12332
12333
12334 dahdi_softhangup_all();
12335 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12336 destroy_all_channels();
12337 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12338
12339 ast_mutex_unlock(&monlock);
12340
12341 #ifdef HAVE_PRI
12342 for (i = 0; i < NUM_SPANS; i++) {
12343 for (j = 0; j < NUM_DCHANS; j++)
12344 dahdi_close_pri_fd(&(pris[i]), j);
12345 }
12346
12347 memset(pris, 0, sizeof(pris));
12348 for (i = 0; i < NUM_SPANS; i++) {
12349 ast_mutex_init(&pris[i].lock);
12350 pris[i].offset = -1;
12351 pris[i].master = AST_PTHREADT_NULL;
12352 for (j = 0; j < NUM_DCHANS; j++)
12353 pris[i].fds[j] = -1;
12354 }
12355 pri_set_error(dahdi_pri_error);
12356 pri_set_message(dahdi_pri_message);
12357 #endif
12358 #ifdef HAVE_SS7
12359 for (i = 0; i < NUM_SPANS; i++) {
12360 for (j = 0; j < NUM_DCHANS; j++)
12361 dahdi_close_ss7_fd(&(linksets[i]), j);
12362 }
12363
12364 memset(linksets, 0, sizeof(linksets));
12365 for (i = 0; i < NUM_SPANS; i++) {
12366 ast_mutex_init(&linksets[i].lock);
12367 linksets[i].master = AST_PTHREADT_NULL;
12368 for (j = 0; j < NUM_DCHANS; j++)
12369 linksets[i].fds[j] = -1;
12370 }
12371 ss7_set_error(dahdi_ss7_error);
12372 ss7_set_message(dahdi_ss7_message);
12373 #endif
12374
12375 if (setup_dahdi(2) != 0) {
12376 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12377 ast_mutex_unlock(&ss_thread_lock);
12378 return 1;
12379 }
12380 ast_mutex_unlock(&ss_thread_lock);
12381 ast_mutex_unlock(&restart_lock);
12382 return 0;
12383 }
12384
12385 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12386 {
12387 switch (cmd) {
12388 case CLI_INIT:
12389 e->command = "dahdi restart";
12390 e->usage =
12391 "Usage: dahdi restart\n"
12392 " Restarts the DAHDI channels: destroys them all and then\n"
12393 " re-reads them from chan_dahdi.conf.\n"
12394 " Note that this will STOP any running CALL on DAHDI channels.\n"
12395 "";
12396 return NULL;
12397 case CLI_GENERATE:
12398 return NULL;
12399 }
12400 if (a->argc != 2)
12401 return CLI_SHOWUSAGE;
12402
12403 if (dahdi_restart() != 0)
12404 return CLI_FAILURE;
12405 return CLI_SUCCESS;
12406 }
12407
12408 static int action_dahdirestart(struct mansession *s, const struct message *m)
12409 {
12410 if (dahdi_restart() != 0) {
12411 astman_send_error(s, m, "Failed rereading DAHDI configuration");
12412 return 1;
12413 }
12414 astman_send_ack(s, m, "DAHDIRestart: Success");
12415 return 0;
12416 }
12417
12418 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12419 {
12420 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12421 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12422 unsigned int targetnum = 0;
12423 int filtertype = 0;
12424 struct dahdi_pvt *tmp = NULL;
12425 char tmps[20] = "";
12426 char statestr[20] = "";
12427 char blockstr[20] = "";
12428 ast_mutex_t *lock;
12429 struct dahdi_pvt *start;
12430 #ifdef HAVE_PRI
12431 int trunkgroup;
12432 struct dahdi_pri *pri = NULL;
12433 int x;
12434 #endif
12435 switch (cmd) {
12436 case CLI_INIT:
12437 e->command = "dahdi show channels [trunkgroup|group|context]";
12438 e->usage =
12439 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12440 " Shows a list of available channels with optional filtering\n"
12441 " <group> must be a number between 0 and 63\n";
12442 return NULL;
12443 case CLI_GENERATE:
12444 return NULL;
12445 }
12446
12447 lock = &iflock;
12448 start = iflist;
12449
12450
12451
12452 if (!((a->argc == 3) || (a->argc == 5)))
12453 return CLI_SHOWUSAGE;
12454
12455 if (a->argc == 5) {
12456 #ifdef HAVE_PRI
12457 if (!strcasecmp(a->argv[3], "trunkgroup")) {
12458
12459 if ((trunkgroup = atoi(a->argv[4])) < 1)
12460 return CLI_SHOWUSAGE;
12461 for (x = 0; x < NUM_SPANS; x++) {
12462 if (pris[x].trunkgroup == trunkgroup) {
12463 pri = pris + x;
12464 break;
12465 }
12466 }
12467 if (pri) {
12468 start = pri->crvs;
12469 lock = &pri->lock;
12470 } else {
12471 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12472 return CLI_FAILURE;
12473 }
12474 } else
12475 #endif
12476 if (!strcasecmp(a->argv[3], "group")) {
12477 targetnum = atoi(a->argv[4]);
12478 if ((targetnum < 0) || (targetnum > 63))
12479 return CLI_SHOWUSAGE;
12480 targetnum = 1 << targetnum;
12481 filtertype = 1;
12482 } else if (!strcasecmp(a->argv[3], "context")) {
12483 filtertype = 2;
12484 }
12485 }
12486
12487 ast_mutex_lock(lock);
12488 #ifdef HAVE_PRI
12489 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12490 #else
12491 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12492 #endif
12493
12494 tmp = start;
12495 while (tmp) {
12496 if (filtertype) {
12497 switch(filtertype) {
12498 case 1:
12499 if (!(tmp->group & targetnum)) {
12500 tmp = tmp->next;
12501 continue;
12502 }
12503 break;
12504 case 2:
12505 if (strcasecmp(tmp->context, a->argv[4])) {
12506 tmp = tmp->next;
12507 continue;
12508 }
12509 break;
12510 default:
12511 ;
12512 }
12513 }
12514 if (tmp->channel > 0) {
12515 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12516 } else
12517 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12518
12519 if (tmp->locallyblocked)
12520 blockstr[0] = 'L';
12521 else
12522 blockstr[0] = ' ';
12523
12524 if (tmp->remotelyblocked)
12525 blockstr[1] = 'R';
12526 else
12527 blockstr[1] = ' ';
12528
12529 blockstr[2] = '\0';
12530
12531 snprintf(statestr, sizeof(statestr), "%s", "In Service");
12532
12533 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12534 tmp = tmp->next;
12535 }
12536 ast_mutex_unlock(lock);
12537 return CLI_SUCCESS;
12538 #undef FORMAT
12539 #undef FORMAT2
12540 }
12541
12542 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12543 {
12544 int channel;
12545 struct dahdi_pvt *tmp = NULL;
12546 struct dahdi_confinfo ci;
12547 struct dahdi_params ps;
12548 int x;
12549 ast_mutex_t *lock;
12550 struct dahdi_pvt *start;
12551 #ifdef HAVE_PRI
12552 char *c;
12553 int trunkgroup;
12554 struct dahdi_pri *pri=NULL;
12555 #endif
12556 switch (cmd) {
12557 case CLI_INIT:
12558 e->command = "dahdi show channel";
12559 e->usage =
12560 "Usage: dahdi show channel <chan num>\n"
12561 " Detailed information about a given channel\n";
12562 return NULL;
12563 case CLI_GENERATE:
12564 return NULL;
12565 }
12566
12567 lock = &iflock;
12568 start = iflist;
12569
12570 if (a->argc != 4)
12571 return CLI_SHOWUSAGE;
12572 #ifdef HAVE_PRI
12573 if ((c = strchr(a->argv[3], ':'))) {
12574 if (sscanf(a->argv[3], "%d:%d", &trunkgroup, &channel) != 2)
12575 return CLI_SHOWUSAGE;
12576 if ((trunkgroup < 1) || (channel < 1))
12577 return CLI_SHOWUSAGE;
12578 for (x = 0; x < NUM_SPANS; x++) {
12579 if (pris[x].trunkgroup == trunkgroup) {
12580 pri = pris + x;
12581 break;
12582 }
12583 }
12584 if (pri) {
12585 start = pri->crvs;
12586 lock = &pri->lock;
12587 } else {
12588 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12589 return CLI_FAILURE;
12590 }
12591 } else
12592 #endif
12593 channel = atoi(a->argv[3]);
12594
12595 ast_mutex_lock(lock);
12596 tmp = start;
12597 while (tmp) {
12598 if (tmp->channel == channel) {
12599 #ifdef HAVE_PRI
12600 if (pri)
12601 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12602 else
12603 #endif
12604 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12605 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12606 ast_cli(a->fd, "Span: %d\n", tmp->span);
12607 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12608 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12609 ast_cli(a->fd, "Context: %s\n", tmp->context);
12610 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12611 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12612 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12613 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12614 if (tmp->vars) {
12615 struct ast_variable *v;
12616 ast_cli(a->fd, "Variables:\n");
12617 for (v = tmp->vars ; v ; v = v->next)
12618 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
12619 }
12620 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12621 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12622 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12623 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12624 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12625 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)" : "");
12626 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)" : "");
12627 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)" : "");
12628 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12629 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12630 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12631 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12632 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12633 if (tmp->busydetect) {
12634 #if defined(BUSYDETECT_TONEONLY)
12635 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12636 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12637 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12638 #endif
12639 #ifdef BUSYDETECT_DEBUG
12640 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
12641 #endif
12642 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
12643 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
12644 }
12645 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12646 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12647 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12648 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12649 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12650 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12651 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12652 ast_cli(a->fd, "Echo Cancellation:\n");
12653 if (tmp->echocancel.head.tap_length) {
12654 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12655 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12656 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12657 }
12658 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12659 } else {
12660 ast_cli(a->fd, "\tnone\n");
12661 }
12662 if (tmp->master)
12663 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12664 for (x = 0; x < MAX_SLAVES; x++) {
12665 if (tmp->slaves[x])
12666 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12667 }
12668 #ifdef HAVE_SS7
12669 if (tmp->ss7) {
12670 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12671 }
12672 #endif
12673 #ifdef HAVE_PRI
12674 if (tmp->pri) {
12675 ast_cli(a->fd, "PRI Flags: ");
12676 if (tmp->resetting)
12677 ast_cli(a->fd, "Resetting ");
12678 if (tmp->call)
12679 ast_cli(a->fd, "Call ");
12680 if (tmp->bearer)
12681 ast_cli(a->fd, "Bearer ");
12682 ast_cli(a->fd, "\n");
12683 if (tmp->logicalspan)
12684 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12685 else
12686 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12687 }
12688
12689 #endif
12690 memset(&ci, 0, sizeof(ci));
12691 ps.channo = tmp->channel;
12692 if (tmp->subs[SUB_REAL].dfd > -1) {
12693 memset(&ci, 0, sizeof(ci));
12694 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12695 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12696 }
12697 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12698 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12699 }
12700 memset(&ps, 0, sizeof(ps));
12701 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12702 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12703 } else {
12704 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12705 }
12706 }
12707 if (ISTRUNK(tmp)) {
12708 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
12709 if (!ast_strlen_zero(progzone))
12710 ast_cli(a->fd, "Progress Zone: %s\n", progzone);
12711 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
12712 if(tmp->busydetect) {
12713 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
12714 if(tmp->busytonelength > 0) {
12715 ast_cli(a->fd, "Busy Pattern:\n");
12716 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12717 if (tmp->busyquietlength > 0)
12718 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12719 else
12720 ast_cli(a->fd, " -- Detect Tone Only\n");
12721 if(tmp->busyfuzziness > 0)
12722 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12723 }
12724 }
12725 }
12726 ast_mutex_unlock(lock);
12727 return CLI_SUCCESS;
12728 }
12729 tmp = tmp->next;
12730 }
12731
12732 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12733 ast_mutex_unlock(lock);
12734 return CLI_FAILURE;
12735 }
12736
12737 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12738 {
12739 int i, j;
12740 switch (cmd) {
12741 case CLI_INIT:
12742 e->command = "dahdi show cadences";
12743 e->usage =
12744 "Usage: dahdi show cadences\n"
12745 " Shows all cadences currently defined\n";
12746 return NULL;
12747 case CLI_GENERATE:
12748 return NULL;
12749 }
12750 for (i = 0; i < num_cadence; i++) {
12751 char output[1024];
12752 char tmp[16], tmp2[64];
12753 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12754 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12755
12756 for (j = 0; j < 16; j++) {
12757 if (cadences[i].ringcadence[j] == 0)
12758 break;
12759 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12760 if (cidrings[i] * 2 - 1 == j)
12761 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12762 else
12763 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12764 if (j != 0)
12765 strncat(output, ",", sizeof(output) - strlen(output) - 1);
12766 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12767 }
12768 ast_cli(a->fd,"%s\n",output);
12769 }
12770 return CLI_SUCCESS;
12771 }
12772
12773
12774 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12775 {
12776 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12777 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12778 int span;
12779 int res;
12780 char alarms[50];
12781
12782 int ctl;
12783 struct dahdi_spaninfo s;
12784
12785 switch (cmd) {
12786 case CLI_INIT:
12787 e->command = "dahdi show status";
12788 e->usage =
12789 "Usage: dahdi show status\n"
12790 " Shows a list of DAHDI cards with status\n";
12791 return NULL;
12792 case CLI_GENERATE:
12793 return NULL;
12794 }
12795 ctl = open("/dev/dahdi/ctl", O_RDWR);
12796 if (ctl < 0) {
12797 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
12798 return CLI_FAILURE;
12799 }
12800 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
12801
12802 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12803 s.spanno = span;
12804 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12805 if (res) {
12806 continue;
12807 }
12808 alarms[0] = '\0';
12809 if (s.alarms > 0) {
12810 if (s.alarms & DAHDI_ALARM_BLUE)
12811 strcat(alarms, "BLU/");
12812 if (s.alarms & DAHDI_ALARM_YELLOW)
12813 strcat(alarms, "YEL/");
12814 if (s.alarms & DAHDI_ALARM_RED)
12815 strcat(alarms, "RED/");
12816 if (s.alarms & DAHDI_ALARM_LOOPBACK)
12817 strcat(alarms, "LB/");
12818 if (s.alarms & DAHDI_ALARM_RECOVER)
12819 strcat(alarms, "REC/");
12820 if (s.alarms & DAHDI_ALARM_NOTOPEN)
12821 strcat(alarms, "NOP/");
12822 if (!strlen(alarms))
12823 strcat(alarms, "UUU/");
12824 if (strlen(alarms)) {
12825
12826 alarms[strlen(alarms) - 1] = '\0';
12827 }
12828 } else {
12829 if (s.numchans)
12830 strcpy(alarms, "OK");
12831 else
12832 strcpy(alarms, "UNCONFIGURED");
12833 }
12834
12835 ast_cli(a->fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count
12836 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
12837 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
12838 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
12839 "CAS"
12840 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
12841 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
12842 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
12843 "Unk"
12844 , s.lineconfig & DAHDI_CONFIG_CRC4 ?
12845 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
12846 , lbostr[s.lbo]
12847 );
12848 }
12849 close(ctl);
12850
12851 return CLI_SUCCESS;
12852 #undef FORMAT
12853 #undef FORMAT2
12854 }
12855
12856 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12857 {
12858 int pseudo_fd = -1;
12859 struct dahdi_versioninfo vi;
12860
12861 switch (cmd) {
12862 case CLI_INIT:
12863 e->command = "dahdi show version";
12864 e->usage =
12865 "Usage: dahdi show version\n"
12866 " Shows the DAHDI version in use\n";
12867 return NULL;
12868 case CLI_GENERATE:
12869 return NULL;
12870 }
12871 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
12872 ast_cli(a->fd, "Failed to open control file to get version.\n");
12873 return CLI_SUCCESS;
12874 }
12875
12876 strcpy(vi.version, "Unknown");
12877 strcpy(vi.echo_canceller, "Unknown");
12878
12879 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
12880 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
12881 else
12882 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
12883
12884 close(pseudo_fd);
12885
12886 return CLI_SUCCESS;
12887 }
12888
12889 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12890 {
12891 int channel;
12892 int gain;
12893 int tx;
12894 struct dahdi_hwgain hwgain;
12895 struct dahdi_pvt *tmp = NULL;
12896
12897 switch (cmd) {
12898 case CLI_INIT:
12899 e->command = "dahdi set hwgain";
12900 e->usage =
12901 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
12902 " Sets the hardware gain on a a given channel, overriding the\n"
12903 " value provided at module loadtime, whether the channel is in\n"
12904 " use or not. Changes take effect immediately.\n"
12905 " <rx|tx> which direction do you want to change (relative to our module)\n"
12906 " <chan num> is the channel number relative to the device\n"
12907 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12908 return NULL;
12909 case CLI_GENERATE:
12910 return NULL;
12911 }
12912
12913 if (a->argc != 6)
12914 return CLI_SHOWUSAGE;
12915
12916 if (!strcasecmp("rx", a->argv[3]))
12917 tx = 0;
12918 else if (!strcasecmp("tx", a->argv[3]))
12919 tx = 1;
12920 else
12921 return CLI_SHOWUSAGE;
12922
12923 channel = atoi(a->argv[4]);
12924 gain = atof(a->argv[5])*10.0;
12925
12926 ast_mutex_lock(&iflock);
12927
12928 for (tmp = iflist; tmp; tmp = tmp->next) {
12929
12930 if (tmp->channel != channel)
12931 continue;
12932
12933 if (tmp->subs[SUB_REAL].dfd == -1)
12934 break;
12935
12936 hwgain.newgain = gain;
12937 hwgain.tx = tx;
12938 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
12939 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
12940 ast_mutex_unlock(&iflock);
12941 return CLI_FAILURE;
12942 }
12943 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
12944 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
12945 break;
12946 }
12947
12948 ast_mutex_unlock(&iflock);
12949
12950 if (tmp)
12951 return CLI_SUCCESS;
12952
12953 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12954 return CLI_FAILURE;
12955
12956 }
12957
12958 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12959 {
12960 int channel;
12961 float gain;
12962 int tx;
12963 int res;
12964 ast_mutex_t *lock;
12965 struct dahdi_pvt *tmp = NULL;
12966
12967 switch (cmd) {
12968 case CLI_INIT:
12969 e->command = "dahdi set swgain";
12970 e->usage =
12971 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
12972 " Sets the software gain on a a given channel, overriding the\n"
12973 " value provided at module loadtime, whether the channel is in\n"
12974 " use or not. Changes take effect immediately.\n"
12975 " <rx|tx> which direction do you want to change (relative to our module)\n"
12976 " <chan num> is the channel number relative to the device\n"
12977 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12978 return NULL;
12979 case CLI_GENERATE:
12980 return NULL;
12981 }
12982
12983 lock = &iflock;
12984
12985 if (a->argc != 6)
12986 return CLI_SHOWUSAGE;
12987
12988 if (!strcasecmp("rx", a->argv[3]))
12989 tx = 0;
12990 else if (!strcasecmp("tx", a->argv[3]))
12991 tx = 1;
12992 else
12993 return CLI_SHOWUSAGE;
12994
12995 channel = atoi(a->argv[4]);
12996 gain = atof(a->argv[5]);
12997
12998 ast_mutex_lock(lock);
12999 for (tmp = iflist; tmp; tmp = tmp->next) {
13000
13001 if (tmp->channel != channel)
13002 continue;
13003
13004 if (tmp->subs[SUB_REAL].dfd == -1)
13005 break;
13006
13007 if (tx)
13008 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13009 else
13010 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13011
13012 if (res) {
13013 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13014 ast_mutex_unlock(lock);
13015 return CLI_FAILURE;
13016 }
13017
13018 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13019 tx ? "tx" : "rx", gain, channel);
13020 break;
13021 }
13022 ast_mutex_unlock(lock);
13023
13024 if (tmp)
13025 return CLI_SUCCESS;
13026
13027 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13028 return CLI_FAILURE;
13029
13030 }
13031
13032 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13033 {
13034 int channel;
13035 int on;
13036 struct dahdi_pvt *dahdi_chan = NULL;
13037
13038 switch (cmd) {
13039 case CLI_INIT:
13040 e->command = "dahdi set dnd";
13041 e->usage =
13042 "Usage: dahdi set dnd <chan#> <on|off>\n"
13043 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13044 " Changes take effect immediately.\n"
13045 " <chan num> is the channel number\n"
13046 " <on|off> Enable or disable DND mode?\n"
13047 ;
13048 return NULL;
13049 case CLI_GENERATE:
13050 return NULL;
13051 }
13052
13053 if (a->argc != 5)
13054 return CLI_SHOWUSAGE;
13055
13056 if ((channel = atoi(a->argv[3])) <= 0) {
13057 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13058 return CLI_SHOWUSAGE;
13059 }
13060
13061 if (ast_true(a->argv[4]))
13062 on = 1;
13063 else if (ast_false(a->argv[4]))
13064 on = 0;
13065 else {
13066 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13067 return CLI_SHOWUSAGE;
13068 }
13069
13070 ast_mutex_lock(&iflock);
13071 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13072 if (dahdi_chan->channel != channel)
13073 continue;
13074
13075
13076 dahdi_dnd(dahdi_chan, on);
13077 break;
13078 }
13079 ast_mutex_unlock(&iflock);
13080
13081 if (!dahdi_chan) {
13082 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13083 return CLI_FAILURE;
13084 }
13085
13086 return CLI_SUCCESS;
13087 }
13088
13089 static struct ast_cli_entry dahdi_cli[] = {
13090 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
13091 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
13092 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
13093 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
13094 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
13095 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
13096 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
13097 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
13098 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
13099 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
13100 };
13101
13102 #define TRANSFER 0
13103 #define HANGUP 1
13104
13105 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13106 {
13107 if (p) {
13108 switch (mode) {
13109 case TRANSFER:
13110 p->fake_event = DAHDI_EVENT_WINKFLASH;
13111 break;
13112 case HANGUP:
13113 p->fake_event = DAHDI_EVENT_ONHOOK;
13114 break;
13115 default:
13116 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
13117 }
13118 }
13119 return 0;
13120 }
13121 static struct dahdi_pvt *find_channel(int channel)
13122 {
13123 struct dahdi_pvt *p = iflist;
13124 while (p) {
13125 if (p->channel == channel) {
13126 break;
13127 }
13128 p = p->next;
13129 }
13130 return p;
13131 }
13132
13133 static int action_dahdidndon(struct mansession *s, const struct message *m)
13134 {
13135 struct dahdi_pvt *p = NULL;
13136 const char *channel = astman_get_header(m, "DAHDIChannel");
13137
13138 if (ast_strlen_zero(channel)) {
13139 astman_send_error(s, m, "No channel specified");
13140 return 0;
13141 }
13142 p = find_channel(atoi(channel));
13143 if (!p) {
13144 astman_send_error(s, m, "No such channel");
13145 return 0;
13146 }
13147 p->dnd = 1;
13148 astman_send_ack(s, m, "DND Enabled");
13149 return 0;
13150 }
13151
13152 static int action_dahdidndoff(struct mansession *s, const struct message *m)
13153 {
13154 struct dahdi_pvt *p = NULL;
13155 const char *channel = astman_get_header(m, "DAHDIChannel");
13156
13157 if (ast_strlen_zero(channel)) {
13158 astman_send_error(s, m, "No channel specified");
13159 return 0;
13160 }
13161 p = find_channel(atoi(channel));
13162 if (!p) {
13163 astman_send_error(s, m, "No such channel");
13164 return 0;
13165 }
13166 p->dnd = 0;
13167 astman_send_ack(s, m, "DND Disabled");
13168 return 0;
13169 }
13170
13171 static int action_transfer(struct mansession *s, const struct message *m)
13172 {
13173 struct dahdi_pvt *p = NULL;
13174 const char *channel = astman_get_header(m, "DAHDIChannel");
13175
13176 if (ast_strlen_zero(channel)) {
13177 astman_send_error(s, m, "No channel specified");
13178 return 0;
13179 }
13180 p = find_channel(atoi(channel));
13181 if (!p) {
13182 astman_send_error(s, m, "No such channel");
13183 return 0;
13184 }
13185 dahdi_fake_event(p,TRANSFER);
13186 astman_send_ack(s, m, "DAHDITransfer");
13187 return 0;
13188 }
13189
13190 static int action_transferhangup(struct mansession *s, const struct message *m)
13191 {
13192 struct dahdi_pvt *p = NULL;
13193 const char *channel = astman_get_header(m, "DAHDIChannel");
13194
13195 if (ast_strlen_zero(channel)) {
13196 astman_send_error(s, m, "No channel specified");
13197 return 0;
13198 }
13199 p = find_channel(atoi(channel));
13200 if (!p) {
13201 astman_send_error(s, m, "No such channel");
13202 return 0;
13203 }
13204 dahdi_fake_event(p,HANGUP);
13205 astman_send_ack(s, m, "DAHDIHangup");
13206 return 0;
13207 }
13208
13209 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
13210 {
13211 struct dahdi_pvt *p = NULL;
13212 const char *channel = astman_get_header(m, "DAHDIChannel");
13213 const char *number = astman_get_header(m, "Number");
13214 int i;
13215
13216 if (ast_strlen_zero(channel)) {
13217 astman_send_error(s, m, "No channel specified");
13218 return 0;
13219 }
13220 if (ast_strlen_zero(number)) {
13221 astman_send_error(s, m, "No number specified");
13222 return 0;
13223 }
13224 p = find_channel(atoi(channel));
13225 if (!p) {
13226 astman_send_error(s, m, "No such channel");
13227 return 0;
13228 }
13229 if (!p->owner) {
13230 astman_send_error(s, m, "Channel does not have it's owner");
13231 return 0;
13232 }
13233 for (i = 0; i < strlen(number); i++) {
13234 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13235 dahdi_queue_frame(p, &f, NULL);
13236 }
13237 astman_send_ack(s, m, "DAHDIDialOffhook");
13238 return 0;
13239 }
13240
13241 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
13242 {
13243 struct dahdi_pvt *tmp = NULL;
13244 const char *id = astman_get_header(m, "ActionID");
13245 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13246 char idText[256] = "";
13247 int channels = 0;
13248 int dahdichanquery = -1;
13249 if (!ast_strlen_zero(dahdichannel)) {
13250 dahdichanquery = atoi(dahdichannel);
13251 }
13252
13253 astman_send_ack(s, m, "DAHDI channel status will follow");
13254 if (!ast_strlen_zero(id))
13255 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13256
13257 ast_mutex_lock(&iflock);
13258
13259 tmp = iflist;
13260 while (tmp) {
13261 if (tmp->channel > 0) {
13262 int alarm = get_alarms(tmp);
13263
13264
13265 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13266 continue;
13267
13268 channels++;
13269 if (tmp->owner) {
13270
13271 astman_append(s,
13272 "Event: DAHDIShowChannels\r\n"
13273 "DAHDIChannel: %d\r\n"
13274 "Channel: %s\r\n"
13275 "Uniqueid: %s\r\n"
13276 "AccountCode: %s\r\n"
13277 "Signalling: %s\r\n"
13278 "SignallingCode: %d\r\n"
13279 "Context: %s\r\n"
13280 "DND: %s\r\n"
13281 "Alarm: %s\r\n"
13282 "%s"
13283 "\r\n",
13284 tmp->channel,
13285 tmp->owner->name,
13286 tmp->owner->uniqueid,
13287 tmp->owner->accountcode,
13288 sig2str(tmp->sig),
13289 tmp->sig,
13290 tmp->context,
13291 tmp->dnd ? "Enabled" : "Disabled",
13292 alarm2str(alarm), idText);
13293 } else {
13294 astman_append(s,
13295 "Event: DAHDIShowChannels\r\n"
13296 "DAHDIChannel: %d\r\n"
13297 "Signalling: %s\r\n"
13298 "SignallingCode: %d\r\n"
13299 "Context: %s\r\n"
13300 "DND: %s\r\n"
13301 "Alarm: %s\r\n"
13302 "%s"
13303 "\r\n",
13304 tmp->channel, sig2str(tmp->sig), tmp->sig,
13305 tmp->context,
13306 tmp->dnd ? "Enabled" : "Disabled",
13307 alarm2str(alarm), idText);
13308 }
13309 }
13310
13311 tmp = tmp->next;
13312 }
13313
13314 ast_mutex_unlock(&iflock);
13315
13316 astman_append(s,
13317 "Event: DAHDIShowChannelsComplete\r\n"
13318 "%s"
13319 "Items: %d\r\n"
13320 "\r\n",
13321 idText,
13322 channels);
13323 return 0;
13324 }
13325
13326 #ifdef HAVE_SS7
13327 static int linkset_addsigchan(int sigchan)
13328 {
13329 struct dahdi_ss7 *link;
13330 int res;
13331 int curfd;
13332 struct dahdi_params p;
13333 struct dahdi_bufferinfo bi;
13334 struct dahdi_spaninfo si;
13335
13336
13337 link = ss7_resolve_linkset(cur_linkset);
13338 if (!link) {
13339 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
13340 return -1;
13341 }
13342
13343 if (cur_ss7type < 0) {
13344 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13345 return -1;
13346 }
13347
13348 if (!link->ss7)
13349 link->ss7 = ss7_new(cur_ss7type);
13350
13351 if (!link->ss7) {
13352 ast_log(LOG_ERROR, "Can't create new SS7!\n");
13353 return -1;
13354 }
13355
13356 link->type = cur_ss7type;
13357
13358 if (cur_pointcode < 0) {
13359 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13360 return -1;
13361 } else
13362 ss7_set_pc(link->ss7, cur_pointcode);
13363
13364 if (sigchan < 0) {
13365 ast_log(LOG_ERROR, "Invalid sigchan!\n");
13366 return -1;
13367 } else {
13368 if (link->numsigchans >= NUM_DCHANS) {
13369 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13370 return -1;
13371 }
13372 curfd = link->numsigchans;
13373
13374 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13375 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13376 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13377 return -1;
13378 }
13379 memset(&p, 0, sizeof(p));
13380 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13381 if (res) {
13382 dahdi_close_ss7_fd(link, curfd);
13383 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13384 return -1;
13385 }
13386 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13387 dahdi_close_ss7_fd(link, curfd);
13388 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13389 return -1;
13390 }
13391
13392 memset(&bi, 0, sizeof(bi));
13393 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13394 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13395 bi.numbufs = 32;
13396 bi.bufsize = 512;
13397
13398 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13399 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13400 dahdi_close_ss7_fd(link, curfd);
13401 return -1;
13402 }
13403
13404 if (p.sigtype == DAHDI_SIG_MTP2)
13405 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13406 else
13407 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13408
13409 link->numsigchans++;
13410
13411 memset(&si, 0, sizeof(si));
13412 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13413 if (res) {
13414 dahdi_close_ss7_fd(link, curfd);
13415 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13416 }
13417
13418 if (!si.alarms) {
13419 link->linkstate[curfd] = LINKSTATE_DOWN;
13420 ss7_link_noalarm(link->ss7, link->fds[curfd]);
13421 } else {
13422 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13423 ss7_link_alarm(link->ss7, link->fds[curfd]);
13424 }
13425 }
13426
13427 if (cur_adjpointcode < 0) {
13428 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13429 return -1;
13430 } else {
13431 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13432 }
13433
13434 if (cur_defaultdpc < 0) {
13435 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13436 return -1;
13437 }
13438
13439 if (cur_networkindicator < 0) {
13440 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13441 return -1;
13442 } else
13443 ss7_set_network_ind(link->ss7, cur_networkindicator);
13444
13445 return 0;
13446 }
13447
13448 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13449 {
13450 int span;
13451 switch (cmd) {
13452 case CLI_INIT:
13453 e->command = "ss7 no debug linkset";
13454 e->usage =
13455 "Usage: ss7 no debug linkset <span>\n"
13456 " Disables debugging on a given SS7 linkset\n";
13457 return NULL;
13458 case CLI_GENERATE:
13459 return NULL;
13460 }
13461 if (a->argc < 5)
13462 return CLI_SHOWUSAGE;
13463 span = atoi(a->argv[4]);
13464 if ((span < 1) || (span > NUM_SPANS)) {
13465 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13466 return CLI_SUCCESS;
13467 }
13468 if (!linksets[span-1].ss7) {
13469 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13470 return CLI_SUCCESS;
13471 }
13472 if (linksets[span-1].ss7)
13473 ss7_set_debug(linksets[span-1].ss7, 0);
13474
13475 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13476 return CLI_SUCCESS;
13477 }
13478
13479 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13480 {
13481 int span;
13482 switch (cmd) {
13483 case CLI_INIT:
13484 e->command = "ss7 debug linkset";
13485 e->usage =
13486 "Usage: ss7 debug linkset <linkset>\n"
13487 " Enables debugging on a given SS7 linkset\n";
13488 return NULL;
13489 case CLI_GENERATE:
13490 return NULL;
13491 }
13492 if (a->argc < 4)
13493 return CLI_SHOWUSAGE;
13494 span = atoi(a->argv[3]);
13495 if ((span < 1) || (span > NUM_SPANS)) {
13496 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13497 return CLI_SUCCESS;
13498 }
13499 if (!linksets[span-1].ss7) {
13500 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13501 return CLI_SUCCESS;
13502 }
13503 if (linksets[span-1].ss7)
13504 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13505
13506 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13507 return CLI_SUCCESS;
13508 }
13509
13510 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13511 {
13512 int linkset, cic;
13513 int blocked = -1, i;
13514 switch (cmd) {
13515 case CLI_INIT:
13516 e->command = "ss7 block cic";
13517 e->usage =
13518 "Usage: ss7 block cic <linkset> <CIC>\n"
13519 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13520 return NULL;
13521 case CLI_GENERATE:
13522 return NULL;
13523 }
13524 if (a->argc == 5)
13525 linkset = atoi(a->argv[3]);
13526 else
13527 return CLI_SHOWUSAGE;
13528
13529 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13530 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13531 return CLI_SUCCESS;
13532 }
13533
13534 if (!linksets[linkset-1].ss7) {
13535 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13536 return CLI_SUCCESS;
13537 }
13538
13539 cic = atoi(a->argv[4]);
13540
13541 if (cic < 1) {
13542 ast_cli(a->fd, "Invalid CIC specified!\n");
13543 return CLI_SUCCESS;
13544 }
13545
13546 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13547 if (linksets[linkset-1].pvts[i]->cic == cic) {
13548 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13549 if (!blocked) {
13550 ast_mutex_lock(&linksets[linkset-1].lock);
13551 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13552 ast_mutex_unlock(&linksets[linkset-1].lock);
13553 }
13554 }
13555 }
13556
13557 if (blocked < 0) {
13558 ast_cli(a->fd, "Invalid CIC specified!\n");
13559 return CLI_SUCCESS;
13560 }
13561
13562 if (!blocked)
13563 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13564 else
13565 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13566
13567
13568 pthread_kill(linksets[linkset-1].master, SIGURG);
13569
13570 return CLI_SUCCESS;
13571 }
13572
13573 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13574 {
13575 int linkset;
13576 int i;
13577 switch (cmd) {
13578 case CLI_INIT:
13579 e->command = "ss7 block linkset";
13580 e->usage =
13581 "Usage: ss7 block linkset <linkset number>\n"
13582 " Sends a remote blocking request for all CICs on the given linkset\n";
13583 return NULL;
13584 case CLI_GENERATE:
13585 return NULL;
13586 }
13587 if (a->argc == 4)
13588 linkset = atoi(a->argv[3]);
13589 else
13590 return CLI_SHOWUSAGE;
13591
13592 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13593 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13594 return CLI_SUCCESS;
13595 }
13596
13597 if (!linksets[linkset-1].ss7) {
13598 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13599 return CLI_SUCCESS;
13600 }
13601
13602 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13603 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13604 ast_mutex_lock(&linksets[linkset-1].lock);
13605 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13606 ast_mutex_unlock(&linksets[linkset-1].lock);
13607 }
13608
13609
13610 pthread_kill(linksets[linkset-1].master, SIGURG);
13611
13612 return CLI_SUCCESS;
13613 }
13614
13615 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13616 {
13617 int linkset, cic;
13618 int i, blocked = -1;
13619 switch (cmd) {
13620 case CLI_INIT:
13621 e->command = "ss7 unblock cic";
13622 e->usage =
13623 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13624 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13625 return NULL;
13626 case CLI_GENERATE:
13627 return NULL;
13628 }
13629
13630 if (a->argc == 5)
13631 linkset = atoi(a->argv[3]);
13632 else
13633 return CLI_SHOWUSAGE;
13634
13635 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13636 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13637 return CLI_SUCCESS;
13638 }
13639
13640 if (!linksets[linkset-1].ss7) {
13641 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13642 return CLI_SUCCESS;
13643 }
13644
13645 cic = atoi(a->argv[4]);
13646
13647 if (cic < 1) {
13648 ast_cli(a->fd, "Invalid CIC specified!\n");
13649 return CLI_SUCCESS;
13650 }
13651
13652 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13653 if (linksets[linkset-1].pvts[i]->cic == cic) {
13654 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13655 if (blocked) {
13656 ast_mutex_lock(&linksets[linkset-1].lock);
13657 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13658 ast_mutex_unlock(&linksets[linkset-1].lock);
13659 }
13660 }
13661 }
13662
13663 if (blocked > 0)
13664 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13665
13666
13667 pthread_kill(linksets[linkset-1].master, SIGURG);
13668
13669 return CLI_SUCCESS;
13670 }
13671
13672 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13673 {
13674 int linkset;
13675 int i;
13676 switch (cmd) {
13677 case CLI_INIT:
13678 e->command = "ss7 unblock linkset";
13679 e->usage =
13680 "Usage: ss7 unblock linkset <linkset number>\n"
13681 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13682 return NULL;
13683 case CLI_GENERATE:
13684 return NULL;
13685 }
13686
13687 if (a->argc == 4)
13688 linkset = atoi(a->argv[3]);
13689 else
13690 return CLI_SHOWUSAGE;
13691
13692 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13693 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13694 return CLI_SUCCESS;
13695 }
13696
13697 if (!linksets[linkset-1].ss7) {
13698 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13699 return CLI_SUCCESS;
13700 }
13701
13702 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13703 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13704 ast_mutex_lock(&linksets[linkset-1].lock);
13705 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13706 ast_mutex_unlock(&linksets[linkset-1].lock);
13707 }
13708
13709
13710 pthread_kill(linksets[linkset-1].master, SIGURG);
13711
13712 return CLI_SUCCESS;
13713 }
13714
13715 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13716 {
13717 int linkset;
13718 struct dahdi_ss7 *ss7;
13719 switch (cmd) {
13720 case CLI_INIT:
13721 e->command = "ss7 show linkset";
13722 e->usage =
13723 "Usage: ss7 show linkset <span>\n"
13724 " Shows the status of an SS7 linkset.\n";
13725 return NULL;
13726 case CLI_GENERATE:
13727 return NULL;
13728 }
13729
13730 if (a->argc < 4)
13731 return CLI_SHOWUSAGE;
13732 linkset = atoi(a->argv[3]);
13733 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13734 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13735 return CLI_SUCCESS;
13736 }
13737 if (!linksets[linkset-1].ss7) {
13738 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13739 return CLI_SUCCESS;
13740 }
13741 if (linksets[linkset-1].ss7)
13742 ss7 = &linksets[linkset-1];
13743
13744 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
13745
13746 return CLI_SUCCESS;
13747 }
13748
13749 static struct ast_cli_entry dahdi_ss7_cli[] = {
13750 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
13751 AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"),
13752 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
13753 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
13754 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
13755 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
13756 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
13757 };
13758 #endif
13759
13760 static int __unload_module(void)
13761 {
13762 struct dahdi_pvt *p;
13763 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13764 int i, j;
13765 #endif
13766
13767 #ifdef HAVE_PRI
13768 for (i = 0; i < NUM_SPANS; i++) {
13769 if (pris[i].master != AST_PTHREADT_NULL)
13770 pthread_cancel(pris[i].master);
13771 }
13772 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
13773 ast_unregister_application(dahdi_send_keypad_facility_app);
13774 #endif
13775 #if defined(HAVE_SS7)
13776 for (i = 0; i < NUM_SPANS; i++) {
13777 if (linksets[i].master != AST_PTHREADT_NULL)
13778 pthread_cancel(linksets[i].master);
13779 }
13780 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
13781 #endif
13782
13783 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13784 ast_manager_unregister( "DAHDIDialOffhook" );
13785 ast_manager_unregister( "DAHDIHangup" );
13786 ast_manager_unregister( "DAHDITransfer" );
13787 ast_manager_unregister( "DAHDIDNDoff" );
13788 ast_manager_unregister( "DAHDIDNDon" );
13789 ast_manager_unregister("DAHDIShowChannels");
13790 ast_manager_unregister("DAHDIRestart");
13791 ast_channel_unregister(&dahdi_tech);
13792 ast_mutex_lock(&iflock);
13793
13794 p = iflist;
13795 while (p) {
13796 if (p->owner)
13797 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
13798 p = p->next;
13799 }
13800 ast_mutex_unlock(&iflock);
13801 ast_mutex_lock(&monlock);
13802 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
13803 pthread_cancel(monitor_thread);
13804 pthread_kill(monitor_thread, SIGURG);
13805 pthread_join(monitor_thread, NULL);
13806 }
13807 monitor_thread = AST_PTHREADT_STOP;
13808 ast_mutex_unlock(&monlock);
13809
13810 destroy_all_channels();
13811
13812 #if defined(HAVE_PRI)
13813 for (i = 0; i < NUM_SPANS; i++) {
13814 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
13815 pthread_join(pris[i].master, NULL);
13816 for (j = 0; j < NUM_DCHANS; j++) {
13817 dahdi_close_pri_fd(&(pris[i]), j);
13818 }
13819 }
13820 #endif
13821
13822 #if defined(HAVE_SS7)
13823 for (i = 0; i < NUM_SPANS; i++) {
13824 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
13825 pthread_join(linksets[i].master, NULL);
13826 for (j = 0; j < NUM_DCHANS; j++) {
13827 dahdi_close_ss7_fd(&(linksets[i]), j);
13828 }
13829 }
13830 #endif
13831
13832 ast_cond_destroy(&ss_thread_complete);
13833 return 0;
13834 }
13835
13836 static int unload_module(void)
13837 {
13838 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13839 int y;
13840 #endif
13841 #ifdef HAVE_PRI
13842 for (y = 0; y < NUM_SPANS; y++)
13843 ast_mutex_destroy(&pris[y].lock);
13844 #endif
13845 #ifdef HAVE_SS7
13846 for (y = 0; y < NUM_SPANS; y++)
13847 ast_mutex_destroy(&linksets[y].lock);
13848 #endif
13849 return __unload_module();
13850 }
13851
13852 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
13853 {
13854 char *c, *chan;
13855 int x, start, finish;
13856 struct dahdi_pvt *tmp;
13857 #ifdef HAVE_PRI
13858 struct dahdi_pri *pri;
13859 int trunkgroup, y;
13860 #endif
13861
13862 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
13863 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
13864 return -1;
13865 }
13866
13867 c = ast_strdupa(value);
13868
13869 #ifdef HAVE_PRI
13870 pri = NULL;
13871 if (iscrv) {
13872 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
13873 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
13874 return -1;
13875 }
13876 if (trunkgroup < 1) {
13877 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
13878 return -1;
13879 }
13880 c += y;
13881 for (y = 0; y < NUM_SPANS; y++) {
13882 if (pris[y].trunkgroup == trunkgroup) {
13883 pri = pris + y;
13884 break;
13885 }
13886 }
13887 if (!pri) {
13888 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
13889 return -1;
13890 }
13891 }
13892 #endif
13893
13894 while ((chan = strsep(&c, ","))) {
13895 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
13896
13897 } else if (sscanf(chan, "%d", &start)) {
13898
13899 finish = start;
13900 } else if (!strcasecmp(chan, "pseudo")) {
13901 finish = start = CHAN_PSEUDO;
13902 if (found_pseudo)
13903 *found_pseudo = 1;
13904 } else {
13905 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
13906 return -1;
13907 }
13908 if (finish < start) {
13909 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
13910 x = finish;
13911 finish = start;
13912 start = x;
13913 }
13914
13915 for (x = start; x <= finish; x++) {
13916 #ifdef HAVE_PRI
13917 tmp = mkintf(x, conf, pri, reload);
13918 #else
13919 tmp = mkintf(x, conf, NULL, reload);
13920 #endif
13921
13922 if (tmp) {
13923 #ifdef HAVE_PRI
13924 if (pri)
13925 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
13926 else
13927 #endif
13928 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
13929 } else {
13930 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
13931 (reload == 1) ? "reconfigure" : "register", value);
13932 return -1;
13933 }
13934 }
13935 }
13936
13937 return 0;
13938 }
13939
13940
13941
13942 #define MAX_CHANLIST_LEN 80
13943
13944 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
13945 {
13946 char *parse = ast_strdupa(data);
13947 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
13948 unsigned int param_count;
13949 unsigned int x;
13950
13951 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
13952 return;
13953
13954 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
13955
13956
13957
13958 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
13959
13960 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
13961 confp->chan.echocancel.head.tap_length = x;
13962 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
13963 confp->chan.echocancel.head.tap_length = 128;
13964
13965
13966
13967 for (x = 1; x < param_count; x++) {
13968 struct {
13969 char *name;
13970 char *value;
13971 } param;
13972
13973 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
13974 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
13975 continue;
13976 }
13977
13978 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
13979 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
13980 continue;
13981 }
13982
13983 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
13984
13985 if (param.value) {
13986 if (sscanf(param.value, "%d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
13987 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
13988 continue;
13989 }
13990 }
13991 confp->chan.echocancel.head.param_count++;
13992 }
13993 }
13994
13995
13996 static int process_dahdi(struct dahdi_chan_conf *confp, struct ast_variable *v, int reload, int skipchannels)
13997 {
13998 struct dahdi_pvt *tmp;
13999 int y;
14000 int found_pseudo = 0;
14001 char dahdichan[MAX_CHANLIST_LEN] = {};
14002
14003 for (; v; v = v->next) {
14004 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14005 continue;
14006
14007
14008 if (!strcasecmp(v->name, "channel")
14009 #ifdef HAVE_PRI
14010 || !strcasecmp(v->name, "crv")
14011 #endif
14012 ) {
14013 int iscrv;
14014 if (skipchannels)
14015 continue;
14016 iscrv = !strcasecmp(v->name, "crv");
14017 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14018 return -1;
14019 } else if (!strcasecmp(v->name, "buffers")) {
14020 int res;
14021 char policy[21] = "";
14022
14023 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
14024 if (res != 2) {
14025 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14026 confp->chan.buf_no = numbufs;
14027 continue;
14028 }
14029 if (confp->chan.buf_no < 0)
14030 confp->chan.buf_no = numbufs;
14031 if (!strcasecmp(policy, "full")) {
14032 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14033 } else if (!strcasecmp(policy, "immediate")) {
14034 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14035 } else {
14036 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14037 }
14038 } else if (!strcasecmp(v->name, "dahdichan")) {
14039 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14040 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14041 usedistinctiveringdetection = ast_true(v->value);
14042 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14043 distinctiveringaftercid = ast_true(v->value);
14044 } else if (!strcasecmp(v->name, "dring1context")) {
14045 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14046 } else if (!strcasecmp(v->name, "dring2context")) {
14047 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14048 } else if (!strcasecmp(v->name, "dring3context")) {
14049 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14050 } else if (!strcasecmp(v->name, "dring1range")) {
14051 confp->chan.drings.ringnum[0].range = atoi(v->value);
14052 } else if (!strcasecmp(v->name, "dring2range")) {
14053 confp->chan.drings.ringnum[1].range = atoi(v->value);
14054 } else if (!strcasecmp(v->name, "dring3range")) {
14055 confp->chan.drings.ringnum[2].range = atoi(v->value);
14056 } else if (!strcasecmp(v->name, "dring1")) {
14057 sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
14058 } else if (!strcasecmp(v->name, "dring2")) {
14059 sscanf(v->value,"%d,%d,%d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
14060 } else if (!strcasecmp(v->name, "dring3")) {
14061 sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
14062 } else if (!strcasecmp(v->name, "usecallerid")) {
14063 confp->chan.use_callerid = ast_true(v->value);
14064 } else if (!strcasecmp(v->name, "cidsignalling")) {
14065 if (!strcasecmp(v->value, "bell"))
14066 confp->chan.cid_signalling = CID_SIG_BELL;
14067 else if (!strcasecmp(v->value, "v23"))
14068 confp->chan.cid_signalling = CID_SIG_V23;
14069 else if (!strcasecmp(v->value, "dtmf"))
14070 confp->chan.cid_signalling = CID_SIG_DTMF;
14071 else if (!strcasecmp(v->value, "smdi"))
14072 confp->chan.cid_signalling = CID_SIG_SMDI;
14073 else if (!strcasecmp(v->value, "v23_jp"))
14074 confp->chan.cid_signalling = CID_SIG_V23_JP;
14075 else if (ast_true(v->value))
14076 confp->chan.cid_signalling = CID_SIG_BELL;
14077 } else if (!strcasecmp(v->name, "cidstart")) {
14078 if (!strcasecmp(v->value, "ring"))
14079 confp->chan.cid_start = CID_START_RING;
14080 else if (!strcasecmp(v->value, "polarity_in"))
14081 confp->chan.cid_start = CID_START_POLARITY_IN;
14082 else if (!strcasecmp(v->value, "polarity"))
14083 confp->chan.cid_start = CID_START_POLARITY;
14084 else if (ast_true(v->value))
14085 confp->chan.cid_start = CID_START_RING;
14086 } else if (!strcasecmp(v->name, "threewaycalling")) {
14087 confp->chan.threewaycalling = ast_true(v->value);
14088 } else if (!strcasecmp(v->name, "cancallforward")) {
14089 confp->chan.cancallforward = ast_true(v->value);
14090 } else if (!strcasecmp(v->name, "relaxdtmf")) {
14091 if (ast_true(v->value))
14092 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14093 else
14094 confp->chan.dtmfrelax = 0;
14095 } else if (!strcasecmp(v->name, "mailbox")) {
14096 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14097 } else if (!strcasecmp(v->name, "adsi")) {
14098 confp->chan.adsi = ast_true(v->value);
14099 } else if (!strcasecmp(v->name, "usesmdi")) {
14100 confp->chan.use_smdi = ast_true(v->value);
14101 } else if (!strcasecmp(v->name, "smdiport")) {
14102 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14103 } else if (!strcasecmp(v->name, "transfer")) {
14104 confp->chan.transfer = ast_true(v->value);
14105 } else if (!strcasecmp(v->name, "canpark")) {
14106 confp->chan.canpark = ast_true(v->value);
14107 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14108 confp->chan.echocanbridged = ast_true(v->value);
14109 } else if (!strcasecmp(v->name, "busydetect")) {
14110 confp->chan.busydetect = ast_true(v->value);
14111 } else if (!strcasecmp(v->name, "busycount")) {
14112 confp->chan.busycount = atoi(v->value);
14113 } else if (!strcasecmp(v->name, "silencethreshold")) {
14114 confp->chan.silencethreshold = atoi(v->value);
14115 } else if (!strcasecmp(v->name, "busycompare")) {
14116 confp->chan.busycompare = ast_true(v->value);
14117 } else if (!strcasecmp(v->name, "busypattern")) {
14118 if (sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
14119 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14120 }
14121 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
14122 if (count == 1)
14123 confp->chan.busyquietlength = 0;
14124 else if (count < 1)
14125 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
14126 } else if (!strcasecmp(v->name, "busyfuzziness")) {
14127 confp->chan.busyfuzziness = atoi(v->value);
14128 } else if (!strcasecmp(v->name, "callprogress")) {
14129 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14130 if (ast_true(v->value))
14131 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14132 } else if (!strcasecmp(v->name, "faxdetect")) {
14133 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14134 if (!strcasecmp(v->value, "incoming")) {
14135 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14136 } else if (!strcasecmp(v->value, "outgoing")) {
14137 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14138 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14139 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14140 } else if (!strcasecmp(v->name, "echocancel")) {
14141 process_echocancel(confp, v->value, v->lineno);
14142 } else if (!strcasecmp(v->name, "echotraining")) {
14143 if (sscanf(v->value, "%d", &y) == 1) {
14144 if ((y < 10) || (y > 4000)) {
14145 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
14146 } else {
14147 confp->chan.echotraining = y;
14148 }
14149 } else if (ast_true(v->value)) {
14150 confp->chan.echotraining = 400;
14151 } else
14152 confp->chan.echotraining = 0;
14153 } else if (!strcasecmp(v->name, "hidecallerid")) {
14154 confp->chan.hidecallerid = ast_true(v->value);
14155 } else if (!strcasecmp(v->name, "hidecalleridname")) {
14156 confp->chan.hidecalleridname = ast_true(v->value);
14157 } else if (!strcasecmp(v->name, "pulsedial")) {
14158 confp->chan.pulse = ast_true(v->value);
14159 } else if (!strcasecmp(v->name, "callreturn")) {
14160 confp->chan.callreturn = ast_true(v->value);
14161 } else if (!strcasecmp(v->name, "callwaiting")) {
14162 confp->chan.callwaiting = ast_true(v->value);
14163 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14164 confp->chan.callwaitingcallerid = ast_true(v->value);
14165 } else if (!strcasecmp(v->name, "context")) {
14166 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14167 } else if (!strcasecmp(v->name, "language")) {
14168 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14169 } else if (!strcasecmp(v->name, "progzone")) {
14170 ast_copy_string(progzone, v->value, sizeof(progzone));
14171 } else if (!strcasecmp(v->name, "mohinterpret")
14172 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14173 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14174 } else if (!strcasecmp(v->name, "mohsuggest")) {
14175 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14176 } else if (!strcasecmp(v->name, "stripmsd")) {
14177 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14178 confp->chan.stripmsd = atoi(v->value);
14179 } else if (!strcasecmp(v->name, "jitterbuffers")) {
14180 numbufs = atoi(v->value);
14181 } else if (!strcasecmp(v->name, "group")) {
14182 confp->chan.group = ast_get_group(v->value);
14183 } else if (!strcasecmp(v->name, "callgroup")) {
14184 if (!strcasecmp(v->value, "none"))
14185 confp->chan.callgroup = 0;
14186 else
14187 confp->chan.callgroup = ast_get_group(v->value);
14188 } else if (!strcasecmp(v->name, "pickupgroup")) {
14189 if (!strcasecmp(v->value, "none"))
14190 confp->chan.pickupgroup = 0;
14191 else
14192 confp->chan.pickupgroup = ast_get_group(v->value);
14193 } else if (!strcasecmp(v->name, "setvar")) {
14194 char *varname = ast_strdupa(v->value), *varval = NULL;
14195 struct ast_variable *tmpvar;
14196 if (varname && (varval = strchr(varname, '='))) {
14197 *varval++ = '\0';
14198 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14199 tmpvar->next = confp->chan.vars;
14200 confp->chan.vars = tmpvar;
14201 }
14202 }
14203 } else if (!strcasecmp(v->name, "immediate")) {
14204 confp->chan.immediate = ast_true(v->value);
14205 } else if (!strcasecmp(v->name, "transfertobusy")) {
14206 confp->chan.transfertobusy = ast_true(v->value);
14207 } else if (!strcasecmp(v->name, "mwimonitor")) {
14208 if (!strcasecmp(v->value, "neon")) {
14209 confp->chan.mwimonitor_neon = 1;
14210 confp->chan.mwimonitor_fsk = 0;
14211 } else {
14212 confp->chan.mwimonitor_neon = 0;
14213 if (!strcasecmp(v->value, "fsk"))
14214 confp->chan.mwimonitor_fsk = 1;
14215 else
14216 confp->chan.mwimonitor_fsk = ast_true(v->value) ? 1 : 0;
14217 }
14218 } else if (!strcasecmp(v->name, "cid_rxgain")) {
14219 if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) {
14220 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14221 }
14222 } else if (!strcasecmp(v->name, "rxgain")) {
14223 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
14224 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14225 }
14226 } else if (!strcasecmp(v->name, "txgain")) {
14227 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
14228 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14229 }
14230 } else if (!strcasecmp(v->name, "tonezone")) {
14231 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
14232 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14233 }
14234 } else if (!strcasecmp(v->name, "callerid")) {
14235 if (!strcasecmp(v->value, "asreceived")) {
14236 confp->chan.cid_num[0] = '\0';
14237 confp->chan.cid_name[0] = '\0';
14238 } else {
14239 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14240 }
14241 } else if (!strcasecmp(v->name, "fullname")) {
14242 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14243 } else if (!strcasecmp(v->name, "cid_number")) {
14244 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14245 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14246 confp->chan.dahditrcallerid = ast_true(v->value);
14247 } else if (!strcasecmp(v->name, "restrictcid")) {
14248 confp->chan.restrictcid = ast_true(v->value);
14249 } else if (!strcasecmp(v->name, "usecallingpres")) {
14250 confp->chan.use_callingpres = ast_true(v->value);
14251 } else if (!strcasecmp(v->name, "accountcode")) {
14252 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14253 } else if (!strcasecmp(v->name, "amaflags")) {
14254 y = ast_cdr_amaflags2int(v->value);
14255 if (y < 0)
14256 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14257 else
14258 confp->chan.amaflags = y;
14259 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14260 confp->chan.polarityonanswerdelay = atoi(v->value);
14261 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14262 confp->chan.answeronpolarityswitch = ast_true(v->value);
14263 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14264 confp->chan.hanguponpolarityswitch = ast_true(v->value);
14265 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14266 confp->chan.sendcalleridafter = atoi(v->value);
14267 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14268 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14269 } else if (reload != 1) {
14270 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14271 int orig_radio = confp->chan.radio;
14272 int orig_outsigmod = confp->chan.outsigmod;
14273 int orig_auto = confp->is_sig_auto;
14274
14275 confp->chan.radio = 0;
14276 confp->chan.outsigmod = -1;
14277 confp->is_sig_auto = 0;
14278 if (!strcasecmp(v->value, "em")) {
14279 confp->chan.sig = SIG_EM;
14280 } else if (!strcasecmp(v->value, "em_e1")) {
14281 confp->chan.sig = SIG_EM_E1;
14282 } else if (!strcasecmp(v->value, "em_w")) {
14283 confp->chan.sig = SIG_EMWINK;
14284 } else if (!strcasecmp(v->value, "fxs_ls")) {
14285 confp->chan.sig = SIG_FXSLS;
14286 } else if (!strcasecmp(v->value, "fxs_gs")) {
14287 confp->chan.sig = SIG_FXSGS;
14288 } else if (!strcasecmp(v->value, "fxs_ks")) {
14289 confp->chan.sig = SIG_FXSKS;
14290 } else if (!strcasecmp(v->value, "fxo_ls")) {
14291 confp->chan.sig = SIG_FXOLS;
14292 } else if (!strcasecmp(v->value, "fxo_gs")) {
14293 confp->chan.sig = SIG_FXOGS;
14294 } else if (!strcasecmp(v->value, "fxo_ks")) {
14295 confp->chan.sig = SIG_FXOKS;
14296 } else if (!strcasecmp(v->value, "fxs_rx")) {
14297 confp->chan.sig = SIG_FXSKS;
14298 confp->chan.radio = 1;
14299 } else if (!strcasecmp(v->value, "fxo_rx")) {
14300 confp->chan.sig = SIG_FXOLS;
14301 confp->chan.radio = 1;
14302 } else if (!strcasecmp(v->value, "fxs_tx")) {
14303 confp->chan.sig = SIG_FXSLS;
14304 confp->chan.radio = 1;
14305 } else if (!strcasecmp(v->value, "fxo_tx")) {
14306 confp->chan.sig = SIG_FXOGS;
14307 confp->chan.radio = 1;
14308 } else if (!strcasecmp(v->value, "em_rx")) {
14309 confp->chan.sig = SIG_EM;
14310 confp->chan.radio = 1;
14311 } else if (!strcasecmp(v->value, "em_tx")) {
14312 confp->chan.sig = SIG_EM;
14313 confp->chan.radio = 1;
14314 } else if (!strcasecmp(v->value, "em_rxtx")) {
14315 confp->chan.sig = SIG_EM;
14316 confp->chan.radio = 2;
14317 } else if (!strcasecmp(v->value, "em_txrx")) {
14318 confp->chan.sig = SIG_EM;
14319 confp->chan.radio = 2;
14320 } else if (!strcasecmp(v->value, "sf")) {
14321 confp->chan.sig = SIG_SF;
14322 } else if (!strcasecmp(v->value, "sf_w")) {
14323 confp->chan.sig = SIG_SFWINK;
14324 } else if (!strcasecmp(v->value, "sf_featd")) {
14325 confp->chan.sig = SIG_FEATD;
14326 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14327 confp->chan.sig = SIG_FEATDMF;
14328 } else if (!strcasecmp(v->value, "sf_featb")) {
14329 confp->chan.sig = SIG_SF_FEATB;
14330 } else if (!strcasecmp(v->value, "sf")) {
14331 confp->chan.sig = SIG_SF;
14332 } else if (!strcasecmp(v->value, "sf_rx")) {
14333 confp->chan.sig = SIG_SF;
14334 confp->chan.radio = 1;
14335 } else if (!strcasecmp(v->value, "sf_tx")) {
14336 confp->chan.sig = SIG_SF;
14337 confp->chan.radio = 1;
14338 } else if (!strcasecmp(v->value, "sf_rxtx")) {
14339 confp->chan.sig = SIG_SF;
14340 confp->chan.radio = 2;
14341 } else if (!strcasecmp(v->value, "sf_txrx")) {
14342 confp->chan.sig = SIG_SF;
14343 confp->chan.radio = 2;
14344 } else if (!strcasecmp(v->value, "featd")) {
14345 confp->chan.sig = SIG_FEATD;
14346 } else if (!strcasecmp(v->value, "featdmf")) {
14347 confp->chan.sig = SIG_FEATDMF;
14348 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14349 confp->chan.sig = SIG_FEATDMF_TA;
14350 } else if (!strcasecmp(v->value, "e911")) {
14351 confp->chan.sig = SIG_E911;
14352 } else if (!strcasecmp(v->value, "fgccama")) {
14353 confp->chan.sig = SIG_FGC_CAMA;
14354 } else if (!strcasecmp(v->value, "fgccamamf")) {
14355 confp->chan.sig = SIG_FGC_CAMAMF;
14356 } else if (!strcasecmp(v->value, "featb")) {
14357 confp->chan.sig = SIG_FEATB;
14358 #ifdef HAVE_PRI
14359 } else if (!strcasecmp(v->value, "pri_net")) {
14360 confp->chan.sig = SIG_PRI;
14361 confp->pri.nodetype = PRI_NETWORK;
14362 } else if (!strcasecmp(v->value, "pri_cpe")) {
14363 confp->chan.sig = SIG_PRI;
14364 confp->pri.nodetype = PRI_CPE;
14365 } else if (!strcasecmp(v->value, "bri_cpe")) {
14366 confp->chan.sig = SIG_BRI;
14367 confp->pri.nodetype = PRI_CPE;
14368 } else if (!strcasecmp(v->value, "bri_net")) {
14369 confp->chan.sig = SIG_BRI;
14370 confp->pri.nodetype = PRI_NETWORK;
14371 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14372 confp->chan.sig = SIG_BRI_PTMP;
14373 confp->pri.nodetype = PRI_CPE;
14374 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14375 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
14376 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14377 confp->chan.sig = SIG_GR303FXOKS;
14378 confp->pri.nodetype = PRI_NETWORK;
14379 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14380 confp->chan.sig = SIG_GR303FXSKS;
14381 confp->pri.nodetype = PRI_CPE;
14382 #endif
14383 #ifdef HAVE_SS7
14384 } else if (!strcasecmp(v->value, "ss7")) {
14385 confp->chan.sig = SIG_SS7;
14386 #endif
14387 } else if (!strcasecmp(v->value, "auto")) {
14388 confp->is_sig_auto = 1;
14389 } else {
14390 confp->chan.outsigmod = orig_outsigmod;
14391 confp->chan.radio = orig_radio;
14392 confp->is_sig_auto = orig_auto;
14393 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14394 }
14395 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14396 if (!strcasecmp(v->value, "em")) {
14397 confp->chan.outsigmod = SIG_EM;
14398 } else if (!strcasecmp(v->value, "em_e1")) {
14399 confp->chan.outsigmod = SIG_EM_E1;
14400 } else if (!strcasecmp(v->value, "em_w")) {
14401 confp->chan.outsigmod = SIG_EMWINK;
14402 } else if (!strcasecmp(v->value, "sf")) {
14403 confp->chan.outsigmod = SIG_SF;
14404 } else if (!strcasecmp(v->value, "sf_w")) {
14405 confp->chan.outsigmod = SIG_SFWINK;
14406 } else if (!strcasecmp(v->value, "sf_featd")) {
14407 confp->chan.outsigmod = SIG_FEATD;
14408 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14409 confp->chan.outsigmod = SIG_FEATDMF;
14410 } else if (!strcasecmp(v->value, "sf_featb")) {
14411 confp->chan.outsigmod = SIG_SF_FEATB;
14412 } else if (!strcasecmp(v->value, "sf")) {
14413 confp->chan.outsigmod = SIG_SF;
14414 } else if (!strcasecmp(v->value, "featd")) {
14415 confp->chan.outsigmod = SIG_FEATD;
14416 } else if (!strcasecmp(v->value, "featdmf")) {
14417 confp->chan.outsigmod = SIG_FEATDMF;
14418 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14419 confp->chan.outsigmod = SIG_FEATDMF_TA;
14420 } else if (!strcasecmp(v->value, "e911")) {
14421 confp->chan.outsigmod = SIG_E911;
14422 } else if (!strcasecmp(v->value, "fgccama")) {
14423 confp->chan.outsigmod = SIG_FGC_CAMA;
14424 } else if (!strcasecmp(v->value, "fgccamamf")) {
14425 confp->chan.outsigmod = SIG_FGC_CAMAMF;
14426 } else if (!strcasecmp(v->value, "featb")) {
14427 confp->chan.outsigmod = SIG_FEATB;
14428 } else {
14429 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14430 }
14431 #ifdef HAVE_PRI
14432 } else if (!strcasecmp(v->name, "pridialplan")) {
14433 if (!strcasecmp(v->value, "national")) {
14434 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14435 } else if (!strcasecmp(v->value, "unknown")) {
14436 confp->pri.dialplan = PRI_UNKNOWN + 1;
14437 } else if (!strcasecmp(v->value, "private")) {
14438 confp->pri.dialplan = PRI_PRIVATE + 1;
14439 } else if (!strcasecmp(v->value, "international")) {
14440 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14441 } else if (!strcasecmp(v->value, "local")) {
14442 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14443 } else if (!strcasecmp(v->value, "dynamic")) {
14444 confp->pri.dialplan = -1;
14445 } else if (!strcasecmp(v->value, "redundant")) {
14446 confp->pri.dialplan = -2;
14447 } else {
14448 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14449 }
14450 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14451 if (!strcasecmp(v->value, "national")) {
14452 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14453 } else if (!strcasecmp(v->value, "unknown")) {
14454 confp->pri.localdialplan = PRI_UNKNOWN + 1;
14455 } else if (!strcasecmp(v->value, "private")) {
14456 confp->pri.localdialplan = PRI_PRIVATE + 1;
14457 } else if (!strcasecmp(v->value, "international")) {
14458 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14459 } else if (!strcasecmp(v->value, "local")) {
14460 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14461 } else if (!strcasecmp(v->value, "dynamic")) {
14462 confp->pri.localdialplan = -1;
14463 } else if (!strcasecmp(v->value, "redundant")) {
14464 confp->pri.localdialplan = -2;
14465 } else {
14466 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14467 }
14468 } else if (!strcasecmp(v->name, "switchtype")) {
14469 if (!strcasecmp(v->value, "national"))
14470 confp->pri.switchtype = PRI_SWITCH_NI2;
14471 else if (!strcasecmp(v->value, "ni1"))
14472 confp->pri.switchtype = PRI_SWITCH_NI1;
14473 else if (!strcasecmp(v->value, "dms100"))
14474 confp->pri.switchtype = PRI_SWITCH_DMS100;
14475 else if (!strcasecmp(v->value, "4ess"))
14476 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14477 else if (!strcasecmp(v->value, "5ess"))
14478 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14479 else if (!strcasecmp(v->value, "euroisdn"))
14480 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14481 else if (!strcasecmp(v->value, "qsig"))
14482 confp->pri.switchtype = PRI_SWITCH_QSIG;
14483 else {
14484 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14485 return -1;
14486 }
14487 } else if (!strcasecmp(v->name, "nsf")) {
14488 if (!strcasecmp(v->value, "sdn"))
14489 confp->pri.nsf = PRI_NSF_SDN;
14490 else if (!strcasecmp(v->value, "megacom"))
14491 confp->pri.nsf = PRI_NSF_MEGACOM;
14492 else if (!strcasecmp(v->value, "tollfreemegacom"))
14493 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14494 else if (!strcasecmp(v->value, "accunet"))
14495 confp->pri.nsf = PRI_NSF_ACCUNET;
14496 else if (!strcasecmp(v->value, "none"))
14497 confp->pri.nsf = PRI_NSF_NONE;
14498 else {
14499 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14500 confp->pri.nsf = PRI_NSF_NONE;
14501 }
14502 } else if (!strcasecmp(v->name, "priindication")) {
14503 if (!strcasecmp(v->value, "outofband"))
14504 confp->chan.priindication_oob = 1;
14505 else if (!strcasecmp(v->value, "inband"))
14506 confp->chan.priindication_oob = 0;
14507 else
14508 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14509 v->value, v->lineno);
14510 } else if (!strcasecmp(v->name, "priexclusive")) {
14511 confp->chan.priexclusive = ast_true(v->value);
14512 } else if (!strcasecmp(v->name, "internationalprefix")) {
14513 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14514 } else if (!strcasecmp(v->name, "nationalprefix")) {
14515 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14516 } else if (!strcasecmp(v->name, "localprefix")) {
14517 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14518 } else if (!strcasecmp(v->name, "privateprefix")) {
14519 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14520 } else if (!strcasecmp(v->name, "unknownprefix")) {
14521 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14522 } else if (!strcasecmp(v->name, "resetinterval")) {
14523 if (!strcasecmp(v->value, "never"))
14524 confp->pri.resetinterval = -1;
14525 else if (atoi(v->value) >= 60)
14526 confp->pri.resetinterval = atoi(v->value);
14527 else
14528 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14529 v->value, v->lineno);
14530 } else if (!strcasecmp(v->name, "minunused")) {
14531 confp->pri.minunused = atoi(v->value);
14532 } else if (!strcasecmp(v->name, "minidle")) {
14533 confp->pri.minidle = atoi(v->value);
14534 } else if (!strcasecmp(v->name, "idleext")) {
14535 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14536 } else if (!strcasecmp(v->name, "idledial")) {
14537 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14538 } else if (!strcasecmp(v->name, "overlapdial")) {
14539 if (ast_true(v->value)) {
14540 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14541 } else if (!strcasecmp(v->value, "incoming")) {
14542 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14543 } else if (!strcasecmp(v->value, "outgoing")) {
14544 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14545 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14546 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14547 } else {
14548 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14549 }
14550 #ifdef HAVE_PRI_INBANDDISCONNECT
14551 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14552 confp->pri.inbanddisconnect = ast_true(v->value);
14553 #endif
14554 } else if (!strcasecmp(v->name, "pritimer")) {
14555 #ifdef PRI_GETSET_TIMERS
14556 char tmp[20], *timerc, *c = tmp;
14557 int timer, timeridx;
14558 ast_copy_string(tmp, v->value, sizeof(tmp));
14559 timerc = strsep(&c, ",");
14560 if (timerc) {
14561 timer = atoi(c);
14562 if (!timer)
14563 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc, v->lineno);
14564 else {
14565 if ((timeridx = pri_timer2idx(timerc)) >= 0)
14566 pritimers[timeridx] = timer;
14567 else
14568 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer at line %d.\n", timerc, v->lineno);
14569 }
14570 } else
14571 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v->value, v->lineno);
14572
14573 } else if (!strcasecmp(v->name, "facilityenable")) {
14574 confp->pri.facilityenable = ast_true(v->value);
14575 #endif
14576 #endif
14577 #ifdef HAVE_SS7
14578 } else if (!strcasecmp(v->name, "ss7type")) {
14579 if (!strcasecmp(v->value, "itu")) {
14580 cur_ss7type = SS7_ITU;
14581 } else if (!strcasecmp(v->value, "ansi")) {
14582 cur_ss7type = SS7_ANSI;
14583 } else
14584 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14585 } else if (!strcasecmp(v->name, "linkset")) {
14586 cur_linkset = atoi(v->value);
14587 } else if (!strcasecmp(v->name, "pointcode")) {
14588 cur_pointcode = parse_pointcode(v->value);
14589 } else if (!strcasecmp(v->name, "adjpointcode")) {
14590 cur_adjpointcode = parse_pointcode(v->value);
14591 } else if (!strcasecmp(v->name, "defaultdpc")) {
14592 cur_defaultdpc = parse_pointcode(v->value);
14593 } else if (!strcasecmp(v->name, "cicbeginswith")) {
14594 cur_cicbeginswith = atoi(v->value);
14595 } else if (!strcasecmp(v->name, "networkindicator")) {
14596 if (!strcasecmp(v->value, "national"))
14597 cur_networkindicator = SS7_NI_NAT;
14598 else if (!strcasecmp(v->value, "national_spare"))
14599 cur_networkindicator = SS7_NI_NAT_SPARE;
14600 else if (!strcasecmp(v->value, "international"))
14601 cur_networkindicator = SS7_NI_INT;
14602 else if (!strcasecmp(v->value, "international_spare"))
14603 cur_networkindicator = SS7_NI_INT_SPARE;
14604 else
14605 cur_networkindicator = -1;
14606 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14607 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14608 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14609 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14610 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14611 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14612 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14613 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14614 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14615 if (!strcasecmp(v->value, "national")) {
14616 confp->ss7.called_nai = SS7_NAI_NATIONAL;
14617 } else if (!strcasecmp(v->value, "international")) {
14618 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14619 } else if (!strcasecmp(v->value, "subscriber")) {
14620 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14621 } else if (!strcasecmp(v->value, "dynamic")) {
14622 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14623 } else {
14624 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14625 }
14626 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14627 if (!strcasecmp(v->value, "national")) {
14628 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14629 } else if (!strcasecmp(v->value, "international")) {
14630 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14631 } else if (!strcasecmp(v->value, "subscriber")) {
14632 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14633 } else if (!strcasecmp(v->value, "dynamic")) {
14634 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14635 } else {
14636 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14637 }
14638 } else if (!strcasecmp(v->name, "sigchan")) {
14639 int sigchan, res;
14640 sigchan = atoi(v->value);
14641 res = linkset_addsigchan(sigchan);
14642 if (res < 0)
14643 return -1;
14644
14645 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14646 struct dahdi_ss7 *link;
14647 link = ss7_resolve_linkset(cur_linkset);
14648 if (!link) {
14649 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
14650 return -1;
14651 }
14652 if (ast_true(v->value))
14653 link->flags |= LINKSET_FLAG_EXPLICITACM;
14654
14655 #endif
14656 } else if (!strcasecmp(v->name, "cadence")) {
14657
14658 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14659 int i;
14660 struct dahdi_ring_cadence new_cadence;
14661 int cid_location = -1;
14662 int firstcadencepos = 0;
14663 char original_args[80];
14664 int cadence_is_ok = 1;
14665
14666 ast_copy_string(original_args, v->value, sizeof(original_args));
14667
14668 element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
14669
14670
14671 if (element_count % 2 == 1) {
14672 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
14673 cadence_is_ok = 0;
14674 }
14675
14676
14677 for (i = 0; i < element_count; i++) {
14678 if (c[i] == 0) {
14679 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
14680 cadence_is_ok = 0;
14681 break;
14682 } else if (c[i] < 0) {
14683 if (i % 2 == 1) {
14684
14685 if (cid_location == -1) {
14686 cid_location = i;
14687 c[i] *= -1;
14688 } else {
14689 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
14690 cadence_is_ok = 0;
14691 break;
14692 }
14693 } else {
14694 if (firstcadencepos == 0) {
14695 firstcadencepos = i;
14696
14697 } else {
14698 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
14699 cadence_is_ok = 0;
14700 break;
14701 }
14702 }
14703 }
14704 }
14705
14706
14707 for (i = 0; i < 16; i++) {
14708 new_cadence.ringcadence[i] = c[i];
14709 }
14710
14711 if (cadence_is_ok) {
14712
14713 if (element_count < 2) {
14714 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
14715 } else {
14716 if (cid_location == -1) {
14717
14718 cid_location = 1;
14719 } else {
14720
14721 cid_location = (cid_location + 1) / 2;
14722 }
14723
14724 if (!user_has_defined_cadences++)
14725
14726 num_cadence = 0;
14727 if ((num_cadence+1) >= NUM_CADENCE_MAX)
14728 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
14729 else {
14730 cadences[num_cadence] = new_cadence;
14731 cidrings[num_cadence++] = cid_location;
14732 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
14733 }
14734 }
14735 }
14736 } else if (!strcasecmp(v->name, "ringtimeout")) {
14737 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
14738 } else if (!strcasecmp(v->name, "prewink")) {
14739 confp->timing.prewinktime = atoi(v->value);
14740 } else if (!strcasecmp(v->name, "preflash")) {
14741 confp->timing.preflashtime = atoi(v->value);
14742 } else if (!strcasecmp(v->name, "wink")) {
14743 confp->timing.winktime = atoi(v->value);
14744 } else if (!strcasecmp(v->name, "flash")) {
14745 confp->timing.flashtime = atoi(v->value);
14746 } else if (!strcasecmp(v->name, "start")) {
14747 confp->timing.starttime = atoi(v->value);
14748 } else if (!strcasecmp(v->name, "rxwink")) {
14749 confp->timing.rxwinktime = atoi(v->value);
14750 } else if (!strcasecmp(v->name, "rxflash")) {
14751 confp->timing.rxflashtime = atoi(v->value);
14752 } else if (!strcasecmp(v->name, "debounce")) {
14753 confp->timing.debouncetime = atoi(v->value);
14754 } else if (!strcasecmp(v->name, "toneduration")) {
14755 int toneduration;
14756 int ctlfd;
14757 int res;
14758 struct dahdi_dialparams dps;
14759
14760 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
14761 if (ctlfd == -1) {
14762 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
14763 return -1;
14764 }
14765
14766 toneduration = atoi(v->value);
14767 if (toneduration > -1) {
14768 memset(&dps, 0, sizeof(dps));
14769
14770 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
14771 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
14772 if (res < 0) {
14773 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
14774 return -1;
14775 }
14776 }
14777 close(ctlfd);
14778 } else if (!strcasecmp(v->name, "defaultcic")) {
14779 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
14780 } else if (!strcasecmp(v->name, "defaultozz")) {
14781 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
14782 } else if (!strcasecmp(v->name, "mwilevel")) {
14783 mwilevel = atoi(v->value);
14784 }
14785 } else if (!skipchannels)
14786 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
14787 }
14788 if (dahdichan[0]) {
14789
14790
14791 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
14792 return -1;
14793 }
14794 }
14795
14796
14797 if (!found_pseudo && reload == 0) {
14798
14799
14800
14801 confp->chan.group = 0;
14802 confp->chan.callgroup = 0;
14803 confp->chan.pickupgroup = 0;
14804
14805 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
14806
14807 if (tmp) {
14808 ast_verb(3, "Automatically generated pseudo channel\n");
14809 } else {
14810 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
14811 }
14812 }
14813 return 0;
14814 }
14815
14816 static int setup_dahdi(int reload)
14817 {
14818 struct ast_config *cfg, *ucfg;
14819 struct ast_variable *v;
14820 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
14821 struct dahdi_chan_conf conf;
14822 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
14823 int res;
14824
14825 #ifdef HAVE_PRI
14826 char *c;
14827 int spanno;
14828 int i;
14829 int logicalspan;
14830 int trunkgroup;
14831 int dchannels[NUM_DCHANS];
14832 #endif
14833
14834 cfg = ast_config_load(config, config_flags);
14835
14836
14837 if (!cfg) {
14838 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
14839 return 0;
14840 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
14841 ucfg = ast_config_load("users.conf", config_flags);
14842 if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
14843 return 0;
14844 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
14845 cfg = ast_config_load(config, config_flags);
14846 } else {
14847 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
14848 ucfg = ast_config_load("users.conf", config_flags);
14849 }
14850
14851
14852 ast_mutex_lock(&iflock);
14853 #ifdef HAVE_PRI
14854 if (reload != 1) {
14855
14856 v = ast_variable_browse(cfg, "trunkgroups");
14857 while (v) {
14858 if (!strcasecmp(v->name, "trunkgroup")) {
14859 trunkgroup = atoi(v->value);
14860 if (trunkgroup > 0) {
14861 if ((c = strchr(v->value, ','))) {
14862 i = 0;
14863 memset(dchannels, 0, sizeof(dchannels));
14864 while (c && (i < NUM_DCHANS)) {
14865 dchannels[i] = atoi(c + 1);
14866 if (dchannels[i] < 0) {
14867 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);
14868 } else
14869 i++;
14870 c = strchr(c + 1, ',');
14871 }
14872 if (i) {
14873 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
14874 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);
14875 } else
14876 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");
14877 } else
14878 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14879 } else
14880 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14881 } else
14882 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
14883 } else if (!strcasecmp(v->name, "spanmap")) {
14884 spanno = atoi(v->value);
14885 if (spanno > 0) {
14886 if ((c = strchr(v->value, ','))) {
14887 trunkgroup = atoi(c + 1);
14888 if (trunkgroup > 0) {
14889 if ((c = strchr(c + 1, ',')))
14890 logicalspan = atoi(c + 1);
14891 else
14892 logicalspan = 0;
14893 if (logicalspan >= 0) {
14894 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
14895 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14896 } else
14897 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14898 } else
14899 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);
14900 } else
14901 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
14902 } else
14903 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
14904 } else
14905 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
14906 } else {
14907 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
14908 }
14909 v = v->next;
14910 }
14911 }
14912 #endif
14913
14914
14915 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
14916
14917 mwimonitornotify[0] = '\0';
14918
14919 v = ast_variable_browse(cfg, "channels");
14920 res = process_dahdi(&base_conf, v, reload, 0);
14921 ast_mutex_unlock(&iflock);
14922 ast_config_destroy(cfg);
14923 if (res)
14924 return res;
14925 if (ucfg) {
14926 char *cat;
14927 const char *chans;
14928 process_dahdi(&base_conf, ast_variable_browse(ucfg, "general"), 1, 1);
14929 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
14930 if (!strcasecmp(cat, "general"))
14931 continue;
14932 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
14933 if (!ast_strlen_zero(chans)) {
14934 if (memcpy(&conf, &base_conf, sizeof(conf)) == NULL) {
14935 ast_log(LOG_ERROR, "Not enough memory for conf copy\n");
14936 ast_config_destroy(ucfg);
14937 return -1;
14938 }
14939 process_dahdi(&conf, ast_variable_browse(ucfg, cat), reload, 0);
14940 }
14941 }
14942 ast_config_destroy(ucfg);
14943 }
14944 #ifdef HAVE_PRI
14945 if (reload != 1) {
14946 int x;
14947 for (x = 0; x < NUM_SPANS; x++) {
14948 if (pris[x].pvts[0]) {
14949 if (start_pri(pris + x)) {
14950 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
14951 return -1;
14952 } else
14953 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
14954 }
14955 }
14956 }
14957 #endif
14958 #ifdef HAVE_SS7
14959 if (reload != 1) {
14960 int x;
14961 for (x = 0; x < NUM_SPANS; x++) {
14962 if (linksets[x].ss7) {
14963 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
14964 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
14965 return -1;
14966 } else
14967 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
14968 }
14969 }
14970 }
14971 #endif
14972
14973 restart_monitor();
14974 return 0;
14975 }
14976
14977 static int load_module(void)
14978 {
14979 int res;
14980 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14981 int y, i;
14982 #endif
14983
14984 #ifdef HAVE_PRI
14985 memset(pris, 0, sizeof(pris));
14986 for (y = 0; y < NUM_SPANS; y++) {
14987 ast_mutex_init(&pris[y].lock);
14988 pris[y].offset = -1;
14989 pris[y].master = AST_PTHREADT_NULL;
14990 for (i = 0; i < NUM_DCHANS; i++)
14991 pris[y].fds[i] = -1;
14992 }
14993 pri_set_error(dahdi_pri_error);
14994 pri_set_message(dahdi_pri_message);
14995 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
14996 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
14997 #endif
14998 #ifdef HAVE_SS7
14999 memset(linksets, 0, sizeof(linksets));
15000 for (y = 0; y < NUM_SPANS; y++) {
15001 ast_mutex_init(&linksets[y].lock);
15002 linksets[y].master = AST_PTHREADT_NULL;
15003 for (i = 0; i < NUM_DCHANS; i++)
15004 linksets[y].fds[i] = -1;
15005 }
15006 ss7_set_error(dahdi_ss7_error);
15007 ss7_set_message(dahdi_ss7_message);
15008 #endif
15009 res = setup_dahdi(0);
15010
15011 if (res)
15012 return AST_MODULE_LOAD_DECLINE;
15013 if (ast_channel_register(&dahdi_tech)) {
15014 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15015 __unload_module();
15016 return AST_MODULE_LOAD_FAILURE;
15017 }
15018 #ifdef HAVE_PRI
15019 ast_string_field_init(&inuse, 16);
15020 ast_string_field_set(&inuse, name, "GR-303InUse");
15021 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
15022 #endif
15023 #ifdef HAVE_SS7
15024 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15025 #endif
15026
15027 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
15028
15029 memset(round_robin, 0, sizeof(round_robin));
15030 ast_manager_register("DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15031 ast_manager_register("DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15032 ast_manager_register("DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15033 ast_manager_register("DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15034 ast_manager_register("DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15035 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status dahdi channels");
15036 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15037
15038 ast_cond_init(&ss_thread_complete, NULL);
15039
15040 return res;
15041 }
15042
15043 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15044 {
15045 #define END_SILENCE_LEN 400
15046 #define HEADER_MS 50
15047 #define TRAILER_MS 5
15048 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15049 #define ASCII_BYTES_PER_CHAR 80
15050
15051 unsigned char *buf,*mybuf;
15052 struct dahdi_pvt *p = c->tech_pvt;
15053 struct pollfd fds[1];
15054 int size,res,fd,len,x;
15055 int bytes=0;
15056
15057 float cr = 1.0;
15058 float ci = 0.0;
15059 float scont = 0.0;
15060 int index;
15061
15062 index = dahdi_get_index(c, p, 0);
15063 if (index < 0) {
15064 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
15065 return -1;
15066 }
15067 if (!text[0]) return(0);
15068 if ((!p->tdd) && (!p->mate)) return(0);
15069 if (p->mate)
15070 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15071 else
15072 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15073 if (!buf)
15074 return -1;
15075 mybuf = buf;
15076 if (p->mate) {
15077 int codec = AST_LAW(p);
15078 for (x = 0; x < HEADER_MS; x++) {
15079 PUT_CLID_MARKMS;
15080 }
15081
15082 for (x = 0; text[x]; x++) {
15083 PUT_CLID(text[x]);
15084 }
15085 for (x = 0; x < TRAILER_MS; x++) {
15086 PUT_CLID_MARKMS;
15087 }
15088 len = bytes;
15089 buf = mybuf;
15090 } else {
15091 len = tdd_generate(p->tdd, buf, text);
15092 if (len < 1) {
15093 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15094 ast_free(mybuf);
15095 return -1;
15096 }
15097 }
15098 memset(buf + len, 0x7f, END_SILENCE_LEN);
15099 len += END_SILENCE_LEN;
15100 fd = p->subs[index].dfd;
15101 while (len) {
15102 if (ast_check_hangup(c)) {
15103 ast_free(mybuf);
15104 return -1;
15105 }
15106 size = len;
15107 if (size > READ_SIZE)
15108 size = READ_SIZE;
15109 fds[0].fd = fd;
15110 fds[0].events = POLLOUT | POLLPRI;
15111 fds[0].revents = 0;
15112 res = poll(fds, 1, -1);
15113 if (!res) {
15114 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15115 continue;
15116 }
15117
15118 if (fds[0].revents & POLLPRI) {
15119 ast_free(mybuf);
15120 return -1;
15121 }
15122 if (!(fds[0].revents & POLLOUT)) {
15123 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15124 continue;
15125 }
15126 res = write(fd, buf, size);
15127 if (res != size) {
15128 if (res == -1) {
15129 ast_free(mybuf);
15130 return -1;
15131 }
15132 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15133 break;
15134 }
15135 len -= size;
15136 buf += size;
15137 }
15138 ast_free(mybuf);
15139 return(0);
15140 }
15141
15142
15143 static int reload(void)
15144 {
15145 int res = 0;
15146
15147 res = setup_dahdi(1);
15148 if (res) {
15149 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15150 return -1;
15151 }
15152 return 0;
15153 }
15154
15155
15156
15157
15158
15159 #ifdef HAVE_PRI
15160 #ifdef HAVE_SS7
15161 #define tdesc "DAHDI Telephony w/PRI & SS7"
15162 #else
15163 #define tdesc "DAHDI Telephony w/PRI"
15164 #endif
15165 #else
15166 #ifdef HAVE_SS7
15167 #define tdesc "DAHDI Telephony w/SS7"
15168 #else
15169 #define tdesc "DAHDI Telephony"
15170 #endif
15171 #endif
15172
15173 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15174 .load = load_module,
15175 .unload = unload_module,
15176 .reload = reload,
15177 );
15178
15179