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: 211596 $")
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 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01647 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01648 return -1;
01649 }
01650 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01651 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01652 return 0;
01653 }
01654
01655 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01656 {
01657 int x;
01658 int useslavenative;
01659 struct dahdi_pvt *slave = NULL;
01660
01661 useslavenative = 1;
01662
01663 for (x = 0; x < 3; x++) {
01664
01665
01666 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01667 useslavenative = 0;
01668 }
01669
01670
01671 if (useslavenative) {
01672 for (x = 0; x < MAX_SLAVES; x++) {
01673 if (p->slaves[x]) {
01674 if (slave) {
01675
01676
01677 slave = NULL;
01678 useslavenative = 0;
01679 break;
01680 } else {
01681
01682 slave = p->slaves[x];
01683 }
01684 }
01685 }
01686 }
01687
01688 if (!slave)
01689 useslavenative = 0;
01690 else if (slave->law != p->law) {
01691 useslavenative = 0;
01692 slave = NULL;
01693 }
01694 if (out)
01695 *out = slave;
01696 return useslavenative;
01697 }
01698
01699 static int reset_conf(struct dahdi_pvt *p)
01700 {
01701 p->confno = -1;
01702 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01703 if (p->subs[SUB_REAL].dfd > -1) {
01704 struct dahdi_confinfo zi;
01705
01706 memset(&zi, 0, sizeof(zi));
01707 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01708 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01709 }
01710 return 0;
01711 }
01712
01713 static int update_conf(struct dahdi_pvt *p)
01714 {
01715 int needconf = 0;
01716 int x;
01717 int useslavenative;
01718 struct dahdi_pvt *slave = NULL;
01719
01720 useslavenative = isslavenative(p, &slave);
01721
01722 for (x = 0; x < 3; x++) {
01723
01724 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01725 conf_add(p, &p->subs[x], x, 0);
01726 needconf++;
01727 } else {
01728 conf_del(p, &p->subs[x], x);
01729 }
01730 }
01731
01732
01733 for (x = 0; x < MAX_SLAVES; x++) {
01734 if (p->slaves[x]) {
01735 if (useslavenative)
01736 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01737 else {
01738 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01739 needconf++;
01740 }
01741 }
01742 }
01743
01744 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01745 if (useslavenative)
01746 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01747 else {
01748 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01749 needconf++;
01750 }
01751 }
01752
01753 if (p->master) {
01754 if (isslavenative(p->master, NULL)) {
01755 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01756 } else {
01757 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01758 }
01759 }
01760 if (!needconf) {
01761
01762
01763 p->confno = -1;
01764 }
01765 if (option_debug)
01766 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01767 return 0;
01768 }
01769
01770 static void dahdi_enable_ec(struct dahdi_pvt *p)
01771 {
01772 int x;
01773 int res;
01774 if (!p)
01775 return;
01776 if (p->echocanon) {
01777 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01778 return;
01779 }
01780 if (p->digital) {
01781 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01782 return;
01783 }
01784 if (p->echocancel) {
01785 if (p->sig == SIG_PRI) {
01786 x = 1;
01787 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
01788 if (res)
01789 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01790 }
01791 x = p->echocancel;
01792 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01793 if (res)
01794 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01795 else {
01796 p->echocanon = 1;
01797 if (option_debug)
01798 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01799 }
01800 } else if (option_debug)
01801 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01802 }
01803
01804 static void dahdi_train_ec(struct dahdi_pvt *p)
01805 {
01806 int x;
01807 int res;
01808 if (p && p->echocancel && p->echotraining) {
01809 x = p->echotraining;
01810 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
01811 if (res)
01812 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
01813 else {
01814 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01815 }
01816 } else
01817 ast_log(LOG_DEBUG, "No echo training requested\n");
01818 }
01819
01820 static void dahdi_disable_ec(struct dahdi_pvt *p)
01821 {
01822 int x;
01823 int res;
01824 if (p->echocancel) {
01825 x = 0;
01826 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01827 if (res)
01828 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
01829 else if (option_debug)
01830 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01831 }
01832 p->echocanon = 0;
01833 }
01834
01835 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
01836 {
01837 int j;
01838 int k;
01839 float linear_gain = pow(10.0, gain / 20.0);
01840
01841 switch (law) {
01842 case DAHDI_LAW_ALAW:
01843 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01844 if (gain) {
01845 k = (int) (((float) AST_ALAW(j)) * linear_gain);
01846 if (k > 32767) k = 32767;
01847 if (k < -32767) k = -32767;
01848 g->txgain[j] = AST_LIN2A(k);
01849 } else {
01850 g->txgain[j] = j;
01851 }
01852 }
01853 break;
01854 case DAHDI_LAW_MULAW:
01855 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01856 if (gain) {
01857 k = (int) (((float) AST_MULAW(j)) * linear_gain);
01858 if (k > 32767) k = 32767;
01859 if (k < -32767) k = -32767;
01860 g->txgain[j] = AST_LIN2MU(k);
01861 } else {
01862 g->txgain[j] = j;
01863 }
01864 }
01865 break;
01866 }
01867 }
01868
01869 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
01870 {
01871 int j;
01872 int k;
01873 float linear_gain = pow(10.0, gain / 20.0);
01874
01875 switch (law) {
01876 case DAHDI_LAW_ALAW:
01877 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01878 if (gain) {
01879 k = (int) (((float) AST_ALAW(j)) * linear_gain);
01880 if (k > 32767) k = 32767;
01881 if (k < -32767) k = -32767;
01882 g->rxgain[j] = AST_LIN2A(k);
01883 } else {
01884 g->rxgain[j] = j;
01885 }
01886 }
01887 break;
01888 case DAHDI_LAW_MULAW:
01889 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01890 if (gain) {
01891 k = (int) (((float) AST_MULAW(j)) * linear_gain);
01892 if (k > 32767) k = 32767;
01893 if (k < -32767) k = -32767;
01894 g->rxgain[j] = AST_LIN2MU(k);
01895 } else {
01896 g->rxgain[j] = j;
01897 }
01898 }
01899 break;
01900 }
01901 }
01902
01903 static int set_actual_txgain(int fd, int chan, float gain, int law)
01904 {
01905 struct dahdi_gains g;
01906 int res;
01907
01908 memset(&g, 0, sizeof(g));
01909 g.chan = chan;
01910 res = ioctl(fd, DAHDI_GETGAINS, &g);
01911 if (res) {
01912 if (option_debug)
01913 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01914 return res;
01915 }
01916
01917 fill_txgain(&g, gain, law);
01918
01919 return ioctl(fd, DAHDI_SETGAINS, &g);
01920 }
01921
01922 static int set_actual_rxgain(int fd, int chan, float gain, int law)
01923 {
01924 struct dahdi_gains g;
01925 int res;
01926
01927 memset(&g, 0, sizeof(g));
01928 g.chan = chan;
01929 res = ioctl(fd, DAHDI_GETGAINS, &g);
01930 if (res) {
01931 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01932 return res;
01933 }
01934
01935 fill_rxgain(&g, gain, law);
01936
01937 return ioctl(fd, DAHDI_SETGAINS, &g);
01938 }
01939
01940 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
01941 {
01942 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01943 }
01944
01945 static int bump_gains(struct dahdi_pvt *p)
01946 {
01947 int res;
01948
01949
01950 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01951 if (res) {
01952 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01953 return -1;
01954 }
01955
01956 return 0;
01957 }
01958
01959 static int restore_gains(struct dahdi_pvt *p)
01960 {
01961 int res;
01962
01963 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01964 if (res) {
01965 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01966 return -1;
01967 }
01968
01969 return 0;
01970 }
01971
01972 static inline int dahdi_set_hook(int fd, int hs)
01973 {
01974 int x, res;
01975
01976 x = hs;
01977 res = ioctl(fd, DAHDI_HOOK, &x);
01978
01979 if (res < 0) {
01980 if (errno == EINPROGRESS)
01981 return 0;
01982 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
01983
01984 }
01985
01986 return res;
01987 }
01988
01989 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
01990 {
01991 int x, y, res;
01992 x = muted;
01993 if (p->sig == SIG_PRI) {
01994 y = 1;
01995 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
01996 if (res)
01997 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
01998 }
01999 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02000 if (res < 0)
02001 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02002 return res;
02003 }
02004
02005 static int save_conference(struct dahdi_pvt *p)
02006 {
02007 struct dahdi_confinfo c;
02008 int res;
02009 if (p->saveconf.confmode) {
02010 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02011 return -1;
02012 }
02013 p->saveconf.chan = 0;
02014 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02015 if (res) {
02016 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02017 p->saveconf.confmode = 0;
02018 return -1;
02019 }
02020 memset(&c, 0, sizeof(c));
02021 c.confmode = DAHDI_CONF_NORMAL;
02022 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02023 if (res) {
02024 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02025 return -1;
02026 }
02027 if (option_debug)
02028 ast_log(LOG_DEBUG, "Disabled conferencing\n");
02029 return 0;
02030 }
02031
02032 static int restore_conference(struct dahdi_pvt *p)
02033 {
02034 int res;
02035 if (p->saveconf.confmode) {
02036 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02037 p->saveconf.confmode = 0;
02038 if (res) {
02039 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02040 return -1;
02041 }
02042 }
02043 if (option_debug)
02044 ast_log(LOG_DEBUG, "Restored conferencing\n");
02045 return 0;
02046 }
02047
02048 static int send_callerid(struct dahdi_pvt *p);
02049
02050 static int send_cwcidspill(struct dahdi_pvt *p)
02051 {
02052 p->callwaitcas = 0;
02053 p->cidcwexpire = 0;
02054 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02055 return -1;
02056 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02057
02058 p->cidlen += READ_SIZE * 4;
02059 p->cidpos = 0;
02060 send_callerid(p);
02061 if (option_verbose > 2)
02062 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02063 return 0;
02064 }
02065
02066 static int has_voicemail(struct dahdi_pvt *p)
02067 {
02068
02069 return ast_app_has_voicemail(p->mailbox, NULL);
02070 }
02071
02072 static int send_callerid(struct dahdi_pvt *p)
02073 {
02074
02075 int res;
02076
02077 if (p->subs[SUB_REAL].linear) {
02078 p->subs[SUB_REAL].linear = 0;
02079 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02080 }
02081 while (p->cidpos < p->cidlen) {
02082 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02083 if (res < 0) {
02084 if (errno == EAGAIN)
02085 return 0;
02086 else {
02087 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02088 return -1;
02089 }
02090 }
02091 if (!res)
02092 return 0;
02093 p->cidpos += res;
02094 }
02095 free(p->cidspill);
02096 p->cidspill = NULL;
02097 if (p->callwaitcas) {
02098
02099 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02100 } else
02101 restore_conference(p);
02102 return 0;
02103 }
02104
02105 static int dahdi_callwait(struct ast_channel *ast)
02106 {
02107 struct dahdi_pvt *p = ast->tech_pvt;
02108 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02109 if (p->cidspill) {
02110 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02111 free(p->cidspill);
02112 }
02113 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02114 return -1;
02115 save_conference(p);
02116
02117 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02118 if (!p->callwaitrings && p->callwaitingcallerid) {
02119 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02120 p->callwaitcas = 1;
02121 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02122 } else {
02123 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02124 p->callwaitcas = 0;
02125 p->cidlen = 2400 + READ_SIZE * 4;
02126 }
02127 p->cidpos = 0;
02128 send_callerid(p);
02129
02130 return 0;
02131 }
02132
02133 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02134 {
02135 struct dahdi_pvt *p = ast->tech_pvt;
02136 int x, res, index,mysig;
02137 char *c, *n, *l;
02138 #ifdef HAVE_PRI
02139 char *s = NULL;
02140 #endif
02141 char dest[256];
02142 ast_mutex_lock(&p->lock);
02143 ast_copy_string(dest, rdest, sizeof(dest));
02144 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02145 if ((ast->_state == AST_STATE_BUSY)) {
02146 p->subs[SUB_REAL].needbusy = 1;
02147 ast_mutex_unlock(&p->lock);
02148 return 0;
02149 }
02150 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02151 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02152 ast_mutex_unlock(&p->lock);
02153 return -1;
02154 }
02155 p->dialednone = 0;
02156 if ((p->radio || (p->oprmode < 0)))
02157 {
02158
02159 ast_setstate(ast, AST_STATE_UP);
02160 ast_mutex_unlock(&p->lock);
02161 return 0;
02162 }
02163 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02164 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02165 if (res)
02166 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02167 p->outgoing = 1;
02168
02169 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02170
02171 mysig = p->sig;
02172 if (p->outsigmod > -1)
02173 mysig = p->outsigmod;
02174
02175 switch (mysig) {
02176 case SIG_FXOLS:
02177 case SIG_FXOGS:
02178 case SIG_FXOKS:
02179 if (p->owner == ast) {
02180
02181
02182
02183 p->dialing = 1;
02184 if (p->use_callerid) {
02185
02186 if (p->cidspill) {
02187 ast_log(LOG_WARNING, "cidspill already exists??\n");
02188 free(p->cidspill);
02189 }
02190 p->callwaitcas = 0;
02191 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02192 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02193 p->cidpos = 0;
02194 send_callerid(p);
02195 }
02196 }
02197
02198 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02199 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02200 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02201 p->cidrings = cidrings[p->distinctivering - 1];
02202 } else {
02203 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02204 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02205 p->cidrings = p->sendcalleridafter;
02206 }
02207
02208
02209 c = strchr(dest, '/');
02210 if (c)
02211 c++;
02212 if (c && (strlen(c) < p->stripmsd)) {
02213 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02214 c = NULL;
02215 }
02216 if (c) {
02217 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02218 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02219 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02220 } else {
02221 p->dop.dialstr[0] = '\0';
02222 }
02223 x = DAHDI_RING;
02224 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02225 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02226 ast_mutex_unlock(&p->lock);
02227 return -1;
02228 }
02229 p->dialing = 1;
02230 } else {
02231
02232 p->callwaitrings = 0;
02233 if (ast->cid.cid_num)
02234 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02235 else
02236 p->callwait_num[0] = '\0';
02237 if (ast->cid.cid_name)
02238 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02239 else
02240 p->callwait_name[0] = '\0';
02241
02242 if (dahdi_callwait(ast)) {
02243 ast_mutex_unlock(&p->lock);
02244 return -1;
02245 }
02246
02247 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02248 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02249
02250 }
02251 n = ast->cid.cid_name;
02252 l = ast->cid.cid_num;
02253 if (l)
02254 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02255 else
02256 p->lastcid_num[0] = '\0';
02257 if (n)
02258 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02259 else
02260 p->lastcid_name[0] = '\0';
02261 ast_setstate(ast, AST_STATE_RINGING);
02262 index = dahdi_get_index(ast, p, 0);
02263 if (index > -1) {
02264 p->subs[index].needringing = 1;
02265 }
02266 break;
02267 case SIG_FXSLS:
02268 case SIG_FXSGS:
02269 case SIG_FXSKS:
02270 case SIG_EMWINK:
02271 case SIG_EM:
02272 case SIG_EM_E1:
02273 case SIG_FEATD:
02274 case SIG_FEATDMF:
02275 case SIG_E911:
02276 case SIG_FGC_CAMA:
02277 case SIG_FGC_CAMAMF:
02278 case SIG_FEATB:
02279 case SIG_SFWINK:
02280 case SIG_SF:
02281 case SIG_SF_FEATD:
02282 case SIG_SF_FEATDMF:
02283 case SIG_FEATDMF_TA:
02284 case SIG_SF_FEATB:
02285 c = strchr(dest, '/');
02286 if (c)
02287 c++;
02288 else
02289 c = "";
02290 if (strlen(c) < p->stripmsd) {
02291 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02292 ast_mutex_unlock(&p->lock);
02293 return -1;
02294 }
02295 #ifdef HAVE_PRI
02296
02297 if (!p->pri) {
02298 #endif
02299 x = DAHDI_START;
02300 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02301 if (res < 0) {
02302 if (errno != EINPROGRESS) {
02303 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02304 ast_mutex_unlock(&p->lock);
02305 return -1;
02306 }
02307 }
02308 #ifdef HAVE_PRI
02309 }
02310 #endif
02311 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02312 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02313
02314 c += p->stripmsd;
02315
02316 switch (mysig) {
02317 case SIG_FEATD:
02318 l = ast->cid.cid_num;
02319 if (l)
02320 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02321 else
02322 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02323 break;
02324 case SIG_FEATDMF:
02325 l = ast->cid.cid_num;
02326 if (l)
02327 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02328 else
02329 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02330 break;
02331 case SIG_FEATDMF_TA:
02332 {
02333 const char *cic, *ozz;
02334
02335
02336 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02337 if (!ozz)
02338 ozz = defaultozz;
02339 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02340 if (!cic)
02341 cic = defaultcic;
02342 if (!ozz || !cic) {
02343 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02344 ast_mutex_unlock(&p->lock);
02345 return -1;
02346 }
02347 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02348 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02349 p->whichwink = 0;
02350 }
02351 break;
02352 case SIG_E911:
02353 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02354 break;
02355 case SIG_FGC_CAMA:
02356 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02357 break;
02358 case SIG_FGC_CAMAMF:
02359 case SIG_FEATB:
02360 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02361 break;
02362 default:
02363 if (p->pulse)
02364 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02365 else
02366 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02367 break;
02368 }
02369
02370 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02371 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02372 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02373 p->echorest[sizeof(p->echorest) - 1] = '\0';
02374 p->echobreak = 1;
02375 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02376 } else
02377 p->echobreak = 0;
02378 if (!res) {
02379 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02380 int saveerr = errno;
02381
02382 x = DAHDI_ONHOOK;
02383 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02384 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02385 ast_mutex_unlock(&p->lock);
02386 return -1;
02387 }
02388 } else
02389 ast_log(LOG_DEBUG, "Deferring dialing...\n");
02390 p->dialing = 1;
02391 if (ast_strlen_zero(c))
02392 p->dialednone = 1;
02393 ast_setstate(ast, AST_STATE_DIALING);
02394 break;
02395 case 0:
02396
02397 ast_setstate(ast, AST_STATE_UP);
02398 break;
02399 case SIG_PRI:
02400
02401 p->dialdest[0] = '\0';
02402 p->dialing = 1;
02403 break;
02404 default:
02405 ast_log(LOG_DEBUG, "not yet implemented\n");
02406 ast_mutex_unlock(&p->lock);
02407 return -1;
02408 }
02409 #ifdef HAVE_PRI
02410 if (p->pri) {
02411 struct pri_sr *sr;
02412 #ifdef SUPPORT_USERUSER
02413 const char *useruser;
02414 #endif
02415 int pridialplan;
02416 int dp_strip;
02417 int prilocaldialplan;
02418 int ldp_strip;
02419 int exclusive;
02420 const char *rr_str;
02421 int redirect_reason;
02422
02423 c = strchr(dest, '/');
02424 if (c) {
02425 c++;
02426 } else {
02427 c = "";
02428 }
02429
02430 l = NULL;
02431 n = NULL;
02432 if (!p->hidecallerid) {
02433 l = ast->cid.cid_num;
02434 if (!p->hidecalleridname) {
02435 n = ast->cid.cid_name;
02436 }
02437 }
02438
02439
02440 if (strlen(c) < p->stripmsd) {
02441 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02442 ast_mutex_unlock(&p->lock);
02443 return -1;
02444 }
02445 if (mysig != SIG_FXSKS) {
02446 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02447 s = strchr(c + p->stripmsd, 'w');
02448 if (s) {
02449 if (strlen(s) > 1)
02450 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02451 else
02452 p->dop.dialstr[0] = '\0';
02453 *s = '\0';
02454 } else {
02455 p->dop.dialstr[0] = '\0';
02456 }
02457 }
02458 if (pri_grab(p, p->pri)) {
02459 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02460 ast_mutex_unlock(&p->lock);
02461 return -1;
02462 }
02463 if (!(p->call = pri_new_call(p->pri->pri))) {
02464 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02465 pri_rel(p->pri);
02466 ast_mutex_unlock(&p->lock);
02467 return -1;
02468 }
02469 if (!(sr = pri_sr_new())) {
02470 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02471 pri_destroycall(p->pri->pri, p->call);
02472 p->call = NULL;
02473 pri_rel(p->pri);
02474 ast_mutex_unlock(&p->lock);
02475 return -1;
02476 }
02477 if (p->bearer || (mysig == SIG_FXSKS)) {
02478 if (p->bearer) {
02479 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);
02480 p->bearer->call = p->call;
02481 } else
02482 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02483 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02484 }
02485 p->digital = IS_DIGITAL(ast->transfercapability);
02486
02487
02488 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
02489 exclusive = 1;
02490 } else {
02491 exclusive = 0;
02492 }
02493
02494 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02495 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02496 (p->digital ? -1 :
02497 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02498 if (p->pri->facilityenable)
02499 pri_facility_enable(p->pri->pri);
02500
02501 if (option_verbose > 2)
02502 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02503 dp_strip = 0;
02504 pridialplan = p->pri->dialplan - 1;
02505 if (pridialplan == -2) {
02506 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02507 dp_strip = strlen(p->pri->internationalprefix);
02508 pridialplan = PRI_INTERNATIONAL_ISDN;
02509 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02510 dp_strip = strlen(p->pri->nationalprefix);
02511 pridialplan = PRI_NATIONAL_ISDN;
02512 } else {
02513 pridialplan = PRI_LOCAL_ISDN;
02514 }
02515 }
02516 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02517
02518 ldp_strip = 0;
02519 prilocaldialplan = p->pri->localdialplan - 1;
02520 if ((l != NULL) && (prilocaldialplan == -2)) {
02521 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02522 ldp_strip = strlen(p->pri->internationalprefix);
02523 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02524 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02525 ldp_strip = strlen(p->pri->nationalprefix);
02526 prilocaldialplan = PRI_NATIONAL_ISDN;
02527 } else {
02528 prilocaldialplan = PRI_LOCAL_ISDN;
02529 }
02530 }
02531 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02532 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02533 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02534 if (!strcasecmp(rr_str, "UNKNOWN"))
02535 redirect_reason = 0;
02536 else if (!strcasecmp(rr_str, "BUSY"))
02537 redirect_reason = 1;
02538 else if (!strcasecmp(rr_str, "NO_REPLY"))
02539 redirect_reason = 2;
02540 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02541 redirect_reason = 15;
02542 else
02543 redirect_reason = PRI_REDIR_UNCONDITIONAL;
02544 } else
02545 redirect_reason = PRI_REDIR_UNCONDITIONAL;
02546 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02547
02548 #ifdef SUPPORT_USERUSER
02549
02550 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02551
02552 if (useruser)
02553 pri_sr_set_useruser(sr, useruser);
02554 #endif
02555
02556 if (pri_setup(p->pri->pri, p->call, sr)) {
02557 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
02558 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02559 pri_rel(p->pri);
02560 ast_mutex_unlock(&p->lock);
02561 pri_sr_free(sr);
02562 return -1;
02563 }
02564 pri_sr_free(sr);
02565 ast_setstate(ast, AST_STATE_DIALING);
02566 pri_rel(p->pri);
02567 }
02568 #endif
02569 ast_mutex_unlock(&p->lock);
02570 return 0;
02571 }
02572
02573 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
02574 {
02575 struct dahdi_pvt *p = *pvt;
02576
02577 if (p->prev)
02578 p->prev->next = p->next;
02579 if (p->next)
02580 p->next->prev = p->prev;
02581 if (p->use_smdi)
02582 ast_smdi_interface_unref(p->smdi_iface);
02583 ast_mutex_destroy(&p->lock);
02584 dahdi_close_sub(p, SUB_REAL);
02585 if (p->owner)
02586 p->owner->tech_pvt = NULL;
02587 free(p);
02588 *pvt = NULL;
02589 }
02590
02591 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
02592 {
02593 int owned = 0;
02594 int i = 0;
02595
02596 if (!now) {
02597 if (cur->owner) {
02598 owned = 1;
02599 }
02600
02601 for (i = 0; i < 3; i++) {
02602 if (cur->subs[i].owner) {
02603 owned = 1;
02604 }
02605 }
02606 if (!owned) {
02607 if (prev) {
02608 prev->next = cur->next;
02609 if (prev->next)
02610 prev->next->prev = prev;
02611 else
02612 ifend = prev;
02613 } else {
02614 iflist = cur->next;
02615 if (iflist)
02616 iflist->prev = NULL;
02617 else
02618 ifend = NULL;
02619 }
02620 destroy_dahdi_pvt(&cur);
02621 }
02622 } else {
02623 if (prev) {
02624 prev->next = cur->next;
02625 if (prev->next)
02626 prev->next->prev = prev;
02627 else
02628 ifend = prev;
02629 } else {
02630 iflist = cur->next;
02631 if (iflist)
02632 iflist->prev = NULL;
02633 else
02634 ifend = NULL;
02635 }
02636 destroy_dahdi_pvt(&cur);
02637 }
02638 return 0;
02639 }
02640
02641 static void destroy_all_channels(void)
02642 {
02643 int x;
02644 struct dahdi_pvt *p, *pl;
02645
02646 while (num_restart_pending) {
02647 usleep(1);
02648 }
02649
02650 ast_mutex_lock(&iflock);
02651
02652 p = iflist;
02653 while (p) {
02654
02655 if (p->cidspill)
02656 ast_free(p->cidspill);
02657 pl = p;
02658 p = p->next;
02659 x = pl->channel;
02660
02661 if (pl)
02662 destroy_dahdi_pvt(&pl);
02663 if (option_verbose > 2)
02664 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
02665 }
02666 iflist = NULL;
02667 ifcount = 0;
02668 ast_mutex_unlock(&iflock);
02669 }
02670
02671 #ifdef HAVE_PRI
02672 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
02673 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
02674
02675 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02676 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02677
02678 static char *dahdi_send_keypad_facility_descrip =
02679 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02680 " IE over the current channel.\n";
02681 static char *zap_send_keypad_facility_descrip =
02682 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02683 " IE over the current channel.\n";
02684
02685 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
02686 {
02687
02688 struct dahdi_pvt *p;
02689 char *digits = (char *) data;
02690
02691 if (ast_strlen_zero(digits)) {
02692 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
02693 return -1;
02694 }
02695
02696 p = (struct dahdi_pvt *)chan->tech_pvt;
02697
02698 if (!p) {
02699 ast_log(LOG_DEBUG, "Unable to find technology private\n");
02700 return -1;
02701 }
02702
02703 ast_mutex_lock(&p->lock);
02704
02705 if (!p->pri || !p->call) {
02706 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
02707 ast_mutex_unlock(&p->lock);
02708 return -1;
02709 }
02710
02711 if (!pri_grab(p, p->pri)) {
02712 pri_keypad_facility(p->pri->pri, p->call, digits);
02713 pri_rel(p->pri);
02714 } else {
02715 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
02716 ast_mutex_unlock(&p->lock);
02717 return -1;
02718 }
02719
02720 ast_mutex_unlock(&p->lock);
02721
02722 return 0;
02723 }
02724
02725 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02726 {
02727 return send_keypad_facility_exec(chan, data);
02728 }
02729
02730 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02731 {
02732 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);
02733 return send_keypad_facility_exec(chan, data);
02734 }
02735
02736 static int pri_is_up(struct dahdi_pri *pri)
02737 {
02738 int x;
02739 for (x = 0; x < NUM_DCHANS; x++) {
02740 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
02741 return 1;
02742 }
02743 return 0;
02744 }
02745
02746 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
02747 {
02748 bearer->owner = &inuse;
02749 bearer->realcall = crv;
02750 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
02751 if (crv->subs[SUB_REAL].owner)
02752 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
02753 crv->bearer = bearer;
02754 crv->call = bearer->call;
02755 crv->pri = pri;
02756 return 0;
02757 }
02758
02759 static char *pri_order(int level)
02760 {
02761 switch (level) {
02762 case 0:
02763 return "Primary";
02764 case 1:
02765 return "Secondary";
02766 case 2:
02767 return "Tertiary";
02768 case 3:
02769 return "Quaternary";
02770 default:
02771 return "<Unknown>";
02772 }
02773 }
02774
02775
02776 static int pri_active_dchan_fd(struct dahdi_pri *pri)
02777 {
02778 int x = -1;
02779
02780 for (x = 0; x < NUM_DCHANS; x++) {
02781 if ((pri->dchans[x] == pri->pri))
02782 break;
02783 }
02784
02785 return pri->fds[x];
02786 }
02787
02788 static int pri_find_dchan(struct dahdi_pri *pri)
02789 {
02790 int oldslot = -1;
02791 struct pri *old;
02792 int newslot = -1;
02793 int x;
02794 old = pri->pri;
02795 for (x = 0; x < NUM_DCHANS; x++) {
02796 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
02797 newslot = x;
02798 if (pri->dchans[x] == old) {
02799 oldslot = x;
02800 }
02801 }
02802 if (newslot < 0) {
02803 newslot = 0;
02804 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
02805 pri->dchannels[newslot]);
02806 }
02807 if (old && (oldslot != newslot))
02808 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
02809 pri->dchannels[oldslot], pri->dchannels[newslot]);
02810 pri->pri = pri->dchans[newslot];
02811 return 0;
02812 }
02813 #endif
02814
02815 static int dahdi_hangup(struct ast_channel *ast)
02816 {
02817 int res;
02818 int index,x, law;
02819
02820 struct dahdi_pvt *p = ast->tech_pvt;
02821 struct dahdi_pvt *tmp = NULL;
02822 struct dahdi_pvt *prev = NULL;
02823 struct dahdi_params par;
02824
02825 if (option_debug)
02826 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
02827 if (!ast->tech_pvt) {
02828 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02829 return 0;
02830 }
02831
02832 ast_mutex_lock(&p->lock);
02833
02834 index = dahdi_get_index(ast, p, 1);
02835
02836 if (p->sig == SIG_PRI) {
02837 x = 1;
02838 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02839 }
02840
02841 x = 0;
02842 dahdi_confmute(p, 0);
02843 restore_gains(p);
02844 if (p->origcid_num) {
02845 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02846 free(p->origcid_num);
02847 p->origcid_num = NULL;
02848 }
02849 if (p->origcid_name) {
02850 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02851 free(p->origcid_name);
02852 p->origcid_name = NULL;
02853 }
02854 if (p->dsp)
02855 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02856 p->exten[0] = '\0';
02857
02858 if (option_debug)
02859 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02860 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
02861 p->ignoredtmf = 0;
02862
02863 if (index > -1) {
02864
02865 p->subs[index].owner = NULL;
02866 p->subs[index].needanswer = 0;
02867 p->subs[index].needflash = 0;
02868 p->subs[index].needringing = 0;
02869 p->subs[index].needbusy = 0;
02870 p->subs[index].needcongestion = 0;
02871 p->subs[index].linear = 0;
02872 p->subs[index].needcallerid = 0;
02873 p->polarity = POLARITY_IDLE;
02874 dahdi_setlinear(p->subs[index].dfd, 0);
02875 if (index == SUB_REAL) {
02876 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
02877 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02878 if (p->subs[SUB_CALLWAIT].inthreeway) {
02879
02880 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02881
02882 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02883 unalloc_sub(p, SUB_CALLWAIT);
02884 p->owner = NULL;
02885 } else {
02886
02887 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
02888 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02889 unalloc_sub(p, SUB_THREEWAY);
02890 if (p->subs[SUB_REAL].inthreeway) {
02891
02892
02893 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02894 p->owner = p->subs[SUB_REAL].owner;
02895 } else {
02896
02897 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02898 p->owner = NULL;
02899 }
02900 p->subs[SUB_REAL].inthreeway = 0;
02901 }
02902 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
02903
02904 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02905 unalloc_sub(p, SUB_CALLWAIT);
02906 p->owner = p->subs[SUB_REAL].owner;
02907 if (p->owner->_state != AST_STATE_UP)
02908 p->subs[SUB_REAL].needanswer = 1;
02909 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02910 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02911 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
02912 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02913 unalloc_sub(p, SUB_THREEWAY);
02914 if (p->subs[SUB_REAL].inthreeway) {
02915
02916
02917 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02918 p->owner = p->subs[SUB_REAL].owner;
02919 } else {
02920
02921 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02922 p->owner = NULL;
02923 }
02924 p->subs[SUB_REAL].inthreeway = 0;
02925 }
02926 } else if (index == SUB_CALLWAIT) {
02927
02928 if (p->subs[SUB_CALLWAIT].inthreeway) {
02929
02930
02931 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02932 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
02933 S_OR(p->mohsuggest, NULL),
02934 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02935 }
02936 p->subs[SUB_THREEWAY].inthreeway = 0;
02937
02938 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02939 unalloc_sub(p, SUB_THREEWAY);
02940 } else
02941 unalloc_sub(p, SUB_CALLWAIT);
02942 } else if (index == SUB_THREEWAY) {
02943 if (p->subs[SUB_CALLWAIT].inthreeway) {
02944
02945
02946 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02947 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
02948 S_OR(p->mohsuggest, NULL),
02949 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02950 }
02951 p->subs[SUB_CALLWAIT].inthreeway = 0;
02952 }
02953 p->subs[SUB_REAL].inthreeway = 0;
02954
02955
02956 unalloc_sub(p, SUB_THREEWAY);
02957 } else {
02958
02959 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02960 }
02961 }
02962
02963 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02964 p->owner = NULL;
02965 p->ringt = 0;
02966 p->distinctivering = 0;
02967 p->confirmanswer = 0;
02968 p->cidrings = 1;
02969 p->outgoing = 0;
02970 p->digital = 0;
02971 p->faxhandled = 0;
02972 p->pulsedial = 0;
02973 p->onhooktime = time(NULL);
02974 #ifdef HAVE_PRI
02975 p->proceeding = 0;
02976 p->dialing = 0;
02977 p->progress = 0;
02978 p->alerting = 0;
02979 p->setup_ack = 0;
02980 #endif
02981 if (p->dsp) {
02982 ast_dsp_free(p->dsp);
02983 p->dsp = NULL;
02984 }
02985
02986 law = DAHDI_LAW_DEFAULT;
02987 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02988 if (res < 0)
02989 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02990
02991 #ifdef HAVE_PRI
02992 if (p->pri) {
02993 #ifdef SUPPORT_USERUSER
02994 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02995 #endif
02996
02997
02998 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02999 if (!pri_grab(p, p->pri)) {
03000 if (p->alreadyhungup) {
03001 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
03002
03003 #ifdef SUPPORT_USERUSER
03004 pri_call_set_useruser(p->call, useruser);
03005 #endif
03006
03007 pri_hangup(p->pri->pri, p->call, -1);
03008 p->call = NULL;
03009 if (p->bearer)
03010 p->bearer->call = NULL;
03011 } else {
03012 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03013 int icause = ast->hangupcause ? ast->hangupcause : -1;
03014 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03015
03016 #ifdef SUPPORT_USERUSER
03017 pri_call_set_useruser(p->call, useruser);
03018 #endif
03019
03020 p->alreadyhungup = 1;
03021 if (p->bearer)
03022 p->bearer->alreadyhungup = 1;
03023 if (cause) {
03024 if (atoi(cause))
03025 icause = atoi(cause);
03026 }
03027 pri_hangup(p->pri->pri, p->call, icause);
03028 }
03029 if (res < 0)
03030 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03031 pri_rel(p->pri);
03032 } else {
03033 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03034 res = -1;
03035 }
03036 } else {
03037 if (p->bearer)
03038 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03039 p->call = NULL;
03040 res = 0;
03041 }
03042 }
03043 #endif
03044 if (p->sig && (p->sig != SIG_PRI))
03045 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03046 if (res < 0) {
03047 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03048 }
03049 switch (p->sig) {
03050 case SIG_FXOGS:
03051 case SIG_FXOLS:
03052 case SIG_FXOKS:
03053 memset(&par, 0, sizeof(par));
03054 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03055 if (!res) {
03056 #if 0
03057 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03058 #endif
03059
03060 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03061 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03062 else
03063 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03064 }
03065 break;
03066 case SIG_FXSGS:
03067 case SIG_FXSLS:
03068 case SIG_FXSKS:
03069
03070
03071 if (ast->_state != AST_STATE_RESERVED) {
03072 time(&p->guardtime);
03073 p->guardtime += 2;
03074 }
03075 break;
03076 default:
03077 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03078 }
03079 if (p->cidspill)
03080 free(p->cidspill);
03081 if (p->sig)
03082 dahdi_disable_ec(p);
03083 x = 0;
03084 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03085 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03086 p->didtdd = 0;
03087 p->cidspill = NULL;
03088 p->callwaitcas = 0;
03089 p->callwaiting = p->permcallwaiting;
03090 p->hidecallerid = p->permhidecallerid;
03091 p->dialing = 0;
03092 p->rdnis[0] = '\0';
03093 update_conf(p);
03094 reset_conf(p);
03095
03096 if (p->sig == SIG_PRI) {
03097 x = 0;
03098 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03099 }
03100 #ifdef HAVE_PRI
03101 if (p->bearer) {
03102 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03103
03104
03105 update_conf(p->bearer);
03106 reset_conf(p->bearer);
03107 p->bearer->owner = NULL;
03108 p->bearer->realcall = NULL;
03109 p->bearer = NULL;
03110 p->subs[SUB_REAL].dfd = -1;
03111 p->pri = NULL;
03112 }
03113 #endif
03114 if (num_restart_pending == 0)
03115 restart_monitor();
03116 }
03117
03118 p->callwaitingrepeat = 0;
03119 p->cidcwexpire = 0;
03120 p->oprmode = 0;
03121 ast->tech_pvt = NULL;
03122 ast_mutex_unlock(&p->lock);
03123 ast_module_unref(ast_module_info->self);
03124 if (option_verbose > 2)
03125 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03126
03127 ast_mutex_lock(&iflock);
03128
03129 if (p->restartpending) {
03130 num_restart_pending--;
03131 }
03132
03133 tmp = iflist;
03134 prev = NULL;
03135 if (p->destroy) {
03136 while (tmp) {
03137 if (tmp == p) {
03138 destroy_channel(prev, tmp, 0);
03139 break;
03140 } else {
03141 prev = tmp;
03142 tmp = tmp->next;
03143 }
03144 }
03145 }
03146 ast_mutex_unlock(&iflock);
03147 return 0;
03148 }
03149
03150 static int dahdi_answer(struct ast_channel *ast)
03151 {
03152 struct dahdi_pvt *p = ast->tech_pvt;
03153 int res = 0;
03154 int index;
03155 int oldstate = ast->_state;
03156 ast_setstate(ast, AST_STATE_UP);
03157 ast_mutex_lock(&p->lock);
03158 index = dahdi_get_index(ast, p, 0);
03159 if (index < 0)
03160 index = SUB_REAL;
03161
03162 if ((p->radio || (p->oprmode < 0))) {
03163 ast_mutex_unlock(&p->lock);
03164 return 0;
03165 }
03166 switch (p->sig) {
03167 case SIG_FXSLS:
03168 case SIG_FXSGS:
03169 case SIG_FXSKS:
03170 p->ringt = 0;
03171
03172 case SIG_EM:
03173 case SIG_EM_E1:
03174 case SIG_EMWINK:
03175 case SIG_FEATD:
03176 case SIG_FEATDMF:
03177 case SIG_FEATDMF_TA:
03178 case SIG_E911:
03179 case SIG_FGC_CAMA:
03180 case SIG_FGC_CAMAMF:
03181 case SIG_FEATB:
03182 case SIG_SF:
03183 case SIG_SFWINK:
03184 case SIG_SF_FEATD:
03185 case SIG_SF_FEATDMF:
03186 case SIG_SF_FEATB:
03187 case SIG_FXOLS:
03188 case SIG_FXOGS:
03189 case SIG_FXOKS:
03190
03191 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03192 if (p->hanguponpolarityswitch) {
03193 gettimeofday(&p->polaritydelaytv, NULL);
03194 }
03195 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03196 tone_zone_play_tone(p->subs[index].dfd, -1);
03197 p->dialing = 0;
03198 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03199 if (oldstate == AST_STATE_RINGING) {
03200 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03201 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03202 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03203 p->owner = p->subs[SUB_REAL].owner;
03204 }
03205 }
03206 if (p->sig & __DAHDI_SIG_FXS) {
03207 dahdi_enable_ec(p);
03208 dahdi_train_ec(p);
03209 }
03210 break;
03211 #ifdef HAVE_PRI
03212 case SIG_PRI:
03213
03214 if (!pri_grab(p, p->pri)) {
03215 p->proceeding = 1;
03216 p->dialing = 0;
03217 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03218 pri_rel(p->pri);
03219 } else {
03220 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03221 res = -1;
03222 }
03223 break;
03224 #endif
03225 case 0:
03226 ast_mutex_unlock(&p->lock);
03227 return 0;
03228 default:
03229 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03230 res = -1;
03231 }
03232 ast_mutex_unlock(&p->lock);
03233 return res;
03234 }
03235
03236 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03237 {
03238 char *cp;
03239 signed char *scp;
03240 int x;
03241 int index;
03242 struct dahdi_pvt *p = chan->tech_pvt, *pp;
03243 struct oprmode *oprmode;
03244
03245
03246
03247 if (!data || (datalen < 1)) {
03248 errno = EINVAL;
03249 return -1;
03250 }
03251
03252 switch (option) {
03253 case AST_OPTION_TXGAIN:
03254 scp = (signed char *) data;
03255 index = dahdi_get_index(chan, p, 0);
03256 if (index < 0) {
03257 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03258 return -1;
03259 }
03260 if (option_debug)
03261 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03262 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
03263 case AST_OPTION_RXGAIN:
03264 scp = (signed char *) data;
03265 index = dahdi_get_index(chan, p, 0);
03266 if (index < 0) {
03267 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03268 return -1;
03269 }
03270 if (option_debug)
03271 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03272 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
03273 case AST_OPTION_TONE_VERIFY:
03274 if (!p->dsp)
03275 break;
03276 cp = (char *) data;
03277 switch (*cp) {
03278 case 1:
03279 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03280 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
03281 break;
03282 case 2:
03283 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03284 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
03285 break;
03286 default:
03287 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03288 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03289 break;
03290 }
03291 break;
03292 case AST_OPTION_TDD:
03293
03294 cp = (char *) data;
03295 p->mate = 0;
03296 if (!*cp) {
03297 if (option_debug)
03298 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03299 if (p->tdd)
03300 tdd_free(p->tdd);
03301 p->tdd = 0;
03302 break;
03303 }
03304 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
03305 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03306 dahdi_disable_ec(p);
03307
03308 if (!p->didtdd) {
03309 unsigned char mybuf[41000];
03310 unsigned char *buf;
03311 int size, res, fd, len;
03312 struct pollfd fds[1];
03313
03314 buf = mybuf;
03315 memset(buf, 0x7f, sizeof(mybuf));
03316 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03317 len = 40000;
03318 index = dahdi_get_index(chan, p, 0);
03319 if (index < 0) {
03320 ast_log(LOG_WARNING, "No index in TDD?\n");
03321 return -1;
03322 }
03323 fd = p->subs[index].dfd;
03324 while (len) {
03325 if (ast_check_hangup(chan))
03326 return -1;
03327 size = len;
03328 if (size > READ_SIZE)
03329 size = READ_SIZE;
03330 fds[0].fd = fd;
03331 fds[0].events = POLLPRI | POLLOUT;
03332 fds[0].revents = 0;
03333 res = poll(fds, 1, -1);
03334 if (!res) {
03335 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03336 continue;
03337 }
03338
03339 if (fds[0].revents & POLLPRI)
03340 return -1;
03341 if (!(fds[0].revents & POLLOUT)) {
03342 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03343 continue;
03344 }
03345 res = write(fd, buf, size);
03346 if (res != size) {
03347 if (res == -1) return -1;
03348 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03349 break;
03350 }
03351 len -= size;
03352 buf += size;
03353 }
03354 p->didtdd = 1;
03355 }
03356 if (*cp == 2) {
03357 if (p->tdd)
03358 tdd_free(p->tdd);
03359 p->tdd = 0;
03360 p->mate = 1;
03361 break;
03362 }
03363 if (!p->tdd) {
03364 p->tdd = tdd_new();
03365 }
03366 break;
03367 case AST_OPTION_RELAXDTMF:
03368 if (!p->dsp)
03369 break;
03370 cp = (char *) data;
03371 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03372 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03373 p->dtmfrelax = 0;
03374 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03375 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03376 break;
03377 case AST_OPTION_AUDIO_MODE:
03378 cp = (char *) data;
03379 if (!*cp) {
03380 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03381 x = 0;
03382 dahdi_disable_ec(p);
03383 } else {
03384 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03385 x = 1;
03386 }
03387 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03388 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03389 break;
03390 case AST_OPTION_OPRMODE:
03391 oprmode = (struct oprmode *) data;
03392 pp = oprmode->peer->tech_pvt;
03393 p->oprmode = pp->oprmode = 0;
03394
03395 p->oprpeer = pp;
03396 pp->oprpeer = p;
03397
03398 if (oprmode->mode)
03399 {
03400 pp->oprmode = oprmode->mode;
03401 p->oprmode = -oprmode->mode;
03402 }
03403 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03404 oprmode->mode, chan->name,oprmode->peer->name);;
03405 break;
03406 case AST_OPTION_ECHOCAN:
03407 cp = (char *) data;
03408 if (*cp) {
03409 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03410 dahdi_enable_ec(p);
03411 } else {
03412 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03413 dahdi_disable_ec(p);
03414 }
03415 break;
03416 }
03417 errno = 0;
03418
03419 return 0;
03420 }
03421
03422 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
03423 {
03424 struct dahdi_pvt *p = chan->tech_pvt;
03425
03426 if (!strcasecmp(data, "rxgain")) {
03427 ast_mutex_lock(&p->lock);
03428 snprintf(buf, len, "%f", p->rxgain);
03429 ast_mutex_unlock(&p->lock);
03430 } else if (!strcasecmp(data, "txgain")) {
03431 ast_mutex_lock(&p->lock);
03432 snprintf(buf, len, "%f", p->txgain);
03433 ast_mutex_unlock(&p->lock);
03434 } else {
03435 ast_copy_string(buf, "", len);
03436 }
03437 return 0;
03438 }
03439
03440
03441 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
03442 {
03443
03444 int x;
03445 int hasslaves;
03446 if (!master)
03447 return;
03448 if (needlock) {
03449 ast_mutex_lock(&master->lock);
03450 if (slave) {
03451 while (ast_mutex_trylock(&slave->lock)) {
03452 DEADLOCK_AVOIDANCE(&master->lock);
03453 }
03454 }
03455 }
03456 hasslaves = 0;
03457 for (x = 0; x < MAX_SLAVES; x++) {
03458 if (master->slaves[x]) {
03459 if (!slave || (master->slaves[x] == slave)) {
03460
03461 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03462 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03463 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03464 master->slaves[x]->master = NULL;
03465 master->slaves[x] = NULL;
03466 } else
03467 hasslaves = 1;
03468 }
03469 if (!hasslaves)
03470 master->inconference = 0;
03471 }
03472 if (!slave) {
03473 if (master->master) {
03474
03475 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03476 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03477 hasslaves = 0;
03478 for (x = 0; x < MAX_SLAVES; x++) {
03479 if (master->master->slaves[x] == master)
03480 master->master->slaves[x] = NULL;
03481 else if (master->master->slaves[x])
03482 hasslaves = 1;
03483 }
03484 if (!hasslaves)
03485 master->master->inconference = 0;
03486 }
03487 master->master = NULL;
03488 }
03489 update_conf(master);
03490 if (needlock) {
03491 if (slave)
03492 ast_mutex_unlock(&slave->lock);
03493 ast_mutex_unlock(&master->lock);
03494 }
03495 }
03496
03497 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
03498 int x;
03499 if (!slave || !master) {
03500 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03501 return;
03502 }
03503 for (x = 0; x < MAX_SLAVES; x++) {
03504 if (!master->slaves[x]) {
03505 master->slaves[x] = slave;
03506 break;
03507 }
03508 }
03509 if (x >= MAX_SLAVES) {
03510 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03511 master->slaves[MAX_SLAVES - 1] = slave;
03512 }
03513 if (slave->master)
03514 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03515 slave->master = master;
03516
03517 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03518 }
03519
03520 static void disable_dtmf_detect(struct dahdi_pvt *p)
03521 {
03522 #ifdef DAHDI_TONEDETECT
03523 int val;
03524 #endif
03525
03526 p->ignoredtmf = 1;
03527
03528 #ifdef DAHDI_TONEDETECT
03529 val = 0;
03530 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03531 #endif
03532 if (!p->hardwaredtmf && p->dsp) {
03533 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03534 ast_dsp_set_features(p->dsp, p->dsp_features);
03535 }
03536 }
03537
03538 static void enable_dtmf_detect(struct dahdi_pvt *p)
03539 {
03540 #ifdef DAHDI_TONEDETECT
03541 int val;
03542 #endif
03543
03544 if (p->channel == CHAN_PSEUDO)
03545 return;
03546
03547 p->ignoredtmf = 0;
03548
03549 #ifdef DAHDI_TONEDETECT
03550 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
03551 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03552 #endif
03553 if (!p->hardwaredtmf && p->dsp) {
03554 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03555 ast_dsp_set_features(p->dsp, p->dsp_features);
03556 }
03557 }
03558
03559 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)
03560 {
03561 struct ast_channel *who;
03562 struct dahdi_pvt *p0, *p1, *op0, *op1;
03563 struct dahdi_pvt *master = NULL, *slave = NULL;
03564 struct ast_frame *f;
03565 int inconf = 0;
03566 int nothingok = 1;
03567 int ofd0, ofd1;
03568 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03569 int os0 = -1, os1 = -1;
03570 int priority = 0;
03571 struct ast_channel *oc0, *oc1;
03572 enum ast_bridge_result res;
03573
03574 #ifdef PRI_2BCT
03575 int triedtopribridge = 0;
03576 q931_call *q931c0 = NULL, *q931c1 = NULL;
03577 #endif
03578
03579
03580
03581
03582
03583
03584 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03585 return AST_BRIDGE_FAILED_NOWARN;
03586
03587 ast_mutex_lock(&c0->lock);
03588 while (ast_mutex_trylock(&c1->lock)) {
03589 DEADLOCK_AVOIDANCE(&c0->lock);
03590 }
03591
03592 p0 = c0->tech_pvt;
03593 p1 = c1->tech_pvt;
03594
03595 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03596 ast_mutex_unlock(&c0->lock);
03597 ast_mutex_unlock(&c1->lock);
03598 return AST_BRIDGE_FAILED_NOWARN;
03599 }
03600
03601 oi0 = dahdi_get_index(c0, p0, 0);
03602 oi1 = dahdi_get_index(c1, p1, 0);
03603 if ((oi0 < 0) || (oi1 < 0)) {
03604 ast_mutex_unlock(&c0->lock);
03605 ast_mutex_unlock(&c1->lock);
03606 return AST_BRIDGE_FAILED;
03607 }
03608
03609 op0 = p0 = c0->tech_pvt;
03610 op1 = p1 = c1->tech_pvt;
03611 ofd0 = c0->fds[0];
03612 ofd1 = c1->fds[0];
03613 oc0 = p0->owner;
03614 oc1 = p1->owner;
03615
03616 if (ast_mutex_trylock(&p0->lock)) {
03617
03618 ast_mutex_unlock(&c0->lock);
03619 ast_mutex_unlock(&c1->lock);
03620 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03621 return AST_BRIDGE_RETRY;
03622 }
03623 if (ast_mutex_trylock(&p1->lock)) {
03624
03625 ast_mutex_unlock(&p0->lock);
03626 ast_mutex_unlock(&c0->lock);
03627 ast_mutex_unlock(&c1->lock);
03628 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03629 return AST_BRIDGE_RETRY;
03630 }
03631
03632 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03633 if (p0->owner && p1->owner) {
03634
03635 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03636 master = p0;
03637 slave = p1;
03638 inconf = 1;
03639 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03640 master = p1;
03641 slave = p0;
03642 inconf = 1;
03643 } else {
03644 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
03645 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03646 p0->channel,
03647 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03648 p0->subs[SUB_REAL].inthreeway, p0->channel,
03649 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03650 p1->subs[SUB_REAL].inthreeway);
03651 }
03652 nothingok = 0;
03653 }
03654 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03655 if (p1->subs[SUB_THREEWAY].inthreeway) {
03656 master = p1;
03657 slave = p0;
03658 nothingok = 0;
03659 }
03660 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03661 if (p0->subs[SUB_THREEWAY].inthreeway) {
03662 master = p0;
03663 slave = p1;
03664 nothingok = 0;
03665 }
03666 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03667
03668
03669 if (p1->subs[SUB_CALLWAIT].inthreeway) {
03670 master = p1;
03671 slave = p0;
03672 nothingok = 0;
03673 }
03674 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03675
03676 if (p0->subs[SUB_CALLWAIT].inthreeway) {
03677 master = p0;
03678 slave = p1;
03679 nothingok = 0;
03680 }
03681 }
03682 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03683 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03684 if (master && slave) {
03685
03686
03687
03688 if ((oi1 == SUB_THREEWAY) &&
03689 p1->subs[SUB_THREEWAY].inthreeway &&
03690 p1->subs[SUB_REAL].owner &&
03691 p1->subs[SUB_REAL].inthreeway &&
03692 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03693 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03694 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
03695 os1 = p1->subs[SUB_REAL].owner->_state;
03696 } else {
03697 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03698 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
03699 }
03700 if ((oi0 == SUB_THREEWAY) &&
03701 p0->subs[SUB_THREEWAY].inthreeway &&
03702 p0->subs[SUB_REAL].owner &&
03703 p0->subs[SUB_REAL].inthreeway &&
03704 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03705 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03706 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
03707 os0 = p0->subs[SUB_REAL].owner->_state;
03708 } else {
03709 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03710 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
03711 }
03712 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03713 if (!p0->echocanbridged || !p1->echocanbridged) {
03714
03715 dahdi_disable_ec(p0);
03716 dahdi_disable_ec(p1);
03717 }
03718 }
03719 dahdi_link(slave, master);
03720 master->inconference = inconf;
03721 } else if (!nothingok)
03722 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03723
03724 update_conf(p0);
03725 update_conf(p1);
03726 t0 = p0->subs[SUB_REAL].inthreeway;
03727 t1 = p1->subs[SUB_REAL].inthreeway;
03728
03729 ast_mutex_unlock(&p0->lock);
03730 ast_mutex_unlock(&p1->lock);
03731
03732 ast_mutex_unlock(&c0->lock);
03733 ast_mutex_unlock(&c1->lock);
03734
03735
03736 if ((!master || !slave) && !nothingok) {
03737 dahdi_enable_ec(p0);
03738 dahdi_enable_ec(p1);
03739 return AST_BRIDGE_FAILED;
03740 }
03741
03742 if (option_verbose > 2)
03743 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03744
03745 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03746 disable_dtmf_detect(op0);
03747
03748 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03749 disable_dtmf_detect(op1);
03750
03751 for (;;) {
03752 struct ast_channel *c0_priority[2] = {c0, c1};
03753 struct ast_channel *c1_priority[2] = {c1, c0};
03754
03755
03756
03757 ast_mutex_lock(&c0->lock);
03758 while (ast_mutex_trylock(&c1->lock)) {
03759 DEADLOCK_AVOIDANCE(&c0->lock);
03760 }
03761
03762 p0 = c0->tech_pvt;
03763 p1 = c1->tech_pvt;
03764
03765 if (op0 == p0)
03766 i0 = dahdi_get_index(c0, p0, 1);
03767 if (op1 == p1)
03768 i1 = dahdi_get_index(c1, p1, 1);
03769 ast_mutex_unlock(&c0->lock);
03770 ast_mutex_unlock(&c1->lock);
03771
03772 if (!timeoutms ||
03773 (op0 != p0) ||
03774 (op1 != p1) ||
03775 (ofd0 != c0->fds[0]) ||
03776 (ofd1 != c1->fds[0]) ||
03777 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
03778 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
03779 (oc0 != p0->owner) ||
03780 (oc1 != p1->owner) ||
03781 (t0 != p0->subs[SUB_REAL].inthreeway) ||
03782 (t1 != p1->subs[SUB_REAL].inthreeway) ||
03783 (oi0 != i0) ||
03784 (oi1 != i1)) {
03785 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03786 op0->channel, oi0, op1->channel, oi1);
03787 res = AST_BRIDGE_RETRY;
03788 goto return_from_bridge;
03789 }
03790
03791 #ifdef PRI_2BCT
03792 q931c0 = p0->call;
03793 q931c1 = p1->call;
03794 if (p0->transfer && p1->transfer
03795 && q931c0 && q931c1
03796 && !triedtopribridge) {
03797 pri_channel_bridge(q931c0, q931c1);
03798 triedtopribridge = 1;
03799 }
03800 #endif
03801
03802 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03803 if (!who) {
03804 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03805 continue;
03806 }
03807 f = ast_read(who);
03808 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03809 *fo = f;
03810 *rc = who;
03811 res = AST_BRIDGE_COMPLETE;
03812 goto return_from_bridge;
03813 }
03814 if (f->frametype == AST_FRAME_DTMF) {
03815 if ((who == c0) && p0->pulsedial) {
03816 ast_write(c1, f);
03817 } else if ((who == c1) && p1->pulsedial) {
03818 ast_write(c0, f);
03819 } else {
03820 *fo = f;
03821 *rc = who;
03822 res = AST_BRIDGE_COMPLETE;
03823 goto return_from_bridge;
03824 }
03825 }
03826 ast_frfree(f);
03827
03828
03829 priority = !priority;
03830 }
03831
03832 return_from_bridge:
03833 if (op0 == p0)
03834 dahdi_enable_ec(p0);
03835
03836 if (op1 == p1)
03837 dahdi_enable_ec(p1);
03838
03839 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03840 enable_dtmf_detect(op0);
03841
03842 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03843 enable_dtmf_detect(op1);
03844
03845 dahdi_unlink(slave, master, 1);
03846
03847 return res;
03848 }
03849
03850 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
03851 {
03852 struct dahdi_pvt *p = newchan->tech_pvt;
03853 int x;
03854 ast_mutex_lock(&p->lock);
03855 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03856 if (p->owner == oldchan) {
03857 p->owner = newchan;
03858 }
03859 for (x = 0; x < 3; x++)
03860 if (p->subs[x].owner == oldchan) {
03861 if (!x)
03862 dahdi_unlink(NULL, p, 0);
03863 p->subs[x].owner = newchan;
03864 }
03865 if (newchan->_state == AST_STATE_RINGING)
03866 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03867 update_conf(p);
03868 ast_mutex_unlock(&p->lock);
03869 return 0;
03870 }
03871
03872 static int dahdi_ring_phone(struct dahdi_pvt *p)
03873 {
03874 int x;
03875 int res;
03876
03877 x = 0;
03878 x = DAHDI_ONHOOK;
03879 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03880 do {
03881 x = DAHDI_RING;
03882 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03883 if (res) {
03884 switch (errno) {
03885 case EBUSY:
03886 case EINTR:
03887
03888 usleep(10000);
03889 continue;
03890 case EINPROGRESS:
03891 res = 0;
03892 break;
03893 default:
03894 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03895 res = 0;
03896 }
03897 }
03898 } while (res);
03899 return res;
03900 }
03901
03902 static void *ss_thread(void *data);
03903
03904 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
03905
03906 static int attempt_transfer(struct dahdi_pvt *p)
03907 {
03908
03909
03910
03911 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03912
03913
03914 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03915 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03916 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03917 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03918 }
03919 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03920 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
03921 }
03922 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03923 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03924 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03925 return -1;
03926 }
03927
03928 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03929 unalloc_sub(p, SUB_THREEWAY);
03930 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03931 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03932 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03933 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03934 }
03935 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03936 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03937 }
03938 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03939 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03940 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03941 return -1;
03942 }
03943
03944 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03945 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03946 unalloc_sub(p, SUB_THREEWAY);
03947
03948 return 1;
03949 } else {
03950 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03951 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03952 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03953 return -1;
03954 }
03955 return 0;
03956 }
03957
03958 static int check_for_conference(struct dahdi_pvt *p)
03959 {
03960 struct dahdi_confinfo ci;
03961
03962 if (p->master || (p->confno > -1))
03963 return 0;
03964 memset(&ci, 0, sizeof(ci));
03965 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
03966 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
03967 return 0;
03968 }
03969
03970
03971
03972 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03973 if (option_verbose > 2)
03974 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03975 return 1;
03976 }
03977 return 0;
03978 }
03979
03980 static int get_alarms(struct dahdi_pvt *p)
03981 {
03982 int res;
03983 struct dahdi_spaninfo zi;
03984 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
03985
03986
03987
03988
03989
03990 struct dahdi_params params;
03991 #endif
03992
03993 memset(&zi, 0, sizeof(zi));
03994 zi.spanno = p->span;
03995
03996
03997 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
03998 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
03999 return 0;
04000 }
04001 if (zi.alarms != DAHDI_ALARM_NONE)
04002 return zi.alarms;
04003 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04004
04005 memset(¶ms, 0, sizeof(params));
04006 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04007 return params.chan_alarms;
04008
04009 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04010 #endif
04011 return DAHDI_ALARM_NONE;
04012 }
04013
04014 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04015 {
04016 struct dahdi_pvt *p = ast->tech_pvt;
04017 struct ast_frame *f = *dest;
04018
04019 if (option_debug)
04020 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04021
04022 if (p->confirmanswer) {
04023 if (option_debug)
04024 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04025
04026
04027 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04028 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04029 *dest = &p->subs[index].f;
04030
04031 p->confirmanswer = 0;
04032 } else if (p->callwaitcas) {
04033 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04034 if (option_debug)
04035 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04036 if (p->cidspill)
04037 free(p->cidspill);
04038 send_cwcidspill(p);
04039 }
04040 if ((f->subclass != 'm') && (f->subclass != 'u'))
04041 p->callwaitcas = 0;
04042 p->subs[index].f.frametype = AST_FRAME_NULL;
04043 p->subs[index].f.subclass = 0;
04044 *dest = &p->subs[index].f;
04045 } else if (f->subclass == 'f') {
04046
04047 if ((p->callprogress & 0x6) && !p->faxhandled) {
04048 p->faxhandled = 1;
04049 if (strcmp(ast->exten, "fax")) {
04050 const char *target_context = S_OR(ast->macrocontext, ast->context);
04051
04052
04053
04054
04055
04056 ast_mutex_unlock(&p->lock);
04057 ast_channel_unlock(ast);
04058 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04059 ast_channel_lock(ast);
04060 ast_mutex_lock(&p->lock);
04061 if (option_verbose > 2)
04062 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04063
04064 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04065 if (ast_async_goto(ast, target_context, "fax", 1))
04066 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04067 } else {
04068 ast_channel_lock(ast);
04069 ast_mutex_lock(&p->lock);
04070 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04071 }
04072 } else if (option_debug)
04073 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04074 } else if (option_debug)
04075 ast_log(LOG_DEBUG, "Fax already handled\n");
04076 dahdi_confmute(p, 0);
04077 p->subs[index].f.frametype = AST_FRAME_NULL;
04078 p->subs[index].f.subclass = 0;
04079 *dest = &p->subs[index].f;
04080 } else if (f->subclass == 'm') {
04081
04082 dahdi_confmute(p, 1);
04083 p->subs[index].f.frametype = AST_FRAME_NULL;
04084 p->subs[index].f.subclass = 0;
04085 *dest = &p->subs[index].f;
04086 } else if (f->subclass == 'u') {
04087
04088 dahdi_confmute(p, 0);
04089 p->subs[index].f.frametype = AST_FRAME_NULL;
04090 p->subs[index].f.subclass = 0;
04091 *dest = &p->subs[index].f;
04092 } else
04093 dahdi_confmute(p, 0);
04094 }
04095
04096 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04097 {
04098 const char *alarm_str = alarm2str(alarms);
04099
04100
04101
04102 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04103 p->unknown_alarm = 1;
04104 return;
04105 } else {
04106 p->unknown_alarm = 0;
04107 }
04108
04109 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04110 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04111 "Alarm: %s\r\n"
04112 "Channel: %d\r\n",
04113 alarm_str, p->channel);
04114 }
04115
04116 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04117 {
04118 int res, x;
04119 int index, mysig;
04120 char *c;
04121 struct dahdi_pvt *p = ast->tech_pvt;
04122 pthread_t threadid;
04123 pthread_attr_t attr;
04124 struct ast_channel *chan;
04125 struct ast_frame *f;
04126
04127 index = dahdi_get_index(ast, p, 0);
04128 mysig = p->sig;
04129 if (p->outsigmod > -1)
04130 mysig = p->outsigmod;
04131 p->subs[index].f.frametype = AST_FRAME_NULL;
04132 p->subs[index].f.subclass = 0;
04133 p->subs[index].f.datalen = 0;
04134 p->subs[index].f.samples = 0;
04135 p->subs[index].f.mallocd = 0;
04136 p->subs[index].f.offset = 0;
04137 p->subs[index].f.src = "dahdi_handle_event";
04138 p->subs[index].f.data = NULL;
04139 f = &p->subs[index].f;
04140
04141 if (index < 0)
04142 return &p->subs[index].f;
04143 if (p->fake_event) {
04144 res = p->fake_event;
04145 p->fake_event = 0;
04146 } else
04147 res = dahdi_get_event(p->subs[index].dfd);
04148
04149 if (option_debug)
04150 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04151
04152 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04153 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04154
04155 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04156 #ifdef HAVE_PRI
04157 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
04158
04159 } else {
04160 #endif
04161 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04162 p->subs[index].f.subclass = res & 0xff;
04163 #ifdef HAVE_PRI
04164 }
04165 #endif
04166 dahdi_handle_dtmfup(ast, index, &f);
04167 return f;
04168 }
04169
04170 if (res & DAHDI_EVENT_DTMFDOWN) {
04171 if (option_debug)
04172 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04173
04174 dahdi_confmute(p, 1);
04175 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04176 p->subs[index].f.subclass = res & 0xff;
04177 return &p->subs[index].f;
04178 }
04179
04180 switch (res) {
04181 #ifdef DAHDI_EVENT_EC_DISABLED
04182 case DAHDI_EVENT_EC_DISABLED:
04183 if (option_verbose > 2)
04184 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04185 p->echocanon = 0;
04186 break;
04187 #endif
04188 case DAHDI_EVENT_BITSCHANGED:
04189 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04190 case DAHDI_EVENT_PULSE_START:
04191
04192 if (!ast->pbx)
04193 tone_zone_play_tone(p->subs[index].dfd, -1);
04194 break;
04195 case DAHDI_EVENT_DIALCOMPLETE:
04196 if (p->inalarm) break;
04197 if ((p->radio || (p->oprmode < 0))) break;
04198 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
04199 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04200 return NULL;
04201 }
04202 if (!x) {
04203 dahdi_enable_ec(p);
04204 if (p->echobreak) {
04205 dahdi_train_ec(p);
04206 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04207 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04208 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04209 p->echobreak = 0;
04210 } else {
04211 p->dialing = 0;
04212 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04213
04214 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04215 ast_setstate(ast, AST_STATE_UP);
04216 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04217 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04218 break;
04219 } else {
04220
04221 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04222 }
04223 }
04224 if (ast->_state == AST_STATE_DIALING) {
04225 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04226 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
04227 } 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)))) {
04228 ast_setstate(ast, AST_STATE_RINGING);
04229 } else if (!p->answeronpolarityswitch) {
04230 ast_setstate(ast, AST_STATE_UP);
04231 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04232 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04233
04234 p->polarity = POLARITY_REV;
04235 } else {
04236
04237 p->polarity = POLARITY_IDLE;
04238 }
04239 }
04240 }
04241 }
04242 break;
04243 case DAHDI_EVENT_ALARM:
04244 #ifdef HAVE_PRI
04245 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04246
04247 if (p->call) {
04248 if (p->pri && p->pri->pri) {
04249 if (!pri_grab(p, p->pri)) {
04250 pri_hangup(p->pri->pri, p->call, -1);
04251 pri_destroycall(p->pri->pri, p->call);
04252 p->call = NULL;
04253 pri_rel(p->pri);
04254 } else
04255 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04256 } else
04257 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04258 }
04259 if (p->owner)
04260 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04261 }
04262 if (p->bearer)
04263 p->bearer->inalarm = 1;
04264 else
04265 #endif
04266 p->inalarm = 1;
04267 res = get_alarms(p);
04268 handle_alarms(p, res);
04269 #ifdef HAVE_LIBPRI
04270 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04271
04272 } else {
04273 break;
04274 }
04275 #endif
04276 case DAHDI_EVENT_ONHOOK:
04277 if (p->radio) {
04278 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04279 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04280 break;
04281 }
04282 if (p->oprmode < 0)
04283 {
04284 if (p->oprmode != -1) break;
04285 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04286 {
04287
04288 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04289 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04290 save_conference(p->oprpeer);
04291 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04292 }
04293 break;
04294 }
04295 switch (p->sig) {
04296 case SIG_FXOLS:
04297 case SIG_FXOGS:
04298 case SIG_FXOKS:
04299 p->onhooktime = time(NULL);
04300 p->msgstate = -1;
04301
04302 if (index == SUB_REAL) {
04303
04304 if (p->subs[SUB_CALLWAIT].owner) {
04305
04306 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04307 if (option_verbose > 2)
04308 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04309 unalloc_sub(p, SUB_CALLWAIT);
04310 #if 0
04311 p->subs[index].needanswer = 0;
04312 p->subs[index].needringing = 0;
04313 #endif
04314 p->callwaitingrepeat = 0;
04315 p->cidcwexpire = 0;
04316 p->owner = NULL;
04317
04318 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04319 p->dialing = 1;
04320 dahdi_ring_phone(p);
04321 } else if (p->subs[SUB_THREEWAY].owner) {
04322 unsigned int mssinceflash;
04323
04324
04325 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04326
04327 ast_mutex_unlock(&p->lock);
04328 DEADLOCK_AVOIDANCE(&ast->lock);
04329
04330
04331
04332 ast_mutex_lock(&p->lock);
04333 if (p->owner != ast) {
04334 ast_log(LOG_WARNING, "This isn't good...\n");
04335 return NULL;
04336 }
04337 }
04338 if (!p->subs[SUB_THREEWAY].owner) {
04339 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04340 return NULL;
04341 }
04342 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04343 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04344 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04345
04346
04347 if (p->subs[SUB_THREEWAY].owner)
04348 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04349 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04350 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04351 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04352 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04353 if (p->transfer) {
04354
04355 p->subs[SUB_REAL].inthreeway = 0;
04356 p->subs[SUB_THREEWAY].inthreeway = 0;
04357
04358 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04359 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04360
04361 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04362 p->owner = NULL;
04363
04364 dahdi_ring_phone(p);
04365 } else {
04366 if ((res = attempt_transfer(p)) < 0) {
04367 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04368 if (p->subs[SUB_THREEWAY].owner)
04369 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04370 } else if (res) {
04371
04372 if (p->subs[SUB_THREEWAY].owner)
04373 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04374 break;
04375 }
04376 }
04377 } else {
04378 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04379 if (p->subs[SUB_THREEWAY].owner)
04380 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04381 }
04382 } else {
04383 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04384
04385 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04386 p->owner = NULL;
04387
04388 dahdi_ring_phone(p);
04389 }
04390 }
04391 } else {
04392 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04393 }
04394
04395 default:
04396 dahdi_disable_ec(p);
04397 return NULL;
04398 }
04399 break;
04400 case DAHDI_EVENT_RINGOFFHOOK:
04401 if (p->inalarm) break;
04402 if (p->oprmode < 0)
04403 {
04404 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04405 {
04406
04407 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04408 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04409 restore_conference(p->oprpeer);
04410 }
04411 break;
04412 }
04413 if (p->radio)
04414 {
04415 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04416 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04417 break;
04418 }
04419
04420
04421 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04422 c = strchr(p->dialdest, '/');
04423 if (c)
04424 c++;
04425 else
04426 c = p->dialdest;
04427 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04428 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04429 if (strlen(p->dop.dialstr) > 4) {
04430 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04431 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04432 p->echorest[sizeof(p->echorest) - 1] = '\0';
04433 p->echobreak = 1;
04434 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04435 } else
04436 p->echobreak = 0;
04437 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04438 int saveerr = errno;
04439
04440 x = DAHDI_ONHOOK;
04441 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04442 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04443 return NULL;
04444 }
04445 p->dialing = 1;
04446 return &p->subs[index].f;
04447 }
04448 switch (p->sig) {
04449 case SIG_FXOLS:
04450 case SIG_FXOGS:
04451 case SIG_FXOKS:
04452 switch (ast->_state) {
04453 case AST_STATE_RINGING:
04454 dahdi_enable_ec(p);
04455 dahdi_train_ec(p);
04456 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04457 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04458
04459 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04460 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04461 if (p->cidspill) {
04462
04463 free(p->cidspill);
04464 p->cidspill = NULL;
04465 }
04466 p->dialing = 0;
04467 p->callwaitcas = 0;
04468 if (p->confirmanswer) {
04469
04470 p->subs[index].f.frametype = AST_FRAME_NULL;
04471 p->subs[index].f.subclass = 0;
04472 } else if (!ast_strlen_zero(p->dop.dialstr)) {
04473
04474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04475 if (res < 0) {
04476 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04477 p->dop.dialstr[0] = '\0';
04478 return NULL;
04479 } else {
04480 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04481 p->subs[index].f.frametype = AST_FRAME_NULL;
04482 p->subs[index].f.subclass = 0;
04483 p->dialing = 1;
04484 }
04485 p->dop.dialstr[0] = '\0';
04486 ast_setstate(ast, AST_STATE_DIALING);
04487 } else
04488 ast_setstate(ast, AST_STATE_UP);
04489 return &p->subs[index].f;
04490 case AST_STATE_DOWN:
04491 ast_setstate(ast, AST_STATE_RING);
04492 ast->rings = 1;
04493 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04494 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04495 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04496 return &p->subs[index].f;
04497 case AST_STATE_UP:
04498
04499 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04500
04501 if (ast_bridged_channel(p->owner))
04502 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04503 p->subs[index].needunhold = 1;
04504 break;
04505 case AST_STATE_RESERVED:
04506
04507 if (has_voicemail(p))
04508 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04509 else
04510 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04511 break;
04512 default:
04513 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04514 }
04515 break;
04516 case SIG_FXSLS:
04517 case SIG_FXSGS:
04518 case SIG_FXSKS:
04519 if (ast->_state == AST_STATE_RING) {
04520 p->ringt = p->ringt_base;
04521 }
04522
04523
04524 case SIG_EM:
04525 case SIG_EM_E1:
04526 case SIG_EMWINK:
04527 case SIG_FEATD:
04528 case SIG_FEATDMF:
04529 case SIG_FEATDMF_TA:
04530 case SIG_E911:
04531 case SIG_FGC_CAMA:
04532 case SIG_FGC_CAMAMF:
04533 case SIG_FEATB:
04534 case SIG_SF:
04535 case SIG_SFWINK:
04536 case SIG_SF_FEATD:
04537 case SIG_SF_FEATDMF:
04538 case SIG_SF_FEATB:
04539 if (ast->_state == AST_STATE_PRERING)
04540 ast_setstate(ast, AST_STATE_RING);
04541 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04542 if (option_debug)
04543 ast_log(LOG_DEBUG, "Ring detected\n");
04544 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04545 p->subs[index].f.subclass = AST_CONTROL_RING;
04546 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04547 if (option_debug)
04548 ast_log(LOG_DEBUG, "Line answered\n");
04549 if (p->confirmanswer) {
04550 p->subs[index].f.frametype = AST_FRAME_NULL;
04551 p->subs[index].f.subclass = 0;
04552 } else {
04553 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04554 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04555 ast_setstate(ast, AST_STATE_UP);
04556 }
04557 } else if (ast->_state != AST_STATE_RING)
04558 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04559 break;
04560 default:
04561 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04562 }
04563 break;
04564 #ifdef DAHDI_EVENT_RINGBEGIN
04565 case DAHDI_EVENT_RINGBEGIN:
04566 switch (p->sig) {
04567 case SIG_FXSLS:
04568 case SIG_FXSGS:
04569 case SIG_FXSKS:
04570 if (ast->_state == AST_STATE_RING) {
04571 p->ringt = p->ringt_base;
04572 }
04573 break;
04574 }
04575 break;
04576 #endif
04577 case DAHDI_EVENT_RINGEROFF:
04578 if (p->inalarm) break;
04579 if ((p->radio || (p->oprmode < 0))) break;
04580 ast->rings++;
04581 if ((ast->rings > p->cidrings) && (p->cidspill)) {
04582 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
04583 free(p->cidspill);
04584 p->cidspill = NULL;
04585 p->callwaitcas = 0;
04586 }
04587 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04588 p->subs[index].f.subclass = AST_CONTROL_RINGING;
04589 break;
04590 case DAHDI_EVENT_RINGERON:
04591 break;
04592 case DAHDI_EVENT_NOALARM:
04593 p->inalarm = 0;
04594 #ifdef HAVE_PRI
04595
04596 if (p->bearer)
04597 p->bearer->inalarm = 0;
04598 #endif
04599 if (!p->unknown_alarm) {
04600 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04601 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04602 "Channel: %d\r\n", p->channel);
04603 } else {
04604 p->unknown_alarm = 0;
04605 }
04606 break;
04607 case DAHDI_EVENT_WINKFLASH:
04608 if (p->inalarm) break;
04609 if (p->radio) break;
04610 if (p->oprmode < 0) break;
04611 if (p->oprmode > 1)
04612 {
04613 struct dahdi_params par;
04614
04615 memset(&par, 0, sizeof(par));
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 memset(&ps, 0, sizeof(ps));
05116 ps.channo = p->channel;
05117 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05118 ast_mutex_unlock(&p->lock);
05119 return NULL;
05120 }
05121 p->firstradio = 1;
05122 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05123 if (ps.rxisoffhook)
05124 {
05125 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05126 }
05127 else
05128 {
05129 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05130 }
05131 ast_mutex_unlock(&p->lock);
05132 return &p->subs[index].f;
05133 }
05134 if (p->ringt == 1) {
05135 ast_mutex_unlock(&p->lock);
05136 return NULL;
05137 }
05138 else if (p->ringt > 0)
05139 p->ringt--;
05140
05141 if (p->subs[index].needringing) {
05142
05143 p->subs[index].needringing = 0;
05144 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05145 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05146 ast_setstate(ast, AST_STATE_RINGING);
05147 ast_mutex_unlock(&p->lock);
05148 return &p->subs[index].f;
05149 }
05150
05151 if (p->subs[index].needbusy) {
05152
05153 p->subs[index].needbusy = 0;
05154 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05155 p->subs[index].f.subclass = AST_CONTROL_BUSY;
05156 ast_mutex_unlock(&p->lock);
05157 return &p->subs[index].f;
05158 }
05159
05160 if (p->subs[index].needcongestion) {
05161
05162 p->subs[index].needcongestion = 0;
05163 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05164 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
05165 ast_mutex_unlock(&p->lock);
05166 return &p->subs[index].f;
05167 }
05168
05169 if (p->subs[index].needcallerid) {
05170 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05171 S_OR(p->lastcid_name, NULL),
05172 S_OR(p->lastcid_num, NULL)
05173 );
05174 p->subs[index].needcallerid = 0;
05175 }
05176
05177 if (p->subs[index].needanswer) {
05178
05179 p->subs[index].needanswer = 0;
05180 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05181 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05182 ast_mutex_unlock(&p->lock);
05183 return &p->subs[index].f;
05184 }
05185
05186 if (p->subs[index].needflash) {
05187
05188 p->subs[index].needflash = 0;
05189 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05190 p->subs[index].f.subclass = AST_CONTROL_FLASH;
05191 ast_mutex_unlock(&p->lock);
05192 return &p->subs[index].f;
05193 }
05194
05195 if (p->subs[index].needhold) {
05196
05197 p->subs[index].needhold = 0;
05198 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05199 p->subs[index].f.subclass = AST_CONTROL_HOLD;
05200 ast_mutex_unlock(&p->lock);
05201 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
05202 return &p->subs[index].f;
05203 }
05204
05205 if (p->subs[index].needunhold) {
05206
05207 p->subs[index].needunhold = 0;
05208 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05209 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
05210 ast_mutex_unlock(&p->lock);
05211 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
05212 return &p->subs[index].f;
05213 }
05214
05215 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05216 if (!p->subs[index].linear) {
05217 p->subs[index].linear = 1;
05218 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05219 if (res)
05220 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
05221 }
05222 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05223 (ast->rawreadformat == AST_FORMAT_ALAW)) {
05224 if (p->subs[index].linear) {
05225 p->subs[index].linear = 0;
05226 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05227 if (res)
05228 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
05229 }
05230 } else {
05231 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05232 ast_mutex_unlock(&p->lock);
05233 return NULL;
05234 }
05235 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
05236 CHECK_BLOCKING(ast);
05237 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05238 ast_clear_flag(ast, AST_FLAG_BLOCKING);
05239
05240 if (res < 0) {
05241 f = NULL;
05242 if (res == -1) {
05243 if (errno == EAGAIN) {
05244
05245 ast_mutex_unlock(&p->lock);
05246 return &p->subs[index].f;
05247 } else if (errno == ELAST) {
05248 f = __dahdi_exception(ast);
05249 } else
05250 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05251 }
05252 ast_mutex_unlock(&p->lock);
05253 return f;
05254 }
05255 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
05256 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05257 f = __dahdi_exception(ast);
05258 ast_mutex_unlock(&p->lock);
05259 return f;
05260 }
05261 if (p->tdd) {
05262 int c;
05263
05264 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05265 if (c < 0) {
05266 ast_log(LOG_DEBUG,"tdd_feed failed\n");
05267 ast_mutex_unlock(&p->lock);
05268 return NULL;
05269 }
05270 if (c) {
05271 p->subs[index].f.subclass = 0;
05272 p->subs[index].f.frametype = AST_FRAME_TEXT;
05273 p->subs[index].f.mallocd = 0;
05274 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05275 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
05276 p->subs[index].f.datalen = 1;
05277 *((char *) p->subs[index].f.data) = c;
05278 ast_mutex_unlock(&p->lock);
05279 return &p->subs[index].f;
05280 }
05281 }
05282
05283 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05284 p->callwaitingrepeat--;
05285 }
05286 if (p->cidcwexpire)
05287 p->cidcwexpire--;
05288
05289 if (p->callwaitingrepeat == 1) {
05290 p->callwaitrings++;
05291 dahdi_callwait(ast);
05292 }
05293
05294 if (p->cidcwexpire == 1) {
05295 if (option_verbose > 2)
05296 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
05297 restore_conference(p);
05298 }
05299 if (p->subs[index].linear) {
05300 p->subs[index].f.datalen = READ_SIZE * 2;
05301 } else
05302 p->subs[index].f.datalen = READ_SIZE;
05303
05304
05305 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05306 send_callerid(p);
05307 }
05308
05309 p->subs[index].f.frametype = AST_FRAME_VOICE;
05310 p->subs[index].f.subclass = ast->rawreadformat;
05311 p->subs[index].f.samples = READ_SIZE;
05312 p->subs[index].f.mallocd = 0;
05313 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05314 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
05315 #if 0
05316 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
05317 #endif
05318 if (p->dialing ||
05319 (index && (ast->_state != AST_STATE_UP)) ||
05320 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05321 ) {
05322
05323
05324 p->subs[index].f.frametype = AST_FRAME_NULL;
05325 p->subs[index].f.subclass = 0;
05326 p->subs[index].f.samples = 0;
05327 p->subs[index].f.mallocd = 0;
05328 p->subs[index].f.offset = 0;
05329 p->subs[index].f.data = NULL;
05330 p->subs[index].f.datalen= 0;
05331 }
05332 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
05333
05334 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05335 if (f) {
05336 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05337 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05338
05339
05340 f = NULL;
05341 }
05342 } else if (f->frametype == AST_FRAME_DTMF) {
05343 #ifdef HAVE_PRI
05344 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
05345
05346 f->frametype = AST_FRAME_NULL;
05347 f->subclass = 0;
05348 }
05349 #endif
05350
05351 p->pulsedial = 0;
05352 }
05353 }
05354 } else
05355 f = &p->subs[index].f;
05356
05357 if (f && (f->frametype == AST_FRAME_DTMF))
05358 dahdi_handle_dtmfup(ast, index, &f);
05359
05360
05361 if (p->fake_event)
05362 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05363
05364 ast_mutex_unlock(&p->lock);
05365 return f;
05366 }
05367
05368 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
05369 {
05370 int sent=0;
05371 int size;
05372 int res;
05373 int fd;
05374 fd = p->subs[index].dfd;
05375 while (len) {
05376 size = len;
05377 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05378 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05379 res = write(fd, buf, size);
05380 if (res != size) {
05381 if (option_debug)
05382 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05383 return sent;
05384 }
05385 len -= size;
05386 buf += size;
05387 }
05388 return sent;
05389 }
05390
05391 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05392 {
05393 struct dahdi_pvt *p = ast->tech_pvt;
05394 int res;
05395 int index;
05396 index = dahdi_get_index(ast, p, 0);
05397 if (index < 0) {
05398 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05399 return -1;
05400 }
05401
05402 #if 0
05403 #ifdef HAVE_PRI
05404 ast_mutex_lock(&p->lock);
05405 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05406 if (p->pri->pri) {
05407 if (!pri_grab(p, p->pri)) {
05408 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05409 pri_rel(p->pri);
05410 } else
05411 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05412 }
05413 p->proceeding=1;
05414 }
05415 ast_mutex_unlock(&p->lock);
05416 #endif
05417 #endif
05418
05419 if (frame->frametype != AST_FRAME_VOICE) {
05420 if (frame->frametype != AST_FRAME_IMAGE)
05421 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05422 return 0;
05423 }
05424 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
05425 (frame->subclass != AST_FORMAT_ULAW) &&
05426 (frame->subclass != AST_FORMAT_ALAW)) {
05427 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05428 return -1;
05429 }
05430 if (p->dialing) {
05431 if (option_debug)
05432 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05433 return 0;
05434 }
05435 if (!p->owner) {
05436 if (option_debug)
05437 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05438 return 0;
05439 }
05440 if (p->cidspill) {
05441 if (option_debug)
05442 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05443 return 0;
05444 }
05445
05446 if (!frame->data || !frame->datalen)
05447 return 0;
05448
05449 if (frame->subclass == AST_FORMAT_SLINEAR) {
05450 if (!p->subs[index].linear) {
05451 p->subs[index].linear = 1;
05452 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05453 if (res)
05454 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05455 }
05456 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05457 } else {
05458
05459 if (p->subs[index].linear) {
05460 p->subs[index].linear = 0;
05461 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05462 if (res)
05463 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05464 }
05465 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05466 }
05467 if (res < 0) {
05468 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05469 return -1;
05470 }
05471 return 0;
05472 }
05473
05474 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
05475 {
05476 struct dahdi_pvt *p = chan->tech_pvt;
05477 int res=-1;
05478 int index;
05479 int func = DAHDI_FLASH;
05480 ast_mutex_lock(&p->lock);
05481 index = dahdi_get_index(chan, p, 0);
05482 if (option_debug)
05483 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05484 if (index == SUB_REAL) {
05485 switch (condition) {
05486 case AST_CONTROL_BUSY:
05487 #ifdef HAVE_PRI
05488 if (p->priindication_oob && p->sig == SIG_PRI) {
05489 chan->hangupcause = AST_CAUSE_USER_BUSY;
05490 chan->_softhangup |= AST_SOFTHANGUP_DEV;
05491 res = 0;
05492 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05493 if (p->pri->pri) {
05494 if (!pri_grab(p, p->pri)) {
05495 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05496 pri_rel(p->pri);
05497 }
05498 else
05499 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05500 }
05501 p->progress = 1;
05502 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05503 } else
05504 #endif
05505 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05506 break;
05507 case AST_CONTROL_RINGING:
05508 #ifdef HAVE_PRI
05509 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05510 if (p->pri->pri) {
05511 if (!pri_grab(p, p->pri)) {
05512 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05513 pri_rel(p->pri);
05514 }
05515 else
05516 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05517 }
05518 p->alerting = 1;
05519 }
05520 #endif
05521 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
05522 if (chan->_state != AST_STATE_UP) {
05523 if ((chan->_state != AST_STATE_RING) ||
05524 ((p->sig != SIG_FXSKS) &&
05525 (p->sig != SIG_FXSLS) &&
05526 (p->sig != SIG_FXSGS)))
05527 ast_setstate(chan, AST_STATE_RINGING);
05528 }
05529 break;
05530 case AST_CONTROL_PROCEEDING:
05531 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05532 #ifdef HAVE_PRI
05533 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05534 if (p->pri->pri) {
05535 if (!pri_grab(p, p->pri)) {
05536 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05537 pri_rel(p->pri);
05538 }
05539 else
05540 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05541 }
05542 p->proceeding = 1;
05543 p->dialing = 0;
05544 }
05545 #endif
05546
05547 res = 0;
05548 break;
05549 case AST_CONTROL_PROGRESS:
05550 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05551 #ifdef HAVE_PRI
05552 p->digital = 0;
05553 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05554 if (p->pri->pri) {
05555 if (!pri_grab(p, p->pri)) {
05556 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05557 pri_rel(p->pri);
05558 }
05559 else
05560 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05561 }
05562 p->progress = 1;
05563 }
05564 #endif
05565
05566 res = 0;
05567 break;
05568 case AST_CONTROL_CONGESTION:
05569 chan->hangupcause = AST_CAUSE_CONGESTION;
05570 #ifdef HAVE_PRI
05571 if (p->priindication_oob && p->sig == SIG_PRI) {
05572 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05573 chan->_softhangup |= AST_SOFTHANGUP_DEV;
05574 res = 0;
05575 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05576 if (p->pri) {
05577 if (!pri_grab(p, p->pri)) {
05578 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05579 pri_rel(p->pri);
05580 } else
05581 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05582 }
05583 p->progress = 1;
05584 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05585 } else
05586 #endif
05587 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05588 break;
05589 case AST_CONTROL_HOLD:
05590 #ifdef HAVE_PRI
05591 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05592 if (!pri_grab(p, p->pri)) {
05593 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05594 pri_rel(p->pri);
05595 } else
05596 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05597 } else
05598 #endif
05599 ast_moh_start(chan, data, p->mohinterpret);
05600 break;
05601 case AST_CONTROL_UNHOLD:
05602 #ifdef HAVE_PRI
05603 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05604 if (!pri_grab(p, p->pri)) {
05605 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05606 pri_rel(p->pri);
05607 } else
05608 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05609 } else
05610 #endif
05611 ast_moh_stop(chan);
05612 break;
05613 case AST_CONTROL_RADIO_KEY:
05614 if (p->radio)
05615 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05616 res = 0;
05617 break;
05618 case AST_CONTROL_RADIO_UNKEY:
05619 if (p->radio)
05620 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
05621 res = 0;
05622 break;
05623 case AST_CONTROL_FLASH:
05624
05625 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05626
05627 p->dop.dialstr[0] = '\0';
05628 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05629 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
05630 chan->name, strerror(errno));
05631 } else
05632 res = 0;
05633 } else
05634 res = 0;
05635 break;
05636 case AST_CONTROL_SRCUPDATE:
05637 res = 0;
05638 break;
05639 case -1:
05640 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05641 break;
05642 }
05643 } else
05644 res = 0;
05645 ast_mutex_unlock(&p->lock);
05646 return res;
05647 }
05648
05649 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
05650 {
05651 struct ast_channel *tmp;
05652 int deflaw;
05653 int res;
05654 int x,y;
05655 int features;
05656 char *b2 = NULL;
05657 struct dahdi_params ps;
05658 char chanprefix[*dahdi_chan_name_len + 4];
05659
05660 if (i->subs[index].owner) {
05661 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05662 return NULL;
05663 }
05664 y = 1;
05665 do {
05666 if (b2)
05667 free(b2);
05668 #ifdef HAVE_PRI
05669 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05670 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05671 else
05672 #endif
05673 if (i->channel == CHAN_PSEUDO)
05674 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05675 else
05676 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05677 for (x = 0; x < 3; x++) {
05678 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
05679 break;
05680 }
05681 y++;
05682 } while (x < 3);
05683 strcpy(chanprefix, dahdi_chan_name);
05684 strcat(chanprefix, "/%s");
05685 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
05686 if (b2)
05687 free(b2);
05688 if (!tmp)
05689 return NULL;
05690 tmp->tech = chan_tech;
05691 memset(&ps, 0, sizeof(ps));
05692 ps.channo = i->channel;
05693 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
05694 if (res) {
05695 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
05696 ps.curlaw = DAHDI_LAW_MULAW;
05697 }
05698 if (ps.curlaw == DAHDI_LAW_ALAW)
05699 deflaw = AST_FORMAT_ALAW;
05700 else
05701 deflaw = AST_FORMAT_ULAW;
05702 if (law) {
05703 if (law == DAHDI_LAW_ALAW)
05704 deflaw = AST_FORMAT_ALAW;
05705 else
05706 deflaw = AST_FORMAT_ULAW;
05707 }
05708 tmp->fds[0] = i->subs[index].dfd;
05709 tmp->nativeformats = deflaw;
05710
05711 tmp->rawreadformat = deflaw;
05712 tmp->readformat = deflaw;
05713 tmp->rawwriteformat = deflaw;
05714 tmp->writeformat = deflaw;
05715 i->subs[index].linear = 0;
05716 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
05717 features = 0;
05718 if (index == SUB_REAL) {
05719 if (i->busydetect && CANBUSYDETECT(i))
05720 features |= DSP_FEATURE_BUSY_DETECT;
05721 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05722 features |= DSP_FEATURE_CALL_PROGRESS;
05723 if ((!i->outgoing && (i->callprogress & 4)) ||
05724 (i->outgoing && (i->callprogress & 2))) {
05725 features |= DSP_FEATURE_FAX_DETECT;
05726 }
05727 #ifdef DAHDI_TONEDETECT
05728 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05729 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
05730 #endif
05731 i->hardwaredtmf = 0;
05732 features |= DSP_FEATURE_DTMF_DETECT;
05733 #ifdef DAHDI_TONEDETECT
05734 } else if (NEED_MFDETECT(i)) {
05735 i->hardwaredtmf = 1;
05736 features |= DSP_FEATURE_DTMF_DETECT;
05737 }
05738 #endif
05739 }
05740 if (features) {
05741 if (i->dsp) {
05742 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05743 } else {
05744 if (i->channel != CHAN_PSEUDO)
05745 i->dsp = ast_dsp_new();
05746 else
05747 i->dsp = NULL;
05748 if (i->dsp) {
05749 i->dsp_features = features;
05750 #ifdef HAVE_PRI
05751
05752 if (i->outgoing && (i->sig == SIG_PRI)) {
05753
05754
05755 i->dsp_features = features & ~DSP_PROGRESS_TALK;
05756 features = 0;
05757 }
05758 #endif
05759 ast_dsp_set_features(i->dsp, features);
05760 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05761 if (!ast_strlen_zero(progzone))
05762 ast_dsp_set_call_progress_zone(i->dsp, progzone);
05763 if (i->busydetect && CANBUSYDETECT(i)) {
05764 if(i->silencethreshold > 0)
05765 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
05766 ast_dsp_set_busy_count(i->dsp, i->busycount);
05767 if(i->busytonelength > 0)
05768 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
05769 if((i->busytonelength == i->busyquietlength) && i->busycompare)
05770 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
05771 }
05772 }
05773 }
05774 }
05775
05776 if (state == AST_STATE_RING)
05777 tmp->rings = 1;
05778 tmp->tech_pvt = i;
05779 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05780
05781 tmp->callgroup = i->callgroup;
05782 tmp->pickupgroup = i->pickupgroup;
05783 }
05784 if (!ast_strlen_zero(i->language))
05785 ast_string_field_set(tmp, language, i->language);
05786 if (!i->owner)
05787 i->owner = tmp;
05788 if (!ast_strlen_zero(i->accountcode))
05789 ast_string_field_set(tmp, accountcode, i->accountcode);
05790 if (i->amaflags)
05791 tmp->amaflags = i->amaflags;
05792 i->subs[index].owner = tmp;
05793 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05794 ast_string_field_set(tmp, call_forward, i->call_forward);
05795
05796 if (!i->adsi)
05797 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05798 if (!ast_strlen_zero(i->exten))
05799 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05800 if (!ast_strlen_zero(i->rdnis))
05801 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05802 if (!ast_strlen_zero(i->dnid))
05803 tmp->cid.cid_dnid = ast_strdup(i->dnid);
05804
05805
05806
05807 #ifdef PRI_ANI
05808 if (!ast_strlen_zero(i->cid_ani))
05809 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05810 else
05811 tmp->cid.cid_ani = ast_strdup(i->cid_num);
05812 #else
05813 tmp->cid.cid_ani = ast_strdup(i->cid_num);
05814 #endif
05815 tmp->cid.cid_pres = i->callingpres;
05816 tmp->cid.cid_ton = i->cid_ton;
05817 #ifdef HAVE_PRI
05818 tmp->transfercapability = transfercapability;
05819 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05820 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05821 i->digital = 1;
05822
05823 i->isidlecall = 0;
05824 i->alreadyhungup = 0;
05825 #endif
05826
05827 i->fake_event = 0;
05828
05829 dahdi_confmute(i, 0);
05830
05831 ast_jb_configure(tmp, &global_jbconf);
05832 if (startpbx) {
05833 if (ast_pbx_start(tmp)) {
05834 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05835 ast_hangup(tmp);
05836 i->owner = NULL;
05837 return NULL;
05838 }
05839 }
05840
05841 ast_module_ref(ast_module_info->self);
05842
05843 return tmp;
05844 }
05845
05846
05847 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
05848 {
05849 char c;
05850
05851 *str = 0;
05852 for (;;)
05853 {
05854
05855 c = ast_waitfordigit(chan, ms);
05856
05857 if (c < 1)
05858 return c;
05859 *str++ = c;
05860 *str = 0;
05861 if (strchr(term, c))
05862 return 1;
05863 }
05864 }
05865
05866 static int dahdi_wink(struct dahdi_pvt *p, int index)
05867 {
05868 int j;
05869 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
05870 for (;;)
05871 {
05872
05873 j = DAHDI_IOMUX_SIGEVENT;
05874
05875 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
05876
05877 if (j & DAHDI_IOMUX_SIGEVENT) break;
05878 }
05879
05880 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
05881 return 0;
05882 }
05883
05884 static void *ss_thread(void *data)
05885 {
05886 struct ast_channel *chan = data;
05887 struct dahdi_pvt *p = chan->tech_pvt;
05888 char exten[AST_MAX_EXTENSION] = "";
05889 char exten2[AST_MAX_EXTENSION] = "";
05890 unsigned char buf[256];
05891 char dtmfcid[300];
05892 char dtmfbuf[300];
05893 struct callerid_state *cs = NULL;
05894 char *name = NULL, *number = NULL;
05895 int distMatches;
05896 int curRingData[3];
05897 int receivedRingT;
05898 int counter1;
05899 int counter;
05900 int samples = 0;
05901 struct ast_smdi_md_message *smdi_msg = NULL;
05902 int flags;
05903 int i;
05904 int timeout;
05905 int getforward = 0;
05906 char *s1, *s2;
05907 int len = 0;
05908 int res;
05909 int index;
05910
05911 ast_mutex_lock(&ss_thread_lock);
05912 ss_thread_count++;
05913 ast_mutex_unlock(&ss_thread_lock);
05914
05915
05916
05917 if (!p) {
05918 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05919 ast_hangup(chan);
05920 goto quit;
05921 }
05922 if (option_verbose > 2)
05923 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05924 index = dahdi_get_index(chan, p, 1);
05925 if (index < 0) {
05926 ast_log(LOG_WARNING, "Huh?\n");
05927 ast_hangup(chan);
05928 goto quit;
05929 }
05930 if (p->dsp)
05931 ast_dsp_digitreset(p->dsp);
05932 switch (p->sig) {
05933 #ifdef HAVE_PRI
05934 case SIG_PRI:
05935
05936 ast_copy_string(exten, p->exten, sizeof(exten));
05937 len = strlen(exten);
05938 res = 0;
05939 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05940 if (len && !ast_ignore_pattern(chan->context, exten))
05941 tone_zone_play_tone(p->subs[index].dfd, -1);
05942 else
05943 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05944 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05945 timeout = matchdigittimeout;
05946 else
05947 timeout = gendigittimeout;
05948 res = ast_waitfordigit(chan, timeout);
05949 if (res < 0) {
05950 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05951 ast_hangup(chan);
05952 goto quit;
05953 } else if (res) {
05954 exten[len++] = res;
05955 exten[len] = '\0';
05956 } else
05957 break;
05958 }
05959
05960 if (ast_strlen_zero(exten)) {
05961 if (option_verbose > 2)
05962 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05963 exten[0] = 's';
05964 exten[1] = '\0';
05965 }
05966 tone_zone_play_tone(p->subs[index].dfd, -1);
05967 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05968
05969 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05970 if (p->dsp) ast_dsp_digitreset(p->dsp);
05971 dahdi_enable_ec(p);
05972 ast_setstate(chan, AST_STATE_RING);
05973 res = ast_pbx_run(chan);
05974 if (res) {
05975 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05976 }
05977 } else {
05978 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05979 chan->hangupcause = AST_CAUSE_UNALLOCATED;
05980 ast_hangup(chan);
05981 p->exten[0] = '\0';
05982
05983 p->call = NULL;
05984 }
05985 goto quit;
05986 break;
05987 #endif
05988 case SIG_FEATD:
05989 case SIG_FEATDMF:
05990 case SIG_FEATDMF_TA:
05991 case SIG_E911:
05992 case SIG_FGC_CAMAMF:
05993 case SIG_FEATB:
05994 case SIG_EMWINK:
05995 case SIG_SF_FEATD:
05996 case SIG_SF_FEATDMF:
05997 case SIG_SF_FEATB:
05998 case SIG_SFWINK:
05999 if (dahdi_wink(p, index))
06000 goto quit;
06001
06002 case SIG_EM:
06003 case SIG_EM_E1:
06004 case SIG_SF:
06005 case SIG_FGC_CAMA:
06006 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06007 if (p->dsp)
06008 ast_dsp_digitreset(p->dsp);
06009
06010 if (p->dsp) {
06011 if (NEED_MFDETECT(p))
06012 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06013 else
06014 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06015 }
06016 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06017
06018 if (!p->immediate)
06019
06020 res = ast_waitfordigit(chan, 5000);
06021 else
06022 res = 0;
06023 if (res > 0) {
06024
06025 dtmfbuf[0] = res;
06026 switch (p->sig) {
06027 case SIG_FEATD:
06028 case SIG_SF_FEATD:
06029 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06030 if (res > 0)
06031 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06032 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06033 break;
06034 case SIG_FEATDMF_TA:
06035 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06036 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06037 if (dahdi_wink(p, index)) goto quit;
06038 dtmfbuf[0] = 0;
06039
06040 res = ast_waitfordigit(chan, 5000);
06041 if (res <= 0) break;
06042 dtmfbuf[0] = res;
06043
06044 case SIG_FEATDMF:
06045 case SIG_E911:
06046 case SIG_FGC_CAMAMF:
06047 case SIG_SF_FEATDMF:
06048 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06049
06050 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06051 {
06052 if (dahdi_wink(p, index)) goto quit;
06053 dtmfbuf[0] = 0;
06054
06055 res = ast_waitfordigit(chan, 5000);
06056 if (res <= 0) break;
06057 dtmfbuf[0] = res;
06058 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06059 }
06060 if (res > 0) {
06061
06062 if (p->sig == SIG_E911)
06063 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06064 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06065 }
06066 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06067 break;
06068 case SIG_FEATB:
06069 case SIG_SF_FEATB:
06070 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06071 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06072 break;
06073 case SIG_EMWINK:
06074
06075
06076
06077
06078 if (res == '*') {
06079 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06080 if (res > 0)
06081 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06082 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06083 break;
06084 }
06085 default:
06086
06087 len = 1;
06088 dtmfbuf[len] = '\0';
06089 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06090 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06091 timeout = matchdigittimeout;
06092 } else {
06093 timeout = gendigittimeout;
06094 }
06095 res = ast_waitfordigit(chan, timeout);
06096 if (res < 0) {
06097 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06098 ast_hangup(chan);
06099 goto quit;
06100 } else if (res) {
06101 dtmfbuf[len++] = res;
06102 dtmfbuf[len] = '\0';
06103 } else {
06104 break;
06105 }
06106 }
06107 break;
06108 }
06109 }
06110 if (res == -1) {
06111 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06112 ast_hangup(chan);
06113 goto quit;
06114 } else if (res < 0) {
06115 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06116 ast_hangup(chan);
06117 goto quit;
06118 }
06119
06120 if (p->sig == SIG_FGC_CAMA) {
06121 char anibuf[100];
06122
06123 if (ast_safe_sleep(chan,1000) == -1) {
06124 ast_hangup(chan);
06125 goto quit;
06126 }
06127 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06128 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06129 res = my_getsigstr(chan, anibuf, "#", 10000);
06130 if ((res > 0) && (strlen(anibuf) > 2)) {
06131 if (anibuf[strlen(anibuf) - 1] == '#')
06132 anibuf[strlen(anibuf) - 1] = 0;
06133 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06134 }
06135 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06136 }
06137
06138 ast_copy_string(exten, dtmfbuf, sizeof(exten));
06139 if (ast_strlen_zero(exten))
06140 ast_copy_string(exten, "s", sizeof(exten));
06141 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06142
06143 if (exten[0] == '*') {
06144 char *stringp=NULL;
06145 ast_copy_string(exten2, exten, sizeof(exten2));
06146
06147 stringp=exten2 +1;
06148 s1 = strsep(&stringp, "*");
06149 s2 = strsep(&stringp, "*");
06150 if (s2) {
06151 if (!ast_strlen_zero(p->cid_num))
06152 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06153 else
06154 ast_set_callerid(chan, s1, NULL, s1);
06155 ast_copy_string(exten, s2, sizeof(exten));
06156 } else
06157 ast_copy_string(exten, s1, sizeof(exten));
06158 } else if (p->sig == SIG_FEATD)
06159 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06160 }
06161 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06162 if (exten[0] == '*') {
06163 char *stringp=NULL;
06164 ast_copy_string(exten2, exten, sizeof(exten2));
06165
06166 stringp=exten2 +1;
06167 s1 = strsep(&stringp, "#");
06168 s2 = strsep(&stringp, "#");
06169 if (s2) {
06170 if (!ast_strlen_zero(p->cid_num))
06171 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06172 else
06173 if (*(s1 + 2))
06174 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06175 ast_copy_string(exten, s2 + 1, sizeof(exten));
06176 } else
06177 ast_copy_string(exten, s1 + 2, sizeof(exten));
06178 } else
06179 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
06180 }
06181 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06182 if (exten[0] == '*') {
06183 char *stringp=NULL;
06184 ast_copy_string(exten2, exten, sizeof(exten2));
06185
06186 stringp=exten2 +1;
06187 s1 = strsep(&stringp, "#");
06188 s2 = strsep(&stringp, "#");
06189 if (s2 && (*(s2 + 1) == '0')) {
06190 if (*(s2 + 2))
06191 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06192 }
06193 if (s1) ast_copy_string(exten, s1, sizeof(exten));
06194 else ast_copy_string(exten, "911", sizeof(exten));
06195 } else
06196 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
06197 }
06198 if (p->sig == SIG_FEATB) {
06199 if (exten[0] == '*') {
06200 char *stringp=NULL;
06201 ast_copy_string(exten2, exten, sizeof(exten2));
06202
06203 stringp=exten2 +1;
06204 s1 = strsep(&stringp, "#");
06205 ast_copy_string(exten, exten2 + 1, sizeof(exten));
06206 } else
06207 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
06208 }
06209 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06210 dahdi_wink(p, index);
06211
06212
06213
06214 if (ast_safe_sleep(chan,100)) goto quit;
06215 }
06216 dahdi_enable_ec(p);
06217 if (NEED_MFDETECT(p)) {
06218 if (p->dsp) {
06219 if (!p->hardwaredtmf)
06220 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06221 else {
06222 ast_dsp_free(p->dsp);
06223 p->dsp = NULL;
06224 }
06225 }
06226 }
06227
06228 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06229 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06230 if (p->dsp) ast_dsp_digitreset(p->dsp);
06231 res = ast_pbx_run(chan);
06232 if (res) {
06233 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06234 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06235 }
06236 goto quit;
06237 } else {
06238 if (option_verbose > 2)
06239 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06240 sleep(2);
06241 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
06242 if (res < 0)
06243 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06244 else
06245 sleep(1);
06246 res = ast_streamfile(chan, "ss-noservice", chan->language);
06247 if (res >= 0)
06248 ast_waitstream(chan, "");
06249 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06250 ast_hangup(chan);
06251 goto quit;
06252 }
06253 break;
06254 case SIG_FXOLS:
06255 case SIG_FXOGS:
06256 case SIG_FXOKS:
06257
06258 timeout = firstdigittimeout;
06259
06260
06261 if (p->subs[SUB_THREEWAY].owner)
06262 timeout = 999999;
06263 while (len < AST_MAX_EXTENSION-1) {
06264
06265
06266 if (p->immediate)
06267 res = 's';
06268 else
06269 res = ast_waitfordigit(chan, timeout);
06270 timeout = 0;
06271 if (res < 0) {
06272 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06273 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06274 ast_hangup(chan);
06275 goto quit;
06276 } else if (res) {
06277 exten[len++]=res;
06278 exten[len] = '\0';
06279 }
06280 if (!ast_ignore_pattern(chan->context, exten))
06281 tone_zone_play_tone(p->subs[index].dfd, -1);
06282 else
06283 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06284 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06285 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06286 if (getforward) {
06287
06288 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
06289 if (option_verbose > 2)
06290 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06291 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06292 if (res)
06293 break;
06294 usleep(500000);
06295 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06296 sleep(1);
06297 memset(exten, 0, sizeof(exten));
06298 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06299 len = 0;
06300 getforward = 0;
06301 } else {
06302 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06303 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06304 if (!ast_strlen_zero(p->cid_num)) {
06305 if (!p->hidecallerid)
06306 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06307 else
06308 ast_set_callerid(chan, NULL, NULL, p->cid_num);
06309 }
06310 if (!ast_strlen_zero(p->cid_name)) {
06311 if (!p->hidecallerid)
06312 ast_set_callerid(chan, NULL, p->cid_name, NULL);
06313 }
06314 ast_setstate(chan, AST_STATE_RING);
06315 dahdi_enable_ec(p);
06316 res = ast_pbx_run(chan);
06317 if (res) {
06318 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06319 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06320 }
06321 goto quit;
06322 }
06323 } else {
06324
06325
06326 timeout = matchdigittimeout;
06327 }
06328 } else if (res == 0) {
06329 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
06330 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06331 dahdi_wait_event(p->subs[index].dfd);
06332 ast_hangup(chan);
06333 goto quit;
06334 } else if (p->callwaiting && !strcmp(exten, "*70")) {
06335 if (option_verbose > 2)
06336 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
06337
06338 p->callwaiting = 0;
06339 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06340 if (res) {
06341 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06342 chan->name, strerror(errno));
06343 }
06344 len = 0;
06345 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06346 memset(exten, 0, sizeof(exten));
06347 timeout = firstdigittimeout;
06348
06349 } else if (!strcmp(exten,ast_pickup_ext())) {
06350
06351
06352
06353
06354 if (index == SUB_REAL) {
06355
06356 if (p->subs[SUB_THREEWAY].owner) {
06357
06358
06359 alloc_sub(p, SUB_CALLWAIT);
06360 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06361 unalloc_sub(p, SUB_THREEWAY);
06362 }
06363 dahdi_enable_ec(p);
06364 if (ast_pickup_call(chan)) {
06365 ast_log(LOG_DEBUG, "No call pickup possible...\n");
06366 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06367 dahdi_wait_event(p->subs[index].dfd);
06368 }
06369 ast_hangup(chan);
06370 goto quit;
06371 } else {
06372 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
06373 ast_hangup(chan);
06374 goto quit;
06375 }
06376
06377 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
06378 if (option_verbose > 2)
06379 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
06380
06381 p->hidecallerid = 1;
06382 if (chan->cid.cid_num)
06383 free(chan->cid.cid_num);
06384 chan->cid.cid_num = NULL;
06385 if (chan->cid.cid_name)
06386 free(chan->cid.cid_name);
06387 chan->cid.cid_name = NULL;
06388 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06389 if (res) {
06390 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06391 chan->name, strerror(errno));
06392 }
06393 len = 0;
06394 memset(exten, 0, sizeof(exten));
06395 timeout = firstdigittimeout;
06396 } else if (p->callreturn && !strcmp(exten, "*69")) {
06397 res = 0;
06398 if (!ast_strlen_zero(p->lastcid_num)) {
06399 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
06400 }
06401 if (!res)
06402 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06403 break;
06404 } else if (!strcmp(exten, "*78")) {
06405
06406 if (option_verbose > 2)
06407 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
06408 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06409 "Channel: %s/%d\r\n"
06410 "Status: enabled\r\n", dahdi_chan_name, p->channel);
06411 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06412 p->dnd = 1;
06413 getforward = 0;
06414 memset(exten, 0, sizeof(exten));
06415 len = 0;
06416 } else if (!strcmp(exten, "*79")) {
06417
06418 if (option_verbose > 2)
06419 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
06420 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06421 "Channel: %s/%d\r\n"
06422 "Status: disabled\r\n", dahdi_chan_name, p->channel);
06423 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06424 p->dnd = 0;
06425 getforward = 0;
06426 memset(exten, 0, sizeof(exten));
06427 len = 0;
06428 } else if (p->cancallforward && !strcmp(exten, "*72")) {
06429 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06430 getforward = 1;
06431 memset(exten, 0, sizeof(exten));
06432 len = 0;
06433 } else if (p->cancallforward && !strcmp(exten, "*73")) {
06434 if (option_verbose > 2)
06435 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
06436 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06437 memset(p->call_forward, 0, sizeof(p->call_forward));
06438 getforward = 0;
06439 memset(exten, 0, sizeof(exten));
06440 len = 0;
06441 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
06442 p->subs[SUB_THREEWAY].owner &&
06443 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06444
06445
06446 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
06447 if (option_verbose > 2)
06448 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
06449 break;
06450 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
06451 if (option_verbose > 2)
06452 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
06453 res = ast_db_put("blacklist", p->lastcid_num, "1");
06454 if (!res) {
06455 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06456 memset(exten, 0, sizeof(exten));
06457 len = 0;
06458 }
06459 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
06460 if (option_verbose > 2)
06461 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
06462
06463 p->hidecallerid = 0;
06464 if (chan->cid.cid_num)
06465 free(chan->cid.cid_num);
06466 chan->cid.cid_num = NULL;
06467 if (chan->cid.cid_name)
06468 free(chan->cid.cid_name);
06469 chan->cid.cid_name = NULL;
06470 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
06471 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06472 if (res) {
06473 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06474 chan->name, strerror(errno));
06475 }
06476 len = 0;
06477 memset(exten, 0, sizeof(exten));
06478 timeout = firstdigittimeout;
06479 } else if (!strcmp(exten, "*0")) {
06480 struct ast_channel *nbridge =
06481 p->subs[SUB_THREEWAY].owner;
06482 struct dahdi_pvt *pbridge = NULL;
06483
06484 if (nbridge && ast_bridged_channel(nbridge))
06485 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06486 if (nbridge && pbridge &&
06487 (nbridge->tech == chan_tech) &&
06488 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
06489 ISTRUNK(pbridge)) {
06490 int func = DAHDI_FLASH;
06491
06492 p->dop.dialstr[0] = '\0';
06493
06494 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06495 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06496 nbridge->name, strerror(errno));
06497 }
06498 swap_subs(p, SUB_REAL, SUB_THREEWAY);
06499 unalloc_sub(p, SUB_THREEWAY);
06500 p->owner = p->subs[SUB_REAL].owner;
06501 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06502 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06503 ast_hangup(chan);
06504 goto quit;
06505 } else {
06506 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06507 dahdi_wait_event(p->subs[index].dfd);
06508 tone_zone_play_tone(p->subs[index].dfd, -1);
06509 swap_subs(p, SUB_REAL, SUB_THREEWAY);
06510 unalloc_sub(p, SUB_THREEWAY);
06511 p->owner = p->subs[SUB_REAL].owner;
06512 ast_hangup(chan);
06513 goto quit;
06514 }
06515 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06516 ((exten[0] != '*') || (strlen(exten) > 2))) {
06517 if (option_debug)
06518 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);
06519 break;
06520 }
06521 if (!timeout)
06522 timeout = gendigittimeout;
06523 if (len && !ast_ignore_pattern(chan->context, exten))
06524 tone_zone_play_tone(p->subs[index].dfd, -1);
06525 }
06526 break;
06527 case SIG_FXSLS:
06528 case SIG_FXSGS:
06529 case SIG_FXSKS:
06530 #ifdef HAVE_PRI
06531 if (p->pri) {
06532
06533 struct ast_frame *f;
06534 int res;
06535 time_t start;
06536
06537 time(&start);
06538 ast_setstate(chan, AST_STATE_RING);
06539 while (time(NULL) < start + 3) {
06540 res = ast_waitfor(chan, 1000);
06541 if (res) {
06542 f = ast_read(chan);
06543 if (!f) {
06544 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06545 ast_hangup(chan);
06546 goto quit;
06547 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06548 res = 1;
06549 } else
06550 res = 0;
06551 ast_frfree(f);
06552 if (res) {
06553 ast_log(LOG_DEBUG, "Got ring!\n");
06554 res = 0;
06555 break;
06556 }
06557 }
06558 }
06559 }
06560 #endif
06561
06562 if (p->use_smdi && p->smdi_iface) {
06563 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06564
06565 if (smdi_msg != NULL) {
06566 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06567
06568 if (smdi_msg->type == 'B')
06569 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06570 else if (smdi_msg->type == 'N')
06571 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06572
06573 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06574 } else {
06575 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06576 }
06577 }
06578
06579 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06580 number = smdi_msg->calling_st;
06581
06582
06583
06584
06585 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06586
06587 if (p->cid_signalling == CID_SIG_DTMF) {
06588 int i = 0;
06589 cs = NULL;
06590 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06591 "channel %s\n", chan->name);
06592 dahdi_setlinear(p->subs[index].dfd, 0);
06593 res = 2000;
06594 for (;;) {
06595 struct ast_frame *f;
06596 res = ast_waitfor(chan, res);
06597 if (res <= 0) {
06598 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06599 "Exiting simple switch\n");
06600 ast_hangup(chan);
06601 goto quit;
06602 }
06603 f = ast_read(chan);
06604 if (!f)
06605 break;
06606 if (f->frametype == AST_FRAME_DTMF) {
06607 dtmfbuf[i++] = f->subclass;
06608 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06609 res = 2000;
06610 }
06611 ast_frfree(f);
06612 if (chan->_state == AST_STATE_RING ||
06613 chan->_state == AST_STATE_RINGING)
06614 break;
06615 }
06616 dtmfbuf[i] = '\0';
06617 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06618
06619 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06620 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06621 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
06622 dtmfcid, flags);
06623
06624 if (!ast_strlen_zero(dtmfcid))
06625 number = dtmfcid;
06626 else
06627 number = NULL;
06628
06629 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06630 cs = callerid_new(p->cid_signalling);
06631 if (cs) {
06632 samples = 0;
06633 #if 1
06634 bump_gains(p);
06635 #endif
06636
06637 dahdi_setlinear(p->subs[index].dfd, 0);
06638
06639
06640 for (;;) {
06641 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06642 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06643 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06644 callerid_free(cs);
06645 ast_hangup(chan);
06646 goto quit;
06647 }
06648 if (i & DAHDI_IOMUX_SIGEVENT) {
06649 res = dahdi_get_event(p->subs[index].dfd);
06650 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06651
06652 if (p->cid_signalling == CID_SIG_V23_JP) {
06653 #ifdef DAHDI_EVENT_RINGBEGIN
06654 if (res == DAHDI_EVENT_RINGBEGIN) {
06655 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06656 usleep(1);
06657 }
06658 #endif
06659 } else {
06660 res = 0;
06661 break;
06662 }
06663 } else if (i & DAHDI_IOMUX_READ) {
06664 res = read(p->subs[index].dfd, buf, sizeof(buf));
06665 if (res < 0) {
06666 if (errno != ELAST) {
06667 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06668 callerid_free(cs);
06669 ast_hangup(chan);
06670 goto quit;
06671 }
06672 break;
06673 }
06674 samples += res;
06675
06676 if (p->cid_signalling == CID_SIG_V23_JP) {
06677 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06678 } else {
06679 res = callerid_feed(cs, buf, res, AST_LAW(p));
06680 }
06681
06682 if (res < 0) {
06683 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
06684 break;
06685 } else if (res)
06686 break;
06687 else if (samples > (8000 * 10))
06688 break;
06689 }
06690 }
06691 if (res == 1) {
06692 callerid_get(cs, &name, &number, &flags);
06693 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06694 }
06695
06696 if (p->cid_signalling == CID_SIG_V23_JP) {
06697 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06698 usleep(1);
06699 res = 4000;
06700 } else {
06701
06702
06703 res = 2000;
06704 }
06705
06706 for (;;) {
06707 struct ast_frame *f;
06708 res = ast_waitfor(chan, res);
06709 if (res <= 0) {
06710 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06711 "Exiting simple switch\n");
06712 ast_hangup(chan);
06713 goto quit;
06714 }
06715 if (!(f = ast_read(chan))) {
06716 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
06717 ast_hangup(chan);
06718 goto quit;
06719 }
06720 ast_frfree(f);
06721 if (chan->_state == AST_STATE_RING ||
06722 chan->_state == AST_STATE_RINGING)
06723 break;
06724 }
06725
06726
06727
06728 if (p->usedistinctiveringdetection) {
06729 len = 0;
06730 distMatches = 0;
06731
06732 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06733 curRingData[receivedRingT] = 0;
06734 receivedRingT = 0;
06735 counter = 0;
06736 counter1 = 0;
06737
06738 if (strcmp(p->context,p->defcontext) != 0) {
06739 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06740 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06741 }
06742
06743 for (;;) {
06744 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06745 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06746 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06747 callerid_free(cs);
06748 ast_hangup(chan);
06749 goto quit;
06750 }
06751 if (i & DAHDI_IOMUX_SIGEVENT) {
06752 res = dahdi_get_event(p->subs[index].dfd);
06753 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06754 res = 0;
06755
06756
06757 curRingData[receivedRingT] = p->ringt;
06758
06759 if (p->ringt < p->ringt_base/2)
06760 break;
06761
06762
06763 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06764 break;
06765 } else if (i & DAHDI_IOMUX_READ) {
06766 res = read(p->subs[index].dfd, buf, sizeof(buf));
06767 if (res < 0) {
06768 if (errno != ELAST) {
06769 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06770 callerid_free(cs);
06771 ast_hangup(chan);
06772 goto quit;
06773 }
06774 break;
06775 }
06776 if (p->ringt)
06777 p->ringt--;
06778 if (p->ringt == 1) {
06779 res = -1;
06780 break;
06781 }
06782 }
06783 }
06784 if (option_verbose > 2)
06785
06786 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06787
06788 for (counter = 0; counter < 3; counter++) {
06789
06790
06791 distMatches = 0;
06792 for (counter1 = 0; counter1 < 3; counter1++) {
06793 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06794 (p->drings.ringnum[counter].ring[counter1]-10)) {
06795 distMatches++;
06796 }
06797 }
06798 if (distMatches == 3) {
06799
06800 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06801 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06802 if (option_verbose > 2)
06803 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06804 break;
06805 }
06806 }
06807 }
06808
06809 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06810 #if 1
06811 restore_gains(p);
06812 #endif
06813 } else
06814 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06815 } else {
06816 ast_log(LOG_WARNING, "Channel %s in prering "
06817 "state, but I have nothing to do. "
06818 "Terminating simple switch, should be "
06819 "restarted by the actual ring.\n",
06820 chan->name);
06821 ast_hangup(chan);
06822 goto quit;
06823 }
06824 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06825
06826 cs = callerid_new(p->cid_signalling);
06827 if (cs) {
06828 #if 1
06829 bump_gains(p);
06830 #endif
06831 samples = 0;
06832 len = 0;
06833 distMatches = 0;
06834
06835 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06836 curRingData[receivedRingT] = 0;
06837 receivedRingT = 0;
06838 counter = 0;
06839 counter1 = 0;
06840
06841 if (strcmp(p->context,p->defcontext) != 0) {
06842 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06843 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06844 }
06845
06846
06847 dahdi_setlinear(p->subs[index].dfd, 0);
06848 for (;;) {
06849 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06850 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06851 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06852 callerid_free(cs);
06853 ast_hangup(chan);
06854 goto quit;
06855 }
06856 if (i & DAHDI_IOMUX_SIGEVENT) {
06857 res = dahdi_get_event(p->subs[index].dfd);
06858 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06859
06860 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
06861 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
06862 p->polarity = POLARITY_IDLE;
06863 callerid_free(cs);
06864 ast_hangup(chan);
06865 goto quit;
06866 }
06867 res = 0;
06868
06869
06870 curRingData[receivedRingT] = p->ringt;
06871
06872 if (p->ringt < p->ringt_base/2)
06873 break;
06874
06875
06876 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06877 break;
06878 } else if (i & DAHDI_IOMUX_READ) {
06879 res = read(p->subs[index].dfd, buf, sizeof(buf));
06880 if (res < 0) {
06881 if (errno != ELAST) {
06882 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06883 callerid_free(cs);
06884 ast_hangup(chan);
06885 goto quit;
06886 }
06887 break;
06888 }
06889 if (p->ringt)
06890 p->ringt--;
06891 if (p->ringt == 1) {
06892 res = -1;
06893 break;
06894 }
06895 samples += res;
06896 res = callerid_feed(cs, buf, res, AST_LAW(p));
06897 if (res < 0) {
06898 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06899 break;
06900 } else if (res)
06901 break;
06902 else if (samples > (8000 * 10))
06903 break;
06904 }
06905 }
06906 if (res == 1) {
06907 callerid_get(cs, &name, &number, &flags);
06908 if (option_debug)
06909 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06910 }
06911 if (distinctiveringaftercid == 1) {
06912
06913 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06914 curRingData[receivedRingT] = 0;
06915 }
06916 receivedRingT = 0;
06917 if (option_verbose > 2)
06918 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06919 for (;;) {
06920 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06921 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06922 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06923 callerid_free(cs);
06924 ast_hangup(chan);
06925 goto quit;
06926 }
06927 if (i & DAHDI_IOMUX_SIGEVENT) {
06928 res = dahdi_get_event(p->subs[index].dfd);
06929 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06930 res = 0;
06931
06932
06933 curRingData[receivedRingT] = p->ringt;
06934
06935 if (p->ringt < p->ringt_base/2)
06936 break;
06937
06938
06939 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06940 break;
06941 } else if (i & DAHDI_IOMUX_READ) {
06942 res = read(p->subs[index].dfd, buf, sizeof(buf));
06943 if (res < 0) {
06944 if (errno != ELAST) {
06945 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06946 callerid_free(cs);
06947 ast_hangup(chan);
06948 goto quit;
06949 }
06950 break;
06951 }
06952 if (p->ringt)
06953 p->ringt--;
06954 if (p->ringt == 1) {
06955 res = -1;
06956 break;
06957 }
06958 }
06959 }
06960 }
06961 if (p->usedistinctiveringdetection) {
06962 if (option_verbose > 2)
06963
06964 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06965
06966 for (counter = 0; counter < 3; counter++) {
06967
06968
06969 if (option_verbose > 2)
06970
06971 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06972 p->drings.ringnum[counter].ring[0],
06973 p->drings.ringnum[counter].ring[1],
06974 p->drings.ringnum[counter].ring[2]);
06975 distMatches = 0;
06976 for (counter1 = 0; counter1 < 3; counter1++) {
06977 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06978 (p->drings.ringnum[counter].ring[counter1]-10)) {
06979 distMatches++;
06980 }
06981 }
06982 if (distMatches == 3) {
06983
06984 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06985 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06986 if (option_verbose > 2)
06987 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06988 break;
06989 }
06990 }
06991 }
06992
06993 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06994 #if 1
06995 restore_gains(p);
06996 #endif
06997 if (res < 0) {
06998 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06999 }
07000 } else
07001 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07002 }
07003 else
07004 cs = NULL;
07005
07006 if (number)
07007 ast_shrink_phone_number(number);
07008 ast_set_callerid(chan, number, name, number);
07009
07010 if (smdi_msg)
07011 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07012
07013 if (cs)
07014 callerid_free(cs);
07015
07016 ast_setstate(chan, AST_STATE_RING);
07017 chan->rings = 1;
07018 p->ringt = p->ringt_base;
07019 res = ast_pbx_run(chan);
07020 if (res) {
07021 ast_hangup(chan);
07022 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07023 }
07024 goto quit;
07025 default:
07026 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07027 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07028 if (res < 0)
07029 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07030 }
07031 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07032 if (res < 0)
07033 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07034 ast_hangup(chan);
07035 quit:
07036 ast_mutex_lock(&ss_thread_lock);
07037 ss_thread_count--;
07038 ast_cond_signal(&ss_thread_complete);
07039 ast_mutex_unlock(&ss_thread_lock);
07040 return NULL;
07041 }
07042
07043
07044 static int dahdi_destroy_channel_bynum(int channel)
07045 {
07046 struct dahdi_pvt *tmp = NULL;
07047 struct dahdi_pvt *prev = NULL;
07048
07049 tmp = iflist;
07050 while (tmp) {
07051 if (tmp->channel == channel) {
07052 int x = DAHDI_FLASH;
07053 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07054 destroy_channel(prev, tmp, 1);
07055 ast_module_unref(ast_module_info->self);
07056 return RESULT_SUCCESS;
07057 }
07058 prev = tmp;
07059 tmp = tmp->next;
07060 }
07061 return RESULT_FAILURE;
07062 }
07063
07064 static int handle_init_event(struct dahdi_pvt *i, int event)
07065 {
07066 int res;
07067 pthread_t threadid;
07068 pthread_attr_t attr;
07069 struct ast_channel *chan;
07070 pthread_attr_init(&attr);
07071 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07072
07073 switch (event) {
07074 case DAHDI_EVENT_NONE:
07075 case DAHDI_EVENT_BITSCHANGED:
07076 break;
07077 case DAHDI_EVENT_WINKFLASH:
07078 case DAHDI_EVENT_RINGOFFHOOK:
07079 if (i->inalarm) break;
07080 if (i->radio) break;
07081
07082 switch (i->sig) {
07083 case SIG_FXOLS:
07084 case SIG_FXOGS:
07085 case SIG_FXOKS:
07086 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07087 if (res && (errno == EBUSY))
07088 break;
07089 if (i->cidspill) {
07090
07091 free(i->cidspill);
07092 i->cidspill = NULL;
07093 }
07094 if (i->immediate) {
07095 dahdi_enable_ec(i);
07096
07097 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07098 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07099 if (!chan) {
07100 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07101 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07102 if (res < 0)
07103 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07104 }
07105 } else {
07106
07107 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07108 if (chan) {
07109 if (has_voicemail(i))
07110 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07111 else
07112 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07113 if (res < 0)
07114 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
07115 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07116 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07117 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07118 if (res < 0)
07119 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07120 ast_hangup(chan);
07121 }
07122 } else
07123 ast_log(LOG_WARNING, "Unable to create channel\n");
07124 }
07125 break;
07126 case SIG_FXSLS:
07127 case SIG_FXSGS:
07128 case SIG_FXSKS:
07129 i->ringt = i->ringt_base;
07130
07131 case SIG_EMWINK:
07132 case SIG_FEATD:
07133 case SIG_FEATDMF:
07134 case SIG_FEATDMF_TA:
07135 case SIG_E911:
07136 case SIG_FGC_CAMA:
07137 case SIG_FGC_CAMAMF:
07138 case SIG_FEATB:
07139 case SIG_EM:
07140 case SIG_EM_E1:
07141 case SIG_SFWINK:
07142 case SIG_SF_FEATD:
07143 case SIG_SF_FEATDMF:
07144 case SIG_SF_FEATB:
07145 case SIG_SF:
07146
07147 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
07148 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07149 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07150 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07151 if (res < 0)
07152 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07153 ast_hangup(chan);
07154 } else if (!chan) {
07155 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
07156 }
07157 break;
07158 default:
07159 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07160 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07161 if (res < 0)
07162 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07163 return -1;
07164 }
07165 break;
07166 case DAHDI_EVENT_NOALARM:
07167 i->inalarm = 0;
07168 if (!i->unknown_alarm) {
07169 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
07170 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07171 "Channel: %d\r\n", i->channel);
07172 } else {
07173 i->unknown_alarm = 0;
07174 }
07175 break;
07176 case DAHDI_EVENT_ALARM:
07177 i->inalarm = 1;
07178 res = get_alarms(i);
07179 handle_alarms(i, res);
07180
07181 case DAHDI_EVENT_ONHOOK:
07182 if (i->radio)
07183 break;
07184
07185 switch (i->sig) {
07186 case SIG_FXOLS:
07187 case SIG_FXOGS:
07188 case SIG_FEATD:
07189 case SIG_FEATDMF:
07190 case SIG_FEATDMF_TA:
07191 case SIG_E911:
07192 case SIG_FGC_CAMA:
07193 case SIG_FGC_CAMAMF:
07194 case SIG_FEATB:
07195 case SIG_EM:
07196 case SIG_EM_E1:
07197 case SIG_EMWINK:
07198 case SIG_SF_FEATD:
07199 case SIG_SF_FEATDMF:
07200 case SIG_SF_FEATB:
07201 case SIG_SF:
07202 case SIG_SFWINK:
07203 case SIG_FXSLS:
07204 case SIG_FXSGS:
07205 case SIG_FXSKS:
07206 case SIG_GR303FXSKS:
07207 dahdi_disable_ec(i);
07208 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07209 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07210 break;
07211 case SIG_GR303FXOKS:
07212 case SIG_FXOKS:
07213 dahdi_disable_ec(i);
07214
07215 #ifdef ZHONE_HACK
07216 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07217 usleep(1);
07218 #endif
07219 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07220 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07221 break;
07222 case SIG_PRI:
07223 dahdi_disable_ec(i);
07224 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07225 break;
07226 default:
07227 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07228 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07229 return -1;
07230 }
07231 break;
07232 case DAHDI_EVENT_POLARITY:
07233 switch (i->sig) {
07234 case SIG_FXSLS:
07235 case SIG_FXSKS:
07236 case SIG_FXSGS:
07237
07238
07239
07240
07241 if (i->hanguponpolarityswitch)
07242 i->polarity = POLARITY_REV;
07243
07244 if (i->cid_start == CID_START_POLARITY) {
07245 i->polarity = POLARITY_REV;
07246 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
07247 "CID detection on channel %d\n",
07248 i->channel);
07249 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
07250 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07251 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07252 }
07253 }
07254 break;
07255 default:
07256 ast_log(LOG_WARNING, "handle_init_event detected "
07257 "polarity reversal on non-FXO (SIG_FXS) "
07258 "interface %d\n", i->channel);
07259 }
07260 break;
07261 case DAHDI_EVENT_REMOVED:
07262 ast_log(LOG_NOTICE,
07263 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
07264 i->channel);
07265 dahdi_destroy_channel_bynum(i->channel);
07266 break;
07267 }
07268 pthread_attr_destroy(&attr);
07269 return 0;
07270 }
07271
07272 static void *do_monitor(void *data)
07273 {
07274 int count, res, res2, spoint, pollres=0;
07275 struct dahdi_pvt *i;
07276 struct dahdi_pvt *last = NULL;
07277 time_t thispass = 0, lastpass = 0;
07278 int found;
07279 char buf[1024];
07280 struct pollfd *pfds=NULL;
07281 int lastalloc = -1;
07282
07283
07284
07285 #if 0
07286 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
07287 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
07288 return NULL;
07289 }
07290 ast_log(LOG_DEBUG, "Monitor starting...\n");
07291 #endif
07292 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07293
07294 for (;;) {
07295
07296 ast_mutex_lock(&iflock);
07297 if (!pfds || (lastalloc != ifcount)) {
07298 if (pfds) {
07299 free(pfds);
07300 pfds = NULL;
07301 }
07302 if (ifcount) {
07303 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
07304 ast_mutex_unlock(&iflock);
07305 return NULL;
07306 }
07307 }
07308 lastalloc = ifcount;
07309 }
07310
07311
07312 count = 0;
07313 i = iflist;
07314 while (i) {
07315 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
07316 if (!i->owner && !i->subs[SUB_REAL].owner) {
07317
07318 pfds[count].fd = i->subs[SUB_REAL].dfd;
07319 pfds[count].events = POLLPRI;
07320 pfds[count].revents = 0;
07321
07322 if (i->cidspill)
07323 pfds[count].events |= POLLIN;
07324 count++;
07325 }
07326 }
07327 i = i->next;
07328 }
07329
07330 ast_mutex_unlock(&iflock);
07331
07332 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
07333 pthread_testcancel();
07334
07335 res = poll(pfds, count, 1000);
07336 pthread_testcancel();
07337 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07338
07339
07340 if (res < 0) {
07341 if ((errno != EAGAIN) && (errno != EINTR))
07342 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07343 continue;
07344 }
07345
07346
07347 ast_mutex_lock(&iflock);
07348 found = 0;
07349 spoint = 0;
07350 lastpass = thispass;
07351 thispass = time(NULL);
07352 i = iflist;
07353 while (i) {
07354 if (thispass != lastpass) {
07355 if (!found && ((i == last) || ((i == iflist) && !last))) {
07356 last = i;
07357 if (last) {
07358 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07359 (last->sig & __DAHDI_SIG_FXO)) {
07360 res = ast_app_has_voicemail(last->mailbox, NULL);
07361 if (last->msgstate != res) {
07362 int x;
07363 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07364 x = DAHDI_FLUSH_BOTH;
07365 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07366 if (res2)
07367 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
07368 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07369
07370 x = 4000;
07371 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07372 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07373 last->cidpos = 0;
07374 last->msgstate = res;
07375 last->onhooktime = thispass;
07376 }
07377 found ++;
07378 }
07379 }
07380 last = last->next;
07381 }
07382 }
07383 }
07384 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
07385 if (i->radio && !i->owner)
07386 {
07387 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07388 if (res)
07389 {
07390 if (option_debug)
07391 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07392
07393 ast_mutex_unlock(&iflock);
07394 handle_init_event(i, res);
07395 ast_mutex_lock(&iflock);
07396 }
07397 i = i->next;
07398 continue;
07399 }
07400 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
07401 if (pollres & POLLIN) {
07402 if (i->owner || i->subs[SUB_REAL].owner) {
07403 #ifdef HAVE_PRI
07404 if (!i->pri)
07405 #endif
07406 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
07407 i = i->next;
07408 continue;
07409 }
07410 if (!i->cidspill) {
07411 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
07412 i = i->next;
07413 continue;
07414 }
07415 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
07416 if (res > 0) {
07417
07418 if (res > i->cidlen - i->cidpos)
07419 res = i->cidlen - i->cidpos;
07420 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
07421 if (res2 > 0) {
07422 i->cidpos += res2;
07423 if (i->cidpos >= i->cidlen) {
07424 free(i->cidspill);
07425 i->cidspill = 0;
07426 i->cidpos = 0;
07427 i->cidlen = 0;
07428 }
07429 } else {
07430 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07431 i->msgstate = -1;
07432 }
07433 } else {
07434 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07435 }
07436 }
07437 if (pollres & POLLPRI) {
07438 if (i->owner || i->subs[SUB_REAL].owner) {
07439 #ifdef HAVE_PRI
07440 if (!i->pri)
07441 #endif
07442 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
07443 i = i->next;
07444 continue;
07445 }
07446 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07447 if (option_debug)
07448 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07449
07450 ast_mutex_unlock(&iflock);
07451 handle_init_event(i, res);
07452 ast_mutex_lock(&iflock);
07453 }
07454 }
07455 i=i->next;
07456 }
07457 ast_mutex_unlock(&iflock);
07458 }
07459
07460 return NULL;
07461
07462 }
07463
07464 static int restart_monitor(void)
07465 {
07466 pthread_attr_t attr;
07467 pthread_attr_init(&attr);
07468 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07469
07470 if (monitor_thread == AST_PTHREADT_STOP)
07471 return 0;
07472 ast_mutex_lock(&monlock);
07473 if (monitor_thread == pthread_self()) {
07474 ast_mutex_unlock(&monlock);
07475 ast_log(LOG_WARNING, "Cannot kill myself\n");
07476 return -1;
07477 }
07478 if (monitor_thread != AST_PTHREADT_NULL) {
07479
07480 pthread_kill(monitor_thread, SIGURG);
07481 } else {
07482
07483 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07484 ast_mutex_unlock(&monlock);
07485 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07486 pthread_attr_destroy(&attr);
07487 return -1;
07488 }
07489 }
07490 ast_mutex_unlock(&monlock);
07491 pthread_attr_destroy(&attr);
07492 return 0;
07493 }
07494
07495 #ifdef HAVE_PRI
07496 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
07497 {
07498 int x;
07499 int trunkgroup;
07500
07501 trunkgroup = pris[*span].mastertrunkgroup;
07502 if (trunkgroup) {
07503
07504 for (x = 0; x < NUM_SPANS; x++) {
07505 if (pris[x].trunkgroup == trunkgroup) {
07506 *span = x;
07507 return 0;
07508 }
07509 }
07510 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
07511 *span = -1;
07512 } else {
07513 if (pris[*span].trunkgroup) {
07514 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
07515 *span = -1;
07516 } else if (pris[*span].mastertrunkgroup) {
07517 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
07518 *span = -1;
07519 } else {
07520 if (si->totalchans == 31) {
07521
07522 pris[*span].dchannels[0] = 16 + offset;
07523 } else if (si->totalchans == 24) {
07524
07525 pris[*span].dchannels[0] = 24 + offset;
07526 } else if (si->totalchans == 3) {
07527
07528 pris[*span].dchannels[0] = 3 + offset;
07529 } else {
07530 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);
07531 *span = -1;
07532 return 0;
07533 }
07534 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
07535 pris[*span].offset = offset;
07536 pris[*span].span = *span + 1;
07537 }
07538 }
07539 return 0;
07540 }
07541
07542 static int pri_create_trunkgroup(int trunkgroup, int *channels)
07543 {
07544 struct dahdi_spaninfo si;
07545 struct dahdi_params p;
07546 int fd;
07547 int span;
07548 int ospan=0;
07549 int x,y;
07550 for (x = 0; x < NUM_SPANS; x++) {
07551 if (pris[x].trunkgroup == trunkgroup) {
07552 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
07553 return -1;
07554 }
07555 }
07556 for (y = 0; y < NUM_DCHANS; y++) {
07557 if (!channels[y])
07558 break;
07559 memset(&si, 0, sizeof(si));
07560 memset(&p, 0, sizeof(p));
07561 fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
07562 if (fd < 0) {
07563 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
07564 return -1;
07565 }
07566 x = channels[y];
07567 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
07568 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
07569 close(fd);
07570 return -1;
07571 }
07572 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
07573 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
07574 return -1;
07575 }
07576 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
07577 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
07578 close(fd);
07579 return -1;
07580 }
07581 span = p.spanno - 1;
07582 if (pris[span].trunkgroup) {
07583 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
07584 close(fd);
07585 return -1;
07586 }
07587 if (pris[span].pvts[0]) {
07588 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
07589 close(fd);
07590 return -1;
07591 }
07592 if (!y) {
07593 pris[span].trunkgroup = trunkgroup;
07594 pris[span].offset = channels[y] - p.chanpos;
07595 ospan = span;
07596 }
07597 pris[ospan].dchannels[y] = channels[y];
07598 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
07599 pris[span].span = span + 1;
07600 close(fd);
07601 }
07602 return 0;
07603 }
07604
07605 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
07606 {
07607 if (pris[span].mastertrunkgroup) {
07608 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);
07609 return -1;
07610 }
07611 pris[span].mastertrunkgroup = trunkgroup;
07612 pris[span].prilogicalspan = logicalspan;
07613 return 0;
07614 }
07615
07616 #endif
07617
07618 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
07619 {
07620
07621 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
07622 char fn[80];
07623 #if 1
07624 struct dahdi_bufferinfo bi;
07625 #endif
07626 int res;
07627 int span=0;
07628 int here = 0;
07629 int x;
07630 struct dahdi_pvt **wlist;
07631 struct dahdi_pvt **wend;
07632 struct dahdi_params p;
07633
07634 wlist = &iflist;
07635 wend = &ifend;
07636
07637 #ifdef HAVE_PRI
07638 if (pri) {
07639 wlist = &pri->crvs;
07640 wend = &pri->crvend;
07641 }
07642 #endif
07643
07644 tmp2 = *wlist;
07645 prev = NULL;
07646
07647 while (tmp2) {
07648 if (!tmp2->destroy) {
07649 if (tmp2->channel == channel) {
07650 tmp = tmp2;
07651 here = 1;
07652 break;
07653 }
07654 if (tmp2->channel > channel) {
07655 break;
07656 }
07657 }
07658 prev = tmp2;
07659 tmp2 = tmp2->next;
07660 }
07661
07662 if (!here && reloading != 1) {
07663 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07664 if (tmp)
07665 free(tmp);
07666 return NULL;
07667 }
07668 ast_mutex_init(&tmp->lock);
07669 ifcount++;
07670 for (x = 0; x < 3; x++)
07671 tmp->subs[x].dfd = -1;
07672 tmp->channel = channel;
07673 }
07674
07675 if (tmp) {
07676 int chan_sig = conf->chan.sig;
07677 if (!here) {
07678 if ((channel != CHAN_PSEUDO) && !pri) {
07679 int count = 0;
07680 snprintf(fn, sizeof(fn), "%d", channel);
07681
07682 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07683 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
07684 usleep(1);
07685 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07686 count++;
07687 }
07688
07689 if (tmp->subs[SUB_REAL].dfd < 0) {
07690 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);
07691 destroy_dahdi_pvt(&tmp);
07692 return NULL;
07693 }
07694 memset(&p, 0, sizeof(p));
07695 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07696 if (res < 0) {
07697 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
07698 destroy_dahdi_pvt(&tmp);
07699 return NULL;
07700 }
07701 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07702 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));
07703 destroy_dahdi_pvt(&tmp);
07704 return NULL;
07705 }
07706 tmp->law = p.curlaw;
07707 tmp->span = p.spanno;
07708 span = p.spanno - 1;
07709 } else {
07710 if (channel == CHAN_PSEUDO)
07711 chan_sig = 0;
07712 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07713 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07714 return NULL;
07715 }
07716 }
07717 #ifdef HAVE_PRI
07718 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07719 int offset;
07720 int myswitchtype;
07721 int matchesdchan;
07722 int x,y;
07723 offset = 0;
07724 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
07725 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07726 destroy_dahdi_pvt(&tmp);
07727 return NULL;
07728 }
07729 if (span >= NUM_SPANS) {
07730 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07731 destroy_dahdi_pvt(&tmp);
07732 return NULL;
07733 } else {
07734 struct dahdi_spaninfo si;
07735 si.spanno = 0;
07736 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
07737 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07738 destroy_dahdi_pvt(&tmp);
07739 return NULL;
07740 }
07741
07742 tmp->logicalspan = pris[span].prilogicalspan;
07743 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07744 if (span < 0) {
07745 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07746 destroy_dahdi_pvt(&tmp);
07747 return NULL;
07748 }
07749 if (chan_sig == SIG_PRI)
07750 myswitchtype = conf->pri.switchtype;
07751 else
07752 myswitchtype = PRI_SWITCH_GR303_TMC;
07753
07754 matchesdchan=0;
07755 for (x = 0; x < NUM_SPANS; x++) {
07756 for (y = 0; y < NUM_DCHANS; y++) {
07757 if (pris[x].dchannels[y] == tmp->channel) {
07758 matchesdchan = 1;
07759 break;
07760 }
07761 }
07762 }
07763 offset = p.chanpos;
07764 if (!matchesdchan) {
07765 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07766 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07767 destroy_dahdi_pvt(&tmp);
07768 return NULL;
07769 }
07770 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07771 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07772 destroy_dahdi_pvt(&tmp);
07773 return NULL;
07774 }
07775 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07776 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07777 destroy_dahdi_pvt(&tmp);
07778 return NULL;
07779 }
07780 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07781 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07782 destroy_dahdi_pvt(&tmp);
07783 return NULL;
07784 }
07785 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07786 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07787 destroy_dahdi_pvt(&tmp);
07788 return NULL;
07789 }
07790 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07791 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07792 destroy_dahdi_pvt(&tmp);
07793 return NULL;
07794 }
07795 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07796 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07797 destroy_dahdi_pvt(&tmp);
07798 return NULL;
07799 }
07800 if (pris[span].numchans >= MAX_CHANNELS) {
07801 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07802 pris[span].trunkgroup);
07803 destroy_dahdi_pvt(&tmp);
07804 return NULL;
07805 }
07806 pris[span].nodetype = conf->pri.nodetype;
07807 pris[span].switchtype = myswitchtype;
07808 pris[span].nsf = conf->pri.nsf;
07809 pris[span].dialplan = conf->pri.dialplan;
07810 pris[span].localdialplan = conf->pri.localdialplan;
07811 pris[span].pvts[pris[span].numchans++] = tmp;
07812 pris[span].minunused = conf->pri.minunused;
07813 pris[span].minidle = conf->pri.minidle;
07814 pris[span].overlapdial = conf->pri.overlapdial;
07815 #ifdef HAVE_PRI_INBANDDISCONNECT
07816 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
07817 #endif
07818 pris[span].facilityenable = conf->pri.facilityenable;
07819 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07820 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07821 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07822 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07823 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07824 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07825 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07826 pris[span].resetinterval = conf->pri.resetinterval;
07827
07828 tmp->pri = &pris[span];
07829 tmp->prioffset = offset;
07830 tmp->call = NULL;
07831 } else {
07832 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07833 destroy_dahdi_pvt(&tmp);
07834 return NULL;
07835 }
07836 }
07837 } else {
07838 tmp->prioffset = 0;
07839 }
07840 #endif
07841 } else {
07842 chan_sig = tmp->sig;
07843 if (tmp->subs[SUB_REAL].dfd > -1) {
07844 memset(&p, 0, sizeof(p));
07845 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07846 }
07847 }
07848
07849 switch (chan_sig) {
07850 case SIG_FXSKS:
07851 case SIG_FXSLS:
07852 case SIG_EM:
07853 case SIG_EM_E1:
07854 case SIG_EMWINK:
07855 case SIG_FEATD:
07856 case SIG_FEATDMF:
07857 case SIG_FEATDMF_TA:
07858 case SIG_FEATB:
07859 case SIG_E911:
07860 case SIG_SF:
07861 case SIG_SFWINK:
07862 case SIG_FGC_CAMA:
07863 case SIG_FGC_CAMAMF:
07864 case SIG_SF_FEATD:
07865 case SIG_SF_FEATDMF:
07866 case SIG_SF_FEATB:
07867 p.starttime = 250;
07868 break;
07869 }
07870
07871 if (tmp->radio) {
07872
07873 p.channo = channel;
07874 p.rxwinktime = 1;
07875 p.rxflashtime = 1;
07876 p.starttime = 1;
07877 p.debouncetime = 5;
07878 }
07879 if (!tmp->radio) {
07880 p.channo = channel;
07881
07882 if (conf->timing.prewinktime >= 0)
07883 p.prewinktime = conf->timing.prewinktime;
07884 if (conf->timing.preflashtime >= 0)
07885 p.preflashtime = conf->timing.preflashtime;
07886 if (conf->timing.winktime >= 0)
07887 p.winktime = conf->timing.winktime;
07888 if (conf->timing.flashtime >= 0)
07889 p.flashtime = conf->timing.flashtime;
07890 if (conf->timing.starttime >= 0)
07891 p.starttime = conf->timing.starttime;
07892 if (conf->timing.rxwinktime >= 0)
07893 p.rxwinktime = conf->timing.rxwinktime;
07894 if (conf->timing.rxflashtime >= 0)
07895 p.rxflashtime = conf->timing.rxflashtime;
07896 if (conf->timing.debouncetime >= 0)
07897 p.debouncetime = conf->timing.debouncetime;
07898 }
07899
07900
07901 if (tmp->subs[SUB_REAL].dfd >= 0)
07902 {
07903 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
07904 if (res < 0) {
07905 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
07906 destroy_dahdi_pvt(&tmp);
07907 return NULL;
07908 }
07909 }
07910 #if 1
07911 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
07912 memset(&bi, 0, sizeof(bi));
07913 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07914 if (!res) {
07915 bi.txbufpolicy = conf->chan.buf_policy;
07916 bi.rxbufpolicy = conf->chan.buf_policy;
07917 bi.numbufs = conf->chan.buf_no;
07918 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07919 if (res < 0) {
07920 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
07921 }
07922 } else
07923 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
07924 }
07925 #endif
07926 tmp->immediate = conf->chan.immediate;
07927 tmp->transfertobusy = conf->chan.transfertobusy;
07928 tmp->sig = chan_sig;
07929 tmp->outsigmod = conf->chan.outsigmod;
07930 tmp->ringt_base = ringt_base;
07931 tmp->firstradio = 0;
07932 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07933 tmp->permcallwaiting = conf->chan.callwaiting;
07934 else
07935 tmp->permcallwaiting = 0;
07936
07937 tmp->destroy = 0;
07938 tmp->drings = drings;
07939 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07940 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07941 tmp->threewaycalling = conf->chan.threewaycalling;
07942 tmp->adsi = conf->chan.adsi;
07943 tmp->use_smdi = conf->chan.use_smdi;
07944 tmp->permhidecallerid = conf->chan.hidecallerid;
07945 tmp->callreturn = conf->chan.callreturn;
07946 tmp->echocancel = conf->chan.echocancel;
07947 tmp->echotraining = conf->chan.echotraining;
07948 tmp->pulse = conf->chan.pulse;
07949 if (tmp->echocancel)
07950 tmp->echocanbridged = conf->chan.echocanbridged;
07951 else {
07952 if (conf->chan.echocanbridged)
07953 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07954 tmp->echocanbridged = 0;
07955 }
07956 tmp->busydetect = conf->chan.busydetect;
07957 tmp->busycount = conf->chan.busycount;
07958 tmp->busycompare = conf->chan.busycompare;
07959 tmp->busytonelength = conf->chan.busytonelength;
07960 tmp->busyquietlength = conf->chan.busyquietlength;
07961 tmp->busyfuzziness = conf->chan.busyfuzziness;
07962 tmp->silencethreshold = conf->chan.silencethreshold;
07963 tmp->callprogress = conf->chan.callprogress;
07964 tmp->cancallforward = conf->chan.cancallforward;
07965 tmp->dtmfrelax = conf->chan.dtmfrelax;
07966 tmp->callwaiting = tmp->permcallwaiting;
07967 tmp->hidecallerid = tmp->permhidecallerid;
07968 tmp->channel = channel;
07969 tmp->stripmsd = conf->chan.stripmsd;
07970 tmp->use_callerid = conf->chan.use_callerid;
07971 tmp->cid_signalling = conf->chan.cid_signalling;
07972 tmp->cid_start = conf->chan.cid_start;
07973 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
07974 tmp->restrictcid = conf->chan.restrictcid;
07975 tmp->use_callingpres = conf->chan.use_callingpres;
07976 tmp->priindication_oob = conf->chan.priindication_oob;
07977 tmp->priexclusive = conf->chan.priexclusive;
07978 if (tmp->usedistinctiveringdetection) {
07979 if (!tmp->use_callerid) {
07980 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07981 tmp->use_callerid = 1;
07982 }
07983 }
07984
07985 if (tmp->cid_signalling == CID_SIG_SMDI) {
07986 if (!tmp->use_smdi) {
07987 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07988 tmp->use_smdi = 1;
07989 }
07990 }
07991 if (tmp->use_smdi) {
07992 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07993 if (!(tmp->smdi_iface)) {
07994 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07995 tmp->use_smdi = 0;
07996 }
07997 }
07998
07999 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
08000 tmp->amaflags = conf->chan.amaflags;
08001 if (!here) {
08002 tmp->confno = -1;
08003 tmp->propconfno = -1;
08004 }
08005 tmp->canpark = conf->chan.canpark;
08006 tmp->transfer = conf->chan.transfer;
08007 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
08008 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
08009 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
08010 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
08011 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
08012 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
08013 tmp->cid_ton = 0;
08014 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
08015 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
08016 tmp->msgstate = -1;
08017 tmp->group = conf->chan.group;
08018 tmp->callgroup = conf->chan.callgroup;
08019 tmp->pickupgroup= conf->chan.pickupgroup;
08020 tmp->rxgain = conf->chan.rxgain;
08021 tmp->txgain = conf->chan.txgain;
08022 tmp->tonezone = conf->chan.tonezone;
08023 tmp->onhooktime = time(NULL);
08024 if (tmp->subs[SUB_REAL].dfd > -1) {
08025 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
08026 if (tmp->dsp)
08027 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
08028 update_conf(tmp);
08029 if (!here) {
08030 if (chan_sig != SIG_PRI)
08031
08032 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08033 }
08034 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
08035 #ifdef HAVE_PRI
08036
08037 if (tmp->pri && !pri_is_up(tmp->pri)) {
08038 tmp->inalarm = 1;
08039 }
08040 #endif
08041 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
08042 tmp->inalarm = 1;
08043 handle_alarms(tmp, res);
08044 } else {
08045
08046
08047
08048
08049
08050
08051
08052
08053
08054
08055 tmp->unknown_alarm = 1;
08056 }
08057 }
08058
08059 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
08060 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
08061 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
08062 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
08063
08064 }
08065 if (tmp && !here) {
08066
08067 if (!*wlist) {
08068 *wlist = tmp;
08069 tmp->prev = NULL;
08070 tmp->next = NULL;
08071 *wend = tmp;
08072 } else {
08073
08074 struct dahdi_pvt *working = *wlist;
08075
08076
08077 if (working->channel > tmp->channel) {
08078 tmp->next = *wlist;
08079 tmp->prev = NULL;
08080 (*wlist)->prev = tmp;
08081 *wlist = tmp;
08082 } else {
08083
08084 while (working) {
08085
08086 if (working->next) {
08087 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
08088 tmp->next = working->next;
08089 tmp->prev = working;
08090 working->next->prev = tmp;
08091 working->next = tmp;
08092 break;
08093 }
08094 } else {
08095
08096 if (working->channel < tmp->channel) {
08097 working->next = tmp;
08098 tmp->next = NULL;
08099 tmp->prev = working;
08100 *wend = tmp;
08101 break;
08102 }
08103 }
08104 working = working->next;
08105 }
08106 }
08107 }
08108 }
08109 return tmp;
08110 }
08111
08112 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
08113 {
08114 int res;
08115 struct dahdi_params par;
08116
08117
08118 if (groupmatch) {
08119 if ((p->group & groupmatch) != groupmatch)
08120 return 0;
08121 *groupmatched = 1;
08122 }
08123
08124 if (channelmatch != -1) {
08125 if (p->channel != channelmatch)
08126 return 0;
08127 *channelmatched = 1;
08128 }
08129
08130 if (busy) {
08131 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
08132 *busy = 1;
08133 }
08134
08135 if (p->dnd)
08136 return 0;
08137
08138 if (p->guardtime && (time(NULL) < p->guardtime))
08139 return 0;
08140
08141
08142 if (!p->owner) {
08143 #ifdef HAVE_PRI
08144
08145 if (p->pri) {
08146 if (p->resetting || p->call)
08147 return 0;
08148 else
08149 return 1;
08150 }
08151 #endif
08152 if (!(p->radio || (p->oprmode < 0)))
08153 {
08154 if (!p->sig || (p->sig == SIG_FXSLS))
08155 return 1;
08156
08157 if (p->subs[SUB_REAL].dfd > -1) {
08158 memset(&par, 0, sizeof(par));
08159 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
08160 } else {
08161
08162 res = 0;
08163 par.rxisoffhook = 0;
08164 }
08165 if (res) {
08166 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
08167 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
08168
08169
08170
08171 if (par.rxbits > -1)
08172 return 1;
08173 if (par.rxisoffhook)
08174 return 1;
08175 else
08176 #ifdef DAHDI_CHECK_HOOKSTATE
08177 return 0;
08178 #else
08179 return 1;
08180 #endif
08181 } else if (par.rxisoffhook) {
08182 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
08183
08184 return 0;
08185 }
08186 }
08187 return 1;
08188 }
08189
08190
08191 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
08192 return 0;
08193
08194 if (!p->callwaiting) {
08195
08196 return 0;
08197 }
08198
08199 if (p->subs[SUB_CALLWAIT].dfd > -1) {
08200
08201 return 0;
08202 }
08203
08204 if ((p->owner->_state != AST_STATE_UP) &&
08205 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
08206
08207 return 0;
08208 }
08209 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
08210
08211 return 0;
08212 }
08213
08214 return 1;
08215 }
08216
08217 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
08218 {
08219 struct dahdi_pvt *p;
08220 struct dahdi_bufferinfo bi;
08221 int res;
08222
08223 if ((p = ast_malloc(sizeof(*p)))) {
08224 memcpy(p, src, sizeof(struct dahdi_pvt));
08225 ast_mutex_init(&p->lock);
08226 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
08227
08228 if (p->subs[SUB_REAL].dfd < 0) {
08229 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
08230 destroy_dahdi_pvt(&p);
08231 return NULL;
08232 }
08233 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08234 if (!res) {
08235 bi.txbufpolicy = p->buf_policy;
08236 bi.rxbufpolicy = p->buf_policy;
08237 bi.numbufs = p->buf_no;
08238 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08239 if (res < 0) {
08240 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
08241 }
08242 } else
08243 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
08244 }
08245 p->destroy = 1;
08246 p->next = iflist;
08247 p->prev = NULL;
08248 iflist = p;
08249 if (iflist->next)
08250 iflist->next->prev = p;
08251 return p;
08252 }
08253
08254
08255 #ifdef HAVE_PRI
08256 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
08257 {
08258 int x;
08259 if (backwards)
08260 x = pri->numchans;
08261 else
08262 x = 0;
08263 for (;;) {
08264 if (backwards && (x < 0))
08265 break;
08266 if (!backwards && (x >= pri->numchans))
08267 break;
08268 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
08269 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
08270 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
08271 return x;
08272 }
08273 if (backwards)
08274 x--;
08275 else
08276 x++;
08277 }
08278 return -1;
08279 }
08280 #endif
08281
08282 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
08283 {
08284 ast_group_t groupmatch = 0;
08285 int channelmatch = -1;
08286 int roundrobin = 0;
08287 int callwait = 0;
08288 int busy = 0;
08289 struct dahdi_pvt *p;
08290 struct ast_channel *tmp = NULL;
08291 char *dest=NULL;
08292 int x;
08293 char *s;
08294 char opt=0;
08295 int res=0, y=0;
08296 int backwards = 0;
08297 #ifdef HAVE_PRI
08298 int crv;
08299 int bearer = -1;
08300 int trunkgroup;
08301 struct dahdi_pri *pri=NULL;
08302 #endif
08303 struct dahdi_pvt *exit, *start, *end;
08304 ast_mutex_t *lock;
08305 int channelmatched = 0;
08306 int groupmatched = 0;
08307
08308
08309
08310
08311
08312
08313
08314
08315
08316
08317
08318
08319
08320
08321
08322
08323
08324
08325
08326 lock = &iflock;
08327 start = iflist;
08328 end = ifend;
08329 if (data) {
08330 dest = ast_strdupa((char *)data);
08331 } else {
08332 ast_log(LOG_WARNING, "Channel requested with no data\n");
08333 return NULL;
08334 }
08335 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
08336
08337 char *stringp;
08338
08339 stringp = dest + 1;
08340 s = strsep(&stringp, "/");
08341 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
08342 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08343 return NULL;
08344 }
08345 groupmatch = ((ast_group_t) 1 << x);
08346 if (toupper(dest[0]) == 'G') {
08347 if (dest[0] == 'G') {
08348 backwards = 1;
08349 p = ifend;
08350 } else
08351 p = iflist;
08352 } else {
08353 if (dest[0] == 'R') {
08354 backwards = 1;
08355 p = round_robin[x]?round_robin[x]->prev:ifend;
08356 if (!p)
08357 p = ifend;
08358 } else {
08359 p = round_robin[x]?round_robin[x]->next:iflist;
08360 if (!p)
08361 p = iflist;
08362 }
08363 roundrobin = 1;
08364 }
08365 } else {
08366 char *stringp;
08367
08368 stringp = dest;
08369 s = strsep(&stringp, "/");
08370 p = iflist;
08371 if (!strcasecmp(s, "pseudo")) {
08372
08373 x = CHAN_PSEUDO;
08374 channelmatch = x;
08375 }
08376 #ifdef HAVE_PRI
08377 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
08378 if ((trunkgroup < 1) || (crv < 1)) {
08379 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08380 return NULL;
08381 }
08382 res--;
08383 for (x = 0; x < NUM_SPANS; x++) {
08384 if (pris[x].trunkgroup == trunkgroup) {
08385 pri = pris + x;
08386 lock = &pri->lock;
08387 start = pri->crvs;
08388 end = pri->crvend;
08389 break;
08390 }
08391 }
08392 if (!pri) {
08393 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08394 return NULL;
08395 }
08396 channelmatch = crv;
08397 p = pris[x].crvs;
08398 }
08399 #endif
08400 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
08401 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08402 return NULL;
08403 } else {
08404 channelmatch = x;
08405 }
08406 }
08407
08408 ast_mutex_lock(lock);
08409 exit = p;
08410 while (p && !tmp) {
08411 if (roundrobin)
08412 round_robin[x] = p;
08413 #if 0
08414 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08415 #endif
08416
08417 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08418 if (option_debug)
08419 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08420 if (p->inalarm)
08421 goto next;
08422
08423 callwait = (p->owner != NULL);
08424 #ifdef HAVE_PRI
08425 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
08426 if (p->sig != SIG_FXSKS) {
08427
08428
08429 bearer = pri_find_empty_chan(pri, 0);
08430 if (bearer < 0) {
08431 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08432 p = NULL;
08433 break;
08434 }
08435 pri_assign_bearer(p, pri, pri->pvts[bearer]);
08436 } else {
08437 if (alloc_sub(p, 0)) {
08438 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08439 p = NULL;
08440 break;
08441 } else
08442 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08443 p->pri = pri;
08444 }
08445 }
08446 #endif
08447 if (p->channel == CHAN_PSEUDO) {
08448 p = chandup(p);
08449 if (!p) {
08450 break;
08451 }
08452 }
08453 if (p->owner) {
08454 if (alloc_sub(p, SUB_CALLWAIT)) {
08455 p = NULL;
08456 break;
08457 }
08458 }
08459 p->outgoing = 1;
08460 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08461 #ifdef HAVE_PRI
08462 if (p->bearer) {
08463
08464 p->bearer->owner = tmp;
08465 }
08466 #endif
08467
08468 if (res > 1) {
08469 if (opt == 'c') {
08470
08471 p->confirmanswer = 1;
08472 } else if (opt == 'r') {
08473
08474 if (res < 3)
08475 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08476 else
08477 p->distinctivering = y;
08478 } else if (opt == 'd') {
08479
08480 p->digital = 1;
08481 if (tmp)
08482 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08483 } else {
08484 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08485 }
08486 }
08487
08488 if (tmp && callwait)
08489 tmp->cdrflags |= AST_CDR_CALLWAIT;
08490 break;
08491 }
08492 next:
08493 if (backwards) {
08494 p = p->prev;
08495 if (!p)
08496 p = end;
08497 } else {
08498 p = p->next;
08499 if (!p)
08500 p = start;
08501 }
08502
08503 if (p == exit)
08504 break;
08505 }
08506 ast_mutex_unlock(lock);
08507 restart_monitor();
08508 if (callwait)
08509 *cause = AST_CAUSE_BUSY;
08510 else if (!tmp) {
08511 if (channelmatched) {
08512 if (busy)
08513 *cause = AST_CAUSE_BUSY;
08514 } else if (groupmatched) {
08515 *cause = AST_CAUSE_CONGESTION;
08516 }
08517 }
08518
08519 return tmp;
08520 }
08521
08522
08523 #ifdef HAVE_PRI
08524 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
08525 {
08526 struct dahdi_pvt *p;
08527 p = pri->crvs;
08528 while (p) {
08529 if (p->channel == crv)
08530 return p;
08531 p = p->next;
08532 }
08533 return NULL;
08534 }
08535
08536
08537 static int pri_find_principle(struct dahdi_pri *pri, int channel)
08538 {
08539 int x;
08540 int span = PRI_SPAN(channel);
08541 int spanfd;
08542 struct dahdi_params param;
08543 int principle = -1;
08544 int explicit = PRI_EXPLICIT(channel);
08545 channel = PRI_CHANNEL(channel);
08546
08547 if (!explicit) {
08548 spanfd = pri_active_dchan_fd(pri);
08549 memset(¶m, 0, sizeof(param));
08550 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
08551 return -1;
08552 span = pris[param.spanno - 1].prilogicalspan;
08553 }
08554
08555 for (x = 0; x < pri->numchans; x++) {
08556 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
08557 principle = x;
08558 break;
08559 }
08560 }
08561
08562 return principle;
08563 }
08564
08565 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
08566 {
08567 int x;
08568 struct dahdi_pvt *crv;
08569 if (!c) {
08570 if (principle < 0)
08571 return -1;
08572 return principle;
08573 }
08574 if ((principle > -1) &&
08575 (principle < pri->numchans) &&
08576 (pri->pvts[principle]) &&
08577 (pri->pvts[principle]->call == c))
08578 return principle;
08579
08580 for (x = 0; x < pri->numchans; x++) {
08581 if (!pri->pvts[x])
08582 continue;
08583 if (pri->pvts[x]->call == c) {
08584
08585 if (principle != x) {
08586 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
08587
08588 if (option_verbose > 2)
08589 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
08590 old->channel, new->channel);
08591 if (new->owner) {
08592 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
08593 old->channel, new->channel, new->channel);
08594 return -1;
08595 }
08596
08597 new->owner = old->owner;
08598 old->owner = NULL;
08599 if (new->owner) {
08600 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
08601 new->owner->tech_pvt = new;
08602 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
08603 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
08604 old->subs[SUB_REAL].owner = NULL;
08605 } else
08606 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);
08607 new->call = old->call;
08608 old->call = NULL;
08609
08610
08611 new->dsp = old->dsp;
08612 new->dsp_features = old->dsp_features;
08613 old->dsp = NULL;
08614 old->dsp_features = 0;
08615 }
08616 return principle;
08617 }
08618 }
08619
08620 crv = pri->crvs;
08621 while (crv) {
08622 if (crv->call == c) {
08623
08624 if (crv->bearer)
08625 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
08626 else if (pri->pvts[principle]->owner)
08627 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
08628 else {
08629
08630
08631 dahdi_close_sub(crv, SUB_REAL);
08632 pri->pvts[principle]->call = crv->call;
08633 pri_assign_bearer(crv, pri, pri->pvts[principle]);
08634 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
08635 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
08636 pri->trunkgroup, crv->channel);
08637 wakeup_sub(crv, SUB_REAL, pri);
08638 }
08639 return principle;
08640 }
08641 crv = crv->next;
08642 }
08643 ast_log(LOG_WARNING, "Call specified, but not found?\n");
08644 return -1;
08645 }
08646
08647 static void *do_idle_thread(void *vchan)
08648 {
08649 struct ast_channel *chan = vchan;
08650 struct dahdi_pvt *pvt = chan->tech_pvt;
08651 struct ast_frame *f;
08652 char ex[80];
08653
08654 int newms, ms = 30000;
08655 if (option_verbose > 2)
08656 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
08657 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
08658 if (ast_call(chan, ex, 0)) {
08659 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
08660 ast_hangup(chan);
08661 return NULL;
08662 }
08663 while ((newms = ast_waitfor(chan, ms)) > 0) {
08664 f = ast_read(chan);
08665 if (!f) {
08666
08667 break;
08668 }
08669 if (f->frametype == AST_FRAME_CONTROL) {
08670 switch (f->subclass) {
08671 case AST_CONTROL_ANSWER:
08672
08673 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
08674 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
08675 chan->priority = 1;
08676 if (option_verbose > 3)
08677 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
08678 ast_pbx_run(chan);
08679
08680 return NULL;
08681 case AST_CONTROL_BUSY:
08682 if (option_verbose > 3)
08683 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
08684 break;
08685 case AST_CONTROL_CONGESTION:
08686 if (option_verbose > 3)
08687 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
08688 break;
08689 };
08690 }
08691 ast_frfree(f);
08692 ms = newms;
08693 }
08694
08695 ast_hangup(chan);
08696 return NULL;
08697 }
08698
08699 #ifndef PRI_RESTART
08700 #error "Upgrade your libpri"
08701 #endif
08702 static void dahdi_pri_message(struct pri *pri, char *s)
08703 {
08704 int x, y;
08705 int dchan = -1, span = -1;
08706 int dchancount = 0;
08707
08708 if (pri) {
08709 for (x = 0; x < NUM_SPANS; x++) {
08710 for (y = 0; y < NUM_DCHANS; y++) {
08711 if (pris[x].dchans[y])
08712 dchancount++;
08713
08714 if (pris[x].dchans[y] == pri)
08715 dchan = y;
08716 }
08717 if (dchan >= 0) {
08718 span = x;
08719 break;
08720 }
08721 dchancount = 0;
08722 }
08723 if ((dchan >= 0) && (span >= 0)) {
08724 if (dchancount > 1)
08725 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
08726 else
08727 ast_verbose("%s", s);
08728 } else
08729 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08730 } else
08731 ast_verbose("%s", s);
08732
08733 ast_mutex_lock(&pridebugfdlock);
08734
08735 if (pridebugfd >= 0) {
08736 if (write(pridebugfd, s, strlen(s)) < 0) {
08737 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08738 }
08739 }
08740
08741 ast_mutex_unlock(&pridebugfdlock);
08742 }
08743
08744 static void dahdi_pri_error(struct pri *pri, char *s)
08745 {
08746 int x, y;
08747 int dchan = -1, span = -1;
08748 int dchancount = 0;
08749
08750 if (pri) {
08751 for (x = 0; x < NUM_SPANS; x++) {
08752 for (y = 0; y < NUM_DCHANS; y++) {
08753 if (pris[x].dchans[y])
08754 dchancount++;
08755
08756 if (pris[x].dchans[y] == pri)
08757 dchan = y;
08758 }
08759 if (dchan >= 0) {
08760 span = x;
08761 break;
08762 }
08763 dchancount = 0;
08764 }
08765 if ((dchan >= 0) && (span >= 0)) {
08766 if (dchancount > 1)
08767 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
08768 else
08769 ast_log(LOG_ERROR, "%s", s);
08770 } else
08771 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08772 } else
08773 ast_log(LOG_ERROR, "%s", s);
08774
08775 ast_mutex_lock(&pridebugfdlock);
08776
08777 if (pridebugfd >= 0) {
08778 if (write(pridebugfd, s, strlen(s)) < 0) {
08779 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08780 }
08781 }
08782
08783 ast_mutex_unlock(&pridebugfdlock);
08784 }
08785
08786 static int pri_check_restart(struct dahdi_pri *pri)
08787 {
08788 do {
08789 pri->resetpos++;
08790 } while ((pri->resetpos < pri->numchans) &&
08791 (!pri->pvts[pri->resetpos] ||
08792 pri->pvts[pri->resetpos]->call ||
08793 pri->pvts[pri->resetpos]->resetting));
08794 if (pri->resetpos < pri->numchans) {
08795
08796 pri->pvts[pri->resetpos]->resetting = 1;
08797 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
08798 } else {
08799 pri->resetting = 0;
08800 time(&pri->lastreset);
08801 }
08802 return 0;
08803 }
08804
08805 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
08806 {
08807 int x;
08808 int redo;
08809 ast_mutex_unlock(&pri->lock);
08810 ast_mutex_lock(&p->lock);
08811 do {
08812 redo = 0;
08813 for (x = 0; x < 3; x++) {
08814 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
08815 redo++;
08816 DEADLOCK_AVOIDANCE(&p->lock);
08817 }
08818 if (p->subs[x].owner) {
08819 ast_queue_hangup(p->subs[x].owner);
08820 ast_mutex_unlock(&p->subs[x].owner->lock);
08821 }
08822 }
08823 } while (redo);
08824 ast_mutex_unlock(&p->lock);
08825 ast_mutex_lock(&pri->lock);
08826 return 0;
08827 }
08828
08829 static char * redirectingreason2str(int redirectingreason)
08830 {
08831 switch (redirectingreason) {
08832 case 0:
08833 return "UNKNOWN";
08834 case 1:
08835 return "BUSY";
08836 case 2:
08837 return "NO_REPLY";
08838 case 0xF:
08839 return "UNCONDITIONAL";
08840 default:
08841 return "NOREDIRECT";
08842 }
08843 }
08844
08845 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
08846 {
08847 if (ast_strlen_zero(number)) {
08848 if (size) {
08849 *buf = '\0';
08850 }
08851 return;
08852 }
08853
08854 switch (plan) {
08855 case PRI_INTERNATIONAL_ISDN:
08856 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
08857 break;
08858 case PRI_NATIONAL_ISDN:
08859 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
08860 break;
08861 case PRI_LOCAL_ISDN:
08862 snprintf(buf, size, "%s%s", pri->localprefix, number);
08863 break;
08864 case PRI_PRIVATE:
08865 snprintf(buf, size, "%s%s", pri->privateprefix, number);
08866 break;
08867 case PRI_UNKNOWN:
08868 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
08869 break;
08870 default:
08871 snprintf(buf, size, "%s", number);
08872 break;
08873 }
08874 }
08875
08876 static int dahdi_setlaw(int dfd, int law)
08877 {
08878 int res;
08879 res = ioctl(dfd, DAHDI_SETLAW, &law);
08880 if (res)
08881 return res;
08882 return 0;
08883 }
08884
08885 static void *pri_dchannel(void *vpri)
08886 {
08887 struct dahdi_pri *pri = vpri;
08888 pri_event *e;
08889 struct pollfd fds[NUM_DCHANS];
08890 int res;
08891 int chanpos = 0;
08892 int x;
08893 int haveidles;
08894 int activeidles;
08895 int nextidle = -1;
08896 struct ast_channel *c;
08897 struct timeval tv, lowest, *next;
08898 struct timeval lastidle = { 0, 0 };
08899 int doidling=0;
08900 char *cc;
08901 char idlen[80];
08902 struct ast_channel *idle;
08903 pthread_t p;
08904 time_t t;
08905 int i, which=-1;
08906 int numdchans;
08907 int cause=0;
08908 struct dahdi_pvt *crv;
08909 pthread_t threadid;
08910 pthread_attr_t attr;
08911 char ani2str[6];
08912 char plancallingnum[256];
08913 char plancallingani[256];
08914 char calledtonstr[10];
08915
08916 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08917
08918 gettimeofday(&lastidle, NULL);
08919 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
08920
08921 cc = strchr(pri->idleext, '@');
08922 if (cc) {
08923 *cc = '\0';
08924 cc++;
08925 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
08926 #if 0
08927
08928 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
08929 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
08930 else
08931 #endif
08932 doidling = 1;
08933 } else
08934 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
08935 }
08936 for (;;) {
08937 for (i = 0; i < NUM_DCHANS; i++) {
08938 if (!pri->dchannels[i])
08939 break;
08940 fds[i].fd = pri->fds[i];
08941 fds[i].events = POLLIN | POLLPRI;
08942 fds[i].revents = 0;
08943 }
08944 numdchans = i;
08945 time(&t);
08946 ast_mutex_lock(&pri->lock);
08947 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
08948 if (pri->resetting && pri_is_up(pri)) {
08949 if (pri->resetpos < 0)
08950 pri_check_restart(pri);
08951 } else {
08952 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
08953 pri->resetting = 1;
08954 pri->resetpos = -1;
08955 }
08956 }
08957 }
08958
08959 if (doidling && pri_is_up(pri)) {
08960 nextidle = -1;
08961 haveidles = 0;
08962 activeidles = 0;
08963 for (x = pri->numchans; x >= 0; x--) {
08964 if (pri->pvts[x] && !pri->pvts[x]->owner &&
08965 !pri->pvts[x]->call) {
08966 if (haveidles < pri->minunused) {
08967 haveidles++;
08968 } else if (!pri->pvts[x]->resetting) {
08969 nextidle = x;
08970 break;
08971 }
08972 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
08973 activeidles++;
08974 }
08975 if (nextidle > -1) {
08976 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
08977
08978 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
08979 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
08980 if (idle) {
08981 pri->pvts[nextidle]->isidlecall = 1;
08982 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
08983 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
08984 dahdi_hangup(idle);
08985 }
08986 } else
08987 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
08988 gettimeofday(&lastidle, NULL);
08989 }
08990 } else if ((haveidles < pri->minunused) &&
08991 (activeidles > pri->minidle)) {
08992
08993
08994 for (x = pri->numchans; x >= 0; x--) {
08995
08996 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
08997 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08998 haveidles++;
08999
09000
09001 if ((haveidles >= pri->minunused) ||
09002 (activeidles <= pri->minidle))
09003 break;
09004 }
09005 }
09006 }
09007 }
09008
09009 lowest = ast_tv(60, 0);
09010 for (i = 0; i < NUM_DCHANS; i++) {
09011
09012 if (!pri->dchannels[i])
09013 break;
09014 if ((next = pri_schedule_next(pri->dchans[i]))) {
09015
09016 tv = ast_tvsub(*next, ast_tvnow());
09017 if (tv.tv_sec < 0) {
09018 tv = ast_tv(0,0);
09019 }
09020 if (doidling || pri->resetting) {
09021 if (tv.tv_sec > 1) {
09022 tv = ast_tv(1, 0);
09023 }
09024 } else {
09025 if (tv.tv_sec > 60) {
09026 tv = ast_tv(60, 0);
09027 }
09028 }
09029 } else if (doidling || pri->resetting) {
09030
09031
09032 tv = ast_tv(1,0);
09033 } else {
09034
09035 tv = ast_tv(60, 0);
09036 }
09037 if (!i || ast_tvcmp(tv, lowest) < 0) {
09038 lowest = tv;
09039 }
09040 }
09041 ast_mutex_unlock(&pri->lock);
09042
09043 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09044 pthread_testcancel();
09045 e = NULL;
09046 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
09047 pthread_testcancel();
09048 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09049
09050 ast_mutex_lock(&pri->lock);
09051 if (!res) {
09052 for (which = 0; which < NUM_DCHANS; which++) {
09053 if (!pri->dchans[which])
09054 break;
09055
09056 e = pri_schedule_run(pri->dchans[which]);
09057 if (e)
09058 break;
09059 }
09060 } else if (res > -1) {
09061 for (which = 0; which < NUM_DCHANS; which++) {
09062 if (!pri->dchans[which])
09063 break;
09064 if (fds[which].revents & POLLPRI) {
09065
09066 x = 0;
09067 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
09068 if (x)
09069 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);
09070
09071 if (x == DAHDI_EVENT_ALARM) {
09072 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
09073 pri_find_dchan(pri);
09074 } else if (x == DAHDI_EVENT_NOALARM) {
09075 pri->dchanavail[which] |= DCHAN_NOTINALARM;
09076 pri_restart(pri->dchans[which]);
09077 }
09078
09079 if (option_debug)
09080 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
09081 } else if (fds[which].revents & POLLIN) {
09082 e = pri_check_event(pri->dchans[which]);
09083 }
09084 if (e)
09085 break;
09086 }
09087 } else if (errno != EINTR)
09088 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
09089
09090 if (e) {
09091 if (pri->debug)
09092 pri_dump_event(pri->dchans[which], e);
09093
09094 if (e->e != PRI_EVENT_DCHAN_DOWN) {
09095 if (!(pri->dchanavail[which] & DCHAN_UP)) {
09096 if (option_verbose > 1)
09097 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
09098 }
09099 pri->dchanavail[which] |= DCHAN_UP;
09100 } else {
09101 if (pri->dchanavail[which] & DCHAN_UP) {
09102 if (option_verbose > 1)
09103 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
09104 }
09105 pri->dchanavail[which] &= ~DCHAN_UP;
09106 }
09107
09108 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
09109
09110 pri->pri = pri->dchans[which];
09111
09112 switch (e->e) {
09113 case PRI_EVENT_DCHAN_UP:
09114 if (!pri->pri) pri_find_dchan(pri);
09115
09116
09117 time(&pri->lastreset);
09118
09119
09120 if (pri->resetinterval > -1) {
09121 pri->lastreset -= pri->resetinterval;
09122 pri->lastreset += 5;
09123 }
09124 pri->resetting = 0;
09125
09126 for (i = 0; i < pri->numchans; i++)
09127 if (pri->pvts[i]) {
09128 pri->pvts[i]->inalarm = 0;
09129 }
09130 break;
09131 case PRI_EVENT_DCHAN_DOWN:
09132 pri_find_dchan(pri);
09133 if (!pri_is_up(pri)) {
09134 pri->resetting = 0;
09135
09136 for (i = 0; i < pri->numchans; i++) {
09137 struct dahdi_pvt *p = pri->pvts[i];
09138 if (p) {
09139 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
09140
09141 if (p->call) {
09142 if (p->pri && p->pri->pri) {
09143 pri_hangup(p->pri->pri, p->call, -1);
09144 pri_destroycall(p->pri->pri, p->call);
09145 p->call = NULL;
09146 } else
09147 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
09148 }
09149 if (p->realcall) {
09150 pri_hangup_all(p->realcall, pri);
09151 } else if (p->owner)
09152 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09153 }
09154 p->inalarm = 1;
09155 }
09156 }
09157 }
09158 break;
09159 case PRI_EVENT_RESTART:
09160 if (e->restart.channel > -1) {
09161 chanpos = pri_find_principle(pri, e->restart.channel);
09162 if (chanpos < 0)
09163 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
09164 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
09165 else {
09166 if (option_verbose > 2)
09167 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
09168 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
09169 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09170 if (pri->pvts[chanpos]->call) {
09171 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
09172 pri->pvts[chanpos]->call = NULL;
09173 }
09174
09175 if (pri->pvts[chanpos]->realcall)
09176 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09177 else if (pri->pvts[chanpos]->owner)
09178 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09179 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09180 }
09181 } else {
09182 if (option_verbose > 2)
09183 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
09184 for (x = 0; x < pri->numchans; x++)
09185 if (pri->pvts[x]) {
09186 ast_mutex_lock(&pri->pvts[x]->lock);
09187 if (pri->pvts[x]->call) {
09188 pri_destroycall(pri->pri, pri->pvts[x]->call);
09189 pri->pvts[x]->call = NULL;
09190 }
09191 if (pri->pvts[chanpos]->realcall)
09192 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09193 else if (pri->pvts[x]->owner)
09194 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09195 ast_mutex_unlock(&pri->pvts[x]->lock);
09196 }
09197 }
09198 break;
09199 case PRI_EVENT_KEYPAD_DIGIT:
09200 chanpos = pri_find_principle(pri, e->digit.channel);
09201 if (chanpos < 0) {
09202 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
09203 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
09204 } else {
09205 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
09206 if (chanpos > -1) {
09207 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09208
09209 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
09210
09211 int digitlen = strlen(e->digit.digits);
09212 char digit;
09213 int i;
09214 for (i = 0; i < digitlen; i++) {
09215 digit = e->digit.digits[i];
09216 {
09217 struct ast_frame f = { AST_FRAME_DTMF, digit, };
09218 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09219 }
09220 }
09221 }
09222 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09223 }
09224 }
09225 break;
09226
09227 case PRI_EVENT_INFO_RECEIVED:
09228 chanpos = pri_find_principle(pri, e->ring.channel);
09229 if (chanpos < 0) {
09230 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
09231 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09232 } else {
09233 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
09234 if (chanpos > -1) {
09235 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09236
09237 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
09238
09239 int digitlen = strlen(e->ring.callednum);
09240 char digit;
09241 int i;
09242 for (i = 0; i < digitlen; i++) {
09243 digit = e->ring.callednum[i];
09244 {
09245 struct ast_frame f = { AST_FRAME_DTMF, digit, };
09246 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09247 }
09248 }
09249 }
09250 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09251 }
09252 }
09253 break;
09254 case PRI_EVENT_RING:
09255 crv = NULL;
09256 if (e->ring.channel == -1)
09257 chanpos = pri_find_empty_chan(pri, 1);
09258 else
09259 chanpos = pri_find_principle(pri, e->ring.channel);
09260
09261 if (chanpos < 0) {
09262 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
09263 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09264 } else {
09265 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09266 if (pri->pvts[chanpos]->owner) {
09267 if (pri->pvts[chanpos]->call == e->ring.call) {
09268 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
09269 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09270 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09271 break;
09272 } else {
09273
09274 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
09275 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09276 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09277 chanpos = -1;
09278 }
09279 }
09280 if (chanpos > -1)
09281 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09282 }
09283 if ((chanpos < 0) && (e->ring.flexible))
09284 chanpos = pri_find_empty_chan(pri, 1);
09285 if (chanpos > -1) {
09286 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09287 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
09288
09289 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
09290 if (crv)
09291 ast_mutex_lock(&crv->lock);
09292 if (!crv || crv->owner) {
09293 pri->pvts[chanpos]->call = NULL;
09294 if (crv) {
09295 if (crv->owner)
09296 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09297 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);
09298 } else
09299 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);
09300 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
09301 if (crv)
09302 ast_mutex_unlock(&crv->lock);
09303 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09304 break;
09305 }
09306 }
09307 pri->pvts[chanpos]->call = e->ring.call;
09308 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
09309 if (pri->pvts[chanpos]->use_callerid) {
09310 ast_shrink_phone_number(plancallingnum);
09311 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
09312 #ifdef PRI_ANI
09313 if (!ast_strlen_zero(e->ring.callingani)) {
09314 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
09315 ast_shrink_phone_number(plancallingani);
09316 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
09317 } else {
09318 pri->pvts[chanpos]->cid_ani[0] = '\0';
09319 }
09320 #endif
09321 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
09322 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
09323 } else {
09324 pri->pvts[chanpos]->cid_num[0] = '\0';
09325 pri->pvts[chanpos]->cid_ani[0] = '\0';
09326 pri->pvts[chanpos]->cid_name[0] = '\0';
09327 pri->pvts[chanpos]->cid_ton = 0;
09328 }
09329 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
09330 e->ring.redirectingnum, e->ring.callingplanrdnis);
09331
09332 if (pri->pvts[chanpos]->immediate) {
09333 if (option_verbose > 2)
09334 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
09335 pri->pvts[chanpos]->exten[0] = 's';
09336 pri->pvts[chanpos]->exten[1] = '\0';
09337 }
09338
09339 else if (!ast_strlen_zero(e->ring.callednum)) {
09340 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
09341 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09342 } else if (pri->overlapdial)
09343 pri->pvts[chanpos]->exten[0] = '\0';
09344 else {
09345
09346 pri->pvts[chanpos]->exten[0] = 's';
09347 pri->pvts[chanpos]->exten[1] = '\0';
09348 }
09349
09350 if (!ast_strlen_zero(e->ring.callednum))
09351 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09352
09353 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
09354 if (option_verbose > 2)
09355 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
09356 pri->pvts[chanpos]->exten[0] = 's';
09357 pri->pvts[chanpos]->exten[1] = '\0';
09358 }
09359
09360 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
09361 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09362
09363 int law;
09364 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
09365
09366 law = 1;
09367 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09368 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
09369 }
09370 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
09371 law = DAHDI_LAW_ALAW;
09372 else
09373 law = DAHDI_LAW_MULAW;
09374 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
09375 if (res < 0)
09376 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
09377 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
09378 if (res < 0)
09379 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
09380 if (e->ring.complete || !pri->overlapdial) {
09381
09382 pri->pvts[chanpos]->proceeding = 1;
09383 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
09384 } else {
09385 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
09386 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09387 else
09388 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09389 }
09390
09391 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
09392
09393
09394 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09395
09396 ast_mutex_unlock(&pri->lock);
09397 if (crv) {
09398
09399 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
09400 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09401 pri->pvts[chanpos]->owner = &inuse;
09402 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
09403 } else {
09404 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09405 }
09406
09407 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09408
09409 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
09410 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
09411 }
09412 if (e->ring.ani2 >= 0) {
09413 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
09414 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09415 }
09416
09417 #ifdef SUPPORT_USERUSER
09418 if (!ast_strlen_zero(e->ring.useruserinfo)) {
09419 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09420 }
09421 #endif
09422
09423 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09424 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09425 if (e->ring.redirectingreason >= 0)
09426 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09427
09428 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09429 ast_mutex_lock(&pri->lock);
09430
09431 pthread_attr_init(&attr);
09432 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09433 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
09434 if (option_verbose > 2)
09435 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
09436 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
09437 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09438 } else {
09439 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
09440 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09441 if (c)
09442 ast_hangup(c);
09443 else {
09444 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09445 pri->pvts[chanpos]->call = NULL;
09446 }
09447 }
09448 pthread_attr_destroy(&attr);
09449 } else {
09450 ast_mutex_unlock(&pri->lock);
09451
09452 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
09453 if (c) {
09454 char calledtonstr[10];
09455
09456 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09457
09458 if (e->ring.ani2 >= 0) {
09459 snprintf(ani2str, 5, "%d", e->ring.ani2);
09460 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09461 }
09462
09463 #ifdef SUPPORT_USERUSER
09464 if (!ast_strlen_zero(e->ring.useruserinfo)) {
09465 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09466 }
09467 #endif
09468
09469 if (e->ring.redirectingreason >= 0)
09470 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09471
09472 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09473 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09474
09475 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09476 ast_mutex_lock(&pri->lock);
09477
09478 if (option_verbose > 2)
09479 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
09480 plancallingnum, pri->pvts[chanpos]->exten,
09481 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09482 dahdi_enable_ec(pri->pvts[chanpos]);
09483 } else {
09484
09485 ast_mutex_lock(&pri->lock);
09486
09487 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
09488 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09489 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09490 pri->pvts[chanpos]->call = NULL;
09491 }
09492 }
09493 } else {
09494 if (option_verbose > 2)
09495 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
09496 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
09497 pri->pvts[chanpos]->prioffset, pri->span);
09498 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
09499 pri->pvts[chanpos]->call = NULL;
09500 pri->pvts[chanpos]->exten[0] = '\0';
09501 }
09502 if (crv)
09503 ast_mutex_unlock(&crv->lock);
09504 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09505 } else {
09506 if (e->ring.flexible)
09507 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
09508 else
09509 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
09510 }
09511 break;
09512 case PRI_EVENT_RINGING:
09513 chanpos = pri_find_principle(pri, e->ringing.channel);
09514 if (chanpos < 0) {
09515 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
09516 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09517 } else {
09518 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
09519 if (chanpos < 0) {
09520 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
09521 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09522 } else {
09523 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09524 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09525 dahdi_enable_ec(pri->pvts[chanpos]);
09526 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
09527 pri->pvts[chanpos]->alerting = 1;
09528 } else
09529 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
09530 #ifdef PRI_PROGRESS_MASK
09531 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09532 #else
09533 if (e->ringing.progress == 8) {
09534 #endif
09535
09536 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09537
09538 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
09539 pri->pvts[chanpos]->dsp_features = 0;
09540 }
09541 }
09542
09543 #ifdef SUPPORT_USERUSER
09544 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
09545 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09546 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09547 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
09548 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09549 }
09550 #endif
09551
09552 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09553 }
09554 }
09555 break;
09556 case PRI_EVENT_PROGRESS:
09557
09558 chanpos = pri_find_principle(pri, e->proceeding.channel);
09559 if (chanpos > -1) {
09560 #ifdef PRI_PROGRESS_MASK
09561 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
09562 #else
09563 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
09564 #endif
09565 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
09566
09567 if (e->proceeding.cause > -1) {
09568 if (option_verbose > 2)
09569 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
09570
09571
09572 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
09573 if (pri->pvts[chanpos]->owner) {
09574 if (option_verbose > 2)
09575 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
09576
09577 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
09578 f.subclass = AST_CONTROL_BUSY;
09579 }
09580 }
09581 }
09582
09583 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09584 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
09585 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09586 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09587 #ifdef PRI_PROGRESS_MASK
09588 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09589 #else
09590 if (e->proceeding.progress == 8) {
09591 #endif
09592
09593 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09594 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09595 pri->pvts[chanpos]->dsp_features = 0;
09596 }
09597
09598 f.subclass = AST_CONTROL_PROGRESS;
09599 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09600 }
09601 pri->pvts[chanpos]->progress = 1;
09602 pri->pvts[chanpos]->dialing = 0;
09603 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09604 }
09605 }
09606 break;
09607 case PRI_EVENT_PROCEEDING:
09608 chanpos = pri_find_principle(pri, e->proceeding.channel);
09609 if (chanpos > -1) {
09610 if (!pri->pvts[chanpos]->proceeding) {
09611 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
09612
09613 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09614 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
09615 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09616 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09617 #ifdef PRI_PROGRESS_MASK
09618 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09619 #else
09620 if (e->proceeding.progress == 8) {
09621 #endif
09622
09623 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09624 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09625 pri->pvts[chanpos]->dsp_features = 0;
09626 }
09627
09628 f.subclass = AST_CONTROL_PROGRESS;
09629 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09630 }
09631 pri->pvts[chanpos]->proceeding = 1;
09632 pri->pvts[chanpos]->dialing = 0;
09633 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09634 }
09635 }
09636 break;
09637 case PRI_EVENT_FACNAME:
09638 chanpos = pri_find_principle(pri, e->facname.channel);
09639 if (chanpos < 0) {
09640 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
09641 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09642 } else {
09643 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
09644 if (chanpos < 0) {
09645 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
09646 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09647 } else {
09648
09649 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09650 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
09651 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
09652 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
09653 dahdi_enable_ec(pri->pvts[chanpos]);
09654 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09655 }
09656 }
09657 break;
09658 case PRI_EVENT_ANSWER:
09659 chanpos = pri_find_principle(pri, e->answer.channel);
09660 if (chanpos < 0) {
09661 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
09662 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09663 } else {
09664 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
09665 if (chanpos < 0) {
09666 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
09667 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09668 } else {
09669 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09670
09671
09672
09673
09674
09675 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09676 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09677 pri->pvts[chanpos]->dsp_features = 0;
09678 }
09679 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
09680 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
09681 x = DAHDI_START;
09682 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09683 if (res < 0) {
09684 if (errno != EINPROGRESS) {
09685 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
09686 }
09687 }
09688 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09689 pri->pvts[chanpos]->dialing = 1;
09690
09691 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
09692 if (res < 0) {
09693 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
09694 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09695 } else
09696 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
09697 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09698 } else if (pri->pvts[chanpos]->confirmanswer) {
09699 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
09700 } else {
09701 pri->pvts[chanpos]->dialing = 0;
09702 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
09703
09704 dahdi_enable_ec(pri->pvts[chanpos]);
09705 }
09706
09707 #ifdef SUPPORT_USERUSER
09708 if (!ast_strlen_zero(e->answer.useruserinfo)) {
09709 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09710 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09711 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
09712 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09713 }
09714 #endif
09715
09716 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09717 }
09718 }
09719 break;
09720 case PRI_EVENT_HANGUP:
09721 chanpos = pri_find_principle(pri, e->hangup.channel);
09722 if (chanpos < 0) {
09723 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
09724 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09725 } else {
09726 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09727 if (chanpos > -1) {
09728 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09729 if (!pri->pvts[chanpos]->alreadyhungup) {
09730
09731 pri->pvts[chanpos]->alreadyhungup = 1;
09732 if (pri->pvts[chanpos]->realcall)
09733 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09734 else if (pri->pvts[chanpos]->owner) {
09735
09736 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09737 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09738 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09739 else {
09740 switch (e->hangup.cause) {
09741 case PRI_CAUSE_USER_BUSY:
09742 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09743 break;
09744 case PRI_CAUSE_CALL_REJECTED:
09745 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09746 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09747 case PRI_CAUSE_SWITCH_CONGESTION:
09748 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09749 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09750 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09751 break;
09752 default:
09753 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09754 }
09755 }
09756 }
09757 if (option_verbose > 2)
09758 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
09759 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
09760 } else {
09761 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09762 pri->pvts[chanpos]->call = NULL;
09763 }
09764 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09765 if (option_verbose > 2)
09766 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
09767 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09768 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09769 pri->pvts[chanpos]->resetting = 1;
09770 }
09771 if (e->hangup.aoc_units > -1)
09772 if (option_verbose > 2)
09773 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09774 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09775
09776 #ifdef SUPPORT_USERUSER
09777 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
09778 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09779 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09780 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09781 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09782 }
09783 #endif
09784
09785 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09786 } else {
09787 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
09788 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09789 }
09790 }
09791 break;
09792 #ifndef PRI_EVENT_HANGUP_REQ
09793 #error please update libpri
09794 #endif
09795 case PRI_EVENT_HANGUP_REQ:
09796 chanpos = pri_find_principle(pri, e->hangup.channel);
09797 if (chanpos < 0) {
09798 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
09799 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09800 } else {
09801 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09802 if (chanpos > -1) {
09803 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09804 if (pri->pvts[chanpos]->realcall)
09805 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09806 else if (pri->pvts[chanpos]->owner) {
09807 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09808 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09809 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09810 else {
09811 switch (e->hangup.cause) {
09812 case PRI_CAUSE_USER_BUSY:
09813 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09814 break;
09815 case PRI_CAUSE_CALL_REJECTED:
09816 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09817 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09818 case PRI_CAUSE_SWITCH_CONGESTION:
09819 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09820 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09821 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09822 break;
09823 default:
09824 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09825 }
09826 }
09827 if (option_verbose > 2)
09828 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);
09829 if (e->hangup.aoc_units > -1)
09830 if (option_verbose > 2)
09831 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09832 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09833 } else {
09834 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09835 pri->pvts[chanpos]->call = NULL;
09836 }
09837 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09838 if (option_verbose > 2)
09839 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
09840 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09841 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09842 pri->pvts[chanpos]->resetting = 1;
09843 }
09844
09845 #ifdef SUPPORT_USERUSER
09846 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09847 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09848 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09849 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09850 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09851 }
09852 #endif
09853
09854 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09855 } else {
09856 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);
09857 }
09858 }
09859 break;
09860 case PRI_EVENT_HANGUP_ACK:
09861 chanpos = pri_find_principle(pri, e->hangup.channel);
09862 if (chanpos < 0) {
09863 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
09864 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09865 } else {
09866 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09867 if (chanpos > -1) {
09868 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09869 pri->pvts[chanpos]->call = NULL;
09870 pri->pvts[chanpos]->resetting = 0;
09871 if (pri->pvts[chanpos]->owner) {
09872 if (option_verbose > 2)
09873 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);
09874 }
09875
09876 #ifdef SUPPORT_USERUSER
09877 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09878 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09879 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09880 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09881 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09882 }
09883 #endif
09884
09885 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09886 }
09887 }
09888 break;
09889 case PRI_EVENT_CONFIG_ERR:
09890 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
09891 break;
09892 case PRI_EVENT_RESTART_ACK:
09893 chanpos = pri_find_principle(pri, e->restartack.channel);
09894 if (chanpos < 0) {
09895
09896
09897
09898 for (x = 0; x < pri->numchans; x++) {
09899 if (pri->pvts[x] && pri->pvts[x]->resetting) {
09900 chanpos = x;
09901 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09902 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
09903 pri->pvts[chanpos]->prioffset, pri->span);
09904 if (pri->pvts[chanpos]->realcall)
09905 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09906 else if (pri->pvts[chanpos]->owner) {
09907 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
09908 pri->pvts[chanpos]->prioffset, pri->span);
09909 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09910 }
09911 pri->pvts[chanpos]->resetting = 0;
09912 if (option_verbose > 2)
09913 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
09914 pri->pvts[chanpos]->prioffset, pri->span);
09915 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09916 if (pri->resetting)
09917 pri_check_restart(pri);
09918 break;
09919 }
09920 }
09921 if (chanpos < 0) {
09922 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
09923 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09924 }
09925 } else {
09926 if (pri->pvts[chanpos]) {
09927 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09928 if (pri->pvts[chanpos]->realcall)
09929 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09930 else if (pri->pvts[chanpos]->owner) {
09931 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
09932 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09933 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09934 }
09935 pri->pvts[chanpos]->resetting = 0;
09936 if (option_verbose > 2)
09937 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
09938 pri->pvts[chanpos]->prioffset, pri->span);
09939 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09940 if (pri->resetting)
09941 pri_check_restart(pri);
09942 }
09943 }
09944 break;
09945 case PRI_EVENT_SETUP_ACK:
09946 chanpos = pri_find_principle(pri, e->setup_ack.channel);
09947 if (chanpos < 0) {
09948 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
09949 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
09950 } else {
09951 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
09952 if (chanpos > -1) {
09953 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09954 pri->pvts[chanpos]->setup_ack = 1;
09955
09956 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
09957 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
09958 pri_information(pri->pri, pri->pvts[chanpos]->call,
09959 pri->pvts[chanpos]->dialdest[x]);
09960 }
09961 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09962 } else
09963 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
09964 }
09965 break;
09966 case PRI_EVENT_NOTIFY:
09967 chanpos = pri_find_principle(pri, e->notify.channel);
09968 if (chanpos < 0) {
09969 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
09970 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
09971 } else {
09972 struct ast_frame f = { AST_FRAME_CONTROL, };
09973 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09974 switch (e->notify.info) {
09975 case PRI_NOTIFY_REMOTE_HOLD:
09976 f.subclass = AST_CONTROL_HOLD;
09977 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09978 break;
09979 case PRI_NOTIFY_REMOTE_RETRIEVAL:
09980 f.subclass = AST_CONTROL_UNHOLD;
09981 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09982 break;
09983 }
09984 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09985 }
09986 break;
09987 default:
09988 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
09989 }
09990 }
09991 ast_mutex_unlock(&pri->lock);
09992 }
09993
09994 return NULL;
09995 }
09996
09997 static int start_pri(struct dahdi_pri *pri)
09998 {
09999 int res, x;
10000 struct dahdi_params p;
10001 struct dahdi_bufferinfo bi;
10002 struct dahdi_spaninfo si;
10003 int i;
10004
10005 for (i = 0; i < NUM_DCHANS; i++) {
10006 if (!pri->dchannels[i])
10007 break;
10008 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
10009 x = pri->dchannels[i];
10010 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
10011 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
10012 return -1;
10013 }
10014 memset(&p, 0, sizeof(p));
10015 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
10016 if (res) {
10017 dahdi_close_pri_fd(pri, i);
10018 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
10019 return -1;
10020 }
10021 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
10022 dahdi_close_pri_fd(pri, i);
10023 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
10024 return -1;
10025 }
10026 memset(&si, 0, sizeof(si));
10027 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
10028 if (res) {
10029 dahdi_close_pri_fd(pri, i);
10030 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
10031 }
10032 if (!si.alarms)
10033 pri->dchanavail[i] |= DCHAN_NOTINALARM;
10034 else
10035 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
10036 memset(&bi, 0, sizeof(bi));
10037 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
10038 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
10039 bi.numbufs = 32;
10040 bi.bufsize = 1024;
10041 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
10042 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
10043 dahdi_close_pri_fd(pri, i);
10044 return -1;
10045 }
10046 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
10047
10048 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
10049 pri->overlapdial = 1;
10050 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
10051 #ifdef HAVE_PRI_INBANDDISCONNECT
10052 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
10053 #endif
10054
10055 if (i)
10056 pri_enslave(pri->dchans[0], pri->dchans[i]);
10057 if (!pri->dchans[i]) {
10058 dahdi_close_pri_fd(pri, i);
10059 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
10060 return -1;
10061 }
10062 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
10063 pri_set_nsf(pri->dchans[i], pri->nsf);
10064 #ifdef PRI_GETSET_TIMERS
10065 for (x = 0; x < PRI_MAX_TIMERS; x++) {
10066 if (pritimers[x] != 0)
10067 pri_set_timer(pri->dchans[i], x, pritimers[x]);
10068 }
10069 #endif
10070 }
10071
10072 pri->pri = pri->dchans[0];
10073 pri->resetpos = -1;
10074 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
10075 for (i = 0; i < NUM_DCHANS; i++) {
10076 if (!pri->dchannels[i])
10077 break;
10078 dahdi_close_pri_fd(pri, i);
10079 }
10080 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
10081 return -1;
10082 }
10083 return 0;
10084 }
10085
10086 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
10087 {
10088 int which, span;
10089 char *ret = NULL;
10090
10091 if (pos != rpos)
10092 return ret;
10093
10094 for (which = span = 0; span < NUM_SPANS; span++) {
10095 if (pris[span].pri && ++which > state) {
10096 if (asprintf(&ret, "%d", span + 1) < 0) {
10097 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
10098 }
10099 break;
10100 }
10101 }
10102 return ret;
10103 }
10104
10105 static char *complete_span_4(const char *line, const char *word, int pos, int state)
10106 {
10107 return complete_span_helper(line,word,pos,state,3);
10108 }
10109
10110 static char *complete_span_5(const char *line, const char *word, int pos, int state)
10111 {
10112 return complete_span_helper(line,word,pos,state,4);
10113 }
10114
10115 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
10116 {
10117 int myfd;
10118
10119 if (!strncasecmp(argv[1], "set", 3)) {
10120 if (argc < 5)
10121 return RESULT_SHOWUSAGE;
10122
10123 if (ast_strlen_zero(argv[4]))
10124 return RESULT_SHOWUSAGE;
10125
10126 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
10127 if (myfd < 0) {
10128 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
10129 return RESULT_SUCCESS;
10130 }
10131
10132 ast_mutex_lock(&pridebugfdlock);
10133
10134 if (pridebugfd >= 0)
10135 close(pridebugfd);
10136
10137 pridebugfd = myfd;
10138 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
10139
10140 ast_mutex_unlock(&pridebugfdlock);
10141
10142 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
10143 } else {
10144
10145 ast_mutex_lock(&pridebugfdlock);
10146 close(pridebugfd);
10147 pridebugfd = -1;
10148 ast_cli(fd, "PRI debug output to file disabled\n");
10149 ast_mutex_unlock(&pridebugfdlock);
10150 }
10151
10152 return RESULT_SUCCESS;
10153 }
10154
10155 #ifdef HAVE_PRI_VERSION
10156 static int handle_pri_version(int fd, int agc, char *argv[]) {
10157 ast_cli(fd, "libpri version: %s\n", pri_get_version());
10158 return RESULT_SUCCESS;
10159 }
10160 #endif
10161
10162 static int handle_pri_debug(int fd, int argc, char *argv[])
10163 {
10164 int span;
10165 int x;
10166 if (argc < 4) {
10167 return RESULT_SHOWUSAGE;
10168 }
10169 span = atoi(argv[3]);
10170 if ((span < 1) || (span > NUM_SPANS)) {
10171 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
10172 return RESULT_SUCCESS;
10173 }
10174 if (!pris[span-1].pri) {
10175 ast_cli(fd, "No PRI running on span %d\n", span);
10176 return RESULT_SUCCESS;
10177 }
10178 for (x = 0; x < NUM_DCHANS; x++) {
10179 if (pris[span-1].dchans[x])
10180 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
10181 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
10182 PRI_DEBUG_Q921_STATE);
10183 }
10184 ast_cli(fd, "Enabled debugging on span %d\n", span);
10185 return RESULT_SUCCESS;
10186 }
10187
10188
10189
10190 static int handle_pri_no_debug(int fd, int argc, char *argv[])
10191 {
10192 int span;
10193 int x;
10194 if (argc < 5)
10195 return RESULT_SHOWUSAGE;
10196 span = atoi(argv[4]);
10197 if ((span < 1) || (span > NUM_SPANS)) {
10198 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
10199 return RESULT_SUCCESS;
10200 }
10201 if (!pris[span-1].pri) {
10202 ast_cli(fd, "No PRI running on span %d\n", span);
10203 return RESULT_SUCCESS;
10204 }
10205 for (x = 0; x < NUM_DCHANS; x++) {
10206 if (pris[span-1].dchans[x])
10207 pri_set_debug(pris[span-1].dchans[x], 0);
10208 }
10209 ast_cli(fd, "Disabled debugging on span %d\n", span);
10210 return RESULT_SUCCESS;
10211 }
10212
10213 static int handle_pri_really_debug(int fd, int argc, char *argv[])
10214 {
10215 int span;
10216 int x;
10217 if (argc < 5)
10218 return RESULT_SHOWUSAGE;
10219 span = atoi(argv[4]);
10220 if ((span < 1) || (span > NUM_SPANS)) {
10221 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
10222 return RESULT_SUCCESS;
10223 }
10224 if (!pris[span-1].pri) {
10225 ast_cli(fd, "No PRI running on span %d\n", span);
10226 return RESULT_SUCCESS;
10227 }
10228 for (x = 0; x < NUM_DCHANS; x++) {
10229 if (pris[span-1].dchans[x])
10230 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
10231 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
10232 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
10233 }
10234 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
10235 return RESULT_SUCCESS;
10236 }
10237
10238 static void build_status(char *s, size_t len, int status, int active)
10239 {
10240 if (!s || len < 1) {
10241 return;
10242 }
10243 s[0] = '\0';
10244 if (status & DCHAN_PROVISIONED)
10245 strncat(s, "Provisioned, ", len - strlen(s) - 1);
10246 if (!(status & DCHAN_NOTINALARM))
10247 strncat(s, "In Alarm, ", len - strlen(s) - 1);
10248 if (status & DCHAN_UP)
10249 strncat(s, "Up", len - strlen(s) - 1);
10250 else
10251 strncat(s, "Down", len - strlen(s) - 1);
10252 if (active)
10253 strncat(s, ", Active", len - strlen(s) - 1);
10254 else
10255 strncat(s, ", Standby", len - strlen(s) - 1);
10256 s[len - 1] = '\0';
10257 }
10258
10259 static int handle_pri_show_spans(int fd, int argc, char *argv[])
10260 {
10261 int span;
10262 int x;
10263 char status[256];
10264 if (argc != 3)
10265 return RESULT_SHOWUSAGE;
10266
10267 for (span = 0; span < NUM_SPANS; span++) {
10268 if (pris[span].pri) {
10269 for (x = 0; x < NUM_DCHANS; x++) {
10270 if (pris[span].dchannels[x]) {
10271 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
10272 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
10273 }
10274 }
10275 }
10276 }
10277 return RESULT_SUCCESS;
10278 }
10279
10280 static int handle_pri_show_span(int fd, int argc, char *argv[])
10281 {
10282 int span;
10283 int x;
10284 char status[256];
10285 if (argc < 4)
10286 return RESULT_SHOWUSAGE;
10287 span = atoi(argv[3]);
10288 if ((span < 1) || (span > NUM_SPANS)) {
10289 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
10290 return RESULT_SUCCESS;
10291 }
10292 if (!pris[span-1].pri) {
10293 ast_cli(fd, "No PRI running on span %d\n", span);
10294 return RESULT_SUCCESS;
10295 }
10296 for (x = 0; x < NUM_DCHANS; x++) {
10297 if (pris[span-1].dchannels[x]) {
10298 #ifdef PRI_DUMP_INFO_STR
10299 char *info_str = NULL;
10300 #endif
10301 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
10302 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
10303 ast_cli(fd, "Status: %s\n", status);
10304 #ifdef PRI_DUMP_INFO_STR
10305 info_str = pri_dump_info_str(pris[span-1].pri);
10306 if (info_str) {
10307 ast_cli(fd, "%s", info_str);
10308 free(info_str);
10309 }
10310 #else
10311 pri_dump_info(pris[span-1].pri);
10312 #endif
10313 ast_cli(fd, "\n");
10314 }
10315 }
10316 return RESULT_SUCCESS;
10317 }
10318
10319 static int handle_pri_show_debug(int fd, int argc, char *argv[])
10320 {
10321 int x;
10322 int span;
10323 int count=0;
10324 int debug=0;
10325
10326 for (span = 0; span < NUM_SPANS; span++) {
10327 if (pris[span].pri) {
10328 for (x = 0; x < NUM_DCHANS; x++) {
10329 debug = 0;
10330 if (pris[span].dchans[x]) {
10331 debug = pri_get_debug(pris[span].dchans[x]);
10332 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" );
10333 count++;
10334 }
10335 }
10336 }
10337
10338 }
10339 ast_mutex_lock(&pridebugfdlock);
10340 if (pridebugfd >= 0)
10341 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
10342 ast_mutex_unlock(&pridebugfdlock);
10343
10344 if (!count)
10345 ast_cli(fd, "No debug set or no PRI running\n");
10346 return RESULT_SUCCESS;
10347 }
10348
10349 static const char pri_debug_help[] =
10350 "Usage: pri debug span <span>\n"
10351 " Enables debugging on a given PRI span\n";
10352
10353 static const char pri_no_debug_help[] =
10354 "Usage: pri no debug span <span>\n"
10355 " Disables debugging on a given PRI span\n";
10356
10357 static const char pri_really_debug_help[] =
10358 "Usage: pri intensive debug span <span>\n"
10359 " Enables debugging down to the Q.921 level\n";
10360
10361 static const char pri_show_span_help[] =
10362 "Usage: pri show span <span>\n"
10363 " Displays PRI Information on a given PRI span\n";
10364
10365 static const char pri_show_spans_help[] =
10366 "Usage: pri show spans\n"
10367 " Displays PRI Information\n";
10368
10369 static struct ast_cli_entry dahdi_pri_cli[] = {
10370 { { "pri", "debug", "span", NULL },
10371 handle_pri_debug, "Enables PRI debugging on a span",
10372 pri_debug_help, complete_span_4 },
10373
10374 { { "pri", "no", "debug", "span", NULL },
10375 handle_pri_no_debug, "Disables PRI debugging on a span",
10376 pri_no_debug_help, complete_span_5 },
10377
10378 { { "pri", "intense", "debug", "span", NULL },
10379 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
10380 pri_really_debug_help, complete_span_5 },
10381
10382 { { "pri", "show", "spans", NULL },
10383 handle_pri_show_spans, "Displays PRI Information",
10384 pri_show_spans_help },
10385
10386 { { "pri", "show", "span", NULL },
10387 handle_pri_show_span, "Displays PRI Information",
10388 pri_show_span_help, complete_span_4 },
10389
10390 { { "pri", "show", "debug", NULL },
10391 handle_pri_show_debug, "Displays current PRI debug settings" },
10392
10393 { { "pri", "set", "debug", "file", NULL },
10394 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
10395
10396 { { "pri", "unset", "debug", "file", NULL },
10397 handle_pri_set_debug_file, "Ends PRI debug output to file" },
10398
10399 #ifdef HAVE_PRI_VERSION
10400 { { "pri", "show", "version", NULL },
10401 handle_pri_version, "Displays version of libpri" },
10402 #endif
10403 };
10404
10405 #endif
10406
10407 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10408 {
10409 int channel;
10410
10411 if (argc != 4)
10412 return RESULT_SHOWUSAGE;
10413
10414 channel = atoi(argv[3]);
10415
10416 return dahdi_destroy_channel_bynum(channel);
10417 }
10418
10419 static void dahdi_softhangup_all(void)
10420 {
10421 struct dahdi_pvt *p;
10422 retry:
10423 ast_mutex_lock(&iflock);
10424 for (p = iflist; p; p = p->next) {
10425 ast_mutex_lock(&p->lock);
10426 if (p->owner && !p->restartpending) {
10427 if (ast_channel_trylock(p->owner)) {
10428 if (option_debug > 2)
10429 ast_verbose("Avoiding deadlock\n");
10430
10431 ast_mutex_unlock(&p->lock);
10432 ast_mutex_unlock(&iflock);
10433 goto retry;
10434 }
10435 if (option_debug > 2)
10436 ast_verbose("Softhanging up on %s\n", p->owner->name);
10437 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10438 p->restartpending = 1;
10439 num_restart_pending++;
10440 ast_channel_unlock(p->owner);
10441 }
10442 ast_mutex_unlock(&p->lock);
10443 }
10444 ast_mutex_unlock(&iflock);
10445 }
10446
10447 static int setup_dahdi(int reload);
10448 static int dahdi_restart(void)
10449 {
10450 #if defined(HAVE_PRI)
10451 int i, j;
10452 #endif
10453 int cancel_code;
10454 struct dahdi_pvt *p;
10455
10456 ast_mutex_lock(&restart_lock);
10457
10458 if (option_verbose)
10459 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10460 dahdi_softhangup_all();
10461 if (option_verbose > 3)
10462 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10463
10464 #if defined(HAVE_PRI)
10465 for (i = 0; i < NUM_SPANS; i++) {
10466 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10467 cancel_code = pthread_cancel(pris[i].master);
10468 pthread_kill(pris[i].master, SIGURG);
10469 if (option_debug > 3)
10470 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10471 pthread_join(pris[i].master, NULL);
10472 if (option_debug > 3)
10473 ast_verbose("Joined thread of span %d\n", i);
10474 }
10475 }
10476 #endif
10477
10478 ast_mutex_lock(&monlock);
10479 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10480 cancel_code = pthread_cancel(monitor_thread);
10481 pthread_kill(monitor_thread, SIGURG);
10482 if (option_debug > 3)
10483 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10484 pthread_join(monitor_thread, NULL);
10485 if (option_debug > 3)
10486 ast_verbose("Joined monitor thread\n");
10487 }
10488 monitor_thread = AST_PTHREADT_NULL;
10489
10490 ast_mutex_lock(&ss_thread_lock);
10491 while (ss_thread_count > 0) {
10492 int x = DAHDI_FLASH;
10493 if (option_debug > 2)
10494 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10495
10496 for (p = iflist; p; p = p->next) {
10497 if (p->owner)
10498 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10499 }
10500 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10501 }
10502
10503
10504 dahdi_softhangup_all();
10505 if (option_verbose > 3)
10506 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10507 destroy_all_channels();
10508 if (option_debug)
10509 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10510
10511 ast_mutex_unlock(&monlock);
10512
10513 #ifdef HAVE_PRI
10514 for (i = 0; i < NUM_SPANS; i++) {
10515 for (j = 0; j < NUM_DCHANS; j++)
10516 dahdi_close_pri_fd(&(pris[i]), j);
10517 }
10518
10519 memset(pris, 0, sizeof(pris));
10520 for (i = 0; i < NUM_SPANS; i++) {
10521 ast_mutex_init(&pris[i].lock);
10522 pris[i].offset = -1;
10523 pris[i].master = AST_PTHREADT_NULL;
10524 for (j = 0; j < NUM_DCHANS; j++)
10525 pris[i].fds[j] = -1;
10526 }
10527 pri_set_error(dahdi_pri_error);
10528 pri_set_message(dahdi_pri_message);
10529 #endif
10530
10531 if (setup_dahdi(2) != 0) {
10532 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10533 ast_mutex_unlock(&ss_thread_lock);
10534 return 1;
10535 }
10536 ast_mutex_unlock(&ss_thread_lock);
10537 ast_mutex_unlock(&restart_lock);
10538 return 0;
10539 }
10540
10541 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10542 {
10543 if (argc != 2) {
10544 return RESULT_SHOWUSAGE;
10545 }
10546
10547 if (dahdi_restart() != 0)
10548 return RESULT_FAILURE;
10549 return RESULT_SUCCESS;
10550 }
10551
10552 static int dahdi_show_channels(int fd, int argc, char **argv)
10553 {
10554 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10555 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10556 struct dahdi_pvt *tmp = NULL;
10557 char tmps[20] = "";
10558 ast_mutex_t *lock;
10559 struct dahdi_pvt *start;
10560 #ifdef HAVE_PRI
10561 int trunkgroup;
10562 struct dahdi_pri *pri = NULL;
10563 int x;
10564 #endif
10565
10566 lock = &iflock;
10567 start = iflist;
10568
10569 #ifdef HAVE_PRI
10570 if (argc == 4) {
10571 if ((trunkgroup = atoi(argv[3])) < 1)
10572 return RESULT_SHOWUSAGE;
10573 for (x = 0; x < NUM_SPANS; x++) {
10574 if (pris[x].trunkgroup == trunkgroup) {
10575 pri = pris + x;
10576 break;
10577 }
10578 }
10579 if (pri) {
10580 start = pri->crvs;
10581 lock = &pri->lock;
10582 } else {
10583 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10584 return RESULT_FAILURE;
10585 }
10586 } else
10587 #endif
10588 if (argc != 3)
10589 return RESULT_SHOWUSAGE;
10590
10591 ast_mutex_lock(lock);
10592 #ifdef HAVE_PRI
10593 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10594 #else
10595 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10596 #endif
10597
10598 tmp = start;
10599 while (tmp) {
10600 if (tmp->channel > 0) {
10601 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10602 } else
10603 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10604 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10605 tmp = tmp->next;
10606 }
10607 ast_mutex_unlock(lock);
10608 return RESULT_SUCCESS;
10609 #undef FORMAT
10610 #undef FORMAT2
10611 }
10612
10613 static int dahdi_show_channel(int fd, int argc, char **argv)
10614 {
10615 int channel;
10616 struct dahdi_pvt *tmp = NULL;
10617 struct dahdi_confinfo ci;
10618 struct dahdi_params ps;
10619 int x;
10620 ast_mutex_t *lock;
10621 struct dahdi_pvt *start;
10622 #ifdef HAVE_PRI
10623 char *c;
10624 int trunkgroup;
10625 struct dahdi_pri *pri=NULL;
10626 #endif
10627
10628 lock = &iflock;
10629 start = iflist;
10630
10631 if (argc != 4)
10632 return RESULT_SHOWUSAGE;
10633 #ifdef HAVE_PRI
10634 if ((c = strchr(argv[3], ':'))) {
10635 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
10636 return RESULT_SHOWUSAGE;
10637 if ((trunkgroup < 1) || (channel < 1))
10638 return RESULT_SHOWUSAGE;
10639 for (x = 0; x < NUM_SPANS; x++) {
10640 if (pris[x].trunkgroup == trunkgroup) {
10641 pri = pris + x;
10642 break;
10643 }
10644 }
10645 if (pri) {
10646 start = pri->crvs;
10647 lock = &pri->lock;
10648 } else {
10649 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10650 return RESULT_FAILURE;
10651 }
10652 } else
10653 #endif
10654 channel = atoi(argv[3]);
10655
10656 ast_mutex_lock(lock);
10657 tmp = start;
10658 while (tmp) {
10659 if (tmp->channel == channel) {
10660 #ifdef HAVE_PRI
10661 if (pri)
10662 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10663 else
10664 #endif
10665 ast_cli(fd, "Channel: %d\n", tmp->channel);
10666 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10667 ast_cli(fd, "Span: %d\n", tmp->span);
10668 ast_cli(fd, "Extension: %s\n", tmp->exten);
10669 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10670 ast_cli(fd, "Context: %s\n", tmp->context);
10671 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10672 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10673 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10674 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10675 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10676 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10677 ast_cli(fd, "Radio: %d\n", tmp->radio);
10678 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10679 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)" : "");
10680 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)" : "");
10681 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)" : "");
10682 ast_cli(fd, "Confno: %d\n", tmp->confno);
10683 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10684 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10685 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10686 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10687 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10688 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10689 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10690 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10691 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10692 if (tmp->master)
10693 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10694 for (x = 0; x < MAX_SLAVES; x++) {
10695 if (tmp->slaves[x])
10696 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10697 }
10698 #ifdef HAVE_PRI
10699 if (tmp->pri) {
10700 ast_cli(fd, "PRI Flags: ");
10701 if (tmp->resetting)
10702 ast_cli(fd, "Resetting ");
10703 if (tmp->call)
10704 ast_cli(fd, "Call ");
10705 if (tmp->bearer)
10706 ast_cli(fd, "Bearer ");
10707 ast_cli(fd, "\n");
10708 if (tmp->logicalspan)
10709 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10710 else
10711 ast_cli(fd, "PRI Logical Span: Implicit\n");
10712 }
10713
10714 #endif
10715 memset(&ci, 0, sizeof(ci));
10716 ps.channo = tmp->channel;
10717 if (tmp->subs[SUB_REAL].dfd > -1) {
10718 memset(&ci, 0, sizeof(ci));
10719 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10720 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10721 }
10722 #ifdef DAHDI_GETCONFMUTE
10723 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10724 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10725 }
10726 #endif
10727 memset(&ps, 0, sizeof(ps));
10728 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10729 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10730 } else {
10731 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10732 }
10733 }
10734 if (ISTRUNK(tmp)) {
10735 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
10736 if (!ast_strlen_zero(progzone))
10737 ast_cli(fd, "Progress Zone: %s\n", progzone);
10738 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
10739 if(tmp->busydetect) {
10740 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10741 if(tmp->busytonelength > 0) {
10742 ast_cli(fd, "Busy Pattern:\n");
10743 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10744 if (tmp->busyquietlength > 0)
10745 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10746 else
10747 ast_cli(fd, " -- Detect Tone Only\n");
10748 if(tmp->busyfuzziness > 0)
10749 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10750 }
10751 }
10752 }
10753 ast_mutex_unlock(lock);
10754 return RESULT_SUCCESS;
10755 }
10756 tmp = tmp->next;
10757 }
10758
10759 ast_cli(fd, "Unable to find given channel %d\n", channel);
10760 ast_mutex_unlock(lock);
10761 return RESULT_FAILURE;
10762 }
10763
10764 static char dahdi_show_cadences_usage[] =
10765 "Usage: dahdi show cadences\n"
10766 " Shows all cadences currently defined\n";
10767
10768 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10769 {
10770 int i, j;
10771 for (i = 0; i < num_cadence; i++) {
10772 char output[1024];
10773 char tmp[16], tmp2[64];
10774 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10775 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10776
10777 for (j = 0; j < 16; j++) {
10778 if (cadences[i].ringcadence[j] == 0)
10779 break;
10780 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10781 if (cidrings[i] * 2 - 1 == j)
10782 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10783 else
10784 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10785 if (j != 0)
10786 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10787 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10788 }
10789 ast_cli(fd,"%s\n",output);
10790 }
10791 return 0;
10792 }
10793
10794
10795 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10796 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10797 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10798
10799 int span;
10800 int res;
10801 char alarms[50];
10802
10803 int ctl;
10804 struct dahdi_spaninfo s;
10805
10806 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
10807 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
10808 ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
10809 return RESULT_FAILURE;
10810 }
10811 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10812
10813 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10814 s.spanno = span;
10815 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10816 if (res) {
10817 continue;
10818 }
10819 alarms[0] = '\0';
10820 if (s.alarms > 0) {
10821 if (s.alarms & DAHDI_ALARM_BLUE)
10822 strcat(alarms, "BLU/");
10823 if (s.alarms & DAHDI_ALARM_YELLOW)
10824 strcat(alarms, "YEL/");
10825 if (s.alarms & DAHDI_ALARM_RED)
10826 strcat(alarms, "RED/");
10827 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10828 strcat(alarms, "LB/");
10829 if (s.alarms & DAHDI_ALARM_RECOVER)
10830 strcat(alarms, "REC/");
10831 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10832 strcat(alarms, "NOP/");
10833 if (!strlen(alarms))
10834 strcat(alarms, "UUU/");
10835 if (strlen(alarms)) {
10836
10837 alarms[strlen(alarms) - 1] = '\0';
10838 }
10839 } else {
10840 if (s.numchans)
10841 strcpy(alarms, "OK");
10842 else
10843 strcpy(alarms, "UNCONFIGURED");
10844 }
10845
10846 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10847 }
10848 close(ctl);
10849
10850 return RESULT_SUCCESS;
10851 #undef FORMAT
10852 #undef FORMAT2
10853 }
10854
10855 static char show_channels_usage[] =
10856 "Usage: dahdi show channels\n"
10857 " Shows a list of available channels\n";
10858
10859 static char show_channel_usage[] =
10860 "Usage: dahdi show channel <chan num>\n"
10861 " Detailed information about a given channel\n";
10862
10863 static char dahdi_show_status_usage[] =
10864 "Usage: dahdi show status\n"
10865 " Shows a list of DAHDI cards with status\n";
10866
10867 static char destroy_channel_usage[] =
10868 "Usage: dahdi destroy channel <chan num>\n"
10869 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10870
10871 static char dahdi_restart_usage[] =
10872 "Usage: dahdi restart\n"
10873 " Restarts the DAHDI channels: destroys them all and then\n"
10874 " re-reads them from chan_dahdi.conf.\n"
10875 " Note that this will STOP any running CALL on DAHDI channels.\n"
10876 "";
10877
10878 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10879 { "zap", "show", "cadences", NULL },
10880 handle_dahdi_show_cadences, NULL,
10881 NULL };
10882
10883 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10884 { "zap", "show", "channels", NULL },
10885 dahdi_show_channels, NULL,
10886 NULL };
10887
10888 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10889 { "zap", "show", "channel", NULL },
10890 dahdi_show_channel, NULL,
10891 NULL };
10892
10893 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10894 { "zap", "destroy", "channel", NULL },
10895 dahdi_destroy_channel, NULL,
10896 NULL };
10897
10898 static struct ast_cli_entry cli_zap_restart_deprecated = {
10899 { "zap", "restart", NULL },
10900 dahdi_restart_cmd, NULL,
10901 NULL };
10902
10903 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10904 { "zap", "show", "status", NULL },
10905 dahdi_show_status, NULL,
10906 NULL };
10907
10908 static struct ast_cli_entry dahdi_cli[] = {
10909 { { "dahdi", "show", "cadences", NULL },
10910 handle_dahdi_show_cadences, "List cadences",
10911 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10912
10913 { { "dahdi", "show", "channels", NULL},
10914 dahdi_show_channels, "Show active DAHDI channels",
10915 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10916
10917 { { "dahdi", "show", "channel", NULL},
10918 dahdi_show_channel, "Show information on a channel",
10919 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10920
10921 { { "dahdi", "destroy", "channel", NULL},
10922 dahdi_destroy_channel, "Destroy a channel",
10923 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10924
10925 { { "dahdi", "restart", NULL},
10926 dahdi_restart_cmd, "Fully restart DAHDI channels",
10927 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10928
10929 { { "dahdi", "show", "status", NULL},
10930 dahdi_show_status, "Show all DAHDI cards status",
10931 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10932 };
10933
10934 #define TRANSFER 0
10935 #define HANGUP 1
10936
10937 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10938 {
10939 if (p) {
10940 switch (mode) {
10941 case TRANSFER:
10942 p->fake_event = DAHDI_EVENT_WINKFLASH;
10943 break;
10944 case HANGUP:
10945 p->fake_event = DAHDI_EVENT_ONHOOK;
10946 break;
10947 default:
10948 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10949 }
10950 }
10951 return 0;
10952 }
10953 static struct dahdi_pvt *find_channel(int channel)
10954 {
10955 struct dahdi_pvt *p = iflist;
10956 while (p) {
10957 if (p->channel == channel) {
10958 break;
10959 }
10960 p = p->next;
10961 }
10962 return p;
10963 }
10964
10965 #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)
10966 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10967
10968 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10969 {
10970 struct dahdi_pvt *p = NULL;
10971 const char *channel = local_astman_header(m, "Channel", zap_mode);
10972
10973 if (ast_strlen_zero(channel)) {
10974 astman_send_error(s, m, "No channel specified");
10975 return 0;
10976 }
10977 if (!(p = find_channel(atoi(channel)))) {
10978 astman_send_error(s, m, "No such channel");
10979 return 0;
10980 }
10981 p->dnd = dnd;
10982 local_astman_ack(s, m, "DND", zap_mode);
10983
10984 return 0;
10985 }
10986
10987 static int zap_action_dndon(struct mansession *s, const struct message *m)
10988 {
10989 return __action_dnd(s, m, 1, 1);
10990 }
10991
10992 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10993 {
10994 return __action_dnd(s, m, 0, 1);
10995 }
10996
10997 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10998 {
10999 return __action_dnd(s, m, 1, 0);
11000 }
11001
11002 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
11003 {
11004 return __action_dnd(s, m, 0, 0);
11005 }
11006
11007 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
11008 {
11009 struct dahdi_pvt *p = NULL;
11010 const char *channel = local_astman_header(m, "Channel", zap_mode);
11011
11012 if (ast_strlen_zero(channel)) {
11013 astman_send_error(s, m, "No channel specified");
11014 return 0;
11015 }
11016 if (!(p = find_channel(atoi(channel)))) {
11017 astman_send_error(s, m, "No such channel");
11018 return 0;
11019 }
11020 dahdi_fake_event(p,TRANSFER);
11021 local_astman_ack(s, m, "Transfer", zap_mode);
11022
11023 return 0;
11024 }
11025
11026 static int zap_action_transfer(struct mansession *s, const struct message *m)
11027 {
11028 return __action_transfer(s, m, 1);
11029 }
11030
11031 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
11032 {
11033 return __action_transfer(s, m, 0);
11034 }
11035
11036 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
11037 {
11038 struct dahdi_pvt *p = NULL;
11039 const char *channel = local_astman_header(m, "Channel", zap_mode);
11040
11041 if (ast_strlen_zero(channel)) {
11042 astman_send_error(s, m, "No channel specified");
11043 return 0;
11044 }
11045 if (!(p = find_channel(atoi(channel)))) {
11046 astman_send_error(s, m, "No such channel");
11047 return 0;
11048 }
11049 dahdi_fake_event(p, HANGUP);
11050 local_astman_ack(s, m, "Hangup", zap_mode);
11051 return 0;
11052 }
11053
11054 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
11055 {
11056 return __action_transferhangup(s, m, 1);
11057 }
11058
11059 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
11060 {
11061 return __action_transferhangup(s, m, 0);
11062 }
11063
11064 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
11065 {
11066 struct dahdi_pvt *p = NULL;
11067 const char *channel = local_astman_header(m, "Channel", zap_mode);
11068 const char *number = astman_get_header(m, "Number");
11069 int i;
11070
11071 if (ast_strlen_zero(channel)) {
11072 astman_send_error(s, m, "No channel specified");
11073 return 0;
11074 }
11075 if (ast_strlen_zero(number)) {
11076 astman_send_error(s, m, "No number specified");
11077 return 0;
11078 }
11079 if (!(p = find_channel(atoi(channel)))) {
11080 astman_send_error(s, m, "No such channel");
11081 return 0;
11082 }
11083 if (!p->owner) {
11084 astman_send_error(s, m, "Channel does not have an owner");
11085 return 0;
11086 }
11087 for (i = 0; i < strlen(number); i++) {
11088 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
11089
11090 dahdi_queue_frame(p, &f, NULL);
11091 }
11092 local_astman_ack(s, m, "DialOffHook", zap_mode);
11093
11094 return 0;
11095 }
11096
11097 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
11098 {
11099 return __action_dialoffhook(s, m, 1);
11100 }
11101
11102 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
11103 {
11104 return __action_dialoffhook(s, m, 0);
11105 }
11106
11107 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
11108 {
11109 struct dahdi_pvt *tmp = NULL;
11110 const char *id = astman_get_header(m, "ActionID");
11111 char idText[256] = "";
11112
11113 local_astman_ack(s, m, " channel status will follow", zap_mode);
11114 if (!ast_strlen_zero(id))
11115 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
11116
11117 ast_mutex_lock(&iflock);
11118
11119 tmp = iflist;
11120 while (tmp) {
11121 if (tmp->channel > 0) {
11122 int alarm = get_alarms(tmp);
11123 astman_append(s,
11124 "Event: %sShowChannels\r\n"
11125 "Channel: %d\r\n"
11126 "Signalling: %s\r\n"
11127 "Context: %s\r\n"
11128 "DND: %s\r\n"
11129 "Alarm: %s\r\n"
11130 "%s"
11131 "\r\n",
11132 dahdi_chan_name,
11133 tmp->channel, sig2str(tmp->sig), tmp->context,
11134 tmp->dnd ? "Enabled" : "Disabled",
11135 alarm2str(alarm), idText);
11136 }
11137
11138 tmp = tmp->next;
11139 }
11140
11141 ast_mutex_unlock(&iflock);
11142
11143 astman_append(s,
11144 "Event: %sShowChannelsComplete\r\n"
11145 "%s"
11146 "\r\n",
11147 dahdi_chan_name,
11148 idText);
11149 return 0;
11150 }
11151
11152 static int zap_action_showchannels(struct mansession *s, const struct message *m)
11153 {
11154 return __action_showchannels(s, m, 1);
11155 }
11156
11157 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
11158 {
11159 return __action_showchannels(s, m, 0);
11160 }
11161
11162 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
11163 {
11164 if (dahdi_restart() != 0) {
11165 if (zap_mode) {
11166 astman_send_error(s, m, "Failed to restart Zap");
11167 } else {
11168 astman_send_error(s, m, "Failed to restart DAHDI");
11169 }
11170 return 1;
11171 }
11172 local_astman_ack(s, m, "Restart: Success", zap_mode);
11173 return 0;
11174 }
11175
11176 static int zap_action_restart(struct mansession *s, const struct message *m)
11177 {
11178 return __action_restart(s, m, 1);
11179 }
11180
11181 static int dahdi_action_restart(struct mansession *s, const struct message *m)
11182 {
11183 return __action_restart(s, m, 0);
11184 }
11185
11186 #define local_astman_unregister(a) do { \
11187 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11188 ast_manager_unregister("DAHDI" a); \
11189 } \
11190 ast_manager_unregister("Zap" a); \
11191 } while (0)
11192
11193 static int __unload_module(void)
11194 {
11195 struct dahdi_pvt *p;
11196
11197 #ifdef HAVE_PRI
11198 int i, j;
11199 for (i = 0; i < NUM_SPANS; i++) {
11200 if (pris[i].master != AST_PTHREADT_NULL)
11201 pthread_cancel(pris[i].master);
11202 }
11203 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11204
11205 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11206 ast_unregister_application(dahdi_send_keypad_facility_app);
11207 }
11208 ast_unregister_application(zap_send_keypad_facility_app);
11209 #endif
11210 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11211 local_astman_unregister("DialOffHook");
11212 local_astman_unregister("Hangup");
11213 local_astman_unregister("Transfer");
11214 local_astman_unregister("DNDoff");
11215 local_astman_unregister("DNDon");
11216 local_astman_unregister("ShowChannels");
11217 local_astman_unregister("Restart");
11218 ast_channel_unregister(chan_tech);
11219 ast_mutex_lock(&iflock);
11220
11221 p = iflist;
11222 while (p) {
11223 if (p->owner)
11224 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
11225 p = p->next;
11226 }
11227 ast_mutex_unlock(&iflock);
11228 ast_mutex_lock(&monlock);
11229 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11230 pthread_cancel(monitor_thread);
11231 pthread_kill(monitor_thread, SIGURG);
11232 pthread_join(monitor_thread, NULL);
11233 }
11234 monitor_thread = AST_PTHREADT_STOP;
11235 ast_mutex_unlock(&monlock);
11236
11237 destroy_all_channels();
11238 #ifdef HAVE_PRI
11239 for (i = 0; i < NUM_SPANS; i++) {
11240 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
11241 pthread_join(pris[i].master, NULL);
11242 for (j = 0; j < NUM_DCHANS; j++) {
11243 dahdi_close_pri_fd(&(pris[i]), j);
11244 }
11245 }
11246 #endif
11247 ast_cond_destroy(&ss_thread_complete);
11248 return 0;
11249 }
11250
11251 static int unload_module(void)
11252 {
11253 #ifdef HAVE_PRI
11254 int y;
11255 for (y = 0; y < NUM_SPANS; y++)
11256 ast_mutex_destroy(&pris[y].lock);
11257 #endif
11258 return __unload_module();
11259 }
11260
11261 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
11262 {
11263 char *c, *chan;
11264 int x, start, finish;
11265 struct dahdi_pvt *tmp;
11266 #ifdef HAVE_PRI
11267 struct dahdi_pri *pri;
11268 int trunkgroup, y;
11269 #endif
11270
11271 if ((reload == 0) && (conf->chan.sig < 0)) {
11272 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
11273 return -1;
11274 }
11275
11276 c = ast_strdupa(value);
11277
11278 #ifdef HAVE_PRI
11279 pri = NULL;
11280 if (iscrv) {
11281 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
11282 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
11283 return -1;
11284 }
11285 if (trunkgroup < 1) {
11286 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
11287 return -1;
11288 }
11289 c += y;
11290 for (y = 0; y < NUM_SPANS; y++) {
11291 if (pris[y].trunkgroup == trunkgroup) {
11292 pri = pris + y;
11293 break;
11294 }
11295 }
11296 if (!pri) {
11297 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
11298 return -1;
11299 }
11300 }
11301 #endif
11302
11303 while ((chan = strsep(&c, ","))) {
11304 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
11305
11306 } else if (sscanf(chan, "%30d", &start)) {
11307
11308 finish = start;
11309 } else if (!strcasecmp(chan, "pseudo")) {
11310 finish = start = CHAN_PSEUDO;
11311 if (found_pseudo)
11312 *found_pseudo = 1;
11313 } else {
11314 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
11315 return -1;
11316 }
11317 if (finish < start) {
11318 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
11319 x = finish;
11320 finish = start;
11321 start = x;
11322 }
11323
11324 for (x = start; x <= finish; x++) {
11325 #ifdef HAVE_PRI
11326 tmp = mkintf(x, conf, pri, reload);
11327 #else
11328 tmp = mkintf(x, conf, NULL, reload);
11329 #endif
11330
11331 if (tmp) {
11332 if (option_verbose > 2) {
11333 #ifdef HAVE_PRI
11334 if (pri)
11335 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
11336 else
11337 #endif
11338 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
11339 }
11340 } else {
11341 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
11342 (reload == 1) ? "reconfigure" : "register", value);
11343 return -1;
11344 }
11345 }
11346 }
11347
11348 return 0;
11349 }
11350
11351
11352
11353 #define MAX_CHANLIST_LEN 80
11354 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
11355 {
11356 struct dahdi_pvt *tmp;
11357 int y;
11358 int found_pseudo = 0;
11359 char dahdichan[MAX_CHANLIST_LEN] = {};
11360
11361 for (; v; v = v->next) {
11362 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11363 continue;
11364
11365
11366 if (!strcasecmp(v->name, "channel")
11367 #ifdef HAVE_PRI
11368 || !strcasecmp(v->name, "crv")
11369 #endif
11370 ) {
11371 int iscrv;
11372 if (skipchannels)
11373 continue;
11374 iscrv = !strcasecmp(v->name, "crv");
11375 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11376 return -1;
11377 } else if (!strcasecmp(v->name, "buffers")) {
11378 int res;
11379 char policy[21] = "";
11380
11381 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
11382 if (res != 2) {
11383 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11384 confp->chan.buf_no = numbufs;
11385 continue;
11386 }
11387 if (confp->chan.buf_no < 0)
11388 confp->chan.buf_no = numbufs;
11389 if (!strcasecmp(policy, "full")) {
11390 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11391 } else if (!strcasecmp(policy, "immediate")) {
11392 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11393 } else {
11394 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11395 }
11396 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11397 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11398 if (v->name[0] == 'z' || v->name[0] == 'Z') {
11399 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11400 }
11401 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11402 if (ast_true(v->value))
11403 confp->chan.usedistinctiveringdetection = 1;
11404 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11405 if (ast_true(v->value))
11406 distinctiveringaftercid = 1;
11407 } else if (!strcasecmp(v->name, "dring1context")) {
11408 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11409 } else if (!strcasecmp(v->name, "dring2context")) {
11410 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11411 } else if (!strcasecmp(v->name, "dring3context")) {
11412 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11413 } else if (!strcasecmp(v->name, "dring1")) {
11414 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11415 } else if (!strcasecmp(v->name, "dring2")) {
11416 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11417 } else if (!strcasecmp(v->name, "dring3")) {
11418 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11419 } else if (!strcasecmp(v->name, "usecallerid")) {
11420 confp->chan.use_callerid = ast_true(v->value);
11421 } else if (!strcasecmp(v->name, "cidsignalling")) {
11422 if (!strcasecmp(v->value, "bell"))
11423 confp->chan.cid_signalling = CID_SIG_BELL;
11424 else if (!strcasecmp(v->value, "v23"))
11425 confp->chan.cid_signalling = CID_SIG_V23;
11426 else if (!strcasecmp(v->value, "dtmf"))
11427 confp->chan.cid_signalling = CID_SIG_DTMF;
11428 else if (!strcasecmp(v->value, "smdi"))
11429 confp->chan.cid_signalling = CID_SIG_SMDI;
11430 else if (!strcasecmp(v->value, "v23_jp"))
11431 confp->chan.cid_signalling = CID_SIG_V23_JP;
11432 else if (ast_true(v->value))
11433 confp->chan.cid_signalling = CID_SIG_BELL;
11434 } else if (!strcasecmp(v->name, "cidstart")) {
11435 if (!strcasecmp(v->value, "ring"))
11436 confp->chan.cid_start = CID_START_RING;
11437 else if (!strcasecmp(v->value, "polarity"))
11438 confp->chan.cid_start = CID_START_POLARITY;
11439 else if (ast_true(v->value))
11440 confp->chan.cid_start = CID_START_RING;
11441 } else if (!strcasecmp(v->name, "threewaycalling")) {
11442 confp->chan.threewaycalling = ast_true(v->value);
11443 } else if (!strcasecmp(v->name, "cancallforward")) {
11444 confp->chan.cancallforward = ast_true(v->value);
11445 } else if (!strcasecmp(v->name, "relaxdtmf")) {
11446 if (ast_true(v->value))
11447 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11448 else
11449 confp->chan.dtmfrelax = 0;
11450 } else if (!strcasecmp(v->name, "mailbox")) {
11451 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11452 } else if (!strcasecmp(v->name, "hasvoicemail")) {
11453 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11454 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11455 }
11456 } else if (!strcasecmp(v->name, "adsi")) {
11457 confp->chan.adsi = ast_true(v->value);
11458 } else if (!strcasecmp(v->name, "usesmdi")) {
11459 confp->chan.use_smdi = ast_true(v->value);
11460 } else if (!strcasecmp(v->name, "smdiport")) {
11461 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11462 } else if (!strcasecmp(v->name, "transfer")) {
11463 confp->chan.transfer = ast_true(v->value);
11464 } else if (!strcasecmp(v->name, "canpark")) {
11465 confp->chan.canpark = ast_true(v->value);
11466 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11467 confp->chan.echocanbridged = ast_true(v->value);
11468 } else if (!strcasecmp(v->name, "busydetect")) {
11469 confp->chan.busydetect = ast_true(v->value);
11470 } else if (!strcasecmp(v->name, "busycount")) {
11471 confp->chan.busycount = atoi(v->value);
11472 } else if (!strcasecmp(v->name, "silencethreshold")) {
11473 confp->chan.silencethreshold = atoi(v->value);
11474 } else if (!strcasecmp(v->name, "busycompare")) {
11475 confp->chan.busycompare = ast_true(v->value);
11476 } else if (!strcasecmp(v->name, "busypattern")) {
11477 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
11478 if (count == 1)
11479 confp->chan.busyquietlength = 0;
11480 else if (count < 1)
11481 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
11482 } else if (!strcasecmp(v->name, "busyfuzziness")) {
11483 confp->chan.busyfuzziness = atoi(v->value);
11484 } else if (!strcasecmp(v->name, "callprogress")) {
11485 if (ast_true(v->value))
11486 confp->chan.callprogress |= 1;
11487 else
11488 confp->chan.callprogress &= ~1;
11489 } else if (!strcasecmp(v->name, "faxdetect")) {
11490 if (!strcasecmp(v->value, "incoming")) {
11491 confp->chan.callprogress |= 4;
11492 confp->chan.callprogress &= ~2;
11493 } else if (!strcasecmp(v->value, "outgoing")) {
11494 confp->chan.callprogress &= ~4;
11495 confp->chan.callprogress |= 2;
11496 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11497 confp->chan.callprogress |= 6;
11498 else
11499 confp->chan.callprogress &= ~6;
11500 } else if (!strcasecmp(v->name, "echocancel")) {
11501 if (!ast_strlen_zero(v->value)) {
11502 y = atoi(v->value);
11503 } else
11504 y = 0;
11505 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11506 confp->chan.echocancel = y;
11507 else {
11508 confp->chan.echocancel = ast_true(v->value);
11509 if (confp->chan.echocancel)
11510 confp->chan.echocancel=128;
11511 }
11512 } else if (!strcasecmp(v->name, "echotraining")) {
11513 if (sscanf(v->value, "%30d", &y) == 1) {
11514 if ((y < 10) || (y > 4000)) {
11515 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
11516 } else {
11517 confp->chan.echotraining = y;
11518 }
11519 } else if (ast_true(v->value)) {
11520 confp->chan.echotraining = 400;
11521 } else
11522 confp->chan.echotraining = 0;
11523 } else if (!strcasecmp(v->name, "hidecallerid")) {
11524 confp->chan.hidecallerid = ast_true(v->value);
11525 } else if (!strcasecmp(v->name, "hidecalleridname")) {
11526 confp->chan.hidecalleridname = ast_true(v->value);
11527 } else if (!strcasecmp(v->name, "pulsedial")) {
11528 confp->chan.pulse = ast_true(v->value);
11529 } else if (!strcasecmp(v->name, "callreturn")) {
11530 confp->chan.callreturn = ast_true(v->value);
11531 } else if (!strcasecmp(v->name, "callwaiting")) {
11532 confp->chan.callwaiting = ast_true(v->value);
11533 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11534 confp->chan.callwaitingcallerid = ast_true(v->value);
11535 } else if (!strcasecmp(v->name, "context")) {
11536 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11537 } else if (!strcasecmp(v->name, "language")) {
11538 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11539 } else if (!strcasecmp(v->name, "progzone")) {
11540 ast_copy_string(progzone, v->value, sizeof(progzone));
11541 } else if (!strcasecmp(v->name, "mohinterpret")
11542 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11543 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11544 } else if (!strcasecmp(v->name, "mohsuggest")) {
11545 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11546 } else if (!strcasecmp(v->name, "stripmsd")) {
11547 confp->chan.stripmsd = atoi(v->value);
11548 } else if (!strcasecmp(v->name, "jitterbuffers")) {
11549 numbufs = atoi(v->value);
11550 } else if (!strcasecmp(v->name, "group")) {
11551 confp->chan.group = ast_get_group(v->value);
11552 } else if (!strcasecmp(v->name, "callgroup")) {
11553 confp->chan.callgroup = ast_get_group(v->value);
11554 } else if (!strcasecmp(v->name, "pickupgroup")) {
11555 confp->chan.pickupgroup = ast_get_group(v->value);
11556 } else if (!strcasecmp(v->name, "immediate")) {
11557 confp->chan.immediate = ast_true(v->value);
11558 } else if (!strcasecmp(v->name, "transfertobusy")) {
11559 confp->chan.transfertobusy = ast_true(v->value);
11560 } else if (!strcasecmp(v->name, "rxgain")) {
11561 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
11562 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11563 }
11564 } else if (!strcasecmp(v->name, "txgain")) {
11565 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
11566 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11567 }
11568 } else if (!strcasecmp(v->name, "tonezone")) {
11569 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
11570 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11571 }
11572 } else if (!strcasecmp(v->name, "callerid")) {
11573 if (!strcasecmp(v->value, "asreceived")) {
11574 confp->chan.cid_num[0] = '\0';
11575 confp->chan.cid_name[0] = '\0';
11576 } else {
11577 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11578 }
11579 } else if (!strcasecmp(v->name, "fullname")) {
11580 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11581 } else if (!strcasecmp(v->name, "cid_number")) {
11582 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11583 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11584 confp->chan.dahditrcallerid = ast_true(v->value);
11585 if (strstr(v->name, "zap")) {
11586 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11587 }
11588 } else if (!strcasecmp(v->name, "restrictcid")) {
11589 confp->chan.restrictcid = ast_true(v->value);
11590 } else if (!strcasecmp(v->name, "usecallingpres")) {
11591 confp->chan.use_callingpres = ast_true(v->value);
11592 } else if (!strcasecmp(v->name, "accountcode")) {
11593 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11594 } else if (!strcasecmp(v->name, "amaflags")) {
11595 y = ast_cdr_amaflags2int(v->value);
11596 if (y < 0)
11597 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11598 else
11599 confp->chan.amaflags = y;
11600 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11601 confp->chan.polarityonanswerdelay = atoi(v->value);
11602 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11603 confp->chan.answeronpolarityswitch = ast_true(v->value);
11604 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11605 confp->chan.hanguponpolarityswitch = ast_true(v->value);
11606 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11607 confp->chan.sendcalleridafter = atoi(v->value);
11608 } else if (reload != 1) {
11609 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
11610 confp->chan.outsigmod = -1;
11611 if (!strcasecmp(v->value, "em")) {
11612 confp->chan.sig = SIG_EM;
11613 } else if (!strcasecmp(v->value, "em_e1")) {
11614 confp->chan.sig = SIG_EM_E1;
11615 } else if (!strcasecmp(v->value, "em_w")) {
11616 confp->chan.sig = SIG_EMWINK;
11617 confp->chan.radio = 0;
11618 } else if (!strcasecmp(v->value, "fxs_ls")) {
11619 confp->chan.sig = SIG_FXSLS;
11620 confp->chan.radio = 0;
11621 } else if (!strcasecmp(v->value, "fxs_gs")) {
11622 confp->chan.sig = SIG_FXSGS;
11623 confp->chan.radio = 0;
11624 } else if (!strcasecmp(v->value, "fxs_ks")) {
11625 confp->chan.sig = SIG_FXSKS;
11626 confp->chan.radio = 0;
11627 } else if (!strcasecmp(v->value, "fxo_ls")) {
11628 confp->chan.sig = SIG_FXOLS;
11629 confp->chan.radio = 0;
11630 } else if (!strcasecmp(v->value, "fxo_gs")) {
11631 confp->chan.sig = SIG_FXOGS;
11632 confp->chan.radio = 0;
11633 } else if (!strcasecmp(v->value, "fxo_ks")) {
11634 confp->chan.sig = SIG_FXOKS;
11635 confp->chan.radio = 0;
11636 } else if (!strcasecmp(v->value, "fxs_rx")) {
11637 confp->chan.sig = SIG_FXSKS;
11638 confp->chan.radio = 1;
11639 } else if (!strcasecmp(v->value, "fxo_rx")) {
11640 confp->chan.sig = SIG_FXOLS;
11641 confp->chan.radio = 1;
11642 } else if (!strcasecmp(v->value, "fxs_tx")) {
11643 confp->chan.sig = SIG_FXSLS;
11644 confp->chan.radio = 1;
11645 } else if (!strcasecmp(v->value, "fxo_tx")) {
11646 confp->chan.sig = SIG_FXOGS;
11647 confp->chan.radio = 1;
11648 } else if (!strcasecmp(v->value, "em_rx")) {
11649 confp->chan.sig = SIG_EM;
11650 confp->chan.radio = 1;
11651 } else if (!strcasecmp(v->value, "em_tx")) {
11652 confp->chan.sig = SIG_EM;
11653 confp->chan.radio = 1;
11654 } else if (!strcasecmp(v->value, "em_rxtx")) {
11655 confp->chan.sig = SIG_EM;
11656 confp->chan.radio = 2;
11657 } else if (!strcasecmp(v->value, "em_txrx")) {
11658 confp->chan.sig = SIG_EM;
11659 confp->chan.radio = 2;
11660 } else if (!strcasecmp(v->value, "sf")) {
11661 confp->chan.sig = SIG_SF;
11662 confp->chan.radio = 0;
11663 } else if (!strcasecmp(v->value, "sf_w")) {
11664 confp->chan.sig = SIG_SFWINK;
11665 confp->chan.radio = 0;
11666 } else if (!strcasecmp(v->value, "sf_featd")) {
11667 confp->chan.sig = SIG_FEATD;
11668 confp->chan.radio = 0;
11669 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11670 confp->chan.sig = SIG_FEATDMF;
11671 confp->chan.radio = 0;
11672 } else if (!strcasecmp(v->value, "sf_featb")) {
11673 confp->chan.sig = SIG_SF_FEATB;
11674 confp->chan.radio = 0;
11675 } else if (!strcasecmp(v->value, "sf")) {
11676 confp->chan.sig = SIG_SF;
11677 confp->chan.radio = 0;
11678 } else if (!strcasecmp(v->value, "sf_rx")) {
11679 confp->chan.sig = SIG_SF;
11680 confp->chan.radio = 1;
11681 } else if (!strcasecmp(v->value, "sf_tx")) {
11682 confp->chan.sig = SIG_SF;
11683 confp->chan.radio = 1;
11684 } else if (!strcasecmp(v->value, "sf_rxtx")) {
11685 confp->chan.sig = SIG_SF;
11686 confp->chan.radio = 2;
11687 } else if (!strcasecmp(v->value, "sf_txrx")) {
11688 confp->chan.sig = SIG_SF;
11689 confp->chan.radio = 2;
11690 } else if (!strcasecmp(v->value, "featd")) {
11691 confp->chan.sig = SIG_FEATD;
11692 confp->chan.radio = 0;
11693 } else if (!strcasecmp(v->value, "featdmf")) {
11694 confp->chan.sig = SIG_FEATDMF;
11695 confp->chan.radio = 0;
11696 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11697 confp->chan.sig = SIG_FEATDMF_TA;
11698 confp->chan.radio = 0;
11699 } else if (!strcasecmp(v->value, "e911")) {
11700 confp->chan.sig = SIG_E911;
11701 confp->chan.radio = 0;
11702 } else if (!strcasecmp(v->value, "fgccama")) {
11703 confp->chan.sig = SIG_FGC_CAMA;
11704 confp->chan.radio = 0;
11705 } else if (!strcasecmp(v->value, "fgccamamf")) {
11706 confp->chan.sig = SIG_FGC_CAMAMF;
11707 confp->chan.radio = 0;
11708 } else if (!strcasecmp(v->value, "featb")) {
11709 confp->chan.sig = SIG_FEATB;
11710 confp->chan.radio = 0;
11711 #ifdef HAVE_PRI
11712 } else if (!strcasecmp(v->value, "pri_net")) {
11713 confp->chan.radio = 0;
11714 confp->chan.sig = SIG_PRI;
11715 confp->pri.nodetype = PRI_NETWORK;
11716 } else if (!strcasecmp(v->value, "pri_cpe")) {
11717 confp->chan.sig = SIG_PRI;
11718 confp->chan.radio = 0;
11719 confp->pri.nodetype = PRI_CPE;
11720 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11721 confp->chan.sig = SIG_GR303FXOKS;
11722 confp->chan.radio = 0;
11723 confp->pri.nodetype = PRI_NETWORK;
11724 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11725 confp->chan.sig = SIG_GR303FXSKS;
11726 confp->chan.radio = 0;
11727 confp->pri.nodetype = PRI_CPE;
11728 #endif
11729 } else {
11730 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11731 }
11732 } else if (!strcasecmp(v->name, "outsignalling")) {
11733 if (!strcasecmp(v->value, "em")) {
11734 confp->chan.outsigmod = SIG_EM;
11735 } else if (!strcasecmp(v->value, "em_e1")) {
11736 confp->chan.outsigmod = SIG_EM_E1;
11737 } else if (!strcasecmp(v->value, "em_w")) {
11738 confp->chan.outsigmod = SIG_EMWINK;
11739 } else if (!strcasecmp(v->value, "sf")) {
11740 confp->chan.outsigmod = SIG_SF;
11741 } else if (!strcasecmp(v->value, "sf_w")) {
11742 confp->chan.outsigmod = SIG_SFWINK;
11743 } else if (!strcasecmp(v->value, "sf_featd")) {
11744 confp->chan.outsigmod = SIG_FEATD;
11745 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11746 confp->chan.outsigmod = SIG_FEATDMF;
11747 } else if (!strcasecmp(v->value, "sf_featb")) {
11748 confp->chan.outsigmod = SIG_SF_FEATB;
11749 } else if (!strcasecmp(v->value, "sf")) {
11750 confp->chan.outsigmod = SIG_SF;
11751 } else if (!strcasecmp(v->value, "featd")) {
11752 confp->chan.outsigmod = SIG_FEATD;
11753 } else if (!strcasecmp(v->value, "featdmf")) {
11754 confp->chan.outsigmod = SIG_FEATDMF;
11755 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11756 confp->chan.outsigmod = SIG_FEATDMF_TA;
11757 } else if (!strcasecmp(v->value, "e911")) {
11758 confp->chan.outsigmod = SIG_E911;
11759 } else if (!strcasecmp(v->value, "fgccama")) {
11760 confp->chan.outsigmod = SIG_FGC_CAMA;
11761 } else if (!strcasecmp(v->value, "fgccamamf")) {
11762 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11763 } else if (!strcasecmp(v->value, "featb")) {
11764 confp->chan.outsigmod = SIG_FEATB;
11765 } else {
11766 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11767 }
11768 #ifdef HAVE_PRI
11769 } else if (!strcasecmp(v->name, "pridialplan")) {
11770 if (!strcasecmp(v->value, "national")) {
11771 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11772 } else if (!strcasecmp(v->value, "unknown")) {
11773 confp->pri.dialplan = PRI_UNKNOWN + 1;
11774 } else if (!strcasecmp(v->value, "private")) {
11775 confp->pri.dialplan = PRI_PRIVATE + 1;
11776 } else if (!strcasecmp(v->value, "international")) {
11777 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11778 } else if (!strcasecmp(v->value, "local")) {
11779 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11780 } else if (!strcasecmp(v->value, "dynamic")) {
11781 confp->pri.dialplan = -1;
11782 } else {
11783 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11784 }
11785 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11786 if (!strcasecmp(v->value, "national")) {
11787 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11788 } else if (!strcasecmp(v->value, "unknown")) {
11789 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11790 } else if (!strcasecmp(v->value, "private")) {
11791 confp->pri.localdialplan = PRI_PRIVATE + 1;
11792 } else if (!strcasecmp(v->value, "international")) {
11793 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11794 } else if (!strcasecmp(v->value, "local")) {
11795 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11796 } else if (!strcasecmp(v->value, "dynamic")) {
11797 confp->pri.localdialplan = -1;
11798 } else {
11799 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11800 }
11801 } else if (!strcasecmp(v->name, "switchtype")) {
11802 if (!strcasecmp(v->value, "national"))
11803 confp->pri.switchtype = PRI_SWITCH_NI2;
11804 else if (!strcasecmp(v->value, "ni1"))
11805 confp->pri.switchtype = PRI_SWITCH_NI1;
11806 else if (!strcasecmp(v->value, "dms100"))
11807 confp->pri.switchtype = PRI_SWITCH_DMS100;
11808 else if (!strcasecmp(v->value, "4ess"))
11809 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11810 else if (!strcasecmp(v->value, "5ess"))
11811 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11812 else if (!strcasecmp(v->value, "euroisdn"))
11813 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11814 else if (!strcasecmp(v->value, "qsig"))
11815 confp->pri.switchtype = PRI_SWITCH_QSIG;
11816 else {
11817 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11818 return -1;
11819 }
11820 } else if (!strcasecmp(v->name, "nsf")) {
11821 if (!strcasecmp(v->value, "sdn"))
11822 confp->pri.nsf = PRI_NSF_SDN;
11823 else if (!strcasecmp(v->value, "megacom"))
11824 confp->pri.nsf = PRI_NSF_MEGACOM;
11825 else if (!strcasecmp(v->value, "tollfreemegacom"))
11826 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11827 else if (!strcasecmp(v->value, "accunet"))
11828 confp->pri.nsf = PRI_NSF_ACCUNET;
11829 else if (!strcasecmp(v->value, "none"))
11830 confp->pri.nsf = PRI_NSF_NONE;
11831 else {
11832 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11833 confp->pri.nsf = PRI_NSF_NONE;
11834 }
11835 } else if (!strcasecmp(v->name, "priindication")) {
11836 if (!strcasecmp(v->value, "outofband"))
11837 confp->chan.priindication_oob = 1;
11838 else if (!strcasecmp(v->value, "inband"))
11839 confp->chan.priindication_oob = 0;
11840 else
11841 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11842 v->value, v->lineno);
11843 } else if (!strcasecmp(v->name, "priexclusive")) {
11844 confp->chan.priexclusive = ast_true(v->value);
11845 } else if (!strcasecmp(v->name, "internationalprefix")) {
11846 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11847 } else if (!strcasecmp(v->name, "nationalprefix")) {
11848 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11849 } else if (!strcasecmp(v->name, "localprefix")) {
11850 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11851 } else if (!strcasecmp(v->name, "privateprefix")) {
11852 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11853 } else if (!strcasecmp(v->name, "unknownprefix")) {
11854 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11855 } else if (!strcasecmp(v->name, "resetinterval")) {
11856 if (!strcasecmp(v->value, "never"))
11857 confp->pri.resetinterval = -1;
11858 else if (atoi(v->value) >= 60)
11859 confp->pri.resetinterval = atoi(v->value);
11860 else
11861 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11862 v->value, v->lineno);
11863 } else if (!strcasecmp(v->name, "minunused")) {
11864 confp->pri.minunused = atoi(v->value);
11865 } else if (!strcasecmp(v->name, "minidle")) {
11866 confp->pri.minidle = atoi(v->value);
11867 } else if (!strcasecmp(v->name, "idleext")) {
11868 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11869 } else if (!strcasecmp(v->name, "idledial")) {
11870 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11871 } else if (!strcasecmp(v->name, "overlapdial")) {
11872 confp->pri.overlapdial = ast_true(v->value);
11873 #ifdef HAVE_PRI_INBANDDISCONNECT
11874 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11875 confp->pri.inbanddisconnect = ast_true(v->value);
11876 #endif
11877 } else if (!strcasecmp(v->name, "pritimer")) {
11878 #ifdef PRI_GETSET_TIMERS
11879 char tmp[20];
11880 char *timerc;
11881 char *c;
11882 int timer;
11883 int timeridx;
11884
11885 ast_copy_string(tmp, v->value, sizeof(tmp));
11886 c = tmp;
11887 timerc = strsep(&c, ",");
11888 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
11889 timeridx = pri_timer2idx(timerc);
11890 timer = atoi(c);
11891 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
11892 ast_log(LOG_WARNING,
11893 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
11894 v->lineno);
11895 } else if (!timer) {
11896 ast_log(LOG_WARNING,
11897 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
11898 c, timerc, v->lineno);
11899 } else {
11900 pritimers[timeridx] = timer;
11901 }
11902 } else {
11903 ast_log(LOG_WARNING,
11904 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
11905 v->value, v->lineno);
11906 }
11907 #endif
11908 } else if (!strcasecmp(v->name, "facilityenable")) {
11909 confp->pri.facilityenable = ast_true(v->value);
11910 #endif
11911 } else if (!strcasecmp(v->name, "cadence")) {
11912
11913 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11914 int i;
11915 struct dahdi_ring_cadence new_cadence;
11916 int cid_location = -1;
11917 int firstcadencepos = 0;
11918 char original_args[80];
11919 int cadence_is_ok = 1;
11920
11921 ast_copy_string(original_args, v->value, sizeof(original_args));
11922
11923 element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
11924
11925
11926 if (element_count % 2 == 1) {
11927 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11928 cadence_is_ok = 0;
11929 }
11930
11931
11932 for (i = 0; i < element_count; i++) {
11933 if (c[i] == 0) {
11934 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11935 cadence_is_ok = 0;
11936 break;
11937 } else if (c[i] < 0) {
11938 if (i % 2 == 1) {
11939
11940 if (cid_location == -1) {
11941 cid_location = i;
11942 c[i] *= -1;
11943 } else {
11944 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11945 cadence_is_ok = 0;
11946 break;
11947 }
11948 } else {
11949 if (firstcadencepos == 0) {
11950 firstcadencepos = i;
11951
11952 } else {
11953 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11954 cadence_is_ok = 0;
11955 break;
11956 }
11957 }
11958 }
11959 }
11960
11961
11962 for (i = 0; i < 16; i++) {
11963 new_cadence.ringcadence[i] = c[i];
11964 }
11965
11966 if (cadence_is_ok) {
11967
11968 if (element_count < 2) {
11969 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11970 } else {
11971 if (cid_location == -1) {
11972
11973 cid_location = 1;
11974 } else {
11975
11976 cid_location = (cid_location + 1) / 2;
11977 }
11978
11979 if (!user_has_defined_cadences++)
11980
11981 num_cadence = 0;
11982 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11983 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11984 else {
11985 cadences[num_cadence] = new_cadence;
11986 cidrings[num_cadence++] = cid_location;
11987 if (option_verbose > 2)
11988 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11989 }
11990 }
11991 }
11992 } else if (!strcasecmp(v->name, "ringtimeout")) {
11993 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11994 } else if (!strcasecmp(v->name, "prewink")) {
11995 confp->timing.prewinktime = atoi(v->value);
11996 } else if (!strcasecmp(v->name, "preflash")) {
11997 confp->timing.preflashtime = atoi(v->value);
11998 } else if (!strcasecmp(v->name, "wink")) {
11999 confp->timing.winktime = atoi(v->value);
12000 } else if (!strcasecmp(v->name, "flash")) {
12001 confp->timing.flashtime = atoi(v->value);
12002 } else if (!strcasecmp(v->name, "start")) {
12003 confp->timing.starttime = atoi(v->value);
12004 } else if (!strcasecmp(v->name, "rxwink")) {
12005 confp->timing.rxwinktime = atoi(v->value);
12006 } else if (!strcasecmp(v->name, "rxflash")) {
12007 confp->timing.rxflashtime = atoi(v->value);
12008 } else if (!strcasecmp(v->name, "debounce")) {
12009 confp->timing.debouncetime = atoi(v->value);
12010 } else if (!strcasecmp(v->name, "toneduration")) {
12011 int toneduration;
12012 int ctlfd;
12013 int res;
12014 struct dahdi_dialparams dps;
12015
12016 ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
12017
12018 if (ctlfd == -1) {
12019 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
12020 return -1;
12021 }
12022
12023 toneduration = atoi(v->value);
12024 if (toneduration > -1) {
12025 memset(&dps, 0, sizeof(dps));
12026
12027 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
12028 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
12029 if (res < 0) {
12030 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
12031 return -1;
12032 }
12033 }
12034 close(ctlfd);
12035 } else if (!strcasecmp(v->name, "defaultcic")) {
12036 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
12037 } else if (!strcasecmp(v->name, "defaultozz")) {
12038 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
12039 }
12040 } else if (!skipchannels)
12041 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
12042 }
12043 if (dahdichan[0]) {
12044
12045
12046 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
12047 return -1;
12048 }
12049 }
12050
12051
12052 if (!found_pseudo && reload != 1) {
12053
12054
12055
12056
12057 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
12058
12059 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
12060
12061 if (tmp) {
12062 if (option_verbose > 2)
12063 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
12064 } else {
12065 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
12066 }
12067 }
12068 return 0;
12069 }
12070
12071 static int setup_dahdi(int reload)
12072 {
12073 struct ast_config *cfg;
12074 struct ast_variable *v;
12075 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
12076 int res;
12077
12078 #ifdef HAVE_PRI
12079 char *c;
12080 int spanno;
12081 int i, x;
12082 int logicalspan;
12083 int trunkgroup;
12084 int dchannels[NUM_DCHANS];
12085 #endif
12086
12087 #ifdef HAVE_ZAPTEL
12088 int load_from_zapata_conf = 1;
12089 #else
12090 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
12091 #endif
12092
12093 if (load_from_zapata_conf) {
12094 if (!(cfg = ast_config_load("zapata.conf"))) {
12095 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
12096 return 0;
12097 }
12098 } else {
12099 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
12100 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
12101 return 0;
12102 }
12103 }
12104
12105
12106 ast_mutex_lock(&iflock);
12107 #ifdef HAVE_PRI
12108 if (reload != 1) {
12109
12110 v = ast_variable_browse(cfg, "trunkgroups");
12111 while (v) {
12112 if (!strcasecmp(v->name, "trunkgroup")) {
12113 trunkgroup = atoi(v->value);
12114 if (trunkgroup > 0) {
12115 if ((c = strchr(v->value, ','))) {
12116 i = 0;
12117 memset(dchannels, 0, sizeof(dchannels));
12118 while (c && (i < NUM_DCHANS)) {
12119 dchannels[i] = atoi(c + 1);
12120 if (dchannels[i] < 0) {
12121 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);
12122 } else
12123 i++;
12124 c = strchr(c + 1, ',');
12125 }
12126 if (i) {
12127 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
12128 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);
12129 } else if (option_verbose > 1)
12130 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");
12131 } else
12132 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12133 } else
12134 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12135 } else
12136 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
12137 } else if (!strcasecmp(v->name, "spanmap")) {
12138 spanno = atoi(v->value);
12139 if (spanno > 0) {
12140 if ((c = strchr(v->value, ','))) {
12141 trunkgroup = atoi(c + 1);
12142 if (trunkgroup > 0) {
12143 if ((c = strchr(c + 1, ',')))
12144 logicalspan = atoi(c + 1);
12145 else
12146 logicalspan = 0;
12147 if (logicalspan >= 0) {
12148 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
12149 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12150 } else if (option_verbose > 1)
12151 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12152 } else
12153 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);
12154 } else
12155 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
12156 } else
12157 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
12158 } else
12159 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
12160 } else {
12161 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
12162 }
12163 v = v->next;
12164 }
12165 }
12166 #endif
12167
12168
12169 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
12170
12171 v = ast_variable_browse(cfg, "channels");
12172 res = process_dahdi(&conf, "", v, reload, 0);
12173 ast_mutex_unlock(&iflock);
12174 ast_config_destroy(cfg);
12175 if (res)
12176 return res;
12177 cfg = ast_config_load("users.conf");
12178 if (cfg) {
12179 char *cat;
12180 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
12181 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
12182 if (!strcasecmp(cat, "general"))
12183 continue;
12184 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
12185 struct dahdi_chan_conf sect_conf;
12186 memcpy(§_conf, &conf, sizeof(sect_conf));
12187
12188 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
12189 }
12190 }
12191 ast_config_destroy(cfg);
12192 }
12193 #ifdef HAVE_PRI
12194 if (reload != 1) {
12195 for (x = 0; x < NUM_SPANS; x++) {
12196 if (pris[x].pvts[0]) {
12197 if (start_pri(pris + x)) {
12198 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
12199 return -1;
12200 } else if (option_verbose > 1)
12201 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
12202 }
12203 }
12204 }
12205 #endif
12206
12207 restart_monitor();
12208 return 0;
12209 }
12210
12211 #define local_astman_register(a, b, c, d) do { \
12212 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12213 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
12214 } \
12215 ast_manager_register("Zap" a, b, zap_ ## c, d); \
12216 } while (0)
12217
12218 static int load_module(void)
12219 {
12220 int res;
12221
12222 #ifdef HAVE_PRI
12223 int y,i;
12224 memset(pris, 0, sizeof(pris));
12225 for (y = 0; y < NUM_SPANS; y++) {
12226 ast_mutex_init(&pris[y].lock);
12227 pris[y].offset = -1;
12228 pris[y].master = AST_PTHREADT_NULL;
12229 for (i = 0; i < NUM_DCHANS; i++)
12230 pris[y].fds[i] = -1;
12231 }
12232 pri_set_error(dahdi_pri_error);
12233 pri_set_message(dahdi_pri_message);
12234 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12235 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
12236 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
12237 }
12238 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
12239 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
12240 #endif
12241 if ((res = setup_dahdi(0))) {
12242 return AST_MODULE_LOAD_DECLINE;
12243 }
12244 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12245 chan_tech = &dahdi_tech;
12246 } else {
12247 chan_tech = &zap_tech;
12248 }
12249 if (ast_channel_register(chan_tech)) {
12250 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
12251 __unload_module();
12252 return -1;
12253 }
12254 #ifdef HAVE_PRI
12255 ast_string_field_init(&inuse, 16);
12256 ast_string_field_set(&inuse, name, "GR-303InUse");
12257 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12258 #endif
12259 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12260
12261 memset(round_robin, 0, sizeof(round_robin));
12262 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
12263 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
12264 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
12265 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
12266 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
12267 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
12268 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
12269
12270 ast_cond_init(&ss_thread_complete, NULL);
12271
12272 return res;
12273 }
12274
12275 static int dahdi_sendtext(struct ast_channel *c, const char *text)
12276 {
12277 #define END_SILENCE_LEN 400
12278 #define HEADER_MS 50
12279 #define TRAILER_MS 5
12280 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
12281 #define ASCII_BYTES_PER_CHAR 80
12282
12283 unsigned char *buf,*mybuf;
12284 struct dahdi_pvt *p = c->tech_pvt;
12285 struct pollfd fds[1];
12286 int size,res,fd,len,x;
12287 int bytes=0;
12288
12289 float cr = 1.0;
12290 float ci = 0.0;
12291 float scont = 0.0;
12292 int index;
12293
12294 index = dahdi_get_index(c, p, 0);
12295 if (index < 0) {
12296 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
12297 return -1;
12298 }
12299 if (!text[0]) return(0);
12300 if ((!p->tdd) && (!p->mate)) return(0);
12301 if (p->mate)
12302 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
12303 else
12304 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
12305 if (!buf)
12306 return -1;
12307 mybuf = buf;
12308 if (p->mate) {
12309 int codec = AST_LAW(p);
12310 for (x = 0; x < HEADER_MS; x++) {
12311 PUT_CLID_MARKMS;
12312 }
12313
12314 for (x = 0; text[x]; x++) {
12315 PUT_CLID(text[x]);
12316 }
12317 for (x = 0; x < TRAILER_MS; x++) {
12318 PUT_CLID_MARKMS;
12319 }
12320 len = bytes;
12321 buf = mybuf;
12322 } else {
12323 len = tdd_generate(p->tdd, buf, text);
12324 if (len < 1) {
12325 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
12326 free(mybuf);
12327 return -1;
12328 }
12329 }
12330 memset(buf + len, 0x7f, END_SILENCE_LEN);
12331 len += END_SILENCE_LEN;
12332 fd = p->subs[index].dfd;
12333 while (len) {
12334 if (ast_check_hangup(c)) {
12335 free(mybuf);
12336 return -1;
12337 }
12338 size = len;
12339 if (size > READ_SIZE)
12340 size = READ_SIZE;
12341 fds[0].fd = fd;
12342 fds[0].events = POLLOUT | POLLPRI;
12343 fds[0].revents = 0;
12344 res = poll(fds, 1, -1);
12345 if (!res) {
12346 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
12347 continue;
12348 }
12349
12350 if (fds[0].revents & POLLPRI) {
12351 ast_free(mybuf);
12352 return -1;
12353 }
12354 if (!(fds[0].revents & POLLOUT)) {
12355 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
12356 continue;
12357 }
12358 res = write(fd, buf, size);
12359 if (res != size) {
12360 if (res == -1) {
12361 free(mybuf);
12362 return -1;
12363 }
12364 if (option_debug)
12365 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
12366 break;
12367 }
12368 len -= size;
12369 buf += size;
12370 }
12371 free(mybuf);
12372 return(0);
12373 }
12374
12375
12376 static int reload(void)
12377 {
12378 int res = 0;
12379
12380 res = setup_dahdi(1);
12381 if (res) {
12382 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12383 return -1;
12384 }
12385 return 0;
12386 }
12387
12388
12389
12390
12391
12392 #ifdef HAVE_PRI
12393 #define tdesc "DAHDI Telephony w/PRI"
12394 #else
12395 #define tdesc "DAHDI Telephony"
12396 #endif
12397
12398 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
12399 .load = load_module,
12400 .unload = unload_module,
12401 .reload = reload,
12402 );
12403
12404