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
00049 #include "asterisk.h"
00050
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 313188 $")
00052
00053 #include <stdio.h>
00054 #include <string.h>
00055 #if defined(__NetBSD__) || defined(__FreeBSD__)
00056 #include <pthread.h>
00057 #include <signal.h>
00058 #else
00059 #include <sys/signal.h>
00060 #endif
00061 #include <errno.h>
00062 #include <stdlib.h>
00063 #if !defined(SOLARIS) && !defined(__FreeBSD__)
00064 #include <stdint.h>
00065 #endif
00066 #include <unistd.h>
00067 #include <sys/ioctl.h>
00068 #include <math.h>
00069 #include <ctype.h>
00070
00071 #ifdef HAVE_PRI
00072 #include <libpri.h>
00073 #endif
00074
00075 #ifdef HAVE_OPENR2
00076 #include <openr2.h>
00077 #endif
00078
00079 #include "asterisk/lock.h"
00080 #include "asterisk/channel.h"
00081 #include "asterisk/config.h"
00082 #include "asterisk/logger.h"
00083 #include "asterisk/module.h"
00084 #include "asterisk/pbx.h"
00085 #include "asterisk/options.h"
00086 #include "asterisk/file.h"
00087 #include "asterisk/ulaw.h"
00088 #include "asterisk/alaw.h"
00089 #include "asterisk/callerid.h"
00090 #include "asterisk/adsi.h"
00091 #include "asterisk/cli.h"
00092 #include "asterisk/cdr.h"
00093 #include "asterisk/features.h"
00094 #include "asterisk/musiconhold.h"
00095 #include "asterisk/say.h"
00096 #include "asterisk/tdd.h"
00097 #include "asterisk/app.h"
00098 #include "asterisk/dsp.h"
00099 #include "asterisk/astdb.h"
00100 #include "asterisk/manager.h"
00101 #include "asterisk/causes.h"
00102 #include "asterisk/term.h"
00103 #include "asterisk/utils.h"
00104 #include "asterisk/transcap.h"
00105 #include "asterisk/stringfields.h"
00106 #include "asterisk/abstract_jb.h"
00107 #include "asterisk/smdi.h"
00108 #include "asterisk/astobj.h"
00109 #define SMDI_MD_WAIT_TIMEOUT 1500
00110
00111 #include "asterisk/dahdi_compat.h"
00112 #include "asterisk/tonezone_compat.h"
00113
00114
00115 static struct ast_jb_conf default_jbconf =
00116 {
00117 .flags = 0,
00118 .max_size = -1,
00119 .resync_threshold = -1,
00120 .impl = ""
00121 };
00122 static struct ast_jb_conf global_jbconf;
00123
00124 #ifndef DAHDI_TONEDETECT
00125
00126 #define DAHDI_EVENT_DTMFDOWN 0
00127 #define DAHDI_EVENT_DTMFUP 0
00128 #endif
00129
00130
00131 #undef SUPPORT_USERUSER
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 #define FORCE_RESTART_UNAVAIL_CHANS 1
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 #define DEFAULT_CIDRINGS 1
00168
00169 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00170
00171
00172 #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))
00173
00174 static const char tdesc[] = "DAHDI Telephony Driver"
00175 #ifdef HAVE_PRI
00176 " w/PRI"
00177 #endif
00178
00179 #ifdef HAVE_OPENR2
00180 " w/OPENR2"
00181 #endif
00182 ;
00183
00184 #define SIG_EM DAHDI_SIG_EM
00185 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00186 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00187 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00188 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00189 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00190 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00191 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00192 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00193 #define SIG_FXSLS DAHDI_SIG_FXSLS
00194 #define SIG_FXSGS DAHDI_SIG_FXSGS
00195 #define SIG_FXSKS DAHDI_SIG_FXSKS
00196 #define SIG_FXOLS DAHDI_SIG_FXOLS
00197 #define SIG_FXOGS DAHDI_SIG_FXOGS
00198 #define SIG_FXOKS DAHDI_SIG_FXOKS
00199 #define SIG_PRI DAHDI_SIG_CLEAR
00200 #define SIG_MFCR2 DAHDI_SIG_CAS
00201 #define SIG_SF DAHDI_SIG_SF
00202 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00203 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00204 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00205 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00206 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00207 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00208 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00209
00210 #define NUM_SPANS 32
00211 #define NUM_DCHANS 4
00212 #define MAX_CHANNELS 672
00213
00214 #define CHAN_PSEUDO -2
00215
00216 #define DCHAN_PROVISIONED (1 << 0)
00217 #define DCHAN_NOTINALARM (1 << 1)
00218 #define DCHAN_UP (1 << 2)
00219
00220 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00221
00222
00223 #define DAHDI_OVERLAPDIAL_NONE 0
00224 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00225 #define DAHDI_OVERLAPDIAL_INCOMING 2
00226 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00227
00228 static char defaultcic[64] = "";
00229 static char defaultozz[64] = "";
00230
00231 static char progzone[10] = "";
00232
00233 static int distinctiveringaftercid = 0;
00234
00235 static int numbufs = 4;
00236 static int dtmfcid_level = 256;
00237
00238 #ifdef HAVE_PRI
00239 static struct ast_channel inuse;
00240 #ifdef PRI_GETSET_TIMERS
00241 static int pritimers[PRI_MAX_TIMERS];
00242 #endif
00243 static int pridebugfd = -1;
00244 static char pridebugfilename[1024] = "";
00245 #endif
00246
00247
00248 static int firstdigittimeout = 16000;
00249
00250
00251 static int gendigittimeout = 8000;
00252
00253
00254 static int matchdigittimeout = 3000;
00255
00256
00257 AST_MUTEX_DEFINE_STATIC(iflock);
00258
00259
00260 static int ifcount = 0;
00261
00262 #ifdef HAVE_PRI
00263 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00264 #endif
00265
00266
00267
00268 AST_MUTEX_DEFINE_STATIC(monlock);
00269
00270
00271
00272 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00273 static ast_cond_t ss_thread_complete;
00274 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00275 AST_MUTEX_DEFINE_STATIC(restart_lock);
00276 static int ss_thread_count = 0;
00277 static int num_restart_pending = 0;
00278
00279 static int restart_monitor(void);
00280
00281 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);
00282
00283 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00284
00285 #define SIG_PRI_LIB_HANDLE_CASES \
00286 SIG_PRI
00287
00288
00289 static inline int dahdi_get_event(int fd)
00290 {
00291 int j;
00292 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00293 return -1;
00294 return j;
00295 }
00296
00297
00298 static inline int dahdi_wait_event(int fd)
00299 {
00300 int i, j = 0;
00301 i = DAHDI_IOMUX_SIGEVENT;
00302 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00303 return -1;
00304 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00305 return -1;
00306 return j;
00307 }
00308
00309
00310 #define READ_SIZE 160
00311
00312 #define MASK_AVAIL (1 << 0)
00313 #define MASK_INUSE (1 << 1)
00314
00315 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00316 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00317 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00318 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00319 #define MIN_MS_SINCE_FLASH ((2000) )
00320 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00321
00322 struct dahdi_pvt;
00323
00324
00325
00326
00327
00328 static int ringt_base = DEFAULT_RINGT;
00329
00330 #ifdef HAVE_OPENR2
00331
00332 struct dahdi_mfcr2 {
00333 pthread_t master;
00334 openr2_context_t *protocol_context;
00335 struct dahdi_pvt *pvts[MAX_CHANNELS];
00336 int numchans;
00337 };
00338
00339 static struct dahdi_mfcr2 r2links[NUM_SPANS];
00340 static openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN;
00341 static int mfcr2_cur_mfback_timeout = -1;
00342 static int mfcr2_cur_metering_pulse_timeout = -1;
00343 static int mfcr2_cur_max_ani = 10;
00344 static int mfcr2_cur_max_dnis = 4;
00345 static int mfcr2_cur_get_ani_first = -1;
00346 static int mfcr2_cur_skip_category = -1;
00347 static int mfcr2_cur_context_index = 0;
00348 static int mfcr2_cur_call_files = 0;
00349 static int mfcr2_cur_allow_collect_calls = 0;
00350 static int mfcr2_cur_accept_on_offer = 1;
00351 static int mfcr2_cur_charge_calls = 1;
00352 static int mfcr2_cur_forced_release = 0;
00353 static int mfcr2_cur_double_answer = 0;
00354 static int mfcr2_cur_immediate_accept = -1;
00355
00356 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00357 static int mfcr2_cur_dtmf_dialing = -1;
00358 static int mfcr2_cur_dtmf_detection = -1;
00359 static int mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
00360 static int mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
00361 #endif
00362 static char mfcr2_cur_logdir[OR2_MAX_PATH];
00363 static char mfcr2_cur_r2proto_file[OR2_MAX_PATH];
00364 static openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
00365 static openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
00366
00367 #endif
00368
00369 #ifdef HAVE_PRI
00370
00371 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00372 #define PRI_CHANNEL(p) ((p) & 0xff)
00373 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00374 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00375
00376
00377 enum dahdi_call_level {
00378
00379 DAHDI_CALL_LEVEL_IDLE,
00380
00381 DAHDI_CALL_LEVEL_SETUP,
00382
00383 DAHDI_CALL_LEVEL_OVERLAP,
00384
00385 DAHDI_CALL_LEVEL_PROCEEDING,
00386
00387 DAHDI_CALL_LEVEL_ALERTING,
00388
00389 DAHDI_CALL_LEVEL_CONNECT,
00390 };
00391
00392 struct dahdi_pri {
00393 pthread_t master;
00394 ast_mutex_t lock;
00395 char idleext[AST_MAX_EXTENSION];
00396 char idlecontext[AST_MAX_CONTEXT];
00397 char idledial[AST_MAX_EXTENSION];
00398 int minunused;
00399 int minidle;
00400 int nodetype;
00401 int switchtype;
00402 int nsf;
00403 int dialplan;
00404 int localdialplan;
00405 char internationalprefix[10];
00406 char nationalprefix[10];
00407 char localprefix[20];
00408 char privateprefix[20];
00409 char unknownprefix[20];
00410 int dchannels[NUM_DCHANS];
00411 int trunkgroup;
00412 int mastertrunkgroup;
00413 int prilogicalspan;
00414 int numchans;
00415 int overlapdial;
00416 int facilityenable;
00417 struct pri *dchans[NUM_DCHANS];
00418 int dchanavail[NUM_DCHANS];
00419 struct pri *pri;
00420
00421 int debug;
00422 int fds[NUM_DCHANS];
00423
00424 int offset;
00425
00426 int span;
00427
00428 int resetting;
00429
00430 int resetpos;
00431 #ifdef HAVE_PRI_INBANDDISCONNECT
00432 unsigned int inbanddisconnect:1;
00433 #endif
00434
00435 unsigned int no_d_channels:1;
00436 time_t lastreset;
00437 long resetinterval;
00438 struct dahdi_pvt *pvts[MAX_CHANNELS];
00439 struct dahdi_pvt *crvs;
00440 struct dahdi_pvt *crvend;
00441 };
00442
00443
00444 static struct dahdi_pri pris[NUM_SPANS];
00445
00446 #if 0
00447 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00448 #else
00449 #define DEFAULT_PRI_DEBUG 0
00450 #endif
00451
00452 static inline void pri_rel(struct dahdi_pri *pri)
00453 {
00454 ast_mutex_unlock(&pri->lock);
00455 }
00456
00457 #else
00458
00459 struct dahdi_pri;
00460 #endif
00461
00462 #define SUB_REAL 0
00463 #define SUB_CALLWAIT 1
00464 #define SUB_THREEWAY 2
00465
00466
00467 #define POLARITY_IDLE 0
00468 #define POLARITY_REV 1
00469
00470
00471 static struct dahdi_distRings drings;
00472
00473 struct distRingData {
00474 int ring[3];
00475 };
00476 struct ringContextData {
00477 char contextData[AST_MAX_CONTEXT];
00478 };
00479 struct dahdi_distRings {
00480 struct distRingData ringnum[3];
00481 struct ringContextData ringContext[3];
00482 };
00483
00484 static char *subnames[] = {
00485 "Real",
00486 "Callwait",
00487 "Threeway"
00488 };
00489
00490 struct dahdi_subchannel {
00491 int dfd;
00492 struct ast_channel *owner;
00493 int chan;
00494 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00495 struct ast_frame f;
00496 unsigned int needringing:1;
00497 unsigned int needbusy:1;
00498 unsigned int needcongestion:1;
00499 unsigned int needcallerid:1;
00500 unsigned int needanswer:1;
00501 unsigned int needflash:1;
00502 unsigned int needhold:1;
00503 unsigned int needunhold:1;
00504 unsigned int linear:1;
00505 unsigned int inthreeway:1;
00506 struct dahdi_confinfo curconf;
00507 };
00508
00509 #define CONF_USER_REAL (1 << 0)
00510 #define CONF_USER_THIRDCALL (1 << 1)
00511
00512 #define MAX_SLAVES 4
00513
00514 static struct dahdi_pvt {
00515 ast_mutex_t lock;
00516 struct ast_channel *owner;
00517
00518
00519 struct dahdi_subchannel sub_unused;
00520 struct dahdi_subchannel subs[3];
00521 struct dahdi_confinfo saveconf;
00522
00523 struct dahdi_pvt *slaves[MAX_SLAVES];
00524 struct dahdi_pvt *master;
00525 int inconference;
00526
00527 int bufsize;
00528 int buf_no;
00529 int buf_policy;
00530 int sig;
00531
00532
00533
00534
00535 int radio;
00536 int outsigmod;
00537 int oprmode;
00538 struct dahdi_pvt *oprpeer;
00539
00540 float rxgain;
00541
00542 float txgain;
00543 int tonezone;
00544 struct dahdi_pvt *next;
00545 struct dahdi_pvt *prev;
00546
00547
00548
00549
00550
00551
00552
00553 unsigned int adsi:1;
00554
00555
00556
00557
00558
00559 unsigned int answeronpolarityswitch:1;
00560
00561
00562
00563
00564
00565 unsigned int busydetect:1;
00566
00567
00568
00569
00570
00571 unsigned int callreturn:1;
00572
00573
00574
00575
00576
00577
00578 unsigned int callwaiting:1;
00579
00580
00581
00582
00583 unsigned int callwaitingcallerid:1;
00584
00585
00586
00587
00588
00589
00590 unsigned int cancallforward:1;
00591
00592
00593
00594
00595 unsigned int canpark:1;
00596
00597 unsigned int confirmanswer:1;
00598
00599
00600
00601
00602 unsigned int destroy:1;
00603 unsigned int didtdd:1;
00604
00605 unsigned int dialednone:1;
00606
00607 unsigned int dialing:1;
00608
00609 unsigned int digital:1;
00610
00611 unsigned int dnd:1;
00612
00613 unsigned int echobreak:1;
00614
00615
00616
00617
00618
00619 unsigned int echocanbridged:1;
00620
00621 unsigned int echocanon:1;
00622
00623 unsigned int faxhandled:1;
00624
00625 unsigned int bufferoverrideinuse:1;
00626
00627 unsigned int firstradio:1;
00628
00629
00630
00631
00632 unsigned int hanguponpolarityswitch:1;
00633
00634 unsigned int hardwaredtmf:1;
00635
00636
00637
00638
00639
00640
00641 unsigned int hidecallerid:1;
00642
00643
00644
00645
00646
00647 unsigned int hidecalleridname:1;
00648
00649 unsigned int ignoredtmf:1;
00650
00651
00652
00653
00654
00655 unsigned int immediate:1;
00656
00657 unsigned int inalarm:1;
00658 unsigned int unknown_alarm:1;
00659
00660 unsigned int mate:1;
00661 #if defined(HAVE_PRI)
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 unsigned int allocated:1;
00673 #endif
00674
00675 unsigned int outgoing:1;
00676
00677
00678
00679
00680
00681
00682 unsigned int permcallwaiting:1;
00683
00684
00685
00686
00687 unsigned int permhidecallerid:1;
00688
00689
00690
00691
00692 unsigned int priindication_oob:1;
00693
00694
00695
00696
00697 unsigned int priexclusive:1;
00698
00699
00700
00701
00702 unsigned int pulse:1;
00703
00704 unsigned int pulsedial:1;
00705 unsigned int restartpending:1;
00706
00707
00708
00709
00710
00711 unsigned int restrictcid:1;
00712
00713
00714
00715
00716 unsigned int threewaycalling:1;
00717
00718
00719
00720
00721
00722
00723
00724
00725 unsigned int transfer:1;
00726
00727
00728
00729
00730
00731
00732
00733 unsigned int use_callerid:1;
00734
00735
00736
00737
00738
00739
00740 unsigned int use_callingpres:1;
00741
00742
00743
00744
00745
00746 unsigned int usedistinctiveringdetection:1;
00747
00748
00749
00750
00751 unsigned int dahditrcallerid:1;
00752
00753
00754
00755
00756 unsigned int transfertobusy:1;
00757
00758
00759
00760
00761 unsigned int use_smdi:1;
00762 #if defined(HAVE_PRI)
00763
00764 unsigned int alreadyhungup:1;
00765
00766
00767
00768
00769 unsigned int isidlecall:1;
00770
00771 unsigned int progress:1;
00772
00773
00774
00775
00776 unsigned int resetting:1;
00777
00778
00779 enum dahdi_call_level call_level;
00780 #endif
00781
00782 struct ast_smdi_interface *smdi_iface;
00783
00784
00785 struct dahdi_distRings drings;
00786
00787
00788
00789
00790
00791 char context[AST_MAX_CONTEXT];
00792
00793
00794
00795 char defcontext[AST_MAX_CONTEXT];
00796
00797 char exten[AST_MAX_EXTENSION];
00798
00799
00800
00801
00802 char language[MAX_LANGUAGE];
00803
00804
00805
00806
00807 char mohinterpret[MAX_MUSICCLASS];
00808
00809
00810
00811
00812 char mohsuggest[MAX_MUSICCLASS];
00813 #ifdef PRI_ANI
00814
00815 char cid_ani[AST_MAX_EXTENSION];
00816 #endif
00817
00818 char cid_num[AST_MAX_EXTENSION];
00819
00820 int cid_ton;
00821
00822 char cid_name[AST_MAX_EXTENSION];
00823
00824 char lastcid_num[AST_MAX_EXTENSION];
00825
00826 char lastcid_name[AST_MAX_EXTENSION];
00827 char *origcid_num;
00828 char *origcid_name;
00829
00830 char callwait_num[AST_MAX_EXTENSION];
00831
00832 char callwait_name[AST_MAX_EXTENSION];
00833
00834 char rdnis[AST_MAX_EXTENSION];
00835
00836 char dnid[AST_MAX_EXTENSION];
00837
00838
00839
00840
00841 ast_group_t group;
00842
00843 int law;
00844 int confno;
00845 int confusers;
00846 int propconfno;
00847
00848
00849
00850
00851 ast_group_t callgroup;
00852
00853
00854
00855
00856 ast_group_t pickupgroup;
00857 int channel;
00858 int span;
00859 time_t guardtime;
00860 int cid_signalling;
00861 int cid_start;
00862 int dtmfcid_holdoff_state;
00863 struct timeval dtmfcid_delay;
00864 int callingpres;
00865 int callwaitingrepeat;
00866 int cidcwexpire;
00867 int cid_suppress_expire;
00868
00869 unsigned char *cidspill;
00870
00871 int cidpos;
00872
00873 int cidlen;
00874
00875 int ringt;
00876
00877
00878
00879
00880 int ringt_base;
00881
00882
00883
00884
00885
00886
00887 int stripmsd;
00888
00889
00890
00891
00892
00893
00894 int callwaitcas;
00895
00896 int callwaitrings;
00897
00898 int echocancel;
00899
00900
00901
00902
00903 int echotraining;
00904
00905 char echorest[20];
00906
00907
00908
00909
00910 int busycount;
00911
00912
00913
00914
00915 int busycompare;
00916
00917
00918
00919
00920 int busytonelength;
00921
00922
00923
00924
00925 int busyquietlength;
00926
00927
00928
00929
00930 int busyfuzziness;
00931
00932
00933
00934
00935 int silencethreshold;
00936
00937
00938
00939
00940 int callprogress;
00941 struct timeval flashtime;
00942
00943 struct ast_dsp *dsp;
00944
00945
00946 struct dahdi_dialoperation dop;
00947 int whichwink;
00948
00949 char finaldial[64];
00950 char accountcode[AST_MAX_ACCOUNT_CODE];
00951 int amaflags;
00952 struct tdd_state *tdd;
00953
00954 char call_forward[AST_MAX_EXTENSION];
00955
00956
00957
00958
00959 char mailbox[AST_MAX_EXTENSION];
00960
00961 char dialdest[256];
00962
00963 int onhooktime;
00964
00965 int msgstate;
00966 int distinctivering;
00967 int cidrings;
00968 int dtmfrelax;
00969
00970 int fake_event;
00971
00972
00973
00974
00975 int polarityonanswerdelay;
00976
00977 struct timeval polaritydelaytv;
00978
00979
00980
00981
00982 int sendcalleridafter;
00983 #ifdef HAVE_PRI
00984
00985 struct dahdi_pri *pri;
00986
00987 struct dahdi_pvt *bearer;
00988
00989 struct dahdi_pvt *realcall;
00990
00991 q931_call *call;
00992
00993 int prioffset;
00994
00995 int logicalspan;
00996 #endif
00997
00998 #ifdef HAVE_OPENR2
00999 int mfcr2call;
01000 int mfcr2block;
01001 struct dahdi_mfcr2 *mfcr2;
01002 openr2_chan_t *r2chan;
01003 openr2_calling_party_category_t mfcr2_recvd_category;
01004 openr2_calling_party_category_t mfcr2_category;
01005 int mfcr2_accept_on_offer;
01006 int mfcr2_charge_calls;
01007 int mfcr2_allow_collect_calls;
01008 int mfcr2_forced_release;
01009 int mfcr2_dnis_index;
01010 int mfcr2_ani_index;
01011 int mfcr2_dnis_matched;
01012 int mfcr2_call_accepted;
01013 #endif
01014
01015
01016 int polarity;
01017
01018 int dsp_features;
01019
01020 char begindigit;
01021 } *iflist = NULL, *ifend = NULL;
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 struct dahdi_chan_conf {
01034 struct dahdi_pvt chan;
01035 #ifdef HAVE_PRI
01036 struct dahdi_pri pri;
01037 #endif
01038 struct dahdi_params timing;
01039
01040
01041
01042
01043
01044 char smdi_port[SMDI_MAX_FILENAME_LEN];
01045 };
01046
01047
01048 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01049
01050
01051
01052 struct dahdi_chan_conf conf = {
01053 #ifdef HAVE_PRI
01054 .pri = {
01055 .nsf = PRI_NSF_NONE,
01056 .switchtype = PRI_SWITCH_NI2,
01057 .dialplan = PRI_NATIONAL_ISDN + 1,
01058 .localdialplan = PRI_NATIONAL_ISDN + 1,
01059 .nodetype = PRI_CPE,
01060
01061 .minunused = 2,
01062 .idleext = "",
01063 .idledial = "",
01064 .internationalprefix = "",
01065 .nationalprefix = "",
01066 .localprefix = "",
01067 .privateprefix = "",
01068 .unknownprefix = "",
01069
01070 .resetinterval = 3600
01071 },
01072 #endif
01073 .chan = {
01074 .context = "default",
01075 .cid_num = "",
01076 .cid_name = "",
01077 .mohinterpret = "default",
01078 .mohsuggest = "",
01079 .transfertobusy = 1,
01080
01081 .cid_signalling = CID_SIG_BELL,
01082 .cid_start = CID_START_RING,
01083 .dahditrcallerid = 0,
01084 .use_callerid = 1,
01085 .sig = -1,
01086 .outsigmod = -1,
01087
01088 .tonezone = -1,
01089
01090 .echocancel = 1,
01091
01092 .busycount = 3,
01093 .busycompare = 0,
01094 .busytonelength = 0,
01095 .busyquietlength = 0,
01096 .busyfuzziness = 0,
01097 .silencethreshold = 0,
01098
01099 .accountcode = "",
01100
01101 .mailbox = "",
01102
01103
01104 .polarityonanswerdelay = 600,
01105
01106 .sendcalleridafter = DEFAULT_CIDRINGS,
01107
01108 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01109 .buf_no = numbufs,
01110 },
01111 .timing = {
01112 .prewinktime = -1,
01113 .preflashtime = -1,
01114 .winktime = -1,
01115 .flashtime = -1,
01116 .starttime = -1,
01117 .rxwinktime = -1,
01118 .rxflashtime = -1,
01119 .debouncetime = -1
01120 },
01121 .smdi_port = "/dev/ttyS0",
01122 };
01123
01124 return conf;
01125 }
01126
01127
01128 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01129 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01130 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01131 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01132 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01133 static int dahdi_hangup(struct ast_channel *ast);
01134 static int dahdi_answer(struct ast_channel *ast);
01135 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01136 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01137 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01138 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01139 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01140 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01141 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
01142 static int dahdi_func_write(struct ast_channel *chan, char *function, char *data, const char *value);
01143
01144 static const struct ast_channel_tech dahdi_tech = {
01145 .type = "DAHDI",
01146 .description = tdesc,
01147 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01148 .requester = dahdi_request,
01149 .send_digit_begin = dahdi_digit_begin,
01150 .send_digit_end = dahdi_digit_end,
01151 .send_text = dahdi_sendtext,
01152 .call = dahdi_call,
01153 .hangup = dahdi_hangup,
01154 .answer = dahdi_answer,
01155 .read = dahdi_read,
01156 .write = dahdi_write,
01157 .bridge = dahdi_bridge,
01158 .exception = dahdi_exception,
01159 .indicate = dahdi_indicate,
01160 .fixup = dahdi_fixup,
01161 .setoption = dahdi_setoption,
01162 .func_channel_read = dahdi_func_read,
01163 .func_channel_write = dahdi_func_write,
01164 };
01165
01166 static const struct ast_channel_tech zap_tech = {
01167 .type = "Zap",
01168 .description = tdesc,
01169 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01170 .requester = dahdi_request,
01171 .send_digit_begin = dahdi_digit_begin,
01172 .send_digit_end = dahdi_digit_end,
01173 .send_text = dahdi_sendtext,
01174 .call = dahdi_call,
01175 .hangup = dahdi_hangup,
01176 .answer = dahdi_answer,
01177 .read = dahdi_read,
01178 .write = dahdi_write,
01179 .bridge = dahdi_bridge,
01180 .exception = dahdi_exception,
01181 .indicate = dahdi_indicate,
01182 .fixup = dahdi_fixup,
01183 .setoption = dahdi_setoption,
01184 .func_channel_read = dahdi_func_read,
01185 .func_channel_write = dahdi_func_write,
01186 };
01187
01188 static const struct ast_channel_tech *chan_tech;
01189
01190 #ifdef HAVE_PRI
01191 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01192 #else
01193 #define GET_CHANNEL(p) ((p)->channel)
01194 #endif
01195
01196 struct dahdi_pvt *round_robin[32];
01197
01198 #ifdef HAVE_PRI
01199 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01200 {
01201 int res;
01202
01203 do {
01204 res = ast_mutex_trylock(&pri->lock);
01205 if (res) {
01206 DEADLOCK_AVOIDANCE(&pvt->lock);
01207 }
01208 } while (res);
01209
01210 if (pri->master != AST_PTHREADT_NULL)
01211 pthread_kill(pri->master, SIGURG);
01212 return 0;
01213 }
01214 #endif
01215
01216 #define NUM_CADENCE_MAX 25
01217 static int num_cadence = 4;
01218 static int user_has_defined_cadences = 0;
01219
01220 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01221 { { 125, 125, 2000, 4000 } },
01222 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01223 { { 125, 125, 125, 125, 125, 4000 } },
01224 { { 1000, 500, 2500, 5000 } },
01225 };
01226
01227
01228
01229
01230
01231 static int cidrings[NUM_CADENCE_MAX] = {
01232 2,
01233 4,
01234 3,
01235 2,
01236 };
01237
01238 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01239 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01240
01241 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01242 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01243
01244 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
01245 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
01246 {
01247 int res;
01248 if (p->subs[SUB_REAL].owner == ast)
01249 res = 0;
01250 else if (p->subs[SUB_CALLWAIT].owner == ast)
01251 res = 1;
01252 else if (p->subs[SUB_THREEWAY].owner == ast)
01253 res = 2;
01254 else {
01255 res = -1;
01256 if (!nullok)
01257 ast_log(LOG_WARNING,
01258 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
01259 ast ? ast->name : "", p->channel, fname, line);
01260 }
01261 return res;
01262 }
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
01280 {
01281 for (;;) {
01282 if (!pvt->subs[sub_idx].owner) {
01283
01284 break;
01285 }
01286 if (!ast_mutex_trylock(&pvt->subs[sub_idx].owner->lock)) {
01287
01288 break;
01289 }
01290
01291 DEADLOCK_AVOIDANCE(&pvt->lock);
01292 }
01293 }
01294
01295 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01296 {
01297 #ifdef HAVE_PRI
01298 if (pri)
01299 ast_mutex_unlock(&pri->lock);
01300 #endif
01301 dahdi_lock_sub_owner(p, a);
01302 if (p->subs[a].owner) {
01303 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01304 ast_mutex_unlock(&p->subs[a].owner->lock);
01305 }
01306 #ifdef HAVE_PRI
01307 if (pri)
01308 ast_mutex_lock(&pri->lock);
01309 #endif
01310 }
01311
01312 #ifdef HAVE_PRI
01313 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
01314 #else
01315 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
01316 #endif
01317 {
01318
01319 #ifdef HAVE_PRI
01320 if (pri)
01321 ast_mutex_unlock(&pri->lock);
01322 #endif
01323 for (;;) {
01324 if (p->owner) {
01325 if (ast_mutex_trylock(&p->owner->lock)) {
01326 DEADLOCK_AVOIDANCE(&p->lock);
01327 } else {
01328 ast_queue_frame(p->owner, f);
01329 ast_mutex_unlock(&p->owner->lock);
01330 break;
01331 }
01332 } else
01333 break;
01334 }
01335 #ifdef HAVE_PRI
01336 if (pri)
01337 ast_mutex_lock(&pri->lock);
01338 #endif
01339 }
01340
01341 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability);
01342 #ifdef HAVE_OPENR2
01343 static void init_mfcr2_globals(void)
01344 {
01345 int r;
01346 mfcr2_cur_context_index = 0;
01347 mfcr2_cur_variant = OR2_VAR_UNKNOWN;
01348 mfcr2_cur_mfback_timeout = -1;
01349 mfcr2_cur_metering_pulse_timeout = -1;
01350 mfcr2_cur_max_ani = 10;
01351 mfcr2_cur_max_dnis = 4;
01352 mfcr2_cur_get_ani_first = -1;
01353 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01354 mfcr2_cur_dtmf_dialing = -1;
01355 mfcr2_cur_dtmf_detection = -1;
01356 mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
01357 mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
01358 #endif
01359 mfcr2_cur_skip_category = -1;
01360 mfcr2_cur_call_files = 0;
01361 mfcr2_cur_allow_collect_calls = 0;
01362 mfcr2_cur_forced_release = 0;
01363 mfcr2_cur_double_answer = 0;
01364 mfcr2_cur_immediate_accept = -1;
01365 mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
01366 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
01367 memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir));
01368 memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file));
01369 memset(r2links, 0, sizeof(r2links));
01370 for (r = 0; r < NUM_SPANS; r++) {
01371 r2links[r].master = AST_PTHREADT_NULL;
01372 }
01373 }
01374
01375 static int dahdi_r2_answer(struct dahdi_pvt *p)
01376 {
01377 int res = 0;
01378
01379
01380
01381 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01382 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01383 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01384 if (!double_answer) {
01385
01386
01387 res = openr2_chan_answer_call(p->r2chan);
01388 } else if (wants_double_answer) {
01389 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01390 } else {
01391 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01392 }
01393 #else
01394 res = openr2_chan_answer_call(p->r2chan);
01395 #endif
01396 return res;
01397 }
01398
01399 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01400 {
01401 openr2_calling_party_category_t cat;
01402 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01403 struct dahdi_pvt *p = c->tech_pvt;
01404 if (ast_strlen_zero(catstr)) {
01405 ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n",
01406 c->name, openr2_proto_get_category_string(p->mfcr2_category));
01407 return p->mfcr2_category;
01408 }
01409 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01410 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01411 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01412 return p->mfcr2_category;
01413 }
01414 ast_log(LOG_DEBUG, "Using category %s\n", catstr);
01415 return cat;
01416 }
01417
01418 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01419 {
01420 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01421 ast_mutex_lock(&p->lock);
01422 if (p->mfcr2call) {
01423 ast_mutex_unlock(&p->lock);
01424
01425
01426
01427
01428
01429 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01430 return;
01431 }
01432 p->mfcr2call = 1;
01433
01434 p->cid_name[0] = 0;
01435 p->cid_num[0] = 0;
01436 p->rdnis[0] = 0;
01437 p->exten[0] = 0;
01438 p->mfcr2_ani_index = 0;
01439 p->mfcr2_dnis_index = 0;
01440 p->mfcr2_dnis_matched = 0;
01441 p->mfcr2_call_accepted = 0;
01442 ast_mutex_unlock(&p->lock);
01443 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01444 }
01445
01446 static void handle_alarms(struct dahdi_pvt *p, int alarms);
01447 static int get_alarms(struct dahdi_pvt *p);
01448 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01449 {
01450 int res;
01451 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01452 ast_mutex_lock(&p->lock);
01453 p->inalarm = alarm ? 1 : 0;
01454 if (p->inalarm) {
01455 res = get_alarms(p);
01456
01457 handle_alarms(p, res);
01458 } else {
01459 if (!p->unknown_alarm) {
01460 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01461 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01462 } else {
01463 p->unknown_alarm = 0;
01464 }
01465 }
01466 ast_mutex_unlock(&p->lock);
01467 ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan));
01468 }
01469
01470 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01471 {
01472 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01473 }
01474
01475 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01476 {
01477 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01478 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01479 if (p->owner) {
01480 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01481 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01482 }
01483 ast_mutex_lock(&p->lock);
01484 p->mfcr2call = 0;
01485 ast_mutex_unlock(&p->lock);
01486 }
01487
01488 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01489 {
01490 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01491 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01492 p->channel, openr2_proto_get_disconnect_string(cause));
01493
01494 openr2_chan_set_idle(p->r2chan);
01495 ast_mutex_lock(&p->lock);
01496 p->mfcr2call = 0;
01497 ast_mutex_unlock(&p->lock);
01498 }
01499 }
01500
01501 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01502 {
01503 struct dahdi_pvt *p;
01504 struct ast_channel *c;
01505 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01506 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category));
01507 p = openr2_chan_get_client_data(r2chan);
01508 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01509 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel);
01510 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01511 return;
01512 }
01513 ast_mutex_lock(&p->lock);
01514 p->mfcr2_recvd_category = category;
01515
01516 if (!p->use_callerid) {
01517 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01518 p->cid_num[0] = 0;
01519 p->cid_name[0] = 0;
01520 }
01521
01522 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01523 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01524 p->exten[0] = 's';
01525 p->exten[1] = 0;
01526 }
01527 ast_mutex_unlock(&p->lock);
01528 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01529 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01530 p->channel, p->exten, p->context);
01531 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01532 } else {
01533
01534 if (!p->mfcr2_accept_on_offer) {
01535 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01536 if (!c) {
01537 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01538 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01539 }
01540
01541
01542 } else if (p->mfcr2_charge_calls) {
01543 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel);
01544 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01545 } else {
01546 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel);
01547 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01548 }
01549 }
01550 }
01551
01552 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01553 {
01554 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01555 ast_verbose("MFC/R2 call end on chan %d\n", p->channel);
01556 ast_mutex_lock(&p->lock);
01557 p->mfcr2call = 0;
01558 ast_mutex_unlock(&p->lock);
01559 }
01560
01561 static void dahdi_enable_ec(struct dahdi_pvt *p);
01562 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01563 {
01564 struct dahdi_pvt *p = NULL;
01565 struct ast_channel *c = NULL;
01566 p = openr2_chan_get_client_data(r2chan);
01567 dahdi_enable_ec(p);
01568 p->mfcr2_call_accepted = 1;
01569 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01570 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01571
01572
01573
01574
01575 if (!p->mfcr2_accept_on_offer) {
01576 openr2_chan_disable_read(r2chan);
01577 ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01578 dahdi_r2_answer(p);
01579 return;
01580 }
01581 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01582 if (c) {
01583
01584 openr2_chan_disable_read(r2chan);
01585 } else {
01586 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01587 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01588 return;
01589 }
01590 } else {
01591 ast_verbose("Call accepted on forward channel %d\n", p->channel);
01592 p->subs[SUB_REAL].needringing = 1;
01593 p->dialing = 0;
01594
01595 openr2_chan_disable_read(r2chan);
01596 }
01597 }
01598
01599 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01600 {
01601 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01602 ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan));
01603 p->subs[SUB_REAL].needanswer = 1;
01604 }
01605
01606 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01607 {
01608
01609 }
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01633 {
01634 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01635 ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan));
01636 ast_mutex_lock(&p->lock);
01637 if (p->owner) {
01638
01639
01640 if (p->owner->_state == AST_STATE_UP) {
01641 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01642 ast_mutex_unlock(&p->lock);
01643 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01644
01645 switch (cause) {
01646 case OR2_CAUSE_BUSY_NUMBER:
01647 p->owner->hangupcause = AST_CAUSE_BUSY;
01648 p->subs[SUB_REAL].needbusy = 1;
01649 break;
01650 case OR2_CAUSE_NUMBER_CHANGED:
01651 p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED;
01652 p->subs[SUB_REAL].needcongestion = 1;
01653 break;
01654 case OR2_CAUSE_NETWORK_CONGESTION:
01655 p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
01656 p->subs[SUB_REAL].needcongestion = 1;
01657 break;
01658 case OR2_CAUSE_OUT_OF_ORDER:
01659 p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01660 p->subs[SUB_REAL].needcongestion = 1;
01661 break;
01662 case OR2_CAUSE_UNALLOCATED_NUMBER:
01663 p->owner->hangupcause = AST_CAUSE_UNALLOCATED;
01664 p->subs[SUB_REAL].needcongestion = 1;
01665 break;
01666 case OR2_CAUSE_NO_ANSWER:
01667 p->owner->hangupcause = AST_CAUSE_NO_ANSWER;
01668 p->subs[SUB_REAL].needcongestion = 1;
01669 break;
01670 case OR2_CAUSE_UNSPECIFIED:
01671 p->owner->hangupcause = AST_CAUSE_NOTDEFINED;
01672 p->subs[SUB_REAL].needcongestion = 1;
01673 break;
01674 case OR2_CAUSE_NORMAL_CLEARING:
01675 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01676 p->subs[SUB_REAL].needcongestion = 1;
01677 break;
01678 default:
01679 ast_log(LOG_WARNING, "Unhandled cause %d\n", cause);
01680 }
01681 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01682 ast_mutex_unlock(&p->lock);
01683 } else {
01684 ast_mutex_unlock(&p->lock);
01685
01686
01687 ast_queue_hangup(p->owner);
01688 }
01689 } else {
01690 ast_mutex_unlock(&p->lock);
01691
01692 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01693 }
01694 }
01695
01696 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01697 {
01698 switch (level) {
01699 case OR2_LOG_NOTICE:
01700 ast_verbose("%s", logmessage);
01701 break;
01702 case OR2_LOG_WARNING:
01703 ast_log(LOG_WARNING, "%s", logmessage);
01704 break;
01705 case OR2_LOG_ERROR:
01706 ast_log(LOG_ERROR, "%s", logmessage);
01707 break;
01708 case OR2_LOG_STACK_TRACE:
01709 case OR2_LOG_MF_TRACE:
01710 case OR2_LOG_CAS_TRACE:
01711 case OR2_LOG_DEBUG:
01712 case OR2_LOG_EX_DEBUG:
01713 ast_log(LOG_DEBUG, "%s", logmessage);
01714 break;
01715 default:
01716 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01717 ast_log(LOG_NOTICE, "%s", logmessage);
01718 break;
01719 }
01720 }
01721
01722 #define DAHDI_R2_REMOTE_BLOCK (1 << 0)
01723 #define DAHDI_R2_LOCAL_BLOCK (1 << 1)
01724 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01725 {
01726 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01727 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel);
01728 ast_mutex_lock(&p->lock);
01729 p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK;
01730 ast_mutex_unlock(&p->lock);
01731 }
01732
01733 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01734 {
01735 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01736 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01737 ast_mutex_lock(&p->lock);
01738 p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK;
01739 ast_mutex_unlock(&p->lock);
01740 }
01741
01742 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01743 __attribute__((format (printf, 3, 0)));
01744 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01745 {
01746 char logmsg[256];
01747 char completemsg[sizeof(logmsg)+50];
01748 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01749 snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg);
01750 dahdi_r2_write_log(level, completemsg);
01751 }
01752
01753 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01754 __attribute__((format (printf, 3, 0)));
01755 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01756 {
01757 char logmsg[256];
01758 char completemsg[sizeof(logmsg)+50];
01759 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01760 snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg);
01761 dahdi_r2_write_log(level, completemsg);
01762 }
01763
01764 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01765 {
01766 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01767
01768 if (p->immediate) {
01769 return 0;
01770 }
01771 p->exten[p->mfcr2_dnis_index] = digit;
01772 p->rdnis[p->mfcr2_dnis_index] = digit;
01773 p->mfcr2_dnis_index++;
01774 p->exten[p->mfcr2_dnis_index] = 0;
01775 p->rdnis[p->mfcr2_dnis_index] = 0;
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785 if ((p->mfcr2_dnis_matched ||
01786 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
01787 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01788 return 0;
01789 }
01790
01791 return 1;
01792 }
01793
01794 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
01795 {
01796 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01797 p->cid_num[p->mfcr2_ani_index] = digit;
01798 p->cid_name[p->mfcr2_ani_index] = digit;
01799 p->mfcr2_ani_index++;
01800 p->cid_num[p->mfcr2_ani_index] = 0;
01801 p->cid_name[p->mfcr2_ani_index] = 0;
01802 }
01803
01804 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
01805 {
01806 ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
01807 }
01808
01809 static openr2_event_interface_t dahdi_r2_event_iface = {
01810 .on_call_init = dahdi_r2_on_call_init,
01811 .on_call_offered = dahdi_r2_on_call_offered,
01812 .on_call_accepted = dahdi_r2_on_call_accepted,
01813 .on_call_answered = dahdi_r2_on_call_answered,
01814 .on_call_disconnect = dahdi_r2_on_call_disconnect,
01815 .on_call_end = dahdi_r2_on_call_end,
01816 .on_call_read = dahdi_r2_on_call_read,
01817 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
01818 .on_os_error = dahdi_r2_on_os_error,
01819 .on_protocol_error = dahdi_r2_on_protocol_error,
01820 .on_line_blocked = dahdi_r2_on_line_blocked,
01821 .on_line_idle = dahdi_r2_on_line_idle,
01822
01823 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
01824 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
01825 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
01826
01827 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
01828 };
01829
01830 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
01831 {
01832 return AST_ALAW(sample);
01833 }
01834
01835 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
01836 {
01837 return AST_LIN2A(sample);
01838 }
01839
01840 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
01841 dahdi_r2_alaw_to_linear,
01842 dahdi_r2_linear_to_alaw
01843 };
01844
01845 #endif
01846
01847 static int restore_gains(struct dahdi_pvt *p);
01848
01849 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01850 {
01851 int tchan;
01852 int tinthreeway;
01853 struct ast_channel *towner;
01854
01855 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01856
01857 tchan = p->subs[a].chan;
01858 towner = p->subs[a].owner;
01859 tinthreeway = p->subs[a].inthreeway;
01860
01861 p->subs[a].chan = p->subs[b].chan;
01862 p->subs[a].owner = p->subs[b].owner;
01863 p->subs[a].inthreeway = p->subs[b].inthreeway;
01864
01865 p->subs[b].chan = tchan;
01866 p->subs[b].owner = towner;
01867 p->subs[b].inthreeway = tinthreeway;
01868
01869 if (p->subs[a].owner)
01870 p->subs[a].owner->fds[0] = p->subs[a].dfd;
01871 if (p->subs[b].owner)
01872 p->subs[b].owner->fds[0] = p->subs[b].dfd;
01873 wakeup_sub(p, a, NULL);
01874 wakeup_sub(p, b, NULL);
01875 }
01876
01877 static int dahdi_open(char *fn)
01878 {
01879 int fd;
01880 int isnum;
01881 int chan = 0;
01882 int bs;
01883 int x;
01884 isnum = 1;
01885 for (x = 0; x < strlen(fn); x++) {
01886 if (!isdigit(fn[x])) {
01887 isnum = 0;
01888 break;
01889 }
01890 }
01891 if (isnum) {
01892 chan = atoi(fn);
01893 if (chan < 1) {
01894 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01895 return -1;
01896 }
01897 fn = DAHDI_FILE_CHANNEL;
01898 }
01899 fd = open(fn, O_RDWR | O_NONBLOCK);
01900 if (fd < 0) {
01901 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01902 return -1;
01903 }
01904 if (chan) {
01905 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01906 x = errno;
01907 close(fd);
01908 errno = x;
01909 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01910 return -1;
01911 }
01912 }
01913 bs = READ_SIZE;
01914 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01915 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01916 x = errno;
01917 close(fd);
01918 errno = x;
01919 return -1;
01920 }
01921 return fd;
01922 }
01923
01924 static void dahdi_close(int fd)
01925 {
01926 if (fd > 0)
01927 close(fd);
01928 }
01929
01930 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01931 {
01932 dahdi_close(chan_pvt->subs[sub_num].dfd);
01933 chan_pvt->subs[sub_num].dfd = -1;
01934 }
01935
01936 #ifdef HAVE_PRI
01937 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01938 {
01939 dahdi_close(pri->fds[fd_num]);
01940 pri->fds[fd_num] = -1;
01941 }
01942 #endif
01943
01944 static int dahdi_setlinear(int dfd, int linear)
01945 {
01946 int res;
01947 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01948 if (res)
01949 return res;
01950 return 0;
01951 }
01952
01953
01954 static int alloc_sub(struct dahdi_pvt *p, int x)
01955 {
01956 struct dahdi_bufferinfo bi;
01957 int res;
01958 if (p->subs[x].dfd < 0) {
01959 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01960 if (p->subs[x].dfd > -1) {
01961 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01962 if (!res) {
01963 bi.txbufpolicy = p->buf_policy;
01964 bi.rxbufpolicy = p->buf_policy;
01965 bi.numbufs = p->buf_no;
01966 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01967 if (res < 0) {
01968 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01969 }
01970 } else
01971 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01972 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01973 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01974 dahdi_close_sub(p, x);
01975 return -1;
01976 }
01977 if (option_debug)
01978 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01979 return 0;
01980 } else
01981 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01982 return -1;
01983 }
01984 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01985 return -1;
01986 }
01987
01988 static int unalloc_sub(struct dahdi_pvt *p, int x)
01989 {
01990 if (!x) {
01991 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01992 return -1;
01993 }
01994 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01995 dahdi_close_sub(p, x);
01996 p->subs[x].linear = 0;
01997 p->subs[x].chan = 0;
01998 p->subs[x].owner = NULL;
01999 p->subs[x].inthreeway = 0;
02000 p->polarity = POLARITY_IDLE;
02001 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02002 return 0;
02003 }
02004
02005 static int digit_to_dtmfindex(char digit)
02006 {
02007 if (isdigit(digit))
02008 return DAHDI_TONE_DTMF_BASE + (digit - '0');
02009 else if (digit >= 'A' && digit <= 'D')
02010 return DAHDI_TONE_DTMF_A + (digit - 'A');
02011 else if (digit >= 'a' && digit <= 'd')
02012 return DAHDI_TONE_DTMF_A + (digit - 'a');
02013 else if (digit == '*')
02014 return DAHDI_TONE_DTMF_s;
02015 else if (digit == '#')
02016 return DAHDI_TONE_DTMF_p;
02017 else
02018 return -1;
02019 }
02020
02021 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02022 {
02023 struct dahdi_pvt *pvt;
02024 int index;
02025 int dtmf = -1;
02026
02027 pvt = chan->tech_pvt;
02028
02029 ast_mutex_lock(&pvt->lock);
02030
02031 index = dahdi_get_index(chan, pvt, 0);
02032
02033 if ((index != SUB_REAL) || !pvt->owner)
02034 goto out;
02035
02036 #ifdef HAVE_PRI
02037 if (pvt->sig == SIG_PRI
02038 && chan->_state == AST_STATE_DIALING) {
02039 if (pvt->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
02040 unsigned int len;
02041
02042 len = strlen(pvt->dialdest);
02043 if (len < sizeof(pvt->dialdest) - 1) {
02044 ast_log(LOG_DEBUG,
02045 "Queueing digit '%c' since setup_ack not yet received\n", digit);
02046 pvt->dialdest[len++] = digit;
02047 pvt->dialdest[len] = '\0';
02048 } else {
02049 ast_log(LOG_WARNING,
02050 "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
02051 pvt->span, digit);
02052 }
02053 goto out;
02054 }
02055 if (pvt->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
02056 if (!pri_grab(pvt, pvt->pri)) {
02057 pri_information(pvt->pri->pri, pvt->call, digit);
02058 pri_rel(pvt->pri);
02059 } else {
02060 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02061 }
02062 goto out;
02063 }
02064 if (pvt->call_level < DAHDI_CALL_LEVEL_CONNECT) {
02065 ast_log(LOG_WARNING,
02066 "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n",
02067 pvt->span, digit, pvt->call_level);
02068 }
02069 }
02070 #endif
02071 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02072 goto out;
02073
02074 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02075 int res;
02076 struct dahdi_dialoperation zo = {
02077 .op = DAHDI_DIAL_OP_APPEND,
02078 .dialstr[0] = 'T',
02079 .dialstr[1] = digit,
02080 .dialstr[2] = 0,
02081 };
02082 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02083 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02084 else
02085 pvt->dialing = 1;
02086 } else {
02087 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
02088 pvt->dialing = 1;
02089 pvt->begindigit = digit;
02090 }
02091
02092 out:
02093 ast_mutex_unlock(&pvt->lock);
02094
02095 return 0;
02096 }
02097
02098 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02099 {
02100 struct dahdi_pvt *pvt;
02101 int res = 0;
02102 int index;
02103 int x;
02104
02105 pvt = chan->tech_pvt;
02106
02107 ast_mutex_lock(&pvt->lock);
02108
02109 index = dahdi_get_index(chan, pvt, 0);
02110
02111 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
02112 goto out;
02113
02114 #ifdef HAVE_PRI
02115
02116 if (pvt->sig == SIG_PRI && !pvt->begindigit)
02117 goto out;
02118 #endif
02119
02120 if (pvt->begindigit) {
02121 x = -1;
02122 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
02123 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02124 pvt->dialing = 0;
02125 pvt->begindigit = 0;
02126 }
02127
02128 out:
02129 ast_mutex_unlock(&pvt->lock);
02130
02131 return res;
02132 }
02133
02134 static char *events[] = {
02135 "No event",
02136 "On hook",
02137 "Ring/Answered",
02138 "Wink/Flash",
02139 "Alarm",
02140 "No more alarm",
02141 "HDLC Abort",
02142 "HDLC Overrun",
02143 "HDLC Bad FCS",
02144 "Dial Complete",
02145 "Ringer On",
02146 "Ringer Off",
02147 "Hook Transition Complete",
02148 "Bits Changed",
02149 "Pulse Start",
02150 "Timer Expired",
02151 "Timer Ping",
02152 "Polarity Reversal",
02153 "Ring Begin",
02154 };
02155
02156 static struct {
02157 int alarm;
02158 char *name;
02159 } alarms[] = {
02160 { DAHDI_ALARM_RED, "Red Alarm" },
02161 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02162 { DAHDI_ALARM_BLUE, "Blue Alarm" },
02163 { DAHDI_ALARM_RECOVER, "Recovering" },
02164 { DAHDI_ALARM_LOOPBACK, "Loopback" },
02165 { DAHDI_ALARM_NOTOPEN, "Not Open" },
02166 { DAHDI_ALARM_NONE, "None" },
02167 };
02168
02169 static char *alarm2str(int alarm)
02170 {
02171 int x;
02172 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
02173 if (alarms[x].alarm & alarm)
02174 return alarms[x].name;
02175 }
02176 return alarm ? "Unknown Alarm" : "No Alarm";
02177 }
02178
02179 static char *event2str(int event)
02180 {
02181 static char buf[256];
02182 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
02183 return events[event];
02184 sprintf(buf, "Event %d", event);
02185 return buf;
02186 }
02187
02188 #ifdef HAVE_PRI
02189 static char *dialplan2str(int dialplan)
02190 {
02191 if (dialplan == -1) {
02192 return("Dynamically set dialplan in ISDN");
02193 }
02194 return (pri_plan2str(dialplan));
02195 }
02196 #endif
02197
02198 static char *dahdi_sig2str(int sig)
02199 {
02200 static char buf[256];
02201 switch (sig) {
02202 case SIG_EM:
02203 return "E & M Immediate";
02204 case SIG_EMWINK:
02205 return "E & M Wink";
02206 case SIG_EM_E1:
02207 return "E & M E1";
02208 case SIG_FEATD:
02209 return "Feature Group D (DTMF)";
02210 case SIG_FEATDMF:
02211 return "Feature Group D (MF)";
02212 case SIG_FEATDMF_TA:
02213 return "Feature Groud D (MF) Tandem Access";
02214 case SIG_FEATB:
02215 return "Feature Group B (MF)";
02216 case SIG_E911:
02217 return "E911 (MF)";
02218 case SIG_FGC_CAMA:
02219 return "FGC/CAMA (Dialpulse)";
02220 case SIG_FGC_CAMAMF:
02221 return "FGC/CAMA (MF)";
02222 case SIG_FXSLS:
02223 return "FXS Loopstart";
02224 case SIG_FXSGS:
02225 return "FXS Groundstart";
02226 case SIG_FXSKS:
02227 return "FXS Kewlstart";
02228 case SIG_FXOLS:
02229 return "FXO Loopstart";
02230 case SIG_FXOGS:
02231 return "FXO Groundstart";
02232 case SIG_FXOKS:
02233 return "FXO Kewlstart";
02234 case SIG_PRI:
02235 return "ISDN PRI";
02236 case SIG_MFCR2:
02237 return "MFC/R2";
02238 case SIG_SF:
02239 return "SF (Tone) Immediate";
02240 case SIG_SFWINK:
02241 return "SF (Tone) Wink";
02242 case SIG_SF_FEATD:
02243 return "SF (Tone) with Feature Group D (DTMF)";
02244 case SIG_SF_FEATDMF:
02245 return "SF (Tone) with Feature Group D (MF)";
02246 case SIG_SF_FEATB:
02247 return "SF (Tone) with Feature Group B (MF)";
02248 case SIG_GR303FXOKS:
02249 return "GR-303 with FXOKS";
02250 case SIG_GR303FXSKS:
02251 return "GR-303 with FXSKS";
02252 case 0:
02253 return "Pseudo";
02254 default:
02255 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02256 return buf;
02257 }
02258 }
02259
02260 #define sig2str dahdi_sig2str
02261
02262 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
02263 {
02264
02265
02266 struct dahdi_confinfo zi;
02267
02268 memset(&zi, 0, sizeof(zi));
02269 zi.chan = 0;
02270
02271 if (slavechannel > 0) {
02272
02273 zi.confmode = DAHDI_CONF_DIGITALMON;
02274 zi.confno = slavechannel;
02275 } else {
02276 if (!index) {
02277
02278 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02279 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02280 } else
02281 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02282 zi.confno = p->confno;
02283 }
02284 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02285 return 0;
02286 if (c->dfd < 0)
02287 return 0;
02288 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02289 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02290 return -1;
02291 }
02292 if (slavechannel < 1) {
02293 p->confno = zi.confno;
02294 }
02295 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02296 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02297 return 0;
02298 }
02299
02300 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02301 {
02302
02303 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02304 return 1;
02305
02306 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02307 return 1;
02308 return 0;
02309 }
02310
02311 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
02312 {
02313 struct dahdi_confinfo zi;
02314 if (
02315 (c->dfd < 0) ||
02316
02317 !isourconf(p, c)
02318
02319 ) return 0;
02320 memset(&zi, 0, sizeof(zi));
02321 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02322 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02323 return -1;
02324 }
02325 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02326 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02327 return 0;
02328 }
02329
02330 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02331 {
02332 int x;
02333 int useslavenative;
02334 struct dahdi_pvt *slave = NULL;
02335
02336 useslavenative = 1;
02337
02338 for (x = 0; x < 3; x++) {
02339
02340
02341 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02342 useslavenative = 0;
02343 }
02344
02345
02346 if (useslavenative) {
02347 for (x = 0; x < MAX_SLAVES; x++) {
02348 if (p->slaves[x]) {
02349 if (slave) {
02350
02351
02352 slave = NULL;
02353 useslavenative = 0;
02354 break;
02355 } else {
02356
02357 slave = p->slaves[x];
02358 }
02359 }
02360 }
02361 }
02362
02363 if (!slave)
02364 useslavenative = 0;
02365 else if (slave->law != p->law) {
02366 useslavenative = 0;
02367 slave = NULL;
02368 }
02369 if (out)
02370 *out = slave;
02371 return useslavenative;
02372 }
02373
02374 static int reset_conf(struct dahdi_pvt *p)
02375 {
02376 p->confno = -1;
02377 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02378 if (p->subs[SUB_REAL].dfd > -1) {
02379 struct dahdi_confinfo zi;
02380
02381 memset(&zi, 0, sizeof(zi));
02382 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02383 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02384 }
02385 return 0;
02386 }
02387
02388 static int update_conf(struct dahdi_pvt *p)
02389 {
02390 int needconf = 0;
02391 int x;
02392 int useslavenative;
02393 struct dahdi_pvt *slave = NULL;
02394
02395 useslavenative = isslavenative(p, &slave);
02396
02397 for (x = 0; x < 3; x++) {
02398
02399 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02400 conf_add(p, &p->subs[x], x, 0);
02401 needconf++;
02402 } else {
02403 conf_del(p, &p->subs[x], x);
02404 }
02405 }
02406
02407
02408 for (x = 0; x < MAX_SLAVES; x++) {
02409 if (p->slaves[x]) {
02410 if (useslavenative)
02411 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02412 else {
02413 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02414 needconf++;
02415 }
02416 }
02417 }
02418
02419 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02420 if (useslavenative)
02421 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02422 else {
02423 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02424 needconf++;
02425 }
02426 }
02427
02428 if (p->master) {
02429 if (isslavenative(p->master, NULL)) {
02430 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02431 } else {
02432 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02433 }
02434 }
02435 if (!needconf) {
02436
02437
02438 p->confno = -1;
02439 }
02440 if (option_debug)
02441 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02442 return 0;
02443 }
02444
02445 static void dahdi_enable_ec(struct dahdi_pvt *p)
02446 {
02447 int x;
02448 int res;
02449 if (!p)
02450 return;
02451 if (p->echocanon) {
02452 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
02453 return;
02454 }
02455 if (p->digital) {
02456 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
02457 return;
02458 }
02459 if (p->echocancel) {
02460 if (p->sig == SIG_PRI) {
02461 x = 1;
02462 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02463 if (res)
02464 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02465 }
02466 x = p->echocancel;
02467 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02468 if (res)
02469 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02470 else {
02471 p->echocanon = 1;
02472 if (option_debug)
02473 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
02474 }
02475 } else if (option_debug)
02476 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
02477 }
02478
02479 static void dahdi_train_ec(struct dahdi_pvt *p)
02480 {
02481 int x;
02482 int res;
02483 if (p && p->echocancel && p->echotraining) {
02484 x = p->echotraining;
02485 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02486 if (res)
02487 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02488 else {
02489 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
02490 }
02491 } else
02492 ast_log(LOG_DEBUG, "No echo training requested\n");
02493 }
02494
02495 static void dahdi_disable_ec(struct dahdi_pvt *p)
02496 {
02497 int x;
02498 int res;
02499 if (p->echocancel) {
02500 x = 0;
02501 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02502 if (res)
02503 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02504 else if (option_debug)
02505 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
02506 }
02507 p->echocanon = 0;
02508 }
02509
02510 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02511 {
02512 int j;
02513 int k;
02514 float linear_gain = pow(10.0, gain / 20.0);
02515
02516 switch (law) {
02517 case DAHDI_LAW_ALAW:
02518 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02519 if (gain) {
02520 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02521 if (k > 32767) k = 32767;
02522 if (k < -32767) k = -32767;
02523 g->txgain[j] = AST_LIN2A(k);
02524 } else {
02525 g->txgain[j] = j;
02526 }
02527 }
02528 break;
02529 case DAHDI_LAW_MULAW:
02530 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02531 if (gain) {
02532 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02533 if (k > 32767) k = 32767;
02534 if (k < -32767) k = -32767;
02535 g->txgain[j] = AST_LIN2MU(k);
02536 } else {
02537 g->txgain[j] = j;
02538 }
02539 }
02540 break;
02541 }
02542 }
02543
02544 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02545 {
02546 int j;
02547 int k;
02548 float linear_gain = pow(10.0, gain / 20.0);
02549
02550 switch (law) {
02551 case DAHDI_LAW_ALAW:
02552 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02553 if (gain) {
02554 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02555 if (k > 32767) k = 32767;
02556 if (k < -32767) k = -32767;
02557 g->rxgain[j] = AST_LIN2A(k);
02558 } else {
02559 g->rxgain[j] = j;
02560 }
02561 }
02562 break;
02563 case DAHDI_LAW_MULAW:
02564 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02565 if (gain) {
02566 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02567 if (k > 32767) k = 32767;
02568 if (k < -32767) k = -32767;
02569 g->rxgain[j] = AST_LIN2MU(k);
02570 } else {
02571 g->rxgain[j] = j;
02572 }
02573 }
02574 break;
02575 }
02576 }
02577
02578 static int set_actual_txgain(int fd, int chan, float gain, int law)
02579 {
02580 struct dahdi_gains g;
02581 int res;
02582
02583 memset(&g, 0, sizeof(g));
02584 g.chan = chan;
02585 res = ioctl(fd, DAHDI_GETGAINS, &g);
02586 if (res) {
02587 if (option_debug)
02588 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02589 return res;
02590 }
02591
02592 fill_txgain(&g, gain, law);
02593
02594 return ioctl(fd, DAHDI_SETGAINS, &g);
02595 }
02596
02597 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02598 {
02599 struct dahdi_gains g;
02600 int res;
02601
02602 memset(&g, 0, sizeof(g));
02603 g.chan = chan;
02604 res = ioctl(fd, DAHDI_GETGAINS, &g);
02605 if (res) {
02606 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02607 return res;
02608 }
02609
02610 fill_rxgain(&g, gain, law);
02611
02612 return ioctl(fd, DAHDI_SETGAINS, &g);
02613 }
02614
02615 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02616 {
02617 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02618 }
02619
02620 static int bump_gains(struct dahdi_pvt *p)
02621 {
02622 int res;
02623
02624
02625 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
02626 if (res) {
02627 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02628 return -1;
02629 }
02630
02631 return 0;
02632 }
02633
02634 static int restore_gains(struct dahdi_pvt *p)
02635 {
02636 int res;
02637
02638 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02639 if (res) {
02640 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02641 return -1;
02642 }
02643
02644 return 0;
02645 }
02646
02647 static inline int dahdi_set_hook(int fd, int hs)
02648 {
02649 int x, res;
02650
02651 x = hs;
02652 res = ioctl(fd, DAHDI_HOOK, &x);
02653
02654 if (res < 0) {
02655 if (errno == EINPROGRESS)
02656 return 0;
02657 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02658
02659 }
02660
02661 return res;
02662 }
02663
02664 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02665 {
02666 int x, y, res;
02667 x = muted;
02668 if (p->sig == SIG_PRI) {
02669 y = 1;
02670 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02671 if (res)
02672 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02673 }
02674 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02675 if (res < 0)
02676 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02677 return res;
02678 }
02679
02680 static int save_conference(struct dahdi_pvt *p)
02681 {
02682 struct dahdi_confinfo c;
02683 int res;
02684 if (p->saveconf.confmode) {
02685 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02686 return -1;
02687 }
02688 p->saveconf.chan = 0;
02689 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02690 if (res) {
02691 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02692 p->saveconf.confmode = 0;
02693 return -1;
02694 }
02695 memset(&c, 0, sizeof(c));
02696 c.confmode = DAHDI_CONF_NORMAL;
02697 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02698 if (res) {
02699 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02700 return -1;
02701 }
02702 if (option_debug)
02703 ast_log(LOG_DEBUG, "Disabled conferencing\n");
02704 return 0;
02705 }
02706
02707 static int restore_conference(struct dahdi_pvt *p)
02708 {
02709 int res;
02710 if (p->saveconf.confmode) {
02711 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02712 p->saveconf.confmode = 0;
02713 if (res) {
02714 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02715 return -1;
02716 }
02717 if (option_debug)
02718 ast_log(LOG_DEBUG, "Restored conferencing\n");
02719 }
02720 return 0;
02721 }
02722
02723 static int send_callerid(struct dahdi_pvt *p);
02724
02725 static int send_cwcidspill(struct dahdi_pvt *p)
02726 {
02727 p->callwaitcas = 0;
02728 p->cidcwexpire = 0;
02729 p->cid_suppress_expire = 0;
02730 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02731 return -1;
02732 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02733
02734 p->cidlen += READ_SIZE * 4;
02735 p->cidpos = 0;
02736 send_callerid(p);
02737 if (option_verbose > 2)
02738 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02739 return 0;
02740 }
02741
02742 static int has_voicemail(struct dahdi_pvt *p)
02743 {
02744
02745 return ast_app_has_voicemail(p->mailbox, NULL);
02746 }
02747
02748 static int send_callerid(struct dahdi_pvt *p)
02749 {
02750
02751 int res;
02752
02753 if (p->subs[SUB_REAL].linear) {
02754 p->subs[SUB_REAL].linear = 0;
02755 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02756 }
02757 while (p->cidpos < p->cidlen) {
02758 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02759 if (res < 0) {
02760 if (errno == EAGAIN)
02761 return 0;
02762 else {
02763 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02764 return -1;
02765 }
02766 }
02767 if (!res)
02768 return 0;
02769 p->cidpos += res;
02770 }
02771 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
02772 free(p->cidspill);
02773 p->cidspill = NULL;
02774 if (p->callwaitcas) {
02775
02776 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02777 p->cid_suppress_expire = p->cidcwexpire;
02778 } else
02779 restore_conference(p);
02780 return 0;
02781 }
02782
02783 static int dahdi_callwait(struct ast_channel *ast)
02784 {
02785 struct dahdi_pvt *p = ast->tech_pvt;
02786 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02787 if (p->cidspill) {
02788 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02789 free(p->cidspill);
02790 }
02791
02792
02793
02794
02795
02796 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02797 return -1;
02798 save_conference(p);
02799
02800 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02801 if (!p->callwaitrings && p->callwaitingcallerid) {
02802 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02803 p->callwaitcas = 1;
02804 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02805 } else {
02806 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02807 p->callwaitcas = 0;
02808 p->cidlen = 2400 + READ_SIZE * 4;
02809 }
02810 p->cidpos = 0;
02811 send_callerid(p);
02812
02813 return 0;
02814 }
02815
02816 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02817 {
02818 struct dahdi_pvt *p = ast->tech_pvt;
02819 int x, res, index,mysig;
02820 char *c, *n, *l;
02821 #ifdef HAVE_PRI
02822 char *s = NULL;
02823 #endif
02824 char dest[256];
02825 ast_mutex_lock(&p->lock);
02826 ast_copy_string(dest, rdest, sizeof(dest));
02827 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02828 if ((ast->_state == AST_STATE_BUSY)) {
02829 p->subs[SUB_REAL].needbusy = 1;
02830 ast_mutex_unlock(&p->lock);
02831 return 0;
02832 }
02833 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02834 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02835 ast_mutex_unlock(&p->lock);
02836 return -1;
02837 }
02838 p->dialednone = 0;
02839 if ((p->radio || (p->oprmode < 0)))
02840 {
02841
02842 ast_setstate(ast, AST_STATE_UP);
02843 ast_mutex_unlock(&p->lock);
02844 return 0;
02845 }
02846 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02847 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02848 if (res)
02849 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02850 p->outgoing = 1;
02851
02852 if (IS_DIGITAL(ast->transfercapability)) {
02853 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02854 } else {
02855 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02856 }
02857
02858 mysig = p->sig;
02859 if (p->outsigmod > -1)
02860 mysig = p->outsigmod;
02861
02862 switch (mysig) {
02863 case SIG_FXOLS:
02864 case SIG_FXOGS:
02865 case SIG_FXOKS:
02866 if (p->owner == ast) {
02867
02868
02869
02870 p->dialing = 1;
02871 if (p->use_callerid) {
02872
02873 if (p->cidspill) {
02874 ast_log(LOG_WARNING, "cidspill already exists??\n");
02875 free(p->cidspill);
02876 }
02877 p->callwaitcas = 0;
02878 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02879 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02880 p->cidpos = 0;
02881 send_callerid(p);
02882 }
02883 }
02884
02885 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02886 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02887 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02888 p->cidrings = cidrings[p->distinctivering - 1];
02889 } else {
02890 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02891 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02892 p->cidrings = p->sendcalleridafter;
02893 }
02894
02895
02896 c = strchr(dest, '/');
02897 if (c)
02898 c++;
02899 if (c && (strlen(c) < p->stripmsd)) {
02900 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02901 c = NULL;
02902 }
02903 if (c) {
02904 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02905 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02906 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02907 } else {
02908 p->dop.dialstr[0] = '\0';
02909 }
02910 x = DAHDI_RING;
02911 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02912 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02913 ast_mutex_unlock(&p->lock);
02914 return -1;
02915 }
02916 p->dialing = 1;
02917 } else {
02918
02919 p->callwaitrings = 0;
02920 if (ast->cid.cid_num)
02921 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02922 else
02923 p->callwait_num[0] = '\0';
02924 if (ast->cid.cid_name)
02925 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02926 else
02927 p->callwait_name[0] = '\0';
02928
02929 if (dahdi_callwait(ast)) {
02930 ast_mutex_unlock(&p->lock);
02931 return -1;
02932 }
02933
02934 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02935 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02936
02937 }
02938 n = ast->cid.cid_name;
02939 l = ast->cid.cid_num;
02940 if (l)
02941 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02942 else
02943 p->lastcid_num[0] = '\0';
02944 if (n)
02945 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02946 else
02947 p->lastcid_name[0] = '\0';
02948 ast_setstate(ast, AST_STATE_RINGING);
02949 index = dahdi_get_index(ast, p, 0);
02950 if (index > -1) {
02951 p->subs[index].needringing = 1;
02952 }
02953 break;
02954 case SIG_FXSLS:
02955 case SIG_FXSGS:
02956 case SIG_FXSKS:
02957 case SIG_EMWINK:
02958 case SIG_EM:
02959 case SIG_EM_E1:
02960 case SIG_FEATD:
02961 case SIG_FEATDMF:
02962 case SIG_E911:
02963 case SIG_FGC_CAMA:
02964 case SIG_FGC_CAMAMF:
02965 case SIG_FEATB:
02966 case SIG_SFWINK:
02967 case SIG_SF:
02968 case SIG_SF_FEATD:
02969 case SIG_SF_FEATDMF:
02970 case SIG_FEATDMF_TA:
02971 case SIG_SF_FEATB:
02972 c = strchr(dest, '/');
02973 if (c)
02974 c++;
02975 else
02976 c = "";
02977 if (strlen(c) < p->stripmsd) {
02978 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02979 ast_mutex_unlock(&p->lock);
02980 return -1;
02981 }
02982 #ifdef HAVE_PRI
02983
02984 if (!p->pri) {
02985 #endif
02986 x = DAHDI_START;
02987 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02988 if (res < 0) {
02989 if (errno != EINPROGRESS) {
02990 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02991 ast_mutex_unlock(&p->lock);
02992 return -1;
02993 }
02994 }
02995 #ifdef HAVE_PRI
02996 }
02997 #endif
02998 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02999 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03000
03001 c += p->stripmsd;
03002
03003 switch (mysig) {
03004 case SIG_FEATD:
03005 l = ast->cid.cid_num;
03006 if (l)
03007 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03008 else
03009 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03010 break;
03011 case SIG_FEATDMF:
03012 l = ast->cid.cid_num;
03013 if (l)
03014 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03015 else
03016 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03017 break;
03018 case SIG_FEATDMF_TA:
03019 {
03020 const char *cic, *ozz;
03021
03022
03023 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03024 if (!ozz)
03025 ozz = defaultozz;
03026 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03027 if (!cic)
03028 cic = defaultcic;
03029 if (!ozz || !cic) {
03030 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03031 ast_mutex_unlock(&p->lock);
03032 return -1;
03033 }
03034 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03035 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03036 p->whichwink = 0;
03037 }
03038 break;
03039 case SIG_E911:
03040 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03041 break;
03042 case SIG_FGC_CAMA:
03043 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03044 break;
03045 case SIG_FGC_CAMAMF:
03046 case SIG_FEATB:
03047 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03048 break;
03049 default:
03050 if (p->pulse)
03051 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03052 else
03053 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03054 break;
03055 }
03056
03057 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03058 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03059 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03060 p->echorest[sizeof(p->echorest) - 1] = '\0';
03061 p->echobreak = 1;
03062 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03063 } else
03064 p->echobreak = 0;
03065 if (!res) {
03066 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03067 int saveerr = errno;
03068
03069 x = DAHDI_ONHOOK;
03070 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03071 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03072 ast_mutex_unlock(&p->lock);
03073 return -1;
03074 }
03075 } else
03076 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res);
03077 p->dialing = 1;
03078 if (ast_strlen_zero(c))
03079 p->dialednone = 1;
03080 ast_setstate(ast, AST_STATE_DIALING);
03081 break;
03082 case 0:
03083
03084 ast_setstate(ast, AST_STATE_UP);
03085 break;
03086 case SIG_PRI:
03087 case SIG_MFCR2:
03088
03089 p->dialdest[0] = '\0';
03090 p->dialing = 1;
03091 break;
03092 default:
03093 ast_log(LOG_DEBUG, "not yet implemented\n");
03094 ast_mutex_unlock(&p->lock);
03095 return -1;
03096 }
03097
03098 #ifdef HAVE_OPENR2
03099 if (p->mfcr2) {
03100 int strip = p->stripmsd;
03101 int callres = 0;
03102 c = strchr(dest, '/');
03103 if (c) {
03104 c++;
03105 } else {
03106 c = dest;
03107 }
03108 if (!p->hidecallerid) {
03109 l = ast->cid.cid_num;
03110 } else {
03111 l = NULL;
03112 }
03113 if (strlen(c) < strip) {
03114 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
03115 strip = 0;
03116 }
03117 p->dialing = 1;
03118 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast));
03119 if (-1 == callres) {
03120 ast_mutex_unlock(&p->lock);
03121 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03122 return -1;
03123 }
03124 ast_setstate(ast, AST_STATE_DIALING);
03125 }
03126 #endif
03127
03128 #ifdef HAVE_PRI
03129 if (p->pri) {
03130 struct pri_sr *sr;
03131 #ifdef SUPPORT_USERUSER
03132 const char *useruser;
03133 #endif
03134 int pridialplan;
03135 int dp_strip;
03136 int prilocaldialplan;
03137 int ldp_strip;
03138 int exclusive;
03139 const char *rr_str;
03140 int redirect_reason;
03141
03142 c = strchr(dest, '/');
03143 if (c) {
03144 c++;
03145 } else {
03146 c = "";
03147 }
03148
03149 l = NULL;
03150 n = NULL;
03151 if (!p->hidecallerid) {
03152 l = ast->cid.cid_num;
03153 if (!p->hidecalleridname) {
03154 n = ast->cid.cid_name;
03155 }
03156 }
03157
03158
03159 if (strlen(c) < p->stripmsd) {
03160 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03161 ast_mutex_unlock(&p->lock);
03162 return -1;
03163 }
03164 if (mysig != SIG_FXSKS) {
03165 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03166 s = strchr(c + p->stripmsd, 'w');
03167 if (s) {
03168 if (strlen(s) > 1)
03169 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03170 else
03171 p->dop.dialstr[0] = '\0';
03172 *s = '\0';
03173 } else {
03174 p->dop.dialstr[0] = '\0';
03175 }
03176 }
03177 if (pri_grab(p, p->pri)) {
03178 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03179 ast_mutex_unlock(&p->lock);
03180 return -1;
03181 }
03182 if (!(p->call = pri_new_call(p->pri->pri))) {
03183 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03184 pri_rel(p->pri);
03185 ast_mutex_unlock(&p->lock);
03186 return -1;
03187 }
03188 if (!(sr = pri_sr_new())) {
03189 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03190 pri_destroycall(p->pri->pri, p->call);
03191 p->call = NULL;
03192 pri_rel(p->pri);
03193 ast_mutex_unlock(&p->lock);
03194 return -1;
03195 }
03196 if (p->bearer || (mysig == SIG_FXSKS)) {
03197 if (p->bearer) {
03198 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);
03199 p->bearer->call = p->call;
03200 } else
03201 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
03202 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03203 }
03204 p->digital = IS_DIGITAL(ast->transfercapability);
03205
03206
03207 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03208 exclusive = 1;
03209 } else {
03210 exclusive = 0;
03211 }
03212
03213 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03214 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03215 (p->digital ? -1 :
03216 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03217 if (p->pri->facilityenable)
03218 pri_facility_enable(p->pri->pri);
03219
03220 if (option_verbose > 2)
03221 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03222 dp_strip = 0;
03223 pridialplan = p->pri->dialplan - 1;
03224 if (pridialplan == -2) {
03225 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03226 dp_strip = strlen(p->pri->internationalprefix);
03227 pridialplan = PRI_INTERNATIONAL_ISDN;
03228 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03229 dp_strip = strlen(p->pri->nationalprefix);
03230 pridialplan = PRI_NATIONAL_ISDN;
03231 } else {
03232 pridialplan = PRI_LOCAL_ISDN;
03233 }
03234 }
03235 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03236
03237 ldp_strip = 0;
03238 prilocaldialplan = p->pri->localdialplan - 1;
03239 if ((l != NULL) && (prilocaldialplan == -2)) {
03240 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03241 ldp_strip = strlen(p->pri->internationalprefix);
03242 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03243 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03244 ldp_strip = strlen(p->pri->nationalprefix);
03245 prilocaldialplan = PRI_NATIONAL_ISDN;
03246 } else {
03247 prilocaldialplan = PRI_LOCAL_ISDN;
03248 }
03249 }
03250 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03251 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03252 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03253 if (!strcasecmp(rr_str, "UNKNOWN"))
03254 redirect_reason = 0;
03255 else if (!strcasecmp(rr_str, "BUSY"))
03256 redirect_reason = 1;
03257 else if (!strcasecmp(rr_str, "NO_REPLY"))
03258 redirect_reason = 2;
03259 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03260 redirect_reason = 15;
03261 else
03262 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03263 } else
03264 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03265 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03266
03267 #ifdef SUPPORT_USERUSER
03268
03269 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03270
03271 if (useruser)
03272 pri_sr_set_useruser(sr, useruser);
03273 #endif
03274
03275 if (pri_setup(p->pri->pri, p->call, sr)) {
03276 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03277 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03278 pri_destroycall(p->pri->pri, p->call);
03279 p->call = NULL;
03280 pri_rel(p->pri);
03281 ast_mutex_unlock(&p->lock);
03282 pri_sr_free(sr);
03283 return -1;
03284 }
03285 p->call_level = DAHDI_CALL_LEVEL_SETUP;
03286 pri_sr_free(sr);
03287 ast_setstate(ast, AST_STATE_DIALING);
03288 pri_rel(p->pri);
03289 }
03290 #endif
03291 ast_mutex_unlock(&p->lock);
03292 return 0;
03293 }
03294
03295 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03296 {
03297 struct dahdi_pvt *p = *pvt;
03298
03299 if (p->prev)
03300 p->prev->next = p->next;
03301 if (p->next)
03302 p->next->prev = p->prev;
03303
03304 free(p->cidspill);
03305 if (p->use_smdi)
03306 ast_smdi_interface_unref(p->smdi_iface);
03307 ast_mutex_destroy(&p->lock);
03308 dahdi_close_sub(p, SUB_REAL);
03309 if (p->owner)
03310 p->owner->tech_pvt = NULL;
03311 free(p);
03312 *pvt = NULL;
03313 }
03314
03315 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03316 {
03317 int owned = 0;
03318 int i = 0;
03319
03320 if (!now) {
03321 if (cur->owner) {
03322 owned = 1;
03323 }
03324
03325 for (i = 0; i < 3; i++) {
03326 if (cur->subs[i].owner) {
03327 owned = 1;
03328 }
03329 }
03330 if (!owned) {
03331 if (prev) {
03332 prev->next = cur->next;
03333 if (prev->next)
03334 prev->next->prev = prev;
03335 else
03336 ifend = prev;
03337 } else {
03338 iflist = cur->next;
03339 if (iflist)
03340 iflist->prev = NULL;
03341 else
03342 ifend = NULL;
03343 }
03344 destroy_dahdi_pvt(&cur);
03345 }
03346 } else {
03347 if (prev) {
03348 prev->next = cur->next;
03349 if (prev->next)
03350 prev->next->prev = prev;
03351 else
03352 ifend = prev;
03353 } else {
03354 iflist = cur->next;
03355 if (iflist)
03356 iflist->prev = NULL;
03357 else
03358 ifend = NULL;
03359 }
03360 destroy_dahdi_pvt(&cur);
03361 }
03362 return 0;
03363 }
03364
03365 static void destroy_all_channels(void)
03366 {
03367 int x;
03368 struct dahdi_pvt *p, *pl;
03369
03370 while (num_restart_pending) {
03371 usleep(1);
03372 }
03373
03374 ast_mutex_lock(&iflock);
03375
03376 p = iflist;
03377 while (p) {
03378 pl = p;
03379 p = p->next;
03380 x = pl->channel;
03381
03382 destroy_dahdi_pvt(&pl);
03383 if (option_verbose > 2)
03384 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03385 }
03386 iflist = NULL;
03387 ifcount = 0;
03388 ast_mutex_unlock(&iflock);
03389 }
03390
03391 #ifdef HAVE_PRI
03392 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03393 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
03394
03395 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03396 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03397
03398 static char *dahdi_send_keypad_facility_descrip =
03399 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03400 " IE over the current channel.\n";
03401 static char *zap_send_keypad_facility_descrip =
03402 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03403 " IE over the current channel.\n";
03404
03405 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
03406 {
03407
03408 struct dahdi_pvt *p;
03409 char *digits = (char *) data;
03410
03411 if (ast_strlen_zero(digits)) {
03412 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
03413 return -1;
03414 }
03415
03416 p = (struct dahdi_pvt *)chan->tech_pvt;
03417
03418 if (!p) {
03419 ast_log(LOG_DEBUG, "Unable to find technology private\n");
03420 return -1;
03421 }
03422
03423 ast_mutex_lock(&p->lock);
03424
03425 if (!p->pri || !p->call) {
03426 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
03427 ast_mutex_unlock(&p->lock);
03428 return -1;
03429 }
03430
03431 if (!pri_grab(p, p->pri)) {
03432 pri_keypad_facility(p->pri->pri, p->call, digits);
03433 pri_rel(p->pri);
03434 } else {
03435 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
03436 ast_mutex_unlock(&p->lock);
03437 return -1;
03438 }
03439
03440 ast_mutex_unlock(&p->lock);
03441
03442 return 0;
03443 }
03444
03445 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03446 {
03447 return send_keypad_facility_exec(chan, data);
03448 }
03449
03450 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03451 {
03452 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);
03453 return send_keypad_facility_exec(chan, data);
03454 }
03455
03456 static int pri_is_up(struct dahdi_pri *pri)
03457 {
03458 int x;
03459 for (x = 0; x < NUM_DCHANS; x++) {
03460 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03461 return 1;
03462 }
03463 return 0;
03464 }
03465
03466 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03467 {
03468 bearer->owner = &inuse;
03469 bearer->realcall = crv;
03470 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03471 if (crv->subs[SUB_REAL].owner)
03472 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03473 crv->bearer = bearer;
03474 crv->call = bearer->call;
03475 crv->pri = pri;
03476 return 0;
03477 }
03478
03479 static char *pri_order(int level)
03480 {
03481 switch (level) {
03482 case 0:
03483 return "Primary";
03484 case 1:
03485 return "Secondary";
03486 case 2:
03487 return "Tertiary";
03488 case 3:
03489 return "Quaternary";
03490 default:
03491 return "<Unknown>";
03492 }
03493 }
03494
03495
03496 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03497 {
03498 int x = -1;
03499
03500 for (x = 0; x < NUM_DCHANS; x++) {
03501 if ((pri->dchans[x] == pri->pri))
03502 break;
03503 }
03504
03505 return pri->fds[x];
03506 }
03507
03508 static int pri_find_dchan(struct dahdi_pri *pri)
03509 {
03510 int oldslot = -1;
03511 struct pri *old;
03512 int newslot = -1;
03513 int x;
03514 old = pri->pri;
03515 for (x = 0; x < NUM_DCHANS; x++) {
03516 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03517 newslot = x;
03518 if (pri->dchans[x] == old) {
03519 oldslot = x;
03520 }
03521 }
03522 if (newslot < 0) {
03523 newslot = 0;
03524 if (!pri->no_d_channels) {
03525 pri->no_d_channels = 1;
03526 ast_log(LOG_WARNING,
03527 "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03528 pri->dchannels[newslot]);
03529 }
03530 } else {
03531 pri->no_d_channels = 0;
03532 }
03533 if (old && (oldslot != newslot))
03534 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03535 pri->dchannels[oldslot], pri->dchannels[newslot]);
03536 pri->pri = pri->dchans[newslot];
03537 return 0;
03538 }
03539 #endif
03540
03541 #ifdef HAVE_OPENR2
03542 static char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
03543 static char *zap_accept_r2_call_app = "ZapAcceptR2Call";
03544
03545 static char *dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03546 static char *zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03547
03548 static char *dahdi_accept_r2_call_descrip =
03549 " DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03550 " You can specify yes or no as argument to accept with or without charge.\n";
03551
03552 static char *zap_accept_r2_call_descrip =
03553 " ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03554 " You can specify yes or no as argument to accept with or without charge.\n";
03555
03556 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
03557 {
03558
03559 openr2_call_mode_t accept_mode;
03560 int res, timeout, maxloops;
03561 struct ast_frame *f;
03562 struct dahdi_pvt *p;
03563 char *parse;
03564 AST_DECLARE_APP_ARGS(args,
03565 AST_APP_ARG(charge);
03566 );
03567
03568 if (ast_strlen_zero(data)) {
03569 ast_log(LOG_DEBUG, "No data sent to application!\n");
03570 return -1;
03571 }
03572
03573 if (chan->tech != &dahdi_tech) {
03574 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
03575 return -1;
03576 }
03577
03578 p = (struct dahdi_pvt *)chan->tech_pvt;
03579 if (!p) {
03580 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
03581 return -1;
03582 }
03583
03584 parse = ast_strdupa(data);
03585 AST_STANDARD_APP_ARGS(args, parse);
03586
03587 if (ast_strlen_zero(args.charge)) {
03588 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
03589 return -1;
03590 }
03591
03592 ast_mutex_lock(&p->lock);
03593 if (!p->mfcr2 || !p->mfcr2call) {
03594 ast_mutex_unlock(&p->lock);
03595 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
03596 return -1;
03597 }
03598
03599 if (p->mfcr2_call_accepted) {
03600 ast_mutex_unlock(&p->lock);
03601 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
03602 return 0;
03603 }
03604 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
03605 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
03606 ast_mutex_unlock(&p->lock);
03607 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03608 return -1;
03609 }
03610 ast_mutex_unlock(&p->lock);
03611
03612 res = 0;
03613 timeout = 100;
03614 maxloops = 50;
03615
03616 while (maxloops > 0) {
03617 maxloops--;
03618 if (ast_check_hangup(chan)) {
03619 break;
03620 }
03621 res = ast_waitfor(chan, timeout);
03622 if (res < 0) {
03623 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
03624 res = -1;
03625 break;
03626 }
03627 if (res == 0) {
03628 continue;
03629 }
03630 f = ast_read(chan);
03631 if (!f) {
03632 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
03633 res = -1;
03634 break;
03635 }
03636 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
03637 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
03638 ast_frfree(f);
03639 res = -1;
03640 break;
03641 }
03642 ast_frfree(f);
03643 ast_mutex_lock(&p->lock);
03644 if (p->mfcr2_call_accepted) {
03645 ast_mutex_unlock(&p->lock);
03646 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
03647 break;
03648 }
03649 ast_mutex_unlock(&p->lock);
03650 }
03651 if (res == -1) {
03652 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03653 }
03654 return res;
03655 }
03656
03657 static int zap_accept_r2_call_exec(struct ast_channel *chan, void *data)
03658 {
03659 return dahdi_accept_r2_call_exec(chan, data);
03660 }
03661
03662 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
03663 {
03664 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
03665 switch (cause) {
03666 case AST_CAUSE_USER_BUSY:
03667 case AST_CAUSE_CALL_REJECTED:
03668 case AST_CAUSE_INTERWORKING:
03669 r2cause = OR2_CAUSE_BUSY_NUMBER;
03670 break;
03671
03672 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
03673 case AST_CAUSE_SWITCH_CONGESTION:
03674 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
03675 break;
03676
03677 case AST_CAUSE_UNALLOCATED:
03678 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
03679 break;
03680
03681 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
03682 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03683 r2cause = OR2_CAUSE_OUT_OF_ORDER;
03684 break;
03685
03686 case AST_CAUSE_NO_ANSWER:
03687 case AST_CAUSE_NO_USER_RESPONSE:
03688 r2cause = OR2_CAUSE_NO_ANSWER;
03689 break;
03690
03691 default:
03692 r2cause = OR2_CAUSE_NORMAL_CLEARING;
03693 break;
03694 }
03695 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n",
03696 r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
03697 return r2cause;
03698 }
03699 #endif
03700
03701 static int dahdi_hangup(struct ast_channel *ast)
03702 {
03703 int res;
03704 int index,x, law;
03705
03706 struct dahdi_pvt *p = ast->tech_pvt;
03707 struct dahdi_pvt *tmp = NULL;
03708 struct dahdi_pvt *prev = NULL;
03709 struct dahdi_params par;
03710
03711 if (option_debug)
03712 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
03713 if (!ast->tech_pvt) {
03714 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03715 return 0;
03716 }
03717
03718 ast_mutex_lock(&p->lock);
03719
03720 index = dahdi_get_index(ast, p, 1);
03721
03722 if (p->sig == SIG_PRI) {
03723 x = 1;
03724 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03725 p->cid_num[0] = '\0';
03726 p->cid_name[0] = '\0';
03727 }
03728
03729 x = 0;
03730 dahdi_confmute(p, 0);
03731 restore_gains(p);
03732 if (p->origcid_num) {
03733 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03734 free(p->origcid_num);
03735 p->origcid_num = NULL;
03736 }
03737 if (p->origcid_name) {
03738 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03739 free(p->origcid_name);
03740 p->origcid_name = NULL;
03741 }
03742 if (p->dsp)
03743 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03744 p->exten[0] = '\0';
03745
03746 if (option_debug)
03747 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03748 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03749 p->ignoredtmf = 0;
03750
03751 if (index > -1) {
03752
03753 p->subs[index].owner = NULL;
03754 p->subs[index].needanswer = 0;
03755 p->subs[index].needflash = 0;
03756 p->subs[index].needringing = 0;
03757 p->subs[index].needbusy = 0;
03758 p->subs[index].needcongestion = 0;
03759 p->subs[index].linear = 0;
03760 p->subs[index].needcallerid = 0;
03761 p->polarity = POLARITY_IDLE;
03762 dahdi_setlinear(p->subs[index].dfd, 0);
03763 switch (index) {
03764 case SUB_REAL:
03765 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03766 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
03767 if (p->subs[SUB_CALLWAIT].inthreeway) {
03768
03769 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
03770
03771 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03772 unalloc_sub(p, SUB_CALLWAIT);
03773 p->owner = NULL;
03774 } else {
03775
03776 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03777 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03778 unalloc_sub(p, SUB_THREEWAY);
03779 if (p->subs[SUB_REAL].inthreeway) {
03780
03781
03782 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03783 p->subs[SUB_REAL].inthreeway = 0;
03784 p->owner = p->subs[SUB_REAL].owner;
03785 } else {
03786
03787 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03788 p->owner = NULL;
03789 }
03790 }
03791 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03792
03793 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
03794 if (!p->subs[SUB_CALLWAIT].owner) {
03795
03796 p->owner = NULL;
03797 break;
03798 }
03799
03800
03801 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03802 unalloc_sub(p, SUB_CALLWAIT);
03803 p->owner = p->subs[SUB_REAL].owner;
03804 if (p->owner->_state != AST_STATE_UP)
03805 p->subs[SUB_REAL].needanswer = 1;
03806 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03807 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03808
03809 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03810 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03811 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03812 unalloc_sub(p, SUB_THREEWAY);
03813 if (p->subs[SUB_REAL].inthreeway) {
03814
03815
03816 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03817 p->subs[SUB_REAL].inthreeway = 0;
03818 p->owner = p->subs[SUB_REAL].owner;
03819 } else {
03820
03821 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03822 p->owner = NULL;
03823 }
03824 }
03825 break;
03826 case SUB_CALLWAIT:
03827
03828 if (p->subs[SUB_CALLWAIT].inthreeway) {
03829
03830 dahdi_lock_sub_owner(p, SUB_THREEWAY);
03831
03832
03833
03834 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03835 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03836 S_OR(p->mohsuggest, NULL),
03837 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03838 }
03839 p->subs[SUB_THREEWAY].inthreeway = 0;
03840
03841 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03842 unalloc_sub(p, SUB_THREEWAY);
03843 if (p->subs[SUB_CALLWAIT].owner) {
03844
03845 ast_mutex_unlock(&p->subs[SUB_CALLWAIT].owner->lock);
03846 }
03847 } else
03848 unalloc_sub(p, SUB_CALLWAIT);
03849 break;
03850 case SUB_THREEWAY:
03851
03852 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
03853 if (p->subs[SUB_CALLWAIT].inthreeway) {
03854
03855
03856 p->subs[SUB_CALLWAIT].inthreeway = 0;
03857 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03858 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03859 S_OR(p->mohsuggest, NULL),
03860 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03861 }
03862 }
03863 if (p->subs[SUB_CALLWAIT].owner) {
03864 ast_mutex_unlock(&p->subs[SUB_CALLWAIT].owner->lock);
03865 }
03866 p->subs[SUB_REAL].inthreeway = 0;
03867
03868
03869 unalloc_sub(p, SUB_THREEWAY);
03870 break;
03871 default:
03872
03873
03874
03875
03876 ast_log(LOG_ERROR, "Index found but not any type of call?\n");
03877 break;
03878 }
03879 }
03880
03881 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03882 p->ringt = 0;
03883 p->distinctivering = 0;
03884 p->confirmanswer = 0;
03885 p->cidrings = 1;
03886 p->outgoing = 0;
03887 p->digital = 0;
03888 p->faxhandled = 0;
03889 p->pulsedial = 0;
03890 p->onhooktime = time(NULL);
03891 #ifdef HAVE_PRI
03892 p->dialing = 0;
03893 p->progress = 0;
03894 p->call_level = DAHDI_CALL_LEVEL_IDLE;
03895 #endif
03896 if (p->dsp) {
03897 ast_dsp_free(p->dsp);
03898 p->dsp = NULL;
03899 }
03900
03901 if (p->bufferoverrideinuse) {
03902
03903 struct dahdi_bufferinfo bi = {
03904 .txbufpolicy = p->buf_policy,
03905 .rxbufpolicy = p->buf_policy,
03906 .bufsize = p->bufsize,
03907 .numbufs = p->buf_no
03908 };
03909 int bpres;
03910
03911 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
03912 ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
03913 }
03914 p->bufferoverrideinuse = 0;
03915 }
03916
03917 law = DAHDI_LAW_DEFAULT;
03918 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03919 if (res < 0)
03920 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03921
03922
03923 #ifdef HAVE_OPENR2
03924 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
03925 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
03926 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
03927 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
03928 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
03929 } else {
03930 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
03931 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
03932 openr2_call_disconnect_cause_t r2cause = r2cause_user
03933 ? dahdi_ast_cause_to_r2_cause(r2cause_user)
03934 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
03935 dahdi_r2_disconnect_call(p, r2cause);
03936 }
03937 } else if (p->mfcr2call) {
03938 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
03939 p->mfcr2call = 0;
03940 }
03941 #endif
03942
03943 #if defined(HAVE_PRI)
03944 if (p->pri) {
03945 #ifdef SUPPORT_USERUSER
03946 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03947 #endif
03948
03949
03950 pri_grab(p, p->pri);
03951 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03952 if (p->alreadyhungup) {
03953 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
03954
03955 #ifdef SUPPORT_USERUSER
03956 pri_call_set_useruser(p->call, useruser);
03957 #endif
03958
03959 pri_hangup(p->pri->pri, p->call, -1);
03960 p->call = NULL;
03961 if (p->bearer)
03962 p->bearer->call = NULL;
03963 } else {
03964 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03965 int icause = ast->hangupcause ? ast->hangupcause : -1;
03966 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03967
03968 #ifdef SUPPORT_USERUSER
03969 pri_call_set_useruser(p->call, useruser);
03970 #endif
03971
03972 p->alreadyhungup = 1;
03973 if (p->bearer)
03974 p->bearer->alreadyhungup = 1;
03975 if (cause) {
03976 if (atoi(cause))
03977 icause = atoi(cause);
03978 }
03979 pri_hangup(p->pri->pri, p->call, icause);
03980 }
03981 } else {
03982 if (p->bearer)
03983 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03984 p->call = NULL;
03985 }
03986 p->allocated = 0;
03987 p->owner = NULL;
03988 pri_rel(p->pri);
03989 res = 0;
03990 } else
03991 #endif
03992 {
03993 p->owner = NULL;
03994 }
03995 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
03996 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03997 if (res < 0) {
03998 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03999 }
04000 switch (p->sig) {
04001 case SIG_FXOGS:
04002 case SIG_FXOLS:
04003 case SIG_FXOKS:
04004 memset(&par, 0, sizeof(par));
04005 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04006 if (!res) {
04007 #if 0
04008 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04009 #endif
04010
04011 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04012 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04013 else
04014 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04015 }
04016 break;
04017 case SIG_FXSGS:
04018 case SIG_FXSLS:
04019 case SIG_FXSKS:
04020
04021
04022 if (ast->_state != AST_STATE_RESERVED) {
04023 time(&p->guardtime);
04024 p->guardtime += 2;
04025 }
04026 break;
04027 default:
04028 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04029 }
04030 free(p->cidspill);
04031 p->cidspill = NULL;
04032 if (p->sig)
04033 dahdi_disable_ec(p);
04034 x = 0;
04035 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04036 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04037 p->didtdd = 0;
04038 p->callwaitcas = 0;
04039 p->callwaiting = p->permcallwaiting;
04040 p->hidecallerid = p->permhidecallerid;
04041 p->dialing = 0;
04042 p->rdnis[0] = '\0';
04043 update_conf(p);
04044 reset_conf(p);
04045
04046 if (p->sig == SIG_PRI) {
04047 x = 0;
04048 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04049 }
04050 #ifdef HAVE_PRI
04051 if (p->bearer) {
04052 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
04053
04054
04055 update_conf(p->bearer);
04056 reset_conf(p->bearer);
04057 p->bearer->owner = NULL;
04058 p->bearer->realcall = NULL;
04059 p->bearer = NULL;
04060 p->subs[SUB_REAL].dfd = -1;
04061 p->pri = NULL;
04062 }
04063 #endif
04064 if (num_restart_pending == 0)
04065 restart_monitor();
04066 }
04067
04068 p->callwaitingrepeat = 0;
04069 p->cidcwexpire = 0;
04070 p->cid_suppress_expire = 0;
04071 p->oprmode = 0;
04072 ast->tech_pvt = NULL;
04073 ast_mutex_unlock(&p->lock);
04074 if (option_verbose > 2)
04075 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
04076
04077 ast_mutex_lock(&iflock);
04078 if (p->restartpending) {
04079 num_restart_pending--;
04080 }
04081
04082 tmp = iflist;
04083 prev = NULL;
04084 if (p->destroy) {
04085 while (tmp) {
04086 if (tmp == p) {
04087 destroy_channel(prev, tmp, 0);
04088 break;
04089 } else {
04090 prev = tmp;
04091 tmp = tmp->next;
04092 }
04093 }
04094 }
04095 ast_mutex_unlock(&iflock);
04096
04097 ast_module_unref(ast_module_info->self);
04098 return 0;
04099 }
04100
04101 static int dahdi_answer(struct ast_channel *ast)
04102 {
04103 struct dahdi_pvt *p = ast->tech_pvt;
04104 int res = 0;
04105 int index;
04106 int oldstate = ast->_state;
04107 ast_setstate(ast, AST_STATE_UP);
04108 ast_mutex_lock(&p->lock);
04109 index = dahdi_get_index(ast, p, 0);
04110 if (index < 0)
04111 index = SUB_REAL;
04112
04113 if ((p->radio || (p->oprmode < 0))) {
04114 ast_mutex_unlock(&p->lock);
04115 return 0;
04116 }
04117 switch (p->sig) {
04118 case SIG_FXSLS:
04119 case SIG_FXSGS:
04120 case SIG_FXSKS:
04121 p->ringt = 0;
04122
04123 case SIG_EM:
04124 case SIG_EM_E1:
04125 case SIG_EMWINK:
04126 case SIG_FEATD:
04127 case SIG_FEATDMF:
04128 case SIG_FEATDMF_TA:
04129 case SIG_E911:
04130 case SIG_FGC_CAMA:
04131 case SIG_FGC_CAMAMF:
04132 case SIG_FEATB:
04133 case SIG_SF:
04134 case SIG_SFWINK:
04135 case SIG_SF_FEATD:
04136 case SIG_SF_FEATDMF:
04137 case SIG_SF_FEATB:
04138 case SIG_FXOLS:
04139 case SIG_FXOGS:
04140 case SIG_FXOKS:
04141
04142 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
04143 if (p->hanguponpolarityswitch) {
04144 gettimeofday(&p->polaritydelaytv, NULL);
04145 }
04146 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04147 tone_zone_play_tone(p->subs[index].dfd, -1);
04148 p->dialing = 0;
04149 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04150 if (oldstate == AST_STATE_RINGING) {
04151 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
04152 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04153 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04154 p->owner = p->subs[SUB_REAL].owner;
04155 }
04156 }
04157 if (p->sig & __DAHDI_SIG_FXS) {
04158 dahdi_enable_ec(p);
04159 dahdi_train_ec(p);
04160 }
04161 break;
04162 #ifdef HAVE_PRI
04163 case SIG_PRI:
04164
04165 if (!pri_grab(p, p->pri)) {
04166 if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04167 p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04168 }
04169 p->dialing = 0;
04170 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04171 pri_rel(p->pri);
04172 } else {
04173 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04174 res = -1;
04175 }
04176 break;
04177 #endif
04178
04179 #ifdef HAVE_OPENR2
04180 case SIG_MFCR2:
04181 if (!p->mfcr2_accept_on_offer) {
04182
04183
04184 if (p->mfcr2_charge_calls) {
04185 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
04186 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04187 } else {
04188 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
04189 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04190 }
04191 } else {
04192 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04193 res = dahdi_r2_answer(p);
04194 }
04195 break;
04196 #endif
04197
04198 case 0:
04199 ast_mutex_unlock(&p->lock);
04200 return 0;
04201 default:
04202 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04203 res = -1;
04204 }
04205 ast_mutex_unlock(&p->lock);
04206 return res;
04207 }
04208
04209 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04210 {
04211 char *cp;
04212 signed char *scp;
04213 int x;
04214 int index;
04215 struct dahdi_pvt *p = chan->tech_pvt, *pp;
04216 struct oprmode *oprmode;
04217
04218
04219
04220 if (!data || (datalen < 1)) {
04221 errno = EINVAL;
04222 return -1;
04223 }
04224
04225 switch (option) {
04226 case AST_OPTION_TXGAIN:
04227 scp = (signed char *) data;
04228 index = dahdi_get_index(chan, p, 0);
04229 if (index < 0) {
04230 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04231 return -1;
04232 }
04233 if (option_debug)
04234 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04235 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
04236 case AST_OPTION_RXGAIN:
04237 scp = (signed char *) data;
04238 index = dahdi_get_index(chan, p, 0);
04239 if (index < 0) {
04240 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04241 return -1;
04242 }
04243 if (option_debug)
04244 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04245 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
04246 case AST_OPTION_TONE_VERIFY:
04247 if (!p->dsp)
04248 break;
04249 cp = (char *) data;
04250 switch (*cp) {
04251 case 1:
04252 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04253 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
04254 break;
04255 case 2:
04256 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04257 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
04258 break;
04259 default:
04260 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04261 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
04262 break;
04263 }
04264 break;
04265 case AST_OPTION_TDD:
04266
04267 cp = (char *) data;
04268 p->mate = 0;
04269 if (!*cp) {
04270 if (option_debug)
04271 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04272 if (p->tdd)
04273 tdd_free(p->tdd);
04274 p->tdd = 0;
04275 break;
04276 }
04277 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
04278 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04279 dahdi_disable_ec(p);
04280
04281 if (!p->didtdd) {
04282 unsigned char mybuf[41000];
04283 unsigned char *buf;
04284 int size, res, fd, len;
04285 struct pollfd fds[1];
04286
04287 buf = mybuf;
04288 memset(buf, 0x7f, sizeof(mybuf));
04289 ast_tdd_gen_ecdisa(buf + 16000, 16000);
04290 len = 40000;
04291 index = dahdi_get_index(chan, p, 0);
04292 if (index < 0) {
04293 ast_log(LOG_WARNING, "No index in TDD?\n");
04294 return -1;
04295 }
04296 fd = p->subs[index].dfd;
04297 while (len) {
04298 if (ast_check_hangup(chan))
04299 return -1;
04300 size = len;
04301 if (size > READ_SIZE)
04302 size = READ_SIZE;
04303 fds[0].fd = fd;
04304 fds[0].events = POLLPRI | POLLOUT;
04305 fds[0].revents = 0;
04306 res = poll(fds, 1, -1);
04307 if (!res) {
04308 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
04309 continue;
04310 }
04311
04312 if (fds[0].revents & POLLPRI)
04313 return -1;
04314 if (!(fds[0].revents & POLLOUT)) {
04315 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
04316 continue;
04317 }
04318 res = write(fd, buf, size);
04319 if (res != size) {
04320 if (res == -1) return -1;
04321 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04322 break;
04323 }
04324 len -= size;
04325 buf += size;
04326 }
04327 p->didtdd = 1;
04328 }
04329 if (*cp == 2) {
04330 if (p->tdd)
04331 tdd_free(p->tdd);
04332 p->tdd = 0;
04333 p->mate = 1;
04334 break;
04335 }
04336 if (!p->tdd) {
04337 p->tdd = tdd_new();
04338 }
04339 break;
04340 case AST_OPTION_RELAXDTMF:
04341 if (!p->dsp)
04342 break;
04343 cp = (char *) data;
04344 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04345 *cp ? "ON" : "OFF", (int) *cp, chan->name);
04346 p->dtmfrelax = 0;
04347 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
04348 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04349 break;
04350 case AST_OPTION_AUDIO_MODE:
04351 cp = (char *) data;
04352 if (!*cp) {
04353 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04354 x = 0;
04355 dahdi_disable_ec(p);
04356 } else {
04357 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04358 x = 1;
04359 }
04360 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04361 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04362 break;
04363 case AST_OPTION_OPRMODE:
04364 oprmode = (struct oprmode *) data;
04365 pp = oprmode->peer->tech_pvt;
04366 p->oprmode = pp->oprmode = 0;
04367
04368 p->oprpeer = pp;
04369 pp->oprpeer = p;
04370
04371 if (oprmode->mode)
04372 {
04373 pp->oprmode = oprmode->mode;
04374 p->oprmode = -oprmode->mode;
04375 }
04376 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
04377 oprmode->mode, chan->name,oprmode->peer->name);;
04378 break;
04379 case AST_OPTION_ECHOCAN:
04380 cp = (char *) data;
04381 if (*cp) {
04382 ast_log(LOG_DEBUG, "Enabling echo cancellation on %s\n", chan->name);
04383 dahdi_enable_ec(p);
04384 } else {
04385 ast_log(LOG_DEBUG, "Disabling echo cancellation on %s\n", chan->name);
04386 dahdi_disable_ec(p);
04387 }
04388 break;
04389 }
04390 errno = 0;
04391
04392 return 0;
04393 }
04394
04395 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
04396 {
04397 struct dahdi_pvt *p = chan->tech_pvt;
04398 int res = 0;
04399
04400 if (!strcasecmp(data, "rxgain")) {
04401 ast_mutex_lock(&p->lock);
04402 snprintf(buf, len, "%f", p->rxgain);
04403 ast_mutex_unlock(&p->lock);
04404 } else if (!strcasecmp(data, "txgain")) {
04405 ast_mutex_lock(&p->lock);
04406 snprintf(buf, len, "%f", p->txgain);
04407 ast_mutex_unlock(&p->lock);
04408 } else {
04409 ast_copy_string(buf, "", len);
04410 res = -1;
04411 }
04412
04413 return res;
04414 }
04415
04416
04417 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
04418 {
04419 int res;
04420 char policy_str[21] = "";
04421
04422 if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
04423 ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
04424 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
04425 return 1;
04426 }
04427 if (*num_buffers < 0) {
04428 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
04429 return -1;
04430 }
04431 if (!strcasecmp(policy_str, "full")) {
04432 *policy = DAHDI_POLICY_WHEN_FULL;
04433 } else if (!strcasecmp(policy_str, "immediate")) {
04434 *policy = DAHDI_POLICY_IMMEDIATE;
04435 #ifdef DAHDI_POLICY_HALF_FULL
04436 } else if (!strcasecmp(policy_str, "half")) {
04437 *policy = DAHDI_POLICY_HALF_FULL;
04438 #endif
04439 } else {
04440 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
04441 return -1;
04442 }
04443
04444 return 0;
04445 }
04446
04447 static int dahdi_func_write(struct ast_channel *chan, char *function, char *data, const char *value)
04448 {
04449 struct dahdi_pvt *p = chan->tech_pvt;
04450 int res = 0;
04451
04452 if (!strcasecmp(data, "buffers")) {
04453 int num_bufs, policy;
04454
04455 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
04456 struct dahdi_bufferinfo bi = {
04457 .txbufpolicy = policy,
04458 .rxbufpolicy = policy,
04459 .bufsize = p->bufsize,
04460 .numbufs = num_bufs,
04461 };
04462 int bpres;
04463
04464 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04465 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
04466 } else {
04467 p->bufferoverrideinuse = 1;
04468 }
04469 } else {
04470 res = -1;
04471 }
04472 } else {
04473 res = -1;
04474 }
04475
04476 return res;
04477 }
04478
04479 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04480 {
04481
04482 int x;
04483 int hasslaves;
04484 if (!master)
04485 return;
04486 if (needlock) {
04487 ast_mutex_lock(&master->lock);
04488 if (slave) {
04489 while (ast_mutex_trylock(&slave->lock)) {
04490 DEADLOCK_AVOIDANCE(&master->lock);
04491 }
04492 }
04493 }
04494 hasslaves = 0;
04495 for (x = 0; x < MAX_SLAVES; x++) {
04496 if (master->slaves[x]) {
04497 if (!slave || (master->slaves[x] == slave)) {
04498
04499 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04500 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04501 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04502 master->slaves[x]->master = NULL;
04503 master->slaves[x] = NULL;
04504 } else
04505 hasslaves = 1;
04506 }
04507 if (!hasslaves)
04508 master->inconference = 0;
04509 }
04510 if (!slave) {
04511 if (master->master) {
04512
04513 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04514 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04515 hasslaves = 0;
04516 for (x = 0; x < MAX_SLAVES; x++) {
04517 if (master->master->slaves[x] == master)
04518 master->master->slaves[x] = NULL;
04519 else if (master->master->slaves[x])
04520 hasslaves = 1;
04521 }
04522 if (!hasslaves)
04523 master->master->inconference = 0;
04524 }
04525 master->master = NULL;
04526 }
04527 update_conf(master);
04528 if (needlock) {
04529 if (slave)
04530 ast_mutex_unlock(&slave->lock);
04531 ast_mutex_unlock(&master->lock);
04532 }
04533 }
04534
04535 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04536 int x;
04537 if (!slave || !master) {
04538 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04539 return;
04540 }
04541 for (x = 0; x < MAX_SLAVES; x++) {
04542 if (!master->slaves[x]) {
04543 master->slaves[x] = slave;
04544 break;
04545 }
04546 }
04547 if (x >= MAX_SLAVES) {
04548 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04549 master->slaves[MAX_SLAVES - 1] = slave;
04550 }
04551 if (slave->master)
04552 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04553 slave->master = master;
04554
04555 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04556 }
04557
04558 static void disable_dtmf_detect(struct dahdi_pvt *p)
04559 {
04560 #ifdef DAHDI_TONEDETECT
04561 int val;
04562 #endif
04563
04564 p->ignoredtmf = 1;
04565
04566 #ifdef DAHDI_TONEDETECT
04567 val = 0;
04568 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04569 #endif
04570 if (!p->hardwaredtmf && p->dsp) {
04571 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04572 ast_dsp_set_features(p->dsp, p->dsp_features);
04573 }
04574 }
04575
04576 static void enable_dtmf_detect(struct dahdi_pvt *p)
04577 {
04578 #ifdef DAHDI_TONEDETECT
04579 int val;
04580 #endif
04581
04582 if (p->channel == CHAN_PSEUDO)
04583 return;
04584
04585 p->ignoredtmf = 0;
04586
04587 #ifdef DAHDI_TONEDETECT
04588 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04589 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04590 #endif
04591 if (!p->hardwaredtmf && p->dsp) {
04592 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04593 ast_dsp_set_features(p->dsp, p->dsp_features);
04594 }
04595 }
04596
04597 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)
04598 {
04599 struct ast_channel *who;
04600 struct dahdi_pvt *p0, *p1, *op0, *op1;
04601 struct dahdi_pvt *master = NULL, *slave = NULL;
04602 struct ast_frame *f;
04603 int inconf = 0;
04604 int nothingok = 1;
04605 int ofd0, ofd1;
04606 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04607 int os0 = -1, os1 = -1;
04608 int priority = 0;
04609 struct ast_channel *oc0, *oc1;
04610 enum ast_bridge_result res;
04611
04612 #ifdef PRI_2BCT
04613 int triedtopribridge = 0;
04614 #endif
04615
04616
04617
04618
04619
04620
04621 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04622 return AST_BRIDGE_FAILED_NOWARN;
04623
04624 ast_mutex_lock(&c0->lock);
04625 while (ast_mutex_trylock(&c1->lock)) {
04626 DEADLOCK_AVOIDANCE(&c0->lock);
04627 }
04628
04629 p0 = c0->tech_pvt;
04630 p1 = c1->tech_pvt;
04631
04632 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04633 ast_mutex_unlock(&c0->lock);
04634 ast_mutex_unlock(&c1->lock);
04635 return AST_BRIDGE_FAILED_NOWARN;
04636 }
04637
04638 oi0 = dahdi_get_index(c0, p0, 0);
04639 oi1 = dahdi_get_index(c1, p1, 0);
04640 if ((oi0 < 0) || (oi1 < 0)) {
04641 ast_mutex_unlock(&c0->lock);
04642 ast_mutex_unlock(&c1->lock);
04643 return AST_BRIDGE_FAILED;
04644 }
04645
04646 op0 = p0 = c0->tech_pvt;
04647 op1 = p1 = c1->tech_pvt;
04648 ofd0 = c0->fds[0];
04649 ofd1 = c1->fds[0];
04650 oc0 = p0->owner;
04651 oc1 = p1->owner;
04652
04653 if (ast_mutex_trylock(&p0->lock)) {
04654
04655 ast_mutex_unlock(&c0->lock);
04656 ast_mutex_unlock(&c1->lock);
04657 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04658 return AST_BRIDGE_RETRY;
04659 }
04660 if (ast_mutex_trylock(&p1->lock)) {
04661
04662 ast_mutex_unlock(&p0->lock);
04663 ast_mutex_unlock(&c0->lock);
04664 ast_mutex_unlock(&c1->lock);
04665 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04666 return AST_BRIDGE_RETRY;
04667 }
04668
04669 if ((p0->callwaiting && p0->callwaitingcallerid)
04670 || (p1->callwaiting && p1->callwaitingcallerid)) {
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680 ast_mutex_unlock(&p0->lock);
04681 ast_mutex_unlock(&p1->lock);
04682 ast_mutex_unlock(&c0->lock);
04683 ast_mutex_unlock(&c1->lock);
04684 return AST_BRIDGE_FAILED_NOWARN;
04685 }
04686
04687 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04688 if (p0->owner && p1->owner) {
04689
04690 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04691 master = p0;
04692 slave = p1;
04693 inconf = 1;
04694 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04695 master = p1;
04696 slave = p0;
04697 inconf = 1;
04698 } else {
04699 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04700 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04701 p0->channel,
04702 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04703 p0->subs[SUB_REAL].inthreeway, p0->channel,
04704 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04705 p1->subs[SUB_REAL].inthreeway);
04706 }
04707 nothingok = 0;
04708 }
04709 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04710 if (p1->subs[SUB_THREEWAY].inthreeway) {
04711 master = p1;
04712 slave = p0;
04713 nothingok = 0;
04714 }
04715 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04716 if (p0->subs[SUB_THREEWAY].inthreeway) {
04717 master = p0;
04718 slave = p1;
04719 nothingok = 0;
04720 }
04721 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04722
04723
04724 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04725 master = p1;
04726 slave = p0;
04727 nothingok = 0;
04728 }
04729 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04730
04731 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04732 master = p0;
04733 slave = p1;
04734 nothingok = 0;
04735 }
04736 }
04737 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
04738 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04739 if (master && slave) {
04740
04741
04742
04743 if ((oi1 == SUB_THREEWAY) &&
04744 p1->subs[SUB_THREEWAY].inthreeway &&
04745 p1->subs[SUB_REAL].owner &&
04746 p1->subs[SUB_REAL].inthreeway &&
04747 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04748 ast_log(LOG_DEBUG,
04749 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
04750 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
04751 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04752 os1 = p1->subs[SUB_REAL].owner->_state;
04753 } else {
04754 ast_log(LOG_DEBUG, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
04755 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
04756 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04757 }
04758 if ((oi0 == SUB_THREEWAY) &&
04759 p0->subs[SUB_THREEWAY].inthreeway &&
04760 p0->subs[SUB_REAL].owner &&
04761 p0->subs[SUB_REAL].inthreeway &&
04762 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04763 ast_log(LOG_DEBUG,
04764 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
04765 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
04766 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04767 os0 = p0->subs[SUB_REAL].owner->_state;
04768 } else {
04769 ast_log(LOG_DEBUG, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
04770 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
04771 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
04772 }
04773 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04774 if (!p0->echocanbridged || !p1->echocanbridged) {
04775
04776 dahdi_disable_ec(p0);
04777 dahdi_disable_ec(p1);
04778 }
04779 }
04780 dahdi_link(slave, master);
04781 master->inconference = inconf;
04782 } else if (!nothingok)
04783 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04784
04785 update_conf(p0);
04786 update_conf(p1);
04787 t0 = p0->subs[SUB_REAL].inthreeway;
04788 t1 = p1->subs[SUB_REAL].inthreeway;
04789
04790 ast_mutex_unlock(&p0->lock);
04791 ast_mutex_unlock(&p1->lock);
04792
04793 ast_mutex_unlock(&c0->lock);
04794 ast_mutex_unlock(&c1->lock);
04795
04796
04797 if ((!master || !slave) && !nothingok) {
04798 dahdi_enable_ec(p0);
04799 dahdi_enable_ec(p1);
04800 return AST_BRIDGE_FAILED;
04801 }
04802
04803 if (option_verbose > 2)
04804 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
04805
04806 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04807 disable_dtmf_detect(op0);
04808
04809 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04810 disable_dtmf_detect(op1);
04811
04812 for (;;) {
04813 struct ast_channel *c0_priority[2] = {c0, c1};
04814 struct ast_channel *c1_priority[2] = {c1, c0};
04815
04816
04817
04818 ast_mutex_lock(&c0->lock);
04819 while (ast_mutex_trylock(&c1->lock)) {
04820 DEADLOCK_AVOIDANCE(&c0->lock);
04821 }
04822
04823 p0 = c0->tech_pvt;
04824 p1 = c1->tech_pvt;
04825
04826 if (op0 == p0)
04827 i0 = dahdi_get_index(c0, p0, 1);
04828 if (op1 == p1)
04829 i1 = dahdi_get_index(c1, p1, 1);
04830 ast_mutex_unlock(&c0->lock);
04831 ast_mutex_unlock(&c1->lock);
04832
04833 if (!timeoutms ||
04834 (op0 != p0) ||
04835 (op1 != p1) ||
04836 (ofd0 != c0->fds[0]) ||
04837 (ofd1 != c1->fds[0]) ||
04838 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04839 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04840 (oc0 != p0->owner) ||
04841 (oc1 != p1->owner) ||
04842 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04843 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04844 (oi0 != i0) ||
04845 (oi1 != i1)) {
04846 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04847 op0->channel, oi0, op1->channel, oi1);
04848 res = AST_BRIDGE_RETRY;
04849 goto return_from_bridge;
04850 }
04851
04852 #ifdef PRI_2BCT
04853 if (!triedtopribridge) {
04854 triedtopribridge = 1;
04855 if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
04856 ast_mutex_lock(&p0->pri->lock);
04857 if (p0->call && p1->call) {
04858 pri_channel_bridge(p0->call, p1->call);
04859 }
04860 ast_mutex_unlock(&p0->pri->lock);
04861 }
04862 }
04863 #endif
04864
04865 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04866 if (!who) {
04867 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
04868 continue;
04869 }
04870 f = ast_read(who);
04871 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04872 *fo = f;
04873 *rc = who;
04874 res = AST_BRIDGE_COMPLETE;
04875 goto return_from_bridge;
04876 }
04877 if (f->frametype == AST_FRAME_DTMF) {
04878 if ((who == c0) && p0->pulsedial) {
04879 ast_write(c1, f);
04880 } else if ((who == c1) && p1->pulsedial) {
04881 ast_write(c0, f);
04882 } else {
04883 *fo = f;
04884 *rc = who;
04885 res = AST_BRIDGE_COMPLETE;
04886 goto return_from_bridge;
04887 }
04888 }
04889 ast_frfree(f);
04890
04891
04892 priority = !priority;
04893 }
04894
04895 return_from_bridge:
04896 if (op0 == p0)
04897 dahdi_enable_ec(p0);
04898
04899 if (op1 == p1)
04900 dahdi_enable_ec(p1);
04901
04902 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04903 enable_dtmf_detect(op0);
04904
04905 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04906 enable_dtmf_detect(op1);
04907
04908 dahdi_unlink(slave, master, 1);
04909
04910 return res;
04911 }
04912
04913 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04914 {
04915 struct dahdi_pvt *p = newchan->tech_pvt;
04916 int x;
04917 ast_mutex_lock(&p->lock);
04918 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
04919 if (p->owner == oldchan) {
04920 p->owner = newchan;
04921 }
04922 for (x = 0; x < 3; x++)
04923 if (p->subs[x].owner == oldchan) {
04924 if (!x)
04925 dahdi_unlink(NULL, p, 0);
04926 p->subs[x].owner = newchan;
04927 }
04928 update_conf(p);
04929 ast_mutex_unlock(&p->lock);
04930 if (newchan->_state == AST_STATE_RINGING)
04931 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04932 return 0;
04933 }
04934
04935 static int dahdi_ring_phone(struct dahdi_pvt *p)
04936 {
04937 int x;
04938 int res;
04939
04940 x = 0;
04941 x = DAHDI_ONHOOK;
04942 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04943 do {
04944 x = DAHDI_RING;
04945 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04946 if (res) {
04947 switch (errno) {
04948 case EBUSY:
04949 case EINTR:
04950
04951 usleep(10000);
04952 continue;
04953 case EINPROGRESS:
04954 res = 0;
04955 break;
04956 default:
04957 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04958 res = 0;
04959 }
04960 }
04961 } while (res);
04962 return res;
04963 }
04964
04965 static void *ss_thread(void *data);
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981 static int attempt_transfer(struct dahdi_pvt *p)
04982 {
04983
04984
04985
04986 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04987
04988
04989 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04990 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04991 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04992
04993
04994
04995
04996
04997
04998
04999 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05000 }
05001 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05002 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05003 }
05004 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05005 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05006 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05007 return -1;
05008 }
05009
05010 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05011 unalloc_sub(p, SUB_THREEWAY);
05012 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05013 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05014 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05015
05016
05017
05018
05019
05020
05021
05022 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05023 }
05024 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05025 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05026 }
05027 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05028 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05029 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05030 return -1;
05031 }
05032
05033 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05034 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05035 unalloc_sub(p, SUB_THREEWAY);
05036
05037 return 1;
05038 } else {
05039 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05040 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05041 return -1;
05042 }
05043 return 0;
05044 }
05045
05046 static int check_for_conference(struct dahdi_pvt *p)
05047 {
05048 struct dahdi_confinfo ci;
05049
05050 if (p->master || (p->confno > -1))
05051 return 0;
05052 memset(&ci, 0, sizeof(ci));
05053 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05054 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05055 return 0;
05056 }
05057
05058
05059
05060 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05061 if (option_verbose > 2)
05062 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
05063 return 1;
05064 }
05065 return 0;
05066 }
05067
05068 static int get_alarms(struct dahdi_pvt *p)
05069 {
05070 int res;
05071 struct dahdi_spaninfo zi;
05072 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
05073
05074
05075
05076
05077
05078 struct dahdi_params params;
05079 #endif
05080
05081 memset(&zi, 0, sizeof(zi));
05082 zi.spanno = p->span;
05083
05084
05085 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
05086 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05087 return 0;
05088 }
05089 if (zi.alarms != DAHDI_ALARM_NONE)
05090 return zi.alarms;
05091 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
05092
05093 memset(¶ms, 0, sizeof(params));
05094 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
05095 return params.chan_alarms;
05096
05097 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05098 #endif
05099 return DAHDI_ALARM_NONE;
05100 }
05101
05102 static void dahdi_handle_dtmf(struct ast_channel *ast, int index, struct ast_frame **dest)
05103 {
05104 struct dahdi_pvt *p = ast->tech_pvt;
05105 struct ast_frame *f = *dest;
05106
05107 if (option_debug)
05108 ast_log(LOG_DEBUG, "%s DTMF digit: 0x%02X '%c' on %s\n",
05109 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
05110 f->subclass, f->subclass, ast->name);
05111
05112 if (p->confirmanswer) {
05113 if (f->frametype == AST_FRAME_DTMF_END) {
05114 if (option_debug)
05115 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
05116
05117
05118 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05119 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05120
05121 p->confirmanswer = 0;
05122 } else {
05123 p->subs[index].f.frametype = AST_FRAME_NULL;
05124 p->subs[index].f.subclass = 0;
05125 }
05126 *dest = &p->subs[index].f;
05127 } else if (p->callwaitcas) {
05128 if (f->frametype == AST_FRAME_DTMF_END) {
05129 if ((f->subclass == 'A') || (f->subclass == 'D')) {
05130 if (option_debug)
05131 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
05132 free(p->cidspill);
05133 p->cidspill = NULL;
05134 send_cwcidspill(p);
05135 }
05136 if ((f->subclass != 'm') && (f->subclass != 'u'))
05137 p->callwaitcas = 0;
05138 }
05139 p->subs[index].f.frametype = AST_FRAME_NULL;
05140 p->subs[index].f.subclass = 0;
05141 *dest = &p->subs[index].f;
05142 } else if (f->subclass == 'f') {
05143 if (f->frametype == AST_FRAME_DTMF_END) {
05144
05145 if ((p->callprogress & 0x6) && !p->faxhandled) {
05146 p->faxhandled = 1;
05147 if (strcmp(ast->exten, "fax")) {
05148 const char *target_context = S_OR(ast->macrocontext, ast->context);
05149
05150
05151
05152
05153
05154 ast_mutex_unlock(&p->lock);
05155 ast_channel_unlock(ast);
05156 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05157 ast_channel_lock(ast);
05158 ast_mutex_lock(&p->lock);
05159 if (option_verbose > 2)
05160 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
05161
05162 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05163 if (ast_async_goto(ast, target_context, "fax", 1))
05164 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05165 } else {
05166 ast_channel_lock(ast);
05167 ast_mutex_lock(&p->lock);
05168 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05169 }
05170 } else if (option_debug)
05171 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
05172 } else if (option_debug)
05173 ast_log(LOG_DEBUG, "Fax already handled\n");
05174 dahdi_confmute(p, 0);
05175 }
05176 p->subs[index].f.frametype = AST_FRAME_NULL;
05177 p->subs[index].f.subclass = 0;
05178 *dest = &p->subs[index].f;
05179 } else if (f->subclass == 'm') {
05180 if (f->frametype == AST_FRAME_DTMF_END) {
05181
05182 dahdi_confmute(p, 1);
05183 }
05184 p->subs[index].f.frametype = AST_FRAME_NULL;
05185 p->subs[index].f.subclass = 0;
05186 *dest = &p->subs[index].f;
05187 } else if (f->subclass == 'u') {
05188 if (f->frametype == AST_FRAME_DTMF_END) {
05189
05190 dahdi_confmute(p, 0);
05191 }
05192 p->subs[index].f.frametype = AST_FRAME_NULL;
05193 p->subs[index].f.subclass = 0;
05194 *dest = &p->subs[index].f;
05195 } else {
05196 if (f->frametype == AST_FRAME_DTMF_END) {
05197 dahdi_confmute(p, 0);
05198 }
05199 }
05200 }
05201
05202 static void handle_alarms(struct dahdi_pvt *p, int alarms)
05203 {
05204 const char *alarm_str = alarm2str(alarms);
05205
05206
05207
05208 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
05209 p->unknown_alarm = 1;
05210 return;
05211 } else {
05212 p->unknown_alarm = 0;
05213 }
05214
05215 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05216 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05217 "Alarm: %s\r\n"
05218 "Channel: %d\r\n",
05219 alarm_str, p->channel);
05220 }
05221
05222 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05223 {
05224 int res, x;
05225 int index, mysig;
05226 char *c;
05227 struct dahdi_pvt *p = ast->tech_pvt;
05228 pthread_t threadid;
05229 pthread_attr_t attr;
05230 struct ast_channel *chan;
05231 struct ast_frame *f;
05232
05233 index = dahdi_get_index(ast, p, 0);
05234 if (index < 0) {
05235 return &ast_null_frame;
05236 }
05237 if (index != SUB_REAL) {
05238 ast_log(LOG_ERROR, "We got an event on a non real sub. Fix it!\n");
05239 }
05240
05241 mysig = p->sig;
05242 if (p->outsigmod > -1)
05243 mysig = p->outsigmod;
05244
05245 p->subs[index].f.frametype = AST_FRAME_NULL;
05246 p->subs[index].f.subclass = 0;
05247 p->subs[index].f.datalen = 0;
05248 p->subs[index].f.samples = 0;
05249 p->subs[index].f.mallocd = 0;
05250 p->subs[index].f.offset = 0;
05251 p->subs[index].f.src = "dahdi_handle_event";
05252 p->subs[index].f.data = NULL;
05253 f = &p->subs[index].f;
05254
05255 if (p->fake_event) {
05256 res = p->fake_event;
05257 p->fake_event = 0;
05258 } else
05259 res = dahdi_get_event(p->subs[index].dfd);
05260
05261 if (option_debug)
05262 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
05263
05264 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05265 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05266
05267 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05268 #ifdef HAVE_PRI
05269 if (p->sig == SIG_PRI
05270 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
05271 && p->pri
05272 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05273
05274 } else
05275 #endif
05276 {
05277 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
05278 p->subs[index].f.subclass = res & 0xff;
05279 dahdi_handle_dtmf(ast, index, &f);
05280 }
05281 return f;
05282 }
05283
05284 if (res & DAHDI_EVENT_DTMFDOWN) {
05285 if (option_debug)
05286 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
05287 #ifdef HAVE_PRI
05288 if (p->sig == SIG_PRI
05289 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
05290 && p->pri
05291 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05292
05293 } else
05294 #endif
05295 {
05296
05297 dahdi_confmute(p, 1);
05298 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
05299 p->subs[index].f.subclass = res & 0xff;
05300 dahdi_handle_dtmf(ast, index, &f);
05301 }
05302 return &p->subs[index].f;
05303 }
05304
05305 switch (res) {
05306 #ifdef DAHDI_EVENT_EC_DISABLED
05307 case DAHDI_EVENT_EC_DISABLED:
05308 if (option_verbose > 2)
05309 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
05310 p->echocanon = 0;
05311 break;
05312 #endif
05313 case DAHDI_EVENT_BITSCHANGED:
05314 #ifdef HAVE_OPENR2
05315 if (p->sig != SIG_MFCR2) {
05316 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05317 } else {
05318 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05319 openr2_chan_handle_cas(p->r2chan);
05320 }
05321 #else
05322 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05323 #endif
05324 case DAHDI_EVENT_PULSE_START:
05325
05326 if (!ast->pbx)
05327 tone_zone_play_tone(p->subs[index].dfd, -1);
05328 break;
05329 case DAHDI_EVENT_DIALCOMPLETE:
05330 #ifdef HAVE_OPENR2
05331 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05332
05333
05334 break;
05335 }
05336 #endif
05337 if (p->inalarm) break;
05338 if ((p->radio || (p->oprmode < 0))) break;
05339 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
05340 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05341 return NULL;
05342 }
05343 if (!x) {
05344 dahdi_enable_ec(p);
05345 if (p->echobreak) {
05346 dahdi_train_ec(p);
05347 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05348 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05349 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05350 p->echobreak = 0;
05351 } else {
05352 p->dialing = 0;
05353 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05354
05355 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05356 ast_setstate(ast, AST_STATE_UP);
05357 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05358 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05359 break;
05360 } else {
05361
05362 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05363 }
05364 }
05365 if (ast->_state == AST_STATE_DIALING) {
05366 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05367 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
05368 } 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)))) {
05369 ast_setstate(ast, AST_STATE_RINGING);
05370 } else if (!p->answeronpolarityswitch) {
05371 ast_setstate(ast, AST_STATE_UP);
05372 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05373 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05374
05375 p->polarity = POLARITY_REV;
05376 } else {
05377
05378 p->polarity = POLARITY_IDLE;
05379 }
05380 }
05381 }
05382 }
05383 break;
05384 case DAHDI_EVENT_ALARM:
05385 #ifdef HAVE_PRI
05386 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05387
05388 if (p->call) {
05389 if (p->pri && p->pri->pri) {
05390 pri_grab(p, p->pri);
05391 pri_destroycall(p->pri->pri, p->call);
05392 p->call = NULL;
05393 pri_rel(p->pri);
05394 } else
05395 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05396 }
05397 if (p->owner)
05398 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05399 }
05400 if (p->bearer) {
05401 p->bearer->inalarm = 1;
05402 p->bearer->resetting = 0;
05403 } else
05404 #endif
05405 {
05406 p->inalarm = 1;
05407 #if defined(HAVE_PRI)
05408 p->resetting = 0;
05409 #endif
05410 }
05411 res = get_alarms(p);
05412 handle_alarms(p, res);
05413 #ifdef HAVE_PRI
05414 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05415
05416 } else {
05417 break;
05418 }
05419 #endif
05420
05421 #ifdef HAVE_OPENR2
05422 if (p->sig == SIG_MFCR2)
05423 break;
05424 #endif
05425
05426 case DAHDI_EVENT_ONHOOK:
05427 if (p->radio) {
05428 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05429 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05430 break;
05431 }
05432 if (p->oprmode < 0)
05433 {
05434 if (p->oprmode != -1) break;
05435 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05436 {
05437
05438 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05439 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05440 save_conference(p->oprpeer);
05441 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05442 }
05443 break;
05444 }
05445 switch (p->sig) {
05446 case SIG_FXOLS:
05447 case SIG_FXOGS:
05448 case SIG_FXOKS:
05449 p->onhooktime = time(NULL);
05450 p->msgstate = -1;
05451
05452 if (index == SUB_REAL) {
05453
05454 if (p->subs[SUB_CALLWAIT].owner) {
05455
05456 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
05457 if (!p->subs[SUB_CALLWAIT].owner) {
05458
05459
05460
05461
05462 dahdi_disable_ec(p);
05463 return NULL;
05464 }
05465
05466
05467 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05468 if (option_verbose > 2)
05469 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05470 unalloc_sub(p, SUB_CALLWAIT);
05471 #if 0
05472 p->subs[index].needanswer = 0;
05473 p->subs[index].needringing = 0;
05474 #endif
05475 p->callwaitingrepeat = 0;
05476 p->cidcwexpire = 0;
05477 p->cid_suppress_expire = 0;
05478 p->owner = NULL;
05479
05480 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05481 p->dialing = 1;
05482
05483 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05484 dahdi_ring_phone(p);
05485 } else if (p->subs[SUB_THREEWAY].owner) {
05486 unsigned int mssinceflash;
05487
05488
05489 dahdi_lock_sub_owner(p, SUB_THREEWAY);
05490 if (!p->subs[SUB_THREEWAY].owner) {
05491 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05492
05493 return NULL;
05494 }
05495 if (p->owner != ast) {
05496 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05497 ast_log(LOG_WARNING, "This isn't good...\n");
05498
05499 return NULL;
05500 }
05501
05502 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05503 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
05504 if (mssinceflash < MIN_MS_SINCE_FLASH) {
05505
05506
05507 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05508 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
05509 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05510 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05511 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05512 if (p->transfer) {
05513
05514 p->subs[SUB_REAL].inthreeway = 0;
05515 p->subs[SUB_THREEWAY].inthreeway = 0;
05516
05517 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05518
05519 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05520
05521 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05522 p->owner = NULL;
05523
05524 dahdi_ring_phone(p);
05525 } else {
05526 res = attempt_transfer(p);
05527 if (res < 0) {
05528
05529 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05530 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05531 } else if (res) {
05532
05533 break;
05534 }
05535 }
05536 } else {
05537 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05538 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05539 }
05540 } else {
05541
05542 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05543
05544 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05545 p->owner = NULL;
05546
05547 dahdi_ring_phone(p);
05548 }
05549 }
05550 } else {
05551 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
05552 }
05553
05554 default:
05555 dahdi_disable_ec(p);
05556 return NULL;
05557 }
05558 break;
05559 case DAHDI_EVENT_RINGOFFHOOK:
05560 if (p->inalarm) break;
05561 if (p->oprmode < 0)
05562 {
05563 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05564 {
05565
05566 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05567 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
05568 restore_conference(p->oprpeer);
05569 }
05570 break;
05571 }
05572 if (p->radio)
05573 {
05574 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05575 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05576 break;
05577 }
05578
05579
05580 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05581 c = strchr(p->dialdest, '/');
05582 if (c)
05583 c++;
05584 else
05585 c = p->dialdest;
05586 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05587 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05588 if (strlen(p->dop.dialstr) > 4) {
05589 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05590 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05591 p->echorest[sizeof(p->echorest) - 1] = '\0';
05592 p->echobreak = 1;
05593 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05594 } else
05595 p->echobreak = 0;
05596 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05597 int saveerr = errno;
05598
05599 x = DAHDI_ONHOOK;
05600 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05601 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05602 return NULL;
05603 }
05604 p->dialing = 1;
05605 return &p->subs[index].f;
05606 }
05607 switch (p->sig) {
05608 case SIG_FXOLS:
05609 case SIG_FXOGS:
05610 case SIG_FXOKS:
05611 switch (ast->_state) {
05612 case AST_STATE_RINGING:
05613 dahdi_enable_ec(p);
05614 dahdi_train_ec(p);
05615 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05616 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05617
05618 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05619 p->subs[SUB_REAL].needringing = 0;
05620 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
05621
05622
05623 free(p->cidspill);
05624 p->cidspill = NULL;
05625 restore_conference(p);
05626
05627 p->dialing = 0;
05628 p->callwaitcas = 0;
05629 if (p->confirmanswer) {
05630
05631 p->subs[index].f.frametype = AST_FRAME_NULL;
05632 p->subs[index].f.subclass = 0;
05633 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05634
05635 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05636 if (res < 0) {
05637 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05638 p->dop.dialstr[0] = '\0';
05639 return NULL;
05640 } else {
05641 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05642 p->subs[index].f.frametype = AST_FRAME_NULL;
05643 p->subs[index].f.subclass = 0;
05644 p->dialing = 1;
05645 }
05646 p->dop.dialstr[0] = '\0';
05647 ast_setstate(ast, AST_STATE_DIALING);
05648 } else
05649 ast_setstate(ast, AST_STATE_UP);
05650 return &p->subs[index].f;
05651 case AST_STATE_DOWN:
05652 ast_setstate(ast, AST_STATE_RING);
05653 ast->rings = 1;
05654 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05655 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05656 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
05657 return &p->subs[index].f;
05658 case AST_STATE_UP:
05659
05660 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05661
05662 if (ast_bridged_channel(p->owner))
05663 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05664 p->subs[index].needunhold = 1;
05665 break;
05666 case AST_STATE_RESERVED:
05667
05668 if (has_voicemail(p))
05669 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05670 else
05671 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05672 break;
05673 default:
05674 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05675 }
05676 break;
05677 case SIG_FXSLS:
05678 case SIG_FXSGS:
05679 case SIG_FXSKS:
05680 if (ast->_state == AST_STATE_RING) {
05681 p->ringt = p->ringt_base;
05682 }
05683
05684
05685 case SIG_EM:
05686 case SIG_EM_E1:
05687 case SIG_EMWINK:
05688 case SIG_FEATD:
05689 case SIG_FEATDMF:
05690 case SIG_FEATDMF_TA:
05691 case SIG_E911:
05692 case SIG_FGC_CAMA:
05693 case SIG_FGC_CAMAMF:
05694 case SIG_FEATB:
05695 case SIG_SF:
05696 case SIG_SFWINK:
05697 case SIG_SF_FEATD:
05698 case SIG_SF_FEATDMF:
05699 case SIG_SF_FEATB:
05700 if (ast->_state == AST_STATE_PRERING)
05701 ast_setstate(ast, AST_STATE_RING);
05702 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05703 if (option_debug)
05704 ast_log(LOG_DEBUG, "Ring detected\n");
05705 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05706 p->subs[index].f.subclass = AST_CONTROL_RING;
05707 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05708 if (option_debug)
05709 ast_log(LOG_DEBUG, "Line answered\n");
05710 if (p->confirmanswer) {
05711 p->subs[index].f.frametype = AST_FRAME_NULL;
05712 p->subs[index].f.subclass = 0;
05713 } else {
05714 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05715 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05716 ast_setstate(ast, AST_STATE_UP);
05717 }
05718 } else if (ast->_state != AST_STATE_RING)
05719 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05720 break;
05721 default:
05722 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05723 }
05724 break;
05725 #ifdef DAHDI_EVENT_RINGBEGIN
05726 case DAHDI_EVENT_RINGBEGIN:
05727 switch (p->sig) {
05728 case SIG_FXSLS:
05729 case SIG_FXSGS:
05730 case SIG_FXSKS:
05731 if (ast->_state == AST_STATE_RING) {
05732 p->ringt = p->ringt_base;
05733 }
05734 break;
05735 }
05736 break;
05737 #endif
05738 case DAHDI_EVENT_RINGEROFF:
05739 if (p->inalarm) break;
05740 if ((p->radio || (p->oprmode < 0))) break;
05741 ast->rings++;
05742 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05743 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05744 free(p->cidspill);
05745 p->cidspill = NULL;
05746 p->callwaitcas = 0;
05747 }
05748 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05749 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05750 break;
05751 case DAHDI_EVENT_RINGERON:
05752 break;
05753 case DAHDI_EVENT_NOALARM:
05754 p->inalarm = 0;
05755 #ifdef HAVE_PRI
05756 p->resetting = 0;
05757
05758 if (p->bearer) {
05759 p->bearer->inalarm = 0;
05760 p->bearer->resetting = 0;
05761 }
05762 #endif
05763 if (!p->unknown_alarm) {
05764 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05765 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05766 "Channel: %d\r\n", p->channel);
05767 } else {
05768 p->unknown_alarm = 0;
05769 }
05770 break;
05771 case DAHDI_EVENT_WINKFLASH:
05772 if (p->inalarm) break;
05773 if (p->radio) break;
05774 if (p->oprmode < 0) break;
05775 if (p->oprmode > 1)
05776 {
05777 struct dahdi_params par;
05778
05779 memset(&par, 0, sizeof(par));
05780 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05781 {
05782 if (!par.rxisoffhook)
05783 {
05784
05785 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05786 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05787 save_conference(p);
05788 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05789 }
05790 }
05791 break;
05792 }
05793
05794 gettimeofday(&p->flashtime, NULL);
05795 switch (mysig) {
05796 case SIG_FXOLS:
05797 case SIG_FXOGS:
05798 case SIG_FXOKS:
05799 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05800 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05801
05802
05803 free(p->cidspill);
05804 p->cidspill = NULL;
05805 restore_conference(p);
05806 p->callwaitcas = 0;
05807
05808 if (index != SUB_REAL) {
05809 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05810 goto winkflashdone;
05811 }
05812
05813 if (p->subs[SUB_CALLWAIT].owner) {
05814
05815 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
05816 if (!p->subs[SUB_CALLWAIT].owner) {
05817
05818
05819
05820
05821 ast_log(LOG_NOTICE, "Whoa, the call-waiting call disappeared.\n");
05822 goto winkflashdone;
05823 }
05824
05825
05826 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05827 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05828 p->owner = p->subs[SUB_REAL].owner;
05829 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
05830 if (p->owner->_state == AST_STATE_RINGING) {
05831 ast_setstate(p->owner, AST_STATE_UP);
05832 p->subs[SUB_REAL].needanswer = 1;
05833 }
05834 p->callwaitingrepeat = 0;
05835 p->cidcwexpire = 0;
05836 p->cid_suppress_expire = 0;
05837
05838
05839 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05840 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05841 S_OR(p->mohsuggest, NULL),
05842 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05843 }
05844 p->subs[SUB_CALLWAIT].needhold = 1;
05845 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05846 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05847 S_OR(p->mohsuggest, NULL),
05848 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05849 }
05850 p->subs[SUB_REAL].needunhold = 1;
05851
05852
05853 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05854 } else if (!p->subs[SUB_THREEWAY].owner) {
05855 if (!p->threewaycalling) {
05856
05857 p->subs[SUB_REAL].needflash = 1;
05858 goto winkflashdone;
05859 } else if (!check_for_conference(p)) {
05860 char cid_num[256];
05861 char cid_name[256];
05862
05863 cid_num[0] = 0;
05864 cid_name[0] = 0;
05865 if (p->dahditrcallerid && p->owner) {
05866 if (p->owner->cid.cid_num)
05867 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05868 if (p->owner->cid.cid_name)
05869 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05870 }
05871
05872
05873 if (!((ast->pbx) ||
05874 (ast->_state == AST_STATE_UP) ||
05875 (ast->_state == AST_STATE_RING))) {
05876 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
05877 goto winkflashdone;
05878 }
05879 if (alloc_sub(p, SUB_THREEWAY)) {
05880 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05881 goto winkflashdone;
05882 }
05883
05884 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05885 if (!chan) {
05886 ast_log(LOG_WARNING,
05887 "Cannot allocate new call structure on channel %d\n",
05888 p->channel);
05889 unalloc_sub(p, SUB_THREEWAY);
05890 goto winkflashdone;
05891 }
05892 if (p->dahditrcallerid) {
05893 if (!p->origcid_num)
05894 p->origcid_num = ast_strdup(p->cid_num);
05895 if (!p->origcid_name)
05896 p->origcid_name = ast_strdup(p->cid_name);
05897 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05898 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05899 }
05900
05901 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05902
05903 dahdi_disable_ec(p);
05904 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05905 if (res)
05906 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05907 p->owner = chan;
05908 pthread_attr_init(&attr);
05909 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05910 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
05911 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05912 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05913 dahdi_enable_ec(p);
05914 ast_hangup(chan);
05915 } else {
05916 if (option_verbose > 2)
05917 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
05918
05919 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05920 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05921 S_OR(p->mohsuggest, NULL),
05922 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05923 }
05924 p->subs[SUB_THREEWAY].needhold = 1;
05925 }
05926 pthread_attr_destroy(&attr);
05927 }
05928 } else {
05929
05930 int orig_3way_sub;
05931
05932
05933 dahdi_lock_sub_owner(p, SUB_THREEWAY);
05934 if (!p->subs[SUB_THREEWAY].owner) {
05935
05936
05937
05938
05939 ast_log(LOG_NOTICE, "Whoa, the 3-way call disappeared.\n");
05940 goto winkflashdone;
05941 }
05942 orig_3way_sub = SUB_THREEWAY;
05943
05944 if (p->subs[SUB_THREEWAY].inthreeway) {
05945
05946 if (option_debug)
05947 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05948
05949 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05950
05951 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05952 orig_3way_sub = SUB_REAL;
05953 p->owner = p->subs[SUB_REAL].owner;
05954 }
05955
05956 if (option_verbose > 2)
05957 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05958 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05959 p->subs[SUB_REAL].inthreeway = 0;
05960 p->subs[SUB_THREEWAY].inthreeway = 0;
05961 } else {
05962
05963 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05964 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05965 if (option_verbose > 2) {
05966 ast_verbose(VERBOSE_PREFIX_3 "Building conference call with %s and %s\n",
05967 p->subs[SUB_THREEWAY].owner->name,
05968 p->subs[SUB_REAL].owner->name);
05969 }
05970
05971 p->subs[SUB_THREEWAY].inthreeway = 1;
05972 p->subs[SUB_REAL].inthreeway = 1;
05973 if (ast->_state == AST_STATE_UP) {
05974 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05975 orig_3way_sub = SUB_REAL;
05976 }
05977 if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) {
05978 ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD);
05979 }
05980 p->subs[orig_3way_sub].needunhold = 1;
05981 p->owner = p->subs[SUB_REAL].owner;
05982 } else {
05983 if (option_verbose > 2)
05984 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05985 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05986 orig_3way_sub = SUB_REAL;
05987 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05988 p->owner = p->subs[SUB_REAL].owner;
05989 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05990 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05991 }
05992 p->subs[SUB_REAL].needunhold = 1;
05993 dahdi_enable_ec(p);
05994 }
05995
05996 }
05997 ast_mutex_unlock(&p->subs[orig_3way_sub].owner->lock);
05998 }
05999 winkflashdone:
06000 update_conf(p);
06001 break;
06002 case SIG_EM:
06003 case SIG_EM_E1:
06004 case SIG_FEATD:
06005 case SIG_SF:
06006 case SIG_SFWINK:
06007 case SIG_SF_FEATD:
06008 case SIG_FXSLS:
06009 case SIG_FXSGS:
06010 if (p->dialing)
06011 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
06012 else
06013 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06014 break;
06015 case SIG_FEATDMF_TA:
06016 switch (p->whichwink) {
06017 case 0:
06018 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06019 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06020 break;
06021 case 1:
06022 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06023 break;
06024 case 2:
06025 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06026 return NULL;
06027 }
06028 p->whichwink++;
06029
06030 case SIG_FEATDMF:
06031 case SIG_E911:
06032 case SIG_FGC_CAMAMF:
06033 case SIG_FGC_CAMA:
06034 case SIG_FEATB:
06035 case SIG_SF_FEATDMF:
06036 case SIG_SF_FEATB:
06037 case SIG_EMWINK:
06038
06039 if (!ast_strlen_zero(p->dop.dialstr)) {
06040 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06041 if (res < 0) {
06042 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06043 p->dop.dialstr[0] = '\0';
06044 return NULL;
06045 } else
06046 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
06047 }
06048 p->dop.dialstr[0] = '\0';
06049 break;
06050 default:
06051 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
06052 }
06053 break;
06054 case DAHDI_EVENT_HOOKCOMPLETE:
06055 if (p->inalarm) break;
06056 if ((p->radio || (p->oprmode < 0))) break;
06057 switch (mysig) {
06058 case SIG_FXSLS:
06059 case SIG_FXSGS:
06060 case SIG_FXSKS:
06061 case SIG_EM:
06062 case SIG_EM_E1:
06063 case SIG_EMWINK:
06064 case SIG_FEATD:
06065 case SIG_SF:
06066 case SIG_SFWINK:
06067 case SIG_SF_FEATD:
06068 if (!ast_strlen_zero(p->dop.dialstr)) {
06069 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06070 if (res < 0) {
06071 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06072 p->dop.dialstr[0] = '\0';
06073 return NULL;
06074 } else
06075 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
06076 }
06077 p->dop.dialstr[0] = '\0';
06078 p->dop.op = DAHDI_DIAL_OP_REPLACE;
06079 break;
06080 case SIG_FEATDMF:
06081 case SIG_FEATDMF_TA:
06082 case SIG_E911:
06083 case SIG_FGC_CAMA:
06084 case SIG_FGC_CAMAMF:
06085 case SIG_FEATB:
06086 case SIG_SF_FEATDMF:
06087 case SIG_SF_FEATB:
06088 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06089 break;
06090 default:
06091 break;
06092 }
06093 break;
06094 case DAHDI_EVENT_POLARITY:
06095
06096
06097
06098
06099
06100
06101 if (p->polarity == POLARITY_IDLE) {
06102 p->polarity = POLARITY_REV;
06103 if (p->answeronpolarityswitch &&
06104 ((ast->_state == AST_STATE_DIALING) ||
06105 (ast->_state == AST_STATE_RINGING))) {
06106 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
06107 ast_setstate(p->owner, AST_STATE_UP);
06108 if (p->hanguponpolarityswitch) {
06109 gettimeofday(&p->polaritydelaytv, NULL);
06110 }
06111 } else
06112 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
06113 }
06114
06115
06116 if (p->hanguponpolarityswitch &&
06117 (p->polarityonanswerdelay > 0) &&
06118 (p->polarity == POLARITY_REV) &&
06119 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
06120
06121 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) );
06122
06123 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06124 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
06125 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06126 p->polarity = POLARITY_IDLE;
06127 } else {
06128 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);
06129 }
06130 } else {
06131 p->polarity = POLARITY_IDLE;
06132 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
06133 }
06134
06135 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) );
06136 break;
06137 default:
06138 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06139 }
06140 return &p->subs[index].f;
06141 }
06142
06143 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06144 {
06145 struct dahdi_pvt *p = ast->tech_pvt;
06146 int res;
06147 int index;
06148 struct ast_frame *f;
06149
06150
06151 index = dahdi_get_index(ast, p, 1);
06152 if (index < 0) {
06153 index = SUB_REAL;
06154 }
06155
06156 p->subs[index].f.frametype = AST_FRAME_NULL;
06157 p->subs[index].f.datalen = 0;
06158 p->subs[index].f.samples = 0;
06159 p->subs[index].f.mallocd = 0;
06160 p->subs[index].f.offset = 0;
06161 p->subs[index].f.subclass = 0;
06162 p->subs[index].f.delivery = ast_tv(0,0);
06163 p->subs[index].f.src = "dahdi_exception";
06164 p->subs[index].f.data = NULL;
06165
06166 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06167
06168
06169
06170
06171
06172 if (p->fake_event) {
06173 res = p->fake_event;
06174 p->fake_event = 0;
06175 } else
06176 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06177
06178 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06179 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06180 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
06181 p->owner = p->subs[SUB_REAL].owner;
06182 if (p->owner && ast != p->owner) {
06183
06184
06185
06186
06187 ast_log(LOG_WARNING, "Event %s on %s is not restored owner %s\n",
06188 event2str(res), ast->name, p->owner->name);
06189 }
06190 if (p->owner && ast_bridged_channel(p->owner))
06191 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06192 p->subs[SUB_REAL].needunhold = 1;
06193 }
06194 switch (res) {
06195 case DAHDI_EVENT_ONHOOK:
06196 dahdi_disable_ec(p);
06197 if (p->owner) {
06198 if (option_verbose > 2)
06199 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
06200 dahdi_ring_phone(p);
06201 p->callwaitingrepeat = 0;
06202 p->cidcwexpire = 0;
06203 p->cid_suppress_expire = 0;
06204 } else {
06205 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
06206 event2str(res));
06207 }
06208 update_conf(p);
06209 break;
06210 case DAHDI_EVENT_RINGOFFHOOK:
06211 dahdi_enable_ec(p);
06212 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06213 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06214 p->subs[SUB_REAL].needanswer = 1;
06215 p->dialing = 0;
06216 }
06217 break;
06218 case DAHDI_EVENT_HOOKCOMPLETE:
06219 case DAHDI_EVENT_RINGERON:
06220 case DAHDI_EVENT_RINGEROFF:
06221
06222 break;
06223 case DAHDI_EVENT_WINKFLASH:
06224 gettimeofday(&p->flashtime, NULL);
06225 if (p->owner) {
06226 if (option_verbose > 2)
06227 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06228 if (p->owner->_state != AST_STATE_UP) {
06229
06230 p->subs[SUB_REAL].needanswer = 1;
06231 ast_setstate(p->owner, AST_STATE_UP);
06232 }
06233 p->callwaitingrepeat = 0;
06234 p->cidcwexpire = 0;
06235 p->cid_suppress_expire = 0;
06236 if (ast_bridged_channel(p->owner))
06237 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06238 p->subs[SUB_REAL].needunhold = 1;
06239 } else {
06240 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
06241 event2str(res));
06242 }
06243 update_conf(p);
06244 break;
06245 default:
06246 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
06247 break;
06248 }
06249 f = &p->subs[index].f;
06250 return f;
06251 }
06252 if (!(p->radio || (p->oprmode < 0)) && option_debug)
06253 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
06254
06255 if (ast != p->owner) {
06256 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
06257 f = &p->subs[index].f;
06258 return f;
06259 }
06260 f = dahdi_handle_event(ast);
06261 return f;
06262 }
06263
06264 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
06265 {
06266 struct dahdi_pvt *p = ast->tech_pvt;
06267 struct ast_frame *f;
06268 ast_mutex_lock(&p->lock);
06269 f = __dahdi_exception(ast);
06270 ast_mutex_unlock(&p->lock);
06271 return f;
06272 }
06273
06274 static struct ast_frame *dahdi_read(struct ast_channel *ast)
06275 {
06276 struct dahdi_pvt *p;
06277 int res;
06278 int index;
06279 void *readbuf;
06280 struct ast_frame *f;
06281
06282
06283
06284
06285
06286
06287 p = ast->tech_pvt;
06288 while (ast_mutex_trylock(&p->lock)) {
06289 DEADLOCK_AVOIDANCE(&ast->lock);
06290
06291
06292
06293
06294
06295
06296 p = ast->tech_pvt;
06297 }
06298
06299 index = dahdi_get_index(ast, p, 0);
06300
06301
06302 if (index < 0) {
06303 ast_log(LOG_WARNING, "We don't exist?\n");
06304 ast_mutex_unlock(&p->lock);
06305 return NULL;
06306 }
06307
06308 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
06309 ast_mutex_unlock(&p->lock);
06310 return NULL;
06311 }
06312
06313 p->subs[index].f.frametype = AST_FRAME_NULL;
06314 p->subs[index].f.datalen = 0;
06315 p->subs[index].f.samples = 0;
06316 p->subs[index].f.mallocd = 0;
06317 p->subs[index].f.offset = 0;
06318 p->subs[index].f.subclass = 0;
06319 p->subs[index].f.delivery = ast_tv(0,0);
06320 p->subs[index].f.src = "dahdi_read";
06321 p->subs[index].f.data = NULL;
06322
06323
06324 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
06325 {
06326 struct dahdi_params ps;
06327
06328 memset(&ps, 0, sizeof(ps));
06329 ps.channo = p->channel;
06330 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
06331 ast_mutex_unlock(&p->lock);
06332 return NULL;
06333 }
06334 p->firstradio = 1;
06335 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06336 if (ps.rxisoffhook)
06337 {
06338 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
06339 }
06340 else
06341 {
06342 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
06343 }
06344 ast_mutex_unlock(&p->lock);
06345 return &p->subs[index].f;
06346 }
06347 if (p->ringt == 1) {
06348 ast_mutex_unlock(&p->lock);
06349 return NULL;
06350 }
06351 else if (p->ringt > 0)
06352 p->ringt--;
06353
06354 #ifdef HAVE_OPENR2
06355 if (p->mfcr2) {
06356 openr2_chan_process_event(p->r2chan);
06357 }
06358 #endif
06359
06360 if (p->subs[index].needringing) {
06361
06362 p->subs[index].needringing = 0;
06363 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06364 p->subs[index].f.subclass = AST_CONTROL_RINGING;
06365 ast_setstate(ast, AST_STATE_RINGING);
06366 ast_mutex_unlock(&p->lock);
06367 return &p->subs[index].f;
06368 }
06369
06370 if (p->subs[index].needbusy) {
06371
06372 p->subs[index].needbusy = 0;
06373 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06374 p->subs[index].f.subclass = AST_CONTROL_BUSY;
06375 ast_mutex_unlock(&p->lock);
06376 return &p->subs[index].f;
06377 }
06378
06379 if (p->subs[index].needcongestion) {
06380
06381 p->subs[index].needcongestion = 0;
06382 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06383 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
06384 ast_mutex_unlock(&p->lock);
06385 return &p->subs[index].f;
06386 }
06387
06388 if (p->subs[index].needcallerid && !ast->cid.cid_tns) {
06389 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06390 S_OR(p->lastcid_name, NULL),
06391 S_OR(p->lastcid_num, NULL)
06392 );
06393 p->subs[index].needcallerid = 0;
06394 }
06395
06396 if (p->subs[index].needanswer) {
06397
06398 p->subs[index].needanswer = 0;
06399 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06400 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
06401 ast_mutex_unlock(&p->lock);
06402 return &p->subs[index].f;
06403 }
06404
06405 #ifdef HAVE_OPENR2
06406 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06407
06408
06409
06410
06411 p->subs[index].f.frametype = AST_FRAME_NULL;
06412 p->subs[index].f.subclass = 0;
06413 p->subs[index].f.samples = 0;
06414 p->subs[index].f.mallocd = 0;
06415 p->subs[index].f.offset = 0;
06416 p->subs[index].f.data = NULL;
06417 p->subs[index].f.datalen= 0;
06418 ast_mutex_unlock(&p->lock);
06419 return &p->subs[index].f;
06420 }
06421 #endif
06422
06423 if (p->subs[index].needflash) {
06424
06425 p->subs[index].needflash = 0;
06426 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06427 p->subs[index].f.subclass = AST_CONTROL_FLASH;
06428 ast_mutex_unlock(&p->lock);
06429 return &p->subs[index].f;
06430 }
06431
06432 if (p->subs[index].needhold) {
06433
06434 p->subs[index].needhold = 0;
06435 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06436 p->subs[index].f.subclass = AST_CONTROL_HOLD;
06437 ast_mutex_unlock(&p->lock);
06438 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
06439 return &p->subs[index].f;
06440 }
06441
06442 if (p->subs[index].needunhold) {
06443
06444 p->subs[index].needunhold = 0;
06445 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06446 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
06447 ast_mutex_unlock(&p->lock);
06448 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
06449 return &p->subs[index].f;
06450 }
06451
06452 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06453 if (!p->subs[index].linear) {
06454 p->subs[index].linear = 1;
06455 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06456 if (res)
06457 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
06458 }
06459 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06460 (ast->rawreadformat == AST_FORMAT_ALAW)) {
06461 if (p->subs[index].linear) {
06462 p->subs[index].linear = 0;
06463 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06464 if (res)
06465 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
06466 }
06467 } else {
06468 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06469 ast_mutex_unlock(&p->lock);
06470 return NULL;
06471 }
06472 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
06473 CHECK_BLOCKING(ast);
06474 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06475 ast_clear_flag(ast, AST_FLAG_BLOCKING);
06476
06477 if (p->use_callerid && (ast->_state == AST_STATE_PRERING &&
06478 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
06479
06480 if (!p->subs[index].linear) {
06481 int x, samplin;
06482 int mean, ssum;
06483
06484
06485 for (x = 0, ssum = 0; x < READ_SIZE; x++) {
06486
06487 ssum += AST_MULAW(((u_char *)readbuf)[x]);
06488 if (option_verbose > 5 && (x % 10 == 0))
06489 ast_log(LOG_NOTICE, "dahdi_read ssum %i, mean %i \n", ssum, ssum / READ_SIZE);
06490 }
06491 mean = ssum / READ_SIZE;
06492
06493 if (option_verbose > 5)
06494 ast_log(LOG_WARNING, "dahdi_read channel %s, mean %i \n", ast->name, mean);
06495 if (ast->rawreadformat == AST_FORMAT_ULAW) {
06496 for (x = 0; x < READ_SIZE; x++) {
06497 samplin = AST_MULAW(((u_char *)readbuf)[x]);
06498 if (option_verbose > 6 && (x % 10 == 0))
06499 ast_log(LOG_NOTICE, "dahdi_read,x %i, samporig %i samplin %i, samplinconv %i, xconv %i\n", x, ((u_char *)readbuf)[x], samplin, samplin - mean, AST_LIN2MU(samplin - mean));
06500 ((u_char *)readbuf)[x] = AST_LIN2MU(samplin - mean);
06501 }
06502 }
06503 }
06504 }
06505
06506
06507 if (res < 0) {
06508 f = NULL;
06509 if (res == -1) {
06510 if (errno == EAGAIN) {
06511
06512 ast_mutex_unlock(&p->lock);
06513 return &p->subs[index].f;
06514 } else if (errno == ELAST) {
06515 f = __dahdi_exception(ast);
06516 } else
06517 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06518 }
06519 ast_mutex_unlock(&p->lock);
06520 return f;
06521 }
06522 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06523 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06524 f = __dahdi_exception(ast);
06525 ast_mutex_unlock(&p->lock);
06526 return f;
06527 }
06528 if (p->tdd) {
06529 int c;
06530
06531 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06532 if (c < 0) {
06533 ast_log(LOG_DEBUG,"tdd_feed failed\n");
06534 ast_mutex_unlock(&p->lock);
06535 return NULL;
06536 }
06537 if (c) {
06538 p->subs[index].f.subclass = 0;
06539 p->subs[index].f.frametype = AST_FRAME_TEXT;
06540 p->subs[index].f.mallocd = 0;
06541 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06542 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06543 p->subs[index].f.datalen = 1;
06544 *((char *) p->subs[index].f.data) = c;
06545 ast_mutex_unlock(&p->lock);
06546 return &p->subs[index].f;
06547 }
06548 }
06549 if (index == SUB_REAL) {
06550
06551 if (p->cidcwexpire) {
06552 if (!--p->cidcwexpire) {
06553
06554 if (option_verbose > 2)
06555 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06556 restore_conference(p);
06557 }
06558 }
06559 if (p->cid_suppress_expire) {
06560 --p->cid_suppress_expire;
06561 }
06562 if (p->callwaitingrepeat) {
06563 if (!--p->callwaitingrepeat) {
06564
06565 ++p->callwaitrings;
06566 dahdi_callwait(ast);
06567 }
06568 }
06569 }
06570 if (p->subs[index].linear) {
06571 p->subs[index].f.datalen = READ_SIZE * 2;
06572 } else
06573 p->subs[index].f.datalen = READ_SIZE;
06574
06575
06576 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06577 send_callerid(p);
06578 }
06579
06580 p->subs[index].f.frametype = AST_FRAME_VOICE;
06581 p->subs[index].f.subclass = ast->rawreadformat;
06582 p->subs[index].f.samples = READ_SIZE;
06583 p->subs[index].f.mallocd = 0;
06584 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06585 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06586 #if 0
06587 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06588 #endif
06589 if (p->dialing ||
06590 (index && (ast->_state != AST_STATE_UP)) ||
06591 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
06592 ) {
06593
06594
06595 p->subs[index].f.frametype = AST_FRAME_NULL;
06596 p->subs[index].f.subclass = 0;
06597 p->subs[index].f.samples = 0;
06598 p->subs[index].f.mallocd = 0;
06599 p->subs[index].f.offset = 0;
06600 p->subs[index].f.data = NULL;
06601 p->subs[index].f.datalen= 0;
06602 }
06603 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
06604
06605 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06606 if (f) {
06607 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06608 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06609
06610
06611 f = NULL;
06612 }
06613 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
06614 || f->frametype == AST_FRAME_DTMF_END) {
06615 #ifdef HAVE_PRI
06616 if (p->sig == SIG_PRI
06617 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06618 && p->pri
06619 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
06620 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06621
06622 ast_log(LOG_DEBUG,
06623 "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
06624 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
06625 f->subclass, f->subclass, ast->name);
06626
06627 f->frametype = AST_FRAME_NULL;
06628 f->subclass = 0;
06629 }
06630 #endif
06631
06632 p->pulsedial = 0;
06633 }
06634 }
06635 } else
06636 f = &p->subs[index].f;
06637
06638 if (f) {
06639 switch (f->frametype) {
06640 case AST_FRAME_DTMF_BEGIN:
06641 case AST_FRAME_DTMF_END:
06642 dahdi_handle_dtmf(ast, index, &f);
06643 break;
06644 case AST_FRAME_VOICE:
06645 if (p->cidspill || p->cid_suppress_expire) {
06646
06647 p->subs[index].f.frametype = AST_FRAME_NULL;
06648 p->subs[index].f.subclass = 0;
06649 p->subs[index].f.samples = 0;
06650 p->subs[index].f.mallocd = 0;
06651 p->subs[index].f.offset = 0;
06652 p->subs[index].f.data = NULL;
06653 p->subs[index].f.datalen= 0;
06654 }
06655 break;
06656 default:
06657 break;
06658 }
06659 }
06660
06661
06662 if (p->fake_event)
06663 ast_set_flag(ast, AST_FLAG_EXCEPTION);
06664
06665 ast_mutex_unlock(&p->lock);
06666 return f;
06667 }
06668
06669 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
06670 {
06671 int sent=0;
06672 int size;
06673 int res;
06674 int fd;
06675 fd = p->subs[index].dfd;
06676 while (len) {
06677 size = len;
06678 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06679 size = (linear ? READ_SIZE * 2 : READ_SIZE);
06680 res = write(fd, buf, size);
06681 if (res != size) {
06682 if (option_debug)
06683 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06684 return sent;
06685 }
06686 len -= size;
06687 buf += size;
06688 }
06689 return sent;
06690 }
06691
06692 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06693 {
06694 struct dahdi_pvt *p = ast->tech_pvt;
06695 int res;
06696 int index;
06697 index = dahdi_get_index(ast, p, 0);
06698 if (index < 0) {
06699 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06700 return -1;
06701 }
06702
06703
06704 if (frame->frametype != AST_FRAME_VOICE) {
06705 if (frame->frametype != AST_FRAME_IMAGE)
06706 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06707 return 0;
06708 }
06709 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06710 (frame->subclass != AST_FORMAT_ULAW) &&
06711 (frame->subclass != AST_FORMAT_ALAW)) {
06712 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06713 return -1;
06714 }
06715 if (p->dialing) {
06716 if (option_debug)
06717 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06718 return 0;
06719 }
06720 if (!p->owner) {
06721 if (option_debug)
06722 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06723 return 0;
06724 }
06725 if (p->cidspill) {
06726 if (option_debug) {
06727 ast_log(LOG_DEBUG,
06728 "Dropping frame since I've still got a callerid spill on %s...\n",
06729 ast->name);
06730 }
06731 return 0;
06732 }
06733
06734 if (!frame->data || !frame->datalen)
06735 return 0;
06736
06737 if (frame->subclass == AST_FORMAT_SLINEAR) {
06738 if (!p->subs[index].linear) {
06739 p->subs[index].linear = 1;
06740 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06741 if (res)
06742 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06743 }
06744 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06745 } else {
06746
06747 if (p->subs[index].linear) {
06748 p->subs[index].linear = 0;
06749 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06750 if (res)
06751 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06752 }
06753 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06754 }
06755 if (res < 0) {
06756 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06757 return -1;
06758 }
06759 return 0;
06760 }
06761
06762 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06763 {
06764 struct dahdi_pvt *p = chan->tech_pvt;
06765 int res=-1;
06766 int index;
06767 int func = DAHDI_FLASH;
06768 ast_mutex_lock(&p->lock);
06769 index = dahdi_get_index(chan, p, 0);
06770 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06771 #ifdef HAVE_OPENR2
06772 if (p->mfcr2 && !p->mfcr2_call_accepted) {
06773 ast_mutex_unlock(&p->lock);
06774
06775
06776 return 0;
06777 }
06778 #endif
06779 if (index == SUB_REAL) {
06780 switch (condition) {
06781 case AST_CONTROL_BUSY:
06782 #ifdef HAVE_PRI
06783 if (p->sig == SIG_PRI) {
06784 if (p->priindication_oob) {
06785 chan->hangupcause = AST_CAUSE_USER_BUSY;
06786 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06787 res = 0;
06788 break;
06789 }
06790 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06791 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
06792 chan->hangupcause = AST_CAUSE_USER_BUSY;
06793 p->progress = 1;
06794 if (p->pri && p->pri->pri) {
06795 if (!pri_grab(p, p->pri)) {
06796 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06797 pri_rel(p->pri);
06798 } else {
06799 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06800 }
06801 }
06802 }
06803 break;
06804 }
06805 #endif
06806 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06807 break;
06808 case AST_CONTROL_RINGING:
06809 #ifdef HAVE_PRI
06810 if (p->sig == SIG_PRI
06811 && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
06812 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
06813 if (p->pri && p->pri->pri) {
06814 if (!pri_grab(p, p->pri)) {
06815 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06816 pri_rel(p->pri);
06817 } else {
06818 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06819 }
06820 }
06821 }
06822 #endif
06823 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06824 if (chan->_state != AST_STATE_UP) {
06825 if ((chan->_state != AST_STATE_RING) ||
06826 ((p->sig != SIG_FXSKS) &&
06827 (p->sig != SIG_FXSLS) &&
06828 (p->sig != SIG_FXSGS)))
06829 ast_setstate(chan, AST_STATE_RINGING);
06830 }
06831 break;
06832 case AST_CONTROL_PROCEEDING:
06833 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06834 #ifdef HAVE_PRI
06835 if (p->sig == SIG_PRI
06836 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
06837 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
06838 if (p->pri && p->pri->pri) {
06839 if (!pri_grab(p, p->pri)) {
06840 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06841 pri_rel(p->pri);
06842 } else {
06843 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06844 }
06845 }
06846 p->dialing = 0;
06847 }
06848 #endif
06849
06850 res = 0;
06851 break;
06852 case AST_CONTROL_PROGRESS:
06853 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06854 #ifdef HAVE_PRI
06855 p->digital = 0;
06856 if (p->sig == SIG_PRI
06857 && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
06858 && !p->outgoing) {
06859 p->progress = 1;
06860 if (p->pri && p->pri->pri) {
06861 if (!pri_grab(p, p->pri)) {
06862 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06863 pri_rel(p->pri);
06864 } else {
06865 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06866 }
06867 }
06868 }
06869 #endif
06870
06871 res = 0;
06872 break;
06873 case AST_CONTROL_CONGESTION:
06874 #ifdef HAVE_PRI
06875 if (p->sig == SIG_PRI) {
06876 if (p->priindication_oob) {
06877
06878 switch (chan->hangupcause) {
06879 case AST_CAUSE_USER_BUSY:
06880 case AST_CAUSE_NORMAL_CLEARING:
06881 case 0:
06882
06883 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06884 break;
06885 default:
06886 break;
06887 }
06888 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06889 res = 0;
06890 break;
06891 }
06892 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06893 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
06894
06895 switch (chan->hangupcause) {
06896 case AST_CAUSE_USER_BUSY:
06897 case AST_CAUSE_NORMAL_CLEARING:
06898 case 0:
06899
06900 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06901 break;
06902 default:
06903 break;
06904 }
06905 p->progress = 1;
06906 if (p->pri && p->pri->pri) {
06907 if (!pri_grab(p, p->pri)) {
06908 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06909 pri_rel(p->pri);
06910 } else {
06911 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06912 }
06913 }
06914 }
06915 break;
06916 }
06917 #endif
06918
06919 switch (chan->hangupcause) {
06920 case AST_CAUSE_USER_BUSY:
06921 case AST_CAUSE_NORMAL_CLEARING:
06922 case 0:
06923
06924 chan->hangupcause = AST_CAUSE_CONGESTION;
06925 break;
06926 default:
06927 break;
06928 }
06929 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06930 break;
06931 case AST_CONTROL_HOLD:
06932 #ifdef HAVE_PRI
06933 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06934 if (!pri_grab(p, p->pri)) {
06935 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06936 pri_rel(p->pri);
06937 } else
06938 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06939 } else
06940 #endif
06941 ast_moh_start(chan, data, p->mohinterpret);
06942 break;
06943 case AST_CONTROL_UNHOLD:
06944 #ifdef HAVE_PRI
06945 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06946 if (!pri_grab(p, p->pri)) {
06947 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06948 pri_rel(p->pri);
06949 } else
06950 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06951 } else
06952 #endif
06953 ast_moh_stop(chan);
06954 break;
06955 case AST_CONTROL_RADIO_KEY:
06956 if (p->radio)
06957 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06958 res = 0;
06959 break;
06960 case AST_CONTROL_RADIO_UNKEY:
06961 if (p->radio)
06962 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06963 res = 0;
06964 break;
06965 case AST_CONTROL_FLASH:
06966
06967 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06968
06969 p->dop.dialstr[0] = '\0';
06970 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06971 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06972 chan->name, strerror(errno));
06973 } else
06974 res = 0;
06975 } else
06976 res = 0;
06977 break;
06978 case AST_CONTROL_SRCUPDATE:
06979 res = 0;
06980 break;
06981 case -1:
06982 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06983 break;
06984 }
06985 } else
06986 res = 0;
06987 ast_mutex_unlock(&p->lock);
06988 return res;
06989 }
06990
06991 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
06992 {
06993 struct ast_channel *tmp;
06994 int deflaw;
06995 int res;
06996 int x,y;
06997 int features;
06998 char *b2 = NULL;
06999 struct dahdi_params ps;
07000 char chanprefix[*dahdi_chan_name_len + 4];
07001
07002 if (i->subs[index].owner) {
07003 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
07004 return NULL;
07005 }
07006 y = 1;
07007 do {
07008 if (b2)
07009 free(b2);
07010 #ifdef HAVE_PRI
07011 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07012 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07013 else
07014 #endif
07015 if (i->channel == CHAN_PSEUDO)
07016 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
07017 else
07018 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
07019 for (x = 0; x < 3; x++) {
07020 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
07021 break;
07022 }
07023 y++;
07024 } while (x < 3);
07025 strcpy(chanprefix, dahdi_chan_name);
07026 strcat(chanprefix, "/%s");
07027 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
07028 if (b2)
07029 free(b2);
07030 if (!tmp)
07031 return NULL;
07032 tmp->tech = chan_tech;
07033 memset(&ps, 0, sizeof(ps));
07034 ps.channo = i->channel;
07035 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07036 if (res) {
07037 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07038 ps.curlaw = DAHDI_LAW_MULAW;
07039 }
07040 if (ps.curlaw == DAHDI_LAW_ALAW)
07041 deflaw = AST_FORMAT_ALAW;
07042 else
07043 deflaw = AST_FORMAT_ULAW;
07044 if (law) {
07045 if (law == DAHDI_LAW_ALAW)
07046 deflaw = AST_FORMAT_ALAW;
07047 else
07048 deflaw = AST_FORMAT_ULAW;
07049 }
07050 tmp->fds[0] = i->subs[index].dfd;
07051 tmp->nativeformats = deflaw;
07052
07053 tmp->rawreadformat = deflaw;
07054 tmp->readformat = deflaw;
07055 tmp->rawwriteformat = deflaw;
07056 tmp->writeformat = deflaw;
07057 i->subs[index].linear = 0;
07058 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
07059 features = 0;
07060 if (index == SUB_REAL) {
07061 if (i->busydetect && CANBUSYDETECT(i))
07062 features |= DSP_FEATURE_BUSY_DETECT;
07063 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
07064 features |= DSP_FEATURE_CALL_PROGRESS;
07065 if ((!i->outgoing && (i->callprogress & 4)) ||
07066 (i->outgoing && (i->callprogress & 2))) {
07067 features |= DSP_FEATURE_FAX_DETECT;
07068 }
07069 #ifdef DAHDI_TONEDETECT
07070 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07071 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
07072 #endif
07073 i->hardwaredtmf = 0;
07074 features |= DSP_FEATURE_DTMF_DETECT;
07075 #ifdef DAHDI_TONEDETECT
07076 } else if (NEED_MFDETECT(i)) {
07077 i->hardwaredtmf = 1;
07078 features |= DSP_FEATURE_DTMF_DETECT;
07079 }
07080 #endif
07081 }
07082 if (features) {
07083 if (i->dsp) {
07084 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
07085 } else {
07086 if (i->channel != CHAN_PSEUDO)
07087 i->dsp = ast_dsp_new();
07088 else
07089 i->dsp = NULL;
07090 if (i->dsp) {
07091 i->dsp_features = features;
07092 #ifdef HAVE_PRI
07093
07094 if (i->outgoing && (i->sig == SIG_PRI)) {
07095
07096
07097 i->dsp_features = features & ~DSP_PROGRESS_TALK;
07098 features = 0;
07099 }
07100 #endif
07101 ast_dsp_set_features(i->dsp, features);
07102 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07103 if (!ast_strlen_zero(progzone))
07104 ast_dsp_set_call_progress_zone(i->dsp, progzone);
07105 if (i->busydetect && CANBUSYDETECT(i)) {
07106 if(i->silencethreshold > 0)
07107 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
07108 ast_dsp_set_busy_count(i->dsp, i->busycount);
07109 if(i->busytonelength > 0)
07110 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
07111 if((i->busytonelength == i->busyquietlength) && i->busycompare)
07112 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
07113 }
07114 }
07115 }
07116 }
07117
07118 if (state == AST_STATE_RING)
07119 tmp->rings = 1;
07120 tmp->tech_pvt = i;
07121 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07122
07123 tmp->callgroup = i->callgroup;
07124 tmp->pickupgroup = i->pickupgroup;
07125 }
07126 if (!ast_strlen_zero(i->language))
07127 ast_string_field_set(tmp, language, i->language);
07128 if (!i->owner)
07129 i->owner = tmp;
07130 if (!ast_strlen_zero(i->accountcode))
07131 ast_string_field_set(tmp, accountcode, i->accountcode);
07132 if (i->amaflags)
07133 tmp->amaflags = i->amaflags;
07134 i->subs[index].owner = tmp;
07135 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07136 ast_string_field_set(tmp, call_forward, i->call_forward);
07137
07138 if (!i->adsi)
07139 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07140 if (!ast_strlen_zero(i->exten))
07141 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07142 if (!ast_strlen_zero(i->rdnis))
07143 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07144 if (!ast_strlen_zero(i->dnid))
07145 tmp->cid.cid_dnid = ast_strdup(i->dnid);
07146
07147
07148
07149 #ifdef PRI_ANI
07150 if (!ast_strlen_zero(i->cid_ani))
07151 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07152 else
07153 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07154 #else
07155 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07156 #endif
07157 tmp->cid.cid_pres = i->callingpres;
07158 tmp->cid.cid_ton = i->cid_ton;
07159 #ifdef HAVE_PRI
07160 tmp->transfercapability = transfercapability;
07161 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07162 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
07163 i->digital = 1;
07164
07165 i->isidlecall = 0;
07166 i->alreadyhungup = 0;
07167 #endif
07168
07169 i->fake_event = 0;
07170
07171 dahdi_confmute(i, 0);
07172
07173 ast_jb_configure(tmp, &global_jbconf);
07174 if (startpbx) {
07175
07176 #ifdef HAVE_OPENR2
07177 if (i->mfcr2call) {
07178 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07179 }
07180 #endif
07181
07182 if (ast_pbx_start(tmp)) {
07183 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07184 ast_hangup(tmp);
07185 i->owner = NULL;
07186 return NULL;
07187 }
07188 }
07189
07190 ast_module_ref(ast_module_info->self);
07191
07192 return tmp;
07193 }
07194
07195
07196 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
07197 {
07198 char c;
07199
07200 *str = 0;
07201 for (;;)
07202 {
07203
07204 c = ast_waitfordigit(chan, ms);
07205
07206 if (c < 1)
07207 return c;
07208 *str++ = c;
07209 *str = 0;
07210 if (strchr(term, c))
07211 return 1;
07212 }
07213 }
07214
07215 static int dahdi_wink(struct dahdi_pvt *p, int index)
07216 {
07217 int j;
07218 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
07219 for (;;)
07220 {
07221
07222 j = DAHDI_IOMUX_SIGEVENT;
07223
07224 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
07225
07226 if (j & DAHDI_IOMUX_SIGEVENT) break;
07227 }
07228
07229 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
07230 return 0;
07231 }
07232
07233 static void *ss_thread(void *data)
07234 {
07235 struct ast_channel *chan = data;
07236 struct dahdi_pvt *p = chan->tech_pvt;
07237 char exten[AST_MAX_EXTENSION] = "";
07238 char exten2[AST_MAX_EXTENSION] = "";
07239 unsigned char buf[256];
07240 char dtmfcid[300];
07241 char dtmfbuf[300];
07242 struct callerid_state *cs = NULL;
07243 char *name = NULL, *number = NULL;
07244 int distMatches;
07245 int curRingData[3];
07246 int receivedRingT;
07247 int counter1;
07248 int counter;
07249 int samples = 0;
07250 struct ast_smdi_md_message *smdi_msg = NULL;
07251 int flags = 0;
07252 int i;
07253 int timeout;
07254 int getforward = 0;
07255 char *s1, *s2;
07256 int len = 0;
07257 int res;
07258 int index;
07259
07260 ast_mutex_lock(&ss_thread_lock);
07261 ss_thread_count++;
07262 ast_mutex_unlock(&ss_thread_lock);
07263
07264
07265
07266 if (!p) {
07267 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
07268 ast_hangup(chan);
07269 goto quit;
07270 }
07271 if (option_verbose > 2)
07272 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
07273 index = dahdi_get_index(chan, p, 0);
07274 if (index < 0) {
07275 ast_hangup(chan);
07276 goto quit;
07277 }
07278 if (p->dsp)
07279 ast_dsp_digitreset(p->dsp);
07280 switch (p->sig) {
07281 #ifdef HAVE_PRI
07282 case SIG_PRI:
07283
07284 ast_copy_string(exten, p->exten, sizeof(exten));
07285 len = strlen(exten);
07286 res = 0;
07287 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07288 if (len && !ast_ignore_pattern(chan->context, exten))
07289 tone_zone_play_tone(p->subs[index].dfd, -1);
07290 else
07291 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07292 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
07293 timeout = matchdigittimeout;
07294 else
07295 timeout = gendigittimeout;
07296 res = ast_waitfordigit(chan, timeout);
07297 if (res < 0) {
07298 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07299 ast_hangup(chan);
07300 goto quit;
07301 } else if (res) {
07302 exten[len++] = res;
07303 exten[len] = '\0';
07304 } else
07305 break;
07306 }
07307
07308 if (ast_strlen_zero(exten)) {
07309 if (option_verbose > 2)
07310 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
07311 exten[0] = 's';
07312 exten[1] = '\0';
07313 }
07314 tone_zone_play_tone(p->subs[index].dfd, -1);
07315 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
07316
07317 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07318 if (p->dsp) {
07319 ast_dsp_digitreset(p->dsp);
07320 }
07321 #if defined(ISSUE_16789)
07322
07323
07324
07325
07326
07327
07328
07329
07330
07331
07332
07333
07334 if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
07335 && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07336 ast_mutex_lock(&p->lock);
07337 if (p->pri->pri) {
07338 if (!pri_grab(p, p->pri)) {
07339 if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
07340 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07341 }
07342 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
07343 pri_rel(p->pri);
07344 } else {
07345 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07346 }
07347 }
07348 ast_mutex_unlock(&p->lock);
07349 }
07350 #endif
07351
07352 dahdi_enable_ec(p);
07353 ast_setstate(chan, AST_STATE_RING);
07354 res = ast_pbx_run(chan);
07355 if (res) {
07356 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
07357 }
07358 } else {
07359 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
07360 chan->hangupcause = AST_CAUSE_UNALLOCATED;
07361 ast_hangup(chan);
07362 p->exten[0] = '\0';
07363
07364 p->call = NULL;
07365 }
07366 goto quit;
07367 break;
07368 #endif
07369 case SIG_FEATD:
07370 case SIG_FEATDMF:
07371 case SIG_FEATDMF_TA:
07372 case SIG_E911:
07373 case SIG_FGC_CAMAMF:
07374 case SIG_FEATB:
07375 case SIG_EMWINK:
07376 case SIG_SF_FEATD:
07377 case SIG_SF_FEATDMF:
07378 case SIG_SF_FEATB:
07379 case SIG_SFWINK:
07380 if (dahdi_wink(p, index))
07381 goto quit;
07382
07383 case SIG_EM:
07384 case SIG_EM_E1:
07385 case SIG_SF:
07386 case SIG_FGC_CAMA:
07387 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07388 if (p->dsp)
07389 ast_dsp_digitreset(p->dsp);
07390
07391 if (p->dsp) {
07392 if (NEED_MFDETECT(p))
07393 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
07394 else
07395 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07396 }
07397 memset(dtmfbuf, 0, sizeof(dtmfbuf));
07398
07399 if (!p->immediate)
07400
07401 res = ast_waitfordigit(chan, 5000);
07402 else
07403 res = 0;
07404 if (res > 0) {
07405
07406 dtmfbuf[0] = res;
07407 switch (p->sig) {
07408 case SIG_FEATD:
07409 case SIG_SF_FEATD:
07410 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07411 if (res > 0)
07412 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07413 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07414 break;
07415 case SIG_FEATDMF_TA:
07416 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07417 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07418 if (dahdi_wink(p, index)) goto quit;
07419 dtmfbuf[0] = 0;
07420
07421 res = ast_waitfordigit(chan, 5000);
07422 if (res <= 0) break;
07423 dtmfbuf[0] = res;
07424
07425 case SIG_FEATDMF:
07426 case SIG_E911:
07427 case SIG_FGC_CAMAMF:
07428 case SIG_SF_FEATDMF:
07429 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07430
07431 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
07432 {
07433 if (dahdi_wink(p, index)) goto quit;
07434 dtmfbuf[0] = 0;
07435
07436 res = ast_waitfordigit(chan, 5000);
07437 if (res <= 0) break;
07438 dtmfbuf[0] = res;
07439 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07440 }
07441 if (res > 0) {
07442
07443 if (p->sig == SIG_E911)
07444 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07445 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
07446 }
07447 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07448 break;
07449 case SIG_FEATB:
07450 case SIG_SF_FEATB:
07451 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07452 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07453 break;
07454 case SIG_EMWINK:
07455
07456
07457
07458
07459 if (res == '*') {
07460 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07461 if (res > 0)
07462 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07463 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07464 break;
07465 }
07466 default:
07467
07468 len = 1;
07469 dtmfbuf[len] = '\0';
07470 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07471 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07472 timeout = matchdigittimeout;
07473 } else {
07474 timeout = gendigittimeout;
07475 }
07476 res = ast_waitfordigit(chan, timeout);
07477 if (res < 0) {
07478 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07479 ast_hangup(chan);
07480 goto quit;
07481 } else if (res) {
07482 dtmfbuf[len++] = res;
07483 dtmfbuf[len] = '\0';
07484 } else {
07485 break;
07486 }
07487 }
07488 break;
07489 }
07490 }
07491 if (res == -1) {
07492 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
07493 ast_hangup(chan);
07494 goto quit;
07495 } else if (res < 0) {
07496 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
07497 ast_hangup(chan);
07498 goto quit;
07499 }
07500
07501 if (p->sig == SIG_FGC_CAMA) {
07502 char anibuf[100];
07503
07504 if (ast_safe_sleep(chan,1000) == -1) {
07505 ast_hangup(chan);
07506 goto quit;
07507 }
07508 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07509 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
07510 res = my_getsigstr(chan, anibuf, "#", 10000);
07511 if ((res > 0) && (strlen(anibuf) > 2)) {
07512 if (anibuf[strlen(anibuf) - 1] == '#')
07513 anibuf[strlen(anibuf) - 1] = 0;
07514 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07515 }
07516 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07517 }
07518
07519 ast_copy_string(exten, dtmfbuf, sizeof(exten));
07520 if (ast_strlen_zero(exten))
07521 ast_copy_string(exten, "s", sizeof(exten));
07522 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07523
07524 if (exten[0] == '*') {
07525 char *stringp=NULL;
07526 ast_copy_string(exten2, exten, sizeof(exten2));
07527
07528 stringp=exten2 +1;
07529 s1 = strsep(&stringp, "*");
07530 s2 = strsep(&stringp, "*");
07531 if (s2) {
07532 if (!ast_strlen_zero(p->cid_num))
07533 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07534 else
07535 ast_set_callerid(chan, s1, NULL, s1);
07536 ast_copy_string(exten, s2, sizeof(exten));
07537 } else
07538 ast_copy_string(exten, s1, sizeof(exten));
07539 } else if (p->sig == SIG_FEATD)
07540 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07541 }
07542 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07543 if (exten[0] == '*') {
07544 char *stringp=NULL;
07545 ast_copy_string(exten2, exten, sizeof(exten2));
07546
07547 stringp=exten2 +1;
07548 s1 = strsep(&stringp, "#");
07549 s2 = strsep(&stringp, "#");
07550 if (s2) {
07551 if (!ast_strlen_zero(p->cid_num))
07552 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07553 else
07554 if (*(s1 + 2))
07555 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07556 ast_copy_string(exten, s2 + 1, sizeof(exten));
07557 } else
07558 ast_copy_string(exten, s1 + 2, sizeof(exten));
07559 } else
07560 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07561 }
07562 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07563 if (exten[0] == '*') {
07564 char *stringp=NULL;
07565 ast_copy_string(exten2, exten, sizeof(exten2));
07566
07567 stringp=exten2 +1;
07568 s1 = strsep(&stringp, "#");
07569 s2 = strsep(&stringp, "#");
07570 if (s2 && (*(s2 + 1) == '0')) {
07571 if (*(s2 + 2))
07572 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07573 }
07574 if (s1) ast_copy_string(exten, s1, sizeof(exten));
07575 else ast_copy_string(exten, "911", sizeof(exten));
07576 } else
07577 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
07578 }
07579 if (p->sig == SIG_FEATB) {
07580 if (exten[0] == '*') {
07581 char *stringp=NULL;
07582 ast_copy_string(exten2, exten, sizeof(exten2));
07583
07584 stringp=exten2 +1;
07585 s1 = strsep(&stringp, "#");
07586 ast_copy_string(exten, exten2 + 1, sizeof(exten));
07587 } else
07588 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
07589 }
07590 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07591 dahdi_wink(p, index);
07592
07593
07594
07595 if (ast_safe_sleep(chan, 100)) {
07596 ast_hangup(chan);
07597 goto quit;
07598 }
07599 }
07600 dahdi_enable_ec(p);
07601 if (NEED_MFDETECT(p)) {
07602 if (p->dsp) {
07603 if (!p->hardwaredtmf)
07604 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07605 else {
07606 ast_dsp_free(p->dsp);
07607 p->dsp = NULL;
07608 }
07609 }
07610 }
07611
07612 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07613 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07614 if (p->dsp) ast_dsp_digitreset(p->dsp);
07615 res = ast_pbx_run(chan);
07616 if (res) {
07617 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07618 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07619 }
07620 goto quit;
07621 } else {
07622 if (option_verbose > 2)
07623 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07624 sleep(2);
07625 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07626 if (res < 0)
07627 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07628 else
07629 sleep(1);
07630 res = ast_streamfile(chan, "ss-noservice", chan->language);
07631 if (res >= 0)
07632 ast_waitstream(chan, "");
07633 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07634 ast_hangup(chan);
07635 goto quit;
07636 }
07637 break;
07638 case SIG_FXOLS:
07639 case SIG_FXOGS:
07640 case SIG_FXOKS:
07641
07642 timeout = firstdigittimeout;
07643
07644
07645 if (p->subs[SUB_THREEWAY].owner)
07646 timeout = 999999;
07647 while (len < AST_MAX_EXTENSION-1) {
07648
07649
07650 if (p->immediate)
07651 res = 's';
07652 else
07653 res = ast_waitfordigit(chan, timeout);
07654 timeout = 0;
07655 if (res < 0) {
07656 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07657 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07658 ast_hangup(chan);
07659 goto quit;
07660 } else if (res) {
07661 exten[len++]=res;
07662 exten[len] = '\0';
07663 }
07664 if (!ast_ignore_pattern(chan->context, exten))
07665 tone_zone_play_tone(p->subs[index].dfd, -1);
07666 else
07667 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07668 if (!strcmp(exten,ast_pickup_ext())) {
07669
07670
07671
07672
07673 if (index == SUB_REAL) {
07674
07675 if (p->subs[SUB_THREEWAY].owner) {
07676
07677
07678 alloc_sub(p, SUB_CALLWAIT);
07679 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07680 unalloc_sub(p, SUB_THREEWAY);
07681 }
07682 dahdi_enable_ec(p);
07683 if (ast_pickup_call(chan)) {
07684 ast_log(LOG_DEBUG, "No call pickup possible...\n");
07685 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07686 dahdi_wait_event(p->subs[index].dfd);
07687 }
07688 ast_hangup(chan);
07689 goto quit;
07690 } else {
07691 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07692 ast_hangup(chan);
07693 goto quit;
07694 }
07695
07696 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07697 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07698 if (getforward) {
07699
07700 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
07701 if (option_verbose > 2)
07702 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07703 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07704 if (res)
07705 break;
07706 usleep(500000);
07707 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07708 sleep(1);
07709 memset(exten, 0, sizeof(exten));
07710 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07711 len = 0;
07712 getforward = 0;
07713 } else {
07714 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07715 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07716 if (!ast_strlen_zero(p->cid_num)) {
07717 if (!p->hidecallerid)
07718 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07719 else
07720 ast_set_callerid(chan, NULL, NULL, p->cid_num);
07721 }
07722 if (!ast_strlen_zero(p->cid_name)) {
07723 if (!p->hidecallerid)
07724 ast_set_callerid(chan, NULL, p->cid_name, NULL);
07725 }
07726 ast_setstate(chan, AST_STATE_RING);
07727 dahdi_enable_ec(p);
07728 res = ast_pbx_run(chan);
07729 if (res) {
07730 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07731 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07732 }
07733 goto quit;
07734 }
07735 } else {
07736
07737
07738 timeout = matchdigittimeout;
07739 }
07740 } else if (res == 0) {
07741 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07742 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07743 dahdi_wait_event(p->subs[index].dfd);
07744 ast_hangup(chan);
07745 goto quit;
07746 } else if (p->callwaiting && !strcmp(exten, "*70")) {
07747 if (option_verbose > 2)
07748 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07749
07750 p->callwaiting = 0;
07751 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07752 if (res) {
07753 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07754 chan->name, strerror(errno));
07755 }
07756 len = 0;
07757 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07758 memset(exten, 0, sizeof(exten));
07759 timeout = firstdigittimeout;
07760
07761 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07762 if (option_verbose > 2)
07763 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07764
07765 p->hidecallerid = 1;
07766 if (chan->cid.cid_num)
07767 free(chan->cid.cid_num);
07768 chan->cid.cid_num = NULL;
07769 if (chan->cid.cid_name)
07770 free(chan->cid.cid_name);
07771 chan->cid.cid_name = NULL;
07772 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07773 if (res) {
07774 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07775 chan->name, strerror(errno));
07776 }
07777 len = 0;
07778 memset(exten, 0, sizeof(exten));
07779 timeout = firstdigittimeout;
07780 } else if (p->callreturn && !strcmp(exten, "*69")) {
07781 res = 0;
07782 if (!ast_strlen_zero(p->lastcid_num)) {
07783 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07784 }
07785 if (!res)
07786 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07787 break;
07788 } else if (!strcmp(exten, "*78")) {
07789
07790 if (option_verbose > 2)
07791 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07792 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07793 "Channel: %s/%d\r\n"
07794 "Status: enabled\r\n", dahdi_chan_name, p->channel);
07795 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07796 p->dnd = 1;
07797 getforward = 0;
07798 memset(exten, 0, sizeof(exten));
07799 len = 0;
07800 } else if (!strcmp(exten, "*79")) {
07801
07802 if (option_verbose > 2)
07803 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07804 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07805 "Channel: %s/%d\r\n"
07806 "Status: disabled\r\n", dahdi_chan_name, p->channel);
07807 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07808 p->dnd = 0;
07809 getforward = 0;
07810 memset(exten, 0, sizeof(exten));
07811 len = 0;
07812 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07813 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07814 getforward = 1;
07815 memset(exten, 0, sizeof(exten));
07816 len = 0;
07817 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07818 if (option_verbose > 2)
07819 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07820 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07821 memset(p->call_forward, 0, sizeof(p->call_forward));
07822 getforward = 0;
07823 memset(exten, 0, sizeof(exten));
07824 len = 0;
07825 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07826 p->subs[SUB_THREEWAY].owner &&
07827 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07828
07829
07830 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07831 if (option_verbose > 2)
07832 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07833 break;
07834 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07835 if (option_verbose > 2)
07836 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07837 res = ast_db_put("blacklist", p->lastcid_num, "1");
07838 if (!res) {
07839 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07840 memset(exten, 0, sizeof(exten));
07841 len = 0;
07842 }
07843 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07844 if (option_verbose > 2)
07845 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07846
07847 p->hidecallerid = 0;
07848 if (chan->cid.cid_num)
07849 free(chan->cid.cid_num);
07850 chan->cid.cid_num = NULL;
07851 if (chan->cid.cid_name)
07852 free(chan->cid.cid_name);
07853 chan->cid.cid_name = NULL;
07854 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07855 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07856 if (res) {
07857 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07858 chan->name, strerror(errno));
07859 }
07860 len = 0;
07861 memset(exten, 0, sizeof(exten));
07862 timeout = firstdigittimeout;
07863 } else if (!strcmp(exten, "*0")) {
07864 struct ast_channel *nbridge =
07865 p->subs[SUB_THREEWAY].owner;
07866 struct dahdi_pvt *pbridge = NULL;
07867
07868 if (nbridge && ast_bridged_channel(nbridge))
07869 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07870 if (nbridge && pbridge &&
07871 (nbridge->tech == chan_tech) &&
07872 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07873 ISTRUNK(pbridge)) {
07874 int func = DAHDI_FLASH;
07875
07876 p->dop.dialstr[0] = '\0';
07877
07878 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07879 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07880 nbridge->name, strerror(errno));
07881 }
07882 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07883 unalloc_sub(p, SUB_THREEWAY);
07884 p->owner = p->subs[SUB_REAL].owner;
07885 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07886 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07887 ast_hangup(chan);
07888 goto quit;
07889 } else {
07890 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07891 dahdi_wait_event(p->subs[index].dfd);
07892 tone_zone_play_tone(p->subs[index].dfd, -1);
07893 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07894 unalloc_sub(p, SUB_THREEWAY);
07895 p->owner = p->subs[SUB_REAL].owner;
07896 ast_hangup(chan);
07897 goto quit;
07898 }
07899 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07900 ((exten[0] != '*') || (strlen(exten) > 2))) {
07901 if (option_debug)
07902 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);
07903 break;
07904 }
07905 if (!timeout)
07906 timeout = gendigittimeout;
07907 if (len && !ast_ignore_pattern(chan->context, exten))
07908 tone_zone_play_tone(p->subs[index].dfd, -1);
07909 }
07910 break;
07911 case SIG_FXSLS:
07912 case SIG_FXSGS:
07913 case SIG_FXSKS:
07914 #ifdef HAVE_PRI
07915 if (p->pri) {
07916
07917 struct ast_frame *f;
07918 int res;
07919 time_t start;
07920
07921 time(&start);
07922 ast_setstate(chan, AST_STATE_RING);
07923 while (time(NULL) < start + 3) {
07924 res = ast_waitfor(chan, 1000);
07925 if (res) {
07926 f = ast_read(chan);
07927 if (!f) {
07928 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07929 ast_hangup(chan);
07930 goto quit;
07931 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07932 res = 1;
07933 } else
07934 res = 0;
07935 ast_frfree(f);
07936 if (res) {
07937 ast_log(LOG_DEBUG, "Got ring!\n");
07938 res = 0;
07939 break;
07940 }
07941 }
07942 }
07943 }
07944 #endif
07945
07946 if (p->use_smdi && p->smdi_iface) {
07947 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07948
07949 if (smdi_msg != NULL) {
07950 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07951
07952 if (smdi_msg->type == 'B')
07953 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07954 else if (smdi_msg->type == 'N')
07955 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07956
07957 ast_log(LOG_DEBUG, "Received SMDI message on %s\n", chan->name);
07958 } else {
07959 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07960 }
07961 }
07962
07963 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07964 number = smdi_msg->calling_st;
07965
07966
07967
07968
07969 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
07970 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
07971
07972 if (p->cid_signalling == CID_SIG_DTMF) {
07973 int i = 0;
07974 cs = NULL;
07975 ast_log(LOG_DEBUG, "Receiving DTMF cid on channel %s\n", chan->name);
07976 dahdi_setlinear(p->subs[index].dfd, 0);
07977
07978
07979
07980
07981
07982
07983 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
07984 res = 4000;
07985 for (;;) {
07986 struct ast_frame *f;
07987 res = ast_waitfor(chan, res);
07988 if (res <= 0) {
07989
07990
07991
07992
07993
07994 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07995 "Exiting simple switch\n");
07996 ast_hangup(chan);
07997 goto quit;
07998 }
07999 f = ast_read(chan);
08000 if (!f)
08001 break;
08002 if (f->frametype == AST_FRAME_DTMF) {
08003 if (i < ARRAY_LEN(dtmfbuf) - 1) {
08004 dtmfbuf[i++] = f->subclass;
08005 }
08006 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
08007 res = 4000;
08008 }
08009 ast_frfree(f);
08010 if (chan->_state == AST_STATE_RING ||
08011 chan->_state == AST_STATE_RINGING)
08012 break;
08013 }
08014 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08015 dtmfbuf[i] = '\0';
08016 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
08017
08018 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
08019 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08020 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", dtmfcid, flags);
08021
08022 if (!ast_strlen_zero(dtmfcid))
08023 number = dtmfcid;
08024 else
08025 number = NULL;
08026
08027 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08028 cs = callerid_new(p->cid_signalling);
08029 if (cs) {
08030 samples = 0;
08031 #if 1
08032 bump_gains(p);
08033 #endif
08034
08035 dahdi_setlinear(p->subs[index].dfd, 0);
08036
08037
08038 for (;;) {
08039 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08040 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
08041 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08042 callerid_free(cs);
08043 ast_hangup(chan);
08044 goto quit;
08045 }
08046 if (i & DAHDI_IOMUX_SIGEVENT) {
08047 res = dahdi_get_event(p->subs[index].dfd);
08048 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08049 if (res == DAHDI_EVENT_NOALARM) {
08050 p->inalarm = 0;
08051 }
08052
08053 if (p->cid_signalling == CID_SIG_V23_JP) {
08054 #ifdef DAHDI_EVENT_RINGBEGIN
08055 if (res == DAHDI_EVENT_RINGBEGIN) {
08056 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08057 usleep(1);
08058 }
08059 #endif
08060 } else {
08061 res = 0;
08062 break;
08063 }
08064 } else if (i & DAHDI_IOMUX_READ) {
08065 res = read(p->subs[index].dfd, buf, sizeof(buf));
08066 if (res < 0) {
08067 if (errno != ELAST) {
08068 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08069 callerid_free(cs);
08070 ast_hangup(chan);
08071 goto quit;
08072 }
08073 break;
08074 }
08075 samples += res;
08076
08077 if (p->cid_signalling == CID_SIG_V23_JP) {
08078 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08079 } else {
08080 res = callerid_feed(cs, buf, res, AST_LAW(p));
08081 }
08082 if (res < 0) {
08083
08084
08085
08086
08087 ast_log(LOG_WARNING,
08088 "Failed to decode CallerID on channel '%s'\n",
08089 chan->name);
08090 break;
08091 } else if (res)
08092 break;
08093 else if (samples > (8000 * 10))
08094 break;
08095 }
08096 }
08097 if (res == 1) {
08098 callerid_get(cs, &name, &number, &flags);
08099 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08100 }
08101
08102 if (p->cid_signalling == CID_SIG_V23_JP) {
08103 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08104 usleep(1);
08105 }
08106
08107
08108 res = 4000;
08109 for (;;) {
08110 struct ast_frame *f;
08111 res = ast_waitfor(chan, res);
08112 if (res <= 0) {
08113 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08114 "Exiting simple switch\n");
08115 ast_hangup(chan);
08116 goto quit;
08117 }
08118 if (!(f = ast_read(chan))) {
08119 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08120 ast_hangup(chan);
08121 goto quit;
08122 }
08123 ast_frfree(f);
08124 if (chan->_state == AST_STATE_RING ||
08125 chan->_state == AST_STATE_RINGING)
08126 break;
08127 }
08128
08129
08130
08131 if (p->usedistinctiveringdetection) {
08132 len = 0;
08133 distMatches = 0;
08134
08135 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
08136 curRingData[receivedRingT] = 0;
08137 receivedRingT = 0;
08138 counter = 0;
08139 counter1 = 0;
08140
08141 if (strcmp(p->context,p->defcontext) != 0) {
08142 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08143 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08144 }
08145
08146 for (;;) {
08147 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08148 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
08149 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08150 callerid_free(cs);
08151 ast_hangup(chan);
08152 goto quit;
08153 }
08154 if (i & DAHDI_IOMUX_SIGEVENT) {
08155 res = dahdi_get_event(p->subs[index].dfd);
08156 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08157 if (res == DAHDI_EVENT_NOALARM) {
08158 p->inalarm = 0;
08159 }
08160 res = 0;
08161
08162
08163 curRingData[receivedRingT] = p->ringt;
08164
08165 if (p->ringt < p->ringt_base/2)
08166 break;
08167
08168
08169 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
08170 break;
08171 } else if (i & DAHDI_IOMUX_READ) {
08172 res = read(p->subs[index].dfd, buf, sizeof(buf));
08173 if (res < 0) {
08174 if (errno != ELAST) {
08175 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08176 callerid_free(cs);
08177 ast_hangup(chan);
08178 goto quit;
08179 }
08180 break;
08181 }
08182 if (p->ringt)
08183 p->ringt--;
08184 if (p->ringt == 1) {
08185 res = -1;
08186 break;
08187 }
08188 }
08189 }
08190 if (option_verbose > 2)
08191
08192 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08193
08194 for (counter = 0; counter < 3; counter++) {
08195
08196
08197 distMatches = 0;
08198 for (counter1 = 0; counter1 < 3; counter1++) {
08199 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
08200 (p->drings.ringnum[counter].ring[counter1]-10)) {
08201 distMatches++;
08202 }
08203 }
08204 if (distMatches == 3) {
08205
08206 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08207 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08208 if (option_verbose > 2)
08209 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
08210 break;
08211 }
08212 }
08213 }
08214
08215 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
08216 #if 1
08217 restore_gains(p);
08218 #endif
08219 } else
08220 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08221 } else {
08222 ast_log(LOG_WARNING, "Channel %s in prering "
08223 "state, but I have nothing to do. "
08224 "Terminating simple switch, should be "
08225 "restarted by the actual ring.\n",
08226 chan->name);
08227 ast_hangup(chan);
08228 goto quit;
08229 }
08230 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
08231
08232 cs = callerid_new(p->cid_signalling);
08233 if (cs) {
08234 #if 1
08235 bump_gains(p);
08236 #endif
08237 samples = 0;
08238 len = 0;
08239 distMatches = 0;
08240
08241 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
08242 curRingData[receivedRingT] = 0;
08243 receivedRingT = 0;
08244 counter = 0;
08245 counter1 = 0;
08246
08247 if (strcmp(p->context,p->defcontext) != 0) {
08248 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08249 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08250 }
08251
08252
08253 dahdi_setlinear(p->subs[index].dfd, 0);
08254 for (;;) {
08255 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08256 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
08257 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08258 callerid_free(cs);
08259 ast_hangup(chan);
08260 goto quit;
08261 }
08262 if (i & DAHDI_IOMUX_SIGEVENT) {
08263 res = dahdi_get_event(p->subs[index].dfd);
08264 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08265 if (res == DAHDI_EVENT_NOALARM) {
08266 p->inalarm = 0;
08267 }
08268
08269 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
08270 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
08271 p->polarity = POLARITY_IDLE;
08272 callerid_free(cs);
08273 ast_hangup(chan);
08274 goto quit;
08275 }
08276 res = 0;
08277
08278
08279 curRingData[receivedRingT] = p->ringt;
08280
08281 if (p->ringt < p->ringt_base/2)
08282 break;
08283
08284
08285 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
08286 break;
08287 } else if (i & DAHDI_IOMUX_READ) {
08288 res = read(p->subs[index].dfd, buf, sizeof(buf));
08289 if (res < 0) {
08290 if (errno != ELAST) {
08291 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08292 callerid_free(cs);
08293 ast_hangup(chan);
08294 goto quit;
08295 }
08296 break;
08297 }
08298 if (p->ringt)
08299 p->ringt--;
08300 if (p->ringt == 1) {
08301 res = -1;
08302 break;
08303 }
08304 samples += res;
08305 res = callerid_feed(cs, buf, res, AST_LAW(p));
08306 if (res < 0) {
08307
08308
08309
08310
08311 ast_log(LOG_WARNING,
08312 "Failed to decode CallerID on channel '%s'\n",
08313 chan->name);
08314 break;
08315 } else if (res)
08316 break;
08317 else if (samples > (8000 * 10))
08318 break;
08319 }
08320 }
08321 if (res == 1) {
08322 callerid_get(cs, &name, &number, &flags);
08323 if (option_debug)
08324 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08325 }
08326 if (distinctiveringaftercid == 1) {
08327
08328 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
08329 curRingData[receivedRingT] = 0;
08330 }
08331 receivedRingT = 0;
08332 if (option_verbose > 2)
08333 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
08334 for (;;) {
08335 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08336 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
08337 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08338 callerid_free(cs);
08339 ast_hangup(chan);
08340 goto quit;
08341 }
08342 if (i & DAHDI_IOMUX_SIGEVENT) {
08343 res = dahdi_get_event(p->subs[index].dfd);
08344 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08345 if (res == DAHDI_EVENT_NOALARM) {
08346 p->inalarm = 0;
08347 }
08348 res = 0;
08349
08350
08351 curRingData[receivedRingT] = p->ringt;
08352
08353 if (p->ringt < p->ringt_base/2)
08354 break;
08355
08356
08357 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
08358 break;
08359 } else if (i & DAHDI_IOMUX_READ) {
08360 res = read(p->subs[index].dfd, buf, sizeof(buf));
08361 if (res < 0) {
08362 if (errno != ELAST) {
08363 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08364 callerid_free(cs);
08365 ast_hangup(chan);
08366 goto quit;
08367 }
08368 break;
08369 }
08370 if (p->ringt)
08371 p->ringt--;
08372 if (p->ringt == 1) {
08373 res = -1;
08374 break;
08375 }
08376 }
08377 }
08378 }
08379 if (p->usedistinctiveringdetection) {
08380 if (option_verbose > 2)
08381
08382 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08383
08384 for (counter = 0; counter < 3; counter++) {
08385
08386
08387 if (option_verbose > 2)
08388
08389 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
08390 p->drings.ringnum[counter].ring[0],
08391 p->drings.ringnum[counter].ring[1],
08392 p->drings.ringnum[counter].ring[2]);
08393 distMatches = 0;
08394 for (counter1 = 0; counter1 < 3; counter1++) {
08395 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
08396 (p->drings.ringnum[counter].ring[counter1]-10)) {
08397 distMatches++;
08398 }
08399 }
08400 if (distMatches == 3) {
08401
08402 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08403 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08404 if (option_verbose > 2)
08405 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
08406 break;
08407 }
08408 }
08409 }
08410
08411 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
08412 #if 1
08413 restore_gains(p);
08414 #endif
08415 if (res < 0) {
08416 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
08417 }
08418 } else
08419 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08420 }
08421 else
08422 cs = NULL;
08423
08424 if (number)
08425 ast_shrink_phone_number(number);
08426 ast_set_callerid(chan, number, name, number);
08427
08428 if (smdi_msg)
08429 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
08430
08431 if (cs)
08432 callerid_free(cs);
08433
08434 ast_setstate(chan, AST_STATE_RING);
08435 chan->rings = 1;
08436 p->ringt = p->ringt_base;
08437 res = ast_pbx_run(chan);
08438 if (res) {
08439 ast_hangup(chan);
08440 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08441 }
08442 goto quit;
08443 default:
08444 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
08445 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
08446 if (res < 0)
08447 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08448 }
08449 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
08450 if (res < 0)
08451 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08452 ast_hangup(chan);
08453 quit:
08454 ast_mutex_lock(&ss_thread_lock);
08455 ss_thread_count--;
08456 ast_cond_signal(&ss_thread_complete);
08457 ast_mutex_unlock(&ss_thread_lock);
08458 return NULL;
08459 }
08460
08461 static int calc_energy(const unsigned char *buf, int len, int law)
08462 {
08463 int x;
08464 int sum = 0;
08465 int ssum = 0, mean = 0;
08466
08467 if (!len)
08468 return 0;
08469
08470
08471 for (x = 0; x < len; x++)
08472 ssum += (law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
08473
08474 mean = ssum / len;
08475
08476 for (x = 0; x < len; x++) {
08477 sum += abs((law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])) - mean);
08478 if (option_verbose > 7)
08479 ast_log(LOG_WARNING, "x %i, bufx: %i sum %i, ssum %i\n", x, buf[x], sum, ssum);
08480 }
08481
08482 if (option_verbose > 5)
08483 ast_log(LOG_WARNING, "mean %i, energy %i\n", mean, sum/len);
08484
08485 return sum / len;
08486 }
08487
08488
08489 static int dahdi_destroy_channel_bynum(int channel)
08490 {
08491 struct dahdi_pvt *tmp = NULL;
08492 struct dahdi_pvt *prev = NULL;
08493
08494 ast_mutex_lock(&iflock);
08495 tmp = iflist;
08496 while (tmp) {
08497 if (tmp->channel == channel) {
08498 int x = DAHDI_FLASH;
08499 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08500 destroy_channel(prev, tmp, 1);
08501 ast_mutex_unlock(&iflock);
08502 ast_module_unref(ast_module_info->self);
08503 return RESULT_SUCCESS;
08504 }
08505 prev = tmp;
08506 tmp = tmp->next;
08507 }
08508 ast_mutex_unlock(&iflock);
08509 return RESULT_FAILURE;
08510 }
08511
08512 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
08513 {
08514 int res;
08515 pthread_t threadid;
08516 pthread_attr_t attr;
08517 struct ast_channel *chan;
08518 pthread_attr_init(&attr);
08519 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08520
08521 switch (event) {
08522 case DAHDI_EVENT_NONE:
08523 case DAHDI_EVENT_BITSCHANGED:
08524 break;
08525 case DAHDI_EVENT_WINKFLASH:
08526 case DAHDI_EVENT_RINGOFFHOOK:
08527 if (i->inalarm) break;
08528 if (i->radio) break;
08529
08530 switch (i->sig) {
08531 case SIG_FXOLS:
08532 case SIG_FXOGS:
08533 case SIG_FXOKS:
08534 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08535 if (res && (errno == EBUSY))
08536 break;
08537
08538
08539 free(i->cidspill);
08540 i->cidspill = NULL;
08541 restore_conference(i);
08542
08543 if (i->immediate) {
08544 dahdi_enable_ec(i);
08545
08546 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08547 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08548 if (!chan) {
08549 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08550 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08551 if (res < 0)
08552 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08553 }
08554 } else {
08555
08556 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08557 if (chan) {
08558 if (has_voicemail(i))
08559 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08560 else
08561 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08562 if (res < 0)
08563 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08564 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08565 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08566 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08567 if (res < 0)
08568 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08569 ast_hangup(chan);
08570 }
08571 } else
08572 ast_log(LOG_WARNING, "Unable to create channel\n");
08573 }
08574 break;
08575 case SIG_FXSLS:
08576 case SIG_FXSGS:
08577 case SIG_FXSKS:
08578 i->ringt = i->ringt_base;
08579
08580 case SIG_EMWINK:
08581 case SIG_FEATD:
08582 case SIG_FEATDMF:
08583 case SIG_FEATDMF_TA:
08584 case SIG_E911:
08585 case SIG_FGC_CAMA:
08586 case SIG_FGC_CAMAMF:
08587 case SIG_FEATB:
08588 case SIG_EM:
08589 case SIG_EM_E1:
08590 case SIG_SFWINK:
08591 case SIG_SF_FEATD:
08592 case SIG_SF_FEATDMF:
08593 case SIG_SF_FEATB:
08594 case SIG_SF:
08595
08596 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08597 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08598 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08599 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08600 if (res < 0)
08601 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08602 ast_hangup(chan);
08603 } else if (!chan) {
08604 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08605 }
08606 break;
08607 default:
08608 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08609 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08610 if (res < 0)
08611 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08612 pthread_attr_destroy(&attr);
08613 return NULL;
08614 }
08615 break;
08616 case DAHDI_EVENT_NOALARM:
08617 i->inalarm = 0;
08618 #if defined(HAVE_PRI)
08619 i->resetting = 0;
08620 #endif
08621 if (!i->unknown_alarm) {
08622 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08623 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08624 "Channel: %d\r\n", i->channel);
08625 } else {
08626 i->unknown_alarm = 0;
08627 }
08628 break;
08629 case DAHDI_EVENT_ALARM:
08630 i->inalarm = 1;
08631 #if defined(HAVE_PRI)
08632 i->resetting = 0;
08633 #endif
08634 res = get_alarms(i);
08635 handle_alarms(i, res);
08636
08637 case DAHDI_EVENT_ONHOOK:
08638 if (i->radio)
08639 break;
08640
08641 switch (i->sig) {
08642 case SIG_FXOLS:
08643 case SIG_FXOGS:
08644 case SIG_FEATD:
08645 case SIG_FEATDMF:
08646 case SIG_FEATDMF_TA:
08647 case SIG_E911:
08648 case SIG_FGC_CAMA:
08649 case SIG_FGC_CAMAMF:
08650 case SIG_FEATB:
08651 case SIG_EM:
08652 case SIG_EM_E1:
08653 case SIG_EMWINK:
08654 case SIG_SF_FEATD:
08655 case SIG_SF_FEATDMF:
08656 case SIG_SF_FEATB:
08657 case SIG_SF:
08658 case SIG_SFWINK:
08659 case SIG_FXSLS:
08660 case SIG_FXSGS:
08661 case SIG_FXSKS:
08662 case SIG_GR303FXSKS:
08663 dahdi_disable_ec(i);
08664 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08665 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08666 break;
08667 case SIG_GR303FXOKS:
08668 case SIG_FXOKS:
08669 dahdi_disable_ec(i);
08670
08671 #ifdef ZHONE_HACK
08672 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08673 usleep(1);
08674 #endif
08675 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08676 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08677 break;
08678 case SIG_PRI:
08679 dahdi_disable_ec(i);
08680 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08681 break;
08682 default:
08683 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08684 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08685 pthread_attr_destroy(&attr);
08686 return NULL;
08687 }
08688 break;
08689 case DAHDI_EVENT_POLARITY:
08690 switch (i->sig) {
08691 case SIG_FXSLS:
08692 case SIG_FXSKS:
08693 case SIG_FXSGS:
08694
08695
08696
08697
08698 if (i->hanguponpolarityswitch)
08699 i->polarity = POLARITY_REV;
08700
08701 if (i->cid_start == CID_START_POLARITY) {
08702 i->polarity = POLARITY_REV;
08703 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08704 "CID detection on channel %d\n",
08705 i->channel);
08706 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08707 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08708 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08709 }
08710 }
08711 break;
08712 default:
08713 ast_log(LOG_WARNING, "handle_init_event detected "
08714 "polarity reversal on non-FXO (SIG_FXS) "
08715 "interface %d\n", i->channel);
08716 }
08717 break;
08718 case DAHDI_EVENT_REMOVED:
08719 ast_log(LOG_NOTICE,
08720 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08721 i->channel);
08722 pthread_attr_destroy(&attr);
08723 return i;
08724 }
08725 pthread_attr_destroy(&attr);
08726 return NULL;
08727 }
08728
08729 static void *do_monitor(void *data)
08730 {
08731 int count, res, res2, spoint, pollres=0;
08732 struct dahdi_pvt *i;
08733 struct dahdi_pvt *last = NULL;
08734 struct dahdi_pvt *doomed;
08735 time_t thispass = 0, lastpass = 0;
08736 int found;
08737 char buf[1024];
08738 struct pollfd *pfds=NULL;
08739 int lastalloc = -1;
08740
08741
08742
08743 #if 0
08744 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08745 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08746 return NULL;
08747 }
08748 ast_log(LOG_DEBUG, "Monitor starting...\n");
08749 #endif
08750 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08751
08752 for (;;) {
08753
08754 ast_mutex_lock(&iflock);
08755 if (!pfds || (lastalloc != ifcount)) {
08756 if (pfds) {
08757 free(pfds);
08758 pfds = NULL;
08759 }
08760 if (ifcount) {
08761 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08762 ast_mutex_unlock(&iflock);
08763 return NULL;
08764 }
08765 }
08766 lastalloc = ifcount;
08767 }
08768
08769
08770 count = 0;
08771 i = iflist;
08772 while (i) {
08773 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08774 if (!i->owner && !i->subs[SUB_REAL].owner) {
08775
08776 pfds[count].fd = i->subs[SUB_REAL].dfd;
08777 pfds[count].events = POLLPRI;
08778 pfds[count].revents = 0;
08779
08780 if (i->cidspill ||
08781 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
08782 pfds[count].events |= POLLIN;
08783 }
08784 count++;
08785 }
08786 }
08787 i = i->next;
08788 }
08789
08790 ast_mutex_unlock(&iflock);
08791
08792 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08793 pthread_testcancel();
08794
08795 res = poll(pfds, count, 1000);
08796 pthread_testcancel();
08797 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08798
08799
08800 if (res < 0) {
08801 if ((errno != EAGAIN) && (errno != EINTR))
08802 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08803 continue;
08804 }
08805
08806
08807 ast_mutex_lock(&iflock);
08808 found = 0;
08809 spoint = 0;
08810 lastpass = thispass;
08811 thispass = time(NULL);
08812 doomed = NULL;
08813 for (i = iflist;; i = i->next) {
08814 if (doomed) {
08815 int res;
08816 res = dahdi_destroy_channel_bynum(doomed->channel);
08817 if (!res) {
08818 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08819 }
08820 doomed = NULL;
08821 }
08822 if (!i) {
08823 break;
08824 }
08825 if (thispass != lastpass) {
08826 if (!found && ((i == last) || ((i == iflist) && !last))) {
08827 last = i;
08828 if (last) {
08829 if (!last->cidspill
08830 && !last->owner
08831 && !ast_strlen_zero(last->mailbox)
08832 && (thispass - last->onhooktime > 3)
08833 && (last->sig & __DAHDI_SIG_FXO)) {
08834 res = ast_app_has_voicemail(last->mailbox, NULL);
08835 if (last->msgstate != res) {
08836 int x;
08837 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08838 x = DAHDI_FLUSH_BOTH;
08839 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08840 if (res2)
08841 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08842 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08843
08844 x = 4000;
08845 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08846 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08847 last->cidpos = 0;
08848 last->msgstate = res;
08849 last->onhooktime = thispass;
08850 }
08851 found ++;
08852 }
08853 }
08854 last = last->next;
08855 }
08856 }
08857 }
08858 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08859 if (i->radio && !i->owner)
08860 {
08861 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08862 if (res)
08863 {
08864 if (option_debug)
08865 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08866
08867 ast_mutex_unlock(&iflock);
08868 doomed = handle_init_event(i, res);
08869 ast_mutex_lock(&iflock);
08870 }
08871 continue;
08872 }
08873 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08874 if (pollres & POLLIN) {
08875 if (i->owner || i->subs[SUB_REAL].owner) {
08876 #ifdef HAVE_PRI
08877 if (!i->pri)
08878 #endif
08879 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08880 continue;
08881 }
08882 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08883 if (res > 0) {
08884
08885
08886 if (i->cid_start == CID_START_DTMF_NOALERT) {
08887 int energy;
08888 struct timeval now;
08889
08890
08891
08892 if (1 == i->dtmfcid_holdoff_state) {
08893 gettimeofday(&i->dtmfcid_delay, NULL);
08894 i->dtmfcid_holdoff_state = 2;
08895 } else if (2 == i->dtmfcid_holdoff_state) {
08896 gettimeofday(&now, NULL);
08897 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
08898 i->dtmfcid_holdoff_state = 0;
08899 }
08900 } else {
08901 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
08902 if (energy > dtmfcid_level) {
08903 pthread_t threadid;
08904 struct ast_channel *chan;
08905 ast_mutex_unlock(&iflock);
08906 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08907 if (!chan) {
08908 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08909 } else {
08910 pthread_attr_t attr;
08911 pthread_attr_init(&attr);
08912 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08913 res = ast_pthread_create(&threadid, &attr, ss_thread, chan);
08914 if (res) {
08915 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08916 } else {
08917 i->dtmfcid_holdoff_state = 1;
08918 }
08919 }
08920 ast_mutex_lock(&iflock);
08921 }
08922 }
08923 }
08924 } else {
08925 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08926 }
08927 }
08928 if (pollres & POLLPRI) {
08929 if (i->owner || i->subs[SUB_REAL].owner) {
08930 #ifdef HAVE_PRI
08931 if (!i->pri)
08932 #endif
08933 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08934 continue;
08935 }
08936 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08937 if (option_debug)
08938 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08939
08940 ast_mutex_unlock(&iflock);
08941 doomed = handle_init_event(i, res);
08942 ast_mutex_lock(&iflock);
08943 }
08944 }
08945 }
08946 ast_mutex_unlock(&iflock);
08947 }
08948
08949 return NULL;
08950
08951 }
08952
08953 static int restart_monitor(void)
08954 {
08955 pthread_attr_t attr;
08956 pthread_attr_init(&attr);
08957 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08958
08959 if (monitor_thread == AST_PTHREADT_STOP)
08960 return 0;
08961 ast_mutex_lock(&monlock);
08962 if (monitor_thread == pthread_self()) {
08963 ast_mutex_unlock(&monlock);
08964 ast_log(LOG_WARNING, "Cannot kill myself\n");
08965 return -1;
08966 }
08967 if (monitor_thread != AST_PTHREADT_NULL) {
08968
08969 pthread_kill(monitor_thread, SIGURG);
08970 } else {
08971
08972 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08973 ast_mutex_unlock(&monlock);
08974 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08975 pthread_attr_destroy(&attr);
08976 return -1;
08977 }
08978 }
08979 ast_mutex_unlock(&monlock);
08980 pthread_attr_destroy(&attr);
08981 return 0;
08982 }
08983
08984 #ifdef HAVE_OPENR2
08985 static struct dahdi_mfcr2 *mfcr2_get_context(int id)
08986 {
08987 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08988 ast_log(LOG_ERROR, "No more R2 links available!.\n");
08989 return NULL;
08990 }
08991 return &r2links[id];
08992 }
08993 #endif
08994
08995 #ifdef HAVE_PRI
08996 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08997 {
08998 int x;
08999 int trunkgroup;
09000
09001 trunkgroup = pris[*span].mastertrunkgroup;
09002 if (trunkgroup) {
09003
09004 for (x = 0; x < NUM_SPANS; x++) {
09005 if (pris[x].trunkgroup == trunkgroup) {
09006 *span = x;
09007 return 0;
09008 }
09009 }
09010 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
09011 *span = -1;
09012 } else {
09013 if (pris[*span].trunkgroup) {
09014 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
09015 *span = -1;
09016 } else if (pris[*span].mastertrunkgroup) {
09017 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
09018 *span = -1;
09019 } else {
09020 if (si->totalchans == 31) {
09021
09022 pris[*span].dchannels[0] = 16 + offset;
09023 } else if (si->totalchans == 24) {
09024
09025 pris[*span].dchannels[0] = 24 + offset;
09026 } else if (si->totalchans == 3) {
09027
09028 pris[*span].dchannels[0] = 3 + offset;
09029 } else {
09030 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);
09031 *span = -1;
09032 return 0;
09033 }
09034 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
09035 pris[*span].offset = offset;
09036 pris[*span].span = *span + 1;
09037 }
09038 }
09039 return 0;
09040 }
09041
09042 static int pri_create_trunkgroup(int trunkgroup, int *channels)
09043 {
09044 struct dahdi_spaninfo si;
09045 struct dahdi_params p;
09046 int fd;
09047 int span;
09048 int ospan=0;
09049 int x,y;
09050 for (x = 0; x < NUM_SPANS; x++) {
09051 if (pris[x].trunkgroup == trunkgroup) {
09052 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
09053 return -1;
09054 }
09055 }
09056 for (y = 0; y < NUM_DCHANS; y++) {
09057 if (!channels[y])
09058 break;
09059 memset(&si, 0, sizeof(si));
09060 memset(&p, 0, sizeof(p));
09061 fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
09062 if (fd < 0) {
09063 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
09064 return -1;
09065 }
09066 x = channels[y];
09067 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
09068 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
09069 close(fd);
09070 return -1;
09071 }
09072 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
09073 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
09074 return -1;
09075 }
09076 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
09077 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
09078 close(fd);
09079 return -1;
09080 }
09081 span = p.spanno - 1;
09082 if (pris[span].trunkgroup) {
09083 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
09084 close(fd);
09085 return -1;
09086 }
09087 if (pris[span].pvts[0]) {
09088 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
09089 close(fd);
09090 return -1;
09091 }
09092 if (!y) {
09093 pris[span].trunkgroup = trunkgroup;
09094 pris[span].offset = channels[y] - p.chanpos;
09095 ospan = span;
09096 }
09097 pris[ospan].dchannels[y] = channels[y];
09098 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
09099 pris[span].span = span + 1;
09100 close(fd);
09101 }
09102 return 0;
09103 }
09104
09105 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
09106 {
09107 if (pris[span].mastertrunkgroup) {
09108 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);
09109 return -1;
09110 }
09111 pris[span].mastertrunkgroup = trunkgroup;
09112 pris[span].prilogicalspan = logicalspan;
09113 return 0;
09114 }
09115
09116 #endif
09117
09118 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
09119 {
09120
09121 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
09122 char fn[80];
09123 #if 1
09124 struct dahdi_bufferinfo bi;
09125 #endif
09126 int res;
09127 int span=0;
09128 int here = 0;
09129 int x;
09130 struct dahdi_pvt **wlist;
09131 struct dahdi_pvt **wend;
09132 struct dahdi_params p;
09133
09134 wlist = &iflist;
09135 wend = &ifend;
09136
09137 #ifdef HAVE_PRI
09138 if (pri) {
09139 wlist = &pri->crvs;
09140 wend = &pri->crvend;
09141 }
09142 #endif
09143
09144 tmp2 = *wlist;
09145 prev = NULL;
09146
09147 while (tmp2) {
09148 if (!tmp2->destroy) {
09149 if (tmp2->channel == channel) {
09150 tmp = tmp2;
09151 here = 1;
09152 break;
09153 }
09154 if (tmp2->channel > channel) {
09155 break;
09156 }
09157 }
09158 prev = tmp2;
09159 tmp2 = tmp2->next;
09160 }
09161
09162 if (!here && reloading != 1) {
09163 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
09164 if (tmp)
09165 free(tmp);
09166 return NULL;
09167 }
09168 ast_mutex_init(&tmp->lock);
09169 ifcount++;
09170 for (x = 0; x < 3; x++)
09171 tmp->subs[x].dfd = -1;
09172 tmp->channel = channel;
09173 tmp->priindication_oob = conf->chan.priindication_oob;
09174 }
09175
09176 if (tmp) {
09177 int chan_sig = conf->chan.sig;
09178 if (!here) {
09179 if ((channel != CHAN_PSEUDO) && !pri) {
09180 int count = 0;
09181 snprintf(fn, sizeof(fn), "%d", channel);
09182
09183 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
09184 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
09185 usleep(1);
09186 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
09187 count++;
09188 }
09189
09190 if (tmp->subs[SUB_REAL].dfd < 0) {
09191 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);
09192 destroy_dahdi_pvt(&tmp);
09193 return NULL;
09194 }
09195 memset(&p, 0, sizeof(p));
09196 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
09197 if (res < 0) {
09198 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
09199 destroy_dahdi_pvt(&tmp);
09200 return NULL;
09201 }
09202 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
09203 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));
09204 destroy_dahdi_pvt(&tmp);
09205 return NULL;
09206 }
09207 tmp->law = p.curlaw;
09208 tmp->span = p.spanno;
09209 span = p.spanno - 1;
09210 } else {
09211 if (channel == CHAN_PSEUDO)
09212 chan_sig = 0;
09213 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
09214 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
09215 return NULL;
09216 }
09217 }
09218 tmp->outsigmod = conf->chan.outsigmod;
09219
09220 #ifdef HAVE_PRI
09221 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
09222 int offset;
09223 int myswitchtype;
09224 int matchesdchan;
09225 int x,y;
09226 offset = 0;
09227 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
09228 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
09229 destroy_dahdi_pvt(&tmp);
09230 return NULL;
09231 }
09232 if (span >= NUM_SPANS) {
09233 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
09234 destroy_dahdi_pvt(&tmp);
09235 return NULL;
09236 } else {
09237 struct dahdi_spaninfo si;
09238 si.spanno = 0;
09239 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
09240 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
09241 destroy_dahdi_pvt(&tmp);
09242 return NULL;
09243 }
09244
09245 tmp->logicalspan = pris[span].prilogicalspan;
09246 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
09247 if (span < 0) {
09248 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
09249 destroy_dahdi_pvt(&tmp);
09250 return NULL;
09251 }
09252 if (chan_sig == SIG_PRI)
09253 myswitchtype = conf->pri.switchtype;
09254 else
09255 myswitchtype = PRI_SWITCH_GR303_TMC;
09256
09257 matchesdchan=0;
09258 for (x = 0; x < NUM_SPANS; x++) {
09259 for (y = 0; y < NUM_DCHANS; y++) {
09260 if (pris[x].dchannels[y] == tmp->channel) {
09261 matchesdchan = 1;
09262 break;
09263 }
09264 }
09265 }
09266 offset = p.chanpos;
09267 if (!matchesdchan) {
09268 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
09269 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
09270 destroy_dahdi_pvt(&tmp);
09271 return NULL;
09272 }
09273 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
09274 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
09275 destroy_dahdi_pvt(&tmp);
09276 return NULL;
09277 }
09278 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
09279 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
09280 destroy_dahdi_pvt(&tmp);
09281 return NULL;
09282 }
09283 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
09284 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
09285 destroy_dahdi_pvt(&tmp);
09286 return NULL;
09287 }
09288 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
09289 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
09290 destroy_dahdi_pvt(&tmp);
09291 return NULL;
09292 }
09293 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
09294 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
09295 destroy_dahdi_pvt(&tmp);
09296 return NULL;
09297 }
09298 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
09299 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
09300 destroy_dahdi_pvt(&tmp);
09301 return NULL;
09302 }
09303 if (pris[span].numchans >= MAX_CHANNELS) {
09304 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
09305 pris[span].trunkgroup);
09306 destroy_dahdi_pvt(&tmp);
09307 return NULL;
09308 }
09309 pris[span].nodetype = conf->pri.nodetype;
09310 pris[span].switchtype = myswitchtype;
09311 pris[span].nsf = conf->pri.nsf;
09312 pris[span].dialplan = conf->pri.dialplan;
09313 pris[span].localdialplan = conf->pri.localdialplan;
09314 pris[span].pvts[pris[span].numchans++] = tmp;
09315 pris[span].minunused = conf->pri.minunused;
09316 pris[span].minidle = conf->pri.minidle;
09317 pris[span].overlapdial = conf->pri.overlapdial;
09318 #ifdef HAVE_PRI_INBANDDISCONNECT
09319 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
09320 #endif
09321 pris[span].facilityenable = conf->pri.facilityenable;
09322 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
09323 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
09324 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
09325 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
09326 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
09327 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
09328 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
09329 pris[span].resetinterval = conf->pri.resetinterval;
09330
09331 tmp->pri = &pris[span];
09332 tmp->prioffset = offset;
09333 tmp->call = NULL;
09334
09335 tmp->priexclusive = conf->chan.priexclusive;
09336 } else {
09337 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
09338 destroy_dahdi_pvt(&tmp);
09339 return NULL;
09340 }
09341 }
09342 } else {
09343 tmp->prioffset = 0;
09344 }
09345 #endif
09346
09347 #ifdef HAVE_OPENR2
09348 if (chan_sig == SIG_MFCR2 && reloading != 1) {
09349 char logdir[OR2_MAX_PATH];
09350 struct dahdi_mfcr2 *dahdi_r2;
09351 int threshold = 0;
09352 int snres = 0;
09353 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
09354 if (!dahdi_r2) {
09355 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
09356 } else if (!dahdi_r2->protocol_context){
09357 char tmplogdir[] = "/tmp";
09358 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
09359 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
09360 if (!dahdi_r2->protocol_context) {
09361 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
09362 destroy_dahdi_pvt(&tmp);
09363 return NULL;
09364 }
09365 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
09366 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
09367 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
09368 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
09369 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
09370 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
09371 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
09372 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
09373 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
09374 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
09375 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
09376 #endif
09377 if (ast_strlen_zero(mfcr2_cur_logdir)) {
09378 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
09379 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09380 }
09381 } else {
09382 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
09383 if (snres >= sizeof(logdir)) {
09384 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
09385 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
09386 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09387 }
09388 } else {
09389 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
09390 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
09391 }
09392 }
09393 }
09394 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
09395 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
09396 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
09397 }
09398 }
09399 }
09400 if (dahdi_r2) {
09401
09402 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
09403 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
09404 tmp->subs[SUB_REAL].dfd, NULL, NULL);
09405 if (!tmp->r2chan) {
09406 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
09407 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
09408 destroy_dahdi_pvt(&tmp);
09409 return NULL;
09410 }
09411 openr2_chan_set_client_data(tmp->r2chan, tmp);
09412
09413 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
09414 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
09415 if (mfcr2_cur_call_files) {
09416 openr2_chan_enable_call_files(tmp->r2chan);
09417 }
09418 tmp->mfcr2_category = mfcr2_cur_category;
09419 tmp->mfcr2 = dahdi_r2;
09420 tmp->mfcr2call = 0;
09421 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
09422 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
09423 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
09424 tmp->mfcr2_ani_index = 0;
09425 tmp->mfcr2_dnis_index = 0;
09426 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
09427 tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
09428 }
09429 }
09430 #endif
09431
09432 } else {
09433 chan_sig = tmp->sig;
09434 if (tmp->subs[SUB_REAL].dfd > -1) {
09435 memset(&p, 0, sizeof(p));
09436 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
09437 }
09438 }
09439
09440 switch (chan_sig) {
09441 case SIG_FXSKS:
09442 case SIG_FXSLS:
09443 case SIG_EM:
09444 case SIG_EM_E1:
09445 case SIG_EMWINK:
09446 case SIG_FEATD:
09447 case SIG_FEATDMF:
09448 case SIG_FEATDMF_TA:
09449 case SIG_FEATB:
09450 case SIG_E911:
09451 case SIG_SF:
09452 case SIG_SFWINK:
09453 case SIG_FGC_CAMA:
09454 case SIG_FGC_CAMAMF:
09455 case SIG_SF_FEATD:
09456 case SIG_SF_FEATDMF:
09457 case SIG_SF_FEATB:
09458 p.starttime = 250;
09459 break;
09460 }
09461
09462 if (tmp->radio) {
09463
09464 p.channo = channel;
09465 p.rxwinktime = 1;
09466 p.rxflashtime = 1;
09467 p.starttime = 1;
09468 p.debouncetime = 5;
09469 }
09470 if (!tmp->radio) {
09471 p.channo = channel;
09472
09473 if (conf->timing.prewinktime >= 0)
09474 p.prewinktime = conf->timing.prewinktime;
09475 if (conf->timing.preflashtime >= 0)
09476 p.preflashtime = conf->timing.preflashtime;
09477 if (conf->timing.winktime >= 0)
09478 p.winktime = conf->timing.winktime;
09479 if (conf->timing.flashtime >= 0)
09480 p.flashtime = conf->timing.flashtime;
09481 if (conf->timing.starttime >= 0)
09482 p.starttime = conf->timing.starttime;
09483 if (conf->timing.rxwinktime >= 0)
09484 p.rxwinktime = conf->timing.rxwinktime;
09485 if (conf->timing.rxflashtime >= 0)
09486 p.rxflashtime = conf->timing.rxflashtime;
09487 if (conf->timing.debouncetime >= 0)
09488 p.debouncetime = conf->timing.debouncetime;
09489 }
09490
09491
09492 if (tmp->subs[SUB_REAL].dfd >= 0)
09493 {
09494 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09495 if (res < 0) {
09496 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09497 destroy_dahdi_pvt(&tmp);
09498 return NULL;
09499 }
09500 }
09501 #if 1
09502 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09503 memset(&bi, 0, sizeof(bi));
09504 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09505 if (!res) {
09506 bi.txbufpolicy = conf->chan.buf_policy;
09507 bi.rxbufpolicy = conf->chan.buf_policy;
09508 bi.numbufs = conf->chan.buf_no;
09509 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09510 if (res < 0) {
09511 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09512 }
09513 } else {
09514 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09515 }
09516 tmp->buf_policy = conf->chan.buf_policy;
09517 tmp->buf_no = conf->chan.buf_no;
09518
09519
09520
09521
09522 tmp->bufsize = bi.bufsize;
09523 }
09524 #endif
09525 tmp->immediate = conf->chan.immediate;
09526 tmp->transfertobusy = conf->chan.transfertobusy;
09527 tmp->sig = chan_sig;
09528 tmp->ringt_base = ringt_base;
09529 tmp->firstradio = 0;
09530 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09531 tmp->permcallwaiting = conf->chan.callwaiting;
09532 else
09533 tmp->permcallwaiting = 0;
09534
09535 tmp->destroy = 0;
09536 tmp->drings = drings;
09537 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
09538 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09539 tmp->threewaycalling = conf->chan.threewaycalling;
09540 tmp->adsi = conf->chan.adsi;
09541 tmp->use_smdi = conf->chan.use_smdi;
09542 tmp->permhidecallerid = conf->chan.hidecallerid;
09543 tmp->hidecalleridname = conf->chan.hidecalleridname;
09544 tmp->callreturn = conf->chan.callreturn;
09545 tmp->echocancel = conf->chan.echocancel;
09546 tmp->echotraining = conf->chan.echotraining;
09547 tmp->pulse = conf->chan.pulse;
09548 if (tmp->echocancel)
09549 tmp->echocanbridged = conf->chan.echocanbridged;
09550 else {
09551 if (conf->chan.echocanbridged)
09552 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09553 tmp->echocanbridged = 0;
09554 }
09555 tmp->busydetect = conf->chan.busydetect;
09556 tmp->busycount = conf->chan.busycount;
09557 tmp->busycompare = conf->chan.busycompare;
09558 tmp->busytonelength = conf->chan.busytonelength;
09559 tmp->busyquietlength = conf->chan.busyquietlength;
09560 tmp->busyfuzziness = conf->chan.busyfuzziness;
09561 tmp->silencethreshold = conf->chan.silencethreshold;
09562 tmp->callprogress = conf->chan.callprogress;
09563 tmp->cancallforward = conf->chan.cancallforward;
09564 tmp->dtmfrelax = conf->chan.dtmfrelax;
09565 tmp->callwaiting = tmp->permcallwaiting;
09566 tmp->hidecallerid = tmp->permhidecallerid;
09567 tmp->channel = channel;
09568 tmp->stripmsd = conf->chan.stripmsd;
09569 tmp->use_callerid = conf->chan.use_callerid;
09570 tmp->cid_signalling = conf->chan.cid_signalling;
09571 tmp->cid_start = conf->chan.cid_start;
09572 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09573 tmp->restrictcid = conf->chan.restrictcid;
09574 tmp->use_callingpres = conf->chan.use_callingpres;
09575 if (tmp->usedistinctiveringdetection) {
09576 if (!tmp->use_callerid) {
09577 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09578 tmp->use_callerid = 1;
09579 }
09580 }
09581
09582 if (tmp->cid_signalling == CID_SIG_SMDI) {
09583 if (!tmp->use_smdi) {
09584 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09585 tmp->use_smdi = 1;
09586 }
09587 }
09588 if (tmp->use_smdi) {
09589 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09590 if (!(tmp->smdi_iface)) {
09591 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09592 tmp->use_smdi = 0;
09593 }
09594 }
09595
09596 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09597 tmp->amaflags = conf->chan.amaflags;
09598 if (!here) {
09599 tmp->confno = -1;
09600 tmp->propconfno = -1;
09601 }
09602 tmp->canpark = conf->chan.canpark;
09603 tmp->transfer = conf->chan.transfer;
09604 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09605 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09606 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09607 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09608 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09609 tmp->cid_ton = 0;
09610 if (chan_sig != SIG_PRI) {
09611 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09612 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09613 } else {
09614 tmp->cid_num[0] = '\0';
09615 tmp->cid_name[0] = '\0';
09616 }
09617 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09618 tmp->msgstate = -1;
09619 tmp->group = conf->chan.group;
09620 tmp->callgroup = conf->chan.callgroup;
09621 tmp->pickupgroup= conf->chan.pickupgroup;
09622 tmp->rxgain = conf->chan.rxgain;
09623 tmp->txgain = conf->chan.txgain;
09624 tmp->tonezone = conf->chan.tonezone;
09625 tmp->onhooktime = time(NULL);
09626 if (tmp->subs[SUB_REAL].dfd > -1) {
09627 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09628 if (tmp->dsp)
09629 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09630 update_conf(tmp);
09631 if (!here) {
09632 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09633
09634 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09635 }
09636 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09637 #ifdef HAVE_PRI
09638
09639 if (tmp->pri && !pri_is_up(tmp->pri)) {
09640 tmp->inalarm = 1;
09641 tmp->resetting = 0;
09642 }
09643 #endif
09644 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09645 tmp->inalarm = 1;
09646 #if defined(HAVE_PRI)
09647 tmp->resetting = 0;
09648 #endif
09649 handle_alarms(tmp, res);
09650 } else {
09651
09652
09653
09654
09655
09656
09657
09658
09659
09660
09661 tmp->unknown_alarm = 1;
09662 }
09663 }
09664
09665 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09666 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09667 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09668 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09669
09670 }
09671 if (tmp && !here) {
09672
09673 if (!*wlist) {
09674 *wlist = tmp;
09675 tmp->prev = NULL;
09676 tmp->next = NULL;
09677 *wend = tmp;
09678 } else {
09679
09680 struct dahdi_pvt *working = *wlist;
09681
09682
09683 if (working->channel > tmp->channel) {
09684 tmp->next = *wlist;
09685 tmp->prev = NULL;
09686 (*wlist)->prev = tmp;
09687 *wlist = tmp;
09688 } else {
09689
09690 while (working) {
09691
09692 if (working->next) {
09693 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09694 tmp->next = working->next;
09695 tmp->prev = working;
09696 working->next->prev = tmp;
09697 working->next = tmp;
09698 break;
09699 }
09700 } else {
09701
09702 if (working->channel < tmp->channel) {
09703 working->next = tmp;
09704 tmp->next = NULL;
09705 tmp->prev = working;
09706 *wend = tmp;
09707 break;
09708 }
09709 }
09710 working = working->next;
09711 }
09712 }
09713 }
09714 }
09715 return tmp;
09716 }
09717
09718 #if defined(HAVE_PRI)
09719
09720
09721
09722
09723
09724
09725
09726
09727
09728 static int sig_pri_is_chan_in_use(struct dahdi_pvt *pvt)
09729 {
09730 return pvt->owner || pvt->call || pvt->allocated || pvt->resetting || pvt->inalarm;
09731 }
09732 #endif
09733
09734 #if defined(HAVE_PRI)
09735
09736
09737
09738
09739
09740
09741
09742
09743
09744 static int sig_pri_is_chan_available(struct dahdi_pvt *pvt)
09745 {
09746 return !sig_pri_is_chan_in_use(pvt);
09747 }
09748 #endif
09749
09750 #if defined(HAVE_PRI)
09751
09752
09753
09754
09755
09756
09757
09758
09759
09760
09761 static int sig_pri_available_check(struct dahdi_pvt *pvt)
09762 {
09763
09764
09765
09766
09767 if (sig_pri_is_chan_available(pvt)) {
09768 return 1;
09769 }
09770 return 0;
09771 }
09772 #endif
09773
09774 #if defined(HAVE_PRI)
09775 static int sig_pri_available(struct dahdi_pvt *pvt)
09776 {
09777 struct dahdi_pvt *p = pvt;
09778 struct dahdi_pri *pri;
09779
09780 if (!p->pri) {
09781
09782 return 0;
09783 }
09784 pri = p->pri;
09785
09786 ast_mutex_lock(&pri->lock);
09787 if (sig_pri_available_check(p)) {
09788 p->allocated = 1;
09789 ast_mutex_unlock(&pri->lock);
09790 return 1;
09791 }
09792
09793 ast_mutex_unlock(&pri->lock);
09794 return 0;
09795 }
09796 #endif
09797
09798 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09799 {
09800 int res;
09801 struct dahdi_params par;
09802
09803
09804 if (groupmatch) {
09805 if ((p->group & groupmatch) != groupmatch)
09806 return 0;
09807 *groupmatched = 1;
09808 }
09809
09810 if (channelmatch != -1) {
09811 if (p->channel != channelmatch)
09812 return 0;
09813 *channelmatched = 1;
09814 }
09815
09816 #if defined(HAVE_PRI)
09817 switch (p->sig) {
09818 case SIG_PRI_LIB_HANDLE_CASES:
09819 return sig_pri_available(p);
09820 default:
09821 break;
09822 }
09823 #endif
09824
09825
09826 if (busy) {
09827 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09828 *busy = 1;
09829 }
09830
09831 if (p->dnd)
09832 return 0;
09833
09834 if (p->guardtime && (time(NULL) < p->guardtime))
09835 return 0;
09836
09837
09838 if (!p->owner) {
09839 #ifdef HAVE_PRI
09840
09841 if (p->pri) {
09842
09843 return sig_pri_available(p);
09844 }
09845 #endif
09846
09847 #ifdef HAVE_OPENR2
09848
09849 if (p->mfcr2) {
09850 if (p->mfcr2call || p->mfcr2block)
09851 return 0;
09852 else
09853 return 1;
09854 }
09855 #endif
09856
09857 if (!(p->radio || (p->oprmode < 0)))
09858 {
09859 if (!p->sig || (p->sig == SIG_FXSLS))
09860 return 1;
09861
09862 if (p->subs[SUB_REAL].dfd > -1) {
09863 memset(&par, 0, sizeof(par));
09864 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09865 } else {
09866
09867 res = 0;
09868 par.rxisoffhook = 0;
09869 }
09870 if (res) {
09871 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09872 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09873
09874
09875
09876 if (par.rxbits > -1)
09877 return 1;
09878 if (par.rxisoffhook)
09879 return 1;
09880 else
09881 #ifdef DAHDI_CHECK_HOOKSTATE
09882 return 0;
09883 #else
09884 return 1;
09885 #endif
09886 } else if (par.rxisoffhook) {
09887 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09888
09889 return 0;
09890 }
09891 }
09892 return 1;
09893 }
09894
09895
09896 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09897 return 0;
09898
09899 if (!p->callwaiting) {
09900
09901 return 0;
09902 }
09903
09904 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09905
09906 return 0;
09907 }
09908
09909 if ((p->owner->_state != AST_STATE_UP) &&
09910 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09911
09912 return 0;
09913 }
09914 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09915
09916 return 0;
09917 }
09918
09919 return 1;
09920 }
09921
09922 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09923 {
09924 struct dahdi_pvt *p;
09925 struct dahdi_bufferinfo bi;
09926 int res;
09927
09928 if ((p = ast_malloc(sizeof(*p)))) {
09929 memcpy(p, src, sizeof(struct dahdi_pvt));
09930 ast_mutex_init(&p->lock);
09931 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09932
09933 if (p->subs[SUB_REAL].dfd < 0) {
09934 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09935 destroy_dahdi_pvt(&p);
09936 return NULL;
09937 }
09938 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09939 if (!res) {
09940 bi.txbufpolicy = p->buf_policy;
09941 bi.rxbufpolicy = p->buf_policy;
09942 bi.numbufs = p->buf_no;
09943 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09944 if (res < 0) {
09945 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09946 }
09947 } else
09948 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09949 }
09950 p->destroy = 1;
09951 p->next = iflist;
09952 p->prev = NULL;
09953 iflist = p;
09954 if (iflist->next)
09955 iflist->next->prev = p;
09956 return p;
09957 }
09958
09959
09960 #ifdef HAVE_PRI
09961
09962
09963
09964
09965
09966
09967
09968
09969
09970
09971
09972
09973 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09974 {
09975 int x;
09976 if (backwards)
09977 x = pri->numchans;
09978 else
09979 x = 0;
09980 for (;;) {
09981 if (backwards && (x < 0))
09982 break;
09983 if (!backwards && (x >= pri->numchans))
09984 break;
09985 if (pri->pvts[x]
09986 && sig_pri_is_chan_available(pri->pvts[x])) {
09987 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
09988 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09989 return x;
09990 }
09991 if (backwards)
09992 x--;
09993 else
09994 x++;
09995 }
09996 return -1;
09997 }
09998 #endif
09999
10000 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
10001 {
10002 ast_group_t groupmatch = 0;
10003 int channelmatch = -1;
10004 int roundrobin = 0;
10005 int callwait = 0;
10006 int busy = 0;
10007 struct dahdi_pvt *p;
10008 struct ast_channel *tmp = NULL;
10009 char *dest=NULL;
10010 int x;
10011 char *s;
10012 char opt=0;
10013 int res=0, y=0;
10014 int backwards = 0;
10015 #ifdef HAVE_PRI
10016 int crv;
10017 int bearer = -1;
10018 int trunkgroup;
10019 struct dahdi_pri *pri=NULL;
10020 #endif
10021 struct dahdi_pvt *exit, *start, *end;
10022 ast_mutex_t *lock;
10023 int channelmatched = 0;
10024 int groupmatched = 0;
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044 lock = &iflock;
10045 start = iflist;
10046 end = ifend;
10047 if (data) {
10048 dest = ast_strdupa((char *)data);
10049 } else {
10050 ast_log(LOG_WARNING, "Channel requested with no data\n");
10051 return NULL;
10052 }
10053 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
10054
10055 char *stringp;
10056
10057 stringp = dest + 1;
10058 s = strsep(&stringp, "/");
10059 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10060 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
10061 return NULL;
10062 }
10063 groupmatch = ((ast_group_t) 1 << x);
10064 if (toupper(dest[0]) == 'G') {
10065 if (dest[0] == 'G') {
10066 backwards = 1;
10067 p = ifend;
10068 } else
10069 p = iflist;
10070 } else {
10071 if (dest[0] == 'R') {
10072 backwards = 1;
10073 p = round_robin[x]?round_robin[x]->prev:ifend;
10074 if (!p)
10075 p = ifend;
10076 } else {
10077 p = round_robin[x]?round_robin[x]->next:iflist;
10078 if (!p)
10079 p = iflist;
10080 }
10081 roundrobin = 1;
10082 }
10083 } else {
10084 char *stringp;
10085
10086 stringp = dest;
10087 s = strsep(&stringp, "/");
10088 p = iflist;
10089 if (!strcasecmp(s, "pseudo")) {
10090
10091 x = CHAN_PSEUDO;
10092 channelmatch = x;
10093 }
10094 #ifdef HAVE_PRI
10095 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
10096 if ((trunkgroup < 1) || (crv < 1)) {
10097 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
10098 return NULL;
10099 }
10100 res--;
10101 for (x = 0; x < NUM_SPANS; x++) {
10102 if (pris[x].trunkgroup == trunkgroup) {
10103 pri = pris + x;
10104 lock = &pri->lock;
10105 start = pri->crvs;
10106 end = pri->crvend;
10107 break;
10108 }
10109 }
10110 if (!pri) {
10111 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
10112 return NULL;
10113 }
10114 channelmatch = crv;
10115 p = pris[x].crvs;
10116 }
10117 #endif
10118 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10119 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
10120 return NULL;
10121 } else {
10122 channelmatch = x;
10123 }
10124 }
10125
10126 ast_mutex_lock(lock);
10127 exit = p;
10128 while (p && !tmp) {
10129 if (roundrobin)
10130 round_robin[x] = p;
10131 #if 0
10132 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
10133 #endif
10134
10135 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
10136 if (option_debug)
10137 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
10138 if (p->inalarm)
10139 goto next;
10140
10141 callwait = (p->owner != NULL);
10142 #ifdef HAVE_PRI
10143 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
10144 if (p->sig != SIG_FXSKS) {
10145
10146
10147 bearer = pri_find_empty_chan(pri, 0);
10148 if (bearer < 0) {
10149 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
10150 p = NULL;
10151 break;
10152 }
10153 pri_assign_bearer(p, pri, pri->pvts[bearer]);
10154 } else {
10155 if (alloc_sub(p, 0)) {
10156 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
10157 p = NULL;
10158 break;
10159 } else
10160 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
10161 p->pri = pri;
10162 }
10163 }
10164 #endif
10165
10166 #ifdef HAVE_OPENR2
10167 if (p->mfcr2) {
10168 ast_mutex_lock(&p->lock);
10169 if (p->mfcr2call) {
10170 ast_mutex_unlock(&p->lock);
10171 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
10172 goto next;
10173 }
10174 if (p->mfcr2block) {
10175 ast_mutex_unlock(&p->lock);
10176 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
10177 goto next;
10178 }
10179 p->mfcr2call = 1;
10180 ast_mutex_unlock(&p->lock);
10181 }
10182 #endif
10183
10184 if (p->channel == CHAN_PSEUDO) {
10185 p = chandup(p);
10186 if (!p) {
10187 break;
10188 }
10189 }
10190 if (p->owner) {
10191 if (alloc_sub(p, SUB_CALLWAIT)) {
10192 p = NULL;
10193 break;
10194 }
10195 }
10196 #if defined(HAVE_PRI)
10197 switch (p->sig) {
10198 case SIG_GR303FXOKS:
10199 case SIG_GR303FXSKS:
10200 case SIG_PRI_LIB_HANDLE_CASES:
10201
10202
10203
10204
10205
10206 ast_mutex_lock(&p->lock);
10207 ast_mutex_unlock(&p->lock);
10208 break;
10209 default:
10210 break;
10211 }
10212 #endif
10213 p->outgoing = 1;
10214 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
10215 if (!tmp) {
10216 p->outgoing = 0;
10217 #if defined(HAVE_PRI)
10218
10219
10220
10221
10222 p->allocated = 0;
10223 #endif
10224 }
10225 #ifdef HAVE_PRI
10226 if (p->bearer) {
10227
10228 p->bearer->owner = tmp;
10229 }
10230 #endif
10231
10232 if (res > 1) {
10233 if (opt == 'c') {
10234
10235 p->confirmanswer = 1;
10236 } else if (opt == 'r') {
10237
10238 if (res < 3)
10239 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
10240 else
10241 p->distinctivering = y;
10242 } else if (opt == 'd') {
10243
10244 p->digital = 1;
10245 if (tmp)
10246 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
10247 } else {
10248 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
10249 }
10250 }
10251
10252 if (tmp && callwait)
10253 tmp->cdrflags |= AST_CDR_CALLWAIT;
10254 break;
10255 }
10256 next:
10257 if (backwards) {
10258 p = p->prev;
10259 if (!p)
10260 p = end;
10261 } else {
10262 p = p->next;
10263 if (!p)
10264 p = start;
10265 }
10266
10267 if (p == exit)
10268 break;
10269 }
10270 ast_mutex_unlock(lock);
10271 restart_monitor();
10272 if (callwait)
10273 *cause = AST_CAUSE_BUSY;
10274 else if (!tmp) {
10275 if (channelmatched) {
10276 if (busy)
10277 *cause = AST_CAUSE_BUSY;
10278 } else if (groupmatched) {
10279 *cause = AST_CAUSE_CONGESTION;
10280 }
10281 }
10282
10283 return tmp;
10284 }
10285
10286 #ifdef HAVE_OPENR2
10287 static void *mfcr2_monitor(void *data)
10288 {
10289 struct dahdi_pvt *p;
10290 struct dahdi_mfcr2 *mfcr2 = data;
10291
10292
10293
10294
10295
10296 struct pollfd pollers[mfcr2->numchans];
10297 int maxsleep = 20;
10298 int res = 0;
10299 int i = 0;
10300 int pollsize = 0;
10301 int oldstate = 0;
10302 int was_idle = 0;
10303 int quit_loop = 0;
10304
10305
10306 for (i = 0; i < mfcr2->numchans; i++) {
10307 p = mfcr2->pvts[i];
10308 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
10309 if (openr2_chan_set_idle(p->r2chan)) {
10310 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
10311 } else {
10312 ast_mutex_lock(&p->lock);
10313 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
10314 mfcr2->pvts[i]->mfcr2call = 0;
10315 ast_mutex_unlock(&p->lock);
10316 }
10317 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
10318 }
10319 while(1) {
10320
10321
10322 pollsize = 0;
10323 for (i = 0; i < mfcr2->numchans; i++) {
10324 pollers[i].events = 0;
10325 pollers[i].revents = 0;
10326 if (mfcr2->pvts[i]->owner) {
10327 continue;
10328 }
10329 if (!mfcr2->pvts[i]->r2chan) {
10330 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
10331 quit_loop = 1;
10332 break;
10333 }
10334 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
10335 pollers[i].events = POLLIN | POLLPRI;
10336 pollsize++;
10337 }
10338 if (quit_loop) {
10339 break;
10340 }
10341
10342 if (pollsize == 0) {
10343 if (!was_idle) {
10344 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
10345 was_idle = 1;
10346 }
10347 poll(NULL, 0, maxsleep);
10348 continue;
10349 }
10350 was_idle = 0;
10351
10352
10353
10354 pthread_testcancel();
10355 res = poll(pollers, mfcr2->numchans, maxsleep);
10356 pthread_testcancel();
10357 if ((res < 0) && (errno != EINTR)) {
10358 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
10359 break;
10360 }
10361
10362 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
10363 for (i = 0; i < mfcr2->numchans; i++) {
10364 if ((pollers[i].revents & POLLPRI) || (pollers[i].revents & POLLIN)) {
10365 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
10366 }
10367 }
10368 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
10369 }
10370 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
10371 return 0;
10372 }
10373 #endif
10374
10375 #if defined(HAVE_PRI)
10376 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10377 {
10378 struct dahdi_pvt *p;
10379 p = pri->crvs;
10380 while (p) {
10381 if (p->channel == crv)
10382 return p;
10383 p = p->next;
10384 }
10385 return NULL;
10386 }
10387 #endif
10388
10389 #if defined(HAVE_PRI)
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403 static void sig_pri_lock_owner(struct dahdi_pri *pri, int chanpos)
10404 {
10405 for (;;) {
10406 if (!pri->pvts[chanpos]->owner) {
10407
10408 break;
10409 }
10410 if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
10411
10412 break;
10413 }
10414
10415 ast_mutex_unlock(&pri->lock);
10416 DEADLOCK_AVOIDANCE(&pri->pvts[chanpos]->lock);
10417 ast_mutex_lock(&pri->lock);
10418 }
10419 }
10420 #endif
10421
10422 #if defined(HAVE_PRI)
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437 static void pri_queue_frame(struct dahdi_pri *pri, int chanpos, struct ast_frame *frame)
10438 {
10439 sig_pri_lock_owner(pri, chanpos);
10440 if (pri->pvts[chanpos]->owner) {
10441 ast_queue_frame(pri->pvts[chanpos]->owner, frame);
10442 ast_channel_unlock(pri->pvts[chanpos]->owner);
10443 }
10444 }
10445 #endif
10446
10447 #if defined(HAVE_PRI)
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462 static void pri_queue_control(struct dahdi_pri *pri, int chanpos, int subclass)
10463 {
10464 struct ast_frame f = {AST_FRAME_CONTROL, };
10465
10466 f.subclass = subclass;
10467 pri_queue_frame(pri, chanpos, &f);
10468 }
10469 #endif
10470
10471 #if defined(HAVE_PRI)
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481
10482
10483
10484
10485 static int pri_find_principle_by_call(struct dahdi_pri *pri, q931_call *call)
10486 {
10487 int idx;
10488
10489 if (!call) {
10490
10491 return -1;
10492 }
10493 for (idx = 0; idx < pri->numchans; ++idx) {
10494 if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
10495
10496 return idx;
10497 }
10498 }
10499 return -1;
10500 }
10501 #endif
10502
10503 #if defined(HAVE_PRI)
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515
10516
10517 static void sig_pri_kill_call(struct dahdi_pri *pri, q931_call *call, int cause)
10518 {
10519 int chanpos;
10520
10521 chanpos = pri_find_principle_by_call(pri, call);
10522 if (chanpos < 0) {
10523 pri_hangup(pri->pri, call, cause);
10524 return;
10525 }
10526 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10527 if (!pri->pvts[chanpos]->owner) {
10528 pri_hangup(pri->pri, call, cause);
10529 pri->pvts[chanpos]->call = NULL;
10530 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10531 return;
10532 }
10533 pri->pvts[chanpos]->owner->hangupcause = cause;
10534 pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
10535 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10536 }
10537 #endif
10538
10539 #if defined(HAVE_PRI)
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549
10550
10551
10552 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10553 {
10554 int x;
10555 int span = PRI_SPAN(channel);
10556 int spanfd;
10557 struct dahdi_params param;
10558 int principle = -1;
10559 int explicit = PRI_EXPLICIT(channel);
10560 channel = PRI_CHANNEL(channel);
10561
10562 if (!explicit) {
10563 spanfd = pri_active_dchan_fd(pri);
10564 memset(¶m, 0, sizeof(param));
10565 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
10566 return -1;
10567 span = pris[param.spanno - 1].prilogicalspan;
10568 }
10569
10570 for (x = 0; x < pri->numchans; x++) {
10571 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10572 principle = x;
10573 break;
10574 }
10575 }
10576
10577 return principle;
10578 }
10579 #endif
10580
10581 #if defined(HAVE_PRI)
10582
10583
10584
10585
10586
10587
10588
10589
10590
10591
10592
10593
10594
10595 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10596 {
10597 int x;
10598 struct dahdi_pvt *crv;
10599 if (!c) {
10600 if (principle < 0)
10601 return -1;
10602 return principle;
10603 }
10604 if ((principle > -1) &&
10605 (principle < pri->numchans) &&
10606 (pri->pvts[principle]) &&
10607 (pri->pvts[principle]->call == c))
10608 return principle;
10609
10610 for (x = 0; x < pri->numchans; x++) {
10611 if (!pri->pvts[x])
10612 continue;
10613 if (pri->pvts[x]->call == c) {
10614
10615 if (principle != x) {
10616 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10617
10618
10619 ast_mutex_lock(&old->lock);
10620 sig_pri_lock_owner(pri, x);
10621 ast_mutex_lock(&new->lock);
10622
10623 if (option_verbose > 2) {
10624 ast_verbose(VERBOSE_PREFIX_3
10625 "Moving call (%s) from channel %d to %d.\n",
10626 old->owner ? old->owner->name : "",
10627 old->channel, new->channel);
10628 }
10629 if (!sig_pri_is_chan_available(new)) {
10630 ast_log(LOG_WARNING,
10631 "Can't move call (%s) from channel %d to %d. It is already in use.\n",
10632 old->owner ? old->owner->name : "",
10633 old->channel, new->channel);
10634 ast_mutex_unlock(&new->lock);
10635 if (old->owner) {
10636 ast_mutex_unlock(&old->owner->lock);
10637 }
10638 ast_mutex_unlock(&old->lock);
10639 return -1;
10640 }
10641
10642
10643 new->owner = old->owner;
10644 old->owner = NULL;
10645 if (new->owner) {
10646 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
10647 new->owner->tech_pvt = new;
10648 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
10649 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10650 old->subs[SUB_REAL].owner = NULL;
10651 } else
10652 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);
10653 new->call = old->call;
10654 old->call = NULL;
10655
10656
10657 new->dsp = old->dsp;
10658 new->dsp_features = old->dsp_features;
10659 old->dsp = NULL;
10660 old->dsp_features = 0;
10661
10662
10663 new->alreadyhungup = old->alreadyhungup;
10664 new->isidlecall = old->isidlecall;
10665 new->progress = old->progress;
10666 new->allocated = old->allocated;
10667 new->outgoing = old->outgoing;
10668 new->digital = old->digital;
10669 old->alreadyhungup = 0;
10670 old->isidlecall = 0;
10671 old->progress = 0;
10672 old->allocated = 0;
10673 old->outgoing = 0;
10674 old->digital = 0;
10675
10676
10677 new->call_level = old->call_level;
10678 old->call_level = DAHDI_CALL_LEVEL_IDLE;
10679
10680 ast_mutex_unlock(&old->lock);
10681 if (new->owner) {
10682 ast_mutex_unlock(&new->owner->lock);
10683 }
10684 ast_mutex_unlock(&new->lock);
10685 }
10686 return principle;
10687 }
10688 }
10689
10690 crv = pri->crvs;
10691 while (crv) {
10692 if (crv->call == c) {
10693
10694 if (crv->bearer)
10695 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10696 else if (pri->pvts[principle]->owner)
10697 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10698 else {
10699
10700
10701 dahdi_close_sub(crv, SUB_REAL);
10702 pri->pvts[principle]->call = crv->call;
10703 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10704 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
10705 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10706 pri->trunkgroup, crv->channel);
10707 wakeup_sub(crv, SUB_REAL, pri);
10708 }
10709 return principle;
10710 }
10711 crv = crv->next;
10712 }
10713 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10714 return -1;
10715 }
10716 #endif
10717
10718 #if defined(HAVE_PRI)
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737 static int pri_find_fixup_principle(struct dahdi_pri *pri, int channel, q931_call *call)
10738 {
10739 int chanpos;
10740
10741 chanpos = pri_find_principle(pri, channel);
10742 if (chanpos < 0) {
10743 ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
10744 pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
10745 sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
10746 return -1;
10747 }
10748 chanpos = pri_fixup_principle(pri, chanpos, call);
10749 if (chanpos < 0) {
10750 ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
10751 pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
10752
10753
10754
10755
10756
10757
10758
10759 sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
10760 return -1;
10761 }
10762 return chanpos;
10763 }
10764 #endif
10765
10766 #if defined(HAVE_PRI)
10767 static void *do_idle_thread(void *vchan)
10768 {
10769 struct ast_channel *chan = vchan;
10770 struct dahdi_pvt *pvt = chan->tech_pvt;
10771 struct ast_frame *f;
10772 char ex[80];
10773
10774 int newms, ms = 30000;
10775 if (option_verbose > 2)
10776 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
10777 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10778 if (ast_call(chan, ex, 0)) {
10779 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10780 ast_hangup(chan);
10781 return NULL;
10782 }
10783 while ((newms = ast_waitfor(chan, ms)) > 0) {
10784 f = ast_read(chan);
10785 if (!f) {
10786
10787 break;
10788 }
10789 if (f->frametype == AST_FRAME_CONTROL) {
10790 switch (f->subclass) {
10791 case AST_CONTROL_ANSWER:
10792
10793 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10794 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10795 chan->priority = 1;
10796 if (option_verbose > 3)
10797 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10798 ast_pbx_run(chan);
10799
10800 return NULL;
10801 case AST_CONTROL_BUSY:
10802 if (option_verbose > 3)
10803 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
10804 break;
10805 case AST_CONTROL_CONGESTION:
10806 if (option_verbose > 3)
10807 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
10808 break;
10809 };
10810 }
10811 ast_frfree(f);
10812 ms = newms;
10813 }
10814
10815 ast_hangup(chan);
10816 return NULL;
10817 }
10818
10819 #ifndef PRI_RESTART
10820 #error "Upgrade your libpri"
10821 #endif
10822 static void dahdi_pri_message(struct pri *pri, char *s)
10823 {
10824 int x, y;
10825 int dchan = -1, span = -1;
10826 int dchancount = 0;
10827
10828 if (pri) {
10829 for (x = 0; x < NUM_SPANS; x++) {
10830 for (y = 0; y < NUM_DCHANS; y++) {
10831 if (pris[x].dchans[y])
10832 dchancount++;
10833
10834 if (pris[x].dchans[y] == pri)
10835 dchan = y;
10836 }
10837 if (dchan >= 0) {
10838 span = x;
10839 break;
10840 }
10841 dchancount = 0;
10842 }
10843 if ((dchan >= 0) && (span >= 0)) {
10844 if (dchancount > 1)
10845 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10846 else
10847 ast_verbose("%s", s);
10848 } else
10849 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
10850 } else
10851 ast_verbose("%s", s);
10852
10853 ast_mutex_lock(&pridebugfdlock);
10854
10855 if (pridebugfd >= 0) {
10856 if (write(pridebugfd, s, strlen(s)) < 0) {
10857 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10858 }
10859 }
10860
10861 ast_mutex_unlock(&pridebugfdlock);
10862 }
10863
10864 static void dahdi_pri_error(struct pri *pri, char *s)
10865 {
10866 int x, y;
10867 int dchan = -1, span = -1;
10868 int dchancount = 0;
10869
10870 if (pri) {
10871 for (x = 0; x < NUM_SPANS; x++) {
10872 for (y = 0; y < NUM_DCHANS; y++) {
10873 if (pris[x].dchans[y])
10874 dchancount++;
10875
10876 if (pris[x].dchans[y] == pri)
10877 dchan = y;
10878 }
10879 if (dchan >= 0) {
10880 span = x;
10881 break;
10882 }
10883 dchancount = 0;
10884 }
10885 if ((dchan >= 0) && (span >= 0)) {
10886 if (dchancount > 1)
10887 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10888 else
10889 ast_log(LOG_ERROR, "%s", s);
10890 } else
10891 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
10892 } else
10893 ast_log(LOG_ERROR, "%s", s);
10894
10895 ast_mutex_lock(&pridebugfdlock);
10896
10897 if (pridebugfd >= 0) {
10898 if (write(pridebugfd, s, strlen(s)) < 0) {
10899 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10900 }
10901 }
10902
10903 ast_mutex_unlock(&pridebugfdlock);
10904 }
10905
10906
10907
10908
10909
10910
10911
10912
10913
10914
10915
10916 static void pri_check_restart(struct dahdi_pri *pri)
10917 {
10918 for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) {
10919 if (!pri->pvts[pri->resetpos]
10920 || sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) {
10921 continue;
10922 }
10923 break;
10924 }
10925 if (pri->resetpos < pri->numchans) {
10926
10927 pri->pvts[pri->resetpos]->resetting = 1;
10928 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10929 } else {
10930 pri->resetting = 0;
10931 time(&pri->lastreset);
10932 }
10933 }
10934
10935 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10936 {
10937 int x;
10938 int redo;
10939 ast_mutex_unlock(&pri->lock);
10940 ast_mutex_lock(&p->lock);
10941 do {
10942 redo = 0;
10943 for (x = 0; x < 3; x++) {
10944 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
10945 redo++;
10946 DEADLOCK_AVOIDANCE(&p->lock);
10947 }
10948 if (p->subs[x].owner) {
10949 ast_queue_hangup(p->subs[x].owner);
10950 ast_mutex_unlock(&p->subs[x].owner->lock);
10951 }
10952 }
10953 } while (redo);
10954 ast_mutex_unlock(&p->lock);
10955 ast_mutex_lock(&pri->lock);
10956 return 0;
10957 }
10958
10959 static char * redirectingreason2str(int redirectingreason)
10960 {
10961 switch (redirectingreason) {
10962 case 0:
10963 return "UNKNOWN";
10964 case 1:
10965 return "BUSY";
10966 case 2:
10967 return "NO_REPLY";
10968 case 0xF:
10969 return "UNCONDITIONAL";
10970 default:
10971 return "NOREDIRECT";
10972 }
10973 }
10974
10975 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10976 {
10977 if (ast_strlen_zero(number)) {
10978 if (size) {
10979 *buf = '\0';
10980 }
10981 return;
10982 }
10983
10984 switch (plan) {
10985 case PRI_INTERNATIONAL_ISDN:
10986 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10987 break;
10988 case PRI_NATIONAL_ISDN:
10989 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10990 break;
10991 case PRI_LOCAL_ISDN:
10992 snprintf(buf, size, "%s%s", pri->localprefix, number);
10993 break;
10994 case PRI_PRIVATE:
10995 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10996 break;
10997 case PRI_UNKNOWN:
10998 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10999 break;
11000 default:
11001 snprintf(buf, size, "%s", number);
11002 break;
11003 }
11004 }
11005
11006 static int dahdi_setlaw(int dfd, int law)
11007 {
11008 int res;
11009 res = ioctl(dfd, DAHDI_SETLAW, &law);
11010 if (res)
11011 return res;
11012 return 0;
11013 }
11014
11015 static void *pri_dchannel(void *vpri)
11016 {
11017 struct dahdi_pri *pri = vpri;
11018 pri_event *e;
11019 struct pollfd fds[NUM_DCHANS];
11020 int res;
11021 int chanpos = 0;
11022 int x;
11023 int haveidles;
11024 int activeidles;
11025 int nextidle = -1;
11026 struct ast_channel *c;
11027 struct timeval tv, lowest, *next;
11028 struct timeval lastidle = { 0, 0 };
11029 int doidling=0;
11030 char *cc;
11031 char idlen[80];
11032 struct ast_channel *idle;
11033 pthread_t p;
11034 time_t t;
11035 int i, which=-1;
11036 int numdchans;
11037 int cause=0;
11038 struct dahdi_pvt *crv;
11039 pthread_t threadid;
11040 pthread_attr_t attr;
11041 char ani2str[6];
11042 char plancallingnum[256];
11043 char plancallingani[256];
11044 char calledtonstr[10];
11045 unsigned int len;
11046
11047 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11048
11049 gettimeofday(&lastidle, NULL);
11050 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
11051
11052 cc = strchr(pri->idleext, '@');
11053 if (cc) {
11054 *cc = '\0';
11055 cc++;
11056 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
11057 #if 0
11058
11059 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
11060 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
11061 else
11062 #endif
11063 doidling = 1;
11064 } else
11065 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
11066 }
11067 for (;;) {
11068 for (i = 0; i < NUM_DCHANS; i++) {
11069 if (!pri->dchannels[i])
11070 break;
11071 fds[i].fd = pri->fds[i];
11072 fds[i].events = POLLIN | POLLPRI;
11073 fds[i].revents = 0;
11074 }
11075 numdchans = i;
11076 time(&t);
11077 ast_mutex_lock(&pri->lock);
11078 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
11079 if (pri->resetting && pri_is_up(pri)) {
11080 if (pri->resetpos < 0) {
11081 pri_check_restart(pri);
11082 }
11083 } else {
11084 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
11085 pri->resetting = 1;
11086 pri->resetpos = -1;
11087 }
11088 }
11089 }
11090
11091 if (doidling && pri_is_up(pri)) {
11092 nextidle = -1;
11093 haveidles = 0;
11094 activeidles = 0;
11095 for (x = pri->numchans; x >= 0; x--) {
11096 if (pri->pvts[x]) {
11097 if (sig_pri_is_chan_available(pri->pvts[x])) {
11098 if (haveidles < pri->minunused) {
11099 haveidles++;
11100 } else {
11101 nextidle = x;
11102 break;
11103 }
11104 } else if (pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
11105 activeidles++;
11106 }
11107 }
11108 }
11109 if (nextidle > -1) {
11110 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
11111
11112 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
11113
11114
11115
11116
11117 ast_mutex_unlock(&pri->lock);
11118 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
11119 ast_mutex_lock(&pri->lock);
11120 if (idle) {
11121 pri->pvts[nextidle]->isidlecall = 1;
11122 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
11123 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
11124 ast_mutex_unlock(&pri->lock);
11125 ast_hangup(idle);
11126 ast_mutex_lock(&pri->lock);
11127 }
11128 } else {
11129 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
11130 }
11131 gettimeofday(&lastidle, NULL);
11132 }
11133 } else if ((haveidles < pri->minunused) &&
11134 (activeidles > pri->minidle)) {
11135
11136
11137 for (x = pri->numchans; x >= 0; x--) {
11138
11139 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
11140 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11141 haveidles++;
11142
11143
11144 if ((haveidles >= pri->minunused) ||
11145 (activeidles <= pri->minidle))
11146 break;
11147 }
11148 }
11149 }
11150 }
11151
11152 lowest = ast_tv(60, 0);
11153 for (i = 0; i < NUM_DCHANS; i++) {
11154
11155 if (!pri->dchannels[i])
11156 break;
11157 if ((next = pri_schedule_next(pri->dchans[i]))) {
11158
11159 tv = ast_tvsub(*next, ast_tvnow());
11160 if (tv.tv_sec < 0) {
11161 tv = ast_tv(0,0);
11162 }
11163 if (doidling || pri->resetting) {
11164 if (tv.tv_sec > 1) {
11165 tv = ast_tv(1, 0);
11166 }
11167 } else {
11168 if (tv.tv_sec > 60) {
11169 tv = ast_tv(60, 0);
11170 }
11171 }
11172 } else if (doidling || pri->resetting) {
11173
11174
11175 tv = ast_tv(1,0);
11176 } else {
11177
11178 tv = ast_tv(60, 0);
11179 }
11180 if (!i || ast_tvcmp(tv, lowest) < 0) {
11181 lowest = tv;
11182 }
11183 }
11184 ast_mutex_unlock(&pri->lock);
11185
11186 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11187 pthread_testcancel();
11188 e = NULL;
11189 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11190 pthread_testcancel();
11191 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11192
11193 ast_mutex_lock(&pri->lock);
11194 if (!res) {
11195 for (which = 0; which < NUM_DCHANS; which++) {
11196 if (!pri->dchans[which])
11197 break;
11198
11199 e = pri_schedule_run(pri->dchans[which]);
11200 if (e)
11201 break;
11202 }
11203 } else if (res > -1) {
11204 for (which = 0; which < NUM_DCHANS; which++) {
11205 if (!pri->dchans[which])
11206 break;
11207 if (fds[which].revents & POLLPRI) {
11208
11209 x = 0;
11210 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11211 if (x)
11212 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);
11213
11214 if (x == DAHDI_EVENT_ALARM) {
11215 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11216 pri_find_dchan(pri);
11217 } else if (x == DAHDI_EVENT_NOALARM) {
11218 pri->dchanavail[which] |= DCHAN_NOTINALARM;
11219 pri_restart(pri->dchans[which]);
11220 }
11221
11222 if (option_debug)
11223 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11224 } else if (fds[which].revents & POLLIN) {
11225 e = pri_check_event(pri->dchans[which]);
11226 }
11227 if (e)
11228 break;
11229 }
11230 } else if (errno != EINTR)
11231 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11232
11233 if (e) {
11234 if (pri->debug)
11235 pri_dump_event(pri->dchans[which], e);
11236
11237 if (e->e != PRI_EVENT_DCHAN_DOWN) {
11238 if (!(pri->dchanavail[which] & DCHAN_UP)) {
11239 if (option_verbose > 1)
11240 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11241 }
11242 pri->dchanavail[which] |= DCHAN_UP;
11243 } else {
11244 if (pri->dchanavail[which] & DCHAN_UP) {
11245 if (option_verbose > 1)
11246 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11247 }
11248 pri->dchanavail[which] &= ~DCHAN_UP;
11249 }
11250
11251 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11252
11253 pri->pri = pri->dchans[which];
11254
11255 switch (e->e) {
11256 case PRI_EVENT_DCHAN_UP:
11257 pri->no_d_channels = 0;
11258 if (!pri->pri) pri_find_dchan(pri);
11259
11260
11261 time(&pri->lastreset);
11262
11263
11264 if (pri->resetinterval > -1) {
11265 pri->lastreset -= pri->resetinterval;
11266 pri->lastreset += 5;
11267 }
11268
11269 pri->resetting = 0;
11270 for (i = 0; i < pri->numchans; i++) {
11271 if (pri->pvts[i]) {
11272 pri->pvts[i]->inalarm = 0;
11273 pri->pvts[i]->resetting = 0;
11274 }
11275 }
11276 break;
11277 case PRI_EVENT_DCHAN_DOWN:
11278 pri_find_dchan(pri);
11279 if (!pri_is_up(pri)) {
11280
11281 pri->resetting = 0;
11282 for (i = 0; i < pri->numchans; i++) {
11283 struct dahdi_pvt *p = pri->pvts[i];
11284 if (p) {
11285 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11286
11287 if (p->call) {
11288 if (p->pri && p->pri->pri) {
11289 pri_destroycall(p->pri->pri, p->call);
11290 p->call = NULL;
11291 } else
11292 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
11293 }
11294 if (p->realcall) {
11295 pri_hangup_all(p->realcall, pri);
11296 } else if (p->owner)
11297 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11298 }
11299 p->inalarm = 1;
11300 p->resetting = 0;
11301 }
11302 }
11303 }
11304 break;
11305 case PRI_EVENT_RESTART:
11306 if (e->restart.channel > -1 && PRI_CHANNEL(e->ring.channel) != 0xFF) {
11307 chanpos = pri_find_principle(pri, e->restart.channel);
11308 if (chanpos < 0)
11309 ast_log(LOG_WARNING,
11310 "Span %d: Restart requested on odd/unavailable channel number %d/%d\n",
11311 pri->span, PRI_SPAN(e->restart.channel),
11312 PRI_CHANNEL(e->restart.channel));
11313 else {
11314 if (option_verbose > 2)
11315 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d restarted\n",
11316 pri->span, PRI_SPAN(e->restart.channel),
11317 PRI_CHANNEL(e->restart.channel));
11318 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11319 if (pri->pvts[chanpos]->call) {
11320 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11321 pri->pvts[chanpos]->call = NULL;
11322 }
11323
11324 if (pri->pvts[chanpos]->realcall)
11325 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11326 else if (pri->pvts[chanpos]->owner)
11327 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11328 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11329 }
11330 } else {
11331 if (option_verbose > 2)
11332 ast_verbose(VERBOSE_PREFIX_2 "Restart requested on entire span %d\n",
11333 pri->span);
11334 for (x = 0; x < pri->numchans; x++)
11335 if (pri->pvts[x]) {
11336 ast_mutex_lock(&pri->pvts[x]->lock);
11337 if (pri->pvts[x]->call) {
11338 pri_destroycall(pri->pri, pri->pvts[x]->call);
11339 pri->pvts[x]->call = NULL;
11340 }
11341 if (pri->pvts[x]->realcall)
11342 pri_hangup_all(pri->pvts[x]->realcall, pri);
11343 else if (pri->pvts[x]->owner)
11344 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11345 ast_mutex_unlock(&pri->pvts[x]->lock);
11346 }
11347 }
11348 break;
11349 case PRI_EVENT_KEYPAD_DIGIT:
11350 chanpos = pri_find_principle_by_call(pri, e->digit.call);
11351 if (chanpos < 0) {
11352 ast_log(LOG_WARNING,
11353 "Span %d: Received keypad digits for unknown call.\n", pri->span);
11354 break;
11355 }
11356 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11357
11358 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11359 && pri->pvts[chanpos]->owner) {
11360
11361 int digitlen = strlen(e->digit.digits);
11362 char digit;
11363 int i;
11364 for (i = 0; i < digitlen; i++) {
11365 digit = e->digit.digits[i];
11366 {
11367 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11368 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11369 }
11370 }
11371 }
11372 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11373 break;
11374
11375 case PRI_EVENT_INFO_RECEIVED:
11376 chanpos = pri_find_principle_by_call(pri, e->ring.call);
11377 if (chanpos < 0) {
11378 ast_log(LOG_WARNING,
11379 "Span %d: Received INFORMATION for unknown call.\n", pri->span);
11380 break;
11381 }
11382 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11383
11384 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11385 && pri->pvts[chanpos]->owner) {
11386
11387 int digitlen = strlen(e->ring.callednum);
11388 char digit;
11389 int i;
11390 for (i = 0; i < digitlen; i++) {
11391 digit = e->ring.callednum[i];
11392 {
11393 struct ast_frame f = { AST_FRAME_DTMF, digit, };
11394 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11395 }
11396 }
11397 }
11398 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11399 break;
11400 case PRI_EVENT_RING:
11401 crv = NULL;
11402 chanpos = pri_find_principle_by_call(pri, e->ring.call);
11403 if (-1 < chanpos) {
11404
11405 ast_log(LOG_WARNING,
11406 "Span %d: Got SETUP with duplicate call ptr. Dropping call.\n",
11407 pri->span);
11408 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
11409 break;
11410 }
11411 if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
11412
11413 chanpos = pri_find_empty_chan(pri, 1);
11414 } else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
11415
11416 {
11417
11418 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INCOMPATIBLE_DESTINATION);
11419 break;
11420 }
11421 } else {
11422
11423 chanpos = pri_find_principle(pri, e->ring.channel);
11424 if (chanpos < 0) {
11425 ast_log(LOG_WARNING,
11426 "Span %d: SETUP on unconfigured channel %d/%d\n",
11427 pri->span, PRI_SPAN(e->ring.channel),
11428 PRI_CHANNEL(e->ring.channel));
11429 } else if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
11430
11431 ast_log(LOG_DEBUG,
11432 "Span %d: SETUP requested unavailable channel %d/%d. Attempting to renegotiate.\n",
11433 pri->span, PRI_SPAN(e->ring.channel),
11434 PRI_CHANNEL(e->ring.channel));
11435 chanpos = -1;
11436 }
11437 #if defined(ALWAYS_PICK_CHANNEL)
11438 if (e->ring.flexible) {
11439 chanpos = -1;
11440 }
11441 #endif
11442 if (chanpos < 0 && e->ring.flexible) {
11443
11444 chanpos = pri_find_empty_chan(pri, 1);
11445 }
11446 }
11447 if (chanpos < 0) {
11448 if (e->ring.flexible) {
11449 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11450 } else {
11451 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11452 }
11453 break;
11454 }
11455
11456 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11457 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11458
11459 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11460 if (crv)
11461 ast_mutex_lock(&crv->lock);
11462 if (!crv || crv->owner) {
11463 pri->pvts[chanpos]->call = NULL;
11464 if (crv) {
11465 if (crv->owner)
11466 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11467 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);
11468 } else
11469 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);
11470 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11471 if (crv)
11472 ast_mutex_unlock(&crv->lock);
11473 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11474 break;
11475 }
11476 }
11477
11478
11479 pri->pvts[chanpos]->call = e->ring.call;
11480
11481 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11482 if (pri->pvts[chanpos]->use_callerid) {
11483 ast_shrink_phone_number(plancallingnum);
11484 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11485 #ifdef PRI_ANI
11486 if (!ast_strlen_zero(e->ring.callingani)) {
11487 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11488 ast_shrink_phone_number(plancallingani);
11489 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11490 } else {
11491 pri->pvts[chanpos]->cid_ani[0] = '\0';
11492 }
11493 #endif
11494 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11495 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
11496 } else {
11497 pri->pvts[chanpos]->cid_num[0] = '\0';
11498 pri->pvts[chanpos]->cid_ani[0] = '\0';
11499 pri->pvts[chanpos]->cid_name[0] = '\0';
11500 pri->pvts[chanpos]->cid_ton = 0;
11501 }
11502 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11503 e->ring.redirectingnum, e->ring.callingplanrdnis);
11504
11505
11506 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11507
11508
11509 if (pri->pvts[chanpos]->immediate) {
11510 if (option_verbose > 2)
11511 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
11512 pri->pvts[chanpos]->exten[0] = 's';
11513 pri->pvts[chanpos]->exten[1] = '\0';
11514 }
11515
11516 else if (!ast_strlen_zero(e->ring.callednum)) {
11517 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11518 } else if (pri->overlapdial)
11519 pri->pvts[chanpos]->exten[0] = '\0';
11520 else {
11521
11522 pri->pvts[chanpos]->exten[0] = 's';
11523 pri->pvts[chanpos]->exten[1] = '\0';
11524 }
11525
11526 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11527 if (option_verbose > 2)
11528 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
11529 pri->pvts[chanpos]->exten[0] = 's';
11530 pri->pvts[chanpos]->exten[1] = '\0';
11531 }
11532
11533
11534 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11535 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11536
11537 int law;
11538 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11539
11540 law = 1;
11541 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11542 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11543 }
11544 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11545 law = DAHDI_LAW_ALAW;
11546 else
11547 law = DAHDI_LAW_MULAW;
11548 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11549 if (res < 0)
11550 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11551 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11552 if (res < 0)
11553 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11554 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11555
11556 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11557 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11558 } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11559 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
11560 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11561 } else {
11562 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
11563 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11564 }
11565
11566 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11567
11568
11569 if (!e->ring.complete
11570 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11571 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11572
11573
11574
11575
11576
11577
11578 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11579 ast_mutex_unlock(&pri->lock);
11580 if (crv) {
11581
11582 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11583 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11584 pri->pvts[chanpos]->owner = &inuse;
11585 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11586 } else {
11587 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11588 }
11589 ast_mutex_lock(&pri->lock);
11590 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11591 if (c) {
11592 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11593 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11594 }
11595 if (e->ring.ani2 >= 0) {
11596 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11597 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11598 }
11599
11600 #ifdef SUPPORT_USERUSER
11601 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11602 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11603 }
11604 #endif
11605
11606 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11607 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11608 if (e->ring.redirectingreason >= 0)
11609 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11610
11611 if (!pri->pvts[chanpos]->digital) {
11612
11613
11614
11615
11616 pri->pvts[chanpos]->progress = 1;
11617 pri_progress(pri->pri, e->ring.call,
11618 PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11619 }
11620 }
11621
11622 pthread_attr_init(&attr);
11623 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11624 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
11625 if (option_verbose > 2)
11626 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11627 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11628 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11629 } else {
11630 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11631 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11632 if (c) {
11633
11634 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11635 ast_mutex_unlock(&pri->lock);
11636 ast_hangup(c);
11637 ast_mutex_lock(&pri->lock);
11638 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11639 } else {
11640 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11641 pri->pvts[chanpos]->call = NULL;
11642 }
11643 }
11644 pthread_attr_destroy(&attr);
11645 } else {
11646
11647
11648
11649
11650
11651
11652 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11653 ast_mutex_unlock(&pri->lock);
11654 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
11655 ast_mutex_lock(&pri->lock);
11656 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11657 if (c) {
11658
11659
11660
11661
11662
11663
11664
11665
11666 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11667 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11668 }
11669 if (e->ring.ani2 >= 0) {
11670 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11671 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11672 }
11673
11674 #ifdef SUPPORT_USERUSER
11675 if (!ast_strlen_zero(e->ring.useruserinfo)) {
11676 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11677 }
11678 #endif
11679
11680 if (e->ring.redirectingreason >= 0)
11681 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11682
11683 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11684 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11685 }
11686 if (c && !ast_pbx_start(c)) {
11687 if (option_verbose > 2)
11688 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11689 plancallingnum, pri->pvts[chanpos]->exten,
11690 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11691
11692 dahdi_enable_ec(pri->pvts[chanpos]);
11693 } else {
11694 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11695 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11696 if (c) {
11697
11698 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11699 ast_mutex_unlock(&pri->lock);
11700 ast_hangup(c);
11701 ast_mutex_lock(&pri->lock);
11702 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11703 } else {
11704 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11705 pri->pvts[chanpos]->call = NULL;
11706 }
11707 }
11708 }
11709 } else {
11710 if (option_verbose > 2)
11711 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Extension %s@%s does not exist. Rejecting call from '%s'.\n",
11712 pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context,
11713 pri->pvts[chanpos]->cid_num);
11714 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11715 pri->pvts[chanpos]->call = NULL;
11716 pri->pvts[chanpos]->exten[0] = '\0';
11717 }
11718 if (crv)
11719 ast_mutex_unlock(&crv->lock);
11720 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11721 break;
11722 case PRI_EVENT_RINGING:
11723 chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
11724 e->ringing.call);
11725 if (chanpos < 0) {
11726 break;
11727 }
11728 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11729 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11730 dahdi_enable_ec(pri->pvts[chanpos]);
11731 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11732 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
11733 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
11734 }
11735 } else
11736 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
11737 if (
11738 #ifdef PRI_PROGRESS_MASK
11739 e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
11740 #else
11741 e->ringing.progress == 8
11742 #endif
11743 ) {
11744
11745 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11746
11747 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11748 pri->pvts[chanpos]->dsp_features = 0;
11749 }
11750 }
11751
11752 #ifdef SUPPORT_USERUSER
11753 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11754 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11755 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11756 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11757 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11758 }
11759 #endif
11760
11761 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11762 break;
11763 case PRI_EVENT_PROGRESS:
11764 chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
11765 e->proceeding.call);
11766 if (chanpos < 0) {
11767 break;
11768 }
11769 if ((!pri->pvts[chanpos]->progress)
11770 #ifdef PRI_PROGRESS_MASK
11771 || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
11772 #else
11773 || (e->proceeding.progress == 8)
11774 #endif
11775 ) {
11776 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11777
11778 if (e->proceeding.cause > -1) {
11779 if (option_verbose > 2)
11780 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
11781
11782
11783 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11784 if (pri->pvts[chanpos]->owner) {
11785 if (option_verbose > 2)
11786 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11787
11788 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11789 f.subclass = AST_CONTROL_BUSY;
11790 }
11791 }
11792 }
11793
11794 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11795 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11796 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11797 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11798 if (
11799 #ifdef PRI_PROGRESS_MASK
11800 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
11801 #else
11802 e->proceeding.progress == 8
11803 #endif
11804 ) {
11805
11806 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11807 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11808 pri->pvts[chanpos]->dsp_features = 0;
11809 }
11810
11811 f.subclass = AST_CONTROL_PROGRESS;
11812 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11813 }
11814 pri->pvts[chanpos]->progress = 1;
11815 pri->pvts[chanpos]->dialing = 0;
11816 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11817 }
11818 break;
11819 case PRI_EVENT_PROCEEDING:
11820 chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
11821 e->proceeding.call);
11822 if (chanpos < 0) {
11823 break;
11824 }
11825 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11826 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
11827 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11828
11829 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11830 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11831 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11832 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11833 if (
11834 #ifdef PRI_PROGRESS_MASK
11835 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
11836 #else
11837 e->proceeding.progress == 8
11838 #endif
11839 ) {
11840
11841 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11842 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11843 pri->pvts[chanpos]->dsp_features = 0;
11844 }
11845
11846 f.subclass = AST_CONTROL_PROGRESS;
11847 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11848 }
11849 pri->pvts[chanpos]->dialing = 0;
11850 }
11851 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11852 break;
11853 case PRI_EVENT_FACNAME:
11854 chanpos = pri_find_principle_by_call(pri, e->facname.call);
11855 if (chanpos < 0) {
11856 ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
11857 pri->span);
11858 break;
11859 }
11860 if (pri->pvts[chanpos]->use_callerid) {
11861
11862 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11863 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11864 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11865 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
11866 dahdi_enable_ec(pri->pvts[chanpos]);
11867 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11868 }
11869 break;
11870 case PRI_EVENT_ANSWER:
11871 chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
11872 if (chanpos < 0) {
11873 break;
11874 }
11875 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11876
11877
11878
11879
11880
11881 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11882 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11883 pri->pvts[chanpos]->dsp_features = 0;
11884 }
11885 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11886 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
11887 x = DAHDI_START;
11888 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11889 if (res < 0) {
11890 if (errno != EINPROGRESS) {
11891 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11892 }
11893 }
11894 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11895 pri->pvts[chanpos]->dialing = 1;
11896
11897 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11898 if (res < 0) {
11899 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11900 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11901 } else
11902 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11903 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11904 } else if (pri->pvts[chanpos]->confirmanswer) {
11905 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11906 } else {
11907 pri->pvts[chanpos]->dialing = 0;
11908 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
11909 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
11910 }
11911 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11912
11913 dahdi_enable_ec(pri->pvts[chanpos]);
11914 }
11915
11916 #ifdef SUPPORT_USERUSER
11917 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11918 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11919 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11920 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11921 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11922 }
11923 #endif
11924
11925 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11926 break;
11927 case PRI_EVENT_HANGUP:
11928 chanpos = pri_find_principle_by_call(pri, e->hangup.call);
11929 if (chanpos < 0) {
11930
11931
11932
11933
11934 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
11935 break;
11936 }
11937 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11938 switch (e->hangup.cause) {
11939 case PRI_CAUSE_INVALID_CALL_REFERENCE:
11940
11941
11942
11943
11944 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
11945 pri->pvts[chanpos]->call = NULL;
11946 break;
11947 default:
11948 break;
11949 }
11950 if (!pri->pvts[chanpos]->alreadyhungup) {
11951
11952 pri->pvts[chanpos]->alreadyhungup = 1;
11953 if (pri->pvts[chanpos]->realcall)
11954 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11955 else if (pri->pvts[chanpos]->owner) {
11956
11957 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11958 switch (pri->pvts[chanpos]->owner->_state) {
11959 case AST_STATE_BUSY:
11960 case AST_STATE_UP:
11961 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11962 break;
11963 default:
11964 if (!pri->pvts[chanpos]->outgoing) {
11965
11966
11967
11968
11969 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11970 break;
11971 }
11972 switch (e->hangup.cause) {
11973 case PRI_CAUSE_USER_BUSY:
11974 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11975 break;
11976 case PRI_CAUSE_CALL_REJECTED:
11977 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11978 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11979 case PRI_CAUSE_SWITCH_CONGESTION:
11980 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11981 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11982 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11983 break;
11984 default:
11985 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11986 break;
11987 }
11988 break;
11989 }
11990 } else {
11991
11992
11993
11994
11995 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11996 pri->pvts[chanpos]->call = NULL;
11997 }
11998 if (option_verbose > 2)
11999 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup, cause %d\n",
12000 pri->span, pri->pvts[chanpos]->logicalspan,
12001 pri->pvts[chanpos]->prioffset, e->hangup.cause);
12002 } else {
12003
12004 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
12005 pri->pvts[chanpos]->call = NULL;
12006 }
12007 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
12008 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
12009 && !pri->resetting && !pri->pvts[chanpos]->resetting) {
12010 if (option_verbose > 2)
12011 ast_verbose(VERBOSE_PREFIX_3
12012 "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
12013 pri->span, pri->pvts[chanpos]->logicalspan,
12014 pri->pvts[chanpos]->prioffset);
12015 pri->pvts[chanpos]->resetting = 1;
12016 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
12017 }
12018 #endif
12019 if (e->hangup.aoc_units > -1)
12020 if (option_verbose > 2)
12021 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
12022 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
12023
12024 #ifdef SUPPORT_USERUSER
12025 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
12026 struct ast_channel *owner = pri->pvts[chanpos]->owner;
12027 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12028 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
12029 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12030 }
12031 #endif
12032
12033 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12034 break;
12035 #ifndef PRI_EVENT_HANGUP_REQ
12036 #error please update libpri
12037 #endif
12038 case PRI_EVENT_HANGUP_REQ:
12039 chanpos = pri_find_principle_by_call(pri, e->hangup.call);
12040 if (chanpos < 0) {
12041
12042
12043
12044
12045 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
12046 break;
12047 }
12048 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12049 switch (e->hangup.cause) {
12050 case PRI_CAUSE_INVALID_CALL_REFERENCE:
12051
12052
12053
12054
12055
12056
12057 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
12058 pri->pvts[chanpos]->call = NULL;
12059 break;
12060 default:
12061 break;
12062 }
12063 if (pri->pvts[chanpos]->realcall)
12064 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12065 else if (pri->pvts[chanpos]->owner) {
12066 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
12067 switch (pri->pvts[chanpos]->owner->_state) {
12068 case AST_STATE_BUSY:
12069 case AST_STATE_UP:
12070 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12071 break;
12072 default:
12073 if (!pri->pvts[chanpos]->outgoing) {
12074
12075
12076
12077
12078 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12079 break;
12080 }
12081 switch (e->hangup.cause) {
12082 case PRI_CAUSE_USER_BUSY:
12083 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
12084 break;
12085 case PRI_CAUSE_CALL_REJECTED:
12086 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
12087 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
12088 case PRI_CAUSE_SWITCH_CONGESTION:
12089 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
12090 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
12091 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
12092 break;
12093 default:
12094 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12095 break;
12096 }
12097 break;
12098 }
12099 if (option_verbose > 2)
12100 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup request, cause %d\n",
12101 pri->span, pri->pvts[chanpos]->logicalspan,
12102 pri->pvts[chanpos]->prioffset, e->hangup.cause);
12103 if (e->hangup.aoc_units > -1)
12104 if (option_verbose > 2)
12105 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
12106 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
12107 } else {
12108
12109
12110
12111
12112 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
12113 pri->pvts[chanpos]->call = NULL;
12114 }
12115 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
12116 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
12117 && !pri->resetting && !pri->pvts[chanpos]->resetting) {
12118 if (option_verbose > 2)
12119 ast_verbose(VERBOSE_PREFIX_3
12120 "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
12121 pri->span, pri->pvts[chanpos]->logicalspan,
12122 pri->pvts[chanpos]->prioffset);
12123 pri->pvts[chanpos]->resetting = 1;
12124 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
12125 }
12126 #endif
12127
12128 #ifdef SUPPORT_USERUSER
12129 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
12130 struct ast_channel *owner = pri->pvts[chanpos]->owner;
12131 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12132 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
12133 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12134 }
12135 #endif
12136
12137 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12138 break;
12139 case PRI_EVENT_HANGUP_ACK:
12140 chanpos = pri_find_principle_by_call(pri, e->hangup.call);
12141 if (chanpos < 0) {
12142 break;
12143 }
12144 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12145 pri->pvts[chanpos]->call = NULL;
12146 if (pri->pvts[chanpos]->owner) {
12147 if (option_verbose > 2)
12148 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup ACK\n",
12149 pri->span, pri->pvts[chanpos]->logicalspan,
12150 pri->pvts[chanpos]->prioffset);
12151 }
12152 #ifdef SUPPORT_USERUSER
12153 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
12154 struct ast_channel *owner = pri->pvts[chanpos]->owner;
12155 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12156 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
12157 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12158 }
12159 #endif
12160
12161 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12162 break;
12163 case PRI_EVENT_CONFIG_ERR:
12164 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
12165 break;
12166 case PRI_EVENT_RESTART_ACK:
12167 chanpos = pri_find_principle(pri, e->restartack.channel);
12168 if (chanpos < 0) {
12169
12170
12171
12172 for (x = 0; x < pri->numchans; x++) {
12173 if (pri->pvts[x] && pri->pvts[x]->resetting) {
12174 chanpos = x;
12175 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12176 ast_log(LOG_DEBUG,
12177 "Span %d: Assuming restart ack is for channel %d/%d\n",
12178 pri->span, pri->pvts[chanpos]->logicalspan,
12179 pri->pvts[chanpos]->prioffset);
12180 if (pri->pvts[chanpos]->realcall)
12181 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12182 else if (pri->pvts[chanpos]->owner) {
12183 ast_log(LOG_WARNING,
12184 "Span %d: Got restart ack on channel %d/%d with owner\n",
12185 pri->span, pri->pvts[chanpos]->logicalspan,
12186 pri->pvts[chanpos]->prioffset);
12187 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12188 }
12189 pri->pvts[chanpos]->resetting = 0;
12190 if (option_verbose > 2)
12191 ast_verbose(VERBOSE_PREFIX_3
12192 "Span %d: Channel %d/%d successfully restarted\n",
12193 pri->span, pri->pvts[chanpos]->logicalspan,
12194 pri->pvts[chanpos]->prioffset);
12195 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12196 if (pri->resetting)
12197 pri_check_restart(pri);
12198 break;
12199 }
12200 }
12201 if (chanpos < 0) {
12202 ast_log(LOG_WARNING,
12203 "Span %d: Restart ACK on strange channel %d/%d\n",
12204 pri->span, PRI_SPAN(e->restartack.channel),
12205 PRI_CHANNEL(e->restartack.channel));
12206 }
12207 } else {
12208 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12209 if (pri->pvts[chanpos]->realcall)
12210 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12211 else if (pri->pvts[chanpos]->owner) {
12212 ast_log(LOG_WARNING,
12213 "Span %d: Got restart ack on channel %d/%d with owner\n",
12214 pri->span, pri->pvts[chanpos]->logicalspan,
12215 pri->pvts[chanpos]->prioffset);
12216 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12217 }
12218 pri->pvts[chanpos]->resetting = 0;
12219 if (option_verbose > 2)
12220 ast_verbose(VERBOSE_PREFIX_3
12221 "Span %d: Channel %d/%d successfully restarted\n",
12222 pri->span, pri->pvts[chanpos]->logicalspan,
12223 pri->pvts[chanpos]->prioffset);
12224 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12225 if (pri->resetting)
12226 pri_check_restart(pri);
12227 }
12228 break;
12229 case PRI_EVENT_SETUP_ACK:
12230 chanpos = pri_find_fixup_principle(pri, e->setup_ack.channel,
12231 e->setup_ack.call);
12232 if (chanpos < 0) {
12233 break;
12234 }
12235 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12236 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
12237 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
12238 }
12239
12240
12241 len = strlen(pri->pvts[chanpos]->dialdest);
12242 for (x = 0; x < len; ++x) {
12243 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
12244 pri_information(pri->pri, pri->pvts[chanpos]->call,
12245 pri->pvts[chanpos]->dialdest[x]);
12246 }
12247
12248 if (!pri->pvts[chanpos]->progress
12249 && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
12250 && !pri->pvts[chanpos]->digital) {
12251
12252
12253
12254
12255 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
12256 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12257 pri->pvts[chanpos]->progress = 1;
12258 pri->pvts[chanpos]->dialing = 0;
12259 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
12260 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
12261 pri->pvts[chanpos]->dsp_features = 0;
12262 }
12263 }
12264 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12265 break;
12266 case PRI_EVENT_NOTIFY:
12267 #if defined(HAVE_PRI_CALL_HOLD)
12268 chanpos = pri_find_principle_by_call(pri, e->notify.call);
12269 if (chanpos < 0) {
12270 ast_log(LOG_WARNING, "Span %d: Received NOTIFY for unknown call.\n",
12271 pri->span);
12272 break;
12273 }
12274 #else
12275
12276
12277
12278
12279
12280 chanpos = pri_find_principle(pri, e->notify.channel);
12281 if (chanpos < 0) {
12282 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
12283 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
12284 break;
12285 }
12286 #endif
12287 {
12288 struct ast_frame f = { AST_FRAME_CONTROL, };
12289 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12290 switch (e->notify.info) {
12291 case PRI_NOTIFY_REMOTE_HOLD:
12292 f.subclass = AST_CONTROL_HOLD;
12293 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12294 break;
12295 case PRI_NOTIFY_REMOTE_RETRIEVAL:
12296 f.subclass = AST_CONTROL_UNHOLD;
12297 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12298 break;
12299 }
12300 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12301 }
12302 break;
12303 default:
12304 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
12305 }
12306 }
12307 ast_mutex_unlock(&pri->lock);
12308 }
12309
12310 return NULL;
12311 }
12312
12313 static int start_pri(struct dahdi_pri *pri)
12314 {
12315 int res, x;
12316 struct dahdi_params p;
12317 struct dahdi_bufferinfo bi;
12318 struct dahdi_spaninfo si;
12319 int i;
12320
12321 for (i = 0; i < NUM_DCHANS; i++) {
12322 if (!pri->dchannels[i])
12323 break;
12324 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
12325 x = pri->dchannels[i];
12326 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
12327 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12328 return -1;
12329 }
12330 memset(&p, 0, sizeof(p));
12331 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12332 if (res) {
12333 dahdi_close_pri_fd(pri, i);
12334 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12335 return -1;
12336 }
12337 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12338 dahdi_close_pri_fd(pri, i);
12339 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
12340 return -1;
12341 }
12342 memset(&si, 0, sizeof(si));
12343 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12344 if (res) {
12345 dahdi_close_pri_fd(pri, i);
12346 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12347 }
12348 if (!si.alarms)
12349 pri->dchanavail[i] |= DCHAN_NOTINALARM;
12350 else
12351 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12352 memset(&bi, 0, sizeof(bi));
12353 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12354 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12355 bi.numbufs = 32;
12356 bi.bufsize = 1024;
12357 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12358 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12359 dahdi_close_pri_fd(pri, i);
12360 return -1;
12361 }
12362 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12363
12364 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12365 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12366 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12367 #ifdef HAVE_PRI_INBANDDISCONNECT
12368 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12369 #endif
12370
12371 if (i)
12372 pri_enslave(pri->dchans[0], pri->dchans[i]);
12373 if (!pri->dchans[i]) {
12374 dahdi_close_pri_fd(pri, i);
12375 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12376 return -1;
12377 }
12378 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12379 pri_set_nsf(pri->dchans[i], pri->nsf);
12380 #ifdef PRI_GETSET_TIMERS
12381 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12382 if (pritimers[x] != 0)
12383 pri_set_timer(pri->dchans[i], x, pritimers[x]);
12384 }
12385 #endif
12386 }
12387
12388 pri->pri = pri->dchans[0];
12389 pri->resetpos = -1;
12390 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12391 for (i = 0; i < NUM_DCHANS; i++) {
12392 if (!pri->dchannels[i])
12393 break;
12394 dahdi_close_pri_fd(pri, i);
12395 }
12396 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12397 return -1;
12398 }
12399 return 0;
12400 }
12401
12402 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
12403 {
12404 int which, span;
12405 char *ret = NULL;
12406
12407 if (pos != rpos)
12408 return ret;
12409
12410 for (which = span = 0; span < NUM_SPANS; span++) {
12411 if (pris[span].pri && ++which > state) {
12412 if (asprintf(&ret, "%d", span + 1) < 0) {
12413 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12414 }
12415 break;
12416 }
12417 }
12418 return ret;
12419 }
12420
12421 static char *complete_span_4(const char *line, const char *word, int pos, int state)
12422 {
12423 return complete_span_helper(line,word,pos,state,3);
12424 }
12425
12426 static char *complete_span_5(const char *line, const char *word, int pos, int state)
12427 {
12428 return complete_span_helper(line,word,pos,state,4);
12429 }
12430
12431 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
12432 {
12433 int myfd;
12434
12435 if (!strncasecmp(argv[1], "set", 3)) {
12436 if (argc < 5)
12437 return RESULT_SHOWUSAGE;
12438
12439 if (ast_strlen_zero(argv[4]))
12440 return RESULT_SHOWUSAGE;
12441
12442 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
12443 if (myfd < 0) {
12444 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
12445 return RESULT_SUCCESS;
12446 }
12447
12448 ast_mutex_lock(&pridebugfdlock);
12449
12450 if (pridebugfd >= 0)
12451 close(pridebugfd);
12452
12453 pridebugfd = myfd;
12454 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
12455
12456 ast_mutex_unlock(&pridebugfdlock);
12457
12458 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
12459 } else {
12460
12461 ast_mutex_lock(&pridebugfdlock);
12462 close(pridebugfd);
12463 pridebugfd = -1;
12464 ast_cli(fd, "PRI debug output to file disabled\n");
12465 ast_mutex_unlock(&pridebugfdlock);
12466 }
12467
12468 return RESULT_SUCCESS;
12469 }
12470
12471 #ifdef HAVE_PRI_VERSION
12472 static int handle_pri_version(int fd, int agc, char *argv[]) {
12473 ast_cli(fd, "libpri version: %s\n", pri_get_version());
12474 return RESULT_SUCCESS;
12475 }
12476 #endif
12477
12478 static int handle_pri_debug(int fd, int argc, char *argv[])
12479 {
12480 int span;
12481 int x;
12482 if (argc < 4) {
12483 return RESULT_SHOWUSAGE;
12484 }
12485 span = atoi(argv[3]);
12486 if ((span < 1) || (span > NUM_SPANS)) {
12487 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
12488 return RESULT_SUCCESS;
12489 }
12490 if (!pris[span-1].pri) {
12491 ast_cli(fd, "No PRI running on span %d\n", span);
12492 return RESULT_SUCCESS;
12493 }
12494 for (x = 0; x < NUM_DCHANS; x++) {
12495 if (pris[span-1].dchans[x])
12496 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12497 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12498 PRI_DEBUG_Q921_STATE);
12499 }
12500 ast_cli(fd, "Enabled debugging on span %d\n", span);
12501 return RESULT_SUCCESS;
12502 }
12503
12504
12505
12506 static int handle_pri_no_debug(int fd, int argc, char *argv[])
12507 {
12508 int span;
12509 int x;
12510 if (argc < 5)
12511 return RESULT_SHOWUSAGE;
12512 span = atoi(argv[4]);
12513 if ((span < 1) || (span > NUM_SPANS)) {
12514 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
12515 return RESULT_SUCCESS;
12516 }
12517 if (!pris[span-1].pri) {
12518 ast_cli(fd, "No PRI running on span %d\n", span);
12519 return RESULT_SUCCESS;
12520 }
12521 for (x = 0; x < NUM_DCHANS; x++) {
12522 if (pris[span-1].dchans[x])
12523 pri_set_debug(pris[span-1].dchans[x], 0);
12524 }
12525 ast_cli(fd, "Disabled debugging on span %d\n", span);
12526 return RESULT_SUCCESS;
12527 }
12528
12529 static int handle_pri_really_debug(int fd, int argc, char *argv[])
12530 {
12531 int span;
12532 int x;
12533 if (argc < 5)
12534 return RESULT_SHOWUSAGE;
12535 span = atoi(argv[4]);
12536 if ((span < 1) || (span > NUM_SPANS)) {
12537 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
12538 return RESULT_SUCCESS;
12539 }
12540 if (!pris[span-1].pri) {
12541 ast_cli(fd, "No PRI running on span %d\n", span);
12542 return RESULT_SUCCESS;
12543 }
12544 for (x = 0; x < NUM_DCHANS; x++) {
12545 if (pris[span-1].dchans[x])
12546 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12547 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12548 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12549 }
12550 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12551 return RESULT_SUCCESS;
12552 }
12553
12554 static void build_status(char *s, size_t len, int status, int active)
12555 {
12556 if (!s || len < 1) {
12557 return;
12558 }
12559 s[0] = '\0';
12560 if (status & DCHAN_PROVISIONED)
12561 strncat(s, "Provisioned, ", len - strlen(s) - 1);
12562 if (!(status & DCHAN_NOTINALARM))
12563 strncat(s, "In Alarm, ", len - strlen(s) - 1);
12564 if (status & DCHAN_UP)
12565 strncat(s, "Up", len - strlen(s) - 1);
12566 else
12567 strncat(s, "Down", len - strlen(s) - 1);
12568 if (active)
12569 strncat(s, ", Active", len - strlen(s) - 1);
12570 else
12571 strncat(s, ", Standby", len - strlen(s) - 1);
12572 s[len - 1] = '\0';
12573 }
12574
12575 static int handle_pri_show_spans(int fd, int argc, char *argv[])
12576 {
12577 int span;
12578 int x;
12579 char status[256];
12580 if (argc != 3)
12581 return RESULT_SHOWUSAGE;
12582
12583 for (span = 0; span < NUM_SPANS; span++) {
12584 if (pris[span].pri) {
12585 for (x = 0; x < NUM_DCHANS; x++) {
12586 if (pris[span].dchannels[x]) {
12587 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12588 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12589 }
12590 }
12591 }
12592 }
12593 return RESULT_SUCCESS;
12594 }
12595
12596 static int handle_pri_show_span(int fd, int argc, char *argv[])
12597 {
12598 int span;
12599 int x;
12600 char status[256];
12601 if (argc < 4)
12602 return RESULT_SHOWUSAGE;
12603 span = atoi(argv[3]);
12604 if ((span < 1) || (span > NUM_SPANS)) {
12605 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
12606 return RESULT_SUCCESS;
12607 }
12608 if (!pris[span-1].pri) {
12609 ast_cli(fd, "No PRI running on span %d\n", span);
12610 return RESULT_SUCCESS;
12611 }
12612 for (x = 0; x < NUM_DCHANS; x++) {
12613 if (pris[span-1].dchannels[x]) {
12614 #ifdef PRI_DUMP_INFO_STR
12615 char *info_str = NULL;
12616 #endif
12617 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12618 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12619 ast_cli(fd, "Status: %s\n", status);
12620 ast_mutex_lock(&pris[span - 1].lock);
12621 #ifdef PRI_DUMP_INFO_STR
12622 info_str = pri_dump_info_str(pris[span-1].pri);
12623 if (info_str) {
12624 ast_cli(fd, "%s", info_str);
12625 free(info_str);
12626 }
12627 #else
12628 pri_dump_info(pris[span-1].pri);
12629 #endif
12630 ast_mutex_unlock(&pris[span - 1].lock);
12631 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12632 }
12633 }
12634 return RESULT_SUCCESS;
12635 }
12636
12637 static int handle_pri_show_debug(int fd, int argc, char *argv[])
12638 {
12639 int x;
12640 int span;
12641 int count=0;
12642 int debug=0;
12643
12644 for (span = 0; span < NUM_SPANS; span++) {
12645 if (pris[span].pri) {
12646 for (x = 0; x < NUM_DCHANS; x++) {
12647 debug = 0;
12648 if (pris[span].dchans[x]) {
12649 debug = pri_get_debug(pris[span].dchans[x]);
12650 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" );
12651 count++;
12652 }
12653 }
12654 }
12655
12656 }
12657 ast_mutex_lock(&pridebugfdlock);
12658 if (pridebugfd >= 0)
12659 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
12660 ast_mutex_unlock(&pridebugfdlock);
12661
12662 if (!count)
12663 ast_cli(fd, "No debug set or no PRI running\n");
12664 return RESULT_SUCCESS;
12665 }
12666
12667 static const char pri_debug_help[] =
12668 "Usage: pri debug span <span>\n"
12669 " Enables debugging on a given PRI span\n";
12670
12671 static const char pri_no_debug_help[] =
12672 "Usage: pri no debug span <span>\n"
12673 " Disables debugging on a given PRI span\n";
12674
12675 static const char pri_really_debug_help[] =
12676 "Usage: pri intensive debug span <span>\n"
12677 " Enables debugging down to the Q.921 level\n";
12678
12679 static const char pri_show_span_help[] =
12680 "Usage: pri show span <span>\n"
12681 " Displays PRI Information on a given PRI span\n";
12682
12683 static const char pri_show_spans_help[] =
12684 "Usage: pri show spans\n"
12685 " Displays PRI Information\n";
12686
12687 static struct ast_cli_entry dahdi_pri_cli[] = {
12688 { { "pri", "debug", "span", NULL },
12689 handle_pri_debug, "Enables PRI debugging on a span",
12690 pri_debug_help, complete_span_4 },
12691
12692 { { "pri", "no", "debug", "span", NULL },
12693 handle_pri_no_debug, "Disables PRI debugging on a span",
12694 pri_no_debug_help, complete_span_5 },
12695
12696 { { "pri", "intense", "debug", "span", NULL },
12697 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
12698 pri_really_debug_help, complete_span_5 },
12699
12700 { { "pri", "show", "spans", NULL },
12701 handle_pri_show_spans, "Displays PRI Information",
12702 pri_show_spans_help },
12703
12704 { { "pri", "show", "span", NULL },
12705 handle_pri_show_span, "Displays PRI Information",
12706 pri_show_span_help, complete_span_4 },
12707
12708 { { "pri", "show", "debug", NULL },
12709 handle_pri_show_debug, "Displays current PRI debug settings" },
12710
12711 { { "pri", "set", "debug", "file", NULL },
12712 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
12713
12714 { { "pri", "unset", "debug", "file", NULL },
12715 handle_pri_set_debug_file, "Ends PRI debug output to file" },
12716
12717 #ifdef HAVE_PRI_VERSION
12718 { { "pri", "show", "version", NULL },
12719 handle_pri_version, "Displays version of libpri" },
12720 #endif
12721 };
12722
12723 #endif
12724
12725 #ifdef HAVE_OPENR2
12726
12727 static int handle_mfcr2_version(int fd, int argc, char *argv[])
12728 {
12729 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
12730 return RESULT_SUCCESS;
12731 }
12732
12733 static int handle_mfcr2_show_variants(int fd, int argc, char *argv[])
12734 {
12735 #define FORMAT "%4s %40s\n"
12736 int numvariants = 0;
12737 int i;
12738 const openr2_variant_entry_t *variants;
12739 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
12740 ast_cli(fd, "Failed to get list of variants.\n");
12741 return RESULT_FAILURE;
12742 }
12743 ast_cli(fd, FORMAT, "Variant Code", "Country");
12744 for (i = 0; i < numvariants; i++) {
12745 ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
12746 }
12747 return RESULT_SUCCESS;
12748 #undef FORMAT
12749 }
12750
12751 static int handle_mfcr2_show_channels(int fd, int argc, char *argv[])
12752 {
12753 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
12754 int filtertype = 0;
12755 int targetnum = 0;
12756 char channo[5];
12757 char anino[5];
12758 char dnisno[5];
12759 struct dahdi_pvt *p;
12760 openr2_context_t *r2context;
12761 openr2_variant_t r2variant;
12762 if (!((argc == 3) || (argc == 5))) {
12763 return RESULT_SHOWUSAGE;
12764 }
12765 if (argc == 5) {
12766 if (!strcasecmp(argv[3], "group")) {
12767 targetnum = atoi(argv[4]);
12768 if ((targetnum < 0) || (targetnum > 63))
12769 return RESULT_SHOWUSAGE;
12770 targetnum = 1 << targetnum;
12771 filtertype = 1;
12772 } else if (!strcasecmp(argv[3], "context")) {
12773 filtertype = 2;
12774 } else {
12775 return RESULT_SHOWUSAGE;
12776 }
12777 }
12778 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
12779 ast_mutex_lock(&iflock);
12780 p = iflist;
12781 while (p) {
12782 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12783 p = p->next;
12784 continue;
12785 }
12786 if (filtertype) {
12787 switch(filtertype) {
12788 case 1:
12789 if (p->group != targetnum) {
12790 p = p->next;
12791 continue;
12792 }
12793 break;
12794 case 2:
12795 if (strcasecmp(p->context, argv[4])) {
12796 p= p->next;
12797 continue;
12798 }
12799 break;
12800 default:
12801 ;
12802 }
12803 }
12804 r2context = openr2_chan_get_context(p->r2chan);
12805 r2variant = openr2_context_get_variant(r2context);
12806 snprintf(channo, sizeof(channo), "%d", p->channel);
12807 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
12808 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
12809 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
12810 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
12811 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
12812 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
12813 p = p->next;
12814 }
12815 ast_mutex_unlock(&iflock);
12816 return RESULT_SUCCESS;
12817 #undef FORMAT
12818 }
12819
12820 static int handle_mfcr2_set_debug(int fd, int argc, char *argv[])
12821 {
12822 struct dahdi_pvt *p = NULL;
12823 int channo = 0;
12824 char *toklevel = NULL;
12825 char *saveptr = NULL;
12826 char *logval = NULL;
12827 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
12828 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
12829 if (argc < 4) {
12830 return RESULT_SHOWUSAGE;
12831 }
12832 channo = (argc == 5) ? atoi(argv[4]) : -1;
12833 logval = ast_strdupa(argv[3]);
12834 toklevel = strtok_r(logval, ",", &saveptr);
12835 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
12836 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
12837 return RESULT_FAILURE;
12838 } else if (OR2_LOG_NOTHING == tmplevel) {
12839 loglevel = tmplevel;
12840 } else {
12841 loglevel |= tmplevel;
12842 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
12843 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
12844 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
12845 continue;
12846 }
12847 loglevel |= tmplevel;
12848 }
12849 }
12850 ast_mutex_lock(&iflock);
12851 p = iflist;
12852 while (p) {
12853 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12854 p = p->next;
12855 continue;
12856 }
12857 if ((channo != -1) && (p->channel != channo )) {
12858 p = p->next;
12859 continue;
12860 }
12861 openr2_chan_set_log_level(p->r2chan, loglevel);
12862 if (channo != -1) {
12863 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
12864 break;
12865 } else {
12866 p = p->next;
12867 }
12868 }
12869 if ((channo != -1) && !p) {
12870 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12871 }
12872 if (channo == -1) {
12873 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
12874 }
12875 ast_mutex_unlock(&iflock);
12876 return RESULT_SUCCESS;
12877 }
12878
12879 static int handle_mfcr2_call_files(int fd, int argc, char *argv[])
12880 {
12881 struct dahdi_pvt *p = NULL;
12882 int channo = 0;
12883 if (argc < 4) {
12884 return RESULT_SHOWUSAGE;
12885 }
12886 channo = (argc == 5) ? atoi(argv[4]) : -1;
12887 ast_mutex_lock(&iflock);
12888 p = iflist;
12889 while (p) {
12890 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12891 p = p->next;
12892 continue;
12893 }
12894 if ((channo != -1) && (p->channel != channo )) {
12895 p = p->next;
12896 continue;
12897 }
12898 if (ast_true(argv[3])) {
12899 openr2_chan_enable_call_files(p->r2chan);
12900 } else {
12901 openr2_chan_disable_call_files(p->r2chan);
12902 }
12903 if (channo != -1) {
12904 if (ast_true(argv[3])) {
12905 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
12906 } else {
12907 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
12908 }
12909 break;
12910 } else {
12911 p = p->next;
12912 }
12913 }
12914 if ((channo != -1) && !p) {
12915 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12916 }
12917 if (channo == -1) {
12918 if (ast_true(argv[3])) {
12919 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
12920 } else {
12921 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
12922 }
12923 }
12924 ast_mutex_unlock(&iflock);
12925 return RESULT_SUCCESS;
12926 }
12927
12928 static int handle_mfcr2_set_idle(int fd, int argc, char *argv[])
12929 {
12930 struct dahdi_pvt *p = NULL;
12931 int channo = 0;
12932 channo = (argc == 4) ? atoi(argv[3]) : -1;
12933 ast_mutex_lock(&iflock);
12934 p = iflist;
12935 while (p) {
12936 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12937 p = p->next;
12938 continue;
12939 }
12940 if ((channo != -1) && (p->channel != channo )) {
12941 p = p->next;
12942 continue;
12943 }
12944 if (!openr2_chan_set_idle(p->r2chan)) {
12945 ast_mutex_lock(&p->lock);
12946 p->mfcr2call = 0;
12947 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
12948 ast_mutex_unlock(&p->lock);
12949 }
12950 if (channo != -1) {
12951 break;
12952 } else {
12953 p = p->next;
12954 }
12955 }
12956 if ((channo != -1) && !p) {
12957 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12958 }
12959 ast_mutex_unlock(&iflock);
12960 return RESULT_SUCCESS;
12961 }
12962
12963 static int handle_mfcr2_set_blocked(int fd, int argc, char *argv[])
12964 {
12965 struct dahdi_pvt *p = NULL;
12966 int channo = 0;
12967 channo = (argc == 4) ? atoi(argv[3]) : -1;
12968 ast_mutex_lock(&iflock);
12969 p = iflist;
12970 while (p) {
12971 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12972 p = p->next;
12973 continue;
12974 }
12975 if ((channo != -1) && (p->channel != channo )) {
12976 p = p->next;
12977 continue;
12978 }
12979 if (!openr2_chan_set_blocked(p->r2chan)) {
12980 ast_mutex_lock(&p->lock);
12981 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
12982 ast_mutex_unlock(&p->lock);
12983 } else {
12984 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
12985 }
12986 if (channo != -1) {
12987 break;
12988 } else {
12989 p = p->next;
12990 }
12991 }
12992 if ((channo != -1) && !p) {
12993 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12994 }
12995 ast_mutex_unlock(&iflock);
12996 return RESULT_SUCCESS;
12997 }
12998
12999 static const char dahdi_r2_version_help[] =
13000 "Usage: mfcr2 show version\n"
13001 " Shows the version of the OpenR2 library being used.\n";
13002 static const char dahdi_r2_variants_help[] =
13003 "Usage: mfcr2 show variants\n"
13004 " Show supported MFC/R2 variants.\n";
13005 static const char dahdi_r2_showchannels_help[] =
13006 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
13007 " Shows the zap channels configured with MFC/R2 signaling.\n";
13008 static const char dahdi_r2_setdebug_help[] =
13009 "Usage: mfcr2 set debug <loglevel> <channel>\n"
13010 " Set a new logging level for the specified channel.\n"
13011 " If no channel is specified the logging level will be applied to all channels.\n";
13012 static const char dahdi_r2_callfiles_help[] =
13013 "Usage: mfcr2 call files [on|off] <channel>\n"
13014 " Enable call files creation on the specified channel.\n"
13015 " If no channel is specified call files creation policy will be applied to all channels.\n";
13016 static const char dahdi_r2_setidle_help[] =
13017 "Usage: mfcr2 set idle <channel>\n"
13018 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
13019 " Force the given channel into IDLE state.\n"
13020 " If no channel is specified, all channels will be set to IDLE.\n";
13021 static const char dahdi_r2_setblocked_help[] =
13022 "Usage: mfcr2 set blocked <channel>\n"
13023 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
13024 " Force the given channel into BLOCKED state.\n"
13025 " If no channel is specified, all channels will be set to BLOCKED.\n";
13026
13027 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
13028 { { "mfcr2", "show", "version", NULL },
13029 handle_mfcr2_version, "Show OpenR2 library version",
13030 dahdi_r2_version_help },
13031
13032 { { "mfcr2", "show", "variants", NULL },
13033 handle_mfcr2_show_variants, "Show supported MFC/R2 variants",
13034 dahdi_r2_variants_help },
13035
13036 { { "mfcr2", "show", "channels", NULL },
13037 handle_mfcr2_show_channels, "Show MFC/R2 channels",
13038 dahdi_r2_showchannels_help },
13039
13040 { { "mfcr2", "set", "debug", NULL },
13041 handle_mfcr2_set_debug, "Set MFC/R2 channel logging level",
13042 dahdi_r2_setdebug_help },
13043
13044 { { "mfcr2", "call", "files", NULL },
13045 handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files",
13046 dahdi_r2_callfiles_help },
13047
13048 { { "mfcr2", "set", "idle", NULL },
13049 handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE",
13050 dahdi_r2_setidle_help },
13051
13052 { { "mfcr2", "set", "blocked", NULL },
13053 handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED",
13054 dahdi_r2_setblocked_help }
13055
13056 };
13057
13058 #endif
13059
13060 static int dahdi_destroy_channel(int fd, int argc, char **argv)
13061 {
13062 int channel;
13063
13064 if (argc != 4)
13065 return RESULT_SHOWUSAGE;
13066
13067 channel = atoi(argv[3]);
13068
13069 return dahdi_destroy_channel_bynum(channel);
13070 }
13071
13072 static void dahdi_softhangup_all(void)
13073 {
13074 struct dahdi_pvt *p;
13075 retry:
13076 ast_mutex_lock(&iflock);
13077 for (p = iflist; p; p = p->next) {
13078 ast_mutex_lock(&p->lock);
13079 if (p->owner && !p->restartpending) {
13080 if (ast_channel_trylock(p->owner)) {
13081 if (option_debug > 2)
13082 ast_verbose("Avoiding deadlock\n");
13083
13084 ast_mutex_unlock(&p->lock);
13085 ast_mutex_unlock(&iflock);
13086 goto retry;
13087 }
13088 if (option_debug > 2)
13089 ast_verbose("Softhanging up on %s\n", p->owner->name);
13090 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
13091 p->restartpending = 1;
13092 num_restart_pending++;
13093 ast_channel_unlock(p->owner);
13094 }
13095 ast_mutex_unlock(&p->lock);
13096 }
13097 ast_mutex_unlock(&iflock);
13098 }
13099
13100 static int setup_dahdi(int reload);
13101 static int dahdi_restart(void)
13102 {
13103
13104 #ifdef HAVE_OPENR2
13105 int r;
13106 #endif
13107
13108 #if defined(HAVE_PRI)
13109 int i, j;
13110 #endif
13111 int cancel_code;
13112 struct dahdi_pvt *p;
13113
13114 ast_mutex_lock(&restart_lock);
13115
13116 if (option_verbose)
13117 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
13118 dahdi_softhangup_all();
13119 if (option_verbose > 3)
13120 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
13121
13122 #ifdef HAVE_OPENR2
13123 for (r = 0; r < NUM_SPANS; r++) {
13124 if (r2links[r].master != AST_PTHREADT_NULL) {
13125 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
13126 pthread_cancel(r2links[r].master);
13127 pthread_join(r2links[r].master, NULL);
13128 openr2_context_delete(r2links[r].protocol_context);
13129 }
13130 }
13131 init_mfcr2_globals();
13132 #endif
13133
13134 #if defined(HAVE_PRI)
13135 for (i = 0; i < NUM_SPANS; i++) {
13136 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
13137 cancel_code = pthread_cancel(pris[i].master);
13138 pthread_kill(pris[i].master, SIGURG);
13139 if (option_debug > 3)
13140 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
13141 pthread_join(pris[i].master, NULL);
13142 if (option_debug > 3)
13143 ast_verbose("Joined thread of span %d\n", i);
13144 }
13145 }
13146 #endif
13147
13148 ast_mutex_lock(&monlock);
13149 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
13150 cancel_code = pthread_cancel(monitor_thread);
13151 pthread_kill(monitor_thread, SIGURG);
13152 if (option_debug > 3)
13153 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
13154 pthread_join(monitor_thread, NULL);
13155 if (option_debug > 3)
13156 ast_verbose("Joined monitor thread\n");
13157 }
13158 monitor_thread = AST_PTHREADT_NULL;
13159
13160 ast_mutex_lock(&ss_thread_lock);
13161 while (ss_thread_count > 0) {
13162 int x = DAHDI_FLASH;
13163 if (option_debug > 2)
13164 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
13165
13166 for (p = iflist; p; p = p->next) {
13167 if (p->owner)
13168 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13169 }
13170 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
13171 }
13172
13173
13174 dahdi_softhangup_all();
13175 if (option_verbose > 3)
13176 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
13177 destroy_all_channels();
13178 if (option_debug)
13179 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
13180
13181 ast_mutex_unlock(&monlock);
13182
13183 #ifdef HAVE_PRI
13184 for (i = 0; i < NUM_SPANS; i++) {
13185 for (j = 0; j < NUM_DCHANS; j++)
13186 dahdi_close_pri_fd(&(pris[i]), j);
13187 }
13188
13189 memset(pris, 0, sizeof(pris));
13190 for (i = 0; i < NUM_SPANS; i++) {
13191 ast_mutex_init(&pris[i].lock);
13192 pris[i].offset = -1;
13193 pris[i].master = AST_PTHREADT_NULL;
13194 for (j = 0; j < NUM_DCHANS; j++)
13195 pris[i].fds[j] = -1;
13196 }
13197 pri_set_error(dahdi_pri_error);
13198 pri_set_message(dahdi_pri_message);
13199 #endif
13200
13201 if (setup_dahdi(2) != 0) {
13202 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
13203 ast_mutex_unlock(&ss_thread_lock);
13204 return 1;
13205 }
13206 ast_mutex_unlock(&ss_thread_lock);
13207 ast_mutex_unlock(&restart_lock);
13208 return 0;
13209 }
13210
13211 static int dahdi_restart_cmd(int fd, int argc, char **argv)
13212 {
13213 if (argc != 2) {
13214 return RESULT_SHOWUSAGE;
13215 }
13216
13217 if (dahdi_restart() != 0)
13218 return RESULT_FAILURE;
13219 return RESULT_SUCCESS;
13220 }
13221
13222 static int dahdi_show_channels(int fd, int argc, char **argv)
13223 {
13224 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
13225 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
13226 struct dahdi_pvt *tmp = NULL;
13227 char tmps[20] = "";
13228 ast_mutex_t *lock;
13229 struct dahdi_pvt *start;
13230 #ifdef HAVE_PRI
13231 int trunkgroup;
13232 struct dahdi_pri *pri = NULL;
13233 int x;
13234 #endif
13235
13236 lock = &iflock;
13237 start = iflist;
13238
13239 #ifdef HAVE_PRI
13240 if (argc == 4) {
13241 if ((trunkgroup = atoi(argv[3])) < 1)
13242 return RESULT_SHOWUSAGE;
13243 for (x = 0; x < NUM_SPANS; x++) {
13244 if (pris[x].trunkgroup == trunkgroup) {
13245 pri = pris + x;
13246 break;
13247 }
13248 }
13249 if (pri) {
13250 start = pri->crvs;
13251 lock = &pri->lock;
13252 } else {
13253 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13254 return RESULT_FAILURE;
13255 }
13256 } else
13257 #endif
13258 if (argc != 3)
13259 return RESULT_SHOWUSAGE;
13260
13261 ast_mutex_lock(lock);
13262 #ifdef HAVE_PRI
13263 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
13264 #else
13265 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
13266 #endif
13267
13268 tmp = start;
13269 while (tmp) {
13270 if (tmp->channel > 0) {
13271 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
13272 } else
13273 ast_copy_string(tmps, "pseudo", sizeof(tmps));
13274 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
13275 tmp = tmp->next;
13276 }
13277 ast_mutex_unlock(lock);
13278 return RESULT_SUCCESS;
13279 #undef FORMAT
13280 #undef FORMAT2
13281 }
13282
13283 static int dahdi_show_channel(int fd, int argc, char **argv)
13284 {
13285 int channel;
13286 struct dahdi_pvt *tmp = NULL;
13287 struct dahdi_confinfo ci;
13288 struct dahdi_params ps;
13289 int x;
13290 ast_mutex_t *lock;
13291 struct dahdi_pvt *start;
13292 #ifdef HAVE_PRI
13293 char *c;
13294 int trunkgroup;
13295 struct dahdi_pri *pri=NULL;
13296 #endif
13297
13298 lock = &iflock;
13299 start = iflist;
13300
13301 if (argc != 4)
13302 return RESULT_SHOWUSAGE;
13303 #ifdef HAVE_PRI
13304 if ((c = strchr(argv[3], ':'))) {
13305 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
13306 return RESULT_SHOWUSAGE;
13307 if ((trunkgroup < 1) || (channel < 1))
13308 return RESULT_SHOWUSAGE;
13309 for (x = 0; x < NUM_SPANS; x++) {
13310 if (pris[x].trunkgroup == trunkgroup) {
13311 pri = pris + x;
13312 break;
13313 }
13314 }
13315 if (pri) {
13316 start = pri->crvs;
13317 lock = &pri->lock;
13318 } else {
13319 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13320 return RESULT_FAILURE;
13321 }
13322 } else
13323 #endif
13324 channel = atoi(argv[3]);
13325
13326 ast_mutex_lock(lock);
13327 tmp = start;
13328 while (tmp) {
13329 if (tmp->channel == channel) {
13330 #ifdef HAVE_PRI
13331 if (pri)
13332 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
13333 else
13334 #endif
13335 ast_cli(fd, "Channel: %d\n", tmp->channel);
13336 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
13337 ast_cli(fd, "Span: %d\n", tmp->span);
13338 ast_cli(fd, "Extension: %s\n", tmp->exten);
13339 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
13340 ast_cli(fd, "Context: %s\n", tmp->context);
13341 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
13342 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
13343 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
13344 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
13345 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
13346 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
13347 ast_cli(fd, "Radio: %d\n", tmp->radio);
13348 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
13349 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)" : "");
13350 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)" : "");
13351 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)" : "");
13352 ast_cli(fd, "Confno: %d\n", tmp->confno);
13353 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
13354 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
13355 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
13356 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
13357 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
13358 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
13359 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
13360 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
13361 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
13362 if (tmp->master)
13363 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
13364 for (x = 0; x < MAX_SLAVES; x++) {
13365 if (tmp->slaves[x])
13366 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
13367 }
13368
13369 #ifdef HAVE_OPENR2
13370 if (tmp->mfcr2) {
13371 char calldir[OR2_MAX_PATH];
13372 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
13373 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
13374 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
13375 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
13376 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
13377 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
13378 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
13379 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
13380 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
13381 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
13382 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
13383 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
13384 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13385 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
13386 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
13387 #endif
13388 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
13389 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
13390 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
13391 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
13392 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
13393 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
13394 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
13395 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
13396 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
13397 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
13398 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
13399 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
13400 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
13401 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
13402 }
13403 #endif
13404
13405 #ifdef HAVE_PRI
13406 if (tmp->pri) {
13407 ast_cli(fd, "PRI Flags: ");
13408 if (tmp->resetting)
13409 ast_cli(fd, "Resetting ");
13410 if (tmp->call)
13411 ast_cli(fd, "Call ");
13412 if (tmp->bearer)
13413 ast_cli(fd, "Bearer ");
13414 if (tmp->allocated) {
13415 ast_cli(fd, "Allocated ");
13416 }
13417 ast_cli(fd, "\n");
13418 if (tmp->logicalspan)
13419 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
13420 else
13421 ast_cli(fd, "PRI Logical Span: Implicit\n");
13422 }
13423 #endif
13424 memset(&ci, 0, sizeof(ci));
13425 ps.channo = tmp->channel;
13426 if (tmp->subs[SUB_REAL].dfd > -1) {
13427 memset(&ci, 0, sizeof(ci));
13428 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
13429 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
13430 }
13431 #ifdef DAHDI_GETCONFMUTE
13432 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
13433 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
13434 }
13435 #endif
13436 memset(&ps, 0, sizeof(ps));
13437 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
13438 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
13439 } else {
13440 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
13441 }
13442 }
13443 if (ISTRUNK(tmp)) {
13444 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
13445 if (!ast_strlen_zero(progzone))
13446 ast_cli(fd, "Progress Zone: %s\n", progzone);
13447 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
13448 if(tmp->busydetect) {
13449 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
13450 if(tmp->busytonelength > 0) {
13451 ast_cli(fd, "Busy Pattern:\n");
13452 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
13453 if (tmp->busyquietlength > 0)
13454 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
13455 else
13456 ast_cli(fd, " -- Detect Tone Only\n");
13457 if(tmp->busyfuzziness > 0)
13458 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
13459 }
13460 }
13461 }
13462 ast_mutex_unlock(lock);
13463 return RESULT_SUCCESS;
13464 }
13465 tmp = tmp->next;
13466 }
13467
13468 ast_cli(fd, "Unable to find given channel %d\n", channel);
13469 ast_mutex_unlock(lock);
13470 return RESULT_FAILURE;
13471 }
13472
13473 static char dahdi_show_cadences_usage[] =
13474 "Usage: dahdi show cadences\n"
13475 " Shows all cadences currently defined\n";
13476
13477 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
13478 {
13479 int i, j;
13480 for (i = 0; i < num_cadence; i++) {
13481 char output[1024];
13482 char tmp[16], tmp2[64];
13483 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
13484 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
13485
13486 for (j = 0; j < 16; j++) {
13487 if (cadences[i].ringcadence[j] == 0)
13488 break;
13489 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
13490 if (cidrings[i] * 2 - 1 == j)
13491 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
13492 else
13493 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
13494 if (j != 0)
13495 strncat(output, ",", sizeof(output) - strlen(output) - 1);
13496 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
13497 }
13498 ast_cli(fd,"%s\n",output);
13499 }
13500 return 0;
13501 }
13502
13503
13504 static int dahdi_show_status(int fd, int argc, char *argv[]) {
13505 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
13506 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
13507
13508 int span;
13509 int res;
13510 char alarms[50];
13511
13512 int ctl;
13513 struct dahdi_spaninfo s;
13514
13515 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
13516 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
13517 ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
13518 return RESULT_FAILURE;
13519 }
13520 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
13521
13522 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13523 s.spanno = span;
13524 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13525 if (res) {
13526 continue;
13527 }
13528 alarms[0] = '\0';
13529 if (s.alarms > 0) {
13530 if (s.alarms & DAHDI_ALARM_BLUE)
13531 strcat(alarms, "BLU/");
13532 if (s.alarms & DAHDI_ALARM_YELLOW)
13533 strcat(alarms, "YEL/");
13534 if (s.alarms & DAHDI_ALARM_RED)
13535 strcat(alarms, "RED/");
13536 if (s.alarms & DAHDI_ALARM_LOOPBACK)
13537 strcat(alarms, "LB/");
13538 if (s.alarms & DAHDI_ALARM_RECOVER)
13539 strcat(alarms, "REC/");
13540 if (s.alarms & DAHDI_ALARM_NOTOPEN)
13541 strcat(alarms, "NOP/");
13542 if (!strlen(alarms))
13543 strcat(alarms, "UUU/");
13544 if (strlen(alarms)) {
13545
13546 alarms[strlen(alarms) - 1] = '\0';
13547 }
13548 } else {
13549 if (s.numchans)
13550 strcpy(alarms, "OK");
13551 else
13552 strcpy(alarms, "UNCONFIGURED");
13553 }
13554
13555 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
13556 }
13557 close(ctl);
13558
13559 return RESULT_SUCCESS;
13560 #undef FORMAT
13561 #undef FORMAT2
13562 }
13563
13564 static char show_channels_usage[] =
13565 "Usage: dahdi show channels\n"
13566 " Shows a list of available channels\n";
13567
13568 static char show_channel_usage[] =
13569 "Usage: dahdi show channel <chan num>\n"
13570 " Detailed information about a given channel\n";
13571
13572 static char dahdi_show_status_usage[] =
13573 "Usage: dahdi show status\n"
13574 " Shows a list of DAHDI cards with status\n";
13575
13576 static char destroy_channel_usage[] =
13577 "Usage: dahdi destroy channel <chan num>\n"
13578 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
13579
13580 static char dahdi_restart_usage[] =
13581 "Usage: dahdi restart\n"
13582 " Restarts the DAHDI channels: destroys them all and then\n"
13583 " re-reads them from chan_dahdi.conf.\n"
13584 " Note that this will STOP any running CALL on DAHDI channels.\n"
13585 "";
13586
13587 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
13588 { "zap", "show", "cadences", NULL },
13589 handle_dahdi_show_cadences, NULL,
13590 NULL };
13591
13592 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
13593 { "zap", "show", "channels", NULL },
13594 dahdi_show_channels, NULL,
13595 NULL };
13596
13597 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
13598 { "zap", "show", "channel", NULL },
13599 dahdi_show_channel, NULL,
13600 NULL };
13601
13602 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
13603 { "zap", "destroy", "channel", NULL },
13604 dahdi_destroy_channel, NULL,
13605 NULL };
13606
13607 static struct ast_cli_entry cli_zap_restart_deprecated = {
13608 { "zap", "restart", NULL },
13609 dahdi_restart_cmd, NULL,
13610 NULL };
13611
13612 static struct ast_cli_entry cli_zap_show_status_deprecated = {
13613 { "zap", "show", "status", NULL },
13614 dahdi_show_status, NULL,
13615 NULL };
13616
13617 static struct ast_cli_entry dahdi_cli[] = {
13618 { { "dahdi", "show", "cadences", NULL },
13619 handle_dahdi_show_cadences, "List cadences",
13620 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
13621
13622 { { "dahdi", "show", "channels", NULL},
13623 dahdi_show_channels, "Show active DAHDI channels",
13624 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
13625
13626 { { "dahdi", "show", "channel", NULL},
13627 dahdi_show_channel, "Show information on a channel",
13628 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
13629
13630 { { "dahdi", "destroy", "channel", NULL},
13631 dahdi_destroy_channel, "Destroy a channel",
13632 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
13633
13634 { { "dahdi", "restart", NULL},
13635 dahdi_restart_cmd, "Fully restart DAHDI channels",
13636 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
13637
13638 { { "dahdi", "show", "status", NULL},
13639 dahdi_show_status, "Show all DAHDI cards status",
13640 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
13641 };
13642
13643 #define TRANSFER 0
13644 #define HANGUP 1
13645
13646 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13647 {
13648 if (p) {
13649 switch (mode) {
13650 case TRANSFER:
13651 p->fake_event = DAHDI_EVENT_WINKFLASH;
13652 break;
13653 case HANGUP:
13654 p->fake_event = DAHDI_EVENT_ONHOOK;
13655 break;
13656 default:
13657 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
13658 }
13659 }
13660 return 0;
13661 }
13662 static struct dahdi_pvt *find_channel(int channel)
13663 {
13664 struct dahdi_pvt *p = iflist;
13665 while (p) {
13666 if (p->channel == channel) {
13667 break;
13668 }
13669 p = p->next;
13670 }
13671 return p;
13672 }
13673
13674 #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)
13675 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
13676
13677 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
13678 {
13679 struct dahdi_pvt *p = NULL;
13680 const char *channel = local_astman_header(m, "Channel", zap_mode);
13681
13682 if (ast_strlen_zero(channel)) {
13683 astman_send_error(s, m, "No channel specified");
13684 return 0;
13685 }
13686 if (!(p = find_channel(atoi(channel)))) {
13687 astman_send_error(s, m, "No such channel");
13688 return 0;
13689 }
13690 p->dnd = dnd;
13691 local_astman_ack(s, m, "DND", zap_mode);
13692
13693 return 0;
13694 }
13695
13696 static int zap_action_dndon(struct mansession *s, const struct message *m)
13697 {
13698 return __action_dnd(s, m, 1, 1);
13699 }
13700
13701 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
13702 {
13703 return __action_dnd(s, m, 0, 1);
13704 }
13705
13706 static int zap_action_dndoff(struct mansession *s, const struct message *m)
13707 {
13708 return __action_dnd(s, m, 1, 0);
13709 }
13710
13711 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
13712 {
13713 return __action_dnd(s, m, 0, 0);
13714 }
13715
13716 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
13717 {
13718 struct dahdi_pvt *p = NULL;
13719 const char *channel = local_astman_header(m, "Channel", zap_mode);
13720
13721 if (ast_strlen_zero(channel)) {
13722 astman_send_error(s, m, "No channel specified");
13723 return 0;
13724 }
13725 if (!(p = find_channel(atoi(channel)))) {
13726 astman_send_error(s, m, "No such channel");
13727 return 0;
13728 }
13729 dahdi_fake_event(p,TRANSFER);
13730 local_astman_ack(s, m, "Transfer", zap_mode);
13731
13732 return 0;
13733 }
13734
13735 static int zap_action_transfer(struct mansession *s, const struct message *m)
13736 {
13737 return __action_transfer(s, m, 1);
13738 }
13739
13740 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
13741 {
13742 return __action_transfer(s, m, 0);
13743 }
13744
13745 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
13746 {
13747 struct dahdi_pvt *p = NULL;
13748 const char *channel = local_astman_header(m, "Channel", zap_mode);
13749
13750 if (ast_strlen_zero(channel)) {
13751 astman_send_error(s, m, "No channel specified");
13752 return 0;
13753 }
13754 if (!(p = find_channel(atoi(channel)))) {
13755 astman_send_error(s, m, "No such channel");
13756 return 0;
13757 }
13758 dahdi_fake_event(p, HANGUP);
13759 local_astman_ack(s, m, "Hangup", zap_mode);
13760 return 0;
13761 }
13762
13763 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
13764 {
13765 return __action_transferhangup(s, m, 1);
13766 }
13767
13768 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
13769 {
13770 return __action_transferhangup(s, m, 0);
13771 }
13772
13773 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
13774 {
13775 struct dahdi_pvt *p = NULL;
13776 const char *channel = local_astman_header(m, "Channel", zap_mode);
13777 const char *number = astman_get_header(m, "Number");
13778 int i;
13779
13780 if (ast_strlen_zero(channel)) {
13781 astman_send_error(s, m, "No channel specified");
13782 return 0;
13783 }
13784 if (ast_strlen_zero(number)) {
13785 astman_send_error(s, m, "No number specified");
13786 return 0;
13787 }
13788 if (!(p = find_channel(atoi(channel)))) {
13789 astman_send_error(s, m, "No such channel");
13790 return 0;
13791 }
13792 if (!p->owner) {
13793 astman_send_error(s, m, "Channel does not have an owner");
13794 return 0;
13795 }
13796 for (i = 0; i < strlen(number); i++) {
13797 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13798
13799 dahdi_queue_frame(p, &f, NULL);
13800 }
13801 local_astman_ack(s, m, "DialOffHook", zap_mode);
13802
13803 return 0;
13804 }
13805
13806 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
13807 {
13808 return __action_dialoffhook(s, m, 1);
13809 }
13810
13811 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
13812 {
13813 return __action_dialoffhook(s, m, 0);
13814 }
13815
13816 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
13817 {
13818 struct dahdi_pvt *tmp = NULL;
13819 const char *id = astman_get_header(m, "ActionID");
13820 char idText[256] = "";
13821
13822 local_astman_ack(s, m, " channel status will follow", zap_mode);
13823 if (!ast_strlen_zero(id))
13824 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
13825
13826 ast_mutex_lock(&iflock);
13827
13828 tmp = iflist;
13829 while (tmp) {
13830 if (tmp->channel > 0) {
13831 int alarm = get_alarms(tmp);
13832 astman_append(s,
13833 "Event: %sShowChannels\r\n"
13834 "Channel: %d\r\n"
13835 "Signalling: %s\r\n"
13836 "Context: %s\r\n"
13837 "DND: %s\r\n"
13838 "Alarm: %s\r\n"
13839 "%s"
13840 "\r\n",
13841 dahdi_chan_name,
13842 tmp->channel, sig2str(tmp->sig), tmp->context,
13843 tmp->dnd ? "Enabled" : "Disabled",
13844 alarm2str(alarm), idText);
13845 }
13846
13847 tmp = tmp->next;
13848 }
13849
13850 ast_mutex_unlock(&iflock);
13851
13852 astman_append(s,
13853 "Event: %sShowChannelsComplete\r\n"
13854 "%s"
13855 "\r\n",
13856 dahdi_chan_name,
13857 idText);
13858 return 0;
13859 }
13860
13861 static int zap_action_showchannels(struct mansession *s, const struct message *m)
13862 {
13863 return __action_showchannels(s, m, 1);
13864 }
13865
13866 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
13867 {
13868 return __action_showchannels(s, m, 0);
13869 }
13870
13871 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
13872 {
13873 if (dahdi_restart() != 0) {
13874 if (zap_mode) {
13875 astman_send_error(s, m, "Failed to restart Zap");
13876 } else {
13877 astman_send_error(s, m, "Failed to restart DAHDI");
13878 }
13879 return 1;
13880 }
13881 local_astman_ack(s, m, "Restart: Success", zap_mode);
13882 return 0;
13883 }
13884
13885 static int zap_action_restart(struct mansession *s, const struct message *m)
13886 {
13887 return __action_restart(s, m, 1);
13888 }
13889
13890 static int dahdi_action_restart(struct mansession *s, const struct message *m)
13891 {
13892 return __action_restart(s, m, 0);
13893 }
13894
13895 #define local_astman_unregister(a) do { \
13896 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13897 ast_manager_unregister("DAHDI" a); \
13898 } \
13899 ast_manager_unregister("Zap" a); \
13900 } while (0)
13901
13902 static int __unload_module(void)
13903 {
13904 struct dahdi_pvt *p;
13905
13906 #ifdef HAVE_OPENR2
13907 int r;
13908 #endif
13909
13910 #ifdef HAVE_PRI
13911 int i, j;
13912 for (i = 0; i < NUM_SPANS; i++) {
13913 if (pris[i].master != AST_PTHREADT_NULL)
13914 pthread_cancel(pris[i].master);
13915 }
13916 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13917
13918 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13919 ast_unregister_application(dahdi_send_keypad_facility_app);
13920 }
13921 ast_unregister_application(zap_send_keypad_facility_app);
13922 #endif
13923
13924 #ifdef HAVE_OPENR2
13925 for (r = 0; r < NUM_SPANS; r++) {
13926 if (r2links[r].master != AST_PTHREADT_NULL) {
13927 pthread_cancel(r2links[r].master);
13928 pthread_join(r2links[r].master, NULL);
13929 }
13930 }
13931 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
13932 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13933 ast_unregister_application(dahdi_accept_r2_call_app);
13934 }
13935 ast_unregister_application(zap_accept_r2_call_app);
13936 #endif
13937
13938 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13939 local_astman_unregister("DialOffHook");
13940 local_astman_unregister("Hangup");
13941 local_astman_unregister("Transfer");
13942 local_astman_unregister("DNDoff");
13943 local_astman_unregister("DNDon");
13944 local_astman_unregister("ShowChannels");
13945 local_astman_unregister("Restart");
13946 ast_channel_unregister(chan_tech);
13947 ast_mutex_lock(&iflock);
13948
13949 p = iflist;
13950 while (p) {
13951 if (p->owner)
13952 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
13953 p = p->next;
13954 }
13955 ast_mutex_unlock(&iflock);
13956 ast_mutex_lock(&monlock);
13957 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
13958 pthread_cancel(monitor_thread);
13959 pthread_kill(monitor_thread, SIGURG);
13960 pthread_join(monitor_thread, NULL);
13961 }
13962 monitor_thread = AST_PTHREADT_STOP;
13963 ast_mutex_unlock(&monlock);
13964
13965 destroy_all_channels();
13966 #ifdef HAVE_PRI
13967 for (i = 0; i < NUM_SPANS; i++) {
13968 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
13969 pthread_join(pris[i].master, NULL);
13970 for (j = 0; j < NUM_DCHANS; j++) {
13971 dahdi_close_pri_fd(&(pris[i]), j);
13972 }
13973 }
13974 #endif
13975
13976 #ifdef HAVE_OPENR2
13977 for (r = 0; r < NUM_SPANS; r++) {
13978 if (r2links[r].protocol_context) {
13979 openr2_context_delete(r2links[r].protocol_context);
13980 }
13981 }
13982 #endif
13983
13984 ast_cond_destroy(&ss_thread_complete);
13985 return 0;
13986 }
13987
13988 static int unload_module(void)
13989 {
13990 #ifdef HAVE_PRI
13991 int y;
13992 for (y = 0; y < NUM_SPANS; y++)
13993 ast_mutex_destroy(&pris[y].lock);
13994 #endif
13995 return __unload_module();
13996 }
13997
13998 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
13999 {
14000 char *c, *chan;
14001 int x, start, finish;
14002 struct dahdi_pvt *tmp;
14003 #ifdef HAVE_PRI
14004 struct dahdi_pri *pri;
14005 int trunkgroup, y;
14006 #endif
14007
14008 if ((reload == 0) && (conf->chan.sig < 0)) {
14009 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14010 return -1;
14011 }
14012
14013 c = ast_strdupa(value);
14014
14015 #ifdef HAVE_PRI
14016 pri = NULL;
14017 if (iscrv) {
14018 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14019 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
14020 return -1;
14021 }
14022 if (trunkgroup < 1) {
14023 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
14024 return -1;
14025 }
14026 c += y;
14027 for (y = 0; y < NUM_SPANS; y++) {
14028 if (pris[y].trunkgroup == trunkgroup) {
14029 pri = pris + y;
14030 break;
14031 }
14032 }
14033 if (!pri) {
14034 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
14035 return -1;
14036 }
14037 }
14038 #endif
14039
14040 while ((chan = strsep(&c, ","))) {
14041 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14042
14043 } else if (sscanf(chan, "%30d", &start)) {
14044
14045 finish = start;
14046 } else if (!strcasecmp(chan, "pseudo")) {
14047 finish = start = CHAN_PSEUDO;
14048 if (found_pseudo)
14049 *found_pseudo = 1;
14050 } else {
14051 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14052 return -1;
14053 }
14054 if (finish < start) {
14055 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14056 x = finish;
14057 finish = start;
14058 start = x;
14059 }
14060
14061 for (x = start; x <= finish; x++) {
14062 #ifdef HAVE_PRI
14063 tmp = mkintf(x, conf, pri, reload);
14064 #else
14065 tmp = mkintf(x, conf, NULL, reload);
14066 #endif
14067
14068 if (tmp) {
14069 if (option_verbose > 2) {
14070 #ifdef HAVE_PRI
14071 if (pri)
14072 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14073 else
14074 #endif
14075 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14076 }
14077 } else {
14078 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14079 (reload == 1) ? "reconfigure" : "register", value);
14080 return -1;
14081 }
14082 }
14083
14084 #ifdef HAVE_OPENR2
14085 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
14086 mfcr2_cur_context_index++;
14087 }
14088 #endif
14089
14090 }
14091
14092 return 0;
14093 }
14094
14095
14096
14097 #define MAX_CHANLIST_LEN 80
14098 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
14099 {
14100 struct dahdi_pvt *tmp;
14101 int y;
14102 int found_pseudo = 0;
14103 char dahdichan[MAX_CHANLIST_LEN] = {};
14104
14105 for (; v; v = v->next) {
14106 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14107 continue;
14108
14109
14110 if (!strcasecmp(v->name, "channel")
14111 #ifdef HAVE_PRI
14112 || !strcasecmp(v->name, "crv")
14113 #endif
14114 ) {
14115 int iscrv;
14116 if (skipchannels)
14117 continue;
14118 iscrv = !strcasecmp(v->name, "crv");
14119 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14120 return -1;
14121 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
14122 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14123 if (v->name[0] == 'z' || v->name[0] == 'Z') {
14124 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
14125 }
14126 } else if (!strcasecmp(v->name, "buffers")) {
14127 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
14128 ast_log(LOG_WARNING, "Using default buffer policy.\n");
14129 confp->chan.buf_no = numbufs;
14130 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14131 }
14132 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14133 if (ast_true(v->value))
14134 confp->chan.usedistinctiveringdetection = 1;
14135 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14136 if (ast_true(v->value))
14137 distinctiveringaftercid = 1;
14138 } else if (!strcasecmp(v->name, "dring1context")) {
14139 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
14140 } else if (!strcasecmp(v->name, "dring2context")) {
14141 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
14142 } else if (!strcasecmp(v->name, "dring3context")) {
14143 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
14144 } else if (!strcasecmp(v->name, "dring1")) {
14145 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
14146 } else if (!strcasecmp(v->name, "dring2")) {
14147 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
14148 } else if (!strcasecmp(v->name, "dring3")) {
14149 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
14150 } else if (!strcasecmp(v->name, "usecallerid")) {
14151 confp->chan.use_callerid = ast_true(v->value);
14152 } else if (!strcasecmp(v->name, "cidsignalling")) {
14153 if (!strcasecmp(v->value, "bell"))
14154 confp->chan.cid_signalling = CID_SIG_BELL;
14155 else if (!strcasecmp(v->value, "v23"))
14156 confp->chan.cid_signalling = CID_SIG_V23;
14157 else if (!strcasecmp(v->value, "dtmf"))
14158 confp->chan.cid_signalling = CID_SIG_DTMF;
14159 else if (!strcasecmp(v->value, "smdi"))
14160 confp->chan.cid_signalling = CID_SIG_SMDI;
14161 else if (!strcasecmp(v->value, "v23_jp"))
14162 confp->chan.cid_signalling = CID_SIG_V23_JP;
14163 else if (ast_true(v->value))
14164 confp->chan.cid_signalling = CID_SIG_BELL;
14165 } else if (!strcasecmp(v->name, "cidstart")) {
14166 if (!strcasecmp(v->value, "ring"))
14167 confp->chan.cid_start = CID_START_RING;
14168 else if (!strcasecmp(v->value, "polarity"))
14169 confp->chan.cid_start = CID_START_POLARITY;
14170 else if (!strcasecmp(v->value, "dtmf"))
14171 confp->chan.cid_start = CID_START_DTMF_NOALERT;
14172 else if (ast_true(v->value))
14173 confp->chan.cid_start = CID_START_RING;
14174 } else if (!strcasecmp(v->name, "threewaycalling")) {
14175 confp->chan.threewaycalling = ast_true(v->value);
14176 } else if (!strcasecmp(v->name, "cancallforward")) {
14177 confp->chan.cancallforward = ast_true(v->value);
14178 } else if (!strcasecmp(v->name, "relaxdtmf")) {
14179 if (ast_true(v->value))
14180 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14181 else
14182 confp->chan.dtmfrelax = 0;
14183 } else if (!strcasecmp(v->name, "mailbox")) {
14184 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14185 } else if (!strcasecmp(v->name, "hasvoicemail")) {
14186 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14187 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14188 }
14189 } else if (!strcasecmp(v->name, "adsi")) {
14190 confp->chan.adsi = ast_true(v->value);
14191 } else if (!strcasecmp(v->name, "usesmdi")) {
14192 confp->chan.use_smdi = ast_true(v->value);
14193 } else if (!strcasecmp(v->name, "smdiport")) {
14194 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14195 } else if (!strcasecmp(v->name, "transfer")) {
14196 confp->chan.transfer = ast_true(v->value);
14197 } else if (!strcasecmp(v->name, "canpark")) {
14198 confp->chan.canpark = ast_true(v->value);
14199 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14200 confp->chan.echocanbridged = ast_true(v->value);
14201 } else if (!strcasecmp(v->name, "busydetect")) {
14202 confp->chan.busydetect = ast_true(v->value);
14203 } else if (!strcasecmp(v->name, "busycount")) {
14204 confp->chan.busycount = atoi(v->value);
14205 } else if (!strcasecmp(v->name, "silencethreshold")) {
14206 confp->chan.silencethreshold = atoi(v->value);
14207 } else if (!strcasecmp(v->name, "busycompare")) {
14208 confp->chan.busycompare = ast_true(v->value);
14209 } else if (!strcasecmp(v->name, "busypattern")) {
14210 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
14211 if (count == 1)
14212 confp->chan.busyquietlength = 0;
14213 else if (count < 1)
14214 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
14215 } else if (!strcasecmp(v->name, "busyfuzziness")) {
14216 confp->chan.busyfuzziness = atoi(v->value);
14217 } else if (!strcasecmp(v->name, "callprogress")) {
14218 if (ast_true(v->value))
14219 confp->chan.callprogress |= 1;
14220 else
14221 confp->chan.callprogress &= ~1;
14222 } else if (!strcasecmp(v->name, "faxdetect")) {
14223 if (!strcasecmp(v->value, "incoming")) {
14224 confp->chan.callprogress |= 4;
14225 confp->chan.callprogress &= ~2;
14226 } else if (!strcasecmp(v->value, "outgoing")) {
14227 confp->chan.callprogress &= ~4;
14228 confp->chan.callprogress |= 2;
14229 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14230 confp->chan.callprogress |= 6;
14231 else
14232 confp->chan.callprogress &= ~6;
14233 } else if (!strcasecmp(v->name, "echocancel")) {
14234 if (!ast_strlen_zero(v->value)) {
14235 y = atoi(v->value);
14236 } else
14237 y = 0;
14238 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
14239 confp->chan.echocancel = y;
14240 else {
14241 confp->chan.echocancel = ast_true(v->value);
14242 if (confp->chan.echocancel)
14243 confp->chan.echocancel=128;
14244 }
14245 } else if (!strcasecmp(v->name, "echotraining")) {
14246 if (sscanf(v->value, "%30d", &y) == 1) {
14247 if ((y < 10) || (y > 4000)) {
14248 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
14249 } else {
14250 confp->chan.echotraining = y;
14251 }
14252 } else if (ast_true(v->value)) {
14253 confp->chan.echotraining = 400;
14254 } else
14255 confp->chan.echotraining = 0;
14256 } else if (!strcasecmp(v->name, "hidecallerid")) {
14257 confp->chan.hidecallerid = ast_true(v->value);
14258 } else if (!strcasecmp(v->name, "hidecalleridname")) {
14259 confp->chan.hidecalleridname = ast_true(v->value);
14260 } else if (!strcasecmp(v->name, "pulsedial")) {
14261 confp->chan.pulse = ast_true(v->value);
14262 } else if (!strcasecmp(v->name, "callreturn")) {
14263 confp->chan.callreturn = ast_true(v->value);
14264 } else if (!strcasecmp(v->name, "callwaiting")) {
14265 confp->chan.callwaiting = ast_true(v->value);
14266 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14267 confp->chan.callwaitingcallerid = ast_true(v->value);
14268 } else if (!strcasecmp(v->name, "context")) {
14269 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14270 } else if (!strcasecmp(v->name, "language")) {
14271 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14272 } else if (!strcasecmp(v->name, "progzone")) {
14273 ast_copy_string(progzone, v->value, sizeof(progzone));
14274 } else if (!strcasecmp(v->name, "mohinterpret")
14275 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14276 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14277 } else if (!strcasecmp(v->name, "mohsuggest")) {
14278 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14279 } else if (!strcasecmp(v->name, "stripmsd")) {
14280 confp->chan.stripmsd = atoi(v->value);
14281 } else if (!strcasecmp(v->name, "jitterbuffers")) {
14282 numbufs = atoi(v->value);
14283 } else if (!strcasecmp(v->name, "group")) {
14284 confp->chan.group = ast_get_group(v->value);
14285 } else if (!strcasecmp(v->name, "callgroup")) {
14286 confp->chan.callgroup = ast_get_group(v->value);
14287 } else if (!strcasecmp(v->name, "pickupgroup")) {
14288 confp->chan.pickupgroup = ast_get_group(v->value);
14289 } else if (!strcasecmp(v->name, "immediate")) {
14290 confp->chan.immediate = ast_true(v->value);
14291 } else if (!strcasecmp(v->name, "transfertobusy")) {
14292 confp->chan.transfertobusy = ast_true(v->value);
14293 } else if (!strcasecmp(v->name, "rxgain")) {
14294 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
14295 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
14296 }
14297 } else if (!strcasecmp(v->name, "txgain")) {
14298 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
14299 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
14300 }
14301 } else if (!strcasecmp(v->name, "tonezone")) {
14302 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
14303 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
14304 }
14305 } else if (!strcasecmp(v->name, "callerid")) {
14306 if (!strcasecmp(v->value, "asreceived")) {
14307 confp->chan.cid_num[0] = '\0';
14308 confp->chan.cid_name[0] = '\0';
14309 } else {
14310 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14311 }
14312 } else if (!strcasecmp(v->name, "fullname")) {
14313 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14314 } else if (!strcasecmp(v->name, "cid_number")) {
14315 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14316 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
14317 confp->chan.dahditrcallerid = ast_true(v->value);
14318 if (strstr(v->name, "zap")) {
14319 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
14320 }
14321 } else if (!strcasecmp(v->name, "restrictcid")) {
14322 confp->chan.restrictcid = ast_true(v->value);
14323 } else if (!strcasecmp(v->name, "usecallingpres")) {
14324 confp->chan.use_callingpres = ast_true(v->value);
14325 } else if (!strcasecmp(v->name, "accountcode")) {
14326 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14327 } else if (!strcasecmp(v->name, "amaflags")) {
14328 y = ast_cdr_amaflags2int(v->value);
14329 if (y < 0)
14330 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
14331 else
14332 confp->chan.amaflags = y;
14333 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14334 confp->chan.polarityonanswerdelay = atoi(v->value);
14335 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14336 confp->chan.answeronpolarityswitch = ast_true(v->value);
14337 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14338 confp->chan.hanguponpolarityswitch = ast_true(v->value);
14339 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14340 confp->chan.sendcalleridafter = atoi(v->value);
14341 } else if (reload != 1) {
14342 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14343 confp->chan.outsigmod = -1;
14344 if (!strcasecmp(v->value, "em")) {
14345 confp->chan.sig = SIG_EM;
14346 } else if (!strcasecmp(v->value, "em_e1")) {
14347 confp->chan.sig = SIG_EM_E1;
14348 } else if (!strcasecmp(v->value, "em_w")) {
14349 confp->chan.sig = SIG_EMWINK;
14350 confp->chan.radio = 0;
14351 } else if (!strcasecmp(v->value, "fxs_ls")) {
14352 confp->chan.sig = SIG_FXSLS;
14353 confp->chan.radio = 0;
14354 } else if (!strcasecmp(v->value, "fxs_gs")) {
14355 confp->chan.sig = SIG_FXSGS;
14356 confp->chan.radio = 0;
14357 } else if (!strcasecmp(v->value, "fxs_ks")) {
14358 confp->chan.sig = SIG_FXSKS;
14359 confp->chan.radio = 0;
14360 } else if (!strcasecmp(v->value, "fxo_ls")) {
14361 confp->chan.sig = SIG_FXOLS;
14362 confp->chan.radio = 0;
14363 } else if (!strcasecmp(v->value, "fxo_gs")) {
14364 confp->chan.sig = SIG_FXOGS;
14365 confp->chan.radio = 0;
14366 } else if (!strcasecmp(v->value, "fxo_ks")) {
14367 confp->chan.sig = SIG_FXOKS;
14368 confp->chan.radio = 0;
14369 } else if (!strcasecmp(v->value, "fxs_rx")) {
14370 confp->chan.sig = SIG_FXSKS;
14371 confp->chan.radio = 1;
14372 } else if (!strcasecmp(v->value, "fxo_rx")) {
14373 confp->chan.sig = SIG_FXOLS;
14374 confp->chan.radio = 1;
14375 } else if (!strcasecmp(v->value, "fxs_tx")) {
14376 confp->chan.sig = SIG_FXSLS;
14377 confp->chan.radio = 1;
14378 } else if (!strcasecmp(v->value, "fxo_tx")) {
14379 confp->chan.sig = SIG_FXOGS;
14380 confp->chan.radio = 1;
14381 } else if (!strcasecmp(v->value, "em_rx")) {
14382 confp->chan.sig = SIG_EM;
14383 confp->chan.radio = 1;
14384 } else if (!strcasecmp(v->value, "em_tx")) {
14385 confp->chan.sig = SIG_EM;
14386 confp->chan.radio = 1;
14387 } else if (!strcasecmp(v->value, "em_rxtx")) {
14388 confp->chan.sig = SIG_EM;
14389 confp->chan.radio = 2;
14390 } else if (!strcasecmp(v->value, "em_txrx")) {
14391 confp->chan.sig = SIG_EM;
14392 confp->chan.radio = 2;
14393 } else if (!strcasecmp(v->value, "sf")) {
14394 confp->chan.sig = SIG_SF;
14395 confp->chan.radio = 0;
14396 } else if (!strcasecmp(v->value, "sf_w")) {
14397 confp->chan.sig = SIG_SFWINK;
14398 confp->chan.radio = 0;
14399 } else if (!strcasecmp(v->value, "sf_featd")) {
14400 confp->chan.sig = SIG_FEATD;
14401 confp->chan.radio = 0;
14402 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14403 confp->chan.sig = SIG_FEATDMF;
14404 confp->chan.radio = 0;
14405 } else if (!strcasecmp(v->value, "sf_featb")) {
14406 confp->chan.sig = SIG_SF_FEATB;
14407 confp->chan.radio = 0;
14408 } else if (!strcasecmp(v->value, "sf")) {
14409 confp->chan.sig = SIG_SF;
14410 confp->chan.radio = 0;
14411 } else if (!strcasecmp(v->value, "sf_rx")) {
14412 confp->chan.sig = SIG_SF;
14413 confp->chan.radio = 1;
14414 } else if (!strcasecmp(v->value, "sf_tx")) {
14415 confp->chan.sig = SIG_SF;
14416 confp->chan.radio = 1;
14417 } else if (!strcasecmp(v->value, "sf_rxtx")) {
14418 confp->chan.sig = SIG_SF;
14419 confp->chan.radio = 2;
14420 } else if (!strcasecmp(v->value, "sf_txrx")) {
14421 confp->chan.sig = SIG_SF;
14422 confp->chan.radio = 2;
14423 } else if (!strcasecmp(v->value, "featd")) {
14424 confp->chan.sig = SIG_FEATD;
14425 confp->chan.radio = 0;
14426 } else if (!strcasecmp(v->value, "featdmf")) {
14427 confp->chan.sig = SIG_FEATDMF;
14428 confp->chan.radio = 0;
14429 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14430 confp->chan.sig = SIG_FEATDMF_TA;
14431 confp->chan.radio = 0;
14432 } else if (!strcasecmp(v->value, "e911")) {
14433 confp->chan.sig = SIG_E911;
14434 confp->chan.radio = 0;
14435 } else if (!strcasecmp(v->value, "fgccama")) {
14436 confp->chan.sig = SIG_FGC_CAMA;
14437 confp->chan.radio = 0;
14438 } else if (!strcasecmp(v->value, "fgccamamf")) {
14439 confp->chan.sig = SIG_FGC_CAMAMF;
14440 confp->chan.radio = 0;
14441 } else if (!strcasecmp(v->value, "featb")) {
14442 confp->chan.sig = SIG_FEATB;
14443 confp->chan.radio = 0;
14444 #ifdef HAVE_OPENR2
14445 } else if (!strcasecmp(v->value, "mfcr2")) {
14446 confp->chan.sig = SIG_MFCR2;
14447 #endif
14448
14449 #ifdef HAVE_PRI
14450 } else if (!strcasecmp(v->value, "pri_net")) {
14451 confp->chan.radio = 0;
14452 confp->chan.sig = SIG_PRI;
14453 confp->pri.nodetype = PRI_NETWORK;
14454 } else if (!strcasecmp(v->value, "pri_cpe")) {
14455 confp->chan.sig = SIG_PRI;
14456 confp->chan.radio = 0;
14457 confp->pri.nodetype = PRI_CPE;
14458 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14459 confp->chan.sig = SIG_GR303FXOKS;
14460 confp->chan.radio = 0;
14461 confp->pri.nodetype = PRI_NETWORK;
14462 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14463 confp->chan.sig = SIG_GR303FXSKS;
14464 confp->chan.radio = 0;
14465 confp->pri.nodetype = PRI_CPE;
14466 #endif
14467 } else {
14468 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
14469 }
14470 } else if (!strcasecmp(v->name, "outsignalling")) {
14471 if (!strcasecmp(v->value, "em")) {
14472 confp->chan.outsigmod = SIG_EM;
14473 } else if (!strcasecmp(v->value, "em_e1")) {
14474 confp->chan.outsigmod = SIG_EM_E1;
14475 } else if (!strcasecmp(v->value, "em_w")) {
14476 confp->chan.outsigmod = SIG_EMWINK;
14477 } else if (!strcasecmp(v->value, "sf")) {
14478 confp->chan.outsigmod = SIG_SF;
14479 } else if (!strcasecmp(v->value, "sf_w")) {
14480 confp->chan.outsigmod = SIG_SFWINK;
14481 } else if (!strcasecmp(v->value, "sf_featd")) {
14482 confp->chan.outsigmod = SIG_FEATD;
14483 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14484 confp->chan.outsigmod = SIG_FEATDMF;
14485 } else if (!strcasecmp(v->value, "sf_featb")) {
14486 confp->chan.outsigmod = SIG_SF_FEATB;
14487 } else if (!strcasecmp(v->value, "sf")) {
14488 confp->chan.outsigmod = SIG_SF;
14489 } else if (!strcasecmp(v->value, "featd")) {
14490 confp->chan.outsigmod = SIG_FEATD;
14491 } else if (!strcasecmp(v->value, "featdmf")) {
14492 confp->chan.outsigmod = SIG_FEATDMF;
14493 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14494 confp->chan.outsigmod = SIG_FEATDMF_TA;
14495 } else if (!strcasecmp(v->value, "e911")) {
14496 confp->chan.outsigmod = SIG_E911;
14497 } else if (!strcasecmp(v->value, "fgccama")) {
14498 confp->chan.outsigmod = SIG_FGC_CAMA;
14499 } else if (!strcasecmp(v->value, "fgccamamf")) {
14500 confp->chan.outsigmod = SIG_FGC_CAMAMF;
14501 } else if (!strcasecmp(v->value, "featb")) {
14502 confp->chan.outsigmod = SIG_FEATB;
14503 } else {
14504 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
14505 }
14506 #ifdef HAVE_PRI
14507 } else if (!strcasecmp(v->name, "pridialplan")) {
14508 if (!strcasecmp(v->value, "national")) {
14509 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14510 } else if (!strcasecmp(v->value, "unknown")) {
14511 confp->pri.dialplan = PRI_UNKNOWN + 1;
14512 } else if (!strcasecmp(v->value, "private")) {
14513 confp->pri.dialplan = PRI_PRIVATE + 1;
14514 } else if (!strcasecmp(v->value, "international")) {
14515 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14516 } else if (!strcasecmp(v->value, "local")) {
14517 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14518 } else if (!strcasecmp(v->value, "dynamic")) {
14519 confp->pri.dialplan = -1;
14520 } else {
14521 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14522 }
14523 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14524 if (!strcasecmp(v->value, "national")) {
14525 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14526 } else if (!strcasecmp(v->value, "unknown")) {
14527 confp->pri.localdialplan = PRI_UNKNOWN + 1;
14528 } else if (!strcasecmp(v->value, "private")) {
14529 confp->pri.localdialplan = PRI_PRIVATE + 1;
14530 } else if (!strcasecmp(v->value, "international")) {
14531 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14532 } else if (!strcasecmp(v->value, "local")) {
14533 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14534 } else if (!strcasecmp(v->value, "dynamic")) {
14535 confp->pri.localdialplan = -1;
14536 } else {
14537 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14538 }
14539 } else if (!strcasecmp(v->name, "switchtype")) {
14540 if (!strcasecmp(v->value, "national"))
14541 confp->pri.switchtype = PRI_SWITCH_NI2;
14542 else if (!strcasecmp(v->value, "ni1"))
14543 confp->pri.switchtype = PRI_SWITCH_NI1;
14544 else if (!strcasecmp(v->value, "dms100"))
14545 confp->pri.switchtype = PRI_SWITCH_DMS100;
14546 else if (!strcasecmp(v->value, "4ess"))
14547 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14548 else if (!strcasecmp(v->value, "5ess"))
14549 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14550 else if (!strcasecmp(v->value, "euroisdn"))
14551 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14552 else if (!strcasecmp(v->value, "qsig"))
14553 confp->pri.switchtype = PRI_SWITCH_QSIG;
14554 else {
14555 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
14556 return -1;
14557 }
14558 } else if (!strcasecmp(v->name, "nsf")) {
14559 if (!strcasecmp(v->value, "sdn"))
14560 confp->pri.nsf = PRI_NSF_SDN;
14561 else if (!strcasecmp(v->value, "megacom"))
14562 confp->pri.nsf = PRI_NSF_MEGACOM;
14563 else if (!strcasecmp(v->value, "tollfreemegacom"))
14564 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14565 else if (!strcasecmp(v->value, "accunet"))
14566 confp->pri.nsf = PRI_NSF_ACCUNET;
14567 else if (!strcasecmp(v->value, "none"))
14568 confp->pri.nsf = PRI_NSF_NONE;
14569 else {
14570 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
14571 confp->pri.nsf = PRI_NSF_NONE;
14572 }
14573 } else if (!strcasecmp(v->name, "priindication")) {
14574 if (!strcasecmp(v->value, "outofband"))
14575 confp->chan.priindication_oob = 1;
14576 else if (!strcasecmp(v->value, "inband"))
14577 confp->chan.priindication_oob = 0;
14578 else
14579 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
14580 v->value, v->lineno);
14581 } else if (!strcasecmp(v->name, "priexclusive")) {
14582 confp->chan.priexclusive = ast_true(v->value);
14583 } else if (!strcasecmp(v->name, "internationalprefix")) {
14584 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14585 } else if (!strcasecmp(v->name, "nationalprefix")) {
14586 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14587 } else if (!strcasecmp(v->name, "localprefix")) {
14588 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14589 } else if (!strcasecmp(v->name, "privateprefix")) {
14590 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14591 } else if (!strcasecmp(v->name, "unknownprefix")) {
14592 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14593 } else if (!strcasecmp(v->name, "resetinterval")) {
14594 if (!strcasecmp(v->value, "never"))
14595 confp->pri.resetinterval = -1;
14596 else if (atoi(v->value) >= 60)
14597 confp->pri.resetinterval = atoi(v->value);
14598 else
14599 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
14600 v->value, v->lineno);
14601 } else if (!strcasecmp(v->name, "minunused")) {
14602 confp->pri.minunused = atoi(v->value);
14603 } else if (!strcasecmp(v->name, "minidle")) {
14604 confp->pri.minidle = atoi(v->value);
14605 } else if (!strcasecmp(v->name, "idleext")) {
14606 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14607 } else if (!strcasecmp(v->name, "idledial")) {
14608 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14609 } else if (!strcasecmp(v->name, "overlapdial")) {
14610 if (ast_true(v->value)) {
14611 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14612 } else if (!strcasecmp(v->value, "incoming")) {
14613 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14614 } else if (!strcasecmp(v->value, "outgoing")) {
14615 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14616 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14617 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14618 } else {
14619 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14620 }
14621 #ifdef HAVE_PRI_INBANDDISCONNECT
14622 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14623 confp->pri.inbanddisconnect = ast_true(v->value);
14624 #endif
14625 } else if (!strcasecmp(v->name, "pritimer")) {
14626 #ifdef PRI_GETSET_TIMERS
14627 char tmp[20];
14628 char *timerc;
14629 char *c;
14630 int timer;
14631 int timeridx;
14632
14633 ast_copy_string(tmp, v->value, sizeof(tmp));
14634 c = tmp;
14635 timerc = strsep(&c, ",");
14636 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
14637 timeridx = pri_timer2idx(timerc);
14638 timer = atoi(c);
14639 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
14640 ast_log(LOG_WARNING,
14641 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
14642 v->lineno);
14643 } else if (!timer) {
14644 ast_log(LOG_WARNING,
14645 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
14646 c, timerc, v->lineno);
14647 } else {
14648 pritimers[timeridx] = timer;
14649 }
14650 } else {
14651 ast_log(LOG_WARNING,
14652 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
14653 v->value, v->lineno);
14654 }
14655 #endif
14656 } else if (!strcasecmp(v->name, "facilityenable")) {
14657 confp->pri.facilityenable = ast_true(v->value);
14658 #endif
14659
14660 #ifdef HAVE_OPENR2
14661 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
14662 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
14663 ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", mfcr2_cur_r2proto_file);
14664 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
14665 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
14666 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
14667 mfcr2_cur_variant = openr2_proto_get_variant(v->value);
14668 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
14669 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
14670 }
14671 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
14672 mfcr2_cur_mfback_timeout = atoi(v->value);
14673 if (!mfcr2_cur_mfback_timeout) {
14674 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
14675 mfcr2_cur_mfback_timeout = -1;
14676 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
14677 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
14678 }
14679 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
14680 mfcr2_cur_metering_pulse_timeout = atoi(v->value);
14681 if (mfcr2_cur_metering_pulse_timeout > 500) {
14682 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
14683 }
14684 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
14685 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
14686 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
14687 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
14688 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
14689 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
14690 mfcr2_cur_dtmf_time_on = atoi(v->value);
14691 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
14692 mfcr2_cur_dtmf_time_off = atoi(v->value);
14693 #endif
14694 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
14695 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
14696 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
14697 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
14698 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
14699 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
14700 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
14701 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
14702 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
14703 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
14704 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
14705 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
14706 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
14707 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
14708 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
14709 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
14710 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
14711 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
14712 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
14713 mfcr2_cur_max_ani = atoi(v->value);
14714 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
14715 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
14716 }
14717 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
14718 mfcr2_cur_max_dnis = atoi(v->value);
14719 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
14720 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
14721 }
14722 } else if (!strcasecmp(v->name, "mfcr2_category")) {
14723 mfcr2_cur_category = openr2_proto_get_category(v->value);
14724 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
14725 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
14726 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
14727 v->value, v->lineno);
14728 }
14729 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
14730 openr2_log_level_t tmplevel;
14731 char *toklevel = NULL;
14732 char *saveptr = NULL;
14733 char *logval = ast_strdupa(v->value);
14734 toklevel = strtok_r(logval, ",", &saveptr);
14735 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14736 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
14737 } else if (OR2_LOG_NOTHING == tmplevel) {
14738 mfcr2_cur_loglevel = tmplevel;
14739 } else {
14740 mfcr2_cur_loglevel |= tmplevel;
14741 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14742 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14743 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
14744 continue;
14745 }
14746 mfcr2_cur_loglevel |= tmplevel;
14747 }
14748 }
14749 #endif
14750
14751 } else if (!strcasecmp(v->name, "cadence")) {
14752
14753 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14754 int i;
14755 struct dahdi_ring_cadence new_cadence;
14756 int cid_location = -1;
14757 int firstcadencepos = 0;
14758 char original_args[80];
14759 int cadence_is_ok = 1;
14760
14761 ast_copy_string(original_args, v->value, sizeof(original_args));
14762
14763 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]);
14764
14765
14766 if (element_count % 2 == 1) {
14767 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
14768 cadence_is_ok = 0;
14769 }
14770
14771
14772 for (i = 0; i < element_count; i++) {
14773 if (c[i] == 0) {
14774 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
14775 cadence_is_ok = 0;
14776 break;
14777 } else if (c[i] < 0) {
14778 if (i % 2 == 1) {
14779
14780 if (cid_location == -1) {
14781 cid_location = i;
14782 c[i] *= -1;
14783 } else {
14784 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
14785 cadence_is_ok = 0;
14786 break;
14787 }
14788 } else {
14789 if (firstcadencepos == 0) {
14790 firstcadencepos = i;
14791
14792 } else {
14793 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
14794 cadence_is_ok = 0;
14795 break;
14796 }
14797 }
14798 }
14799 }
14800
14801
14802 for (i = 0; i < 16; i++) {
14803 new_cadence.ringcadence[i] = c[i];
14804 }
14805
14806 if (cadence_is_ok) {
14807
14808 if (element_count < 2) {
14809 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
14810 } else {
14811 if (cid_location == -1) {
14812
14813 cid_location = 1;
14814 } else {
14815
14816 cid_location = (cid_location + 1) / 2;
14817 }
14818
14819 if (!user_has_defined_cadences++)
14820
14821 num_cadence = 0;
14822 if ((num_cadence+1) >= NUM_CADENCE_MAX)
14823 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
14824 else {
14825 cadences[num_cadence] = new_cadence;
14826 cidrings[num_cadence++] = cid_location;
14827 if (option_verbose > 2)
14828 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
14829 }
14830 }
14831 }
14832 } else if (!strcasecmp(v->name, "ringtimeout")) {
14833 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
14834 } else if (!strcasecmp(v->name, "prewink")) {
14835 confp->timing.prewinktime = atoi(v->value);
14836 } else if (!strcasecmp(v->name, "preflash")) {
14837 confp->timing.preflashtime = atoi(v->value);
14838 } else if (!strcasecmp(v->name, "wink")) {
14839 confp->timing.winktime = atoi(v->value);
14840 } else if (!strcasecmp(v->name, "flash")) {
14841 confp->timing.flashtime = atoi(v->value);
14842 } else if (!strcasecmp(v->name, "start")) {
14843 confp->timing.starttime = atoi(v->value);
14844 } else if (!strcasecmp(v->name, "rxwink")) {
14845 confp->timing.rxwinktime = atoi(v->value);
14846 } else if (!strcasecmp(v->name, "rxflash")) {
14847 confp->timing.rxflashtime = atoi(v->value);
14848 } else if (!strcasecmp(v->name, "debounce")) {
14849 confp->timing.debouncetime = atoi(v->value);
14850 } else if (!strcasecmp(v->name, "toneduration")) {
14851 int toneduration;
14852 int ctlfd;
14853 int res;
14854 struct dahdi_dialparams dps;
14855
14856 ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
14857
14858 if (ctlfd == -1) {
14859 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
14860 return -1;
14861 }
14862
14863 toneduration = atoi(v->value);
14864 if (toneduration > -1) {
14865 memset(&dps, 0, sizeof(dps));
14866
14867 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
14868 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
14869 if (res < 0) {
14870 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
14871 close(ctlfd);
14872 return -1;
14873 }
14874 }
14875 close(ctlfd);
14876 } else if (!strcasecmp(v->name, "defaultcic")) {
14877 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
14878 } else if (!strcasecmp(v->name, "defaultozz")) {
14879 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
14880 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
14881 dtmfcid_level = atoi(v->value);
14882 }
14883 } else if (!skipchannels)
14884 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
14885 }
14886 if (dahdichan[0]) {
14887
14888
14889 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
14890 return -1;
14891 }
14892 }
14893
14894
14895 if (!found_pseudo && reload != 1) {
14896
14897
14898
14899
14900 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
14901
14902 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
14903
14904 if (tmp) {
14905 if (option_verbose > 2)
14906 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
14907 } else {
14908 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
14909 }
14910 }
14911 return 0;
14912 }
14913
14914 static int setup_dahdi(int reload)
14915 {
14916 struct ast_config *cfg;
14917 struct ast_variable *v;
14918 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
14919 int res;
14920
14921 #ifdef HAVE_PRI
14922 char *c;
14923 int spanno;
14924 int i, x;
14925 int logicalspan;
14926 int trunkgroup;
14927 int dchannels[NUM_DCHANS];
14928 #endif
14929
14930 #ifdef HAVE_ZAPTEL
14931 int load_from_zapata_conf = 1;
14932 #else
14933 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
14934 #endif
14935
14936 if (load_from_zapata_conf) {
14937 if (!(cfg = ast_config_load("zapata.conf"))) {
14938 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
14939 return 0;
14940 }
14941 } else {
14942 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
14943 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
14944 return 0;
14945 }
14946 }
14947
14948
14949 ast_mutex_lock(&iflock);
14950 #ifdef HAVE_PRI
14951 if (reload != 1) {
14952
14953 v = ast_variable_browse(cfg, "trunkgroups");
14954 while (v) {
14955 if (!strcasecmp(v->name, "trunkgroup")) {
14956 trunkgroup = atoi(v->value);
14957 if (trunkgroup > 0) {
14958 if ((c = strchr(v->value, ','))) {
14959 i = 0;
14960 memset(dchannels, 0, sizeof(dchannels));
14961 while (c && (i < NUM_DCHANS)) {
14962 dchannels[i] = atoi(c + 1);
14963 if (dchannels[i] < 0) {
14964 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);
14965 } else
14966 i++;
14967 c = strchr(c + 1, ',');
14968 }
14969 if (i) {
14970 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
14971 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);
14972 } else if (option_verbose > 1)
14973 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");
14974 } else
14975 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14976 } else
14977 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14978 } else
14979 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
14980 } else if (!strcasecmp(v->name, "spanmap")) {
14981 spanno = atoi(v->value);
14982 if (spanno > 0) {
14983 if ((c = strchr(v->value, ','))) {
14984 trunkgroup = atoi(c + 1);
14985 if (trunkgroup > 0) {
14986 if ((c = strchr(c + 1, ',')))
14987 logicalspan = atoi(c + 1);
14988 else
14989 logicalspan = 0;
14990 if (logicalspan >= 0) {
14991 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
14992 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14993 } else if (option_verbose > 1)
14994 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14995 } else
14996 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);
14997 } else
14998 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
14999 } else
15000 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15001 } else
15002 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15003 } else {
15004 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15005 }
15006 v = v->next;
15007 }
15008 }
15009 #endif
15010
15011
15012 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
15013
15014 v = ast_variable_browse(cfg, "channels");
15015 res = process_dahdi(&conf, "", v, reload, 0);
15016 ast_mutex_unlock(&iflock);
15017 ast_config_destroy(cfg);
15018 if (res)
15019 return res;
15020 cfg = ast_config_load("users.conf");
15021 if (cfg) {
15022 char *cat;
15023
15024
15025 conf = dahdi_chan_conf_default();
15026 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
15027 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15028 if (!strcasecmp(cat, "general"))
15029 continue;
15030 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
15031 struct dahdi_chan_conf sect_conf;
15032 memcpy(§_conf, &conf, sizeof(sect_conf));
15033
15034 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
15035 }
15036 }
15037 ast_config_destroy(cfg);
15038 }
15039 #ifdef HAVE_PRI
15040 if (reload != 1) {
15041 for (x = 0; x < NUM_SPANS; x++) {
15042 if (pris[x].pvts[0]) {
15043 if (start_pri(pris + x)) {
15044 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15045 return -1;
15046 } else if (option_verbose > 1)
15047 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
15048 }
15049 }
15050 }
15051 #endif
15052
15053 #ifdef HAVE_OPENR2
15054 if (reload != 1) {
15055 int x;
15056 for (x = 0; x < NUM_SPANS; x++) {
15057 if (r2links[x].protocol_context) {
15058 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
15059 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
15060 return -1;
15061 } else {
15062 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
15063 }
15064 }
15065 }
15066 }
15067 #endif
15068
15069
15070 restart_monitor();
15071 return 0;
15072 }
15073
15074 #define local_astman_register(a, b, c, d) do { \
15075 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
15076 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
15077 } \
15078 ast_manager_register("Zap" a, b, zap_ ## c, d); \
15079 } while (0)
15080
15081 static int load_module(void)
15082 {
15083 int res;
15084
15085 #ifdef HAVE_PRI
15086 int y,i;
15087 memset(pris, 0, sizeof(pris));
15088 for (y = 0; y < NUM_SPANS; y++) {
15089 ast_mutex_init(&pris[y].lock);
15090 pris[y].offset = -1;
15091 pris[y].master = AST_PTHREADT_NULL;
15092 for (i = 0; i < NUM_DCHANS; i++)
15093 pris[y].fds[i] = -1;
15094 }
15095 pri_set_error(dahdi_pri_error);
15096 pri_set_message(dahdi_pri_message);
15097 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
15098 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15099 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15100 }
15101 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
15102 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
15103 #endif
15104
15105 #ifdef HAVE_OPENR2
15106 init_mfcr2_globals();
15107 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
15108 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
15109 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
15110 }
15111 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
15112 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
15113 #endif
15114
15115 if ((res = setup_dahdi(0))) {
15116 return AST_MODULE_LOAD_DECLINE;
15117 }
15118 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
15119 chan_tech = &dahdi_tech;
15120 } else {
15121 chan_tech = &zap_tech;
15122 }
15123 if (ast_channel_register(chan_tech)) {
15124 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
15125 __unload_module();
15126 return -1;
15127 }
15128 #ifdef HAVE_PRI
15129 ast_string_field_init(&inuse, 16);
15130 ast_string_field_set(&inuse, name, "GR-303InUse");
15131 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
15132 #endif
15133
15134 #ifdef HAVE_OPENR2
15135 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
15136 #endif
15137
15138 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
15139
15140 memset(round_robin, 0, sizeof(round_robin));
15141 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
15142 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
15143 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
15144 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
15145 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
15146 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
15147 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
15148
15149 ast_cond_init(&ss_thread_complete, NULL);
15150
15151 return res;
15152 }
15153
15154 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15155 {
15156 #define END_SILENCE_LEN 400
15157 #define HEADER_MS 50
15158 #define TRAILER_MS 5
15159 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15160 #define ASCII_BYTES_PER_CHAR 80
15161
15162 unsigned char *buf,*mybuf;
15163 struct dahdi_pvt *p = c->tech_pvt;
15164 struct pollfd fds[1];
15165 int size,res,fd,len,x;
15166 int bytes=0;
15167
15168 float cr = 1.0;
15169 float ci = 0.0;
15170 float scont = 0.0;
15171 int index;
15172
15173 index = dahdi_get_index(c, p, 0);
15174 if (index < 0) {
15175 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
15176 return -1;
15177 }
15178 if (!text[0]) return(0);
15179 if ((!p->tdd) && (!p->mate)) return(0);
15180 if (p->mate)
15181 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15182 else
15183 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15184 if (!buf)
15185 return -1;
15186 mybuf = buf;
15187 if (p->mate) {
15188 int codec = AST_LAW(p);
15189 for (x = 0; x < HEADER_MS; x++) {
15190 PUT_CLID_MARKMS;
15191 }
15192
15193 for (x = 0; text[x]; x++) {
15194 PUT_CLID(text[x]);
15195 }
15196 for (x = 0; x < TRAILER_MS; x++) {
15197 PUT_CLID_MARKMS;
15198 }
15199 len = bytes;
15200 buf = mybuf;
15201 } else {
15202 len = tdd_generate(p->tdd, buf, text);
15203 if (len < 1) {
15204 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15205 free(mybuf);
15206 return -1;
15207 }
15208 }
15209 memset(buf + len, 0x7f, END_SILENCE_LEN);
15210 len += END_SILENCE_LEN;
15211 fd = p->subs[index].dfd;
15212 while (len) {
15213 if (ast_check_hangup(c)) {
15214 free(mybuf);
15215 return -1;
15216 }
15217 size = len;
15218 if (size > READ_SIZE)
15219 size = READ_SIZE;
15220 fds[0].fd = fd;
15221 fds[0].events = POLLOUT | POLLPRI;
15222 fds[0].revents = 0;
15223 res = poll(fds, 1, -1);
15224 if (!res) {
15225 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
15226 continue;
15227 }
15228
15229 if (fds[0].revents & POLLPRI) {
15230 ast_free(mybuf);
15231 return -1;
15232 }
15233 if (!(fds[0].revents & POLLOUT)) {
15234 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
15235 continue;
15236 }
15237 res = write(fd, buf, size);
15238 if (res != size) {
15239 if (res == -1) {
15240 free(mybuf);
15241 return -1;
15242 }
15243 if (option_debug)
15244 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15245 break;
15246 }
15247 len -= size;
15248 buf += size;
15249 }
15250 free(mybuf);
15251 return(0);
15252 }
15253
15254
15255 static int reload(void)
15256 {
15257 int res = 0;
15258
15259 res = setup_dahdi(1);
15260 if (res) {
15261 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15262 return -1;
15263 }
15264 return 0;
15265 }
15266
15267
15268
15269
15270
15271 #ifdef HAVE_PRI
15272 #define tdesc "DAHDI Telephony w/PRI"
15273 #else
15274 #define tdesc "DAHDI Telephony"
15275 #endif
15276
15277 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15278 .load = load_module,
15279 .unload = unload_module,
15280 .reload = reload,
15281 );
15282
15283