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: 180010 $")
00051
00052 #include <stdio.h>
00053 #include <string.h>
00054 #ifdef __NetBSD__
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <errno.h>
00061 #include <stdlib.h>
00062 #if !defined(SOLARIS) && !defined(__FreeBSD__)
00063 #include <stdint.h>
00064 #endif
00065 #include <unistd.h>
00066 #include <sys/ioctl.h>
00067 #include <math.h>
00068 #include <ctype.h>
00069
00070 #ifdef HAVE_PRI
00071 #include <libpri.h>
00072 #endif
00073
00074 #include "asterisk/lock.h"
00075 #include "asterisk/channel.h"
00076 #include "asterisk/config.h"
00077 #include "asterisk/logger.h"
00078 #include "asterisk/module.h"
00079 #include "asterisk/pbx.h"
00080 #include "asterisk/options.h"
00081 #include "asterisk/file.h"
00082 #include "asterisk/ulaw.h"
00083 #include "asterisk/alaw.h"
00084 #include "asterisk/callerid.h"
00085 #include "asterisk/adsi.h"
00086 #include "asterisk/cli.h"
00087 #include "asterisk/cdr.h"
00088 #include "asterisk/features.h"
00089 #include "asterisk/musiconhold.h"
00090 #include "asterisk/say.h"
00091 #include "asterisk/tdd.h"
00092 #include "asterisk/app.h"
00093 #include "asterisk/dsp.h"
00094 #include "asterisk/astdb.h"
00095 #include "asterisk/manager.h"
00096 #include "asterisk/causes.h"
00097 #include "asterisk/term.h"
00098 #include "asterisk/utils.h"
00099 #include "asterisk/transcap.h"
00100 #include "asterisk/stringfields.h"
00101 #include "asterisk/abstract_jb.h"
00102 #include "asterisk/smdi.h"
00103 #include "asterisk/astobj.h"
00104 #define SMDI_MD_WAIT_TIMEOUT 1500
00105
00106 #include "asterisk/dahdi_compat.h"
00107 #include "asterisk/tonezone_compat.h"
00108
00109
00110 static struct ast_jb_conf default_jbconf =
00111 {
00112 .flags = 0,
00113 .max_size = -1,
00114 .resync_threshold = -1,
00115 .impl = ""
00116 };
00117 static struct ast_jb_conf global_jbconf;
00118
00119 #ifndef DAHDI_TONEDETECT
00120
00121 #define DAHDI_EVENT_DTMFDOWN 0
00122 #define DAHDI_EVENT_DTMFUP 0
00123 #endif
00124
00125
00126 #undef SUPPORT_USERUSER
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 #define DEFAULT_CIDRINGS 1
00148
00149 #define CHANNEL_PSEUDO -12
00150
00151 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00152
00153
00154 #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))
00155
00156 static const char tdesc[] = "DAHDI Telephony Driver"
00157 #ifdef HAVE_PRI
00158 " w/PRI"
00159 #endif
00160 ;
00161
00162 #define SIG_EM DAHDI_SIG_EM
00163 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00164 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00165 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00166 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00167 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00168 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00169 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00170 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00171 #define SIG_FXSLS DAHDI_SIG_FXSLS
00172 #define SIG_FXSGS DAHDI_SIG_FXSGS
00173 #define SIG_FXSKS DAHDI_SIG_FXSKS
00174 #define SIG_FXOLS DAHDI_SIG_FXOLS
00175 #define SIG_FXOGS DAHDI_SIG_FXOGS
00176 #define SIG_FXOKS DAHDI_SIG_FXOKS
00177 #define SIG_PRI DAHDI_SIG_CLEAR
00178 #define SIG_SF DAHDI_SIG_SF
00179 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00180 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00181 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00182 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00183 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00184 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00185 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00186
00187 #define NUM_SPANS 32
00188 #define NUM_DCHANS 4
00189 #define MAX_CHANNELS 672
00190
00191 #define CHAN_PSEUDO -2
00192
00193 #define DCHAN_PROVISIONED (1 << 0)
00194 #define DCHAN_NOTINALARM (1 << 1)
00195 #define DCHAN_UP (1 << 2)
00196
00197 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00198
00199 static char defaultcic[64] = "";
00200 static char defaultozz[64] = "";
00201
00202 static char progzone[10] = "";
00203
00204 static int distinctiveringaftercid = 0;
00205
00206 static int numbufs = 4;
00207
00208 #ifdef HAVE_PRI
00209 static struct ast_channel inuse;
00210 #ifdef PRI_GETSET_TIMERS
00211 static int pritimers[PRI_MAX_TIMERS];
00212 #endif
00213 static int pridebugfd = -1;
00214 static char pridebugfilename[1024] = "";
00215 #endif
00216
00217
00218 static int firstdigittimeout = 16000;
00219
00220
00221 static int gendigittimeout = 8000;
00222
00223
00224 static int matchdigittimeout = 3000;
00225
00226
00227 AST_MUTEX_DEFINE_STATIC(iflock);
00228
00229
00230 static int ifcount = 0;
00231
00232 #ifdef HAVE_PRI
00233 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00234 #endif
00235
00236
00237
00238 AST_MUTEX_DEFINE_STATIC(monlock);
00239
00240
00241
00242 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00243 static ast_cond_t ss_thread_complete;
00244 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00245 AST_MUTEX_DEFINE_STATIC(restart_lock);
00246 static int ss_thread_count = 0;
00247 static int num_restart_pending = 0;
00248
00249 static int restart_monitor(void);
00250
00251 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);
00252
00253 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00254
00255
00256 static inline int dahdi_get_event(int fd)
00257 {
00258 int j;
00259 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00260 return -1;
00261 return j;
00262 }
00263
00264
00265 static inline int dahdi_wait_event(int fd)
00266 {
00267 int i, j = 0;
00268 i = DAHDI_IOMUX_SIGEVENT;
00269 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00270 return -1;
00271 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00272 return -1;
00273 return j;
00274 }
00275
00276
00277 #define READ_SIZE 160
00278
00279 #define MASK_AVAIL (1 << 0)
00280 #define MASK_INUSE (1 << 1)
00281
00282 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00283 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00284 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00285 #define MIN_MS_SINCE_FLASH ( (2000) )
00286 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00287
00288 struct dahdi_pvt;
00289
00290
00291
00292
00293
00294 static int ringt_base = DEFAULT_RINGT;
00295
00296 #ifdef HAVE_PRI
00297
00298 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00299 #define PRI_CHANNEL(p) ((p) & 0xff)
00300 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00301 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00302
00303 struct dahdi_pri {
00304 pthread_t master;
00305 ast_mutex_t lock;
00306 char idleext[AST_MAX_EXTENSION];
00307 char idlecontext[AST_MAX_CONTEXT];
00308 char idledial[AST_MAX_EXTENSION];
00309 int minunused;
00310 int minidle;
00311 int nodetype;
00312 int switchtype;
00313 int nsf;
00314 int dialplan;
00315 int localdialplan;
00316 char internationalprefix[10];
00317 char nationalprefix[10];
00318 char localprefix[20];
00319 char privateprefix[20];
00320 char unknownprefix[20];
00321 int dchannels[NUM_DCHANS];
00322 int trunkgroup;
00323 int mastertrunkgroup;
00324 int prilogicalspan;
00325 int numchans;
00326 int overlapdial;
00327 int facilityenable;
00328 struct pri *dchans[NUM_DCHANS];
00329 int dchanavail[NUM_DCHANS];
00330 struct pri *pri;
00331
00332 int debug;
00333 int fds[NUM_DCHANS];
00334
00335 int offset;
00336
00337 int span;
00338
00339 int resetting;
00340
00341 int resetpos;
00342 #ifdef HAVE_PRI_INBANDDISCONNECT
00343 unsigned int inbanddisconnect:1;
00344 #endif
00345 time_t lastreset;
00346 long resetinterval;
00347 struct dahdi_pvt *pvts[MAX_CHANNELS];
00348 struct dahdi_pvt *crvs;
00349 struct dahdi_pvt *crvend;
00350 };
00351
00352
00353 static struct dahdi_pri pris[NUM_SPANS];
00354
00355 #if 0
00356 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00357 #else
00358 #define DEFAULT_PRI_DEBUG 0
00359 #endif
00360
00361 static inline void pri_rel(struct dahdi_pri *pri)
00362 {
00363 ast_mutex_unlock(&pri->lock);
00364 }
00365
00366 #else
00367
00368 struct dahdi_pri;
00369 #endif
00370
00371 #define SUB_REAL 0
00372 #define SUB_CALLWAIT 1
00373 #define SUB_THREEWAY 2
00374
00375
00376 #define POLARITY_IDLE 0
00377 #define POLARITY_REV 1
00378
00379
00380 static struct dahdi_distRings drings;
00381
00382 struct distRingData {
00383 int ring[3];
00384 };
00385 struct ringContextData {
00386 char contextData[AST_MAX_CONTEXT];
00387 };
00388 struct dahdi_distRings {
00389 struct distRingData ringnum[3];
00390 struct ringContextData ringContext[3];
00391 };
00392
00393 static char *subnames[] = {
00394 "Real",
00395 "Callwait",
00396 "Threeway"
00397 };
00398
00399 struct dahdi_subchannel {
00400 int dfd;
00401 struct ast_channel *owner;
00402 int chan;
00403 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00404 struct ast_frame f;
00405 unsigned int needringing:1;
00406 unsigned int needbusy:1;
00407 unsigned int needcongestion:1;
00408 unsigned int needcallerid:1;
00409 unsigned int needanswer:1;
00410 unsigned int needflash:1;
00411 unsigned int needhold:1;
00412 unsigned int needunhold:1;
00413 unsigned int linear:1;
00414 unsigned int inthreeway:1;
00415 struct dahdi_confinfo curconf;
00416 };
00417
00418 #define CONF_USER_REAL (1 << 0)
00419 #define CONF_USER_THIRDCALL (1 << 1)
00420
00421 #define MAX_SLAVES 4
00422
00423 static struct dahdi_pvt {
00424 ast_mutex_t lock;
00425 struct ast_channel *owner;
00426
00427
00428 struct dahdi_subchannel sub_unused;
00429 struct dahdi_subchannel subs[3];
00430 struct dahdi_confinfo saveconf;
00431
00432 struct dahdi_pvt *slaves[MAX_SLAVES];
00433 struct dahdi_pvt *master;
00434 int inconference;
00435
00436 int buf_no;
00437 int buf_policy;
00438 int sig;
00439
00440
00441
00442
00443 int radio;
00444 int outsigmod;
00445 int oprmode;
00446 struct dahdi_pvt *oprpeer;
00447
00448 float rxgain;
00449
00450 float txgain;
00451 int tonezone;
00452 struct dahdi_pvt *next;
00453 struct dahdi_pvt *prev;
00454
00455
00456
00457
00458
00459
00460
00461 unsigned int adsi:1;
00462
00463
00464
00465
00466
00467 unsigned int answeronpolarityswitch:1;
00468
00469
00470
00471
00472
00473 unsigned int busydetect:1;
00474
00475
00476
00477
00478
00479 unsigned int callreturn:1;
00480
00481
00482
00483
00484
00485
00486 unsigned int callwaiting:1;
00487
00488
00489
00490
00491 unsigned int callwaitingcallerid:1;
00492
00493
00494
00495
00496
00497
00498 unsigned int cancallforward:1;
00499
00500
00501
00502
00503 unsigned int canpark:1;
00504
00505 unsigned int confirmanswer:1;
00506
00507
00508
00509
00510 unsigned int destroy:1;
00511 unsigned int didtdd:1;
00512
00513 unsigned int dialednone:1;
00514
00515 unsigned int dialing:1;
00516
00517 unsigned int digital:1;
00518
00519 unsigned int dnd:1;
00520
00521 unsigned int echobreak:1;
00522
00523
00524
00525
00526
00527 unsigned int echocanbridged:1;
00528
00529 unsigned int echocanon:1;
00530
00531 unsigned int faxhandled:1;
00532
00533 unsigned int firstradio:1;
00534
00535
00536
00537
00538 unsigned int hanguponpolarityswitch:1;
00539
00540 unsigned int hardwaredtmf:1;
00541
00542
00543
00544
00545
00546
00547 unsigned int hidecallerid:1;
00548
00549
00550
00551
00552
00553 unsigned int hidecalleridname:1;
00554
00555 unsigned int ignoredtmf:1;
00556
00557
00558
00559
00560
00561 unsigned int immediate:1;
00562
00563 unsigned int inalarm:1;
00564 unsigned int unknown_alarm:1;
00565
00566 unsigned int mate:1;
00567
00568 unsigned int outgoing:1;
00569
00570
00571
00572
00573
00574
00575 unsigned int permcallwaiting:1;
00576
00577
00578
00579
00580 unsigned int permhidecallerid:1;
00581
00582
00583
00584
00585 unsigned int priindication_oob:1;
00586
00587
00588
00589
00590 unsigned int priexclusive:1;
00591
00592
00593
00594
00595 unsigned int pulse:1;
00596
00597 unsigned int pulsedial:1;
00598 unsigned int restartpending:1;
00599
00600
00601
00602
00603
00604 unsigned int restrictcid:1;
00605
00606
00607
00608
00609 unsigned int threewaycalling:1;
00610
00611
00612
00613
00614
00615
00616
00617
00618 unsigned int transfer:1;
00619
00620
00621
00622
00623
00624
00625
00626 unsigned int use_callerid:1;
00627
00628
00629
00630
00631
00632
00633 unsigned int use_callingpres:1;
00634
00635
00636
00637
00638
00639 unsigned int usedistinctiveringdetection:1;
00640
00641
00642
00643
00644 unsigned int dahditrcallerid:1;
00645
00646
00647
00648
00649 unsigned int transfertobusy:1;
00650 #if defined(HAVE_PRI)
00651
00652 unsigned int alerting:1;
00653
00654 unsigned int alreadyhungup:1;
00655
00656
00657
00658
00659 unsigned int isidlecall:1;
00660
00661
00662
00663
00664 unsigned int proceeding:1;
00665
00666 unsigned int progress:1;
00667
00668
00669
00670
00671 unsigned int resetting:1;
00672
00673
00674
00675
00676 unsigned int setup_ack:1;
00677 #endif
00678
00679
00680
00681
00682 unsigned int use_smdi:1;
00683
00684 struct ast_smdi_interface *smdi_iface;
00685
00686
00687 struct dahdi_distRings drings;
00688
00689
00690
00691
00692
00693 char context[AST_MAX_CONTEXT];
00694
00695
00696
00697 char defcontext[AST_MAX_CONTEXT];
00698
00699 char exten[AST_MAX_EXTENSION];
00700
00701
00702
00703
00704 char language[MAX_LANGUAGE];
00705
00706
00707
00708
00709 char mohinterpret[MAX_MUSICCLASS];
00710
00711
00712
00713
00714 char mohsuggest[MAX_MUSICCLASS];
00715 #ifdef PRI_ANI
00716
00717 char cid_ani[AST_MAX_EXTENSION];
00718 #endif
00719
00720 char cid_num[AST_MAX_EXTENSION];
00721
00722 int cid_ton;
00723
00724 char cid_name[AST_MAX_EXTENSION];
00725
00726 char lastcid_num[AST_MAX_EXTENSION];
00727
00728 char lastcid_name[AST_MAX_EXTENSION];
00729 char *origcid_num;
00730 char *origcid_name;
00731
00732 char callwait_num[AST_MAX_EXTENSION];
00733
00734 char callwait_name[AST_MAX_EXTENSION];
00735
00736 char rdnis[AST_MAX_EXTENSION];
00737
00738 char dnid[AST_MAX_EXTENSION];
00739
00740
00741
00742
00743 ast_group_t group;
00744
00745 int law;
00746 int confno;
00747 int confusers;
00748 int propconfno;
00749
00750
00751
00752
00753 ast_group_t callgroup;
00754
00755
00756
00757
00758 ast_group_t pickupgroup;
00759 int channel;
00760 int span;
00761 time_t guardtime;
00762 int cid_signalling;
00763 int cid_start;
00764 int callingpres;
00765 int callwaitingrepeat;
00766 int cidcwexpire;
00767
00768 unsigned char *cidspill;
00769
00770 int cidpos;
00771
00772 int cidlen;
00773
00774 int ringt;
00775
00776
00777
00778
00779 int ringt_base;
00780
00781
00782
00783
00784
00785
00786 int stripmsd;
00787
00788 int callwaitcas;
00789
00790 int callwaitrings;
00791
00792 int echocancel;
00793
00794
00795
00796
00797 int echotraining;
00798
00799 char echorest[20];
00800
00801
00802
00803
00804 int busycount;
00805
00806
00807
00808
00809 int busycompare;
00810
00811
00812
00813
00814 int busytonelength;
00815
00816
00817
00818
00819 int busyquietlength;
00820
00821
00822
00823
00824 int busyfuzziness;
00825
00826
00827
00828
00829 int silencethreshold;
00830
00831
00832
00833
00834 int callprogress;
00835 struct timeval flashtime;
00836
00837 struct ast_dsp *dsp;
00838
00839
00840 struct dahdi_dialoperation dop;
00841 int whichwink;
00842
00843 char finaldial[64];
00844 char accountcode[AST_MAX_ACCOUNT_CODE];
00845 int amaflags;
00846 struct tdd_state *tdd;
00847
00848 char call_forward[AST_MAX_EXTENSION];
00849
00850
00851
00852
00853 char mailbox[AST_MAX_EXTENSION];
00854
00855 char dialdest[256];
00856
00857 int onhooktime;
00858
00859 int msgstate;
00860 int distinctivering;
00861 int cidrings;
00862 int dtmfrelax;
00863
00864 int fake_event;
00865
00866
00867
00868
00869 int polarityonanswerdelay;
00870
00871 struct timeval polaritydelaytv;
00872
00873
00874
00875
00876 int sendcalleridafter;
00877 #ifdef HAVE_PRI
00878
00879 struct dahdi_pri *pri;
00880
00881 struct dahdi_pvt *bearer;
00882
00883 struct dahdi_pvt *realcall;
00884
00885 q931_call *call;
00886
00887 int prioffset;
00888
00889 int logicalspan;
00890 #endif
00891
00892 int polarity;
00893
00894 int dsp_features;
00895
00896 char begindigit;
00897 } *iflist = NULL, *ifend = NULL;
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 struct dahdi_chan_conf {
00910 struct dahdi_pvt chan;
00911 #ifdef HAVE_PRI
00912 struct dahdi_pri pri;
00913 #endif
00914 struct dahdi_params timing;
00915
00916
00917
00918
00919
00920 char smdi_port[SMDI_MAX_FILENAME_LEN];
00921 };
00922
00923
00924 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
00925
00926
00927
00928 struct dahdi_chan_conf conf = {
00929 #ifdef HAVE_PRI
00930 .pri = {
00931 .nsf = PRI_NSF_NONE,
00932 .switchtype = PRI_SWITCH_NI2,
00933 .dialplan = PRI_NATIONAL_ISDN + 1,
00934 .localdialplan = PRI_NATIONAL_ISDN + 1,
00935 .nodetype = PRI_CPE,
00936
00937 .minunused = 2,
00938 .idleext = "",
00939 .idledial = "",
00940 .internationalprefix = "",
00941 .nationalprefix = "",
00942 .localprefix = "",
00943 .privateprefix = "",
00944 .unknownprefix = "",
00945
00946 .resetinterval = 3600
00947 },
00948 #endif
00949 .chan = {
00950 .context = "default",
00951 .cid_num = "",
00952 .cid_name = "",
00953 .mohinterpret = "default",
00954 .mohsuggest = "",
00955 .transfertobusy = 1,
00956
00957 .cid_signalling = CID_SIG_BELL,
00958 .cid_start = CID_START_RING,
00959 .dahditrcallerid = 0,
00960 .use_callerid = 1,
00961 .sig = -1,
00962 .outsigmod = -1,
00963
00964 .tonezone = -1,
00965
00966 .echocancel = 1,
00967
00968 .busycount = 3,
00969 .busycompare = 0,
00970 .busytonelength = 0,
00971 .busyquietlength = 0,
00972 .busyfuzziness = 0,
00973 .silencethreshold = 0,
00974
00975 .accountcode = "",
00976
00977 .mailbox = "",
00978
00979
00980 .polarityonanswerdelay = 600,
00981
00982 .sendcalleridafter = DEFAULT_CIDRINGS,
00983
00984 .buf_policy = DAHDI_POLICY_IMMEDIATE,
00985 .buf_no = numbufs
00986 },
00987 .timing = {
00988 .prewinktime = -1,
00989 .preflashtime = -1,
00990 .winktime = -1,
00991 .flashtime = -1,
00992 .starttime = -1,
00993 .rxwinktime = -1,
00994 .rxflashtime = -1,
00995 .debouncetime = -1
00996 },
00997 .smdi_port = "/dev/ttyS0",
00998 };
00999
01000 return conf;
01001 }
01002
01003
01004 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01005 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01006 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01007 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01008 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01009 static int dahdi_hangup(struct ast_channel *ast);
01010 static int dahdi_answer(struct ast_channel *ast);
01011 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01012 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01013 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01014 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01015 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01016 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01017 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
01018
01019 static const struct ast_channel_tech dahdi_tech = {
01020 .type = "DAHDI",
01021 .description = tdesc,
01022 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01023 .requester = dahdi_request,
01024 .send_digit_begin = dahdi_digit_begin,
01025 .send_digit_end = dahdi_digit_end,
01026 .send_text = dahdi_sendtext,
01027 .call = dahdi_call,
01028 .hangup = dahdi_hangup,
01029 .answer = dahdi_answer,
01030 .read = dahdi_read,
01031 .write = dahdi_write,
01032 .bridge = dahdi_bridge,
01033 .exception = dahdi_exception,
01034 .indicate = dahdi_indicate,
01035 .fixup = dahdi_fixup,
01036 .setoption = dahdi_setoption,
01037 .func_channel_read = dahdi_func_read,
01038 };
01039
01040 static const struct ast_channel_tech zap_tech = {
01041 .type = "Zap",
01042 .description = tdesc,
01043 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01044 .requester = dahdi_request,
01045 .send_digit_begin = dahdi_digit_begin,
01046 .send_digit_end = dahdi_digit_end,
01047 .send_text = dahdi_sendtext,
01048 .call = dahdi_call,
01049 .hangup = dahdi_hangup,
01050 .answer = dahdi_answer,
01051 .read = dahdi_read,
01052 .write = dahdi_write,
01053 .bridge = dahdi_bridge,
01054 .exception = dahdi_exception,
01055 .indicate = dahdi_indicate,
01056 .fixup = dahdi_fixup,
01057 .setoption = dahdi_setoption,
01058 .func_channel_read = dahdi_func_read,
01059 };
01060
01061 static const struct ast_channel_tech *chan_tech;
01062
01063 #ifdef HAVE_PRI
01064 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01065 #else
01066 #define GET_CHANNEL(p) ((p)->channel)
01067 #endif
01068
01069 struct dahdi_pvt *round_robin[32];
01070
01071 #ifdef HAVE_PRI
01072 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01073 {
01074 int res;
01075
01076 do {
01077 res = ast_mutex_trylock(&pri->lock);
01078 if (res) {
01079 DEADLOCK_AVOIDANCE(&pvt->lock);
01080 }
01081 } while (res);
01082
01083 if (pri->master != AST_PTHREADT_NULL)
01084 pthread_kill(pri->master, SIGURG);
01085 return 0;
01086 }
01087 #endif
01088
01089 #define NUM_CADENCE_MAX 25
01090 static int num_cadence = 4;
01091 static int user_has_defined_cadences = 0;
01092
01093 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01094 { { 125, 125, 2000, 4000 } },
01095 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01096 { { 125, 125, 125, 125, 125, 4000 } },
01097 { { 1000, 500, 2500, 5000 } },
01098 };
01099
01100
01101
01102
01103
01104 static int cidrings[NUM_CADENCE_MAX] = {
01105 2,
01106 4,
01107 3,
01108 2,
01109 };
01110
01111 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01112 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01113
01114 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01115 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01116
01117 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01118 {
01119 int res;
01120 if (p->subs[SUB_REAL].owner == ast)
01121 res = 0;
01122 else if (p->subs[SUB_CALLWAIT].owner == ast)
01123 res = 1;
01124 else if (p->subs[SUB_THREEWAY].owner == ast)
01125 res = 2;
01126 else {
01127 res = -1;
01128 if (!nullok)
01129 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01130 }
01131 return res;
01132 }
01133
01134 #ifdef HAVE_PRI
01135 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01136 #else
01137 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01138 #endif
01139 {
01140 #ifdef HAVE_PRI
01141 if (pri)
01142 ast_mutex_unlock(&pri->lock);
01143 #endif
01144 for (;;) {
01145 if (p->subs[a].owner) {
01146 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
01147 DEADLOCK_AVOIDANCE(&p->lock);
01148 } else {
01149 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01150 ast_mutex_unlock(&p->subs[a].owner->lock);
01151 break;
01152 }
01153 } else
01154 break;
01155 }
01156 #ifdef HAVE_PRI
01157 if (pri)
01158 ast_mutex_lock(&pri->lock);
01159 #endif
01160 }
01161
01162 #ifdef HAVE_PRI
01163 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
01164 #else
01165 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
01166 #endif
01167 {
01168
01169 #ifdef HAVE_PRI
01170 if (pri)
01171 ast_mutex_unlock(&pri->lock);
01172 #endif
01173 for (;;) {
01174 if (p->owner) {
01175 if (ast_mutex_trylock(&p->owner->lock)) {
01176 DEADLOCK_AVOIDANCE(&p->lock);
01177 } else {
01178 ast_queue_frame(p->owner, f);
01179 ast_mutex_unlock(&p->owner->lock);
01180 break;
01181 }
01182 } else
01183 break;
01184 }
01185 #ifdef HAVE_PRI
01186 if (pri)
01187 ast_mutex_lock(&pri->lock);
01188 #endif
01189 }
01190
01191 static int restore_gains(struct dahdi_pvt *p);
01192
01193 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01194 {
01195 int tchan;
01196 int tinthreeway;
01197 struct ast_channel *towner;
01198
01199 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01200
01201 tchan = p->subs[a].chan;
01202 towner = p->subs[a].owner;
01203 tinthreeway = p->subs[a].inthreeway;
01204
01205 p->subs[a].chan = p->subs[b].chan;
01206 p->subs[a].owner = p->subs[b].owner;
01207 p->subs[a].inthreeway = p->subs[b].inthreeway;
01208
01209 p->subs[b].chan = tchan;
01210 p->subs[b].owner = towner;
01211 p->subs[b].inthreeway = tinthreeway;
01212
01213 if (p->subs[a].owner)
01214 p->subs[a].owner->fds[0] = p->subs[a].dfd;
01215 if (p->subs[b].owner)
01216 p->subs[b].owner->fds[0] = p->subs[b].dfd;
01217 wakeup_sub(p, a, NULL);
01218 wakeup_sub(p, b, NULL);
01219 }
01220
01221 static int dahdi_open(char *fn)
01222 {
01223 int fd;
01224 int isnum;
01225 int chan = 0;
01226 int bs;
01227 int x;
01228 isnum = 1;
01229 for (x = 0; x < strlen(fn); x++) {
01230 if (!isdigit(fn[x])) {
01231 isnum = 0;
01232 break;
01233 }
01234 }
01235 if (isnum) {
01236 chan = atoi(fn);
01237 if (chan < 1) {
01238 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01239 return -1;
01240 }
01241 fn = DAHDI_FILE_CHANNEL;
01242 }
01243 fd = open(fn, O_RDWR | O_NONBLOCK);
01244 if (fd < 0) {
01245 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01246 return -1;
01247 }
01248 if (chan) {
01249 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01250 x = errno;
01251 close(fd);
01252 errno = x;
01253 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01254 return -1;
01255 }
01256 }
01257 bs = READ_SIZE;
01258 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01259 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01260 x = errno;
01261 close(fd);
01262 errno = x;
01263 return -1;
01264 }
01265 return fd;
01266 }
01267
01268 static void dahdi_close(int fd)
01269 {
01270 if (fd > 0)
01271 close(fd);
01272 }
01273
01274 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01275 {
01276 dahdi_close(chan_pvt->subs[sub_num].dfd);
01277 chan_pvt->subs[sub_num].dfd = -1;
01278 }
01279
01280 #ifdef HAVE_PRI
01281 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01282 {
01283 dahdi_close(pri->fds[fd_num]);
01284 pri->fds[fd_num] = -1;
01285 }
01286 #endif
01287
01288 static int dahdi_setlinear(int dfd, int linear)
01289 {
01290 int res;
01291 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01292 if (res)
01293 return res;
01294 return 0;
01295 }
01296
01297
01298 static int alloc_sub(struct dahdi_pvt *p, int x)
01299 {
01300 struct dahdi_bufferinfo bi;
01301 int res;
01302 if (p->subs[x].dfd < 0) {
01303 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01304 if (p->subs[x].dfd > -1) {
01305 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01306 if (!res) {
01307 bi.txbufpolicy = p->buf_policy;
01308 bi.rxbufpolicy = p->buf_policy;
01309 bi.numbufs = p->buf_no;
01310 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01311 if (res < 0) {
01312 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01313 }
01314 } else
01315 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01316 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01317 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01318 dahdi_close_sub(p, x);
01319 return -1;
01320 }
01321 if (option_debug)
01322 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01323 return 0;
01324 } else
01325 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01326 return -1;
01327 }
01328 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01329 return -1;
01330 }
01331
01332 static int unalloc_sub(struct dahdi_pvt *p, int x)
01333 {
01334 if (!x) {
01335 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01336 return -1;
01337 }
01338 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01339 dahdi_close_sub(p, x);
01340 p->subs[x].linear = 0;
01341 p->subs[x].chan = 0;
01342 p->subs[x].owner = NULL;
01343 p->subs[x].inthreeway = 0;
01344 p->polarity = POLARITY_IDLE;
01345 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01346 return 0;
01347 }
01348
01349 static int digit_to_dtmfindex(char digit)
01350 {
01351 if (isdigit(digit))
01352 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01353 else if (digit >= 'A' && digit <= 'D')
01354 return DAHDI_TONE_DTMF_A + (digit - 'A');
01355 else if (digit >= 'a' && digit <= 'd')
01356 return DAHDI_TONE_DTMF_A + (digit - 'a');
01357 else if (digit == '*')
01358 return DAHDI_TONE_DTMF_s;
01359 else if (digit == '#')
01360 return DAHDI_TONE_DTMF_p;
01361 else
01362 return -1;
01363 }
01364
01365 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01366 {
01367 struct dahdi_pvt *pvt;
01368 int index;
01369 int dtmf = -1;
01370
01371 pvt = chan->tech_pvt;
01372
01373 ast_mutex_lock(&pvt->lock);
01374
01375 index = dahdi_get_index(chan, pvt, 0);
01376
01377 if ((index != SUB_REAL) || !pvt->owner)
01378 goto out;
01379
01380 #ifdef HAVE_PRI
01381 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01382 if (pvt->setup_ack) {
01383 if (!pri_grab(pvt, pvt->pri)) {
01384 pri_information(pvt->pri->pri, pvt->call, digit);
01385 pri_rel(pvt->pri);
01386 } else
01387 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01388 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01389 int res;
01390 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01391 res = strlen(pvt->dialdest);
01392 pvt->dialdest[res++] = digit;
01393 pvt->dialdest[res] = '\0';
01394 }
01395 goto out;
01396 }
01397 #endif
01398 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01399 goto out;
01400
01401 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01402 int res;
01403 struct dahdi_dialoperation zo = {
01404 .op = DAHDI_DIAL_OP_APPEND,
01405 .dialstr[0] = 'T',
01406 .dialstr[1] = digit,
01407 .dialstr[2] = 0,
01408 };
01409 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01410 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01411 else
01412 pvt->dialing = 1;
01413 } else {
01414 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01415 pvt->dialing = 1;
01416 pvt->begindigit = digit;
01417 }
01418
01419 out:
01420 ast_mutex_unlock(&pvt->lock);
01421
01422 return 0;
01423 }
01424
01425 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01426 {
01427 struct dahdi_pvt *pvt;
01428 int res = 0;
01429 int index;
01430 int x;
01431
01432 pvt = chan->tech_pvt;
01433
01434 ast_mutex_lock(&pvt->lock);
01435
01436 index = dahdi_get_index(chan, pvt, 0);
01437
01438 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01439 goto out;
01440
01441 #ifdef HAVE_PRI
01442
01443 if (pvt->sig == SIG_PRI && !pvt->begindigit)
01444 goto out;
01445 #endif
01446
01447 if (pvt->begindigit) {
01448 x = -1;
01449 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01450 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01451 pvt->dialing = 0;
01452 pvt->begindigit = 0;
01453 }
01454
01455 out:
01456 ast_mutex_unlock(&pvt->lock);
01457
01458 return res;
01459 }
01460
01461 static char *events[] = {
01462 "No event",
01463 "On hook",
01464 "Ring/Answered",
01465 "Wink/Flash",
01466 "Alarm",
01467 "No more alarm",
01468 "HDLC Abort",
01469 "HDLC Overrun",
01470 "HDLC Bad FCS",
01471 "Dial Complete",
01472 "Ringer On",
01473 "Ringer Off",
01474 "Hook Transition Complete",
01475 "Bits Changed",
01476 "Pulse Start",
01477 "Timer Expired",
01478 "Timer Ping",
01479 "Polarity Reversal",
01480 "Ring Begin",
01481 };
01482
01483 static struct {
01484 int alarm;
01485 char *name;
01486 } alarms[] = {
01487 { DAHDI_ALARM_RED, "Red Alarm" },
01488 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01489 { DAHDI_ALARM_BLUE, "Blue Alarm" },
01490 { DAHDI_ALARM_RECOVER, "Recovering" },
01491 { DAHDI_ALARM_LOOPBACK, "Loopback" },
01492 { DAHDI_ALARM_NOTOPEN, "Not Open" },
01493 { DAHDI_ALARM_NONE, "None" },
01494 };
01495
01496 static char *alarm2str(int alarm)
01497 {
01498 int x;
01499 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01500 if (alarms[x].alarm & alarm)
01501 return alarms[x].name;
01502 }
01503 return alarm ? "Unknown Alarm" : "No Alarm";
01504 }
01505
01506 static char *event2str(int event)
01507 {
01508 static char buf[256];
01509 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01510 return events[event];
01511 sprintf(buf, "Event %d", event);
01512 return buf;
01513 }
01514
01515 #ifdef HAVE_PRI
01516 static char *dialplan2str(int dialplan)
01517 {
01518 if (dialplan == -1) {
01519 return("Dynamically set dialplan in ISDN");
01520 }
01521 return (pri_plan2str(dialplan));
01522 }
01523 #endif
01524
01525 static char *dahdi_sig2str(int sig)
01526 {
01527 static char buf[256];
01528 switch (sig) {
01529 case SIG_EM:
01530 return "E & M Immediate";
01531 case SIG_EMWINK:
01532 return "E & M Wink";
01533 case SIG_EM_E1:
01534 return "E & M E1";
01535 case SIG_FEATD:
01536 return "Feature Group D (DTMF)";
01537 case SIG_FEATDMF:
01538 return "Feature Group D (MF)";
01539 case SIG_FEATDMF_TA:
01540 return "Feature Groud D (MF) Tandem Access";
01541 case SIG_FEATB:
01542 return "Feature Group B (MF)";
01543 case SIG_E911:
01544 return "E911 (MF)";
01545 case SIG_FGC_CAMA:
01546 return "FGC/CAMA (Dialpulse)";
01547 case SIG_FGC_CAMAMF:
01548 return "FGC/CAMA (MF)";
01549 case SIG_FXSLS:
01550 return "FXS Loopstart";
01551 case SIG_FXSGS:
01552 return "FXS Groundstart";
01553 case SIG_FXSKS:
01554 return "FXS Kewlstart";
01555 case SIG_FXOLS:
01556 return "FXO Loopstart";
01557 case SIG_FXOGS:
01558 return "FXO Groundstart";
01559 case SIG_FXOKS:
01560 return "FXO Kewlstart";
01561 case SIG_PRI:
01562 return "ISDN PRI";
01563 case SIG_SF:
01564 return "SF (Tone) Immediate";
01565 case SIG_SFWINK:
01566 return "SF (Tone) Wink";
01567 case SIG_SF_FEATD:
01568 return "SF (Tone) with Feature Group D (DTMF)";
01569 case SIG_SF_FEATDMF:
01570 return "SF (Tone) with Feature Group D (MF)";
01571 case SIG_SF_FEATB:
01572 return "SF (Tone) with Feature Group B (MF)";
01573 case SIG_GR303FXOKS:
01574 return "GR-303 with FXOKS";
01575 case SIG_GR303FXSKS:
01576 return "GR-303 with FXSKS";
01577 case 0:
01578 return "Pseudo";
01579 default:
01580 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01581 return buf;
01582 }
01583 }
01584
01585 #define sig2str dahdi_sig2str
01586
01587 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
01588 {
01589
01590
01591 struct dahdi_confinfo zi;
01592
01593 memset(&zi, 0, sizeof(zi));
01594 zi.chan = 0;
01595
01596 if (slavechannel > 0) {
01597
01598 zi.confmode = DAHDI_CONF_DIGITALMON;
01599 zi.confno = slavechannel;
01600 } else {
01601 if (!index) {
01602
01603 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01604 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01605 } else
01606 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01607 zi.confno = p->confno;
01608 }
01609 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01610 return 0;
01611 if (c->dfd < 0)
01612 return 0;
01613 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01614 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01615 return -1;
01616 }
01617 if (slavechannel < 1) {
01618 p->confno = zi.confno;
01619 }
01620 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01621 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01622 return 0;
01623 }
01624
01625 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01626 {
01627
01628 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01629 return 1;
01630
01631 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01632 return 1;
01633 return 0;
01634 }
01635
01636 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
01637 {
01638 struct dahdi_confinfo zi;
01639 if (
01640 (c->dfd < 0) ||
01641
01642 !isourconf(p, c)
01643
01644 ) return 0;
01645 memset(&zi, 0, sizeof(zi));
01646 zi.chan = 0;
01647 zi.confno = 0;
01648 zi.confmode = 0;
01649 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01650 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01651 return -1;
01652 }
01653 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01654 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01655 return 0;
01656 }
01657
01658 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01659 {
01660 int x;
01661 int useslavenative;
01662 struct dahdi_pvt *slave = NULL;
01663
01664 useslavenative = 1;
01665
01666 for (x = 0; x < 3; x++) {
01667
01668
01669 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01670 useslavenative = 0;
01671 }
01672
01673
01674 if (useslavenative) {
01675 for (x = 0; x < MAX_SLAVES; x++) {
01676 if (p->slaves[x]) {
01677 if (slave) {
01678
01679
01680 slave = NULL;
01681 useslavenative = 0;
01682 break;
01683 } else {
01684
01685 slave = p->slaves[x];
01686 }
01687 }
01688 }
01689 }
01690
01691 if (!slave)
01692 useslavenative = 0;
01693 else if (slave->law != p->law) {
01694 useslavenative = 0;
01695 slave = NULL;
01696 }
01697 if (out)
01698 *out = slave;
01699 return useslavenative;
01700 }
01701
01702 static int reset_conf(struct dahdi_pvt *p)
01703 {
01704 struct dahdi_confinfo zi;
01705 memset(&zi, 0, sizeof(zi));
01706 p->confno = -1;
01707 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01708 if (p->subs[SUB_REAL].dfd > -1) {
01709 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01710 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01711 }
01712 return 0;
01713 }
01714
01715 static int update_conf(struct dahdi_pvt *p)
01716 {
01717 int needconf = 0;
01718 int x;
01719 int useslavenative;
01720 struct dahdi_pvt *slave = NULL;
01721
01722 useslavenative = isslavenative(p, &slave);
01723
01724 for (x = 0; x < 3; x++) {
01725
01726 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01727 conf_add(p, &p->subs[x], x, 0);
01728 needconf++;
01729 } else {
01730 conf_del(p, &p->subs[x], x);
01731 }
01732 }
01733
01734
01735 for (x = 0; x < MAX_SLAVES; x++) {
01736 if (p->slaves[x]) {
01737 if (useslavenative)
01738 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01739 else {
01740 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01741 needconf++;
01742 }
01743 }
01744 }
01745
01746 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01747 if (useslavenative)
01748 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01749 else {
01750 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01751 needconf++;
01752 }
01753 }
01754
01755 if (p->master) {
01756 if (isslavenative(p->master, NULL)) {
01757 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01758 } else {
01759 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01760 }
01761 }
01762 if (!needconf) {
01763
01764
01765 p->confno = -1;
01766 }
01767 if (option_debug)
01768 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01769 return 0;
01770 }
01771
01772 static void dahdi_enable_ec(struct dahdi_pvt *p)
01773 {
01774 int x;
01775 int res;
01776 if (!p)
01777 return;
01778 if (p->echocanon) {
01779 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01780 return;
01781 }
01782 if (p->digital) {
01783 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01784 return;
01785 }
01786 if (p->echocancel) {
01787 if (p->sig == SIG_PRI) {
01788 x = 1;
01789 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
01790 if (res)
01791 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01792 }
01793 x = p->echocancel;
01794 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01795 if (res)
01796 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01797 else {
01798 p->echocanon = 1;
01799 if (option_debug)
01800 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01801 }
01802 } else if (option_debug)
01803 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01804 }
01805
01806 static void dahdi_train_ec(struct dahdi_pvt *p)
01807 {
01808 int x;
01809 int res;
01810 if (p && p->echocancel && p->echotraining) {
01811 x = p->echotraining;
01812 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
01813 if (res)
01814 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
01815 else {
01816 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01817 }
01818 } else
01819 ast_log(LOG_DEBUG, "No echo training requested\n");
01820 }
01821
01822 static void dahdi_disable_ec(struct dahdi_pvt *p)
01823 {
01824 int x;
01825 int res;
01826 if (p->echocancel) {
01827 x = 0;
01828 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01829 if (res)
01830 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
01831 else if (option_debug)
01832 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01833 }
01834 p->echocanon = 0;
01835 }
01836
01837 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
01838 {
01839 int j;
01840 int k;
01841 float linear_gain = pow(10.0, gain / 20.0);
01842
01843 switch (law) {
01844 case DAHDI_LAW_ALAW:
01845 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01846 if (gain) {
01847 k = (int) (((float) AST_ALAW(j)) * linear_gain);
01848 if (k > 32767) k = 32767;
01849 if (k < -32767) k = -32767;
01850 g->txgain[j] = AST_LIN2A(k);
01851 } else {
01852 g->txgain[j] = j;
01853 }
01854 }
01855 break;
01856 case DAHDI_LAW_MULAW:
01857 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01858 if (gain) {
01859 k = (int) (((float) AST_MULAW(j)) * linear_gain);
01860 if (k > 32767) k = 32767;
01861 if (k < -32767) k = -32767;
01862 g->txgain[j] = AST_LIN2MU(k);
01863 } else {
01864 g->txgain[j] = j;
01865 }
01866 }
01867 break;
01868 }
01869 }
01870
01871 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
01872 {
01873 int j;
01874 int k;
01875 float linear_gain = pow(10.0, gain / 20.0);
01876
01877 switch (law) {
01878 case DAHDI_LAW_ALAW:
01879 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01880 if (gain) {
01881 k = (int) (((float) AST_ALAW(j)) * linear_gain);
01882 if (k > 32767) k = 32767;
01883 if (k < -32767) k = -32767;
01884 g->rxgain[j] = AST_LIN2A(k);
01885 } else {
01886 g->rxgain[j] = j;
01887 }
01888 }
01889 break;
01890 case DAHDI_LAW_MULAW:
01891 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01892 if (gain) {
01893 k = (int) (((float) AST_MULAW(j)) * linear_gain);
01894 if (k > 32767) k = 32767;
01895 if (k < -32767) k = -32767;
01896 g->rxgain[j] = AST_LIN2MU(k);
01897 } else {
01898 g->rxgain[j] = j;
01899 }
01900 }
01901 break;
01902 }
01903 }
01904
01905 static int set_actual_txgain(int fd, int chan, float gain, int law)
01906 {
01907 struct dahdi_gains g;
01908 int res;
01909
01910 memset(&g, 0, sizeof(g));
01911 g.chan = chan;
01912 res = ioctl(fd, DAHDI_GETGAINS, &g);
01913 if (res) {
01914 if (option_debug)
01915 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01916 return res;
01917 }
01918
01919 fill_txgain(&g, gain, law);
01920
01921 return ioctl(fd, DAHDI_SETGAINS, &g);
01922 }
01923
01924 static int set_actual_rxgain(int fd, int chan, float gain, int law)
01925 {
01926 struct dahdi_gains g;
01927 int res;
01928
01929 memset(&g, 0, sizeof(g));
01930 g.chan = chan;
01931 res = ioctl(fd, DAHDI_GETGAINS, &g);
01932 if (res) {
01933 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01934 return res;
01935 }
01936
01937 fill_rxgain(&g, gain, law);
01938
01939 return ioctl(fd, DAHDI_SETGAINS, &g);
01940 }
01941
01942 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
01943 {
01944 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01945 }
01946
01947 static int bump_gains(struct dahdi_pvt *p)
01948 {
01949 int res;
01950
01951
01952 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01953 if (res) {
01954 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01955 return -1;
01956 }
01957
01958 return 0;
01959 }
01960
01961 static int restore_gains(struct dahdi_pvt *p)
01962 {
01963 int res;
01964
01965 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01966 if (res) {
01967 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01968 return -1;
01969 }
01970
01971 return 0;
01972 }
01973
01974 static inline int dahdi_set_hook(int fd, int hs)
01975 {
01976 int x, res;
01977
01978 x = hs;
01979 res = ioctl(fd, DAHDI_HOOK, &x);
01980
01981 if (res < 0) {
01982 if (errno == EINPROGRESS)
01983 return 0;
01984 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
01985
01986 }
01987
01988 return res;
01989 }
01990
01991 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
01992 {
01993 int x, y, res;
01994 x = muted;
01995 if (p->sig == SIG_PRI) {
01996 y = 1;
01997 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
01998 if (res)
01999 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02000 }
02001 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02002 if (res < 0)
02003 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02004 return res;
02005 }
02006
02007 static int save_conference(struct dahdi_pvt *p)
02008 {
02009 struct dahdi_confinfo c;
02010 int res;
02011 if (p->saveconf.confmode) {
02012 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02013 return -1;
02014 }
02015 p->saveconf.chan = 0;
02016 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02017 if (res) {
02018 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02019 p->saveconf.confmode = 0;
02020 return -1;
02021 }
02022 c.chan = 0;
02023 c.confno = 0;
02024 c.confmode = DAHDI_CONF_NORMAL;
02025 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02026 if (res) {
02027 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02028 return -1;
02029 }
02030 if (option_debug)
02031 ast_log(LOG_DEBUG, "Disabled conferencing\n");
02032 return 0;
02033 }
02034
02035 static int restore_conference(struct dahdi_pvt *p)
02036 {
02037 int res;
02038 if (p->saveconf.confmode) {
02039 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02040 p->saveconf.confmode = 0;
02041 if (res) {
02042 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02043 return -1;
02044 }
02045 }
02046 if (option_debug)
02047 ast_log(LOG_DEBUG, "Restored conferencing\n");
02048 return 0;
02049 }
02050
02051 static int send_callerid(struct dahdi_pvt *p);
02052
02053 static int send_cwcidspill(struct dahdi_pvt *p)
02054 {
02055 p->callwaitcas = 0;
02056 p->cidcwexpire = 0;
02057 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02058 return -1;
02059 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02060
02061 p->cidlen += READ_SIZE * 4;
02062 p->cidpos = 0;
02063 send_callerid(p);
02064 if (option_verbose > 2)
02065 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02066 return 0;
02067 }
02068
02069 static int has_voicemail(struct dahdi_pvt *p)
02070 {
02071
02072 return ast_app_has_voicemail(p->mailbox, NULL);
02073 }
02074
02075 static int send_callerid(struct dahdi_pvt *p)
02076 {
02077
02078 int res;
02079
02080 if (p->subs[SUB_REAL].linear) {
02081 p->subs[SUB_REAL].linear = 0;
02082 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02083 }
02084 while (p->cidpos < p->cidlen) {
02085 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02086 if (res < 0) {
02087 if (errno == EAGAIN)
02088 return 0;
02089 else {
02090 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02091 return -1;
02092 }
02093 }
02094 if (!res)
02095 return 0;
02096 p->cidpos += res;
02097 }
02098 free(p->cidspill);
02099 p->cidspill = NULL;
02100 if (p->callwaitcas) {
02101
02102 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02103 } else
02104 restore_conference(p);
02105 return 0;
02106 }
02107
02108 static int dahdi_callwait(struct ast_channel *ast)
02109 {
02110 struct dahdi_pvt *p = ast->tech_pvt;
02111 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02112 if (p->cidspill) {
02113 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02114 free(p->cidspill);
02115 }
02116 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02117 return -1;
02118 save_conference(p);
02119
02120 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02121 if (!p->callwaitrings && p->callwaitingcallerid) {
02122 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02123 p->callwaitcas = 1;
02124 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02125 } else {
02126 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02127 p->callwaitcas = 0;
02128 p->cidlen = 2400 + READ_SIZE * 4;
02129 }
02130 p->cidpos = 0;
02131 send_callerid(p);
02132
02133 return 0;
02134 }
02135
02136 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02137 {
02138 struct dahdi_pvt *p = ast->tech_pvt;
02139 int x, res, index,mysig;
02140 char *c, *n, *l;
02141 #ifdef HAVE_PRI
02142 char *s = NULL;
02143 #endif
02144 char dest[256];
02145 ast_mutex_lock(&p->lock);
02146 ast_copy_string(dest, rdest, sizeof(dest));
02147 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02148 if ((ast->_state == AST_STATE_BUSY)) {
02149 p->subs[SUB_REAL].needbusy = 1;
02150 ast_mutex_unlock(&p->lock);
02151 return 0;
02152 }
02153 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02154 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02155 ast_mutex_unlock(&p->lock);
02156 return -1;
02157 }
02158 p->dialednone = 0;
02159 if ((p->radio || (p->oprmode < 0)))
02160 {
02161
02162 ast_setstate(ast, AST_STATE_UP);
02163 ast_mutex_unlock(&p->lock);
02164 return 0;
02165 }
02166 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02167 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02168 if (res)
02169 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02170 p->outgoing = 1;
02171
02172 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02173
02174 mysig = p->sig;
02175 if (p->outsigmod > -1)
02176 mysig = p->outsigmod;
02177
02178 switch (mysig) {
02179 case SIG_FXOLS:
02180 case SIG_FXOGS:
02181 case SIG_FXOKS:
02182 if (p->owner == ast) {
02183
02184
02185
02186 p->dialing = 1;
02187 if (p->use_callerid) {
02188
02189 if (p->cidspill) {
02190 ast_log(LOG_WARNING, "cidspill already exists??\n");
02191 free(p->cidspill);
02192 }
02193 p->callwaitcas = 0;
02194 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02195 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02196 p->cidpos = 0;
02197 send_callerid(p);
02198 }
02199 }
02200
02201 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02202 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02203 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02204 p->cidrings = cidrings[p->distinctivering - 1];
02205 } else {
02206 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02207 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02208 p->cidrings = p->sendcalleridafter;
02209 }
02210
02211
02212 c = strchr(dest, '/');
02213 if (c)
02214 c++;
02215 if (c && (strlen(c) < p->stripmsd)) {
02216 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02217 c = NULL;
02218 }
02219 if (c) {
02220 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02221 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02222 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02223 } else {
02224 p->dop.dialstr[0] = '\0';
02225 }
02226 x = DAHDI_RING;
02227 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02228 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02229 ast_mutex_unlock(&p->lock);
02230 return -1;
02231 }
02232 p->dialing = 1;
02233 } else {
02234
02235 p->callwaitrings = 0;
02236 if (ast->cid.cid_num)
02237 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02238 else
02239 p->callwait_num[0] = '\0';
02240 if (ast->cid.cid_name)
02241 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02242 else
02243 p->callwait_name[0] = '\0';
02244
02245 if (dahdi_callwait(ast)) {
02246 ast_mutex_unlock(&p->lock);
02247 return -1;
02248 }
02249
02250 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02251 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02252
02253 }
02254 n = ast->cid.cid_name;
02255 l = ast->cid.cid_num;
02256 if (l)
02257 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02258 else
02259 p->lastcid_num[0] = '\0';
02260 if (n)
02261 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02262 else
02263 p->lastcid_name[0] = '\0';
02264 ast_setstate(ast, AST_STATE_RINGING);
02265 index = dahdi_get_index(ast, p, 0);
02266 if (index > -1) {
02267 p->subs[index].needringing = 1;
02268 }
02269 break;
02270 case SIG_FXSLS:
02271 case SIG_FXSGS:
02272 case SIG_FXSKS:
02273 case SIG_EMWINK:
02274 case SIG_EM:
02275 case SIG_EM_E1:
02276 case SIG_FEATD:
02277 case SIG_FEATDMF:
02278 case SIG_E911:
02279 case SIG_FGC_CAMA:
02280 case SIG_FGC_CAMAMF:
02281 case SIG_FEATB:
02282 case SIG_SFWINK:
02283 case SIG_SF:
02284 case SIG_SF_FEATD:
02285 case SIG_SF_FEATDMF:
02286 case SIG_FEATDMF_TA:
02287 case SIG_SF_FEATB:
02288 c = strchr(dest, '/');
02289 if (c)
02290 c++;
02291 else
02292 c = "";
02293 if (strlen(c) < p->stripmsd) {
02294 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02295 ast_mutex_unlock(&p->lock);
02296 return -1;
02297 }
02298 #ifdef HAVE_PRI
02299
02300 if (!p->pri) {
02301 #endif
02302 x = DAHDI_START;
02303 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02304 if (res < 0) {
02305 if (errno != EINPROGRESS) {
02306 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02307 ast_mutex_unlock(&p->lock);
02308 return -1;
02309 }
02310 }
02311 #ifdef HAVE_PRI
02312 }
02313 #endif
02314 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02315 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02316
02317 c += p->stripmsd;
02318
02319 switch (mysig) {
02320 case SIG_FEATD:
02321 l = ast->cid.cid_num;
02322 if (l)
02323 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02324 else
02325 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02326 break;
02327 case SIG_FEATDMF:
02328 l = ast->cid.cid_num;
02329 if (l)
02330 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02331 else
02332 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02333 break;
02334 case SIG_FEATDMF_TA:
02335 {
02336 const char *cic, *ozz;
02337
02338
02339 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02340 if (!ozz)
02341 ozz = defaultozz;
02342 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02343 if (!cic)
02344 cic = defaultcic;
02345 if (!ozz || !cic) {
02346 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02347 ast_mutex_unlock(&p->lock);
02348 return -1;
02349 }
02350 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02351 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02352 p->whichwink = 0;
02353 }
02354 break;
02355 case SIG_E911:
02356 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02357 break;
02358 case SIG_FGC_CAMA:
02359 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02360 break;
02361 case SIG_FGC_CAMAMF:
02362 case SIG_FEATB:
02363 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02364 break;
02365 default:
02366 if (p->pulse)
02367 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02368 else
02369 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02370 break;
02371 }
02372
02373 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02374 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02375 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02376 p->echorest[sizeof(p->echorest) - 1] = '\0';
02377 p->echobreak = 1;
02378 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02379 } else
02380 p->echobreak = 0;
02381 if (!res) {
02382 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02383 int saveerr = errno;
02384
02385 x = DAHDI_ONHOOK;
02386 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02387 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02388 ast_mutex_unlock(&p->lock);
02389 return -1;
02390 }
02391 } else
02392 ast_log(LOG_DEBUG, "Deferring dialing...\n");
02393 p->dialing = 1;
02394 if (ast_strlen_zero(c))
02395 p->dialednone = 1;
02396 ast_setstate(ast, AST_STATE_DIALING);
02397 break;
02398 case 0:
02399
02400 ast_setstate(ast, AST_STATE_UP);
02401 break;
02402 case SIG_PRI:
02403
02404 p->dialdest[0] = '\0';
02405 break;
02406 default:
02407 ast_log(LOG_DEBUG, "not yet implemented\n");
02408 ast_mutex_unlock(&p->lock);
02409 return -1;
02410 }
02411 #ifdef HAVE_PRI
02412 if (p->pri) {
02413 struct pri_sr *sr;
02414 #ifdef SUPPORT_USERUSER
02415 const char *useruser;
02416 #endif
02417 int pridialplan;
02418 int dp_strip;
02419 int prilocaldialplan;
02420 int ldp_strip;
02421 int exclusive;
02422 const char *rr_str;
02423 int redirect_reason;
02424
02425 c = strchr(dest, '/');
02426 if (c) {
02427 c++;
02428 } else {
02429 c = "";
02430 }
02431
02432 l = NULL;
02433 n = NULL;
02434 if (!p->hidecallerid) {
02435 l = ast->cid.cid_num;
02436 if (!p->hidecalleridname) {
02437 n = ast->cid.cid_name;
02438 }
02439 }
02440
02441
02442 if (strlen(c) < p->stripmsd) {
02443 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02444 ast_mutex_unlock(&p->lock);
02445 return -1;
02446 }
02447 if (mysig != SIG_FXSKS) {
02448 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02449 s = strchr(c + p->stripmsd, 'w');
02450 if (s) {
02451 if (strlen(s) > 1)
02452 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02453 else
02454 p->dop.dialstr[0] = '\0';
02455 *s = '\0';
02456 } else {
02457 p->dop.dialstr[0] = '\0';
02458 }
02459 }
02460 if (pri_grab(p, p->pri)) {
02461 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02462 ast_mutex_unlock(&p->lock);
02463 return -1;
02464 }
02465 if (!(p->call = pri_new_call(p->pri->pri))) {
02466 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02467 pri_rel(p->pri);
02468 ast_mutex_unlock(&p->lock);
02469 return -1;
02470 }
02471 if (!(sr = pri_sr_new())) {
02472 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02473 pri_destroycall(p->pri->pri, p->call);
02474 p->call = NULL;
02475 pri_rel(p->pri);
02476 ast_mutex_unlock(&p->lock);
02477 return -1;
02478 }
02479 if (p->bearer || (mysig == SIG_FXSKS)) {
02480 if (p->bearer) {
02481 ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02482 p->bearer->call = p->call;
02483 } else
02484 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02485 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02486 }
02487 p->digital = IS_DIGITAL(ast->transfercapability);
02488
02489 if (p->priexclusive)
02490 exclusive = 1;
02491 else {
02492
02493 if (p->pri->nodetype == PRI_NETWORK)
02494 exclusive = 0;
02495 else
02496 exclusive = 1;
02497 }
02498
02499 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02500 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02501 (p->digital ? -1 :
02502 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02503 if (p->pri->facilityenable)
02504 pri_facility_enable(p->pri->pri);
02505
02506 if (option_verbose > 2)
02507 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02508 dp_strip = 0;
02509 pridialplan = p->pri->dialplan - 1;
02510 if (pridialplan == -2) {
02511 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02512 dp_strip = strlen(p->pri->internationalprefix);
02513 pridialplan = PRI_INTERNATIONAL_ISDN;
02514 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02515 dp_strip = strlen(p->pri->nationalprefix);
02516 pridialplan = PRI_NATIONAL_ISDN;
02517 } else {
02518 pridialplan = PRI_LOCAL_ISDN;
02519 }
02520 }
02521 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02522
02523 ldp_strip = 0;
02524 prilocaldialplan = p->pri->localdialplan - 1;
02525 if ((l != NULL) && (prilocaldialplan == -2)) {
02526 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02527 ldp_strip = strlen(p->pri->internationalprefix);
02528 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02529 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02530 ldp_strip = strlen(p->pri->nationalprefix);
02531 prilocaldialplan = PRI_NATIONAL_ISDN;
02532 } else {
02533 prilocaldialplan = PRI_LOCAL_ISDN;
02534 }
02535 }
02536 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02537 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02538 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02539 if (!strcasecmp(rr_str, "UNKNOWN"))
02540 redirect_reason = 0;
02541 else if (!strcasecmp(rr_str, "BUSY"))
02542 redirect_reason = 1;
02543 else if (!strcasecmp(rr_str, "NO_REPLY"))
02544 redirect_reason = 2;
02545 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02546 redirect_reason = 15;
02547 else
02548 redirect_reason = PRI_REDIR_UNCONDITIONAL;
02549 } else
02550 redirect_reason = PRI_REDIR_UNCONDITIONAL;
02551 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02552
02553 #ifdef SUPPORT_USERUSER
02554
02555 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02556
02557 if (useruser)
02558 pri_sr_set_useruser(sr, useruser);
02559 #endif
02560
02561 if (pri_setup(p->pri->pri, p->call, sr)) {
02562 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
02563 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02564 pri_rel(p->pri);
02565 ast_mutex_unlock(&p->lock);
02566 pri_sr_free(sr);
02567 return -1;
02568 }
02569 pri_sr_free(sr);
02570 ast_setstate(ast, AST_STATE_DIALING);
02571 pri_rel(p->pri);
02572 }
02573 #endif
02574 ast_mutex_unlock(&p->lock);
02575 return 0;
02576 }
02577
02578 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
02579 {
02580 struct dahdi_pvt *p = *pvt;
02581
02582 if (p->prev)
02583 p->prev->next = p->next;
02584 if (p->next)
02585 p->next->prev = p->prev;
02586 if (p->use_smdi)
02587 ast_smdi_interface_unref(p->smdi_iface);
02588 ast_mutex_destroy(&p->lock);
02589 dahdi_close_sub(p, SUB_REAL);
02590 if (p->owner)
02591 p->owner->tech_pvt = NULL;
02592 free(p);
02593 *pvt = NULL;
02594 }
02595
02596 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
02597 {
02598 int owned = 0;
02599 int i = 0;
02600
02601 if (!now) {
02602 if (cur->owner) {
02603 owned = 1;
02604 }
02605
02606 for (i = 0; i < 3; i++) {
02607 if (cur->subs[i].owner) {
02608 owned = 1;
02609 }
02610 }
02611 if (!owned) {
02612 if (prev) {
02613 prev->next = cur->next;
02614 if (prev->next)
02615 prev->next->prev = prev;
02616 else
02617 ifend = prev;
02618 } else {
02619 iflist = cur->next;
02620 if (iflist)
02621 iflist->prev = NULL;
02622 else
02623 ifend = NULL;
02624 }
02625 destroy_dahdi_pvt(&cur);
02626 }
02627 } else {
02628 if (prev) {
02629 prev->next = cur->next;
02630 if (prev->next)
02631 prev->next->prev = prev;
02632 else
02633 ifend = prev;
02634 } else {
02635 iflist = cur->next;
02636 if (iflist)
02637 iflist->prev = NULL;
02638 else
02639 ifend = NULL;
02640 }
02641 destroy_dahdi_pvt(&cur);
02642 }
02643 return 0;
02644 }
02645
02646 static void destroy_all_channels(void)
02647 {
02648 int x;
02649 struct dahdi_pvt *p, *pl;
02650
02651 while (num_restart_pending) {
02652 usleep(1);
02653 }
02654
02655 ast_mutex_lock(&iflock);
02656
02657 p = iflist;
02658 while (p) {
02659
02660 if (p->cidspill)
02661 ast_free(p->cidspill);
02662 pl = p;
02663 p = p->next;
02664 x = pl->channel;
02665
02666 if (pl)
02667 destroy_dahdi_pvt(&pl);
02668 if (option_verbose > 2)
02669 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
02670 }
02671 iflist = NULL;
02672 ifcount = 0;
02673 ast_mutex_unlock(&iflock);
02674 }
02675
02676 #ifdef HAVE_PRI
02677 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
02678 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
02679
02680 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02681 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02682
02683 static char *dahdi_send_keypad_facility_descrip =
02684 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02685 " IE over the current channel.\n";
02686 static char *zap_send_keypad_facility_descrip =
02687 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02688 " IE over the current channel.\n";
02689
02690 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
02691 {
02692
02693 struct dahdi_pvt *p;
02694 char *digits = (char *) data;
02695
02696 if (ast_strlen_zero(digits)) {
02697 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
02698 return -1;
02699 }
02700
02701 p = (struct dahdi_pvt *)chan->tech_pvt;
02702
02703 if (!p) {
02704 ast_log(LOG_DEBUG, "Unable to find technology private\n");
02705 return -1;
02706 }
02707
02708 ast_mutex_lock(&p->lock);
02709
02710 if (!p->pri || !p->call) {
02711 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
02712 ast_mutex_unlock(&p->lock);
02713 return -1;
02714 }
02715
02716 if (!pri_grab(p, p->pri)) {
02717 pri_keypad_facility(p->pri->pri, p->call, digits);
02718 pri_rel(p->pri);
02719 } else {
02720 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
02721 ast_mutex_unlock(&p->lock);
02722 return -1;
02723 }
02724
02725 ast_mutex_unlock(&p->lock);
02726
02727 return 0;
02728 }
02729
02730 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02731 {
02732 return send_keypad_facility_exec(chan, data);
02733 }
02734
02735 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02736 {
02737 ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app);
02738 return send_keypad_facility_exec(chan, data);
02739 }
02740
02741 static int pri_is_up(struct dahdi_pri *pri)
02742 {
02743 int x;
02744 for (x = 0; x < NUM_DCHANS; x++) {
02745 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
02746 return 1;
02747 }
02748 return 0;
02749 }
02750
02751 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
02752 {
02753 bearer->owner = &inuse;
02754 bearer->realcall = crv;
02755 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
02756 if (crv->subs[SUB_REAL].owner)
02757 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
02758 crv->bearer = bearer;
02759 crv->call = bearer->call;
02760 crv->pri = pri;
02761 return 0;
02762 }
02763
02764 static char *pri_order(int level)
02765 {
02766 switch (level) {
02767 case 0:
02768 return "Primary";
02769 case 1:
02770 return "Secondary";
02771 case 2:
02772 return "Tertiary";
02773 case 3:
02774 return "Quaternary";
02775 default:
02776 return "<Unknown>";
02777 }
02778 }
02779
02780
02781 static int pri_active_dchan_fd(struct dahdi_pri *pri)
02782 {
02783 int x = -1;
02784
02785 for (x = 0; x < NUM_DCHANS; x++) {
02786 if ((pri->dchans[x] == pri->pri))
02787 break;
02788 }
02789
02790 return pri->fds[x];
02791 }
02792
02793 static int pri_find_dchan(struct dahdi_pri *pri)
02794 {
02795 int oldslot = -1;
02796 struct pri *old;
02797 int newslot = -1;
02798 int x;
02799 old = pri->pri;
02800 for (x = 0; x < NUM_DCHANS; x++) {
02801 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
02802 newslot = x;
02803 if (pri->dchans[x] == old) {
02804 oldslot = x;
02805 }
02806 }
02807 if (newslot < 0) {
02808 newslot = 0;
02809 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
02810 pri->dchannels[newslot]);
02811 }
02812 if (old && (oldslot != newslot))
02813 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
02814 pri->dchannels[oldslot], pri->dchannels[newslot]);
02815 pri->pri = pri->dchans[newslot];
02816 return 0;
02817 }
02818 #endif
02819
02820 static int dahdi_hangup(struct ast_channel *ast)
02821 {
02822 int res;
02823 int index,x, law;
02824
02825 struct dahdi_pvt *p = ast->tech_pvt;
02826 struct dahdi_pvt *tmp = NULL;
02827 struct dahdi_pvt *prev = NULL;
02828 struct dahdi_params par;
02829
02830 if (option_debug)
02831 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
02832 if (!ast->tech_pvt) {
02833 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02834 return 0;
02835 }
02836
02837 ast_mutex_lock(&p->lock);
02838
02839 index = dahdi_get_index(ast, p, 1);
02840
02841 if (p->sig == SIG_PRI) {
02842 x = 1;
02843 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02844 }
02845
02846 x = 0;
02847 dahdi_confmute(p, 0);
02848 restore_gains(p);
02849 if (p->origcid_num) {
02850 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02851 free(p->origcid_num);
02852 p->origcid_num = NULL;
02853 }
02854 if (p->origcid_name) {
02855 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02856 free(p->origcid_name);
02857 p->origcid_name = NULL;
02858 }
02859 if (p->dsp)
02860 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02861 p->exten[0] = '\0';
02862
02863 if (option_debug)
02864 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02865 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
02866 p->ignoredtmf = 0;
02867
02868 if (index > -1) {
02869
02870 p->subs[index].owner = NULL;
02871 p->subs[index].needanswer = 0;
02872 p->subs[index].needflash = 0;
02873 p->subs[index].needringing = 0;
02874 p->subs[index].needbusy = 0;
02875 p->subs[index].needcongestion = 0;
02876 p->subs[index].linear = 0;
02877 p->subs[index].needcallerid = 0;
02878 p->polarity = POLARITY_IDLE;
02879 dahdi_setlinear(p->subs[index].dfd, 0);
02880 if (index == SUB_REAL) {
02881 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
02882 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02883 if (p->subs[SUB_CALLWAIT].inthreeway) {
02884
02885 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02886
02887 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02888 unalloc_sub(p, SUB_CALLWAIT);
02889 p->owner = NULL;
02890 } else {
02891
02892 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
02893 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02894 unalloc_sub(p, SUB_THREEWAY);
02895 if (p->subs[SUB_REAL].inthreeway) {
02896
02897
02898 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02899 p->owner = p->subs[SUB_REAL].owner;
02900 } else {
02901
02902 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02903 p->owner = NULL;
02904 }
02905 p->subs[SUB_REAL].inthreeway = 0;
02906 }
02907 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
02908
02909 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02910 unalloc_sub(p, SUB_CALLWAIT);
02911 p->owner = p->subs[SUB_REAL].owner;
02912 if (p->owner->_state != AST_STATE_UP)
02913 p->subs[SUB_REAL].needanswer = 1;
02914 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02915 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02916 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
02917 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02918 unalloc_sub(p, SUB_THREEWAY);
02919 if (p->subs[SUB_REAL].inthreeway) {
02920
02921
02922 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02923 p->owner = p->subs[SUB_REAL].owner;
02924 } else {
02925
02926 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02927 p->owner = NULL;
02928 }
02929 p->subs[SUB_REAL].inthreeway = 0;
02930 }
02931 } else if (index == SUB_CALLWAIT) {
02932
02933 if (p->subs[SUB_CALLWAIT].inthreeway) {
02934
02935
02936 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02937 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
02938 S_OR(p->mohsuggest, NULL),
02939 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02940 }
02941 p->subs[SUB_THREEWAY].inthreeway = 0;
02942
02943 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02944 unalloc_sub(p, SUB_THREEWAY);
02945 } else
02946 unalloc_sub(p, SUB_CALLWAIT);
02947 } else if (index == SUB_THREEWAY) {
02948 if (p->subs[SUB_CALLWAIT].inthreeway) {
02949
02950
02951 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02952 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
02953 S_OR(p->mohsuggest, NULL),
02954 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02955 }
02956 p->subs[SUB_CALLWAIT].inthreeway = 0;
02957 }
02958 p->subs[SUB_REAL].inthreeway = 0;
02959
02960
02961 unalloc_sub(p, SUB_THREEWAY);
02962 } else {
02963
02964 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02965 }
02966 }
02967
02968 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02969 p->owner = NULL;
02970 p->ringt = 0;
02971 p->distinctivering = 0;
02972 p->confirmanswer = 0;
02973 p->cidrings = 1;
02974 p->outgoing = 0;
02975 p->digital = 0;
02976 p->faxhandled = 0;
02977 p->pulsedial = 0;
02978 p->onhooktime = time(NULL);
02979 #ifdef HAVE_PRI
02980 p->proceeding = 0;
02981 p->progress = 0;
02982 p->alerting = 0;
02983 p->setup_ack = 0;
02984 #endif
02985 if (p->dsp) {
02986 ast_dsp_free(p->dsp);
02987 p->dsp = NULL;
02988 }
02989
02990 law = DAHDI_LAW_DEFAULT;
02991 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02992 if (res < 0)
02993 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02994
02995 #ifdef HAVE_PRI
02996 if (p->pri) {
02997 #ifdef SUPPORT_USERUSER
02998 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02999 #endif
03000
03001
03002 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03003 if (!pri_grab(p, p->pri)) {
03004 if (p->alreadyhungup) {
03005 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
03006
03007 #ifdef SUPPORT_USERUSER
03008 pri_call_set_useruser(p->call, useruser);
03009 #endif
03010
03011 pri_hangup(p->pri->pri, p->call, -1);
03012 p->call = NULL;
03013 if (p->bearer)
03014 p->bearer->call = NULL;
03015 } else {
03016 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03017 int icause = ast->hangupcause ? ast->hangupcause : -1;
03018 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03019
03020 #ifdef SUPPORT_USERUSER
03021 pri_call_set_useruser(p->call, useruser);
03022 #endif
03023
03024 p->alreadyhungup = 1;
03025 if (p->bearer)
03026 p->bearer->alreadyhungup = 1;
03027 if (cause) {
03028 if (atoi(cause))
03029 icause = atoi(cause);
03030 }
03031 pri_hangup(p->pri->pri, p->call, icause);
03032 }
03033 if (res < 0)
03034 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03035 pri_rel(p->pri);
03036 } else {
03037 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03038 res = -1;
03039 }
03040 } else {
03041 if (p->bearer)
03042 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03043 p->call = NULL;
03044 res = 0;
03045 }
03046 }
03047 #endif
03048 if (p->sig && (p->sig != SIG_PRI))
03049 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03050 if (res < 0) {
03051 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03052 }
03053 switch (p->sig) {
03054 case SIG_FXOGS:
03055 case SIG_FXOLS:
03056 case SIG_FXOKS:
03057 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03058 if (!res) {
03059 #if 0
03060 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03061 #endif
03062
03063 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03064 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03065 else
03066 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03067 }
03068 break;
03069 case SIG_FXSGS:
03070 case SIG_FXSLS:
03071 case SIG_FXSKS:
03072
03073
03074 if (ast->_state != AST_STATE_RESERVED) {
03075 time(&p->guardtime);
03076 p->guardtime += 2;
03077 }
03078 break;
03079 default:
03080 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03081 }
03082 if (p->cidspill)
03083 free(p->cidspill);
03084 if (p->sig)
03085 dahdi_disable_ec(p);
03086 x = 0;
03087 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03088 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03089 p->didtdd = 0;
03090 p->cidspill = NULL;
03091 p->callwaitcas = 0;
03092 p->callwaiting = p->permcallwaiting;
03093 p->hidecallerid = p->permhidecallerid;
03094 p->dialing = 0;
03095 p->rdnis[0] = '\0';
03096 update_conf(p);
03097 reset_conf(p);
03098
03099 if (p->sig == SIG_PRI) {
03100 x = 0;
03101 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03102 }
03103 #ifdef HAVE_PRI
03104 if (p->bearer) {
03105 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03106
03107
03108 update_conf(p->bearer);
03109 reset_conf(p->bearer);
03110 p->bearer->owner = NULL;
03111 p->bearer->realcall = NULL;
03112 p->bearer = NULL;
03113 p->subs[SUB_REAL].dfd = -1;
03114 p->pri = NULL;
03115 }
03116 #endif
03117 if (num_restart_pending == 0)
03118 restart_monitor();
03119 }
03120
03121 p->callwaitingrepeat = 0;
03122 p->cidcwexpire = 0;
03123 p->oprmode = 0;
03124 ast->tech_pvt = NULL;
03125 ast_mutex_unlock(&p->lock);
03126 ast_module_unref(ast_module_info->self);
03127 if (option_verbose > 2)
03128 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03129
03130 ast_mutex_lock(&iflock);
03131
03132 if (p->restartpending) {
03133 num_restart_pending--;
03134 }
03135
03136 tmp = iflist;
03137 prev = NULL;
03138 if (p->destroy) {
03139 while (tmp) {
03140 if (tmp == p) {
03141 destroy_channel(prev, tmp, 0);
03142 break;
03143 } else {
03144 prev = tmp;
03145 tmp = tmp->next;
03146 }
03147 }
03148 }
03149 ast_mutex_unlock(&iflock);
03150 return 0;
03151 }
03152
03153 static int dahdi_answer(struct ast_channel *ast)
03154 {
03155 struct dahdi_pvt *p = ast->tech_pvt;
03156 int res = 0;
03157 int index;
03158 int oldstate = ast->_state;
03159 ast_setstate(ast, AST_STATE_UP);
03160 ast_mutex_lock(&p->lock);
03161 index = dahdi_get_index(ast, p, 0);
03162 if (index < 0)
03163 index = SUB_REAL;
03164
03165 if ((p->radio || (p->oprmode < 0))) {
03166 ast_mutex_unlock(&p->lock);
03167 return 0;
03168 }
03169 switch (p->sig) {
03170 case SIG_FXSLS:
03171 case SIG_FXSGS:
03172 case SIG_FXSKS:
03173 p->ringt = 0;
03174
03175 case SIG_EM:
03176 case SIG_EM_E1:
03177 case SIG_EMWINK:
03178 case SIG_FEATD:
03179 case SIG_FEATDMF:
03180 case SIG_FEATDMF_TA:
03181 case SIG_E911:
03182 case SIG_FGC_CAMA:
03183 case SIG_FGC_CAMAMF:
03184 case SIG_FEATB:
03185 case SIG_SF:
03186 case SIG_SFWINK:
03187 case SIG_SF_FEATD:
03188 case SIG_SF_FEATDMF:
03189 case SIG_SF_FEATB:
03190 case SIG_FXOLS:
03191 case SIG_FXOGS:
03192 case SIG_FXOKS:
03193
03194 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03195 if (p->hanguponpolarityswitch) {
03196 gettimeofday(&p->polaritydelaytv, NULL);
03197 }
03198 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03199 tone_zone_play_tone(p->subs[index].dfd, -1);
03200 p->dialing = 0;
03201 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03202 if (oldstate == AST_STATE_RINGING) {
03203 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03204 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03205 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03206 p->owner = p->subs[SUB_REAL].owner;
03207 }
03208 }
03209 if (p->sig & __DAHDI_SIG_FXS) {
03210 dahdi_enable_ec(p);
03211 dahdi_train_ec(p);
03212 }
03213 break;
03214 #ifdef HAVE_PRI
03215 case SIG_PRI:
03216
03217 if (!pri_grab(p, p->pri)) {
03218 p->proceeding = 1;
03219 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03220 pri_rel(p->pri);
03221 } else {
03222 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03223 res = -1;
03224 }
03225 break;
03226 #endif
03227 case 0:
03228 ast_mutex_unlock(&p->lock);
03229 return 0;
03230 default:
03231 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03232 res = -1;
03233 }
03234 ast_mutex_unlock(&p->lock);
03235 return res;
03236 }
03237
03238 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03239 {
03240 char *cp;
03241 signed char *scp;
03242 int x;
03243 int index;
03244 struct dahdi_pvt *p = chan->tech_pvt, *pp;
03245 struct oprmode *oprmode;
03246
03247
03248
03249 if (!data || (datalen < 1)) {
03250 errno = EINVAL;
03251 return -1;
03252 }
03253
03254 switch (option) {
03255 case AST_OPTION_TXGAIN:
03256 scp = (signed char *) data;
03257 index = dahdi_get_index(chan, p, 0);
03258 if (index < 0) {
03259 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03260 return -1;
03261 }
03262 if (option_debug)
03263 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03264 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
03265 case AST_OPTION_RXGAIN:
03266 scp = (signed char *) data;
03267 index = dahdi_get_index(chan, p, 0);
03268 if (index < 0) {
03269 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03270 return -1;
03271 }
03272 if (option_debug)
03273 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03274 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
03275 case AST_OPTION_TONE_VERIFY:
03276 if (!p->dsp)
03277 break;
03278 cp = (char *) data;
03279 switch (*cp) {
03280 case 1:
03281 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03282 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
03283 break;
03284 case 2:
03285 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03286 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
03287 break;
03288 default:
03289 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03290 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03291 break;
03292 }
03293 break;
03294 case AST_OPTION_TDD:
03295
03296 cp = (char *) data;
03297 p->mate = 0;
03298 if (!*cp) {
03299 if (option_debug)
03300 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03301 if (p->tdd)
03302 tdd_free(p->tdd);
03303 p->tdd = 0;
03304 break;
03305 }
03306 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
03307 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03308 dahdi_disable_ec(p);
03309
03310 if (!p->didtdd) {
03311 unsigned char mybuf[41000];
03312 unsigned char *buf;
03313 int size, res, fd, len;
03314 struct pollfd fds[1];
03315
03316 buf = mybuf;
03317 memset(buf, 0x7f, sizeof(mybuf));
03318 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03319 len = 40000;
03320 index = dahdi_get_index(chan, p, 0);
03321 if (index < 0) {
03322 ast_log(LOG_WARNING, "No index in TDD?\n");
03323 return -1;
03324 }
03325 fd = p->subs[index].dfd;
03326 while (len) {
03327 if (ast_check_hangup(chan))
03328 return -1;
03329 size = len;
03330 if (size > READ_SIZE)
03331 size = READ_SIZE;
03332 fds[0].fd = fd;
03333 fds[0].events = POLLPRI | POLLOUT;
03334 fds[0].revents = 0;
03335 res = poll(fds, 1, -1);
03336 if (!res) {
03337 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03338 continue;
03339 }
03340
03341 if (fds[0].revents & POLLPRI)
03342 return -1;
03343 if (!(fds[0].revents & POLLOUT)) {
03344 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03345 continue;
03346 }
03347 res = write(fd, buf, size);
03348 if (res != size) {
03349 if (res == -1) return -1;
03350 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03351 break;
03352 }
03353 len -= size;
03354 buf += size;
03355 }
03356 p->didtdd = 1;
03357 }
03358 if (*cp == 2) {
03359 if (p->tdd)
03360 tdd_free(p->tdd);
03361 p->tdd = 0;
03362 p->mate = 1;
03363 break;
03364 }
03365 if (!p->tdd) {
03366 p->tdd = tdd_new();
03367 }
03368 break;
03369 case AST_OPTION_RELAXDTMF:
03370 if (!p->dsp)
03371 break;
03372 cp = (char *) data;
03373 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03374 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03375 p->dtmfrelax = 0;
03376 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03377 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03378 break;
03379 case AST_OPTION_AUDIO_MODE:
03380 cp = (char *) data;
03381 if (!*cp) {
03382 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03383 x = 0;
03384 dahdi_disable_ec(p);
03385 } else {
03386 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03387 x = 1;
03388 }
03389 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03390 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03391 break;
03392 case AST_OPTION_OPRMODE:
03393 oprmode = (struct oprmode *) data;
03394 pp = oprmode->peer->tech_pvt;
03395 p->oprmode = pp->oprmode = 0;
03396
03397 p->oprpeer = pp;
03398 pp->oprpeer = p;
03399
03400 if (oprmode->mode)
03401 {
03402 pp->oprmode = oprmode->mode;
03403 p->oprmode = -oprmode->mode;
03404 }
03405 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03406 oprmode->mode, chan->name,oprmode->peer->name);;
03407 break;
03408 case AST_OPTION_ECHOCAN:
03409 cp = (char *) data;
03410 if (*cp) {
03411 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03412 dahdi_enable_ec(p);
03413 } else {
03414 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03415 dahdi_disable_ec(p);
03416 }
03417 break;
03418 }
03419 errno = 0;
03420
03421 return 0;
03422 }
03423
03424 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
03425 {
03426 struct dahdi_pvt *p = chan->tech_pvt;
03427
03428 if (!strcasecmp(data, "rxgain")) {
03429 ast_mutex_lock(&p->lock);
03430 snprintf(buf, len, "%f", p->rxgain);
03431 ast_mutex_unlock(&p->lock);
03432 } else if (!strcasecmp(data, "txgain")) {
03433 ast_mutex_lock(&p->lock);
03434 snprintf(buf, len, "%f", p->txgain);
03435 ast_mutex_unlock(&p->lock);
03436 } else {
03437 ast_copy_string(buf, "", len);
03438 }
03439 return 0;
03440 }
03441
03442
03443 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
03444 {
03445
03446 int x;
03447 int hasslaves;
03448 if (!master)
03449 return;
03450 if (needlock) {
03451 ast_mutex_lock(&master->lock);
03452 if (slave) {
03453 while (ast_mutex_trylock(&slave->lock)) {
03454 DEADLOCK_AVOIDANCE(&master->lock);
03455 }
03456 }
03457 }
03458 hasslaves = 0;
03459 for (x = 0; x < MAX_SLAVES; x++) {
03460 if (master->slaves[x]) {
03461 if (!slave || (master->slaves[x] == slave)) {
03462
03463 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03464 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03465 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03466 master->slaves[x]->master = NULL;
03467 master->slaves[x] = NULL;
03468 } else
03469 hasslaves = 1;
03470 }
03471 if (!hasslaves)
03472 master->inconference = 0;
03473 }
03474 if (!slave) {
03475 if (master->master) {
03476
03477 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03478 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03479 hasslaves = 0;
03480 for (x = 0; x < MAX_SLAVES; x++) {
03481 if (master->master->slaves[x] == master)
03482 master->master->slaves[x] = NULL;
03483 else if (master->master->slaves[x])
03484 hasslaves = 1;
03485 }
03486 if (!hasslaves)
03487 master->master->inconference = 0;
03488 }
03489 master->master = NULL;
03490 }
03491 update_conf(master);
03492 if (needlock) {
03493 if (slave)
03494 ast_mutex_unlock(&slave->lock);
03495 ast_mutex_unlock(&master->lock);
03496 }
03497 }
03498
03499 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
03500 int x;
03501 if (!slave || !master) {
03502 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03503 return;
03504 }
03505 for (x = 0; x < MAX_SLAVES; x++) {
03506 if (!master->slaves[x]) {
03507 master->slaves[x] = slave;
03508 break;
03509 }
03510 }
03511 if (x >= MAX_SLAVES) {
03512 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03513 master->slaves[MAX_SLAVES - 1] = slave;
03514 }
03515 if (slave->master)
03516 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03517 slave->master = master;
03518
03519 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03520 }
03521
03522 static void disable_dtmf_detect(struct dahdi_pvt *p)
03523 {
03524 #ifdef DAHDI_TONEDETECT
03525 int val;
03526 #endif
03527
03528 p->ignoredtmf = 1;
03529
03530 #ifdef DAHDI_TONEDETECT
03531 val = 0;
03532 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03533 #endif
03534 if (!p->hardwaredtmf && p->dsp) {
03535 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03536 ast_dsp_set_features(p->dsp, p->dsp_features);
03537 }
03538 }
03539
03540 static void enable_dtmf_detect(struct dahdi_pvt *p)
03541 {
03542 #ifdef DAHDI_TONEDETECT
03543 int val;
03544 #endif
03545
03546 if (p->channel == CHAN_PSEUDO)
03547 return;
03548
03549 p->ignoredtmf = 0;
03550
03551 #ifdef DAHDI_TONEDETECT
03552 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
03553 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03554 #endif
03555 if (!p->hardwaredtmf && p->dsp) {
03556 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03557 ast_dsp_set_features(p->dsp, p->dsp_features);
03558 }
03559 }
03560
03561 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)
03562 {
03563 struct ast_channel *who;
03564 struct dahdi_pvt *p0, *p1, *op0, *op1;
03565 struct dahdi_pvt *master = NULL, *slave = NULL;
03566 struct ast_frame *f;
03567 int inconf = 0;
03568 int nothingok = 1;
03569 int ofd0, ofd1;
03570 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03571 int os0 = -1, os1 = -1;
03572 int priority = 0;
03573 struct ast_channel *oc0, *oc1;
03574 enum ast_bridge_result res;
03575
03576 #ifdef PRI_2BCT
03577 int triedtopribridge = 0;
03578 q931_call *q931c0 = NULL, *q931c1 = NULL;
03579 #endif
03580
03581
03582
03583
03584
03585
03586 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03587 return AST_BRIDGE_FAILED_NOWARN;
03588
03589 ast_mutex_lock(&c0->lock);
03590 while (ast_mutex_trylock(&c1->lock)) {
03591 DEADLOCK_AVOIDANCE(&c0->lock);
03592 }
03593
03594 p0 = c0->tech_pvt;
03595 p1 = c1->tech_pvt;
03596
03597 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03598 ast_mutex_unlock(&c0->lock);
03599 ast_mutex_unlock(&c1->lock);
03600 return AST_BRIDGE_FAILED_NOWARN;
03601 }
03602
03603 oi0 = dahdi_get_index(c0, p0, 0);
03604 oi1 = dahdi_get_index(c1, p1, 0);
03605 if ((oi0 < 0) || (oi1 < 0)) {
03606 ast_mutex_unlock(&c0->lock);
03607 ast_mutex_unlock(&c1->lock);
03608 return AST_BRIDGE_FAILED;
03609 }
03610
03611 op0 = p0 = c0->tech_pvt;
03612 op1 = p1 = c1->tech_pvt;
03613 ofd0 = c0->fds[0];
03614 ofd1 = c1->fds[0];
03615 oc0 = p0->owner;
03616 oc1 = p1->owner;
03617
03618 if (ast_mutex_trylock(&p0->lock)) {
03619
03620 ast_mutex_unlock(&c0->lock);
03621 ast_mutex_unlock(&c1->lock);
03622 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03623 return AST_BRIDGE_RETRY;
03624 }
03625 if (ast_mutex_trylock(&p1->lock)) {
03626
03627 ast_mutex_unlock(&p0->lock);
03628 ast_mutex_unlock(&c0->lock);
03629 ast_mutex_unlock(&c1->lock);
03630 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03631 return AST_BRIDGE_RETRY;
03632 }
03633
03634 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03635 if (p0->owner && p1->owner) {
03636
03637 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03638 master = p0;
03639 slave = p1;
03640 inconf = 1;
03641 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03642 master = p1;
03643 slave = p0;
03644 inconf = 1;
03645 } else {
03646 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
03647 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03648 p0->channel,
03649 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03650 p0->subs[SUB_REAL].inthreeway, p0->channel,
03651 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03652 p1->subs[SUB_REAL].inthreeway);
03653 }
03654 nothingok = 0;
03655 }
03656 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03657 if (p1->subs[SUB_THREEWAY].inthreeway) {
03658 master = p1;
03659 slave = p0;
03660 nothingok = 0;
03661 }
03662 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03663 if (p0->subs[SUB_THREEWAY].inthreeway) {
03664 master = p0;
03665 slave = p1;
03666 nothingok = 0;
03667 }
03668 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03669
03670
03671 if (p1->subs[SUB_CALLWAIT].inthreeway) {
03672 master = p1;
03673 slave = p0;
03674 nothingok = 0;
03675 }
03676 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03677
03678 if (p0->subs[SUB_CALLWAIT].inthreeway) {
03679 master = p0;
03680 slave = p1;
03681 nothingok = 0;
03682 }
03683 }
03684 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03685 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03686 if (master && slave) {
03687
03688
03689
03690 if ((oi1 == SUB_THREEWAY) &&
03691 p1->subs[SUB_THREEWAY].inthreeway &&
03692 p1->subs[SUB_REAL].owner &&
03693 p1->subs[SUB_REAL].inthreeway &&
03694 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03695 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03696 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
03697 os1 = p1->subs[SUB_REAL].owner->_state;
03698 } else {
03699 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03700 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
03701 }
03702 if ((oi0 == SUB_THREEWAY) &&
03703 p0->subs[SUB_THREEWAY].inthreeway &&
03704 p0->subs[SUB_REAL].owner &&
03705 p0->subs[SUB_REAL].inthreeway &&
03706 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03707 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03708 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
03709 os0 = p0->subs[SUB_REAL].owner->_state;
03710 } else {
03711 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03712 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
03713 }
03714 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03715 if (!p0->echocanbridged || !p1->echocanbridged) {
03716
03717 dahdi_disable_ec(p0);
03718 dahdi_disable_ec(p1);
03719 }
03720 }
03721 dahdi_link(slave, master);
03722 master->inconference = inconf;
03723 } else if (!nothingok)
03724 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03725
03726 update_conf(p0);
03727 update_conf(p1);
03728 t0 = p0->subs[SUB_REAL].inthreeway;
03729 t1 = p1->subs[SUB_REAL].inthreeway;
03730
03731 ast_mutex_unlock(&p0->lock);
03732 ast_mutex_unlock(&p1->lock);
03733
03734 ast_mutex_unlock(&c0->lock);
03735 ast_mutex_unlock(&c1->lock);
03736
03737
03738 if ((!master || !slave) && !nothingok) {
03739 dahdi_enable_ec(p0);
03740 dahdi_enable_ec(p1);
03741 return AST_BRIDGE_FAILED;
03742 }
03743
03744 if (option_verbose > 2)
03745 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03746
03747 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03748 disable_dtmf_detect(op0);
03749
03750 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03751 disable_dtmf_detect(op1);
03752
03753 for (;;) {
03754 struct ast_channel *c0_priority[2] = {c0, c1};
03755 struct ast_channel *c1_priority[2] = {c1, c0};
03756
03757
03758
03759 ast_mutex_lock(&c0->lock);
03760 while (ast_mutex_trylock(&c1->lock)) {
03761 DEADLOCK_AVOIDANCE(&c0->lock);
03762 }
03763
03764 p0 = c0->tech_pvt;
03765 p1 = c1->tech_pvt;
03766
03767 if (op0 == p0)
03768 i0 = dahdi_get_index(c0, p0, 1);
03769 if (op1 == p1)
03770 i1 = dahdi_get_index(c1, p1, 1);
03771 ast_mutex_unlock(&c0->lock);
03772 ast_mutex_unlock(&c1->lock);
03773
03774 if (!timeoutms ||
03775 (op0 != p0) ||
03776 (op1 != p1) ||
03777 (ofd0 != c0->fds[0]) ||
03778 (ofd1 != c1->fds[0]) ||
03779 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
03780 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
03781 (oc0 != p0->owner) ||
03782 (oc1 != p1->owner) ||
03783 (t0 != p0->subs[SUB_REAL].inthreeway) ||
03784 (t1 != p1->subs[SUB_REAL].inthreeway) ||
03785 (oi0 != i0) ||
03786 (oi1 != i1)) {
03787 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03788 op0->channel, oi0, op1->channel, oi1);
03789 res = AST_BRIDGE_RETRY;
03790 goto return_from_bridge;
03791 }
03792
03793 #ifdef PRI_2BCT
03794 q931c0 = p0->call;
03795 q931c1 = p1->call;
03796 if (p0->transfer && p1->transfer
03797 && q931c0 && q931c1
03798 && !triedtopribridge) {
03799 pri_channel_bridge(q931c0, q931c1);
03800 triedtopribridge = 1;
03801 }
03802 #endif
03803
03804 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03805 if (!who) {
03806 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03807 continue;
03808 }
03809 f = ast_read(who);
03810 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03811 *fo = f;
03812 *rc = who;
03813 res = AST_BRIDGE_COMPLETE;
03814 goto return_from_bridge;
03815 }
03816 if (f->frametype == AST_FRAME_DTMF) {
03817 if ((who == c0) && p0->pulsedial) {
03818 ast_write(c1, f);
03819 } else if ((who == c1) && p1->pulsedial) {
03820 ast_write(c0, f);
03821 } else {
03822 *fo = f;
03823 *rc = who;
03824 res = AST_BRIDGE_COMPLETE;
03825 goto return_from_bridge;
03826 }
03827 }
03828 ast_frfree(f);
03829
03830
03831 priority = !priority;
03832 }
03833
03834 return_from_bridge:
03835 if (op0 == p0)
03836 dahdi_enable_ec(p0);
03837
03838 if (op1 == p1)
03839 dahdi_enable_ec(p1);
03840
03841 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03842 enable_dtmf_detect(op0);
03843
03844 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03845 enable_dtmf_detect(op1);
03846
03847 dahdi_unlink(slave, master, 1);
03848
03849 return res;
03850 }
03851
03852 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
03853 {
03854 struct dahdi_pvt *p = newchan->tech_pvt;
03855 int x;
03856 ast_mutex_lock(&p->lock);
03857 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03858 if (p->owner == oldchan) {
03859 p->owner = newchan;
03860 }
03861 for (x = 0; x < 3; x++)
03862 if (p->subs[x].owner == oldchan) {
03863 if (!x)
03864 dahdi_unlink(NULL, p, 0);
03865 p->subs[x].owner = newchan;
03866 }
03867 if (newchan->_state == AST_STATE_RINGING)
03868 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03869 update_conf(p);
03870 ast_mutex_unlock(&p->lock);
03871 return 0;
03872 }
03873
03874 static int dahdi_ring_phone(struct dahdi_pvt *p)
03875 {
03876 int x;
03877 int res;
03878
03879 x = 0;
03880 x = DAHDI_ONHOOK;
03881 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03882 do {
03883 x = DAHDI_RING;
03884 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03885 if (res) {
03886 switch (errno) {
03887 case EBUSY:
03888 case EINTR:
03889
03890 usleep(10000);
03891 continue;
03892 case EINPROGRESS:
03893 res = 0;
03894 break;
03895 default:
03896 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03897 res = 0;
03898 }
03899 }
03900 } while (res);
03901 return res;
03902 }
03903
03904 static void *ss_thread(void *data);
03905
03906 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
03907
03908 static int attempt_transfer(struct dahdi_pvt *p)
03909 {
03910
03911
03912
03913 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03914
03915
03916 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03917 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03918 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03919 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03920 }
03921 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03922 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
03923 }
03924 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03925 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03926 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03927 return -1;
03928 }
03929
03930 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03931 unalloc_sub(p, SUB_THREEWAY);
03932 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03933 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03934 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03935 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03936 }
03937 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03938 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03939 }
03940 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03941 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03942 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03943 return -1;
03944 }
03945
03946 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03947 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03948 unalloc_sub(p, SUB_THREEWAY);
03949
03950 return 1;
03951 } else {
03952 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03953 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03954 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03955 return -1;
03956 }
03957 return 0;
03958 }
03959
03960 static int check_for_conference(struct dahdi_pvt *p)
03961 {
03962 struct dahdi_confinfo ci;
03963
03964 if (p->master || (p->confno > -1))
03965 return 0;
03966 memset(&ci, 0, sizeof(ci));
03967 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
03968 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
03969 return 0;
03970 }
03971
03972
03973
03974 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03975 if (option_verbose > 2)
03976 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03977 return 1;
03978 }
03979 return 0;
03980 }
03981
03982 static int get_alarms(struct dahdi_pvt *p)
03983 {
03984 int res;
03985 struct dahdi_spaninfo zi;
03986 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
03987
03988
03989
03990
03991
03992 struct dahdi_params params;
03993 #endif
03994
03995 memset(&zi, 0, sizeof(zi));
03996 zi.spanno = p->span;
03997
03998
03999 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
04000 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04001 return 0;
04002 }
04003 if (zi.alarms != DAHDI_ALARM_NONE)
04004 return zi.alarms;
04005 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04006
04007 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04008 return params.chan_alarms;
04009
04010 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04011 #endif
04012 return DAHDI_ALARM_NONE;
04013 }
04014
04015 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04016 {
04017 struct dahdi_pvt *p = ast->tech_pvt;
04018 struct ast_frame *f = *dest;
04019
04020 if (option_debug)
04021 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04022
04023 if (p->confirmanswer) {
04024 if (option_debug)
04025 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04026
04027
04028 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04029 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04030 *dest = &p->subs[index].f;
04031
04032 p->confirmanswer = 0;
04033 } else if (p->callwaitcas) {
04034 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04035 if (option_debug)
04036 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04037 if (p->cidspill)
04038 free(p->cidspill);
04039 send_cwcidspill(p);
04040 }
04041 if ((f->subclass != 'm') && (f->subclass != 'u'))
04042 p->callwaitcas = 0;
04043 p->subs[index].f.frametype = AST_FRAME_NULL;
04044 p->subs[index].f.subclass = 0;
04045 *dest = &p->subs[index].f;
04046 } else if (f->subclass == 'f') {
04047
04048 if ((p->callprogress & 0x6) && !p->faxhandled) {
04049 p->faxhandled = 1;
04050 if (strcmp(ast->exten, "fax")) {
04051 const char *target_context = S_OR(ast->macrocontext, ast->context);
04052
04053
04054
04055
04056
04057 ast_mutex_unlock(&p->lock);
04058 ast_channel_unlock(ast);
04059 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04060 ast_channel_lock(ast);
04061 ast_mutex_lock(&p->lock);
04062 if (option_verbose > 2)
04063 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04064
04065 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04066 if (ast_async_goto(ast, target_context, "fax", 1))
04067 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04068 } else {
04069 ast_channel_lock(ast);
04070 ast_mutex_lock(&p->lock);
04071 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04072 }
04073 } else if (option_debug)
04074 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04075 } else if (option_debug)
04076 ast_log(LOG_DEBUG, "Fax already handled\n");
04077 dahdi_confmute(p, 0);
04078 p->subs[index].f.frametype = AST_FRAME_NULL;
04079 p->subs[index].f.subclass = 0;
04080 *dest = &p->subs[index].f;
04081 } else if (f->subclass == 'm') {
04082
04083 dahdi_confmute(p, 1);
04084 p->subs[index].f.frametype = AST_FRAME_NULL;
04085 p->subs[index].f.subclass = 0;
04086 *dest = &p->subs[index].f;
04087 } else if (f->subclass == 'u') {
04088
04089 dahdi_confmute(p, 0);
04090 p->subs[index].f.frametype = AST_FRAME_NULL;
04091 p->subs[index].f.subclass = 0;
04092 *dest = &p->subs[index].f;
04093 } else
04094 dahdi_confmute(p, 0);
04095 }
04096
04097 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04098 {
04099 const char *alarm_str = alarm2str(alarms);
04100
04101
04102
04103 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04104 p->unknown_alarm = 1;
04105 return;
04106 } else {
04107 p->unknown_alarm = 0;
04108 }
04109
04110 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04111 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04112 "Alarm: %s\r\n"
04113 "Channel: %d\r\n",
04114 alarm_str, p->channel);
04115 }
04116
04117 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04118 {
04119 int res, x;
04120 int index, mysig;
04121 char *c;
04122 struct dahdi_pvt *p = ast->tech_pvt;
04123 pthread_t threadid;
04124 pthread_attr_t attr;
04125 struct ast_channel *chan;
04126 struct ast_frame *f;
04127
04128 index = dahdi_get_index(ast, p, 0);
04129 mysig = p->sig;
04130 if (p->outsigmod > -1)
04131 mysig = p->outsigmod;
04132 p->subs[index].f.frametype = AST_FRAME_NULL;
04133 p->subs[index].f.subclass = 0;
04134 p->subs[index].f.datalen = 0;
04135 p->subs[index].f.samples = 0;
04136 p->subs[index].f.mallocd = 0;
04137 p->subs[index].f.offset = 0;
04138 p->subs[index].f.src = "dahdi_handle_event";
04139 p->subs[index].f.data = NULL;
04140 f = &p->subs[index].f;
04141
04142 if (index < 0)
04143 return &p->subs[index].f;
04144 if (p->fake_event) {
04145 res = p->fake_event;
04146 p->fake_event = 0;
04147 } else
04148 res = dahdi_get_event(p->subs[index].dfd);
04149
04150 if (option_debug)
04151 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04152
04153 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04154 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04155
04156 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04157 #ifdef HAVE_PRI
04158 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
04159
04160 } else {
04161 #endif
04162 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04163 p->subs[index].f.subclass = res & 0xff;
04164 #ifdef HAVE_PRI
04165 }
04166 #endif
04167 dahdi_handle_dtmfup(ast, index, &f);
04168 return f;
04169 }
04170
04171 if (res & DAHDI_EVENT_DTMFDOWN) {
04172 if (option_debug)
04173 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04174
04175 dahdi_confmute(p, 1);
04176 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04177 p->subs[index].f.subclass = res & 0xff;
04178 return &p->subs[index].f;
04179 }
04180
04181 switch (res) {
04182 #ifdef DAHDI_EVENT_EC_DISABLED
04183 case DAHDI_EVENT_EC_DISABLED:
04184 if (option_verbose > 2)
04185 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04186 p->echocanon = 0;
04187 break;
04188 #endif
04189 case DAHDI_EVENT_BITSCHANGED:
04190 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04191 case DAHDI_EVENT_PULSE_START:
04192
04193 if (!ast->pbx)
04194 tone_zone_play_tone(p->subs[index].dfd, -1);
04195 break;
04196 case DAHDI_EVENT_DIALCOMPLETE:
04197 if (p->inalarm) break;
04198 if ((p->radio || (p->oprmode < 0))) break;
04199 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
04200 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04201 return NULL;
04202 }
04203 if (!x) {
04204 dahdi_enable_ec(p);
04205 if (p->echobreak) {
04206 dahdi_train_ec(p);
04207 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04208 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04209 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04210 p->echobreak = 0;
04211 } else {
04212 p->dialing = 0;
04213 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04214
04215 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04216 ast_setstate(ast, AST_STATE_UP);
04217 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04218 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04219 break;
04220 } else {
04221
04222 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04223 }
04224 }
04225 if (ast->_state == AST_STATE_DIALING) {
04226 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04227 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
04228 } 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)))) {
04229 ast_setstate(ast, AST_STATE_RINGING);
04230 } else if (!p->answeronpolarityswitch) {
04231 ast_setstate(ast, AST_STATE_UP);
04232 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04233 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04234
04235 p->polarity = POLARITY_REV;
04236 } else {
04237
04238 p->polarity = POLARITY_IDLE;
04239 }
04240 }
04241 }
04242 }
04243 break;
04244 case DAHDI_EVENT_ALARM:
04245 #ifdef HAVE_PRI
04246 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04247
04248 if (p->call) {
04249 if (p->pri && p->pri->pri) {
04250 if (!pri_grab(p, p->pri)) {
04251 pri_hangup(p->pri->pri, p->call, -1);
04252 pri_destroycall(p->pri->pri, p->call);
04253 p->call = NULL;
04254 pri_rel(p->pri);
04255 } else
04256 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04257 } else
04258 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04259 }
04260 if (p->owner)
04261 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04262 }
04263 if (p->bearer)
04264 p->bearer->inalarm = 1;
04265 else
04266 #endif
04267 p->inalarm = 1;
04268 res = get_alarms(p);
04269 handle_alarms(p, res);
04270 #ifdef HAVE_LIBPRI
04271 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04272
04273 } else {
04274 break;
04275 }
04276 #endif
04277 case DAHDI_EVENT_ONHOOK:
04278 if (p->radio) {
04279 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04280 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04281 break;
04282 }
04283 if (p->oprmode < 0)
04284 {
04285 if (p->oprmode != -1) break;
04286 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04287 {
04288
04289 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04290 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04291 save_conference(p->oprpeer);
04292 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04293 }
04294 break;
04295 }
04296 switch (p->sig) {
04297 case SIG_FXOLS:
04298 case SIG_FXOGS:
04299 case SIG_FXOKS:
04300 p->onhooktime = time(NULL);
04301 p->msgstate = -1;
04302
04303 if (index == SUB_REAL) {
04304
04305 if (p->subs[SUB_CALLWAIT].owner) {
04306
04307 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04308 if (option_verbose > 2)
04309 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04310 unalloc_sub(p, SUB_CALLWAIT);
04311 #if 0
04312 p->subs[index].needanswer = 0;
04313 p->subs[index].needringing = 0;
04314 #endif
04315 p->callwaitingrepeat = 0;
04316 p->cidcwexpire = 0;
04317 p->owner = NULL;
04318
04319 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04320 p->dialing = 1;
04321 dahdi_ring_phone(p);
04322 } else if (p->subs[SUB_THREEWAY].owner) {
04323 unsigned int mssinceflash;
04324
04325
04326 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04327
04328 ast_mutex_unlock(&p->lock);
04329 DEADLOCK_AVOIDANCE(&ast->lock);
04330
04331
04332
04333 ast_mutex_lock(&p->lock);
04334 if (p->owner != ast) {
04335 ast_log(LOG_WARNING, "This isn't good...\n");
04336 return NULL;
04337 }
04338 }
04339 if (!p->subs[SUB_THREEWAY].owner) {
04340 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04341 return NULL;
04342 }
04343 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04344 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04345 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04346
04347
04348 if (p->subs[SUB_THREEWAY].owner)
04349 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04350 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04351 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04352 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04353 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04354 if (p->transfer) {
04355
04356 p->subs[SUB_REAL].inthreeway = 0;
04357 p->subs[SUB_THREEWAY].inthreeway = 0;
04358
04359 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04360 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04361
04362 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04363 p->owner = NULL;
04364
04365 dahdi_ring_phone(p);
04366 } else {
04367 if ((res = attempt_transfer(p)) < 0) {
04368 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04369 if (p->subs[SUB_THREEWAY].owner)
04370 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04371 } else if (res) {
04372
04373 if (p->subs[SUB_THREEWAY].owner)
04374 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04375 break;
04376 }
04377 }
04378 } else {
04379 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04380 if (p->subs[SUB_THREEWAY].owner)
04381 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04382 }
04383 } else {
04384 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04385
04386 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04387 p->owner = NULL;
04388
04389 dahdi_ring_phone(p);
04390 }
04391 }
04392 } else {
04393 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04394 }
04395
04396 default:
04397 dahdi_disable_ec(p);
04398 return NULL;
04399 }
04400 break;
04401 case DAHDI_EVENT_RINGOFFHOOK:
04402 if (p->inalarm) break;
04403 if (p->oprmode < 0)
04404 {
04405 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04406 {
04407
04408 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04409 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04410 restore_conference(p->oprpeer);
04411 }
04412 break;
04413 }
04414 if (p->radio)
04415 {
04416 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04417 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04418 break;
04419 }
04420
04421
04422 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04423 c = strchr(p->dialdest, '/');
04424 if (c)
04425 c++;
04426 else
04427 c = p->dialdest;
04428 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04429 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04430 if (strlen(p->dop.dialstr) > 4) {
04431 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04432 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04433 p->echorest[sizeof(p->echorest) - 1] = '\0';
04434 p->echobreak = 1;
04435 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04436 } else
04437 p->echobreak = 0;
04438 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04439 int saveerr = errno;
04440
04441 x = DAHDI_ONHOOK;
04442 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04443 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04444 return NULL;
04445 }
04446 p->dialing = 1;
04447 return &p->subs[index].f;
04448 }
04449 switch (p->sig) {
04450 case SIG_FXOLS:
04451 case SIG_FXOGS:
04452 case SIG_FXOKS:
04453 switch (ast->_state) {
04454 case AST_STATE_RINGING:
04455 dahdi_enable_ec(p);
04456 dahdi_train_ec(p);
04457 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04458 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04459
04460 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04461 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04462 if (p->cidspill) {
04463
04464 free(p->cidspill);
04465 p->cidspill = NULL;
04466 }
04467 p->dialing = 0;
04468 p->callwaitcas = 0;
04469 if (p->confirmanswer) {
04470
04471 p->subs[index].f.frametype = AST_FRAME_NULL;
04472 p->subs[index].f.subclass = 0;
04473 } else if (!ast_strlen_zero(p->dop.dialstr)) {
04474
04475 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04476 if (res < 0) {
04477 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04478 p->dop.dialstr[0] = '\0';
04479 return NULL;
04480 } else {
04481 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04482 p->subs[index].f.frametype = AST_FRAME_NULL;
04483 p->subs[index].f.subclass = 0;
04484 p->dialing = 1;
04485 }
04486 p->dop.dialstr[0] = '\0';
04487 ast_setstate(ast, AST_STATE_DIALING);
04488 } else
04489 ast_setstate(ast, AST_STATE_UP);
04490 return &p->subs[index].f;
04491 case AST_STATE_DOWN:
04492 ast_setstate(ast, AST_STATE_RING);
04493 ast->rings = 1;
04494 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04495 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04496 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04497 return &p->subs[index].f;
04498 case AST_STATE_UP:
04499
04500 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04501
04502 if (ast_bridged_channel(p->owner))
04503 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04504 p->subs[index].needunhold = 1;
04505 break;
04506 case AST_STATE_RESERVED:
04507
04508 if (has_voicemail(p))
04509 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04510 else
04511 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04512 break;
04513 default:
04514 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04515 }
04516 break;
04517 case SIG_FXSLS:
04518 case SIG_FXSGS:
04519 case SIG_FXSKS:
04520 if (ast->_state == AST_STATE_RING) {
04521 p->ringt = p->ringt_base;
04522 }
04523
04524
04525 case SIG_EM:
04526 case SIG_EM_E1:
04527 case SIG_EMWINK:
04528 case SIG_FEATD:
04529 case SIG_FEATDMF:
04530 case SIG_FEATDMF_TA:
04531 case SIG_E911:
04532 case SIG_FGC_CAMA:
04533 case SIG_FGC_CAMAMF:
04534 case SIG_FEATB:
04535 case SIG_SF:
04536 case SIG_SFWINK:
04537 case SIG_SF_FEATD:
04538 case SIG_SF_FEATDMF:
04539 case SIG_SF_FEATB:
04540 if (ast->_state == AST_STATE_PRERING)
04541 ast_setstate(ast, AST_STATE_RING);
04542 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04543 if (option_debug)
04544 ast_log(LOG_DEBUG, "Ring detected\n");
04545 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04546 p->subs[index].f.subclass = AST_CONTROL_RING;
04547 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04548 if (option_debug)
04549 ast_log(LOG_DEBUG, "Line answered\n");
04550 if (p->confirmanswer) {
04551 p->subs[index].f.frametype = AST_FRAME_NULL;
04552 p->subs[index].f.subclass = 0;
04553 } else {
04554 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04555 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04556 ast_setstate(ast, AST_STATE_UP);
04557 }
04558 } else if (ast->_state != AST_STATE_RING)
04559 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04560 break;
04561 default:
04562 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04563 }
04564 break;
04565 #ifdef DAHDI_EVENT_RINGBEGIN
04566 case DAHDI_EVENT_RINGBEGIN:
04567 switch (p->sig) {
04568 case SIG_FXSLS:
04569 case SIG_FXSGS:
04570 case SIG_FXSKS:
04571 if (ast->_state == AST_STATE_RING) {
04572 p->ringt = p->ringt_base;
04573 }
04574 break;
04575 }
04576 break;
04577 #endif
04578 case DAHDI_EVENT_RINGEROFF:
04579 if (p->inalarm) break;
04580 if ((p->radio || (p->oprmode < 0))) break;
04581 ast->rings++;
04582 if ((ast->rings > p->cidrings) && (p->cidspill)) {
04583 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
04584 free(p->cidspill);
04585 p->cidspill = NULL;
04586 p->callwaitcas = 0;
04587 }
04588 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04589 p->subs[index].f.subclass = AST_CONTROL_RINGING;
04590 break;
04591 case DAHDI_EVENT_RINGERON:
04592 break;
04593 case DAHDI_EVENT_NOALARM:
04594 p->inalarm = 0;
04595 #ifdef HAVE_PRI
04596
04597 if (p->bearer)
04598 p->bearer->inalarm = 0;
04599 #endif
04600 if (!p->unknown_alarm) {
04601 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04602 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04603 "Channel: %d\r\n", p->channel);
04604 } else {
04605 p->unknown_alarm = 0;
04606 }
04607 break;
04608 case DAHDI_EVENT_WINKFLASH:
04609 if (p->inalarm) break;
04610 if (p->radio) break;
04611 if (p->oprmode < 0) break;
04612 if (p->oprmode > 1)
04613 {
04614 struct dahdi_params par;
04615
04616 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
04617 {
04618 if (!par.rxisoffhook)
04619 {
04620
04621 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04622 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
04623 save_conference(p);
04624 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04625 }
04626 }
04627 break;
04628 }
04629
04630 gettimeofday(&p->flashtime, NULL);
04631 switch (mysig) {
04632 case SIG_FXOLS:
04633 case SIG_FXOGS:
04634 case SIG_FXOKS:
04635 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
04636 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04637 p->callwaitcas = 0;
04638
04639 if (index != SUB_REAL) {
04640 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
04641 goto winkflashdone;
04642 }
04643
04644 if (p->subs[SUB_CALLWAIT].owner) {
04645
04646 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
04647 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04648 p->owner = p->subs[SUB_REAL].owner;
04649 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
04650 if (p->owner->_state == AST_STATE_RINGING) {
04651 ast_setstate(p->owner, AST_STATE_UP);
04652 p->subs[SUB_REAL].needanswer = 1;
04653 }
04654 p->callwaitingrepeat = 0;
04655 p->cidcwexpire = 0;
04656
04657 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04658 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04659 S_OR(p->mohsuggest, NULL),
04660 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04661 }
04662 p->subs[SUB_CALLWAIT].needhold = 1;
04663 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04664 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
04665 S_OR(p->mohsuggest, NULL),
04666 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04667 }
04668 p->subs[SUB_REAL].needunhold = 1;
04669 } else if (!p->subs[SUB_THREEWAY].owner) {
04670 if (!p->threewaycalling) {
04671
04672 p->subs[SUB_REAL].needflash = 1;
04673 goto winkflashdone;
04674 } else if (!check_for_conference(p)) {
04675 char cid_num[256];
04676 char cid_name[256];
04677
04678 cid_num[0] = 0;
04679 cid_name[0] = 0;
04680 if (p->dahditrcallerid && p->owner) {
04681 if (p->owner->cid.cid_num)
04682 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
04683 if (p->owner->cid.cid_name)
04684 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
04685 }
04686
04687
04688 if (!((ast->pbx) ||
04689 (ast->_state == AST_STATE_UP) ||
04690 (ast->_state == AST_STATE_RING))) {
04691 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
04692 goto winkflashdone;
04693 }
04694 if (alloc_sub(p, SUB_THREEWAY)) {
04695 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
04696 goto winkflashdone;
04697 }
04698
04699 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
04700 if (p->dahditrcallerid) {
04701 if (!p->origcid_num)
04702 p->origcid_num = ast_strdup(p->cid_num);
04703 if (!p->origcid_name)
04704 p->origcid_name = ast_strdup(p->cid_name);
04705 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
04706 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
04707 }
04708
04709 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04710
04711 dahdi_disable_ec(p);
04712 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
04713 if (res)
04714 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
04715 p->owner = chan;
04716 pthread_attr_init(&attr);
04717 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04718 if (!chan) {
04719 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
04720 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
04721 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
04722 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04723 dahdi_enable_ec(p);
04724 ast_hangup(chan);
04725 } else {
04726 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04727 int way3bridge = 0, cdr3way = 0;
04728
04729 if (!other) {
04730 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04731 } else
04732 way3bridge = 1;
04733
04734 if (p->subs[SUB_THREEWAY].owner->cdr)
04735 cdr3way = 1;
04736
04737 if (option_verbose > 2)
04738 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
04739
04740 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04741 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04742 S_OR(p->mohsuggest, NULL),
04743 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04744 }
04745 p->subs[SUB_THREEWAY].needhold = 1;
04746 }
04747 pthread_attr_destroy(&attr);
04748 }
04749 } else {
04750
04751 if (p->subs[SUB_THREEWAY].inthreeway) {
04752
04753 if (option_debug)
04754 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
04755
04756 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
04757
04758 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04759 p->owner = p->subs[SUB_REAL].owner;
04760 }
04761
04762 if (option_verbose > 2)
04763 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
04764 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04765 p->subs[SUB_REAL].inthreeway = 0;
04766 p->subs[SUB_THREEWAY].inthreeway = 0;
04767 } else {
04768
04769 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
04770 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
04771 int otherindex = SUB_THREEWAY;
04772 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04773 int way3bridge = 0, cdr3way = 0;
04774
04775 if (!other) {
04776 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04777 } else
04778 way3bridge = 1;
04779
04780 if (p->subs[SUB_THREEWAY].owner->cdr)
04781 cdr3way = 1;
04782
04783 if (option_verbose > 2)
04784 ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
04785
04786 p->subs[SUB_THREEWAY].inthreeway = 1;
04787 p->subs[SUB_REAL].inthreeway = 1;
04788 if (ast->_state == AST_STATE_UP) {
04789 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04790 otherindex = SUB_REAL;
04791 }
04792 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
04793 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
04794 p->subs[otherindex].needunhold = 1;
04795 p->owner = p->subs[SUB_REAL].owner;
04796 if (ast->_state == AST_STATE_RINGING) {
04797 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
04798 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04799 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04800 }
04801 } else {
04802 if (option_verbose > 2)
04803 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
04804 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04805 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04806 p->owner = p->subs[SUB_REAL].owner;
04807 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
04808 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04809 p->subs[SUB_REAL].needunhold = 1;
04810 dahdi_enable_ec(p);
04811 }
04812
04813 }
04814 }
04815 winkflashdone:
04816 update_conf(p);
04817 break;
04818 case SIG_EM:
04819 case SIG_EM_E1:
04820 case SIG_EMWINK:
04821 case SIG_FEATD:
04822 case SIG_SF:
04823 case SIG_SFWINK:
04824 case SIG_SF_FEATD:
04825 case SIG_FXSLS:
04826 case SIG_FXSGS:
04827 if (p->dialing)
04828 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
04829 else
04830 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
04831 break;
04832 case SIG_FEATDMF_TA:
04833 switch (p->whichwink) {
04834 case 0:
04835 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04836 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04837 break;
04838 case 1:
04839 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
04840 break;
04841 case 2:
04842 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
04843 return NULL;
04844 }
04845 p->whichwink++;
04846
04847 case SIG_FEATDMF:
04848 case SIG_E911:
04849 case SIG_FGC_CAMAMF:
04850 case SIG_FGC_CAMA:
04851 case SIG_FEATB:
04852 case SIG_SF_FEATDMF:
04853 case SIG_SF_FEATB:
04854
04855 if (!ast_strlen_zero(p->dop.dialstr)) {
04856 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04857 if (res < 0) {
04858 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04859 p->dop.dialstr[0] = '\0';
04860 return NULL;
04861 } else
04862 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04863 }
04864 p->dop.dialstr[0] = '\0';
04865 break;
04866 default:
04867 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
04868 }
04869 break;
04870 case DAHDI_EVENT_HOOKCOMPLETE:
04871 if (p->inalarm) break;
04872 if ((p->radio || (p->oprmode < 0))) break;
04873 switch (mysig) {
04874 case SIG_FXSLS:
04875 case SIG_FXSGS:
04876 case SIG_FXSKS:
04877 case SIG_EM:
04878 case SIG_EM_E1:
04879 case SIG_EMWINK:
04880 case SIG_FEATD:
04881 case SIG_SF:
04882 case SIG_SFWINK:
04883 case SIG_SF_FEATD:
04884 if (!ast_strlen_zero(p->dop.dialstr)) {
04885 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04886 if (res < 0) {
04887 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04888 p->dop.dialstr[0] = '\0';
04889 return NULL;
04890 } else
04891 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04892 }
04893 p->dop.dialstr[0] = '\0';
04894 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04895 break;
04896 case SIG_FEATDMF:
04897 case SIG_FEATDMF_TA:
04898 case SIG_E911:
04899 case SIG_FGC_CAMA:
04900 case SIG_FGC_CAMAMF:
04901 case SIG_FEATB:
04902 case SIG_SF_FEATDMF:
04903 case SIG_SF_FEATB:
04904 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
04905 break;
04906 default:
04907 break;
04908 }
04909 break;
04910 case DAHDI_EVENT_POLARITY:
04911
04912
04913
04914
04915
04916
04917 if (p->polarity == POLARITY_IDLE) {
04918 p->polarity = POLARITY_REV;
04919 if (p->answeronpolarityswitch &&
04920 ((ast->_state == AST_STATE_DIALING) ||
04921 (ast->_state == AST_STATE_RINGING))) {
04922 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
04923 ast_setstate(p->owner, AST_STATE_UP);
04924 if (p->hanguponpolarityswitch) {
04925 gettimeofday(&p->polaritydelaytv, NULL);
04926 }
04927 } else
04928 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
04929 }
04930
04931
04932 if (p->hanguponpolarityswitch &&
04933 (p->polarityonanswerdelay > 0) &&
04934 (p->polarity == POLARITY_REV) &&
04935 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
04936
04937 ast_log(LOG_DEBUG, "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) );
04938
04939 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
04940 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
04941 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
04942 p->polarity = POLARITY_IDLE;
04943 } else {
04944 ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
04945 }
04946 } else {
04947 p->polarity = POLARITY_IDLE;
04948 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
04949 }
04950
04951 ast_log(LOG_DEBUG, "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) );
04952 break;
04953 default:
04954 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
04955 }
04956 return &p->subs[index].f;
04957 }
04958
04959 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
04960 {
04961 struct dahdi_pvt *p = ast->tech_pvt;
04962 int res;
04963 int usedindex=-1;
04964 int index;
04965 struct ast_frame *f;
04966
04967
04968 index = dahdi_get_index(ast, p, 1);
04969
04970 p->subs[index].f.frametype = AST_FRAME_NULL;
04971 p->subs[index].f.datalen = 0;
04972 p->subs[index].f.samples = 0;
04973 p->subs[index].f.mallocd = 0;
04974 p->subs[index].f.offset = 0;
04975 p->subs[index].f.subclass = 0;
04976 p->subs[index].f.delivery = ast_tv(0,0);
04977 p->subs[index].f.src = "dahdi_exception";
04978 p->subs[index].f.data = NULL;
04979
04980
04981 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04982
04983
04984
04985
04986
04987 if (p->fake_event) {
04988 res = p->fake_event;
04989 p->fake_event = 0;
04990 } else
04991 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
04992
04993 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
04994 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
04995 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04996 p->owner = p->subs[SUB_REAL].owner;
04997 if (p->owner && ast_bridged_channel(p->owner))
04998 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04999 p->subs[SUB_REAL].needunhold = 1;
05000 }
05001 switch (res) {
05002 case DAHDI_EVENT_ONHOOK:
05003 dahdi_disable_ec(p);
05004 if (p->owner) {
05005 if (option_verbose > 2)
05006 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
05007 dahdi_ring_phone(p);
05008 p->callwaitingrepeat = 0;
05009 p->cidcwexpire = 0;
05010 } else
05011 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05012 update_conf(p);
05013 break;
05014 case DAHDI_EVENT_RINGOFFHOOK:
05015 dahdi_enable_ec(p);
05016 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05017 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05018 p->subs[SUB_REAL].needanswer = 1;
05019 p->dialing = 0;
05020 }
05021 break;
05022 case DAHDI_EVENT_HOOKCOMPLETE:
05023 case DAHDI_EVENT_RINGERON:
05024 case DAHDI_EVENT_RINGEROFF:
05025
05026 break;
05027 case DAHDI_EVENT_WINKFLASH:
05028 gettimeofday(&p->flashtime, NULL);
05029 if (p->owner) {
05030 if (option_verbose > 2)
05031 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05032 if (p->owner->_state != AST_STATE_UP) {
05033
05034 usedindex = dahdi_get_index(p->owner, p, 0);
05035 if (usedindex > -1) {
05036 p->subs[usedindex].needanswer = 1;
05037 }
05038 ast_setstate(p->owner, AST_STATE_UP);
05039 }
05040 p->callwaitingrepeat = 0;
05041 p->cidcwexpire = 0;
05042 if (ast_bridged_channel(p->owner))
05043 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05044 p->subs[SUB_REAL].needunhold = 1;
05045 } else
05046 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05047 update_conf(p);
05048 break;
05049 default:
05050 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05051 }
05052 f = &p->subs[index].f;
05053 return f;
05054 }
05055 if (!(p->radio || (p->oprmode < 0)) && option_debug)
05056 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05057
05058 if (ast != p->owner) {
05059 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05060 f = &p->subs[index].f;
05061 return f;
05062 }
05063 f = dahdi_handle_event(ast);
05064 return f;
05065 }
05066
05067 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05068 {
05069 struct dahdi_pvt *p = ast->tech_pvt;
05070 struct ast_frame *f;
05071 ast_mutex_lock(&p->lock);
05072 f = __dahdi_exception(ast);
05073 ast_mutex_unlock(&p->lock);
05074 return f;
05075 }
05076
05077 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05078 {
05079 struct dahdi_pvt *p = ast->tech_pvt;
05080 int res;
05081 int index;
05082 void *readbuf;
05083 struct ast_frame *f;
05084
05085 while (ast_mutex_trylock(&p->lock)) {
05086 DEADLOCK_AVOIDANCE(&ast->lock);
05087 }
05088
05089 index = dahdi_get_index(ast, p, 0);
05090
05091
05092 if (index < 0) {
05093 ast_log(LOG_WARNING, "We dont exist?\n");
05094 ast_mutex_unlock(&p->lock);
05095 return NULL;
05096 }
05097
05098 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
05099
05100 p->subs[index].f.frametype = AST_FRAME_NULL;
05101 p->subs[index].f.datalen = 0;
05102 p->subs[index].f.samples = 0;
05103 p->subs[index].f.mallocd = 0;
05104 p->subs[index].f.offset = 0;
05105 p->subs[index].f.subclass = 0;
05106 p->subs[index].f.delivery = ast_tv(0,0);
05107 p->subs[index].f.src = "dahdi_read";
05108 p->subs[index].f.data = NULL;
05109
05110
05111 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05112 {
05113 struct dahdi_params ps;
05114
05115 ps.channo = p->channel;
05116 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05117 ast_mutex_unlock(&p->lock);
05118 return NULL;
05119 }
05120 p->firstradio = 1;
05121 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05122 if (ps.rxisoffhook)
05123 {
05124 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05125 }
05126 else
05127 {
05128 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05129 }
05130 ast_mutex_unlock(&p->lock);
05131 return &p->subs[index].f;
05132 }
05133 if (p->ringt == 1) {
05134 ast_mutex_unlock(&p->lock);
05135 return NULL;
05136 }
05137 else if (p->ringt > 0)
05138 p->ringt--;
05139
05140 if (p->subs[index].needringing) {
05141
05142 p->subs[index].needringing = 0;
05143 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05144 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05145 ast_setstate(ast, AST_STATE_RINGING);
05146 ast_mutex_unlock(&p->lock);
05147 return &p->subs[index].f;
05148 }
05149
05150 if (p->subs[index].needbusy) {
05151
05152 p->subs[index].needbusy = 0;
05153 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05154 p->subs[index].f.subclass = AST_CONTROL_BUSY;
05155 ast_mutex_unlock(&p->lock);
05156 return &p->subs[index].f;
05157 }
05158
05159 if (p->subs[index].needcongestion) {
05160
05161 p->subs[index].needcongestion = 0;
05162 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05163 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
05164 ast_mutex_unlock(&p->lock);
05165 return &p->subs[index].f;
05166 }
05167
05168 if (p->subs[index].needcallerid) {
05169 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05170 S_OR(p->lastcid_name, NULL),
05171 S_OR(p->lastcid_num, NULL)
05172 );
05173 p->subs[index].needcallerid = 0;
05174 }
05175
05176 if (p->subs[index].needanswer) {
05177
05178 p->subs[index].needanswer = 0;
05179 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05180 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05181 ast_mutex_unlock(&p->lock);
05182 return &p->subs[index].f;
05183 }
05184
05185 if (p->subs[index].needflash) {
05186
05187 p->subs[index].needflash = 0;
05188 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05189 p->subs[index].f.subclass = AST_CONTROL_FLASH;
05190 ast_mutex_unlock(&p->lock);
05191 return &p->subs[index].f;
05192 }
05193
05194 if (p->subs[index].needhold) {
05195
05196 p->subs[index].needhold = 0;
05197 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05198 p->subs[index].f.subclass = AST_CONTROL_HOLD;
05199 ast_mutex_unlock(&p->lock);
05200 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
05201 return &p->subs[index].f;
05202 }
05203
05204 if (p->subs[index].needunhold) {
05205
05206 p->subs[index].needunhold = 0;
05207 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05208 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
05209 ast_mutex_unlock(&p->lock);
05210 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
05211 return &p->subs[index].f;
05212 }
05213
05214 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05215 if (!p->subs[index].linear) {
05216 p->subs[index].linear = 1;
05217 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05218 if (res)
05219 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
05220 }
05221 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05222 (ast->rawreadformat == AST_FORMAT_ALAW)) {
05223 if (p->subs[index].linear) {
05224 p->subs[index].linear = 0;
05225 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05226 if (res)
05227 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
05228 }
05229 } else {
05230 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05231 ast_mutex_unlock(&p->lock);
05232 return NULL;
05233 }
05234 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
05235 CHECK_BLOCKING(ast);
05236 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05237 ast_clear_flag(ast, AST_FLAG_BLOCKING);
05238
05239 if (res < 0) {
05240 f = NULL;
05241 if (res == -1) {
05242 if (errno == EAGAIN) {
05243
05244 ast_mutex_unlock(&p->lock);
05245 return &p->subs[index].f;
05246 } else if (errno == ELAST) {
05247 f = __dahdi_exception(ast);
05248 } else
05249 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05250 }
05251 ast_mutex_unlock(&p->lock);
05252 return f;
05253 }
05254 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
05255 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05256 f = __dahdi_exception(ast);
05257 ast_mutex_unlock(&p->lock);
05258 return f;
05259 }
05260 if (p->tdd) {
05261 int c;
05262
05263 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05264 if (c < 0) {
05265 ast_log(LOG_DEBUG,"tdd_feed failed\n");
05266 ast_mutex_unlock(&p->lock);
05267 return NULL;
05268 }
05269 if (c) {
05270 p->subs[index].f.subclass = 0;
05271 p->subs[index].f.frametype = AST_FRAME_TEXT;
05272 p->subs[index].f.mallocd = 0;
05273 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05274 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
05275 p->subs[index].f.datalen = 1;
05276 *((char *) p->subs[index].f.data) = c;
05277 ast_mutex_unlock(&p->lock);
05278 return &p->subs[index].f;
05279 }
05280 }
05281
05282 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05283 p->callwaitingrepeat--;
05284 }
05285 if (p->cidcwexpire)
05286 p->cidcwexpire--;
05287
05288 if (p->callwaitingrepeat == 1) {
05289 p->callwaitrings++;
05290 dahdi_callwait(ast);
05291 }
05292
05293 if (p->cidcwexpire == 1) {
05294 if (option_verbose > 2)
05295 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
05296 restore_conference(p);
05297 }
05298 if (p->subs[index].linear) {
05299 p->subs[index].f.datalen = READ_SIZE * 2;
05300 } else
05301 p->subs[index].f.datalen = READ_SIZE;
05302
05303
05304 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05305 send_callerid(p);
05306 }
05307
05308 p->subs[index].f.frametype = AST_FRAME_VOICE;
05309 p->subs[index].f.subclass = ast->rawreadformat;
05310 p->subs[index].f.samples = READ_SIZE;
05311 p->subs[index].f.mallocd = 0;
05312 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05313 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
05314 #if 0
05315 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
05316 #endif
05317 if (p->dialing ||
05318 (index && (ast->_state != AST_STATE_UP)) ||
05319 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05320 ) {
05321
05322
05323 p->subs[index].f.frametype = AST_FRAME_NULL;
05324 p->subs[index].f.subclass = 0;
05325 p->subs[index].f.samples = 0;
05326 p->subs[index].f.mallocd = 0;
05327 p->subs[index].f.offset = 0;
05328 p->subs[index].f.data = NULL;
05329 p->subs[index].f.datalen= 0;
05330 }
05331 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
05332
05333 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05334 if (f) {
05335 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05336 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05337
05338
05339 f = NULL;
05340 }
05341 } else if (f->frametype == AST_FRAME_DTMF) {
05342 #ifdef HAVE_PRI
05343 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
05344
05345 f->frametype = AST_FRAME_NULL;
05346 f->subclass = 0;
05347 }
05348 #endif
05349
05350 p->pulsedial = 0;
05351 }
05352 }
05353 } else
05354 f = &p->subs[index].f;
05355
05356 if (f && (f->frametype == AST_FRAME_DTMF))
05357 dahdi_handle_dtmfup(ast, index, &f);
05358
05359
05360 if (p->fake_event)
05361 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05362
05363 ast_mutex_unlock(&p->lock);
05364 return f;
05365 }
05366
05367 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
05368 {
05369 int sent=0;
05370 int size;
05371 int res;
05372 int fd;
05373 fd = p->subs[index].dfd;
05374 while (len) {
05375 size = len;
05376 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05377 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05378 res = write(fd, buf, size);
05379 if (res != size) {
05380 if (option_debug)
05381 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05382 return sent;
05383 }
05384 len -= size;
05385 buf += size;
05386 }
05387 return sent;
05388 }
05389
05390 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05391 {
05392 struct dahdi_pvt *p = ast->tech_pvt;
05393 int res;
05394 int index;
05395 index = dahdi_get_index(ast, p, 0);
05396 if (index < 0) {
05397 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05398 return -1;
05399 }
05400
05401 #if 0
05402 #ifdef HAVE_PRI
05403 ast_mutex_lock(&p->lock);
05404 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05405 if (p->pri->pri) {
05406 if (!pri_grab(p, p->pri)) {
05407 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05408 pri_rel(p->pri);
05409 } else
05410 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05411 }
05412 p->proceeding=1;
05413 }
05414 ast_mutex_unlock(&p->lock);
05415 #endif
05416 #endif
05417
05418 if (frame->frametype != AST_FRAME_VOICE) {
05419 if (frame->frametype != AST_FRAME_IMAGE)
05420 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05421 return 0;
05422 }
05423 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
05424 (frame->subclass != AST_FORMAT_ULAW) &&
05425 (frame->subclass != AST_FORMAT_ALAW)) {
05426 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05427 return -1;
05428 }
05429 if (p->dialing) {
05430 if (option_debug)
05431 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05432 return 0;
05433 }
05434 if (!p->owner) {
05435 if (option_debug)
05436 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05437 return 0;
05438 }
05439 if (p->cidspill) {
05440 if (option_debug)
05441 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05442 return 0;
05443 }
05444
05445 if (!frame->data || !frame->datalen)
05446 return 0;
05447
05448 if (frame->subclass == AST_FORMAT_SLINEAR) {
05449 if (!p->subs[index].linear) {
05450 p->subs[index].linear = 1;
05451 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05452 if (res)
05453 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05454 }
05455 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05456 } else {
05457
05458 if (p->subs[index].linear) {
05459 p->subs[index].linear = 0;
05460 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05461 if (res)
05462 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05463 }
05464 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05465 }
05466 if (res < 0) {
05467 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05468 return -1;
05469 }
05470 return 0;
05471 }
05472
05473 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
05474 {
05475 struct dahdi_pvt *p = chan->tech_pvt;
05476 int res=-1;
05477 int index;
05478 int func = DAHDI_FLASH;
05479 ast_mutex_lock(&p->lock);
05480 index = dahdi_get_index(chan, p, 0);
05481 if (option_debug)
05482 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05483 if (index == SUB_REAL) {
05484 switch (condition) {
05485 case AST_CONTROL_BUSY:
05486 #ifdef HAVE_PRI
05487 if (p->priindication_oob && p->sig == SIG_PRI) {
05488 chan->hangupcause = AST_CAUSE_USER_BUSY;
05489 chan->_softhangup |= AST_SOFTHANGUP_DEV;
05490 res = 0;
05491 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05492 if (p->pri->pri) {
05493 if (!pri_grab(p, p->pri)) {
05494 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05495 pri_rel(p->pri);
05496 }
05497 else
05498 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05499 }
05500 p->progress = 1;
05501 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05502 } else
05503 #endif
05504 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05505 break;
05506 case AST_CONTROL_RINGING:
05507 #ifdef HAVE_PRI
05508 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05509 if (p->pri->pri) {
05510 if (!pri_grab(p, p->pri)) {
05511 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05512 pri_rel(p->pri);
05513 }
05514 else
05515 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05516 }
05517 p->alerting = 1;
05518 }
05519 #endif
05520 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
05521 if (chan->_state != AST_STATE_UP) {
05522 if ((chan->_state != AST_STATE_RING) ||
05523 ((p->sig != SIG_FXSKS) &&
05524 (p->sig != SIG_FXSLS) &&
05525 (p->sig != SIG_FXSGS)))
05526 ast_setstate(chan, AST_STATE_RINGING);
05527 }
05528 break;
05529 case AST_CONTROL_PROCEEDING:
05530 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05531 #ifdef HAVE_PRI
05532 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05533 if (p->pri->pri) {
05534 if (!pri_grab(p, p->pri)) {
05535 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05536 pri_rel(p->pri);
05537 }
05538 else
05539 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05540 }
05541 p->proceeding = 1;
05542 }
05543 #endif
05544
05545 res = 0;
05546 break;
05547 case AST_CONTROL_PROGRESS:
05548 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05549 #ifdef HAVE_PRI
05550 p->digital = 0;
05551 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05552 if (p->pri->pri) {
05553 if (!pri_grab(p, p->pri)) {
05554 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05555 pri_rel(p->pri);
05556 }
05557 else
05558 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05559 }
05560 p->progress = 1;
05561 }
05562 #endif
05563
05564 res = 0;
05565 break;
05566 case AST_CONTROL_CONGESTION:
05567 chan->hangupcause = AST_CAUSE_CONGESTION;
05568 #ifdef HAVE_PRI
05569 if (p->priindication_oob && p->sig == SIG_PRI) {
05570 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05571 chan->_softhangup |= AST_SOFTHANGUP_DEV;
05572 res = 0;
05573 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05574 if (p->pri) {
05575 if (!pri_grab(p, p->pri)) {
05576 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05577 pri_rel(p->pri);
05578 } else
05579 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05580 }
05581 p->progress = 1;
05582 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05583 } else
05584 #endif
05585 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05586 break;
05587 case AST_CONTROL_HOLD:
05588 #ifdef HAVE_PRI
05589 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05590 if (!pri_grab(p, p->pri)) {
05591 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05592 pri_rel(p->pri);
05593 } else
05594 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05595 } else
05596 #endif
05597 ast_moh_start(chan, data, p->mohinterpret);
05598 break;
05599 case AST_CONTROL_UNHOLD:
05600 #ifdef HAVE_PRI
05601 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05602 if (!pri_grab(p, p->pri)) {
05603 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05604 pri_rel(p->pri);
05605 } else
05606 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05607 } else
05608 #endif
05609 ast_moh_stop(chan);
05610 break;
05611 case AST_CONTROL_RADIO_KEY:
05612 if (p->radio)
05613 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05614 res = 0;
05615 break;
05616 case AST_CONTROL_RADIO_UNKEY:
05617 if (p->radio)
05618 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
05619 res = 0;
05620 break;
05621 case AST_CONTROL_FLASH:
05622
05623 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05624
05625 p->dop.dialstr[0] = '\0';
05626 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05627 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
05628 chan->name, strerror(errno));
05629 } else
05630 res = 0;
05631 } else
05632 res = 0;
05633 break;
05634 case AST_CONTROL_SRCUPDATE:
05635 res = 0;
05636 break;
05637 case -1:
05638 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05639 break;
05640 }
05641 } else
05642 res = 0;
05643 ast_mutex_unlock(&p->lock);
05644 return res;
05645 }
05646
05647 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
05648 {
05649 struct ast_channel *tmp;
05650 int deflaw;
05651 int res;
05652 int x,y;
05653 int features;
05654 char *b2 = NULL;
05655 struct dahdi_params ps;
05656 char chanprefix[*dahdi_chan_name_len + 4];
05657
05658 if (i->subs[index].owner) {
05659 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05660 return NULL;
05661 }
05662 y = 1;
05663 do {
05664 if (b2)
05665 free(b2);
05666 #ifdef HAVE_PRI
05667 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05668 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05669 else
05670 #endif
05671 if (i->channel == CHAN_PSEUDO)
05672 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05673 else
05674 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05675 for (x = 0; x < 3; x++) {
05676 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
05677 break;
05678 }
05679 y++;
05680 } while (x < 3);
05681 strcpy(chanprefix, dahdi_chan_name);
05682 strcat(chanprefix, "/%s");
05683 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
05684 if (b2)
05685 free(b2);
05686 if (!tmp)
05687 return NULL;
05688 tmp->tech = chan_tech;
05689 ps.channo = i->channel;
05690 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
05691 if (res) {
05692 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
05693 ps.curlaw = DAHDI_LAW_MULAW;
05694 }
05695 if (ps.curlaw == DAHDI_LAW_ALAW)
05696 deflaw = AST_FORMAT_ALAW;
05697 else
05698 deflaw = AST_FORMAT_ULAW;
05699 if (law) {
05700 if (law == DAHDI_LAW_ALAW)
05701 deflaw = AST_FORMAT_ALAW;
05702 else
05703 deflaw = AST_FORMAT_ULAW;
05704 }
05705 tmp->fds[0] = i->subs[index].dfd;
05706 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05707
05708 tmp->rawreadformat = deflaw;
05709 tmp->readformat = deflaw;
05710 tmp->rawwriteformat = deflaw;
05711 tmp->writeformat = deflaw;
05712 i->subs[index].linear = 0;
05713 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
05714 features = 0;
05715 if (index == SUB_REAL) {
05716 if (i->busydetect && CANBUSYDETECT(i))
05717 features |= DSP_FEATURE_BUSY_DETECT;
05718 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05719 features |= DSP_FEATURE_CALL_PROGRESS;
05720 if ((!i->outgoing && (i->callprogress & 4)) ||
05721 (i->outgoing && (i->callprogress & 2))) {
05722 features |= DSP_FEATURE_FAX_DETECT;
05723 }
05724 #ifdef DAHDI_TONEDETECT
05725 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05726 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
05727 #endif
05728 i->hardwaredtmf = 0;
05729 features |= DSP_FEATURE_DTMF_DETECT;
05730 #ifdef DAHDI_TONEDETECT
05731 } else if (NEED_MFDETECT(i)) {
05732 i->hardwaredtmf = 1;
05733 features |= DSP_FEATURE_DTMF_DETECT;
05734 }
05735 #endif
05736 }
05737 if (features) {
05738 if (i->dsp) {
05739 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05740 } else {
05741 if (i->channel != CHAN_PSEUDO)
05742 i->dsp = ast_dsp_new();
05743 else
05744 i->dsp = NULL;
05745 if (i->dsp) {
05746 i->dsp_features = features;
05747 #ifdef HAVE_PRI
05748
05749 if (i->outgoing && (i->sig == SIG_PRI)) {
05750
05751
05752 i->dsp_features = features & ~DSP_PROGRESS_TALK;
05753 features = 0;
05754 }
05755 #endif
05756 ast_dsp_set_features(i->dsp, features);
05757 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05758 if (!ast_strlen_zero(progzone))
05759 ast_dsp_set_call_progress_zone(i->dsp, progzone);
05760 if (i->busydetect && CANBUSYDETECT(i)) {
05761 if(i->silencethreshold > 0)
05762 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
05763 ast_dsp_set_busy_count(i->dsp, i->busycount);
05764 if(i->busytonelength > 0)
05765 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
05766 if((i->busytonelength == i->busyquietlength) && i->busycompare)
05767 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
05768 }
05769 }
05770 }
05771 }
05772
05773 if (state == AST_STATE_RING)
05774 tmp->rings = 1;
05775 tmp->tech_pvt = i;
05776 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05777
05778 tmp->callgroup = i->callgroup;
05779 tmp->pickupgroup = i->pickupgroup;
05780 }
05781 if (!ast_strlen_zero(i->language))
05782 ast_string_field_set(tmp, language, i->language);
05783 if (!i->owner)
05784 i->owner = tmp;
05785 if (!ast_strlen_zero(i->accountcode))
05786 ast_string_field_set(tmp, accountcode, i->accountcode);
05787 if (i->amaflags)
05788 tmp->amaflags = i->amaflags;
05789 i->subs[index].owner = tmp;
05790 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05791 ast_string_field_set(tmp, call_forward, i->call_forward);
05792
05793 if (!i->adsi)
05794 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05795 if (!ast_strlen_zero(i->exten))
05796 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05797 if (!ast_strlen_zero(i->rdnis))
05798 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05799 if (!ast_strlen_zero(i->dnid))
05800 tmp->cid.cid_dnid = ast_strdup(i->dnid);
05801
05802
05803
05804 #ifdef PRI_ANI
05805 if (!ast_strlen_zero(i->cid_ani))
05806 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05807 else
05808 tmp->cid.cid_ani = ast_strdup(i->cid_num);
05809 #else
05810 tmp->cid.cid_ani = ast_strdup(i->cid_num);
05811 #endif
05812 tmp->cid.cid_pres = i->callingpres;
05813 tmp->cid.cid_ton = i->cid_ton;
05814 #ifdef HAVE_PRI
05815 tmp->transfercapability = transfercapability;
05816 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05817 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05818 i->digital = 1;
05819
05820 i->isidlecall = 0;
05821 i->alreadyhungup = 0;
05822 #endif
05823
05824 i->fake_event = 0;
05825
05826 dahdi_confmute(i, 0);
05827
05828 ast_jb_configure(tmp, &global_jbconf);
05829 if (startpbx) {
05830 if (ast_pbx_start(tmp)) {
05831 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05832 ast_hangup(tmp);
05833 i->owner = NULL;
05834 return NULL;
05835 }
05836 }
05837
05838 ast_module_ref(ast_module_info->self);
05839
05840 return tmp;
05841 }
05842
05843
05844 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
05845 {
05846 char c;
05847
05848 *str = 0;
05849 for (;;)
05850 {
05851
05852 c = ast_waitfordigit(chan, ms);
05853
05854 if (c < 1)
05855 return c;
05856 *str++ = c;
05857 *str = 0;
05858 if (strchr(term, c))
05859 return 1;
05860 }
05861 }
05862
05863 static int dahdi_wink(struct dahdi_pvt *p, int index)
05864 {
05865 int j;
05866 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
05867 for (;;)
05868 {
05869
05870 j = DAHDI_IOMUX_SIGEVENT;
05871
05872 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
05873
05874 if (j & DAHDI_IOMUX_SIGEVENT) break;
05875 }
05876
05877 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
05878 return 0;
05879 }
05880
05881 static void *ss_thread(void *data)
05882 {
05883 struct ast_channel *chan = data;
05884 struct dahdi_pvt *p = chan->tech_pvt;
05885 char exten[AST_MAX_EXTENSION] = "";
05886 char exten2[AST_MAX_EXTENSION] = "";
05887 unsigned char buf[256];
05888 char dtmfcid[300];
05889 char dtmfbuf[300];
05890 struct callerid_state *cs = NULL;
05891 char *name = NULL, *number = NULL;
05892 int distMatches;
05893 int curRingData[3];
05894 int receivedRingT;
05895 int counter1;
05896 int counter;
05897 int samples = 0;
05898 struct ast_smdi_md_message *smdi_msg = NULL;
05899 int flags;
05900 int i;
05901 int timeout;
05902 int getforward = 0;
05903 char *s1, *s2;
05904 int len = 0;
05905 int res;
05906 int index;
05907
05908 ast_mutex_lock(&ss_thread_lock);
05909 ss_thread_count++;
05910 ast_mutex_unlock(&ss_thread_lock);
05911
05912
05913
05914 if (!p) {
05915 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05916 ast_hangup(chan);
05917 goto quit;
05918 }
05919 if (option_verbose > 2)
05920 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05921 index = dahdi_get_index(chan, p, 1);
05922 if (index < 0) {
05923 ast_log(LOG_WARNING, "Huh?\n");
05924 ast_hangup(chan);
05925 goto quit;
05926 }
05927 if (p->dsp)
05928 ast_dsp_digitreset(p->dsp);
05929 switch (p->sig) {
05930 #ifdef HAVE_PRI
05931 case SIG_PRI:
05932
05933 ast_copy_string(exten, p->exten, sizeof(exten));
05934 len = strlen(exten);
05935 res = 0;
05936 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05937 if (len && !ast_ignore_pattern(chan->context, exten))
05938 tone_zone_play_tone(p->subs[index].dfd, -1);
05939 else
05940 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05941 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05942 timeout = matchdigittimeout;
05943 else
05944 timeout = gendigittimeout;
05945 res = ast_waitfordigit(chan, timeout);
05946 if (res < 0) {
05947 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05948 ast_hangup(chan);
05949 goto quit;
05950 } else if (res) {
05951 exten[len++] = res;
05952 exten[len] = '\0';
05953 } else
05954 break;
05955 }
05956
05957 if (ast_strlen_zero(exten)) {
05958 if (option_verbose > 2)
05959 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05960 exten[0] = 's';
05961 exten[1] = '\0';
05962 }
05963 tone_zone_play_tone(p->subs[index].dfd, -1);
05964 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05965
05966 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05967 if (p->dsp) ast_dsp_digitreset(p->dsp);
05968 dahdi_enable_ec(p);
05969 ast_setstate(chan, AST_STATE_RING);
05970 res = ast_pbx_run(chan);
05971 if (res) {
05972 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05973 }
05974 } else {
05975 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05976 chan->hangupcause = AST_CAUSE_UNALLOCATED;
05977 ast_hangup(chan);
05978 p->exten[0] = '\0';
05979
05980 p->call = NULL;
05981 }
05982 goto quit;
05983 break;
05984 #endif
05985 case SIG_FEATD:
05986 case SIG_FEATDMF:
05987 case SIG_FEATDMF_TA:
05988 case SIG_E911:
05989 case SIG_FGC_CAMAMF:
05990 case SIG_FEATB:
05991 case SIG_EMWINK:
05992 case SIG_SF_FEATD:
05993 case SIG_SF_FEATDMF:
05994 case SIG_SF_FEATB:
05995 case SIG_SFWINK:
05996 if (dahdi_wink(p, index))
05997 goto quit;
05998
05999 case SIG_EM:
06000 case SIG_EM_E1:
06001 case SIG_SF:
06002 case SIG_FGC_CAMA:
06003 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06004 if (p->dsp)
06005 ast_dsp_digitreset(p->dsp);
06006
06007 if (p->dsp) {
06008 if (NEED_MFDETECT(p))
06009 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06010 else
06011 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06012 }
06013 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06014
06015 if (!p->immediate)
06016
06017 res = ast_waitfordigit(chan, 5000);
06018 else
06019 res = 0;
06020 if (res > 0) {
06021
06022 dtmfbuf[0] = res;
06023 switch (p->sig) {
06024 case SIG_FEATD:
06025 case SIG_SF_FEATD:
06026 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06027 if (res > 0)
06028 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06029 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06030 break;
06031 case SIG_FEATDMF_TA:
06032 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06033 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06034 if (dahdi_wink(p, index)) goto quit;
06035 dtmfbuf[0] = 0;
06036
06037 res = ast_waitfordigit(chan, 5000);
06038 if (res <= 0) break;
06039 dtmfbuf[0] = res;
06040
06041 case SIG_FEATDMF:
06042 case SIG_E911:
06043 case SIG_FGC_CAMAMF:
06044 case SIG_SF_FEATDMF:
06045 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06046
06047 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06048 {
06049 if (dahdi_wink(p, index)) goto quit;
06050 dtmfbuf[0] = 0;
06051
06052 res = ast_waitfordigit(chan, 5000);
06053 if (res <= 0) break;
06054 dtmfbuf[0] = res;
06055 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06056 }
06057 if (res > 0) {
06058
06059 if (p->sig == SIG_E911)
06060 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06061 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06062 }
06063 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06064 break;
06065 case SIG_FEATB:
06066 case SIG_SF_FEATB:
06067 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06068 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06069 break;
06070 case SIG_EMWINK:
06071
06072
06073
06074
06075 if (res == '*') {
06076 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06077 if (res > 0)
06078 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06079 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06080 break;
06081 }
06082 default:
06083
06084 len = 1;
06085 dtmfbuf[len] = '\0';
06086 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06087 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06088 timeout = matchdigittimeout;
06089 } else {
06090 timeout = gendigittimeout;
06091 }
06092 res = ast_waitfordigit(chan, timeout);
06093 if (res < 0) {
06094 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06095 ast_hangup(chan);
06096 goto quit;
06097 } else if (res) {
06098 dtmfbuf[len++] = res;
06099 dtmfbuf[len] = '\0';
06100 } else {
06101 break;
06102 }
06103 }
06104 break;
06105 }
06106 }
06107 if (res == -1) {
06108 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06109 ast_hangup(chan);
06110 goto quit;
06111 } else if (res < 0) {
06112 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06113 ast_hangup(chan);
06114 goto quit;
06115 }
06116
06117 if (p->sig == SIG_FGC_CAMA) {
06118 char anibuf[100];
06119
06120 if (ast_safe_sleep(chan,1000) == -1) {
06121 ast_hangup(chan);
06122 goto quit;
06123 }
06124 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06125 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06126 res = my_getsigstr(chan, anibuf, "#", 10000);
06127 if ((res > 0) && (strlen(anibuf) > 2)) {
06128 if (anibuf[strlen(anibuf) - 1] == '#')
06129 anibuf[strlen(anibuf) - 1] = 0;
06130 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06131 }
06132 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06133 }
06134
06135 ast_copy_string(exten, dtmfbuf, sizeof(exten));
06136 if (ast_strlen_zero(exten))
06137 ast_copy_string(exten, "s", sizeof(exten));
06138 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06139
06140 if (exten[0] == '*') {
06141 char *stringp=NULL;
06142 ast_copy_string(exten2, exten, sizeof(exten2));
06143
06144 stringp=exten2 +1;
06145 s1 = strsep(&stringp, "*");
06146 s2 = strsep(&stringp, "*");
06147 if (s2) {
06148 if (!ast_strlen_zero(p->cid_num))
06149 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06150 else
06151 ast_set_callerid(chan, s1, NULL, s1);
06152 ast_copy_string(exten, s2, sizeof(exten));
06153 } else
06154 ast_copy_string(exten, s1, sizeof(exten));
06155 } else if (p->sig == SIG_FEATD)
06156 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06157 }
06158 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06159 if (exten[0] == '*') {
06160 char *stringp=NULL;
06161 ast_copy_string(exten2, exten, sizeof(exten2));
06162
06163 stringp=exten2 +1;
06164 s1 = strsep(&stringp, "#");
06165 s2 = strsep(&stringp, "#");
06166 if (s2) {
06167 if (!ast_strlen_zero(p->cid_num))
06168 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06169 else
06170 if (*(s1 + 2))
06171 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06172 ast_copy_string(exten, s2 + 1, sizeof(exten));
06173 } else
06174 ast_copy_string(exten, s1 + 2, sizeof(exten));
06175 } else
06176 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06177 }
06178 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06179 if (exten[0] == '*') {
06180 char *stringp=NULL;
06181 ast_copy_string(exten2, exten, sizeof(exten2));
06182
06183 stringp=exten2 +1;
06184 s1 = strsep(&stringp, "#");
06185 s2 = strsep(&stringp, "#");
06186 if (s2 && (*(s2 + 1) == '0')) {
06187 if (*(s2 + 2))
06188 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06189 }
06190 if (s1) ast_copy_string(exten, s1, sizeof(exten));
06191 else ast_copy_string(exten, "911", sizeof(exten));
06192 } else
06193 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
06194 }
06195 if (p->sig == SIG_FEATB) {
06196 if (exten[0] == '*') {
06197 char *stringp=NULL;
06198 ast_copy_string(exten2, exten, sizeof(exten2));
06199
06200 stringp=exten2 +1;
06201 s1 = strsep(&stringp, "#");
06202 ast_copy_string(exten, exten2 + 1, sizeof(exten));
06203 } else
06204 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
06205 }
06206 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06207 dahdi_wink(p, index);
06208
06209
06210
06211 if (ast_safe_sleep(chan,100)) goto quit;
06212 }
06213 dahdi_enable_ec(p);
06214 if (NEED_MFDETECT(p)) {
06215 if (p->dsp) {
06216 if (!p->hardwaredtmf)
06217 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06218 else {
06219 ast_dsp_free(p->dsp);
06220 p->dsp = NULL;
06221 }
06222 }
06223 }
06224
06225 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06226 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06227 if (p->dsp) ast_dsp_digitreset(p->dsp);
06228 res = ast_pbx_run(chan);
06229 if (res) {
06230 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06231 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06232 }
06233 goto quit;
06234 } else {
06235 if (option_verbose > 2)
06236 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06237 sleep(2);
06238 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
06239 if (res < 0)
06240 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06241 else
06242 sleep(1);
06243 res = ast_streamfile(chan, "ss-noservice", chan->language);
06244 if (res >= 0)
06245 ast_waitstream(chan, "");
06246 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06247 ast_hangup(chan);
06248 goto quit;
06249 }
06250 break;
06251 case SIG_FXOLS:
06252 case SIG_FXOGS:
06253 case SIG_FXOKS:
06254
06255 timeout = firstdigittimeout;
06256
06257
06258 if (p->subs[SUB_THREEWAY].owner)
06259 timeout = 999999;
06260 while (len < AST_MAX_EXTENSION-1) {
06261
06262
06263 if (p->immediate)
06264 res = 's';
06265 else
06266 res = ast_waitfordigit(chan, timeout);
06267 timeout = 0;
06268 if (res < 0) {
06269 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06270 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06271 ast_hangup(chan);
06272 goto quit;
06273 } else if (res) {
06274 exten[len++]=res;
06275 exten[len] = '\0';
06276 }
06277 if (!ast_ignore_pattern(chan->context, exten))
06278 tone_zone_play_tone(p->subs[index].dfd, -1);
06279 else
06280 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06281 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06282 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06283 if (getforward) {
06284
06285 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
06286 if (option_verbose > 2)
06287 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06288 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06289 if (res)
06290 break;
06291 usleep(500000);
06292 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06293 sleep(1);
06294 memset(exten, 0, sizeof(exten));
06295 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06296 len = 0;
06297 getforward = 0;
06298 } else {
06299 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06300 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06301 if (!ast_strlen_zero(p->cid_num)) {
06302 if (!p->hidecallerid)
06303 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06304 else
06305 ast_set_callerid(chan, NULL, NULL, p->cid_num);
06306 }
06307 if (!ast_strlen_zero(p->cid_name)) {
06308 if (!p->hidecallerid)
06309 ast_set_callerid(chan, NULL, p->cid_name, NULL);
06310 }
06311 ast_setstate(chan, AST_STATE_RING);
06312 dahdi_enable_ec(p);
06313 res = ast_pbx_run(chan);
06314 if (res) {
06315 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06316 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06317 }
06318 goto quit;
06319 }
06320 } else {
06321
06322
06323 timeout = matchdigittimeout;
06324 }
06325 } else if (res == 0) {
06326 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
06327 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06328 dahdi_wait_event(p->subs[index].dfd);
06329 ast_hangup(chan);
06330 goto quit;
06331 } else if (p->callwaiting && !strcmp(exten, "*70")) {
06332 if (option_verbose > 2)
06333 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
06334
06335 p->callwaiting = 0;
06336 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06337 if (res) {
06338 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06339 chan->name, strerror(errno));
06340 }
06341 len = 0;
06342 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06343 memset(exten, 0, sizeof(exten));
06344 timeout = firstdigittimeout;
06345
06346 } else if (!strcmp(exten,ast_pickup_ext())) {
06347
06348
06349
06350
06351 if (index == SUB_REAL) {
06352
06353 if (p->subs[SUB_THREEWAY].owner) {
06354
06355
06356 alloc_sub(p, SUB_CALLWAIT);
06357 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06358 unalloc_sub(p, SUB_THREEWAY);
06359 }
06360 dahdi_enable_ec(p);
06361 if (ast_pickup_call(chan)) {
06362 ast_log(LOG_DEBUG, "No call pickup possible...\n");
06363 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06364 dahdi_wait_event(p->subs[index].dfd);
06365 }
06366 ast_hangup(chan);
06367 goto quit;
06368 } else {
06369 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
06370 ast_hangup(chan);
06371 goto quit;
06372 }
06373
06374 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
06375 if (option_verbose > 2)
06376 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
06377
06378 p->hidecallerid = 1;
06379 if (chan->cid.cid_num)
06380 free(chan->cid.cid_num);
06381 chan->cid.cid_num = NULL;
06382 if (chan->cid.cid_name)
06383 free(chan->cid.cid_name);
06384 chan->cid.cid_name = NULL;
06385 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06386 if (res) {
06387 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06388 chan->name, strerror(errno));
06389 }
06390 len = 0;
06391 memset(exten, 0, sizeof(exten));
06392 timeout = firstdigittimeout;
06393 } else if (p->callreturn && !strcmp(exten, "*69")) {
06394 res = 0;
06395 if (!ast_strlen_zero(p->lastcid_num)) {
06396 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
06397 }
06398 if (!res)
06399 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06400 break;
06401 } else if (!strcmp(exten, "*78")) {
06402
06403 if (option_verbose > 2)
06404 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
06405 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06406 "Channel: %s/%d\r\n"
06407 "Status: enabled\r\n", dahdi_chan_name, p->channel);
06408 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06409 p->dnd = 1;
06410 getforward = 0;
06411 memset(exten, 0, sizeof(exten));
06412 len = 0;
06413 } else if (!strcmp(exten, "*79")) {
06414
06415 if (option_verbose > 2)
06416 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
06417 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06418 "Channel: %s/%d\r\n"
06419 "Status: disabled\r\n", dahdi_chan_name, p->channel);
06420 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06421 p->dnd = 0;
06422 getforward = 0;
06423 memset(exten, 0, sizeof(exten));
06424 len = 0;
06425 } else if (p->cancallforward && !strcmp(exten, "*72")) {
06426 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06427 getforward = 1;
06428 memset(exten, 0, sizeof(exten));
06429 len = 0;
06430 } else if (p->cancallforward && !strcmp(exten, "*73")) {
06431 if (option_verbose > 2)
06432 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
06433 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06434 memset(p->call_forward, 0, sizeof(p->call_forward));
06435 getforward = 0;
06436 memset(exten, 0, sizeof(exten));
06437 len = 0;
06438 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
06439 p->subs[SUB_THREEWAY].owner &&
06440 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06441
06442
06443 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
06444 if (option_verbose > 2)
06445 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
06446 break;
06447 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
06448 if (option_verbose > 2)
06449 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
06450 res = ast_db_put("blacklist", p->lastcid_num, "1");
06451 if (!res) {
06452 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06453 memset(exten, 0, sizeof(exten));
06454 len = 0;
06455 }
06456 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
06457 if (option_verbose > 2)
06458 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
06459
06460 p->hidecallerid = 0;
06461 if (chan->cid.cid_num)
06462 free(chan->cid.cid_num);
06463 chan->cid.cid_num = NULL;
06464 if (chan->cid.cid_name)
06465 free(chan->cid.cid_name);
06466 chan->cid.cid_name = NULL;
06467 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
06468 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06469 if (res) {
06470 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06471 chan->name, strerror(errno));
06472 }
06473 len = 0;
06474 memset(exten, 0, sizeof(exten));
06475 timeout = firstdigittimeout;
06476 } else if (!strcmp(exten, "*0")) {
06477 struct ast_channel *nbridge =
06478 p->subs[SUB_THREEWAY].owner;
06479 struct dahdi_pvt *pbridge = NULL;
06480
06481 if (nbridge && ast_bridged_channel(nbridge))
06482 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06483 if (nbridge && pbridge &&
06484 (nbridge->tech == chan_tech) &&
06485 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
06486 ISTRUNK(pbridge)) {
06487 int func = DAHDI_FLASH;
06488
06489 p->dop.dialstr[0] = '\0';
06490
06491 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06492 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06493 nbridge->name, strerror(errno));
06494 }
06495 swap_subs(p, SUB_REAL, SUB_THREEWAY);
06496 unalloc_sub(p, SUB_THREEWAY);
06497 p->owner = p->subs[SUB_REAL].owner;
06498 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06499 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06500 ast_hangup(chan);
06501 goto quit;
06502 } else {
06503 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06504 dahdi_wait_event(p->subs[index].dfd);
06505 tone_zone_play_tone(p->subs[index].dfd, -1);
06506 swap_subs(p, SUB_REAL, SUB_THREEWAY);
06507 unalloc_sub(p, SUB_THREEWAY);
06508 p->owner = p->subs[SUB_REAL].owner;
06509 ast_hangup(chan);
06510 goto quit;
06511 }
06512 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06513 ((exten[0] != '*') || (strlen(exten) > 2))) {
06514 if (option_debug)
06515 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
06516 break;
06517 }
06518 if (!timeout)
06519 timeout = gendigittimeout;
06520 if (len && !ast_ignore_pattern(chan->context, exten))
06521 tone_zone_play_tone(p->subs[index].dfd, -1);
06522 }
06523 break;
06524 case SIG_FXSLS:
06525 case SIG_FXSGS:
06526 case SIG_FXSKS:
06527 #ifdef HAVE_PRI
06528 if (p->pri) {
06529
06530 struct ast_frame *f;
06531 int res;
06532 time_t start;
06533
06534 time(&start);
06535 ast_setstate(chan, AST_STATE_RING);
06536 while (time(NULL) < start + 3) {
06537 res = ast_waitfor(chan, 1000);
06538 if (res) {
06539 f = ast_read(chan);
06540 if (!f) {
06541 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06542 ast_hangup(chan);
06543 goto quit;
06544 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06545 res = 1;
06546 } else
06547 res = 0;
06548 ast_frfree(f);
06549 if (res) {
06550 ast_log(LOG_DEBUG, "Got ring!\n");
06551 res = 0;
06552 break;
06553 }
06554 }
06555 }
06556 }
06557 #endif
06558
06559 if (p->use_smdi && p->smdi_iface) {
06560 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06561
06562 if (smdi_msg != NULL) {
06563 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06564
06565 if (smdi_msg->type == 'B')
06566 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06567 else if (smdi_msg->type == 'N')
06568 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06569
06570 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06571 } else {
06572 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06573 }
06574 }
06575
06576 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06577 number = smdi_msg->calling_st;
06578
06579
06580
06581
06582 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06583
06584 if (p->cid_signalling == CID_SIG_DTMF) {
06585 int i = 0;
06586 cs = NULL;
06587 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06588 "channel %s\n", chan->name);
06589 dahdi_setlinear(p->subs[index].dfd, 0);
06590 res = 2000;
06591 for (;;) {
06592 struct ast_frame *f;
06593 res = ast_waitfor(chan, res);
06594 if (res <= 0) {
06595 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06596 "Exiting simple switch\n");
06597 ast_hangup(chan);
06598 goto quit;
06599 }
06600 f = ast_read(chan);
06601 if (!f)
06602 break;
06603 if (f->frametype == AST_FRAME_DTMF) {
06604 dtmfbuf[i++] = f->subclass;
06605 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06606 res = 2000;
06607 }
06608 ast_frfree(f);
06609 if (chan->_state == AST_STATE_RING ||
06610 chan->_state == AST_STATE_RINGING)
06611 break;
06612 }
06613 dtmfbuf[i] = '\0';
06614 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06615
06616 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06617 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06618 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
06619 dtmfcid, flags);
06620
06621 if (!ast_strlen_zero(dtmfcid))
06622 number = dtmfcid;
06623 else
06624 number = NULL;
06625
06626 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06627 cs = callerid_new(p->cid_signalling);
06628 if (cs) {
06629 samples = 0;
06630 #if 1
06631 bump_gains(p);
06632 #endif
06633
06634 dahdi_setlinear(p->subs[index].dfd, 0);
06635
06636
06637 for (;;) {
06638 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06639 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06640 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06641 callerid_free(cs);
06642 ast_hangup(chan);
06643 goto quit;
06644 }
06645 if (i & DAHDI_IOMUX_SIGEVENT) {
06646 res = dahdi_get_event(p->subs[index].dfd);
06647 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06648
06649 if (p->cid_signalling == CID_SIG_V23_JP) {
06650 #ifdef DAHDI_EVENT_RINGBEGIN
06651 if (res == DAHDI_EVENT_RINGBEGIN) {
06652 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06653 usleep(1);
06654 }
06655 #endif
06656 } else {
06657 res = 0;
06658 break;
06659 }
06660 } else if (i & DAHDI_IOMUX_READ) {
06661 res = read(p->subs[index].dfd, buf, sizeof(buf));
06662 if (res < 0) {
06663 if (errno != ELAST) {
06664 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06665 callerid_free(cs);
06666 ast_hangup(chan);
06667 goto quit;
06668 }
06669 break;
06670 }
06671 samples += res;
06672
06673 if (p->cid_signalling == CID_SIG_V23_JP) {
06674 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06675 } else {
06676 res = callerid_feed(cs, buf, res, AST_LAW(p));
06677 }
06678
06679 if (res < 0) {
06680 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
06681 break;
06682 } else if (res)
06683 break;
06684 else if (samples > (8000 * 10))
06685 break;
06686 }
06687 }
06688 if (res == 1) {
06689 callerid_get(cs, &name, &number, &flags);
06690 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06691 }
06692
06693 if (p->cid_signalling == CID_SIG_V23_JP) {
06694 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06695 usleep(1);
06696 res = 4000;
06697 } else {
06698
06699
06700 res = 2000;
06701 }
06702
06703 for (;;) {
06704 struct ast_frame *f;
06705 res = ast_waitfor(chan, res);
06706 if (res <= 0) {
06707 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06708 "Exiting simple switch\n");
06709 ast_hangup(chan);
06710 goto quit;
06711 }
06712 if (!(f = ast_read(chan))) {
06713 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
06714 ast_hangup(chan);
06715 goto quit;
06716 }
06717 ast_frfree(f);
06718 if (chan->_state == AST_STATE_RING ||
06719 chan->_state == AST_STATE_RINGING)
06720 break;
06721 }
06722
06723
06724
06725 if (p->usedistinctiveringdetection) {
06726 len = 0;
06727 distMatches = 0;
06728
06729 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06730 curRingData[receivedRingT] = 0;
06731 receivedRingT = 0;
06732 counter = 0;
06733 counter1 = 0;
06734
06735 if (strcmp(p->context,p->defcontext) != 0) {
06736 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06737 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06738 }
06739
06740 for (;;) {
06741 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06742 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06743 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06744 callerid_free(cs);
06745 ast_hangup(chan);
06746 goto quit;
06747 }
06748 if (i & DAHDI_IOMUX_SIGEVENT) {
06749 res = dahdi_get_event(p->subs[index].dfd);
06750 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06751 res = 0;
06752
06753
06754 curRingData[receivedRingT] = p->ringt;
06755
06756 if (p->ringt < p->ringt_base/2)
06757 break;
06758
06759
06760 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06761 break;
06762 } else if (i & DAHDI_IOMUX_READ) {
06763 res = read(p->subs[index].dfd, buf, sizeof(buf));
06764 if (res < 0) {
06765 if (errno != ELAST) {
06766 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06767 callerid_free(cs);
06768 ast_hangup(chan);
06769 goto quit;
06770 }
06771 break;
06772 }
06773 if (p->ringt)
06774 p->ringt--;
06775 if (p->ringt == 1) {
06776 res = -1;
06777 break;
06778 }
06779 }
06780 }
06781 if (option_verbose > 2)
06782
06783 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06784
06785 for (counter = 0; counter < 3; counter++) {
06786
06787
06788 distMatches = 0;
06789 for (counter1 = 0; counter1 < 3; counter1++) {
06790 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06791 (p->drings.ringnum[counter].ring[counter1]-10)) {
06792 distMatches++;
06793 }
06794 }
06795 if (distMatches == 3) {
06796
06797 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06798 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06799 if (option_verbose > 2)
06800 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06801 break;
06802 }
06803 }
06804 }
06805
06806 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06807 #if 1
06808 restore_gains(p);
06809 #endif
06810 } else
06811 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06812 } else {
06813 ast_log(LOG_WARNING, "Channel %s in prering "
06814 "state, but I have nothing to do. "
06815 "Terminating simple switch, should be "
06816 "restarted by the actual ring.\n",
06817 chan->name);
06818 ast_hangup(chan);
06819 goto quit;
06820 }
06821 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06822
06823 cs = callerid_new(p->cid_signalling);
06824 if (cs) {
06825 #if 1
06826 bump_gains(p);
06827 #endif
06828 samples = 0;
06829 len = 0;
06830 distMatches = 0;
06831
06832 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06833 curRingData[receivedRingT] = 0;
06834 receivedRingT = 0;
06835 counter = 0;
06836 counter1 = 0;
06837
06838 if (strcmp(p->context,p->defcontext) != 0) {
06839 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06840 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06841 }
06842
06843
06844 dahdi_setlinear(p->subs[index].dfd, 0);
06845 for (;;) {
06846 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06847 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06848 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06849 callerid_free(cs);
06850 ast_hangup(chan);
06851 goto quit;
06852 }
06853 if (i & DAHDI_IOMUX_SIGEVENT) {
06854 res = dahdi_get_event(p->subs[index].dfd);
06855 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06856
06857 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
06858 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
06859 p->polarity = POLARITY_IDLE;
06860 callerid_free(cs);
06861 ast_hangup(chan);
06862 goto quit;
06863 }
06864 res = 0;
06865
06866
06867 curRingData[receivedRingT] = p->ringt;
06868
06869 if (p->ringt < p->ringt_base/2)
06870 break;
06871
06872
06873 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06874 break;
06875 } else if (i & DAHDI_IOMUX_READ) {
06876 res = read(p->subs[index].dfd, buf, sizeof(buf));
06877 if (res < 0) {
06878 if (errno != ELAST) {
06879 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06880 callerid_free(cs);
06881 ast_hangup(chan);
06882 goto quit;
06883 }
06884 break;
06885 }
06886 if (p->ringt)
06887 p->ringt--;
06888 if (p->ringt == 1) {
06889 res = -1;
06890 break;
06891 }
06892 samples += res;
06893 res = callerid_feed(cs, buf, res, AST_LAW(p));
06894 if (res < 0) {
06895 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06896 break;
06897 } else if (res)
06898 break;
06899 else if (samples > (8000 * 10))
06900 break;
06901 }
06902 }
06903 if (res == 1) {
06904 callerid_get(cs, &name, &number, &flags);
06905 if (option_debug)
06906 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06907 }
06908 if (distinctiveringaftercid == 1) {
06909
06910 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06911 curRingData[receivedRingT] = 0;
06912 }
06913 receivedRingT = 0;
06914 if (option_verbose > 2)
06915 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06916 for (;;) {
06917 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06918 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06919 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06920 callerid_free(cs);
06921 ast_hangup(chan);
06922 goto quit;
06923 }
06924 if (i & DAHDI_IOMUX_SIGEVENT) {
06925 res = dahdi_get_event(p->subs[index].dfd);
06926 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06927 res = 0;
06928
06929
06930 curRingData[receivedRingT] = p->ringt;
06931
06932 if (p->ringt < p->ringt_base/2)
06933 break;
06934
06935
06936 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06937 break;
06938 } else if (i & DAHDI_IOMUX_READ) {
06939 res = read(p->subs[index].dfd, buf, sizeof(buf));
06940 if (res < 0) {
06941 if (errno != ELAST) {
06942 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06943 callerid_free(cs);
06944 ast_hangup(chan);
06945 goto quit;
06946 }
06947 break;
06948 }
06949 if (p->ringt)
06950 p->ringt--;
06951 if (p->ringt == 1) {
06952 res = -1;
06953 break;
06954 }
06955 }
06956 }
06957 }
06958 if (p->usedistinctiveringdetection) {
06959 if (option_verbose > 2)
06960
06961 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06962
06963 for (counter = 0; counter < 3; counter++) {
06964
06965
06966 if (option_verbose > 2)
06967
06968 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06969 p->drings.ringnum[counter].ring[0],
06970 p->drings.ringnum[counter].ring[1],
06971 p->drings.ringnum[counter].ring[2]);
06972 distMatches = 0;
06973 for (counter1 = 0; counter1 < 3; counter1++) {
06974 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06975 (p->drings.ringnum[counter].ring[counter1]-10)) {
06976 distMatches++;
06977 }
06978 }
06979 if (distMatches == 3) {
06980
06981 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06982 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06983 if (option_verbose > 2)
06984 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06985 break;
06986 }
06987 }
06988 }
06989
06990 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06991 #if 1
06992 restore_gains(p);
06993 #endif
06994 if (res < 0) {
06995 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06996 }
06997 } else
06998 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06999 }
07000 else
07001 cs = NULL;
07002
07003 if (number)
07004 ast_shrink_phone_number(number);
07005 ast_set_callerid(chan, number, name, number);
07006
07007 if (smdi_msg)
07008 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07009
07010 if (cs)
07011 callerid_free(cs);
07012
07013 ast_setstate(chan, AST_STATE_RING);
07014 chan->rings = 1;
07015 p->ringt = p->ringt_base;
07016 res = ast_pbx_run(chan);
07017 if (res) {
07018 ast_hangup(chan);
07019 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07020 }
07021 goto quit;
07022 default:
07023 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07024 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07025 if (res < 0)
07026 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07027 }
07028 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07029 if (res < 0)
07030 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07031 ast_hangup(chan);
07032 quit:
07033 ast_mutex_lock(&ss_thread_lock);
07034 ss_thread_count--;
07035 ast_cond_signal(&ss_thread_complete);
07036 ast_mutex_unlock(&ss_thread_lock);
07037 return NULL;
07038 }
07039
07040
07041 static int dahdi_destroy_channel_bynum(int channel)
07042 {
07043 struct dahdi_pvt *tmp = NULL;
07044 struct dahdi_pvt *prev = NULL;
07045
07046 tmp = iflist;
07047 while (tmp) {
07048 if (tmp->channel == channel) {
07049 int x = DAHDI_FLASH;
07050 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07051 destroy_channel(prev, tmp, 1);
07052 ast_module_unref(ast_module_info->self);
07053 return RESULT_SUCCESS;
07054 }
07055 prev = tmp;
07056 tmp = tmp->next;
07057 }
07058 return RESULT_FAILURE;
07059 }
07060
07061 static int handle_init_event(struct dahdi_pvt *i, int event)
07062 {
07063 int res;
07064 pthread_t threadid;
07065 pthread_attr_t attr;
07066 struct ast_channel *chan;
07067 pthread_attr_init(&attr);
07068 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07069
07070 switch (event) {
07071 case DAHDI_EVENT_NONE:
07072 case DAHDI_EVENT_BITSCHANGED:
07073 break;
07074 case DAHDI_EVENT_WINKFLASH:
07075 case DAHDI_EVENT_RINGOFFHOOK:
07076 if (i->inalarm) break;
07077 if (i->radio) break;
07078
07079 switch (i->sig) {
07080 case SIG_FXOLS:
07081 case SIG_FXOGS:
07082 case SIG_FXOKS:
07083 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07084 if (res && (errno == EBUSY))
07085 break;
07086 if (i->cidspill) {
07087
07088 free(i->cidspill);
07089 i->cidspill = NULL;
07090 }
07091 if (i->immediate) {
07092 dahdi_enable_ec(i);
07093
07094 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07095 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07096 if (!chan) {
07097 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07098 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07099 if (res < 0)
07100 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07101 }
07102 } else {
07103
07104 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07105 if (chan) {
07106 if (has_voicemail(i))
07107 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07108 else
07109 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07110 if (res < 0)
07111 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
07112 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07113 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07114 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07115 if (res < 0)
07116 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07117 ast_hangup(chan);
07118 }
07119 } else
07120 ast_log(LOG_WARNING, "Unable to create channel\n");
07121 }
07122 break;
07123 case SIG_FXSLS:
07124 case SIG_FXSGS:
07125 case SIG_FXSKS:
07126 i->ringt = i->ringt_base;
07127
07128 case SIG_EMWINK:
07129 case SIG_FEATD:
07130 case SIG_FEATDMF:
07131 case SIG_FEATDMF_TA:
07132 case SIG_E911:
07133 case SIG_FGC_CAMA:
07134 case SIG_FGC_CAMAMF:
07135 case SIG_FEATB:
07136 case SIG_EM:
07137 case SIG_EM_E1:
07138 case SIG_SFWINK:
07139 case SIG_SF_FEATD:
07140 case SIG_SF_FEATDMF:
07141 case SIG_SF_FEATB:
07142 case SIG_SF:
07143
07144 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
07145 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07146 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07147 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07148 if (res < 0)
07149 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07150 ast_hangup(chan);
07151 } else if (!chan) {
07152 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
07153 }
07154 break;
07155 default:
07156 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07157 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07158 if (res < 0)
07159 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07160 return -1;
07161 }
07162 break;
07163 case DAHDI_EVENT_NOALARM:
07164 i->inalarm = 0;
07165 if (!i->unknown_alarm) {
07166 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
07167 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07168 "Channel: %d\r\n", i->channel);
07169 } else {
07170 i->unknown_alarm = 0;
07171 }
07172 break;
07173 case DAHDI_EVENT_ALARM:
07174 i->inalarm = 1;
07175 res = get_alarms(i);
07176 handle_alarms(i, res);
07177
07178 case DAHDI_EVENT_ONHOOK:
07179 if (i->radio)
07180 break;
07181
07182 switch (i->sig) {
07183 case SIG_FXOLS:
07184 case SIG_FXOGS:
07185 case SIG_FEATD:
07186 case SIG_FEATDMF:
07187 case SIG_FEATDMF_TA:
07188 case SIG_E911:
07189 case SIG_FGC_CAMA:
07190 case SIG_FGC_CAMAMF:
07191 case SIG_FEATB:
07192 case SIG_EM:
07193 case SIG_EM_E1:
07194 case SIG_EMWINK:
07195 case SIG_SF_FEATD:
07196 case SIG_SF_FEATDMF:
07197 case SIG_SF_FEATB:
07198 case SIG_SF:
07199 case SIG_SFWINK:
07200 case SIG_FXSLS:
07201 case SIG_FXSGS:
07202 case SIG_FXSKS:
07203 case SIG_GR303FXSKS:
07204 dahdi_disable_ec(i);
07205 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07206 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07207 break;
07208 case SIG_GR303FXOKS:
07209 case SIG_FXOKS:
07210 dahdi_disable_ec(i);
07211
07212 #ifdef ZHONE_HACK
07213 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07214 usleep(1);
07215 #endif
07216 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07217 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07218 break;
07219 case SIG_PRI:
07220 dahdi_disable_ec(i);
07221 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07222 break;
07223 default:
07224 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07225 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07226 return -1;
07227 }
07228 break;
07229 case DAHDI_EVENT_POLARITY:
07230 switch (i->sig) {
07231 case SIG_FXSLS:
07232 case SIG_FXSKS:
07233 case SIG_FXSGS:
07234
07235
07236
07237
07238 if (i->hanguponpolarityswitch)
07239 i->polarity = POLARITY_REV;
07240
07241 if (i->cid_start == CID_START_POLARITY) {
07242 i->polarity = POLARITY_REV;
07243 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
07244 "CID detection on channel %d\n",
07245 i->channel);
07246 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
07247 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07248 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07249 }
07250 }
07251 break;
07252 default:
07253 ast_log(LOG_WARNING, "handle_init_event detected "
07254 "polarity reversal on non-FXO (SIG_FXS) "
07255 "interface %d\n", i->channel);
07256 }
07257 break;
07258 case DAHDI_EVENT_REMOVED:
07259 ast_log(LOG_NOTICE,
07260 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
07261 i->channel);
07262 dahdi_destroy_channel_bynum(i->channel);
07263 break;
07264 }
07265 pthread_attr_destroy(&attr);
07266 return 0;
07267 }
07268
07269 static void *do_monitor(void *data)
07270 {
07271 int count, res, res2, spoint, pollres=0;
07272 struct dahdi_pvt *i;
07273 struct dahdi_pvt *last = NULL;
07274 time_t thispass = 0, lastpass = 0;
07275 int found;
07276 char buf[1024];
07277 struct pollfd *pfds=NULL;
07278 int lastalloc = -1;
07279
07280
07281
07282 #if 0
07283 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
07284 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
07285 return NULL;
07286 }
07287 ast_log(LOG_DEBUG, "Monitor starting...\n");
07288 #endif
07289 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07290
07291 for (;;) {
07292
07293 ast_mutex_lock(&iflock);
07294 if (!pfds || (lastalloc != ifcount)) {
07295 if (pfds) {
07296 free(pfds);
07297 pfds = NULL;
07298 }
07299 if (ifcount) {
07300 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
07301 ast_mutex_unlock(&iflock);
07302 return NULL;
07303 }
07304 }
07305 lastalloc = ifcount;
07306 }
07307
07308
07309 count = 0;
07310 i = iflist;
07311 while (i) {
07312 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
07313 if (!i->owner && !i->subs[SUB_REAL].owner) {
07314
07315 pfds[count].fd = i->subs[SUB_REAL].dfd;
07316 pfds[count].events = POLLPRI;
07317 pfds[count].revents = 0;
07318
07319 if (i->cidspill)
07320 pfds[count].events |= POLLIN;
07321 count++;
07322 }
07323 }
07324 i = i->next;
07325 }
07326
07327 ast_mutex_unlock(&iflock);
07328
07329 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
07330 pthread_testcancel();
07331
07332 res = poll(pfds, count, 1000);
07333 pthread_testcancel();
07334 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07335
07336
07337 if (res < 0) {
07338 if ((errno != EAGAIN) && (errno != EINTR))
07339 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07340 continue;
07341 }
07342
07343
07344 ast_mutex_lock(&iflock);
07345 found = 0;
07346 spoint = 0;
07347 lastpass = thispass;
07348 thispass = time(NULL);
07349 i = iflist;
07350 while (i) {
07351 if (thispass != lastpass) {
07352 if (!found && ((i == last) || ((i == iflist) && !last))) {
07353 last = i;
07354 if (last) {
07355 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07356 (last->sig & __DAHDI_SIG_FXO)) {
07357 res = ast_app_has_voicemail(last->mailbox, NULL);
07358 if (last->msgstate != res) {
07359 int x;
07360 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07361 x = DAHDI_FLUSH_BOTH;
07362 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07363 if (res2)
07364 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
07365 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07366
07367 x = 4000;
07368 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07369 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07370 last->cidpos = 0;
07371 last->msgstate = res;
07372 last->onhooktime = thispass;
07373 }
07374 found ++;
07375 }
07376 }
07377 last = last->next;
07378 }
07379 }
07380 }
07381 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
07382 if (i->radio && !i->owner)
07383 {
07384 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07385 if (res)
07386 {
07387 if (option_debug)
07388 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07389
07390 ast_mutex_unlock(&iflock);
07391 handle_init_event(i, res);
07392 ast_mutex_lock(&iflock);
07393 }
07394 i = i->next;
07395 continue;
07396 }
07397 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
07398 if (pollres & POLLIN) {
07399 if (i->owner || i->subs[SUB_REAL].owner) {
07400 #ifdef HAVE_PRI
07401 if (!i->pri)
07402 #endif
07403 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
07404 i = i->next;
07405 continue;
07406 }
07407 if (!i->cidspill) {
07408 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
07409 i = i->next;
07410 continue;
07411 }
07412 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
07413 if (res > 0) {
07414
07415 if (res > i->cidlen - i->cidpos)
07416 res = i->cidlen - i->cidpos;
07417 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
07418 if (res2 > 0) {
07419 i->cidpos += res2;
07420 if (i->cidpos >= i->cidlen) {
07421 free(i->cidspill);
07422 i->cidspill = 0;
07423 i->cidpos = 0;
07424 i->cidlen = 0;
07425 }
07426 } else {
07427 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07428 i->msgstate = -1;
07429 }
07430 } else {
07431 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07432 }
07433 }
07434 if (pollres & POLLPRI) {
07435 if (i->owner || i->subs[SUB_REAL].owner) {
07436 #ifdef HAVE_PRI
07437 if (!i->pri)
07438 #endif
07439 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
07440 i = i->next;
07441 continue;
07442 }
07443 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07444 if (option_debug)
07445 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07446
07447 ast_mutex_unlock(&iflock);
07448 handle_init_event(i, res);
07449 ast_mutex_lock(&iflock);
07450 }
07451 }
07452 i=i->next;
07453 }
07454 ast_mutex_unlock(&iflock);
07455 }
07456
07457 return NULL;
07458
07459 }
07460
07461 static int restart_monitor(void)
07462 {
07463 pthread_attr_t attr;
07464 pthread_attr_init(&attr);
07465 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07466
07467 if (monitor_thread == AST_PTHREADT_STOP)
07468 return 0;
07469 ast_mutex_lock(&monlock);
07470 if (monitor_thread == pthread_self()) {
07471 ast_mutex_unlock(&monlock);
07472 ast_log(LOG_WARNING, "Cannot kill myself\n");
07473 return -1;
07474 }
07475 if (monitor_thread != AST_PTHREADT_NULL) {
07476
07477 pthread_kill(monitor_thread, SIGURG);
07478 } else {
07479
07480 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07481 ast_mutex_unlock(&monlock);
07482 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07483 pthread_attr_destroy(&attr);
07484 return -1;
07485 }
07486 }
07487 ast_mutex_unlock(&monlock);
07488 pthread_attr_destroy(&attr);
07489 return 0;
07490 }
07491
07492 #ifdef HAVE_PRI
07493 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
07494 {
07495 int x;
07496 int trunkgroup;
07497
07498 trunkgroup = pris[*span].mastertrunkgroup;
07499 if (trunkgroup) {
07500
07501 for (x = 0; x < NUM_SPANS; x++) {
07502 if (pris[x].trunkgroup == trunkgroup) {
07503 *span = x;
07504 return 0;
07505 }
07506 }
07507 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
07508 *span = -1;
07509 } else {
07510 if (pris[*span].trunkgroup) {
07511 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
07512 *span = -1;
07513 } else if (pris[*span].mastertrunkgroup) {
07514 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
07515 *span = -1;
07516 } else {
07517 if (si->totalchans == 31) {
07518
07519 pris[*span].dchannels[0] = 16 + offset;
07520 } else if (si->totalchans == 24) {
07521
07522 pris[*span].dchannels[0] = 24 + offset;
07523 } else if (si->totalchans == 3) {
07524
07525 pris[*span].dchannels[0] = 3 + offset;
07526 } else {
07527 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);
07528 *span = -1;
07529 return 0;
07530 }
07531 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
07532 pris[*span].offset = offset;
07533 pris[*span].span = *span + 1;
07534 }
07535 }
07536 return 0;
07537 }
07538
07539 static int pri_create_trunkgroup(int trunkgroup, int *channels)
07540 {
07541 struct dahdi_spaninfo si;
07542 struct dahdi_params p;
07543 int fd;
07544 int span;
07545 int ospan=0;
07546 int x,y;
07547 for (x = 0; x < NUM_SPANS; x++) {
07548 if (pris[x].trunkgroup == trunkgroup) {
07549 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
07550 return -1;
07551 }
07552 }
07553 for (y = 0; y < NUM_DCHANS; y++) {
07554 if (!channels[y])
07555 break;
07556 memset(&si, 0, sizeof(si));
07557 memset(&p, 0, sizeof(p));
07558 fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
07559 if (fd < 0) {
07560 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
07561 return -1;
07562 }
07563 x = channels[y];
07564 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
07565 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
07566 close(fd);
07567 return -1;
07568 }
07569 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
07570 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
07571 return -1;
07572 }
07573 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
07574 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
07575 close(fd);
07576 return -1;
07577 }
07578 span = p.spanno - 1;
07579 if (pris[span].trunkgroup) {
07580 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
07581 close(fd);
07582 return -1;
07583 }
07584 if (pris[span].pvts[0]) {
07585 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
07586 close(fd);
07587 return -1;
07588 }
07589 if (!y) {
07590 pris[span].trunkgroup = trunkgroup;
07591 pris[span].offset = channels[y] - p.chanpos;
07592 ospan = span;
07593 }
07594 pris[ospan].dchannels[y] = channels[y];
07595 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
07596 pris[span].span = span + 1;
07597 close(fd);
07598 }
07599 return 0;
07600 }
07601
07602 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
07603 {
07604 if (pris[span].mastertrunkgroup) {
07605 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);
07606 return -1;
07607 }
07608 pris[span].mastertrunkgroup = trunkgroup;
07609 pris[span].prilogicalspan = logicalspan;
07610 return 0;
07611 }
07612
07613 #endif
07614
07615 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
07616 {
07617
07618 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
07619 char fn[80];
07620 #if 1
07621 struct dahdi_bufferinfo bi;
07622 #endif
07623 int res;
07624 int span=0;
07625 int here = 0;
07626 int x;
07627 struct dahdi_pvt **wlist;
07628 struct dahdi_pvt **wend;
07629 struct dahdi_params p;
07630
07631 wlist = &iflist;
07632 wend = &ifend;
07633
07634 #ifdef HAVE_PRI
07635 if (pri) {
07636 wlist = &pri->crvs;
07637 wend = &pri->crvend;
07638 }
07639 #endif
07640
07641 tmp2 = *wlist;
07642 prev = NULL;
07643
07644 while (tmp2) {
07645 if (!tmp2->destroy) {
07646 if (tmp2->channel == channel) {
07647 tmp = tmp2;
07648 here = 1;
07649 break;
07650 }
07651 if (tmp2->channel > channel) {
07652 break;
07653 }
07654 }
07655 prev = tmp2;
07656 tmp2 = tmp2->next;
07657 }
07658
07659 if (!here && reloading != 1) {
07660 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07661 if (tmp)
07662 free(tmp);
07663 return NULL;
07664 }
07665 ast_mutex_init(&tmp->lock);
07666 ifcount++;
07667 for (x = 0; x < 3; x++)
07668 tmp->subs[x].dfd = -1;
07669 tmp->channel = channel;
07670 }
07671
07672 if (tmp) {
07673 int chan_sig = conf->chan.sig;
07674 if (!here) {
07675 if ((channel != CHAN_PSEUDO) && !pri) {
07676 int count = 0;
07677 snprintf(fn, sizeof(fn), "%d", channel);
07678
07679 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07680 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
07681 usleep(1);
07682 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07683 count++;
07684 }
07685
07686 if (tmp->subs[SUB_REAL].dfd < 0) {
07687 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);
07688 destroy_dahdi_pvt(&tmp);
07689 return NULL;
07690 }
07691 memset(&p, 0, sizeof(p));
07692 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07693 if (res < 0) {
07694 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
07695 destroy_dahdi_pvt(&tmp);
07696 return NULL;
07697 }
07698 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07699 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype));
07700 destroy_dahdi_pvt(&tmp);
07701 return NULL;
07702 }
07703 tmp->law = p.curlaw;
07704 tmp->span = p.spanno;
07705 span = p.spanno - 1;
07706 } else {
07707 if (channel == CHAN_PSEUDO)
07708 chan_sig = 0;
07709 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07710 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07711 return NULL;
07712 }
07713 }
07714 #ifdef HAVE_PRI
07715 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07716 int offset;
07717 int myswitchtype;
07718 int matchesdchan;
07719 int x,y;
07720 offset = 0;
07721 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
07722 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07723 destroy_dahdi_pvt(&tmp);
07724 return NULL;
07725 }
07726 if (span >= NUM_SPANS) {
07727 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07728 destroy_dahdi_pvt(&tmp);
07729 return NULL;
07730 } else {
07731 struct dahdi_spaninfo si;
07732 si.spanno = 0;
07733 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
07734 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07735 destroy_dahdi_pvt(&tmp);
07736 return NULL;
07737 }
07738
07739 tmp->logicalspan = pris[span].prilogicalspan;
07740 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07741 if (span < 0) {
07742 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07743 destroy_dahdi_pvt(&tmp);
07744 return NULL;
07745 }
07746 if (chan_sig == SIG_PRI)
07747 myswitchtype = conf->pri.switchtype;
07748 else
07749 myswitchtype = PRI_SWITCH_GR303_TMC;
07750
07751 matchesdchan=0;
07752 for (x = 0; x < NUM_SPANS; x++) {
07753 for (y = 0; y < NUM_DCHANS; y++) {
07754 if (pris[x].dchannels[y] == tmp->channel) {
07755 matchesdchan = 1;
07756 break;
07757 }
07758 }
07759 }
07760 offset = p.chanpos;
07761 if (!matchesdchan) {
07762 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07763 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07764 destroy_dahdi_pvt(&tmp);
07765 return NULL;
07766 }
07767 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07768 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07769 destroy_dahdi_pvt(&tmp);
07770 return NULL;
07771 }
07772 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07773 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07774 destroy_dahdi_pvt(&tmp);
07775 return NULL;
07776 }
07777 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07778 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07779 destroy_dahdi_pvt(&tmp);
07780 return NULL;
07781 }
07782 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07783 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07784 destroy_dahdi_pvt(&tmp);
07785 return NULL;
07786 }
07787 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07788 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07789 destroy_dahdi_pvt(&tmp);
07790 return NULL;
07791 }
07792 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07793 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07794 destroy_dahdi_pvt(&tmp);
07795 return NULL;
07796 }
07797 if (pris[span].numchans >= MAX_CHANNELS) {
07798 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07799 pris[span].trunkgroup);
07800 destroy_dahdi_pvt(&tmp);
07801 return NULL;
07802 }
07803 pris[span].nodetype = conf->pri.nodetype;
07804 pris[span].switchtype = myswitchtype;
07805 pris[span].nsf = conf->pri.nsf;
07806 pris[span].dialplan = conf->pri.dialplan;
07807 pris[span].localdialplan = conf->pri.localdialplan;
07808 pris[span].pvts[pris[span].numchans++] = tmp;
07809 pris[span].minunused = conf->pri.minunused;
07810 pris[span].minidle = conf->pri.minidle;
07811 pris[span].overlapdial = conf->pri.overlapdial;
07812 #ifdef HAVE_PRI_INBANDDISCONNECT
07813 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
07814 #endif
07815 pris[span].facilityenable = conf->pri.facilityenable;
07816 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07817 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07818 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07819 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07820 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07821 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07822 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07823 pris[span].resetinterval = conf->pri.resetinterval;
07824
07825 tmp->pri = &pris[span];
07826 tmp->prioffset = offset;
07827 tmp->call = NULL;
07828 } else {
07829 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07830 destroy_dahdi_pvt(&tmp);
07831 return NULL;
07832 }
07833 }
07834 } else {
07835 tmp->prioffset = 0;
07836 }
07837 #endif
07838 } else {
07839 chan_sig = tmp->sig;
07840 memset(&p, 0, sizeof(p));
07841 if (tmp->subs[SUB_REAL].dfd > -1)
07842 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07843 }
07844
07845 switch (chan_sig) {
07846 case SIG_FXSKS:
07847 case SIG_FXSLS:
07848 case SIG_EM:
07849 case SIG_EM_E1:
07850 case SIG_EMWINK:
07851 case SIG_FEATD:
07852 case SIG_FEATDMF:
07853 case SIG_FEATDMF_TA:
07854 case SIG_FEATB:
07855 case SIG_E911:
07856 case SIG_SF:
07857 case SIG_SFWINK:
07858 case SIG_FGC_CAMA:
07859 case SIG_FGC_CAMAMF:
07860 case SIG_SF_FEATD:
07861 case SIG_SF_FEATDMF:
07862 case SIG_SF_FEATB:
07863 p.starttime = 250;
07864 break;
07865 }
07866
07867 if (tmp->radio) {
07868
07869 p.channo = channel;
07870 p.rxwinktime = 1;
07871 p.rxflashtime = 1;
07872 p.starttime = 1;
07873 p.debouncetime = 5;
07874 }
07875 if (!tmp->radio) {
07876 p.channo = channel;
07877
07878 if (conf->timing.prewinktime >= 0)
07879 p.prewinktime = conf->timing.prewinktime;
07880 if (conf->timing.preflashtime >= 0)
07881 p.preflashtime = conf->timing.preflashtime;
07882 if (conf->timing.winktime >= 0)
07883 p.winktime = conf->timing.winktime;
07884 if (conf->timing.flashtime >= 0)
07885 p.flashtime = conf->timing.flashtime;
07886 if (conf->timing.starttime >= 0)
07887 p.starttime = conf->timing.starttime;
07888 if (conf->timing.rxwinktime >= 0)
07889 p.rxwinktime = conf->timing.rxwinktime;
07890 if (conf->timing.rxflashtime >= 0)
07891 p.rxflashtime = conf->timing.rxflashtime;
07892 if (conf->timing.debouncetime >= 0)
07893 p.debouncetime = conf->timing.debouncetime;
07894 }
07895
07896
07897 if (tmp->subs[SUB_REAL].dfd >= 0)
07898 {
07899 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
07900 if (res < 0) {
07901 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
07902 destroy_dahdi_pvt(&tmp);
07903 return NULL;
07904 }
07905 }
07906 #if 1
07907 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
07908 memset(&bi, 0, sizeof(bi));
07909 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07910 if (!res) {
07911 bi.txbufpolicy = conf->chan.buf_policy;
07912 bi.rxbufpolicy = conf->chan.buf_policy;
07913 bi.numbufs = conf->chan.buf_no;
07914 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07915 if (res < 0) {
07916 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
07917 }
07918 } else
07919 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
07920 }
07921 #endif
07922 tmp->immediate = conf->chan.immediate;
07923 tmp->transfertobusy = conf->chan.transfertobusy;
07924 tmp->sig = chan_sig;
07925 tmp->outsigmod = conf->chan.outsigmod;
07926 tmp->ringt_base = ringt_base;
07927 tmp->firstradio = 0;
07928 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07929 tmp->permcallwaiting = conf->chan.callwaiting;
07930 else
07931 tmp->permcallwaiting = 0;
07932
07933 tmp->destroy = 0;
07934 tmp->drings = drings;
07935 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07936 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07937 tmp->threewaycalling = conf->chan.threewaycalling;
07938 tmp->adsi = conf->chan.adsi;
07939 tmp->use_smdi = conf->chan.use_smdi;
07940 tmp->permhidecallerid = conf->chan.hidecallerid;
07941 tmp->callreturn = conf->chan.callreturn;
07942 tmp->echocancel = conf->chan.echocancel;
07943 tmp->echotraining = conf->chan.echotraining;
07944 tmp->pulse = conf->chan.pulse;
07945 if (tmp->echocancel)
07946 tmp->echocanbridged = conf->chan.echocanbridged;
07947 else {
07948 if (conf->chan.echocanbridged)
07949 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07950 tmp->echocanbridged = 0;
07951 }
07952 tmp->busydetect = conf->chan.busydetect;
07953 tmp->busycount = conf->chan.busycount;
07954 tmp->busycompare = conf->chan.busycompare;
07955 tmp->busytonelength = conf->chan.busytonelength;
07956 tmp->busyquietlength = conf->chan.busyquietlength;
07957 tmp->busyfuzziness = conf->chan.busyfuzziness;
07958 tmp->silencethreshold = conf->chan.silencethreshold;
07959 tmp->callprogress = conf->chan.callprogress;
07960 tmp->cancallforward = conf->chan.cancallforward;
07961 tmp->dtmfrelax = conf->chan.dtmfrelax;
07962 tmp->callwaiting = tmp->permcallwaiting;
07963 tmp->hidecallerid = tmp->permhidecallerid;
07964 tmp->channel = channel;
07965 tmp->stripmsd = conf->chan.stripmsd;
07966 tmp->use_callerid = conf->chan.use_callerid;
07967 tmp->cid_signalling = conf->chan.cid_signalling;
07968 tmp->cid_start = conf->chan.cid_start;
07969 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
07970 tmp->restrictcid = conf->chan.restrictcid;
07971 tmp->use_callingpres = conf->chan.use_callingpres;
07972 tmp->priindication_oob = conf->chan.priindication_oob;
07973 tmp->priexclusive = conf->chan.priexclusive;
07974 if (tmp->usedistinctiveringdetection) {
07975 if (!tmp->use_callerid) {
07976 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07977 tmp->use_callerid = 1;
07978 }
07979 }
07980
07981 if (tmp->cid_signalling == CID_SIG_SMDI) {
07982 if (!tmp->use_smdi) {
07983 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07984 tmp->use_smdi = 1;
07985 }
07986 }
07987 if (tmp->use_smdi) {
07988 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07989 if (!(tmp->smdi_iface)) {
07990 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07991 tmp->use_smdi = 0;
07992 }
07993 }
07994
07995 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
07996 tmp->amaflags = conf->chan.amaflags;
07997 if (!here) {
07998 tmp->confno = -1;
07999 tmp->propconfno = -1;
08000 }
08001 tmp->canpark = conf->chan.canpark;
08002 tmp->transfer = conf->chan.transfer;
08003 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
08004 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
08005 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
08006 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
08007 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
08008 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
08009 tmp->cid_ton = 0;
08010 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
08011 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
08012 tmp->msgstate = -1;
08013 tmp->group = conf->chan.group;
08014 tmp->callgroup = conf->chan.callgroup;
08015 tmp->pickupgroup= conf->chan.pickupgroup;
08016 tmp->rxgain = conf->chan.rxgain;
08017 tmp->txgain = conf->chan.txgain;
08018 tmp->tonezone = conf->chan.tonezone;
08019 tmp->onhooktime = time(NULL);
08020 if (tmp->subs[SUB_REAL].dfd > -1) {
08021 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
08022 if (tmp->dsp)
08023 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
08024 update_conf(tmp);
08025 if (!here) {
08026 if (chan_sig != SIG_PRI)
08027
08028 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08029 }
08030 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
08031 #ifdef HAVE_PRI
08032
08033 if (tmp->pri && !pri_is_up(tmp->pri)) {
08034 tmp->inalarm = 1;
08035 }
08036 #endif
08037 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
08038 tmp->inalarm = 1;
08039 handle_alarms(tmp, res);
08040 } else {
08041
08042
08043
08044
08045
08046
08047
08048
08049
08050
08051 tmp->unknown_alarm = 1;
08052 }
08053 }
08054
08055 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
08056 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
08057 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
08058 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
08059
08060 }
08061 if (tmp && !here) {
08062
08063 if (!*wlist) {
08064 *wlist = tmp;
08065 tmp->prev = NULL;
08066 tmp->next = NULL;
08067 *wend = tmp;
08068 } else {
08069
08070 struct dahdi_pvt *working = *wlist;
08071
08072
08073 if (working->channel > tmp->channel) {
08074 tmp->next = *wlist;
08075 tmp->prev = NULL;
08076 (*wlist)->prev = tmp;
08077 *wlist = tmp;
08078 } else {
08079
08080 while (working) {
08081
08082 if (working->next) {
08083 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
08084 tmp->next = working->next;
08085 tmp->prev = working;
08086 working->next->prev = tmp;
08087 working->next = tmp;
08088 break;
08089 }
08090 } else {
08091
08092 if (working->channel < tmp->channel) {
08093 working->next = tmp;
08094 tmp->next = NULL;
08095 tmp->prev = working;
08096 *wend = tmp;
08097 break;
08098 }
08099 }
08100 working = working->next;
08101 }
08102 }
08103 }
08104 }
08105 return tmp;
08106 }
08107
08108 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
08109 {
08110 int res;
08111 struct dahdi_params par;
08112
08113
08114 if (groupmatch) {
08115 if ((p->group & groupmatch) != groupmatch)
08116 return 0;
08117 *groupmatched = 1;
08118 }
08119
08120 if (channelmatch != -1) {
08121 if (p->channel != channelmatch)
08122 return 0;
08123 *channelmatched = 1;
08124 }
08125
08126 if (busy) {
08127 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
08128 *busy = 1;
08129 }
08130
08131 if (p->dnd)
08132 return 0;
08133
08134 if (p->guardtime && (time(NULL) < p->guardtime))
08135 return 0;
08136
08137
08138 if (!p->owner) {
08139 #ifdef HAVE_PRI
08140
08141 if (p->pri) {
08142 if (p->resetting || p->call)
08143 return 0;
08144 else
08145 return 1;
08146 }
08147 #endif
08148 if (!(p->radio || (p->oprmode < 0)))
08149 {
08150 if (!p->sig || (p->sig == SIG_FXSLS))
08151 return 1;
08152
08153 if (p->subs[SUB_REAL].dfd > -1)
08154 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
08155 else {
08156
08157 res = 0;
08158 par.rxisoffhook = 0;
08159 }
08160 if (res) {
08161 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
08162 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
08163
08164
08165
08166 if (par.rxbits > -1)
08167 return 1;
08168 if (par.rxisoffhook)
08169 return 1;
08170 else
08171 #ifdef DAHDI_CHECK_HOOKSTATE
08172 return 0;
08173 #else
08174 return 1;
08175 #endif
08176 } else if (par.rxisoffhook) {
08177 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
08178
08179 return 0;
08180 }
08181 }
08182 return 1;
08183 }
08184
08185
08186 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
08187 return 0;
08188
08189 if (!p->callwaiting) {
08190
08191 return 0;
08192 }
08193
08194 if (p->subs[SUB_CALLWAIT].dfd > -1) {
08195
08196 return 0;
08197 }
08198
08199 if ((p->owner->_state != AST_STATE_UP) &&
08200 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
08201
08202 return 0;
08203 }
08204 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
08205
08206 return 0;
08207 }
08208
08209 return 1;
08210 }
08211
08212 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
08213 {
08214 struct dahdi_pvt *p;
08215 struct dahdi_bufferinfo bi;
08216 int res;
08217
08218 if ((p = ast_malloc(sizeof(*p)))) {
08219 memcpy(p, src, sizeof(struct dahdi_pvt));
08220 ast_mutex_init(&p->lock);
08221 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
08222
08223 if (p->subs[SUB_REAL].dfd < 0) {
08224 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
08225 destroy_dahdi_pvt(&p);
08226 return NULL;
08227 }
08228 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08229 if (!res) {
08230 bi.txbufpolicy = p->buf_policy;
08231 bi.rxbufpolicy = p->buf_policy;
08232 bi.numbufs = p->buf_no;
08233 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08234 if (res < 0) {
08235 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
08236 }
08237 } else
08238 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
08239 }
08240 p->destroy = 1;
08241 p->next = iflist;
08242 p->prev = NULL;
08243 iflist = p;
08244 if (iflist->next)
08245 iflist->next->prev = p;
08246 return p;
08247 }
08248
08249
08250 #ifdef HAVE_PRI
08251 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
08252 {
08253 int x;
08254 if (backwards)
08255 x = pri->numchans;
08256 else
08257 x = 0;
08258 for (;;) {
08259 if (backwards && (x < 0))
08260 break;
08261 if (!backwards && (x >= pri->numchans))
08262 break;
08263 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
08264 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
08265 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
08266 return x;
08267 }
08268 if (backwards)
08269 x--;
08270 else
08271 x++;
08272 }
08273 return -1;
08274 }
08275 #endif
08276
08277 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
08278 {
08279 ast_group_t groupmatch = 0;
08280 int channelmatch = -1;
08281 int roundrobin = 0;
08282 int callwait = 0;
08283 int busy = 0;
08284 struct dahdi_pvt *p;
08285 struct ast_channel *tmp = NULL;
08286 char *dest=NULL;
08287 int x;
08288 char *s;
08289 char opt=0;
08290 int res=0, y=0;
08291 int backwards = 0;
08292 #ifdef HAVE_PRI
08293 int crv;
08294 int bearer = -1;
08295 int trunkgroup;
08296 struct dahdi_pri *pri=NULL;
08297 #endif
08298 struct dahdi_pvt *exit, *start, *end;
08299 ast_mutex_t *lock;
08300 int channelmatched = 0;
08301 int groupmatched = 0;
08302
08303
08304
08305
08306
08307
08308
08309
08310
08311
08312
08313
08314
08315
08316
08317
08318
08319
08320
08321 lock = &iflock;
08322 start = iflist;
08323 end = ifend;
08324 if (data) {
08325 dest = ast_strdupa((char *)data);
08326 } else {
08327 ast_log(LOG_WARNING, "Channel requested with no data\n");
08328 return NULL;
08329 }
08330 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
08331
08332 char *stringp;
08333
08334 stringp = dest + 1;
08335 s = strsep(&stringp, "/");
08336 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08337 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08338 return NULL;
08339 }
08340 groupmatch = ((ast_group_t) 1 << x);
08341 if (toupper(dest[0]) == 'G') {
08342 if (dest[0] == 'G') {
08343 backwards = 1;
08344 p = ifend;
08345 } else
08346 p = iflist;
08347 } else {
08348 if (dest[0] == 'R') {
08349 backwards = 1;
08350 p = round_robin[x]?round_robin[x]->prev:ifend;
08351 if (!p)
08352 p = ifend;
08353 } else {
08354 p = round_robin[x]?round_robin[x]->next:iflist;
08355 if (!p)
08356 p = iflist;
08357 }
08358 roundrobin = 1;
08359 }
08360 } else {
08361 char *stringp;
08362
08363 stringp = dest;
08364 s = strsep(&stringp, "/");
08365 p = iflist;
08366 if (!strcasecmp(s, "pseudo")) {
08367
08368 x = CHAN_PSEUDO;
08369 channelmatch = x;
08370 }
08371 #ifdef HAVE_PRI
08372 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
08373 if ((trunkgroup < 1) || (crv < 1)) {
08374 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08375 return NULL;
08376 }
08377 res--;
08378 for (x = 0; x < NUM_SPANS; x++) {
08379 if (pris[x].trunkgroup == trunkgroup) {
08380 pri = pris + x;
08381 lock = &pri->lock;
08382 start = pri->crvs;
08383 end = pri->crvend;
08384 break;
08385 }
08386 }
08387 if (!pri) {
08388 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08389 return NULL;
08390 }
08391 channelmatch = crv;
08392 p = pris[x].crvs;
08393 }
08394 #endif
08395 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08396 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08397 return NULL;
08398 } else {
08399 channelmatch = x;
08400 }
08401 }
08402
08403 ast_mutex_lock(lock);
08404 exit = p;
08405 while (p && !tmp) {
08406 if (roundrobin)
08407 round_robin[x] = p;
08408 #if 0
08409 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08410 #endif
08411
08412 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08413 if (option_debug)
08414 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08415 if (p->inalarm)
08416 goto next;
08417
08418 callwait = (p->owner != NULL);
08419 #ifdef HAVE_PRI
08420 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
08421 if (p->sig != SIG_FXSKS) {
08422
08423
08424 bearer = pri_find_empty_chan(pri, 0);
08425 if (bearer < 0) {
08426 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08427 p = NULL;
08428 break;
08429 }
08430 pri_assign_bearer(p, pri, pri->pvts[bearer]);
08431 } else {
08432 if (alloc_sub(p, 0)) {
08433 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08434 p = NULL;
08435 break;
08436 } else
08437 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08438 p->pri = pri;
08439 }
08440 }
08441 #endif
08442 if (p->channel == CHAN_PSEUDO) {
08443 p = chandup(p);
08444 if (!p) {
08445 break;
08446 }
08447 }
08448 if (p->owner) {
08449 if (alloc_sub(p, SUB_CALLWAIT)) {
08450 p = NULL;
08451 break;
08452 }
08453 }
08454 p->outgoing = 1;
08455 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08456 #ifdef HAVE_PRI
08457 if (p->bearer) {
08458
08459 p->bearer->owner = tmp;
08460 }
08461 #endif
08462
08463 if (res > 1) {
08464 if (opt == 'c') {
08465
08466 p->confirmanswer = 1;
08467 } else if (opt == 'r') {
08468
08469 if (res < 3)
08470 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08471 else
08472 p->distinctivering = y;
08473 } else if (opt == 'd') {
08474
08475 p->digital = 1;
08476 if (tmp)
08477 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08478 } else {
08479 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08480 }
08481 }
08482
08483 if (tmp && callwait)
08484 tmp->cdrflags |= AST_CDR_CALLWAIT;
08485 break;
08486 }
08487 next:
08488 if (backwards) {
08489 p = p->prev;
08490 if (!p)
08491 p = end;
08492 } else {
08493 p = p->next;
08494 if (!p)
08495 p = start;
08496 }
08497
08498 if (p == exit)
08499 break;
08500 }
08501 ast_mutex_unlock(lock);
08502 restart_monitor();
08503 if (callwait)
08504 *cause = AST_CAUSE_BUSY;
08505 else if (!tmp) {
08506 if (channelmatched) {
08507 if (busy)
08508 *cause = AST_CAUSE_BUSY;
08509 } else if (groupmatched) {
08510 *cause = AST_CAUSE_CONGESTION;
08511 }
08512 }
08513
08514 return tmp;
08515 }
08516
08517
08518 #ifdef HAVE_PRI
08519 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
08520 {
08521 struct dahdi_pvt *p;
08522 p = pri->crvs;
08523 while (p) {
08524 if (p->channel == crv)
08525 return p;
08526 p = p->next;
08527 }
08528 return NULL;
08529 }
08530
08531
08532 static int pri_find_principle(struct dahdi_pri *pri, int channel)
08533 {
08534 int x;
08535 int span = PRI_SPAN(channel);
08536 int spanfd;
08537 struct dahdi_params param;
08538 int principle = -1;
08539 int explicit = PRI_EXPLICIT(channel);
08540 channel = PRI_CHANNEL(channel);
08541
08542 if (!explicit) {
08543 spanfd = pri_active_dchan_fd(pri);
08544 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
08545 return -1;
08546 span = pris[param.spanno - 1].prilogicalspan;
08547 }
08548
08549 for (x = 0; x < pri->numchans; x++) {
08550 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
08551 principle = x;
08552 break;
08553 }
08554 }
08555
08556 return principle;
08557 }
08558
08559 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
08560 {
08561 int x;
08562 struct dahdi_pvt *crv;
08563 if (!c) {
08564 if (principle < 0)
08565 return -1;
08566 return principle;
08567 }
08568 if ((principle > -1) &&
08569 (principle < pri->numchans) &&
08570 (pri->pvts[principle]) &&
08571 (pri->pvts[principle]->call == c))
08572 return principle;
08573
08574 for (x = 0; x < pri->numchans; x++) {
08575 if (!pri->pvts[x])
08576 continue;
08577 if (pri->pvts[x]->call == c) {
08578
08579 if (principle != x) {
08580 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
08581
08582 if (option_verbose > 2)
08583 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
08584 old->channel, new->channel);
08585 if (new->owner) {
08586 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
08587 old->channel, new->channel, new->channel);
08588 return -1;
08589 }
08590
08591 new->owner = old->owner;
08592 old->owner = NULL;
08593 if (new->owner) {
08594 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
08595 new->owner->tech_pvt = new;
08596 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
08597 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
08598 old->subs[SUB_REAL].owner = NULL;
08599 } else
08600 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);
08601 new->call = old->call;
08602 old->call = NULL;
08603
08604
08605 new->dsp = old->dsp;
08606 new->dsp_features = old->dsp_features;
08607 old->dsp = NULL;
08608 old->dsp_features = 0;
08609 }
08610 return principle;
08611 }
08612 }
08613
08614 crv = pri->crvs;
08615 while (crv) {
08616 if (crv->call == c) {
08617
08618 if (crv->bearer)
08619 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
08620 else if (pri->pvts[principle]->owner)
08621 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
08622 else {
08623
08624
08625 dahdi_close_sub(crv, SUB_REAL);
08626 pri->pvts[principle]->call = crv->call;
08627 pri_assign_bearer(crv, pri, pri->pvts[principle]);
08628 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
08629 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
08630 pri->trunkgroup, crv->channel);
08631 wakeup_sub(crv, SUB_REAL, pri);
08632 }
08633 return principle;
08634 }
08635 crv = crv->next;
08636 }
08637 ast_log(LOG_WARNING, "Call specified, but not found?\n");
08638 return -1;
08639 }
08640
08641 static void *do_idle_thread(void *vchan)
08642 {
08643 struct ast_channel *chan = vchan;
08644 struct dahdi_pvt *pvt = chan->tech_pvt;
08645 struct ast_frame *f;
08646 char ex[80];
08647
08648 int newms, ms = 30000;
08649 if (option_verbose > 2)
08650 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
08651 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
08652 if (ast_call(chan, ex, 0)) {
08653 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
08654 ast_hangup(chan);
08655 return NULL;
08656 }
08657 while ((newms = ast_waitfor(chan, ms)) > 0) {
08658 f = ast_read(chan);
08659 if (!f) {
08660
08661 break;
08662 }
08663 if (f->frametype == AST_FRAME_CONTROL) {
08664 switch (f->subclass) {
08665 case AST_CONTROL_ANSWER:
08666
08667 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
08668 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
08669 chan->priority = 1;
08670 if (option_verbose > 3)
08671 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
08672 ast_pbx_run(chan);
08673
08674 return NULL;
08675 case AST_CONTROL_BUSY:
08676 if (option_verbose > 3)
08677 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
08678 break;
08679 case AST_CONTROL_CONGESTION:
08680 if (option_verbose > 3)
08681 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
08682 break;
08683 };
08684 }
08685 ast_frfree(f);
08686 ms = newms;
08687 }
08688
08689 ast_hangup(chan);
08690 return NULL;
08691 }
08692
08693 #ifndef PRI_RESTART
08694 #error "Upgrade your libpri"
08695 #endif
08696 static void dahdi_pri_message(struct pri *pri, char *s)
08697 {
08698 int x, y;
08699 int dchan = -1, span = -1;
08700 int dchancount = 0;
08701
08702 if (pri) {
08703 for (x = 0; x < NUM_SPANS; x++) {
08704 for (y = 0; y < NUM_DCHANS; y++) {
08705 if (pris[x].dchans[y])
08706 dchancount++;
08707
08708 if (pris[x].dchans[y] == pri)
08709 dchan = y;
08710 }
08711 if (dchan >= 0) {
08712 span = x;
08713 break;
08714 }
08715 dchancount = 0;
08716 }
08717 if ((dchan >= 0) && (span >= 0)) {
08718 if (dchancount > 1)
08719 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
08720 else
08721 ast_verbose("%s", s);
08722 } else
08723 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08724 } else
08725 ast_verbose("%s", s);
08726
08727 ast_mutex_lock(&pridebugfdlock);
08728
08729 if (pridebugfd >= 0) {
08730 if (write(pridebugfd, s, strlen(s)) < 0) {
08731 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08732 }
08733 }
08734
08735 ast_mutex_unlock(&pridebugfdlock);
08736 }
08737
08738 static void dahdi_pri_error(struct pri *pri, char *s)
08739 {
08740 int x, y;
08741 int dchan = -1, span = -1;
08742 int dchancount = 0;
08743
08744 if (pri) {
08745 for (x = 0; x < NUM_SPANS; x++) {
08746 for (y = 0; y < NUM_DCHANS; y++) {
08747 if (pris[x].dchans[y])
08748 dchancount++;
08749
08750 if (pris[x].dchans[y] == pri)
08751 dchan = y;
08752 }
08753 if (dchan >= 0) {
08754 span = x;
08755 break;
08756 }
08757 dchancount = 0;
08758 }
08759 if ((dchan >= 0) && (span >= 0)) {
08760 if (dchancount > 1)
08761 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
08762 else
08763 ast_log(LOG_ERROR, "%s", s);
08764 } else
08765 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08766 } else
08767 ast_log(LOG_ERROR, "%s", s);
08768
08769 ast_mutex_lock(&pridebugfdlock);
08770
08771 if (pridebugfd >= 0) {
08772 if (write(pridebugfd, s, strlen(s)) < 0) {
08773 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08774 }
08775 }
08776
08777 ast_mutex_unlock(&pridebugfdlock);
08778 }
08779
08780 static int pri_check_restart(struct dahdi_pri *pri)
08781 {
08782 do {
08783 pri->resetpos++;
08784 } while ((pri->resetpos < pri->numchans) &&
08785 (!pri->pvts[pri->resetpos] ||
08786 pri->pvts[pri->resetpos]->call ||
08787 pri->pvts[pri->resetpos]->resetting));
08788 if (pri->resetpos < pri->numchans) {
08789
08790 pri->pvts[pri->resetpos]->resetting = 1;
08791 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
08792 } else {
08793 pri->resetting = 0;
08794 time(&pri->lastreset);
08795 }
08796 return 0;
08797 }
08798
08799 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
08800 {
08801 int x;
08802 int redo;
08803 ast_mutex_unlock(&pri->lock);
08804 ast_mutex_lock(&p->lock);
08805 do {
08806 redo = 0;
08807 for (x = 0; x < 3; x++) {
08808 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
08809 redo++;
08810 DEADLOCK_AVOIDANCE(&p->lock);
08811 }
08812 if (p->subs[x].owner) {
08813 ast_queue_hangup(p->subs[x].owner);
08814 ast_mutex_unlock(&p->subs[x].owner->lock);
08815 }
08816 }
08817 } while (redo);
08818 ast_mutex_unlock(&p->lock);
08819 ast_mutex_lock(&pri->lock);
08820 return 0;
08821 }
08822
08823 static char * redirectingreason2str(int redirectingreason)
08824 {
08825 switch (redirectingreason) {
08826 case 0:
08827 return "UNKNOWN";
08828 case 1:
08829 return "BUSY";
08830 case 2:
08831 return "NO_REPLY";
08832 case 0xF:
08833 return "UNCONDITIONAL";
08834 default:
08835 return "NOREDIRECT";
08836 }
08837 }
08838
08839 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
08840 {
08841 switch (plan) {
08842 case PRI_INTERNATIONAL_ISDN:
08843 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
08844 break;
08845 case PRI_NATIONAL_ISDN:
08846 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
08847 break;
08848 case PRI_LOCAL_ISDN:
08849 snprintf(buf, size, "%s%s", pri->localprefix, number);
08850 break;
08851 case PRI_PRIVATE:
08852 snprintf(buf, size, "%s%s", pri->privateprefix, number);
08853 break;
08854 case PRI_UNKNOWN:
08855 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
08856 break;
08857 default:
08858 snprintf(buf, size, "%s", number);
08859 break;
08860 }
08861 }
08862
08863 static int dahdi_setlaw(int dfd, int law)
08864 {
08865 int res;
08866 res = ioctl(dfd, DAHDI_SETLAW, &law);
08867 if (res)
08868 return res;
08869 return 0;
08870 }
08871
08872 static void *pri_dchannel(void *vpri)
08873 {
08874 struct dahdi_pri *pri = vpri;
08875 pri_event *e;
08876 struct pollfd fds[NUM_DCHANS];
08877 int res;
08878 int chanpos = 0;
08879 int x;
08880 int haveidles;
08881 int activeidles;
08882 int nextidle = -1;
08883 struct ast_channel *c;
08884 struct timeval tv, lowest, *next;
08885 struct timeval lastidle = { 0, 0 };
08886 int doidling=0;
08887 char *cc;
08888 char idlen[80];
08889 struct ast_channel *idle;
08890 pthread_t p;
08891 time_t t;
08892 int i, which=-1;
08893 int numdchans;
08894 int cause=0;
08895 struct dahdi_pvt *crv;
08896 pthread_t threadid;
08897 pthread_attr_t attr;
08898 char ani2str[6];
08899 char plancallingnum[256];
08900 char plancallingani[256];
08901 char calledtonstr[10];
08902
08903 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08904
08905 gettimeofday(&lastidle, NULL);
08906 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
08907
08908 cc = strchr(pri->idleext, '@');
08909 if (cc) {
08910 *cc = '\0';
08911 cc++;
08912 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
08913 #if 0
08914
08915 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
08916 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
08917 else
08918 #endif
08919 doidling = 1;
08920 } else
08921 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
08922 }
08923 for (;;) {
08924 for (i = 0; i < NUM_DCHANS; i++) {
08925 if (!pri->dchannels[i])
08926 break;
08927 fds[i].fd = pri->fds[i];
08928 fds[i].events = POLLIN | POLLPRI;
08929 fds[i].revents = 0;
08930 }
08931 numdchans = i;
08932 time(&t);
08933 ast_mutex_lock(&pri->lock);
08934 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
08935 if (pri->resetting && pri_is_up(pri)) {
08936 if (pri->resetpos < 0)
08937 pri_check_restart(pri);
08938 } else {
08939 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
08940 pri->resetting = 1;
08941 pri->resetpos = -1;
08942 }
08943 }
08944 }
08945
08946 if (doidling && pri_is_up(pri)) {
08947 nextidle = -1;
08948 haveidles = 0;
08949 activeidles = 0;
08950 for (x = pri->numchans; x >= 0; x--) {
08951 if (pri->pvts[x] && !pri->pvts[x]->owner &&
08952 !pri->pvts[x]->call) {
08953 if (haveidles < pri->minunused) {
08954 haveidles++;
08955 } else if (!pri->pvts[x]->resetting) {
08956 nextidle = x;
08957 break;
08958 }
08959 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
08960 activeidles++;
08961 }
08962 if (nextidle > -1) {
08963 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
08964
08965 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
08966 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
08967 if (idle) {
08968 pri->pvts[nextidle]->isidlecall = 1;
08969 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
08970 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
08971 dahdi_hangup(idle);
08972 }
08973 } else
08974 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
08975 gettimeofday(&lastidle, NULL);
08976 }
08977 } else if ((haveidles < pri->minunused) &&
08978 (activeidles > pri->minidle)) {
08979
08980
08981 for (x = pri->numchans; x >= 0; x--) {
08982
08983 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
08984 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08985 haveidles++;
08986
08987
08988 if ((haveidles >= pri->minunused) ||
08989 (activeidles <= pri->minidle))
08990 break;
08991 }
08992 }
08993 }
08994 }
08995
08996 lowest = ast_tv(60, 0);
08997 for (i = 0; i < NUM_DCHANS; i++) {
08998
08999 if (!pri->dchannels[i])
09000 break;
09001 if ((next = pri_schedule_next(pri->dchans[i]))) {
09002
09003 tv = ast_tvsub(*next, ast_tvnow());
09004 if (tv.tv_sec < 0) {
09005 tv = ast_tv(0,0);
09006 }
09007 if (doidling || pri->resetting) {
09008 if (tv.tv_sec > 1) {
09009 tv = ast_tv(1, 0);
09010 }
09011 } else {
09012 if (tv.tv_sec > 60) {
09013 tv = ast_tv(60, 0);
09014 }
09015 }
09016 } else if (doidling || pri->resetting) {
09017
09018
09019 tv = ast_tv(1,0);
09020 } else {
09021
09022 tv = ast_tv(60, 0);
09023 }
09024 if (!i || ast_tvcmp(tv, lowest) < 0) {
09025 lowest = tv;
09026 }
09027 }
09028 ast_mutex_unlock(&pri->lock);
09029
09030 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09031 pthread_testcancel();
09032 e = NULL;
09033 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
09034 pthread_testcancel();
09035 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09036
09037 ast_mutex_lock(&pri->lock);
09038 if (!res) {
09039 for (which = 0; which < NUM_DCHANS; which++) {
09040 if (!pri->dchans[which])
09041 break;
09042
09043 e = pri_schedule_run(pri->dchans[which]);
09044 if (e)
09045 break;
09046 }
09047 } else if (res > -1) {
09048 for (which = 0; which < NUM_DCHANS; which++) {
09049 if (!pri->dchans[which])
09050 break;
09051 if (fds[which].revents & POLLPRI) {
09052
09053 x = 0;
09054 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
09055 if (x)
09056 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);
09057
09058 if (x == DAHDI_EVENT_ALARM) {
09059 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
09060 pri_find_dchan(pri);
09061 } else if (x == DAHDI_EVENT_NOALARM) {
09062 pri->dchanavail[which] |= DCHAN_NOTINALARM;
09063 pri_restart(pri->dchans[which]);
09064 }
09065
09066 if (option_debug)
09067 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
09068 } else if (fds[which].revents & POLLIN) {
09069 e = pri_check_event(pri->dchans[which]);
09070 }
09071 if (e)
09072 break;
09073 }
09074 } else if (errno != EINTR)
09075 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
09076
09077 if (e) {
09078 if (pri->debug)
09079 pri_dump_event(pri->dchans[which], e);
09080
09081 if (e->e != PRI_EVENT_DCHAN_DOWN) {
09082 if (!(pri->dchanavail[which] & DCHAN_UP)) {
09083 if (option_verbose > 1)
09084 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
09085 }
09086 pri->dchanavail[which] |= DCHAN_UP;
09087 } else {
09088 if (pri->dchanavail[which] & DCHAN_UP) {
09089 if (option_verbose > 1)
09090 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
09091 }
09092 pri->dchanavail[which] &= ~DCHAN_UP;
09093 }
09094
09095 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
09096
09097 pri->pri = pri->dchans[which];
09098
09099 switch (e->e) {
09100 case PRI_EVENT_DCHAN_UP:
09101 if (!pri->pri) pri_find_dchan(pri);
09102
09103
09104 time(&pri->lastreset);
09105
09106
09107 if (pri->resetinterval > -1) {
09108 pri->lastreset -= pri->resetinterval;
09109 pri->lastreset += 5;
09110 }
09111 pri->resetting = 0;
09112
09113 for (i = 0; i < pri->numchans; i++)
09114 if (pri->pvts[i]) {
09115 pri->pvts[i]->inalarm = 0;
09116 }
09117 break;
09118 case PRI_EVENT_DCHAN_DOWN:
09119 pri_find_dchan(pri);
09120 if (!pri_is_up(pri)) {
09121 pri->resetting = 0;
09122
09123 for (i = 0; i < pri->numchans; i++) {
09124 struct dahdi_pvt *p = pri->pvts[i];
09125 if (p) {
09126 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
09127
09128 if (p->call) {
09129 if (p->pri && p->pri->pri) {
09130 pri_hangup(p->pri->pri, p->call, -1);
09131 pri_destroycall(p->pri->pri, p->call);
09132 p->call = NULL;
09133 } else
09134 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
09135 }
09136 if (p->realcall) {
09137 pri_hangup_all(p->realcall, pri);
09138 } else if (p->owner)
09139 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09140 }
09141 p->inalarm = 1;
09142 }
09143 }
09144 }
09145 break;
09146 case PRI_EVENT_RESTART:
09147 if (e->restart.channel > -1) {
09148 chanpos = pri_find_principle(pri, e->restart.channel);
09149 if (chanpos < 0)
09150 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
09151 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
09152 else {
09153 if (option_verbose > 2)
09154 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
09155 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
09156 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09157 if (pri->pvts[chanpos]->call) {
09158 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
09159 pri->pvts[chanpos]->call = NULL;
09160 }
09161
09162 if (pri->pvts[chanpos]->realcall)
09163 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09164 else if (pri->pvts[chanpos]->owner)
09165 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09166 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09167 }
09168 } else {
09169 if (option_verbose > 2)
09170 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
09171 for (x = 0; x < pri->numchans; x++)
09172 if (pri->pvts[x]) {
09173 ast_mutex_lock(&pri->pvts[x]->lock);
09174 if (pri->pvts[x]->call) {
09175 pri_destroycall(pri->pri, pri->pvts[x]->call);
09176 pri->pvts[x]->call = NULL;
09177 }
09178 if (pri->pvts[chanpos]->realcall)
09179 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09180 else if (pri->pvts[x]->owner)
09181 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09182 ast_mutex_unlock(&pri->pvts[x]->lock);
09183 }
09184 }
09185 break;
09186 case PRI_EVENT_KEYPAD_DIGIT:
09187 chanpos = pri_find_principle(pri, e->digit.channel);
09188 if (chanpos < 0) {
09189 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
09190 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
09191 } else {
09192 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
09193 if (chanpos > -1) {
09194 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09195
09196 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
09197
09198 int digitlen = strlen(e->digit.digits);
09199 char digit;
09200 int i;
09201 for (i = 0; i < digitlen; i++) {
09202 digit = e->digit.digits[i];
09203 {
09204 struct ast_frame f = { AST_FRAME_DTMF, digit, };
09205 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09206 }
09207 }
09208 }
09209 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09210 }
09211 }
09212 break;
09213
09214 case PRI_EVENT_INFO_RECEIVED:
09215 chanpos = pri_find_principle(pri, e->ring.channel);
09216 if (chanpos < 0) {
09217 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
09218 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09219 } else {
09220 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
09221 if (chanpos > -1) {
09222 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09223
09224 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
09225
09226 int digitlen = strlen(e->ring.callednum);
09227 char digit;
09228 int i;
09229 for (i = 0; i < digitlen; i++) {
09230 digit = e->ring.callednum[i];
09231 {
09232 struct ast_frame f = { AST_FRAME_DTMF, digit, };
09233 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09234 }
09235 }
09236 }
09237 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09238 }
09239 }
09240 break;
09241 case PRI_EVENT_RING:
09242 crv = NULL;
09243 if (e->ring.channel == -1)
09244 chanpos = pri_find_empty_chan(pri, 1);
09245 else
09246 chanpos = pri_find_principle(pri, e->ring.channel);
09247
09248 if (chanpos < 0) {
09249 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
09250 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09251 } else {
09252 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09253 if (pri->pvts[chanpos]->owner) {
09254 if (pri->pvts[chanpos]->call == e->ring.call) {
09255 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
09256 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09257 break;
09258 } else {
09259
09260 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
09261 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09262 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09263 chanpos = -1;
09264 }
09265 }
09266 if (chanpos > -1)
09267 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09268 }
09269 if ((chanpos < 0) && (e->ring.flexible))
09270 chanpos = pri_find_empty_chan(pri, 1);
09271 if (chanpos > -1) {
09272 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09273 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
09274
09275 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
09276 if (crv)
09277 ast_mutex_lock(&crv->lock);
09278 if (!crv || crv->owner) {
09279 pri->pvts[chanpos]->call = NULL;
09280 if (crv) {
09281 if (crv->owner)
09282 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09283 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);
09284 } else
09285 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);
09286 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
09287 if (crv)
09288 ast_mutex_unlock(&crv->lock);
09289 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09290 break;
09291 }
09292 }
09293 pri->pvts[chanpos]->call = e->ring.call;
09294 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
09295 if (pri->pvts[chanpos]->use_callerid) {
09296 ast_shrink_phone_number(plancallingnum);
09297 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
09298 #ifdef PRI_ANI
09299 if (!ast_strlen_zero(e->ring.callingani)) {
09300 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
09301 ast_shrink_phone_number(plancallingani);
09302 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
09303 } else {
09304 pri->pvts[chanpos]->cid_ani[0] = '\0';
09305 }
09306 #endif
09307 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
09308 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
09309 } else {
09310 pri->pvts[chanpos]->cid_num[0] = '\0';
09311 pri->pvts[chanpos]->cid_ani[0] = '\0';
09312 pri->pvts[chanpos]->cid_name[0] = '\0';
09313 pri->pvts[chanpos]->cid_ton = 0;
09314 }
09315 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
09316 e->ring.redirectingnum, e->ring.callingplanrdnis);
09317
09318 if (pri->pvts[chanpos]->immediate) {
09319 if (option_verbose > 2)
09320 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
09321 pri->pvts[chanpos]->exten[0] = 's';
09322 pri->pvts[chanpos]->exten[1] = '\0';
09323 }
09324
09325 else if (!ast_strlen_zero(e->ring.callednum)) {
09326 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
09327 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09328 } else if (pri->overlapdial)
09329 pri->pvts[chanpos]->exten[0] = '\0';
09330 else {
09331
09332 pri->pvts[chanpos]->exten[0] = 's';
09333 pri->pvts[chanpos]->exten[1] = '\0';
09334 }
09335
09336 if (!ast_strlen_zero(e->ring.callednum))
09337 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09338
09339 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
09340 if (option_verbose > 2)
09341 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
09342 pri->pvts[chanpos]->exten[0] = 's';
09343 pri->pvts[chanpos]->exten[1] = '\0';
09344 }
09345
09346 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
09347 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09348
09349 int law;
09350 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
09351
09352 law = 1;
09353 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09354 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
09355 }
09356 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
09357 law = DAHDI_LAW_ALAW;
09358 else
09359 law = DAHDI_LAW_MULAW;
09360 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
09361 if (res < 0)
09362 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
09363 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
09364 if (res < 0)
09365 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
09366 if (e->ring.complete || !pri->overlapdial) {
09367
09368 pri->pvts[chanpos]->proceeding = 1;
09369 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
09370 } else {
09371 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
09372 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09373 else
09374 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09375 }
09376
09377 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
09378
09379
09380 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09381
09382 ast_mutex_unlock(&pri->lock);
09383 if (crv) {
09384
09385 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
09386 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09387 pri->pvts[chanpos]->owner = &inuse;
09388 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
09389 } else {
09390 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09391 }
09392
09393 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09394
09395 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
09396 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
09397 }
09398 if (e->ring.ani2 >= 0) {
09399 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
09400 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09401 }
09402
09403 #ifdef SUPPORT_USERUSER
09404 if (!ast_strlen_zero(e->ring.useruserinfo)) {
09405 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09406 }
09407 #endif
09408
09409 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09410 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09411 if (e->ring.redirectingreason >= 0)
09412 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09413
09414 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09415 ast_mutex_lock(&pri->lock);
09416
09417 pthread_attr_init(&attr);
09418 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09419 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
09420 if (option_verbose > 2)
09421 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
09422 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
09423 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09424 } else {
09425 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
09426 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09427 if (c)
09428 ast_hangup(c);
09429 else {
09430 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09431 pri->pvts[chanpos]->call = NULL;
09432 }
09433 }
09434 pthread_attr_destroy(&attr);
09435 } else {
09436 ast_mutex_unlock(&pri->lock);
09437
09438 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
09439 if (c) {
09440 char calledtonstr[10];
09441
09442 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09443
09444 if (e->ring.ani2 >= 0) {
09445 snprintf(ani2str, 5, "%d", e->ring.ani2);
09446 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09447 }
09448
09449 #ifdef SUPPORT_USERUSER
09450 if (!ast_strlen_zero(e->ring.useruserinfo)) {
09451 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09452 }
09453 #endif
09454
09455 if (e->ring.redirectingreason >= 0)
09456 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09457
09458 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09459 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09460
09461 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09462 ast_mutex_lock(&pri->lock);
09463
09464 if (option_verbose > 2)
09465 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
09466 plancallingnum, pri->pvts[chanpos]->exten,
09467 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09468 dahdi_enable_ec(pri->pvts[chanpos]);
09469 } else {
09470
09471 ast_mutex_lock(&pri->lock);
09472
09473 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
09474 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09475 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09476 pri->pvts[chanpos]->call = NULL;
09477 }
09478 }
09479 } else {
09480 if (option_verbose > 2)
09481 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
09482 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
09483 pri->pvts[chanpos]->prioffset, pri->span);
09484 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
09485 pri->pvts[chanpos]->call = NULL;
09486 pri->pvts[chanpos]->exten[0] = '\0';
09487 }
09488 if (crv)
09489 ast_mutex_unlock(&crv->lock);
09490 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09491 } else {
09492 if (e->ring.flexible)
09493 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
09494 else
09495 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
09496 }
09497 break;
09498 case PRI_EVENT_RINGING:
09499 chanpos = pri_find_principle(pri, e->ringing.channel);
09500 if (chanpos < 0) {
09501 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
09502 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09503 } else {
09504 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
09505 if (chanpos < 0) {
09506 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
09507 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09508 } else {
09509 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09510 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09511 dahdi_enable_ec(pri->pvts[chanpos]);
09512 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
09513 pri->pvts[chanpos]->alerting = 1;
09514 } else
09515 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
09516 #ifdef PRI_PROGRESS_MASK
09517 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09518 #else
09519 if (e->ringing.progress == 8) {
09520 #endif
09521
09522 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09523
09524 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
09525 pri->pvts[chanpos]->dsp_features = 0;
09526 }
09527 }
09528
09529 #ifdef SUPPORT_USERUSER
09530 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
09531 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09532 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09533 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
09534 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09535 }
09536 #endif
09537
09538 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09539 }
09540 }
09541 break;
09542 case PRI_EVENT_PROGRESS:
09543
09544 chanpos = pri_find_principle(pri, e->proceeding.channel);
09545 if (chanpos > -1) {
09546 #ifdef PRI_PROGRESS_MASK
09547 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
09548 #else
09549 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
09550 #endif
09551 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
09552
09553 if (e->proceeding.cause > -1) {
09554 if (option_verbose > 2)
09555 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
09556
09557
09558 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
09559 if (pri->pvts[chanpos]->owner) {
09560 if (option_verbose > 2)
09561 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
09562
09563 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
09564 f.subclass = AST_CONTROL_BUSY;
09565 }
09566 }
09567 }
09568
09569 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09570 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
09571 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09572 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09573 #ifdef PRI_PROGRESS_MASK
09574 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09575 #else
09576 if (e->proceeding.progress == 8) {
09577 #endif
09578
09579 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09580 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09581 pri->pvts[chanpos]->dsp_features = 0;
09582 }
09583 }
09584 pri->pvts[chanpos]->progress = 1;
09585 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09586 }
09587 }
09588 break;
09589 case PRI_EVENT_PROCEEDING:
09590 chanpos = pri_find_principle(pri, e->proceeding.channel);
09591 if (chanpos > -1) {
09592 if (!pri->pvts[chanpos]->proceeding) {
09593 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
09594
09595 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09596 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
09597 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09598 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09599 #ifdef PRI_PROGRESS_MASK
09600 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09601 #else
09602 if (e->proceeding.progress == 8) {
09603 #endif
09604
09605 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09606 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09607 pri->pvts[chanpos]->dsp_features = 0;
09608 }
09609
09610 f.subclass = AST_CONTROL_PROGRESS;
09611 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09612 }
09613 pri->pvts[chanpos]->proceeding = 1;
09614 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09615 }
09616 }
09617 break;
09618 case PRI_EVENT_FACNAME:
09619 chanpos = pri_find_principle(pri, e->facname.channel);
09620 if (chanpos < 0) {
09621 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
09622 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09623 } else {
09624 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
09625 if (chanpos < 0) {
09626 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
09627 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09628 } else {
09629
09630 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09631 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
09632 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
09633 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
09634 dahdi_enable_ec(pri->pvts[chanpos]);
09635 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09636 }
09637 }
09638 break;
09639 case PRI_EVENT_ANSWER:
09640 chanpos = pri_find_principle(pri, e->answer.channel);
09641 if (chanpos < 0) {
09642 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
09643 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09644 } else {
09645 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
09646 if (chanpos < 0) {
09647 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
09648 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09649 } else {
09650 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09651
09652
09653
09654
09655
09656 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09657 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09658 pri->pvts[chanpos]->dsp_features = 0;
09659 }
09660 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
09661 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
09662 x = DAHDI_START;
09663 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09664 if (res < 0) {
09665 if (errno != EINPROGRESS) {
09666 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
09667 }
09668 }
09669 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09670 pri->pvts[chanpos]->dialing = 1;
09671
09672 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
09673 if (res < 0) {
09674 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
09675 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09676 } else
09677 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
09678 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09679 } else if (pri->pvts[chanpos]->confirmanswer) {
09680 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
09681 } else {
09682 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
09683
09684 dahdi_enable_ec(pri->pvts[chanpos]);
09685 }
09686
09687 #ifdef SUPPORT_USERUSER
09688 if (!ast_strlen_zero(e->answer.useruserinfo)) {
09689 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09690 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09691 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
09692 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09693 }
09694 #endif
09695
09696 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09697 }
09698 }
09699 break;
09700 case PRI_EVENT_HANGUP:
09701 chanpos = pri_find_principle(pri, e->hangup.channel);
09702 if (chanpos < 0) {
09703 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
09704 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09705 } else {
09706 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09707 if (chanpos > -1) {
09708 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09709 if (!pri->pvts[chanpos]->alreadyhungup) {
09710
09711 pri->pvts[chanpos]->alreadyhungup = 1;
09712 if (pri->pvts[chanpos]->realcall)
09713 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09714 else if (pri->pvts[chanpos]->owner) {
09715
09716 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09717 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09718 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09719 else {
09720 switch (e->hangup.cause) {
09721 case PRI_CAUSE_USER_BUSY:
09722 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09723 break;
09724 case PRI_CAUSE_CALL_REJECTED:
09725 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09726 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09727 case PRI_CAUSE_SWITCH_CONGESTION:
09728 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09729 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09730 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09731 break;
09732 default:
09733 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09734 }
09735 }
09736 }
09737 if (option_verbose > 2)
09738 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
09739 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
09740 } else {
09741 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09742 pri->pvts[chanpos]->call = NULL;
09743 }
09744 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09745 if (option_verbose > 2)
09746 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
09747 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09748 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09749 pri->pvts[chanpos]->resetting = 1;
09750 }
09751 if (e->hangup.aoc_units > -1)
09752 if (option_verbose > 2)
09753 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09754 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09755
09756 #ifdef SUPPORT_USERUSER
09757 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
09758 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09759 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09760 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09761 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09762 }
09763 #endif
09764
09765 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09766 } else {
09767 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
09768 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09769 }
09770 }
09771 break;
09772 #ifndef PRI_EVENT_HANGUP_REQ
09773 #error please update libpri
09774 #endif
09775 case PRI_EVENT_HANGUP_REQ:
09776 chanpos = pri_find_principle(pri, e->hangup.channel);
09777 if (chanpos < 0) {
09778 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
09779 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09780 } else {
09781 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09782 if (chanpos > -1) {
09783 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09784 if (pri->pvts[chanpos]->realcall)
09785 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09786 else if (pri->pvts[chanpos]->owner) {
09787 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09788 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09789 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09790 else {
09791 switch (e->hangup.cause) {
09792 case PRI_CAUSE_USER_BUSY:
09793 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09794 break;
09795 case PRI_CAUSE_CALL_REJECTED:
09796 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09797 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09798 case PRI_CAUSE_SWITCH_CONGESTION:
09799 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09800 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09801 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09802 break;
09803 default:
09804 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09805 }
09806 }
09807 if (option_verbose > 2)
09808 ast_verbose(VERBOSE_PREFIX_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);
09809 if (e->hangup.aoc_units > -1)
09810 if (option_verbose > 2)
09811 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09812 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09813 } else {
09814 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09815 pri->pvts[chanpos]->call = NULL;
09816 }
09817 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09818 if (option_verbose > 2)
09819 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
09820 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09821 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09822 pri->pvts[chanpos]->resetting = 1;
09823 }
09824
09825 #ifdef SUPPORT_USERUSER
09826 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09827 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09828 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09829 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09830 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09831 }
09832 #endif
09833
09834 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09835 } else {
09836 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);
09837 }
09838 }
09839 break;
09840 case PRI_EVENT_HANGUP_ACK:
09841 chanpos = pri_find_principle(pri, e->hangup.channel);
09842 if (chanpos < 0) {
09843 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
09844 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09845 } else {
09846 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09847 if (chanpos > -1) {
09848 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09849 pri->pvts[chanpos]->call = NULL;
09850 pri->pvts[chanpos]->resetting = 0;
09851 if (pri->pvts[chanpos]->owner) {
09852 if (option_verbose > 2)
09853 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09854 }
09855
09856 #ifdef SUPPORT_USERUSER
09857 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09858 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09859 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09860 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09861 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09862 }
09863 #endif
09864
09865 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09866 }
09867 }
09868 break;
09869 case PRI_EVENT_CONFIG_ERR:
09870 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
09871 break;
09872 case PRI_EVENT_RESTART_ACK:
09873 chanpos = pri_find_principle(pri, e->restartack.channel);
09874 if (chanpos < 0) {
09875
09876
09877
09878 for (x = 0; x < pri->numchans; x++) {
09879 if (pri->pvts[x] && pri->pvts[x]->resetting) {
09880 chanpos = x;
09881 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09882 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
09883 pri->pvts[chanpos]->prioffset, pri->span);
09884 if (pri->pvts[chanpos]->realcall)
09885 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09886 else if (pri->pvts[chanpos]->owner) {
09887 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
09888 pri->pvts[chanpos]->prioffset, pri->span);
09889 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09890 }
09891 pri->pvts[chanpos]->resetting = 0;
09892 if (option_verbose > 2)
09893 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
09894 pri->pvts[chanpos]->prioffset, pri->span);
09895 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09896 if (pri->resetting)
09897 pri_check_restart(pri);
09898 break;
09899 }
09900 }
09901 if (chanpos < 0) {
09902 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
09903 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09904 }
09905 } else {
09906 if (pri->pvts[chanpos]) {
09907 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09908 if (pri->pvts[chanpos]->realcall)
09909 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09910 else if (pri->pvts[chanpos]->owner) {
09911 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
09912 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09913 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09914 }
09915 pri->pvts[chanpos]->resetting = 0;
09916 if (option_verbose > 2)
09917 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
09918 pri->pvts[chanpos]->prioffset, pri->span);
09919 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09920 if (pri->resetting)
09921 pri_check_restart(pri);
09922 }
09923 }
09924 break;
09925 case PRI_EVENT_SETUP_ACK:
09926 chanpos = pri_find_principle(pri, e->setup_ack.channel);
09927 if (chanpos < 0) {
09928 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
09929 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
09930 } else {
09931 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
09932 if (chanpos > -1) {
09933 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09934 pri->pvts[chanpos]->setup_ack = 1;
09935
09936 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
09937 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
09938 pri_information(pri->pri, pri->pvts[chanpos]->call,
09939 pri->pvts[chanpos]->dialdest[x]);
09940 }
09941 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09942 } else
09943 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
09944 }
09945 break;
09946 case PRI_EVENT_NOTIFY:
09947 chanpos = pri_find_principle(pri, e->notify.channel);
09948 if (chanpos < 0) {
09949 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
09950 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
09951 } else {
09952 struct ast_frame f = { AST_FRAME_CONTROL, };
09953 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09954 switch (e->notify.info) {
09955 case PRI_NOTIFY_REMOTE_HOLD:
09956 f.subclass = AST_CONTROL_HOLD;
09957 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09958 break;
09959 case PRI_NOTIFY_REMOTE_RETRIEVAL:
09960 f.subclass = AST_CONTROL_UNHOLD;
09961 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09962 break;
09963 }
09964 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09965 }
09966 break;
09967 default:
09968 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
09969 }
09970 }
09971 ast_mutex_unlock(&pri->lock);
09972 }
09973
09974 return NULL;
09975 }
09976
09977 static int start_pri(struct dahdi_pri *pri)
09978 {
09979 int res, x;
09980 struct dahdi_params p;
09981 struct dahdi_bufferinfo bi;
09982 struct dahdi_spaninfo si;
09983 int i;
09984
09985 for (i = 0; i < NUM_DCHANS; i++) {
09986 if (!pri->dchannels[i])
09987 break;
09988 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
09989 x = pri->dchannels[i];
09990 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
09991 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
09992 return -1;
09993 }
09994 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
09995 if (res) {
09996 dahdi_close_pri_fd(pri, i);
09997 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
09998 return -1;
09999 }
10000 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
10001 dahdi_close_pri_fd(pri, i);
10002 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
10003 return -1;
10004 }
10005 memset(&si, 0, sizeof(si));
10006 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
10007 if (res) {
10008 dahdi_close_pri_fd(pri, i);
10009 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
10010 }
10011 if (!si.alarms)
10012 pri->dchanavail[i] |= DCHAN_NOTINALARM;
10013 else
10014 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
10015 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
10016 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
10017 bi.numbufs = 32;
10018 bi.bufsize = 1024;
10019 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
10020 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
10021 dahdi_close_pri_fd(pri, i);
10022 return -1;
10023 }
10024 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
10025
10026 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
10027 pri->overlapdial = 1;
10028 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
10029 #ifdef HAVE_PRI_INBANDDISCONNECT
10030 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
10031 #endif
10032
10033 if (i)
10034 pri_enslave(pri->dchans[0], pri->dchans[i]);
10035 if (!pri->dchans[i]) {
10036 dahdi_close_pri_fd(pri, i);
10037 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
10038 return -1;
10039 }
10040 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
10041 pri_set_nsf(pri->dchans[i], pri->nsf);
10042 #ifdef PRI_GETSET_TIMERS
10043 for (x = 0; x < PRI_MAX_TIMERS; x++) {
10044 if (pritimers[x] != 0)
10045 pri_set_timer(pri->dchans[i], x, pritimers[x]);
10046 }
10047 #endif
10048 }
10049
10050 pri->pri = pri->dchans[0];
10051 pri->resetpos = -1;
10052 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
10053 for (i = 0; i < NUM_DCHANS; i++) {
10054 if (!pri->dchannels[i])
10055 break;
10056 dahdi_close_pri_fd(pri, i);
10057 }
10058 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
10059 return -1;
10060 }
10061 return 0;
10062 }
10063
10064 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
10065 {
10066 int which, span;
10067 char *ret = NULL;
10068
10069 if (pos != rpos)
10070 return ret;
10071
10072 for (which = span = 0; span < NUM_SPANS; span++) {
10073 if (pris[span].pri && ++which > state) {
10074 if (asprintf(&ret, "%d", span + 1) < 0) {
10075 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
10076 }
10077 break;
10078 }
10079 }
10080 return ret;
10081 }
10082
10083 static char *complete_span_4(const char *line, const char *word, int pos, int state)
10084 {
10085 return complete_span_helper(line,word,pos,state,3);
10086 }
10087
10088 static char *complete_span_5(const char *line, const char *word, int pos, int state)
10089 {
10090 return complete_span_helper(line,word,pos,state,4);
10091 }
10092
10093 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
10094 {
10095 int myfd;
10096
10097 if (!strncasecmp(argv[1], "set", 3)) {
10098 if (argc < 5)
10099 return RESULT_SHOWUSAGE;
10100
10101 if (ast_strlen_zero(argv[4]))
10102 return RESULT_SHOWUSAGE;
10103
10104 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
10105 if (myfd < 0) {
10106 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
10107 return RESULT_SUCCESS;
10108 }
10109
10110 ast_mutex_lock(&pridebugfdlock);
10111
10112 if (pridebugfd >= 0)
10113 close(pridebugfd);
10114
10115 pridebugfd = myfd;
10116 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
10117
10118 ast_mutex_unlock(&pridebugfdlock);
10119
10120 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
10121 } else {
10122
10123 ast_mutex_lock(&pridebugfdlock);
10124 close(pridebugfd);
10125 pridebugfd = -1;
10126 ast_cli(fd, "PRI debug output to file disabled\n");
10127 ast_mutex_unlock(&pridebugfdlock);
10128 }
10129
10130 return RESULT_SUCCESS;
10131 }
10132
10133 #ifdef HAVE_PRI_VERSION
10134 static int handle_pri_version(int fd, int agc, char *argv[]) {
10135 ast_cli(fd, "libpri version: %s\n", pri_get_version());
10136 return RESULT_SUCCESS;
10137 }
10138 #endif
10139
10140 static int handle_pri_debug(int fd, int argc, char *argv[])
10141 {
10142 int span;
10143 int x;
10144 if (argc < 4) {
10145 return RESULT_SHOWUSAGE;
10146 }
10147 span = atoi(argv[3]);
10148 if ((span < 1) || (span > NUM_SPANS)) {
10149 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
10150 return RESULT_SUCCESS;
10151 }
10152 if (!pris[span-1].pri) {
10153 ast_cli(fd, "No PRI running on span %d\n", span);
10154 return RESULT_SUCCESS;
10155 }
10156 for (x = 0; x < NUM_DCHANS; x++) {
10157 if (pris[span-1].dchans[x])
10158 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
10159 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
10160 PRI_DEBUG_Q921_STATE);
10161 }
10162 ast_cli(fd, "Enabled debugging on span %d\n", span);
10163 return RESULT_SUCCESS;
10164 }
10165
10166
10167
10168 static int handle_pri_no_debug(int fd, int argc, char *argv[])
10169 {
10170 int span;
10171 int x;
10172 if (argc < 5)
10173 return RESULT_SHOWUSAGE;
10174 span = atoi(argv[4]);
10175 if ((span < 1) || (span > NUM_SPANS)) {
10176 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
10177 return RESULT_SUCCESS;
10178 }
10179 if (!pris[span-1].pri) {
10180 ast_cli(fd, "No PRI running on span %d\n", span);
10181 return RESULT_SUCCESS;
10182 }
10183 for (x = 0; x < NUM_DCHANS; x++) {
10184 if (pris[span-1].dchans[x])
10185 pri_set_debug(pris[span-1].dchans[x], 0);
10186 }
10187 ast_cli(fd, "Disabled debugging on span %d\n", span);
10188 return RESULT_SUCCESS;
10189 }
10190
10191 static int handle_pri_really_debug(int fd, int argc, char *argv[])
10192 {
10193 int span;
10194 int x;
10195 if (argc < 5)
10196 return RESULT_SHOWUSAGE;
10197 span = atoi(argv[4]);
10198 if ((span < 1) || (span > NUM_SPANS)) {
10199 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
10200 return RESULT_SUCCESS;
10201 }
10202 if (!pris[span-1].pri) {
10203 ast_cli(fd, "No PRI running on span %d\n", span);
10204 return RESULT_SUCCESS;
10205 }
10206 for (x = 0; x < NUM_DCHANS; x++) {
10207 if (pris[span-1].dchans[x])
10208 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
10209 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
10210 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
10211 }
10212 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
10213 return RESULT_SUCCESS;
10214 }
10215
10216 static void build_status(char *s, size_t len, int status, int active)
10217 {
10218 if (!s || len < 1) {
10219 return;
10220 }
10221 s[0] = '\0';
10222 if (status & DCHAN_PROVISIONED)
10223 strncat(s, "Provisioned, ", len - strlen(s) - 1);
10224 if (!(status & DCHAN_NOTINALARM))
10225 strncat(s, "In Alarm, ", len - strlen(s) - 1);
10226 if (status & DCHAN_UP)
10227 strncat(s, "Up", len - strlen(s) - 1);
10228 else
10229 strncat(s, "Down", len - strlen(s) - 1);
10230 if (active)
10231 strncat(s, ", Active", len - strlen(s) - 1);
10232 else
10233 strncat(s, ", Standby", len - strlen(s) - 1);
10234 s[len - 1] = '\0';
10235 }
10236
10237 static int handle_pri_show_spans(int fd, int argc, char *argv[])
10238 {
10239 int span;
10240 int x;
10241 char status[256];
10242 if (argc != 3)
10243 return RESULT_SHOWUSAGE;
10244
10245 for (span = 0; span < NUM_SPANS; span++) {
10246 if (pris[span].pri) {
10247 for (x = 0; x < NUM_DCHANS; x++) {
10248 if (pris[span].dchannels[x]) {
10249 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
10250 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
10251 }
10252 }
10253 }
10254 }
10255 return RESULT_SUCCESS;
10256 }
10257
10258 static int handle_pri_show_span(int fd, int argc, char *argv[])
10259 {
10260 int span;
10261 int x;
10262 char status[256];
10263 if (argc < 4)
10264 return RESULT_SHOWUSAGE;
10265 span = atoi(argv[3]);
10266 if ((span < 1) || (span > NUM_SPANS)) {
10267 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
10268 return RESULT_SUCCESS;
10269 }
10270 if (!pris[span-1].pri) {
10271 ast_cli(fd, "No PRI running on span %d\n", span);
10272 return RESULT_SUCCESS;
10273 }
10274 for (x = 0; x < NUM_DCHANS; x++) {
10275 if (pris[span-1].dchannels[x]) {
10276 #ifdef PRI_DUMP_INFO_STR
10277 char *info_str = NULL;
10278 #endif
10279 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
10280 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
10281 ast_cli(fd, "Status: %s\n", status);
10282 #ifdef PRI_DUMP_INFO_STR
10283 info_str = pri_dump_info_str(pris[span-1].pri);
10284 if (info_str) {
10285 ast_cli(fd, "%s", info_str);
10286 free(info_str);
10287 }
10288 #else
10289 pri_dump_info(pris[span-1].pri);
10290 #endif
10291 ast_cli(fd, "\n");
10292 }
10293 }
10294 return RESULT_SUCCESS;
10295 }
10296
10297 static int handle_pri_show_debug(int fd, int argc, char *argv[])
10298 {
10299 int x;
10300 int span;
10301 int count=0;
10302 int debug=0;
10303
10304 for (span = 0; span < NUM_SPANS; span++) {
10305 if (pris[span].pri) {
10306 for (x = 0; x < NUM_DCHANS; x++) {
10307 debug = 0;
10308 if (pris[span].dchans[x]) {
10309 debug = pri_get_debug(pris[span].dchans[x]);
10310 ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
10311 count++;
10312 }
10313 }
10314 }
10315
10316 }
10317 ast_mutex_lock(&pridebugfdlock);
10318 if (pridebugfd >= 0)
10319 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
10320 ast_mutex_unlock(&pridebugfdlock);
10321
10322 if (!count)
10323 ast_cli(fd, "No debug set or no PRI running\n");
10324 return RESULT_SUCCESS;
10325 }
10326
10327 static const char pri_debug_help[] =
10328 "Usage: pri debug span <span>\n"
10329 " Enables debugging on a given PRI span\n";
10330
10331 static const char pri_no_debug_help[] =
10332 "Usage: pri no debug span <span>\n"
10333 " Disables debugging on a given PRI span\n";
10334
10335 static const char pri_really_debug_help[] =
10336 "Usage: pri intensive debug span <span>\n"
10337 " Enables debugging down to the Q.921 level\n";
10338
10339 static const char pri_show_span_help[] =
10340 "Usage: pri show span <span>\n"
10341 " Displays PRI Information on a given PRI span\n";
10342
10343 static const char pri_show_spans_help[] =
10344 "Usage: pri show spans\n"
10345 " Displays PRI Information\n";
10346
10347 static struct ast_cli_entry dahdi_pri_cli[] = {
10348 { { "pri", "debug", "span", NULL },
10349 handle_pri_debug, "Enables PRI debugging on a span",
10350 pri_debug_help, complete_span_4 },
10351
10352 { { "pri", "no", "debug", "span", NULL },
10353 handle_pri_no_debug, "Disables PRI debugging on a span",
10354 pri_no_debug_help, complete_span_5 },
10355
10356 { { "pri", "intense", "debug", "span", NULL },
10357 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
10358 pri_really_debug_help, complete_span_5 },
10359
10360 { { "pri", "show", "spans", NULL },
10361 handle_pri_show_spans, "Displays PRI Information",
10362 pri_show_spans_help },
10363
10364 { { "pri", "show", "span", NULL },
10365 handle_pri_show_span, "Displays PRI Information",
10366 pri_show_span_help, complete_span_4 },
10367
10368 { { "pri", "show", "debug", NULL },
10369 handle_pri_show_debug, "Displays current PRI debug settings" },
10370
10371 { { "pri", "set", "debug", "file", NULL },
10372 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
10373
10374 { { "pri", "unset", "debug", "file", NULL },
10375 handle_pri_set_debug_file, "Ends PRI debug output to file" },
10376
10377 #ifdef HAVE_PRI_VERSION
10378 { { "pri", "show", "version", NULL },
10379 handle_pri_version, "Displays version of libpri" },
10380 #endif
10381 };
10382
10383 #endif
10384
10385 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10386 {
10387 int channel;
10388
10389 if (argc != 4)
10390 return RESULT_SHOWUSAGE;
10391
10392 channel = atoi(argv[3]);
10393
10394 return dahdi_destroy_channel_bynum(channel);
10395 }
10396
10397 static void dahdi_softhangup_all(void)
10398 {
10399 struct dahdi_pvt *p;
10400 retry:
10401 ast_mutex_lock(&iflock);
10402 for (p = iflist; p; p = p->next) {
10403 ast_mutex_lock(&p->lock);
10404 if (p->owner && !p->restartpending) {
10405 if (ast_channel_trylock(p->owner)) {
10406 if (option_debug > 2)
10407 ast_verbose("Avoiding deadlock\n");
10408
10409 ast_mutex_unlock(&p->lock);
10410 ast_mutex_unlock(&iflock);
10411 goto retry;
10412 }
10413 if (option_debug > 2)
10414 ast_verbose("Softhanging up on %s\n", p->owner->name);
10415 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10416 p->restartpending = 1;
10417 num_restart_pending++;
10418 ast_channel_unlock(p->owner);
10419 }
10420 ast_mutex_unlock(&p->lock);
10421 }
10422 ast_mutex_unlock(&iflock);
10423 }
10424
10425 static int setup_dahdi(int reload);
10426 static int dahdi_restart(void)
10427 {
10428 #if defined(HAVE_PRI)
10429 int i, j;
10430 #endif
10431 int cancel_code;
10432 struct dahdi_pvt *p;
10433
10434 ast_mutex_lock(&restart_lock);
10435
10436 if (option_verbose)
10437 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10438 dahdi_softhangup_all();
10439 if (option_verbose > 3)
10440 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10441
10442 #if defined(HAVE_PRI)
10443 for (i = 0; i < NUM_SPANS; i++) {
10444 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10445 cancel_code = pthread_cancel(pris[i].master);
10446 pthread_kill(pris[i].master, SIGURG);
10447 if (option_debug > 3)
10448 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10449 pthread_join(pris[i].master, NULL);
10450 if (option_debug > 3)
10451 ast_verbose("Joined thread of span %d\n", i);
10452 }
10453 }
10454 #endif
10455
10456 ast_mutex_lock(&monlock);
10457 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10458 cancel_code = pthread_cancel(monitor_thread);
10459 pthread_kill(monitor_thread, SIGURG);
10460 if (option_debug > 3)
10461 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10462 pthread_join(monitor_thread, NULL);
10463 if (option_debug > 3)
10464 ast_verbose("Joined monitor thread\n");
10465 }
10466 monitor_thread = AST_PTHREADT_NULL;
10467
10468 ast_mutex_lock(&ss_thread_lock);
10469 while (ss_thread_count > 0) {
10470 int x = DAHDI_FLASH;
10471 if (option_debug > 2)
10472 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10473
10474 for (p = iflist; p; p = p->next) {
10475 if (p->owner)
10476 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10477 }
10478 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10479 }
10480
10481
10482 dahdi_softhangup_all();
10483 if (option_verbose > 3)
10484 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10485 destroy_all_channels();
10486 if (option_debug)
10487 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10488
10489 ast_mutex_unlock(&monlock);
10490
10491 #ifdef HAVE_PRI
10492 for (i = 0; i < NUM_SPANS; i++) {
10493 for (j = 0; j < NUM_DCHANS; j++)
10494 dahdi_close_pri_fd(&(pris[i]), j);
10495 }
10496
10497 memset(pris, 0, sizeof(pris));
10498 for (i = 0; i < NUM_SPANS; i++) {
10499 ast_mutex_init(&pris[i].lock);
10500 pris[i].offset = -1;
10501 pris[i].master = AST_PTHREADT_NULL;
10502 for (j = 0; j < NUM_DCHANS; j++)
10503 pris[i].fds[j] = -1;
10504 }
10505 pri_set_error(dahdi_pri_error);
10506 pri_set_message(dahdi_pri_message);
10507 #endif
10508
10509 if (setup_dahdi(2) != 0) {
10510 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10511 ast_mutex_unlock(&ss_thread_lock);
10512 return 1;
10513 }
10514 ast_mutex_unlock(&ss_thread_lock);
10515 ast_mutex_unlock(&restart_lock);
10516 return 0;
10517 }
10518
10519 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10520 {
10521 if (argc != 2) {
10522 return RESULT_SHOWUSAGE;
10523 }
10524
10525 if (dahdi_restart() != 0)
10526 return RESULT_FAILURE;
10527 return RESULT_SUCCESS;
10528 }
10529
10530 static int dahdi_show_channels(int fd, int argc, char **argv)
10531 {
10532 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10533 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10534 struct dahdi_pvt *tmp = NULL;
10535 char tmps[20] = "";
10536 ast_mutex_t *lock;
10537 struct dahdi_pvt *start;
10538 #ifdef HAVE_PRI
10539 int trunkgroup;
10540 struct dahdi_pri *pri = NULL;
10541 int x;
10542 #endif
10543
10544 lock = &iflock;
10545 start = iflist;
10546
10547 #ifdef HAVE_PRI
10548 if (argc == 4) {
10549 if ((trunkgroup = atoi(argv[3])) < 1)
10550 return RESULT_SHOWUSAGE;
10551 for (x = 0; x < NUM_SPANS; x++) {
10552 if (pris[x].trunkgroup == trunkgroup) {
10553 pri = pris + x;
10554 break;
10555 }
10556 }
10557 if (pri) {
10558 start = pri->crvs;
10559 lock = &pri->lock;
10560 } else {
10561 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10562 return RESULT_FAILURE;
10563 }
10564 } else
10565 #endif
10566 if (argc != 3)
10567 return RESULT_SHOWUSAGE;
10568
10569 ast_mutex_lock(lock);
10570 #ifdef HAVE_PRI
10571 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10572 #else
10573 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10574 #endif
10575
10576 tmp = start;
10577 while (tmp) {
10578 if (tmp->channel > 0) {
10579 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10580 } else
10581 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10582 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10583 tmp = tmp->next;
10584 }
10585 ast_mutex_unlock(lock);
10586 return RESULT_SUCCESS;
10587 #undef FORMAT
10588 #undef FORMAT2
10589 }
10590
10591 static int dahdi_show_channel(int fd, int argc, char **argv)
10592 {
10593 int channel;
10594 struct dahdi_pvt *tmp = NULL;
10595 struct dahdi_confinfo ci;
10596 struct dahdi_params ps;
10597 int x;
10598 ast_mutex_t *lock;
10599 struct dahdi_pvt *start;
10600 #ifdef HAVE_PRI
10601 char *c;
10602 int trunkgroup;
10603 struct dahdi_pri *pri=NULL;
10604 #endif
10605
10606 lock = &iflock;
10607 start = iflist;
10608
10609 if (argc != 4)
10610 return RESULT_SHOWUSAGE;
10611 #ifdef HAVE_PRI
10612 if ((c = strchr(argv[3], ':'))) {
10613 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10614 return RESULT_SHOWUSAGE;
10615 if ((trunkgroup < 1) || (channel < 1))
10616 return RESULT_SHOWUSAGE;
10617 for (x = 0; x < NUM_SPANS; x++) {
10618 if (pris[x].trunkgroup == trunkgroup) {
10619 pri = pris + x;
10620 break;
10621 }
10622 }
10623 if (pri) {
10624 start = pri->crvs;
10625 lock = &pri->lock;
10626 } else {
10627 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10628 return RESULT_FAILURE;
10629 }
10630 } else
10631 #endif
10632 channel = atoi(argv[3]);
10633
10634 ast_mutex_lock(lock);
10635 tmp = start;
10636 while (tmp) {
10637 if (tmp->channel == channel) {
10638 #ifdef HAVE_PRI
10639 if (pri)
10640 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10641 else
10642 #endif
10643 ast_cli(fd, "Channel: %d\n", tmp->channel);
10644 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10645 ast_cli(fd, "Span: %d\n", tmp->span);
10646 ast_cli(fd, "Extension: %s\n", tmp->exten);
10647 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10648 ast_cli(fd, "Context: %s\n", tmp->context);
10649 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10650 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10651 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10652 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10653 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10654 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10655 ast_cli(fd, "Radio: %d\n", tmp->radio);
10656 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10657 ast_cli(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)" : "");
10658 ast_cli(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)" : "");
10659 ast_cli(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)" : "");
10660 ast_cli(fd, "Confno: %d\n", tmp->confno);
10661 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10662 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10663 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10664 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10665 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10666 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10667 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10668 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10669 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10670 if (tmp->master)
10671 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10672 for (x = 0; x < MAX_SLAVES; x++) {
10673 if (tmp->slaves[x])
10674 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10675 }
10676 #ifdef HAVE_PRI
10677 if (tmp->pri) {
10678 ast_cli(fd, "PRI Flags: ");
10679 if (tmp->resetting)
10680 ast_cli(fd, "Resetting ");
10681 if (tmp->call)
10682 ast_cli(fd, "Call ");
10683 if (tmp->bearer)
10684 ast_cli(fd, "Bearer ");
10685 ast_cli(fd, "\n");
10686 if (tmp->logicalspan)
10687 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10688 else
10689 ast_cli(fd, "PRI Logical Span: Implicit\n");
10690 }
10691
10692 #endif
10693 memset(&ci, 0, sizeof(ci));
10694 ps.channo = tmp->channel;
10695 if (tmp->subs[SUB_REAL].dfd > -1) {
10696 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10697 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10698 }
10699 #ifdef DAHDI_GETCONFMUTE
10700 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10701 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10702 }
10703 #endif
10704 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10705 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10706 } else {
10707 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10708 }
10709 }
10710 if (ISTRUNK(tmp)) {
10711 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
10712 if (!ast_strlen_zero(progzone))
10713 ast_cli(fd, "Progress Zone: %s\n", progzone);
10714 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
10715 if(tmp->busydetect) {
10716 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10717 if(tmp->busytonelength > 0) {
10718 ast_cli(fd, "Busy Pattern:\n");
10719 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10720 if (tmp->busyquietlength > 0)
10721 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10722 else
10723 ast_cli(fd, " -- Detect Tone Only\n");
10724 if(tmp->busyfuzziness > 0)
10725 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10726 }
10727 }
10728 }
10729 ast_mutex_unlock(lock);
10730 return RESULT_SUCCESS;
10731 }
10732 tmp = tmp->next;
10733 }
10734
10735 ast_cli(fd, "Unable to find given channel %d\n", channel);
10736 ast_mutex_unlock(lock);
10737 return RESULT_FAILURE;
10738 }
10739
10740 static char dahdi_show_cadences_usage[] =
10741 "Usage: dahdi show cadences\n"
10742 " Shows all cadences currently defined\n";
10743
10744 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10745 {
10746 int i, j;
10747 for (i = 0; i < num_cadence; i++) {
10748 char output[1024];
10749 char tmp[16], tmp2[64];
10750 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10751 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10752
10753 for (j = 0; j < 16; j++) {
10754 if (cadences[i].ringcadence[j] == 0)
10755 break;
10756 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10757 if (cidrings[i] * 2 - 1 == j)
10758 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10759 else
10760 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10761 if (j != 0)
10762 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10763 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10764 }
10765 ast_cli(fd,"%s\n",output);
10766 }
10767 return 0;
10768 }
10769
10770
10771 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10772 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10773 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10774
10775 int span;
10776 int res;
10777 char alarms[50];
10778
10779 int ctl;
10780 struct dahdi_spaninfo s;
10781
10782 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
10783 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
10784 ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
10785 return RESULT_FAILURE;
10786 }
10787 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10788
10789 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10790 s.spanno = span;
10791 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10792 if (res) {
10793 continue;
10794 }
10795 alarms[0] = '\0';
10796 if (s.alarms > 0) {
10797 if (s.alarms & DAHDI_ALARM_BLUE)
10798 strcat(alarms, "BLU/");
10799 if (s.alarms & DAHDI_ALARM_YELLOW)
10800 strcat(alarms, "YEL/");
10801 if (s.alarms & DAHDI_ALARM_RED)
10802 strcat(alarms, "RED/");
10803 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10804 strcat(alarms, "LB/");
10805 if (s.alarms & DAHDI_ALARM_RECOVER)
10806 strcat(alarms, "REC/");
10807 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10808 strcat(alarms, "NOP/");
10809 if (!strlen(alarms))
10810 strcat(alarms, "UUU/");
10811 if (strlen(alarms)) {
10812
10813 alarms[strlen(alarms) - 1] = '\0';
10814 }
10815 } else {
10816 if (s.numchans)
10817 strcpy(alarms, "OK");
10818 else
10819 strcpy(alarms, "UNCONFIGURED");
10820 }
10821
10822 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10823 }
10824 close(ctl);
10825
10826 return RESULT_SUCCESS;
10827 #undef FORMAT
10828 #undef FORMAT2
10829 }
10830
10831 static char show_channels_usage[] =
10832 "Usage: dahdi show channels\n"
10833 " Shows a list of available channels\n";
10834
10835 static char show_channel_usage[] =
10836 "Usage: dahdi show channel <chan num>\n"
10837 " Detailed information about a given channel\n";
10838
10839 static char dahdi_show_status_usage[] =
10840 "Usage: dahdi show status\n"
10841 " Shows a list of DAHDI cards with status\n";
10842
10843 static char destroy_channel_usage[] =
10844 "Usage: dahdi destroy channel <chan num>\n"
10845 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10846
10847 static char dahdi_restart_usage[] =
10848 "Usage: dahdi restart\n"
10849 " Restarts the DAHDI channels: destroys them all and then\n"
10850 " re-reads them from chan_dahdi.conf.\n"
10851 " Note that this will STOP any running CALL on DAHDI channels.\n"
10852 "";
10853
10854 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10855 { "zap", "show", "cadences", NULL },
10856 handle_dahdi_show_cadences, NULL,
10857 NULL };
10858
10859 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10860 { "zap", "show", "channels", NULL },
10861 dahdi_show_channels, NULL,
10862 NULL };
10863
10864 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10865 { "zap", "show", "channel", NULL },
10866 dahdi_show_channel, NULL,
10867 NULL };
10868
10869 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10870 { "zap", "destroy", "channel", NULL },
10871 dahdi_destroy_channel, NULL,
10872 NULL };
10873
10874 static struct ast_cli_entry cli_zap_restart_deprecated = {
10875 { "zap", "restart", NULL },
10876 dahdi_restart_cmd, NULL,
10877 NULL };
10878
10879 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10880 { "zap", "show", "status", NULL },
10881 dahdi_show_status, NULL,
10882 NULL };
10883
10884 static struct ast_cli_entry dahdi_cli[] = {
10885 { { "dahdi", "show", "cadences", NULL },
10886 handle_dahdi_show_cadences, "List cadences",
10887 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10888
10889 { { "dahdi", "show", "channels", NULL},
10890 dahdi_show_channels, "Show active DAHDI channels",
10891 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10892
10893 { { "dahdi", "show", "channel", NULL},
10894 dahdi_show_channel, "Show information on a channel",
10895 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10896
10897 { { "dahdi", "destroy", "channel", NULL},
10898 dahdi_destroy_channel, "Destroy a channel",
10899 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10900
10901 { { "dahdi", "restart", NULL},
10902 dahdi_restart_cmd, "Fully restart DAHDI channels",
10903 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10904
10905 { { "dahdi", "show", "status", NULL},
10906 dahdi_show_status, "Show all DAHDI cards status",
10907 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10908 };
10909
10910 #define TRANSFER 0
10911 #define HANGUP 1
10912
10913 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10914 {
10915 if (p) {
10916 switch (mode) {
10917 case TRANSFER:
10918 p->fake_event = DAHDI_EVENT_WINKFLASH;
10919 break;
10920 case HANGUP:
10921 p->fake_event = DAHDI_EVENT_ONHOOK;
10922 break;
10923 default:
10924 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10925 }
10926 }
10927 return 0;
10928 }
10929 static struct dahdi_pvt *find_channel(int channel)
10930 {
10931 struct dahdi_pvt *p = iflist;
10932 while (p) {
10933 if (p->channel == channel) {
10934 break;
10935 }
10936 p = p->next;
10937 }
10938 return p;
10939 }
10940
10941 #define local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
10942 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10943
10944 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10945 {
10946 struct dahdi_pvt *p = NULL;
10947 const char *channel = local_astman_header(m, "Channel", zap_mode);
10948
10949 if (ast_strlen_zero(channel)) {
10950 astman_send_error(s, m, "No channel specified");
10951 return 0;
10952 }
10953 if (!(p = find_channel(atoi(channel)))) {
10954 astman_send_error(s, m, "No such channel");
10955 return 0;
10956 }
10957 p->dnd = dnd;
10958 local_astman_ack(s, m, "DND", zap_mode);
10959
10960 return 0;
10961 }
10962
10963 static int zap_action_dndon(struct mansession *s, const struct message *m)
10964 {
10965 return __action_dnd(s, m, 1, 1);
10966 }
10967
10968 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10969 {
10970 return __action_dnd(s, m, 0, 1);
10971 }
10972
10973 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10974 {
10975 return __action_dnd(s, m, 1, 0);
10976 }
10977
10978 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10979 {
10980 return __action_dnd(s, m, 0, 0);
10981 }
10982
10983 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10984 {
10985 struct dahdi_pvt *p = NULL;
10986 const char *channel = local_astman_header(m, "Channel", zap_mode);
10987
10988 if (ast_strlen_zero(channel)) {
10989 astman_send_error(s, m, "No channel specified");
10990 return 0;
10991 }
10992 if (!(p = find_channel(atoi(channel)))) {
10993 astman_send_error(s, m, "No such channel");
10994 return 0;
10995 }
10996 dahdi_fake_event(p,TRANSFER);
10997 local_astman_ack(s, m, "Transfer", zap_mode);
10998
10999 return 0;
11000 }
11001
11002 static int zap_action_transfer(struct mansession *s, const struct message *m)
11003 {
11004 return __action_transfer(s, m, 1);
11005 }
11006
11007 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
11008 {
11009 return __action_transfer(s, m, 0);
11010 }
11011
11012 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
11013 {
11014 struct dahdi_pvt *p = NULL;
11015 const char *channel = local_astman_header(m, "Channel", zap_mode);
11016
11017 if (ast_strlen_zero(channel)) {
11018 astman_send_error(s, m, "No channel specified");
11019 return 0;
11020 }
11021 if (!(p = find_channel(atoi(channel)))) {
11022 astman_send_error(s, m, "No such channel");
11023 return 0;
11024 }
11025 dahdi_fake_event(p, HANGUP);
11026 local_astman_ack(s, m, "Hangup", zap_mode);
11027 return 0;
11028 }
11029
11030 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
11031 {
11032 return __action_transferhangup(s, m, 1);
11033 }
11034
11035 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
11036 {
11037 return __action_transferhangup(s, m, 0);
11038 }
11039
11040 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
11041 {
11042 struct dahdi_pvt *p = NULL;
11043 const char *channel = local_astman_header(m, "Channel", zap_mode);
11044 const char *number = astman_get_header(m, "Number");
11045 int i;
11046
11047 if (ast_strlen_zero(channel)) {
11048 astman_send_error(s, m, "No channel specified");
11049 return 0;
11050 }
11051 if (ast_strlen_zero(number)) {
11052 astman_send_error(s, m, "No number specified");
11053 return 0;
11054 }
11055 if (!(p = find_channel(atoi(channel)))) {
11056 astman_send_error(s, m, "No such channel");
11057 return 0;
11058 }
11059 if (!p->owner) {
11060 astman_send_error(s, m, "Channel does not have an owner");
11061 return 0;
11062 }
11063 for (i = 0; i < strlen(number); i++) {
11064 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
11065
11066 dahdi_queue_frame(p, &f, NULL);
11067 }
11068 local_astman_ack(s, m, "DialOffHook", zap_mode);
11069
11070 return 0;
11071 }
11072
11073 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
11074 {
11075 return __action_dialoffhook(s, m, 1);
11076 }
11077
11078 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
11079 {
11080 return __action_dialoffhook(s, m, 0);
11081 }
11082
11083 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
11084 {
11085 struct dahdi_pvt *tmp = NULL;
11086 const char *id = astman_get_header(m, "ActionID");
11087 char idText[256] = "";
11088
11089 local_astman_ack(s, m, " channel status will follow", zap_mode);
11090 if (!ast_strlen_zero(id))
11091 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
11092
11093 ast_mutex_lock(&iflock);
11094
11095 tmp = iflist;
11096 while (tmp) {
11097 if (tmp->channel > 0) {
11098 int alarm = get_alarms(tmp);
11099 astman_append(s,
11100 "Event: %sShowChannels\r\n"
11101 "Channel: %d\r\n"
11102 "Signalling: %s\r\n"
11103 "Context: %s\r\n"
11104 "DND: %s\r\n"
11105 "Alarm: %s\r\n"
11106 "%s"
11107 "\r\n",
11108 dahdi_chan_name,
11109 tmp->channel, sig2str(tmp->sig), tmp->context,
11110 tmp->dnd ? "Enabled" : "Disabled",
11111 alarm2str(alarm), idText);
11112 }
11113
11114 tmp = tmp->next;
11115 }
11116
11117 ast_mutex_unlock(&iflock);
11118
11119 astman_append(s,
11120 "Event: %sShowChannelsComplete\r\n"
11121 "%s"
11122 "\r\n",
11123 dahdi_chan_name,
11124 idText);
11125 return 0;
11126 }
11127
11128 static int zap_action_showchannels(struct mansession *s, const struct message *m)
11129 {
11130 return __action_showchannels(s, m, 1);
11131 }
11132
11133 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
11134 {
11135 return __action_showchannels(s, m, 0);
11136 }
11137
11138 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
11139 {
11140 if (dahdi_restart() != 0) {
11141 if (zap_mode) {
11142 astman_send_error(s, m, "Failed to restart Zap");
11143 } else {
11144 astman_send_error(s, m, "Failed to restart DAHDI");
11145 }
11146 return 1;
11147 }
11148 local_astman_ack(s, m, "Restart: Success", zap_mode);
11149 return 0;
11150 }
11151
11152 static int zap_action_restart(struct mansession *s, const struct message *m)
11153 {
11154 return __action_restart(s, m, 1);
11155 }
11156
11157 static int dahdi_action_restart(struct mansession *s, const struct message *m)
11158 {
11159 return __action_restart(s, m, 0);
11160 }
11161
11162 #define local_astman_unregister(a) do { \
11163 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11164 ast_manager_unregister("DAHDI" a); \
11165 } \
11166 ast_manager_unregister("Zap" a); \
11167 } while (0)
11168
11169 static int __unload_module(void)
11170 {
11171 struct dahdi_pvt *p;
11172
11173 #ifdef HAVE_PRI
11174 int i, j;
11175 for (i = 0; i < NUM_SPANS; i++) {
11176 if (pris[i].master != AST_PTHREADT_NULL)
11177 pthread_cancel(pris[i].master);
11178 }
11179 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11180
11181 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11182 ast_unregister_application(dahdi_send_keypad_facility_app);
11183 }
11184 ast_unregister_application(zap_send_keypad_facility_app);
11185 #endif
11186 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11187 local_astman_unregister("DialOffHook");
11188 local_astman_unregister("Hangup");
11189 local_astman_unregister("Transfer");
11190 local_astman_unregister("DNDoff");
11191 local_astman_unregister("DNDon");
11192 local_astman_unregister("ShowChannels");
11193 local_astman_unregister("Restart");
11194 ast_channel_unregister(chan_tech);
11195 ast_mutex_lock(&iflock);
11196
11197 p = iflist;
11198 while (p) {
11199 if (p->owner)
11200 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
11201 p = p->next;
11202 }
11203 ast_mutex_unlock(&iflock);
11204 ast_mutex_lock(&monlock);
11205 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11206 pthread_cancel(monitor_thread);
11207 pthread_kill(monitor_thread, SIGURG);
11208 pthread_join(monitor_thread, NULL);
11209 }
11210 monitor_thread = AST_PTHREADT_STOP;
11211 ast_mutex_unlock(&monlock);
11212
11213 destroy_all_channels();
11214 #ifdef HAVE_PRI
11215 for (i = 0; i < NUM_SPANS; i++) {
11216 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
11217 pthread_join(pris[i].master, NULL);
11218 for (j = 0; j < NUM_DCHANS; j++) {
11219 dahdi_close_pri_fd(&(pris[i]), j);
11220 }
11221 }
11222 #endif
11223 ast_cond_destroy(&ss_thread_complete);
11224 return 0;
11225 }
11226
11227 static int unload_module(void)
11228 {
11229 #ifdef HAVE_PRI
11230 int y;
11231 for (y = 0; y < NUM_SPANS; y++)
11232 ast_mutex_destroy(&pris[y].lock);
11233 #endif
11234 return __unload_module();
11235 }
11236
11237 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
11238 {
11239 char *c, *chan;
11240 int x, start, finish;
11241 struct dahdi_pvt *tmp;
11242 #ifdef HAVE_PRI
11243 struct dahdi_pri *pri;
11244 int trunkgroup, y;
11245 #endif
11246
11247 if ((reload == 0) && (conf->chan.sig < 0)) {
11248 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
11249 return -1;
11250 }
11251
11252 c = ast_strdupa(value);
11253
11254 #ifdef HAVE_PRI
11255 pri = NULL;
11256 if (iscrv) {
11257 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
11258 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
11259 return -1;
11260 }
11261 if (trunkgroup < 1) {
11262 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
11263 return -1;
11264 }
11265 c += y;
11266 for (y = 0; y < NUM_SPANS; y++) {
11267 if (pris[y].trunkgroup == trunkgroup) {
11268 pri = pris + y;
11269 break;
11270 }
11271 }
11272 if (!pri) {
11273 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
11274 return -1;
11275 }
11276 }
11277 #endif
11278
11279 while ((chan = strsep(&c, ","))) {
11280 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
11281
11282 } else if (sscanf(chan, "%d", &start)) {
11283
11284 finish = start;
11285 } else if (!strcasecmp(chan, "pseudo")) {
11286 finish = start = CHAN_PSEUDO;
11287 if (found_pseudo)
11288 *found_pseudo = 1;
11289 } else {
11290 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
11291 return -1;
11292 }
11293 if (finish < start) {
11294 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
11295 x = finish;
11296 finish = start;
11297 start = x;
11298 }
11299
11300 for (x = start; x <= finish; x++) {
11301 #ifdef HAVE_PRI
11302 tmp = mkintf(x, conf, pri, reload);
11303 #else
11304 tmp = mkintf(x, conf, NULL, reload);
11305 #endif
11306
11307 if (tmp) {
11308 if (option_verbose > 2) {
11309 #ifdef HAVE_PRI
11310 if (pri)
11311 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
11312 else
11313 #endif
11314 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
11315 }
11316 } else {
11317 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
11318 (reload == 1) ? "reconfigure" : "register", value);
11319 return -1;
11320 }
11321 }
11322 }
11323
11324 return 0;
11325 }
11326
11327
11328
11329 #define MAX_CHANLIST_LEN 80
11330 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
11331 {
11332 struct dahdi_pvt *tmp;
11333 int y;
11334 int found_pseudo = 0;
11335 char dahdichan[MAX_CHANLIST_LEN] = {};
11336
11337 for (; v; v = v->next) {
11338 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11339 continue;
11340
11341
11342 if (!strcasecmp(v->name, "channel")
11343 #ifdef HAVE_PRI
11344 || !strcasecmp(v->name, "crv")
11345 #endif
11346 ) {
11347 int iscrv;
11348 if (skipchannels)
11349 continue;
11350 iscrv = !strcasecmp(v->name, "crv");
11351 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11352 return -1;
11353 } else if (!strcasecmp(v->name, "buffers")) {
11354 int res;
11355 char policy[21] = "";
11356
11357 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
11358 if (res != 2) {
11359 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11360 confp->chan.buf_no = numbufs;
11361 continue;
11362 }
11363 if (confp->chan.buf_no < 0)
11364 confp->chan.buf_no = numbufs;
11365 if (!strcasecmp(policy, "full")) {
11366 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11367 } else if (!strcasecmp(policy, "immediate")) {
11368 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11369 } else {
11370 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11371 }
11372 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11373 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11374 if (v->name[0] == 'z' || v->name[0] == 'Z') {
11375 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11376 }
11377 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11378 if (ast_true(v->value))
11379 confp->chan.usedistinctiveringdetection = 1;
11380 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11381 if (ast_true(v->value))
11382 distinctiveringaftercid = 1;
11383 } else if (!strcasecmp(v->name, "dring1context")) {
11384 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11385 } else if (!strcasecmp(v->name, "dring2context")) {
11386 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11387 } else if (!strcasecmp(v->name, "dring3context")) {
11388 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11389 } else if (!strcasecmp(v->name, "dring1")) {
11390 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11391 } else if (!strcasecmp(v->name, "dring2")) {
11392 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11393 } else if (!strcasecmp(v->name, "dring3")) {
11394 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11395 } else if (!strcasecmp(v->name, "usecallerid")) {
11396 confp->chan.use_callerid = ast_true(v->value);
11397 } else if (!strcasecmp(v->name, "cidsignalling")) {
11398 if (!strcasecmp(v->value, "bell"))
11399 confp->chan.cid_signalling = CID_SIG_BELL;
11400 else if (!strcasecmp(v->value, "v23"))
11401 confp->chan.cid_signalling = CID_SIG_V23;
11402 else if (!strcasecmp(v->value, "dtmf"))
11403 confp->chan.cid_signalling = CID_SIG_DTMF;
11404 else if (!strcasecmp(v->value, "smdi"))
11405 confp->chan.cid_signalling = CID_SIG_SMDI;
11406 else if (!strcasecmp(v->value, "v23_jp"))
11407 confp->chan.cid_signalling = CID_SIG_V23_JP;
11408 else if (ast_true(v->value))
11409 confp->chan.cid_signalling = CID_SIG_BELL;
11410 } else if (!strcasecmp(v->name, "cidstart")) {
11411 if (!strcasecmp(v->value, "ring"))
11412 confp->chan.cid_start = CID_START_RING;
11413 else if (!strcasecmp(v->value, "polarity"))
11414 confp->chan.cid_start = CID_START_POLARITY;
11415 else if (ast_true(v->value))
11416 confp->chan.cid_start = CID_START_RING;
11417 } else if (!strcasecmp(v->name, "threewaycalling")) {
11418 confp->chan.threewaycalling = ast_true(v->value);
11419 } else if (!strcasecmp(v->name, "cancallforward")) {
11420 confp->chan.cancallforward = ast_true(v->value);
11421 } else if (!strcasecmp(v->name, "relaxdtmf")) {
11422 if (ast_true(v->value))
11423 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11424 else
11425 confp->chan.dtmfrelax = 0;
11426 } else if (!strcasecmp(v->name, "mailbox")) {
11427 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11428 } else if (!strcasecmp(v->name, "hasvoicemail")) {
11429 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11430 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11431 }
11432 } else if (!strcasecmp(v->name, "adsi")) {
11433 confp->chan.adsi = ast_true(v->value);
11434 } else if (!strcasecmp(v->name, "usesmdi")) {
11435 confp->chan.use_smdi = ast_true(v->value);
11436 } else if (!strcasecmp(v->name, "smdiport")) {
11437 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11438 } else if (!strcasecmp(v->name, "transfer")) {
11439 confp->chan.transfer = ast_true(v->value);
11440 } else if (!strcasecmp(v->name, "canpark")) {
11441 confp->chan.canpark = ast_true(v->value);
11442 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11443 confp->chan.echocanbridged = ast_true(v->value);
11444 } else if (!strcasecmp(v->name, "busydetect")) {
11445 confp->chan.busydetect = ast_true(v->value);
11446 } else if (!strcasecmp(v->name, "busycount")) {
11447 confp->chan.busycount = atoi(v->value);
11448 } else if (!strcasecmp(v->name, "silencethreshold")) {
11449 confp->chan.silencethreshold = atoi(v->value);
11450 } else if (!strcasecmp(v->name, "busycompare")) {
11451 confp->chan.busycompare = ast_true(v->value);
11452 } else if (!strcasecmp(v->name, "busypattern")) {
11453 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
11454 if (count == 1)
11455 confp->chan.busyquietlength = 0;
11456 else if (count < 1)
11457 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
11458 } else if (!strcasecmp(v->name, "busyfuzziness")) {
11459 confp->chan.busyfuzziness = atoi(v->value);
11460 } else if (!strcasecmp(v->name, "callprogress")) {
11461 if (ast_true(v->value))
11462 confp->chan.callprogress |= 1;
11463 else
11464 confp->chan.callprogress &= ~1;
11465 } else if (!strcasecmp(v->name, "faxdetect")) {
11466 if (!strcasecmp(v->value, "incoming")) {
11467 confp->chan.callprogress |= 4;
11468 confp->chan.callprogress &= ~2;
11469 } else if (!strcasecmp(v->value, "outgoing")) {
11470 confp->chan.callprogress &= ~4;
11471 confp->chan.callprogress |= 2;
11472 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11473 confp->chan.callprogress |= 6;
11474 else
11475 confp->chan.callprogress &= ~6;
11476 } else if (!strcasecmp(v->name, "echocancel")) {
11477 if (!ast_strlen_zero(v->value)) {
11478 y = atoi(v->value);
11479 } else
11480 y = 0;
11481 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11482 confp->chan.echocancel = y;
11483 else {
11484 confp->chan.echocancel = ast_true(v->value);
11485 if (confp->chan.echocancel)
11486 confp->chan.echocancel=128;
11487 }
11488 } else if (!strcasecmp(v->name, "echotraining")) {
11489 if (sscanf(v->value, "%d", &y) == 1) {
11490 if ((y < 10) || (y > 4000)) {
11491 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
11492 } else {
11493 confp->chan.echotraining = y;
11494 }
11495 } else if (ast_true(v->value)) {
11496 confp->chan.echotraining = 400;
11497 } else
11498 confp->chan.echotraining = 0;
11499 } else if (!strcasecmp(v->name, "hidecallerid")) {
11500 confp->chan.hidecallerid = ast_true(v->value);
11501 } else if (!strcasecmp(v->name, "hidecalleridname")) {
11502 confp->chan.hidecalleridname = ast_true(v->value);
11503 } else if (!strcasecmp(v->name, "pulsedial")) {
11504 confp->chan.pulse = ast_true(v->value);
11505 } else if (!strcasecmp(v->name, "callreturn")) {
11506 confp->chan.callreturn = ast_true(v->value);
11507 } else if (!strcasecmp(v->name, "callwaiting")) {
11508 confp->chan.callwaiting = ast_true(v->value);
11509 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11510 confp->chan.callwaitingcallerid = ast_true(v->value);
11511 } else if (!strcasecmp(v->name, "context")) {
11512 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11513 } else if (!strcasecmp(v->name, "language")) {
11514 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11515 } else if (!strcasecmp(v->name, "progzone")) {
11516 ast_copy_string(progzone, v->value, sizeof(progzone));
11517 } else if (!strcasecmp(v->name, "mohinterpret")
11518 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11519 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11520 } else if (!strcasecmp(v->name, "mohsuggest")) {
11521 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11522 } else if (!strcasecmp(v->name, "stripmsd")) {
11523 confp->chan.stripmsd = atoi(v->value);
11524 } else if (!strcasecmp(v->name, "jitterbuffers")) {
11525 numbufs = atoi(v->value);
11526 } else if (!strcasecmp(v->name, "group")) {
11527 confp->chan.group = ast_get_group(v->value);
11528 } else if (!strcasecmp(v->name, "callgroup")) {
11529 confp->chan.callgroup = ast_get_group(v->value);
11530 } else if (!strcasecmp(v->name, "pickupgroup")) {
11531 confp->chan.pickupgroup = ast_get_group(v->value);
11532 } else if (!strcasecmp(v->name, "immediate")) {
11533 confp->chan.immediate = ast_true(v->value);
11534 } else if (!strcasecmp(v->name, "transfertobusy")) {
11535 confp->chan.transfertobusy = ast_true(v->value);
11536 } else if (!strcasecmp(v->name, "rxgain")) {
11537 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11538 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11539 }
11540 } else if (!strcasecmp(v->name, "txgain")) {
11541 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11542 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11543 }
11544 } else if (!strcasecmp(v->name, "tonezone")) {
11545 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11546 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11547 }
11548 } else if (!strcasecmp(v->name, "callerid")) {
11549 if (!strcasecmp(v->value, "asreceived")) {
11550 confp->chan.cid_num[0] = '\0';
11551 confp->chan.cid_name[0] = '\0';
11552 } else {
11553 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11554 }
11555 } else if (!strcasecmp(v->name, "fullname")) {
11556 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11557 } else if (!strcasecmp(v->name, "cid_number")) {
11558 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11559 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11560 confp->chan.dahditrcallerid = ast_true(v->value);
11561 if (strstr(v->name, "zap")) {
11562 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11563 }
11564 } else if (!strcasecmp(v->name, "restrictcid")) {
11565 confp->chan.restrictcid = ast_true(v->value);
11566 } else if (!strcasecmp(v->name, "usecallingpres")) {
11567 confp->chan.use_callingpres = ast_true(v->value);
11568 } else if (!strcasecmp(v->name, "accountcode")) {
11569 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11570 } else if (!strcasecmp(v->name, "amaflags")) {
11571 y = ast_cdr_amaflags2int(v->value);
11572 if (y < 0)
11573 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11574 else
11575 confp->chan.amaflags = y;
11576 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11577 confp->chan.polarityonanswerdelay = atoi(v->value);
11578 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11579 confp->chan.answeronpolarityswitch = ast_true(v->value);
11580 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11581 confp->chan.hanguponpolarityswitch = ast_true(v->value);
11582 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11583 confp->chan.sendcalleridafter = atoi(v->value);
11584 } else if (reload != 1){
11585 if (!strcasecmp(v->name, "signalling")) {
11586 confp->chan.outsigmod = -1;
11587 if (!strcasecmp(v->value, "em")) {
11588 confp->chan.sig = SIG_EM;
11589 } else if (!strcasecmp(v->value, "em_e1")) {
11590 confp->chan.sig = SIG_EM_E1;
11591 } else if (!strcasecmp(v->value, "em_w")) {
11592 confp->chan.sig = SIG_EMWINK;
11593 confp->chan.radio = 0;
11594 } else if (!strcasecmp(v->value, "fxs_ls")) {
11595 confp->chan.sig = SIG_FXSLS;
11596 confp->chan.radio = 0;
11597 } else if (!strcasecmp(v->value, "fxs_gs")) {
11598 confp->chan.sig = SIG_FXSGS;
11599 confp->chan.radio = 0;
11600 } else if (!strcasecmp(v->value, "fxs_ks")) {
11601 confp->chan.sig = SIG_FXSKS;
11602 confp->chan.radio = 0;
11603 } else if (!strcasecmp(v->value, "fxo_ls")) {
11604 confp->chan.sig = SIG_FXOLS;
11605 confp->chan.radio = 0;
11606 } else if (!strcasecmp(v->value, "fxo_gs")) {
11607 confp->chan.sig = SIG_FXOGS;
11608 confp->chan.radio = 0;
11609 } else if (!strcasecmp(v->value, "fxo_ks")) {
11610 confp->chan.sig = SIG_FXOKS;
11611 confp->chan.radio = 0;
11612 } else if (!strcasecmp(v->value, "fxs_rx")) {
11613 confp->chan.sig = SIG_FXSKS;
11614 confp->chan.radio = 1;
11615 } else if (!strcasecmp(v->value, "fxo_rx")) {
11616 confp->chan.sig = SIG_FXOLS;
11617 confp->chan.radio = 1;
11618 } else if (!strcasecmp(v->value, "fxs_tx")) {
11619 confp->chan.sig = SIG_FXSLS;
11620 confp->chan.radio = 1;
11621 } else if (!strcasecmp(v->value, "fxo_tx")) {
11622 confp->chan.sig = SIG_FXOGS;
11623 confp->chan.radio = 1;
11624 } else if (!strcasecmp(v->value, "em_rx")) {
11625 confp->chan.sig = SIG_EM;
11626 confp->chan.radio = 1;
11627 } else if (!strcasecmp(v->value, "em_tx")) {
11628 confp->chan.sig = SIG_EM;
11629 confp->chan.radio = 1;
11630 } else if (!strcasecmp(v->value, "em_rxtx")) {
11631 confp->chan.sig = SIG_EM;
11632 confp->chan.radio = 2;
11633 } else if (!strcasecmp(v->value, "em_txrx")) {
11634 confp->chan.sig = SIG_EM;
11635 confp->chan.radio = 2;
11636 } else if (!strcasecmp(v->value, "sf")) {
11637 confp->chan.sig = SIG_SF;
11638 confp->chan.radio = 0;
11639 } else if (!strcasecmp(v->value, "sf_w")) {
11640 confp->chan.sig = SIG_SFWINK;
11641 confp->chan.radio = 0;
11642 } else if (!strcasecmp(v->value, "sf_featd")) {
11643 confp->chan.sig = SIG_FEATD;
11644 confp->chan.radio = 0;
11645 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11646 confp->chan.sig = SIG_FEATDMF;
11647 confp->chan.radio = 0;
11648 } else if (!strcasecmp(v->value, "sf_featb")) {
11649 confp->chan.sig = SIG_SF_FEATB;
11650 confp->chan.radio = 0;
11651 } else if (!strcasecmp(v->value, "sf")) {
11652 confp->chan.sig = SIG_SF;
11653 confp->chan.radio = 0;
11654 } else if (!strcasecmp(v->value, "sf_rx")) {
11655 confp->chan.sig = SIG_SF;
11656 confp->chan.radio = 1;
11657 } else if (!strcasecmp(v->value, "sf_tx")) {
11658 confp->chan.sig = SIG_SF;
11659 confp->chan.radio = 1;
11660 } else if (!strcasecmp(v->value, "sf_rxtx")) {
11661 confp->chan.sig = SIG_SF;
11662 confp->chan.radio = 2;
11663 } else if (!strcasecmp(v->value, "sf_txrx")) {
11664 confp->chan.sig = SIG_SF;
11665 confp->chan.radio = 2;
11666 } else if (!strcasecmp(v->value, "featd")) {
11667 confp->chan.sig = SIG_FEATD;
11668 confp->chan.radio = 0;
11669 } else if (!strcasecmp(v->value, "featdmf")) {
11670 confp->chan.sig = SIG_FEATDMF;
11671 confp->chan.radio = 0;
11672 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11673 confp->chan.sig = SIG_FEATDMF_TA;
11674 confp->chan.radio = 0;
11675 } else if (!strcasecmp(v->value, "e911")) {
11676 confp->chan.sig = SIG_E911;
11677 confp->chan.radio = 0;
11678 } else if (!strcasecmp(v->value, "fgccama")) {
11679 confp->chan.sig = SIG_FGC_CAMA;
11680 confp->chan.radio = 0;
11681 } else if (!strcasecmp(v->value, "fgccamamf")) {
11682 confp->chan.sig = SIG_FGC_CAMAMF;
11683 confp->chan.radio = 0;
11684 } else if (!strcasecmp(v->value, "featb")) {
11685 confp->chan.sig = SIG_FEATB;
11686 confp->chan.radio = 0;
11687 #ifdef HAVE_PRI
11688 } else if (!strcasecmp(v->value, "pri_net")) {
11689 confp->chan.radio = 0;
11690 confp->chan.sig = SIG_PRI;
11691 confp->pri.nodetype = PRI_NETWORK;
11692 } else if (!strcasecmp(v->value, "pri_cpe")) {
11693 confp->chan.sig = SIG_PRI;
11694 confp->chan.radio = 0;
11695 confp->pri.nodetype = PRI_CPE;
11696 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11697 confp->chan.sig = SIG_GR303FXOKS;
11698 confp->chan.radio = 0;
11699 confp->pri.nodetype = PRI_NETWORK;
11700 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11701 confp->chan.sig = SIG_GR303FXSKS;
11702 confp->chan.radio = 0;
11703 confp->pri.nodetype = PRI_CPE;
11704 #endif
11705 } else {
11706 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11707 }
11708 } else if (!strcasecmp(v->name, "outsignalling")) {
11709 if (!strcasecmp(v->value, "em")) {
11710 confp->chan.outsigmod = SIG_EM;
11711 } else if (!strcasecmp(v->value, "em_e1")) {
11712 confp->chan.outsigmod = SIG_EM_E1;
11713 } else if (!strcasecmp(v->value, "em_w")) {
11714 confp->chan.outsigmod = SIG_EMWINK;
11715 } else if (!strcasecmp(v->value, "sf")) {
11716 confp->chan.outsigmod = SIG_SF;
11717 } else if (!strcasecmp(v->value, "sf_w")) {
11718 confp->chan.outsigmod = SIG_SFWINK;
11719 } else if (!strcasecmp(v->value, "sf_featd")) {
11720 confp->chan.outsigmod = SIG_FEATD;
11721 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11722 confp->chan.outsigmod = SIG_FEATDMF;
11723 } else if (!strcasecmp(v->value, "sf_featb")) {
11724 confp->chan.outsigmod = SIG_SF_FEATB;
11725 } else if (!strcasecmp(v->value, "sf")) {
11726 confp->chan.outsigmod = SIG_SF;
11727 } else if (!strcasecmp(v->value, "featd")) {
11728 confp->chan.outsigmod = SIG_FEATD;
11729 } else if (!strcasecmp(v->value, "featdmf")) {
11730 confp->chan.outsigmod = SIG_FEATDMF;
11731 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11732 confp->chan.outsigmod = SIG_FEATDMF_TA;
11733 } else if (!strcasecmp(v->value, "e911")) {
11734 confp->chan.outsigmod = SIG_E911;
11735 } else if (!strcasecmp(v->value, "fgccama")) {
11736 confp->chan.outsigmod = SIG_FGC_CAMA;
11737 } else if (!strcasecmp(v->value, "fgccamamf")) {
11738 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11739 } else if (!strcasecmp(v->value, "featb")) {
11740 confp->chan.outsigmod = SIG_FEATB;
11741 } else {
11742 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11743 }
11744 #ifdef HAVE_PRI
11745 } else if (!strcasecmp(v->name, "pridialplan")) {
11746 if (!strcasecmp(v->value, "national")) {
11747 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11748 } else if (!strcasecmp(v->value, "unknown")) {
11749 confp->pri.dialplan = PRI_UNKNOWN + 1;
11750 } else if (!strcasecmp(v->value, "private")) {
11751 confp->pri.dialplan = PRI_PRIVATE + 1;
11752 } else if (!strcasecmp(v->value, "international")) {
11753 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11754 } else if (!strcasecmp(v->value, "local")) {
11755 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11756 } else if (!strcasecmp(v->value, "dynamic")) {
11757 confp->pri.dialplan = -1;
11758 } else {
11759 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11760 }
11761 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11762 if (!strcasecmp(v->value, "national")) {
11763 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11764 } else if (!strcasecmp(v->value, "unknown")) {
11765 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11766 } else if (!strcasecmp(v->value, "private")) {
11767 confp->pri.localdialplan = PRI_PRIVATE + 1;
11768 } else if (!strcasecmp(v->value, "international")) {
11769 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11770 } else if (!strcasecmp(v->value, "local")) {
11771 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11772 } else if (!strcasecmp(v->value, "dynamic")) {
11773 confp->pri.localdialplan = -1;
11774 } else {
11775 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11776 }
11777 } else if (!strcasecmp(v->name, "switchtype")) {
11778 if (!strcasecmp(v->value, "national"))
11779 confp->pri.switchtype = PRI_SWITCH_NI2;
11780 else if (!strcasecmp(v->value, "ni1"))
11781 confp->pri.switchtype = PRI_SWITCH_NI1;
11782 else if (!strcasecmp(v->value, "dms100"))
11783 confp->pri.switchtype = PRI_SWITCH_DMS100;
11784 else if (!strcasecmp(v->value, "4ess"))
11785 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11786 else if (!strcasecmp(v->value, "5ess"))
11787 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11788 else if (!strcasecmp(v->value, "euroisdn"))
11789 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11790 else if (!strcasecmp(v->value, "qsig"))
11791 confp->pri.switchtype = PRI_SWITCH_QSIG;
11792 else {
11793 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11794 return -1;
11795 }
11796 } else if (!strcasecmp(v->name, "nsf")) {
11797 if (!strcasecmp(v->value, "sdn"))
11798 confp->pri.nsf = PRI_NSF_SDN;
11799 else if (!strcasecmp(v->value, "megacom"))
11800 confp->pri.nsf = PRI_NSF_MEGACOM;
11801 else if (!strcasecmp(v->value, "tollfreemegacom"))
11802 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11803 else if (!strcasecmp(v->value, "accunet"))
11804 confp->pri.nsf = PRI_NSF_ACCUNET;
11805 else if (!strcasecmp(v->value, "none"))
11806 confp->pri.nsf = PRI_NSF_NONE;
11807 else {
11808 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11809 confp->pri.nsf = PRI_NSF_NONE;
11810 }
11811 } else if (!strcasecmp(v->name, "priindication")) {
11812 if (!strcasecmp(v->value, "outofband"))
11813 confp->chan.priindication_oob = 1;
11814 else if (!strcasecmp(v->value, "inband"))
11815 confp->chan.priindication_oob = 0;
11816 else
11817 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11818 v->value, v->lineno);
11819 } else if (!strcasecmp(v->name, "priexclusive")) {
11820 confp->chan.priexclusive = ast_true(v->value);
11821 } else if (!strcasecmp(v->name, "internationalprefix")) {
11822 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11823 } else if (!strcasecmp(v->name, "nationalprefix")) {
11824 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11825 } else if (!strcasecmp(v->name, "localprefix")) {
11826 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11827 } else if (!strcasecmp(v->name, "privateprefix")) {
11828 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11829 } else if (!strcasecmp(v->name, "unknownprefix")) {
11830 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11831 } else if (!strcasecmp(v->name, "resetinterval")) {
11832 if (!strcasecmp(v->value, "never"))
11833 confp->pri.resetinterval = -1;
11834 else if (atoi(v->value) >= 60)
11835 confp->pri.resetinterval = atoi(v->value);
11836 else
11837 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11838 v->value, v->lineno);
11839 } else if (!strcasecmp(v->name, "minunused")) {
11840 confp->pri.minunused = atoi(v->value);
11841 } else if (!strcasecmp(v->name, "minidle")) {
11842 confp->pri.minidle = atoi(v->value);
11843 } else if (!strcasecmp(v->name, "idleext")) {
11844 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11845 } else if (!strcasecmp(v->name, "idledial")) {
11846 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11847 } else if (!strcasecmp(v->name, "overlapdial")) {
11848 confp->pri.overlapdial = ast_true(v->value);
11849 #ifdef HAVE_PRI_INBANDDISCONNECT
11850 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11851 confp->pri.inbanddisconnect = ast_true(v->value);
11852 #endif
11853 } else if (!strcasecmp(v->name, "pritimer")) {
11854 #ifdef PRI_GETSET_TIMERS
11855 char *timerc, *c;
11856 int timer, timeridx;
11857 c = v->value;
11858 timerc = strsep(&c, ",");
11859 if (timerc) {
11860 timer = atoi(c);
11861 if (!timer)
11862 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11863 else {
11864 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11865 pritimers[timeridx] = timer;
11866 else
11867 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11868 }
11869 } else
11870 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11871
11872 } else if (!strcasecmp(v->name, "facilityenable")) {
11873 confp->pri.facilityenable = ast_true(v->value);
11874 #endif
11875 #endif
11876 } else if (!strcasecmp(v->name, "cadence")) {
11877
11878 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11879 int i;
11880 struct dahdi_ring_cadence new_cadence;
11881 int cid_location = -1;
11882 int firstcadencepos = 0;
11883 char original_args[80];
11884 int cadence_is_ok = 1;
11885
11886 ast_copy_string(original_args, v->value, sizeof(original_args));
11887
11888 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]);
11889
11890
11891 if (element_count % 2 == 1) {
11892 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11893 cadence_is_ok = 0;
11894 }
11895
11896
11897 for (i = 0; i < element_count; i++) {
11898 if (c[i] == 0) {
11899 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11900 cadence_is_ok = 0;
11901 break;
11902 } else if (c[i] < 0) {
11903 if (i % 2 == 1) {
11904
11905 if (cid_location == -1) {
11906 cid_location = i;
11907 c[i] *= -1;
11908 } else {
11909 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11910 cadence_is_ok = 0;
11911 break;
11912 }
11913 } else {
11914 if (firstcadencepos == 0) {
11915 firstcadencepos = i;
11916
11917 } else {
11918 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11919 cadence_is_ok = 0;
11920 break;
11921 }
11922 }
11923 }
11924 }
11925
11926
11927 for (i = 0; i < 16; i++) {
11928 new_cadence.ringcadence[i] = c[i];
11929 }
11930
11931 if (cadence_is_ok) {
11932
11933 if (element_count < 2) {
11934 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11935 } else {
11936 if (cid_location == -1) {
11937
11938 cid_location = 1;
11939 } else {
11940
11941 cid_location = (cid_location + 1) / 2;
11942 }
11943
11944 if (!user_has_defined_cadences++)
11945
11946 num_cadence = 0;
11947 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11948 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11949 else {
11950 cadences[num_cadence] = new_cadence;
11951 cidrings[num_cadence++] = cid_location;
11952 if (option_verbose > 2)
11953 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11954 }
11955 }
11956 }
11957 } else if (!strcasecmp(v->name, "ringtimeout")) {
11958 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11959 } else if (!strcasecmp(v->name, "prewink")) {
11960 confp->timing.prewinktime = atoi(v->value);
11961 } else if (!strcasecmp(v->name, "preflash")) {
11962 confp->timing.preflashtime = atoi(v->value);
11963 } else if (!strcasecmp(v->name, "wink")) {
11964 confp->timing.winktime = atoi(v->value);
11965 } else if (!strcasecmp(v->name, "flash")) {
11966 confp->timing.flashtime = atoi(v->value);
11967 } else if (!strcasecmp(v->name, "start")) {
11968 confp->timing.starttime = atoi(v->value);
11969 } else if (!strcasecmp(v->name, "rxwink")) {
11970 confp->timing.rxwinktime = atoi(v->value);
11971 } else if (!strcasecmp(v->name, "rxflash")) {
11972 confp->timing.rxflashtime = atoi(v->value);
11973 } else if (!strcasecmp(v->name, "debounce")) {
11974 confp->timing.debouncetime = atoi(v->value);
11975 } else if (!strcasecmp(v->name, "toneduration")) {
11976 int toneduration;
11977 int ctlfd;
11978 int res;
11979 struct dahdi_dialparams dps;
11980
11981 ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
11982
11983 if (ctlfd == -1) {
11984 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
11985 return -1;
11986 }
11987
11988 toneduration = atoi(v->value);
11989 if (toneduration > -1) {
11990 memset(&dps, 0, sizeof(dps));
11991
11992 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11993 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11994 if (res < 0) {
11995 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11996 return -1;
11997 }
11998 }
11999 close(ctlfd);
12000 } else if (!strcasecmp(v->name, "defaultcic")) {
12001 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
12002 } else if (!strcasecmp(v->name, "defaultozz")) {
12003 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
12004 }
12005 } else if (!skipchannels)
12006 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
12007 }
12008 if (dahdichan[0]) {
12009
12010
12011 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
12012 return -1;
12013 }
12014 }
12015
12016
12017 if (!found_pseudo && reload == 0) {
12018
12019
12020
12021
12022 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
12023
12024 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
12025
12026 if (tmp) {
12027 if (option_verbose > 2)
12028 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
12029 } else {
12030 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
12031 }
12032 }
12033 return 0;
12034 }
12035
12036 static int setup_dahdi(int reload)
12037 {
12038 struct ast_config *cfg;
12039 struct ast_variable *v;
12040 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
12041 int res;
12042
12043 #ifdef HAVE_PRI
12044 char *c;
12045 int spanno;
12046 int i, x;
12047 int logicalspan;
12048 int trunkgroup;
12049 int dchannels[NUM_DCHANS];
12050 #endif
12051
12052 #ifdef HAVE_ZAPTEL
12053 int load_from_zapata_conf = 1;
12054 #else
12055 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
12056 #endif
12057
12058 if (load_from_zapata_conf) {
12059 if (!(cfg = ast_config_load("zapata.conf"))) {
12060 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
12061 return 0;
12062 }
12063 } else {
12064 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
12065 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
12066 return 0;
12067 }
12068 }
12069
12070
12071 ast_mutex_lock(&iflock);
12072 #ifdef HAVE_PRI
12073 if (reload != 1) {
12074
12075 v = ast_variable_browse(cfg, "trunkgroups");
12076 while (v) {
12077 if (!strcasecmp(v->name, "trunkgroup")) {
12078 trunkgroup = atoi(v->value);
12079 if (trunkgroup > 0) {
12080 if ((c = strchr(v->value, ','))) {
12081 i = 0;
12082 memset(dchannels, 0, sizeof(dchannels));
12083 while (c && (i < NUM_DCHANS)) {
12084 dchannels[i] = atoi(c + 1);
12085 if (dchannels[i] < 0) {
12086 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);
12087 } else
12088 i++;
12089 c = strchr(c + 1, ',');
12090 }
12091 if (i) {
12092 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
12093 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);
12094 } else if (option_verbose > 1)
12095 ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
12096 } else
12097 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12098 } else
12099 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12100 } else
12101 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
12102 } else if (!strcasecmp(v->name, "spanmap")) {
12103 spanno = atoi(v->value);
12104 if (spanno > 0) {
12105 if ((c = strchr(v->value, ','))) {
12106 trunkgroup = atoi(c + 1);
12107 if (trunkgroup > 0) {
12108 if ((c = strchr(c + 1, ',')))
12109 logicalspan = atoi(c + 1);
12110 else
12111 logicalspan = 0;
12112 if (logicalspan >= 0) {
12113 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
12114 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12115 } else if (option_verbose > 1)
12116 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12117 } else
12118 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);
12119 } else
12120 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
12121 } else
12122 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
12123 } else
12124 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
12125 } else {
12126 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
12127 }
12128 v = v->next;
12129 }
12130 }
12131 #endif
12132
12133
12134 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
12135
12136 v = ast_variable_browse(cfg, "channels");
12137 res = process_dahdi(&conf, "", v, reload, 0);
12138 ast_mutex_unlock(&iflock);
12139 ast_config_destroy(cfg);
12140 if (res)
12141 return res;
12142 cfg = ast_config_load("users.conf");
12143 if (cfg) {
12144 char *cat;
12145 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
12146 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
12147 if (!strcasecmp(cat, "general"))
12148 continue;
12149 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
12150 struct dahdi_chan_conf sect_conf;
12151 memcpy(§_conf, &conf, sizeof(sect_conf));
12152
12153 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
12154 }
12155 }
12156 ast_config_destroy(cfg);
12157 }
12158 #ifdef HAVE_PRI
12159 if (reload != 1) {
12160 for (x = 0; x < NUM_SPANS; x++) {
12161 if (pris[x].pvts[0]) {
12162 if (start_pri(pris + x)) {
12163 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
12164 return -1;
12165 } else if (option_verbose > 1)
12166 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
12167 }
12168 }
12169 }
12170 #endif
12171
12172 restart_monitor();
12173 return 0;
12174 }
12175
12176 #define local_astman_register(a, b, c, d) do { \
12177 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12178 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
12179 } \
12180 ast_manager_register("Zap" a, b, zap_ ## c, d); \
12181 } while (0)
12182
12183 static int load_module(void)
12184 {
12185 int res;
12186
12187 #ifdef HAVE_PRI
12188 int y,i;
12189 memset(pris, 0, sizeof(pris));
12190 for (y = 0; y < NUM_SPANS; y++) {
12191 ast_mutex_init(&pris[y].lock);
12192 pris[y].offset = -1;
12193 pris[y].master = AST_PTHREADT_NULL;
12194 for (i = 0; i < NUM_DCHANS; i++)
12195 pris[y].fds[i] = -1;
12196 }
12197 pri_set_error(dahdi_pri_error);
12198 pri_set_message(dahdi_pri_message);
12199 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12200 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
12201 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
12202 }
12203 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
12204 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
12205 #endif
12206 if ((res = setup_dahdi(0))) {
12207 return AST_MODULE_LOAD_DECLINE;
12208 }
12209 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12210 chan_tech = &dahdi_tech;
12211 } else {
12212 chan_tech = &zap_tech;
12213 }
12214 if (ast_channel_register(chan_tech)) {
12215 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
12216 __unload_module();
12217 return -1;
12218 }
12219 #ifdef HAVE_PRI
12220 ast_string_field_init(&inuse, 16);
12221 ast_string_field_set(&inuse, name, "GR-303InUse");
12222 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12223 #endif
12224 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12225
12226 memset(round_robin, 0, sizeof(round_robin));
12227 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
12228 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
12229 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
12230 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
12231 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
12232 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
12233 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
12234
12235 ast_cond_init(&ss_thread_complete, NULL);
12236
12237 return res;
12238 }
12239
12240 static int dahdi_sendtext(struct ast_channel *c, const char *text)
12241 {
12242 #define END_SILENCE_LEN 400
12243 #define HEADER_MS 50
12244 #define TRAILER_MS 5
12245 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
12246 #define ASCII_BYTES_PER_CHAR 80
12247
12248 unsigned char *buf,*mybuf;
12249 struct dahdi_pvt *p = c->tech_pvt;
12250 struct pollfd fds[1];
12251 int size,res,fd,len,x;
12252 int bytes=0;
12253
12254 float cr = 1.0;
12255 float ci = 0.0;
12256 float scont = 0.0;
12257 int index;
12258
12259 index = dahdi_get_index(c, p, 0);
12260 if (index < 0) {
12261 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
12262 return -1;
12263 }
12264 if (!text[0]) return(0);
12265 if ((!p->tdd) && (!p->mate)) return(0);
12266 if (p->mate)
12267 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
12268 else
12269 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
12270 if (!buf)
12271 return -1;
12272 mybuf = buf;
12273 if (p->mate) {
12274 int codec = AST_LAW(p);
12275 for (x = 0; x < HEADER_MS; x++) {
12276 PUT_CLID_MARKMS;
12277 }
12278
12279 for (x = 0; text[x]; x++) {
12280 PUT_CLID(text[x]);
12281 }
12282 for (x = 0; x < TRAILER_MS; x++) {
12283 PUT_CLID_MARKMS;
12284 }
12285 len = bytes;
12286 buf = mybuf;
12287 } else {
12288 len = tdd_generate(p->tdd, buf, text);
12289 if (len < 1) {
12290 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
12291 free(mybuf);
12292 return -1;
12293 }
12294 }
12295 memset(buf + len, 0x7f, END_SILENCE_LEN);
12296 len += END_SILENCE_LEN;
12297 fd = p->subs[index].dfd;
12298 while (len) {
12299 if (ast_check_hangup(c)) {
12300 free(mybuf);
12301 return -1;
12302 }
12303 size = len;
12304 if (size > READ_SIZE)
12305 size = READ_SIZE;
12306 fds[0].fd = fd;
12307 fds[0].events = POLLOUT | POLLPRI;
12308 fds[0].revents = 0;
12309 res = poll(fds, 1, -1);
12310 if (!res) {
12311 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
12312 continue;
12313 }
12314
12315 if (fds[0].revents & POLLPRI) {
12316 ast_free(mybuf);
12317 return -1;
12318 }
12319 if (!(fds[0].revents & POLLOUT)) {
12320 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
12321 continue;
12322 }
12323 res = write(fd, buf, size);
12324 if (res != size) {
12325 if (res == -1) {
12326 free(mybuf);
12327 return -1;
12328 }
12329 if (option_debug)
12330 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
12331 break;
12332 }
12333 len -= size;
12334 buf += size;
12335 }
12336 free(mybuf);
12337 return(0);
12338 }
12339
12340
12341 static int reload(void)
12342 {
12343 int res = 0;
12344
12345 res = setup_dahdi(1);
12346 if (res) {
12347 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12348 return -1;
12349 }
12350 return 0;
12351 }
12352
12353
12354
12355
12356
12357 #ifdef HAVE_PRI
12358 #define tdesc "DAHDI Telephony w/PRI"
12359 #else
12360 #define tdesc "DAHDI Telephony"
12361 #endif
12362
12363 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
12364 .load = load_module,
12365 .unload = unload_module,
12366 .reload = reload,
12367 );
12368
12369