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: 232090 $")
00052
00053 #include <stdio.h>
00054 #include <string.h>
00055 #ifdef __NetBSD__
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
00147
00148
00149
00150
00151
00152 #define DEFAULT_CIDRINGS 1
00153
00154 #define CHANNEL_PSEUDO -12
00155
00156 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00157
00158
00159 #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))
00160
00161 static const char tdesc[] = "DAHDI Telephony Driver"
00162 #ifdef HAVE_PRI
00163 " w/PRI"
00164 #endif
00165 #ifdef HAVE_OPENR2
00166 " w/OPENR2"
00167 #endif
00168 ;
00169
00170 #define SIG_EM DAHDI_SIG_EM
00171 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00173 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00174 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00175 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00176 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00177 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00178 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00179 #define SIG_FXSLS DAHDI_SIG_FXSLS
00180 #define SIG_FXSGS DAHDI_SIG_FXSGS
00181 #define SIG_FXSKS DAHDI_SIG_FXSKS
00182 #define SIG_FXOLS DAHDI_SIG_FXOLS
00183 #define SIG_FXOGS DAHDI_SIG_FXOGS
00184 #define SIG_FXOKS DAHDI_SIG_FXOKS
00185 #define SIG_PRI DAHDI_SIG_CLEAR
00186 #define SIG_MFCR2 DAHDI_SIG_CAS
00187 #define SIG_SF DAHDI_SIG_SF
00188 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00189 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00190 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00191 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00192 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00193 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00194 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00195
00196 #define NUM_SPANS 32
00197 #define NUM_DCHANS 4
00198 #define MAX_CHANNELS 672
00199
00200 #define CHAN_PSEUDO -2
00201
00202 #define DCHAN_PROVISIONED (1 << 0)
00203 #define DCHAN_NOTINALARM (1 << 1)
00204 #define DCHAN_UP (1 << 2)
00205
00206 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00207
00208
00209 #define DAHDI_OVERLAPDIAL_NONE 0
00210 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00211 #define DAHDI_OVERLAPDIAL_INCOMING 2
00212 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00213
00214 static char defaultcic[64] = "";
00215 static char defaultozz[64] = "";
00216
00217 static char progzone[10] = "";
00218
00219 static int distinctiveringaftercid = 0;
00220
00221 static int numbufs = 4;
00222 static int dtmfcid_level = 256;
00223
00224 #ifdef HAVE_PRI
00225 static struct ast_channel inuse;
00226 #ifdef PRI_GETSET_TIMERS
00227 static int pritimers[PRI_MAX_TIMERS];
00228 #endif
00229 static int pridebugfd = -1;
00230 static char pridebugfilename[1024] = "";
00231 #endif
00232
00233
00234 static int firstdigittimeout = 16000;
00235
00236
00237 static int gendigittimeout = 8000;
00238
00239
00240 static int matchdigittimeout = 3000;
00241
00242
00243 AST_MUTEX_DEFINE_STATIC(iflock);
00244
00245
00246 static int ifcount = 0;
00247
00248 #ifdef HAVE_PRI
00249 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00250 #endif
00251
00252
00253
00254 AST_MUTEX_DEFINE_STATIC(monlock);
00255
00256
00257
00258 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00259 static ast_cond_t ss_thread_complete;
00260 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00261 AST_MUTEX_DEFINE_STATIC(restart_lock);
00262 static int ss_thread_count = 0;
00263 static int num_restart_pending = 0;
00264
00265 static int restart_monitor(void);
00266
00267 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);
00268
00269 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00270
00271
00272 static inline int dahdi_get_event(int fd)
00273 {
00274 int j;
00275 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00276 return -1;
00277 return j;
00278 }
00279
00280
00281 static inline int dahdi_wait_event(int fd)
00282 {
00283 int i, j = 0;
00284 i = DAHDI_IOMUX_SIGEVENT;
00285 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00286 return -1;
00287 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00288 return -1;
00289 return j;
00290 }
00291
00292
00293 #define READ_SIZE 160
00294
00295 #define MASK_AVAIL (1 << 0)
00296 #define MASK_INUSE (1 << 1)
00297
00298 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00299 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00300 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00301 #define MIN_MS_SINCE_FLASH ( (2000) )
00302 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00303
00304 struct dahdi_pvt;
00305
00306
00307
00308
00309
00310 static int ringt_base = DEFAULT_RINGT;
00311
00312 #ifdef HAVE_OPENR2
00313
00314 struct dahdi_mfcr2 {
00315 pthread_t master;
00316 openr2_context_t *protocol_context;
00317 struct dahdi_pvt *pvts[MAX_CHANNELS];
00318 int numchans;
00319 };
00320
00321 static struct dahdi_mfcr2 r2links[NUM_SPANS];
00322 static openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN;
00323 static int mfcr2_cur_mfback_timeout = -1;
00324 static int mfcr2_cur_metering_pulse_timeout = -1;
00325 static int mfcr2_cur_max_ani = 10;
00326 static int mfcr2_cur_max_dnis = 4;
00327 static int mfcr2_cur_get_ani_first = -1;
00328 static int mfcr2_cur_skip_category = -1;
00329 static int mfcr2_cur_context_index = 0;
00330 static int mfcr2_cur_call_files = 0;
00331 static int mfcr2_cur_allow_collect_calls = 0;
00332 static int mfcr2_cur_accept_on_offer = 1;
00333 static int mfcr2_cur_charge_calls = 1;
00334 static int mfcr2_cur_forced_release = 0;
00335 static int mfcr2_cur_double_answer = 0;
00336 static int mfcr2_cur_immediate_accept = -1;
00337
00338 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00339 static int mfcr2_cur_dtmf_dialing = -1;
00340 static int mfcr2_cur_dtmf_detection = -1;
00341 static int mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
00342 static int mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
00343 #endif
00344 static char mfcr2_cur_logdir[OR2_MAX_PATH];
00345 static char mfcr2_cur_r2proto_file[OR2_MAX_PATH];
00346 static openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
00347 static openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
00348
00349 #endif
00350
00351 #ifdef HAVE_PRI
00352
00353 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00354 #define PRI_CHANNEL(p) ((p) & 0xff)
00355 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00356 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00357
00358 struct dahdi_pri {
00359 pthread_t master;
00360 ast_mutex_t lock;
00361 char idleext[AST_MAX_EXTENSION];
00362 char idlecontext[AST_MAX_CONTEXT];
00363 char idledial[AST_MAX_EXTENSION];
00364 int minunused;
00365 int minidle;
00366 int nodetype;
00367 int switchtype;
00368 int nsf;
00369 int dialplan;
00370 int localdialplan;
00371 char internationalprefix[10];
00372 char nationalprefix[10];
00373 char localprefix[20];
00374 char privateprefix[20];
00375 char unknownprefix[20];
00376 int dchannels[NUM_DCHANS];
00377 int trunkgroup;
00378 int mastertrunkgroup;
00379 int prilogicalspan;
00380 int numchans;
00381 int overlapdial;
00382 int facilityenable;
00383 struct pri *dchans[NUM_DCHANS];
00384 int dchanavail[NUM_DCHANS];
00385 struct pri *pri;
00386
00387 int debug;
00388 int fds[NUM_DCHANS];
00389
00390 int offset;
00391
00392 int span;
00393
00394 int resetting;
00395
00396 int resetpos;
00397 #ifdef HAVE_PRI_INBANDDISCONNECT
00398 unsigned int inbanddisconnect:1;
00399 #endif
00400 time_t lastreset;
00401 long resetinterval;
00402 struct dahdi_pvt *pvts[MAX_CHANNELS];
00403 struct dahdi_pvt *crvs;
00404 struct dahdi_pvt *crvend;
00405 };
00406
00407
00408 static struct dahdi_pri pris[NUM_SPANS];
00409
00410 #if 0
00411 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00412 #else
00413 #define DEFAULT_PRI_DEBUG 0
00414 #endif
00415
00416 static inline void pri_rel(struct dahdi_pri *pri)
00417 {
00418 ast_mutex_unlock(&pri->lock);
00419 }
00420
00421 #else
00422
00423 struct dahdi_pri;
00424 #endif
00425
00426 #define SUB_REAL 0
00427 #define SUB_CALLWAIT 1
00428 #define SUB_THREEWAY 2
00429
00430
00431 #define POLARITY_IDLE 0
00432 #define POLARITY_REV 1
00433
00434
00435 static struct dahdi_distRings drings;
00436
00437 struct distRingData {
00438 int ring[3];
00439 };
00440 struct ringContextData {
00441 char contextData[AST_MAX_CONTEXT];
00442 };
00443 struct dahdi_distRings {
00444 struct distRingData ringnum[3];
00445 struct ringContextData ringContext[3];
00446 };
00447
00448 static char *subnames[] = {
00449 "Real",
00450 "Callwait",
00451 "Threeway"
00452 };
00453
00454 struct dahdi_subchannel {
00455 int dfd;
00456 struct ast_channel *owner;
00457 int chan;
00458 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00459 struct ast_frame f;
00460 unsigned int needringing:1;
00461 unsigned int needbusy:1;
00462 unsigned int needcongestion:1;
00463 unsigned int needcallerid:1;
00464 unsigned int needanswer:1;
00465 unsigned int needflash:1;
00466 unsigned int needhold:1;
00467 unsigned int needunhold:1;
00468 unsigned int linear:1;
00469 unsigned int inthreeway:1;
00470 struct dahdi_confinfo curconf;
00471 };
00472
00473 #define CONF_USER_REAL (1 << 0)
00474 #define CONF_USER_THIRDCALL (1 << 1)
00475
00476 #define MAX_SLAVES 4
00477
00478 static struct dahdi_pvt {
00479 ast_mutex_t lock;
00480 struct ast_channel *owner;
00481
00482
00483 struct dahdi_subchannel sub_unused;
00484 struct dahdi_subchannel subs[3];
00485 struct dahdi_confinfo saveconf;
00486
00487 struct dahdi_pvt *slaves[MAX_SLAVES];
00488 struct dahdi_pvt *master;
00489 int inconference;
00490
00491 int buf_no;
00492 int buf_policy;
00493 int sig;
00494
00495
00496
00497
00498 int radio;
00499 int outsigmod;
00500 int oprmode;
00501 struct dahdi_pvt *oprpeer;
00502
00503 float rxgain;
00504
00505 float txgain;
00506 int tonezone;
00507 struct dahdi_pvt *next;
00508 struct dahdi_pvt *prev;
00509
00510
00511
00512
00513
00514
00515
00516 unsigned int adsi:1;
00517
00518
00519
00520
00521
00522 unsigned int answeronpolarityswitch:1;
00523
00524
00525
00526
00527
00528 unsigned int busydetect:1;
00529
00530
00531
00532
00533
00534 unsigned int callreturn:1;
00535
00536
00537
00538
00539
00540
00541 unsigned int callwaiting:1;
00542
00543
00544
00545
00546 unsigned int callwaitingcallerid:1;
00547
00548
00549
00550
00551
00552
00553 unsigned int cancallforward:1;
00554
00555
00556
00557
00558 unsigned int canpark:1;
00559
00560 unsigned int confirmanswer:1;
00561
00562
00563
00564
00565 unsigned int destroy:1;
00566 unsigned int didtdd:1;
00567
00568 unsigned int dialednone:1;
00569
00570 unsigned int dialing:1;
00571
00572 unsigned int digital:1;
00573
00574 unsigned int dnd:1;
00575
00576 unsigned int echobreak:1;
00577
00578
00579
00580
00581
00582 unsigned int echocanbridged:1;
00583
00584 unsigned int echocanon:1;
00585
00586 unsigned int faxhandled:1;
00587
00588 unsigned int firstradio:1;
00589
00590
00591
00592
00593 unsigned int hanguponpolarityswitch:1;
00594
00595 unsigned int hardwaredtmf:1;
00596
00597
00598
00599
00600
00601
00602 unsigned int hidecallerid:1;
00603
00604
00605
00606
00607
00608 unsigned int hidecalleridname:1;
00609
00610 unsigned int ignoredtmf:1;
00611
00612
00613
00614
00615
00616 unsigned int immediate:1;
00617
00618 unsigned int inalarm:1;
00619 unsigned int unknown_alarm:1;
00620
00621 unsigned int mate:1;
00622
00623 unsigned int outgoing:1;
00624
00625
00626
00627
00628
00629
00630 unsigned int permcallwaiting:1;
00631
00632
00633
00634
00635 unsigned int permhidecallerid:1;
00636
00637
00638
00639
00640 unsigned int priindication_oob:1;
00641
00642
00643
00644
00645 unsigned int priexclusive:1;
00646
00647
00648
00649
00650 unsigned int pulse:1;
00651
00652 unsigned int pulsedial:1;
00653 unsigned int restartpending:1;
00654
00655
00656
00657
00658
00659 unsigned int restrictcid:1;
00660
00661
00662
00663
00664 unsigned int threewaycalling:1;
00665
00666
00667
00668
00669
00670
00671
00672
00673 unsigned int transfer:1;
00674
00675
00676
00677
00678
00679
00680
00681 unsigned int use_callerid:1;
00682
00683
00684
00685
00686
00687
00688 unsigned int use_callingpres:1;
00689
00690
00691
00692
00693
00694 unsigned int usedistinctiveringdetection:1;
00695
00696
00697
00698
00699 unsigned int dahditrcallerid:1;
00700
00701
00702
00703
00704 unsigned int transfertobusy:1;
00705 #if defined(HAVE_PRI)
00706
00707 unsigned int alerting:1;
00708
00709 unsigned int alreadyhungup:1;
00710
00711
00712
00713
00714 unsigned int isidlecall:1;
00715
00716
00717
00718
00719 unsigned int proceeding:1;
00720
00721 unsigned int progress:1;
00722
00723
00724
00725
00726 unsigned int resetting:1;
00727
00728
00729
00730
00731 unsigned int setup_ack:1;
00732 #endif
00733
00734
00735
00736
00737 unsigned int use_smdi:1;
00738
00739 struct ast_smdi_interface *smdi_iface;
00740
00741
00742 struct dahdi_distRings drings;
00743
00744
00745
00746
00747
00748 char context[AST_MAX_CONTEXT];
00749
00750
00751
00752 char defcontext[AST_MAX_CONTEXT];
00753
00754 char exten[AST_MAX_EXTENSION];
00755
00756
00757
00758
00759 char language[MAX_LANGUAGE];
00760
00761
00762
00763
00764 char mohinterpret[MAX_MUSICCLASS];
00765
00766
00767
00768
00769 char mohsuggest[MAX_MUSICCLASS];
00770 #ifdef PRI_ANI
00771
00772 char cid_ani[AST_MAX_EXTENSION];
00773 #endif
00774
00775 char cid_num[AST_MAX_EXTENSION];
00776
00777 int cid_ton;
00778
00779 char cid_name[AST_MAX_EXTENSION];
00780
00781 char lastcid_num[AST_MAX_EXTENSION];
00782
00783 char lastcid_name[AST_MAX_EXTENSION];
00784 char *origcid_num;
00785 char *origcid_name;
00786
00787 char callwait_num[AST_MAX_EXTENSION];
00788
00789 char callwait_name[AST_MAX_EXTENSION];
00790
00791 char rdnis[AST_MAX_EXTENSION];
00792
00793 char dnid[AST_MAX_EXTENSION];
00794
00795
00796
00797
00798 ast_group_t group;
00799
00800 int law;
00801 int confno;
00802 int confusers;
00803 int propconfno;
00804
00805
00806
00807
00808 ast_group_t callgroup;
00809
00810
00811
00812
00813 ast_group_t pickupgroup;
00814 int channel;
00815 int span;
00816 time_t guardtime;
00817 int cid_signalling;
00818 int cid_start;
00819 int dtmfcid_holdoff_state;
00820 struct timeval dtmfcid_delay;
00821 int callingpres;
00822 int callwaitingrepeat;
00823 int cidcwexpire;
00824
00825 unsigned char *cidspill;
00826
00827 int cidpos;
00828
00829 int cidlen;
00830
00831 int ringt;
00832
00833
00834
00835
00836 int ringt_base;
00837
00838
00839
00840
00841
00842
00843 int stripmsd;
00844
00845 int callwaitcas;
00846
00847 int callwaitrings;
00848
00849 int echocancel;
00850
00851
00852
00853
00854 int echotraining;
00855
00856 char echorest[20];
00857
00858
00859
00860
00861 int busycount;
00862
00863
00864
00865
00866 int busycompare;
00867
00868
00869
00870
00871 int busytonelength;
00872
00873
00874
00875
00876 int busyquietlength;
00877
00878
00879
00880
00881 int busyfuzziness;
00882
00883
00884
00885
00886 int silencethreshold;
00887
00888
00889
00890
00891 int callprogress;
00892 struct timeval flashtime;
00893
00894 struct ast_dsp *dsp;
00895
00896
00897 struct dahdi_dialoperation dop;
00898 int whichwink;
00899
00900 char finaldial[64];
00901 char accountcode[AST_MAX_ACCOUNT_CODE];
00902 int amaflags;
00903 struct tdd_state *tdd;
00904
00905 char call_forward[AST_MAX_EXTENSION];
00906
00907
00908
00909
00910 char mailbox[AST_MAX_EXTENSION];
00911
00912 char dialdest[256];
00913
00914 int onhooktime;
00915
00916 int msgstate;
00917 int distinctivering;
00918 int cidrings;
00919 int dtmfrelax;
00920
00921 int fake_event;
00922
00923
00924
00925
00926 int polarityonanswerdelay;
00927
00928 struct timeval polaritydelaytv;
00929
00930
00931
00932
00933 int sendcalleridafter;
00934 #ifdef HAVE_PRI
00935
00936 struct dahdi_pri *pri;
00937
00938 struct dahdi_pvt *bearer;
00939
00940 struct dahdi_pvt *realcall;
00941
00942 q931_call *call;
00943
00944 int prioffset;
00945
00946 int logicalspan;
00947 #endif
00948 #ifdef HAVE_OPENR2
00949 int mfcr2call;
00950 int mfcr2block;
00951 struct dahdi_mfcr2 *mfcr2;
00952 openr2_chan_t *r2chan;
00953 openr2_calling_party_category_t mfcr2_recvd_category;
00954 openr2_calling_party_category_t mfcr2_category;
00955 int mfcr2_accept_on_offer;
00956 int mfcr2_charge_calls;
00957 int mfcr2_allow_collect_calls;
00958 int mfcr2_forced_release;
00959 int mfcr2_dnis_index;
00960 int mfcr2_ani_index;
00961 int mfcr2_dnis_matched;
00962 int mfcr2_call_accepted;
00963 #endif
00964
00965 int polarity;
00966
00967 int dsp_features;
00968
00969 char begindigit;
00970 } *iflist = NULL, *ifend = NULL;
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982 struct dahdi_chan_conf {
00983 struct dahdi_pvt chan;
00984 #ifdef HAVE_PRI
00985 struct dahdi_pri pri;
00986 #endif
00987 struct dahdi_params timing;
00988
00989
00990
00991
00992
00993 char smdi_port[SMDI_MAX_FILENAME_LEN];
00994 };
00995
00996
00997 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
00998
00999
01000
01001 struct dahdi_chan_conf conf = {
01002 #ifdef HAVE_PRI
01003 .pri = {
01004 .nsf = PRI_NSF_NONE,
01005 .switchtype = PRI_SWITCH_NI2,
01006 .dialplan = PRI_NATIONAL_ISDN + 1,
01007 .localdialplan = PRI_NATIONAL_ISDN + 1,
01008 .nodetype = PRI_CPE,
01009
01010 .minunused = 2,
01011 .idleext = "",
01012 .idledial = "",
01013 .internationalprefix = "",
01014 .nationalprefix = "",
01015 .localprefix = "",
01016 .privateprefix = "",
01017 .unknownprefix = "",
01018
01019 .resetinterval = 3600
01020 },
01021 #endif
01022 .chan = {
01023 .context = "default",
01024 .cid_num = "",
01025 .cid_name = "",
01026 .mohinterpret = "default",
01027 .mohsuggest = "",
01028 .transfertobusy = 1,
01029
01030 .cid_signalling = CID_SIG_BELL,
01031 .cid_start = CID_START_RING,
01032 .dahditrcallerid = 0,
01033 .use_callerid = 1,
01034 .sig = -1,
01035 .outsigmod = -1,
01036
01037 .tonezone = -1,
01038
01039 .echocancel = 1,
01040
01041 .busycount = 3,
01042 .busycompare = 0,
01043 .busytonelength = 0,
01044 .busyquietlength = 0,
01045 .busyfuzziness = 0,
01046 .silencethreshold = 0,
01047
01048 .accountcode = "",
01049
01050 .mailbox = "",
01051
01052
01053 .polarityonanswerdelay = 600,
01054
01055 .sendcalleridafter = DEFAULT_CIDRINGS,
01056
01057 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01058 .buf_no = numbufs
01059 },
01060 .timing = {
01061 .prewinktime = -1,
01062 .preflashtime = -1,
01063 .winktime = -1,
01064 .flashtime = -1,
01065 .starttime = -1,
01066 .rxwinktime = -1,
01067 .rxflashtime = -1,
01068 .debouncetime = -1
01069 },
01070 .smdi_port = "/dev/ttyS0",
01071 };
01072
01073 return conf;
01074 }
01075
01076
01077 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01078 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01079 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01080 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01081 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01082 static int dahdi_hangup(struct ast_channel *ast);
01083 static int dahdi_answer(struct ast_channel *ast);
01084 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01085 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01086 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01087 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01088 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01089 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01090 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
01091
01092 static const struct ast_channel_tech dahdi_tech = {
01093 .type = "DAHDI",
01094 .description = tdesc,
01095 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01096 .requester = dahdi_request,
01097 .send_digit_begin = dahdi_digit_begin,
01098 .send_digit_end = dahdi_digit_end,
01099 .send_text = dahdi_sendtext,
01100 .call = dahdi_call,
01101 .hangup = dahdi_hangup,
01102 .answer = dahdi_answer,
01103 .read = dahdi_read,
01104 .write = dahdi_write,
01105 .bridge = dahdi_bridge,
01106 .exception = dahdi_exception,
01107 .indicate = dahdi_indicate,
01108 .fixup = dahdi_fixup,
01109 .setoption = dahdi_setoption,
01110 .func_channel_read = dahdi_func_read,
01111 };
01112
01113 static const struct ast_channel_tech zap_tech = {
01114 .type = "Zap",
01115 .description = tdesc,
01116 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01117 .requester = dahdi_request,
01118 .send_digit_begin = dahdi_digit_begin,
01119 .send_digit_end = dahdi_digit_end,
01120 .send_text = dahdi_sendtext,
01121 .call = dahdi_call,
01122 .hangup = dahdi_hangup,
01123 .answer = dahdi_answer,
01124 .read = dahdi_read,
01125 .write = dahdi_write,
01126 .bridge = dahdi_bridge,
01127 .exception = dahdi_exception,
01128 .indicate = dahdi_indicate,
01129 .fixup = dahdi_fixup,
01130 .setoption = dahdi_setoption,
01131 .func_channel_read = dahdi_func_read,
01132 };
01133
01134 static const struct ast_channel_tech *chan_tech;
01135
01136 #ifdef HAVE_PRI
01137 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01138 #else
01139 #define GET_CHANNEL(p) ((p)->channel)
01140 #endif
01141
01142 struct dahdi_pvt *round_robin[32];
01143
01144 #ifdef HAVE_PRI
01145 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01146 {
01147 int res;
01148
01149 do {
01150 res = ast_mutex_trylock(&pri->lock);
01151 if (res) {
01152 DEADLOCK_AVOIDANCE(&pvt->lock);
01153 }
01154 } while (res);
01155
01156 if (pri->master != AST_PTHREADT_NULL)
01157 pthread_kill(pri->master, SIGURG);
01158 return 0;
01159 }
01160 #endif
01161
01162 #define NUM_CADENCE_MAX 25
01163 static int num_cadence = 4;
01164 static int user_has_defined_cadences = 0;
01165
01166 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01167 { { 125, 125, 2000, 4000 } },
01168 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01169 { { 125, 125, 125, 125, 125, 4000 } },
01170 { { 1000, 500, 2500, 5000 } },
01171 };
01172
01173
01174
01175
01176
01177 static int cidrings[NUM_CADENCE_MAX] = {
01178 2,
01179 4,
01180 3,
01181 2,
01182 };
01183
01184 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01185 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01186
01187 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01188 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01189
01190 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01191 {
01192 int res;
01193 if (p->subs[SUB_REAL].owner == ast)
01194 res = 0;
01195 else if (p->subs[SUB_CALLWAIT].owner == ast)
01196 res = 1;
01197 else if (p->subs[SUB_THREEWAY].owner == ast)
01198 res = 2;
01199 else {
01200 res = -1;
01201 if (!nullok)
01202 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01203 }
01204 return res;
01205 }
01206
01207 #ifdef HAVE_PRI
01208 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01209 #else
01210 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01211 #endif
01212 {
01213 #ifdef HAVE_PRI
01214 if (pri)
01215 ast_mutex_unlock(&pri->lock);
01216 #endif
01217 for (;;) {
01218 if (p->subs[a].owner) {
01219 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
01220 DEADLOCK_AVOIDANCE(&p->lock);
01221 } else {
01222 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01223 ast_mutex_unlock(&p->subs[a].owner->lock);
01224 break;
01225 }
01226 } else
01227 break;
01228 }
01229 #ifdef HAVE_PRI
01230 if (pri)
01231 ast_mutex_lock(&pri->lock);
01232 #endif
01233 }
01234
01235 #ifdef HAVE_PRI
01236 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
01237 #else
01238 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
01239 #endif
01240 {
01241
01242 #ifdef HAVE_PRI
01243 if (pri)
01244 ast_mutex_unlock(&pri->lock);
01245 #endif
01246 for (;;) {
01247 if (p->owner) {
01248 if (ast_mutex_trylock(&p->owner->lock)) {
01249 DEADLOCK_AVOIDANCE(&p->lock);
01250 } else {
01251 ast_queue_frame(p->owner, f);
01252 ast_mutex_unlock(&p->owner->lock);
01253 break;
01254 }
01255 } else
01256 break;
01257 }
01258 #ifdef HAVE_PRI
01259 if (pri)
01260 ast_mutex_lock(&pri->lock);
01261 #endif
01262 }
01263
01264 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability);
01265 #ifdef HAVE_OPENR2
01266 static void init_mfcr2_globals(void)
01267 {
01268 int r;
01269 mfcr2_cur_context_index = 0;
01270 mfcr2_cur_variant = OR2_VAR_UNKNOWN;
01271 mfcr2_cur_mfback_timeout = -1;
01272 mfcr2_cur_metering_pulse_timeout = -1;
01273 mfcr2_cur_max_ani = 10;
01274 mfcr2_cur_max_dnis = 4;
01275 mfcr2_cur_get_ani_first = -1;
01276 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01277 mfcr2_cur_dtmf_dialing = -1;
01278 mfcr2_cur_dtmf_detection = -1;
01279 mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
01280 mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
01281 #endif
01282 mfcr2_cur_skip_category = -1;
01283 mfcr2_cur_call_files = 0;
01284 mfcr2_cur_allow_collect_calls = 0;
01285 mfcr2_cur_forced_release = 0;
01286 mfcr2_cur_double_answer = 0;
01287 mfcr2_cur_immediate_accept = -1;
01288 mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
01289 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
01290 memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir));
01291 memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file));
01292 memset(r2links, 0, sizeof(r2links));
01293 for (r = 0; r < NUM_SPANS; r++) {
01294 r2links[r].master = AST_PTHREADT_NULL;
01295 }
01296 }
01297
01298 static int dahdi_r2_answer(struct dahdi_pvt *p)
01299 {
01300 int res = 0;
01301
01302
01303
01304 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01305 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01306 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01307 if (!double_answer) {
01308
01309
01310 res = openr2_chan_answer_call(p->r2chan);
01311 } else if (wants_double_answer) {
01312 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01313 } else {
01314 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01315 }
01316 #else
01317 res = openr2_chan_answer_call(p->r2chan);
01318 #endif
01319 return res;
01320 }
01321
01322 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01323 {
01324 openr2_calling_party_category_t cat;
01325 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01326 struct dahdi_pvt *p = c->tech_pvt;
01327 if (ast_strlen_zero(catstr)) {
01328 ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n",
01329 c->name, openr2_proto_get_category_string(p->mfcr2_category));
01330 return p->mfcr2_category;
01331 }
01332 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01333 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01334 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01335 return p->mfcr2_category;
01336 }
01337 ast_log(LOG_DEBUG, "Using category %s\n", catstr);
01338 return cat;
01339 }
01340
01341 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01342 {
01343 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01344 ast_mutex_lock(&p->lock);
01345 if (p->mfcr2call) {
01346 ast_mutex_unlock(&p->lock);
01347
01348
01349
01350
01351
01352 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01353 return;
01354 }
01355 p->mfcr2call = 1;
01356
01357 p->cid_name[0] = 0;
01358 p->cid_num[0] = 0;
01359 p->rdnis[0] = 0;
01360 p->exten[0] = 0;
01361 p->mfcr2_ani_index = 0;
01362 p->mfcr2_dnis_index = 0;
01363 p->mfcr2_dnis_matched = 0;
01364 p->mfcr2_call_accepted = 0;
01365 ast_mutex_unlock(&p->lock);
01366 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01367 }
01368
01369 static void handle_alarms(struct dahdi_pvt *p, int alarms);
01370 static int get_alarms(struct dahdi_pvt *p);
01371 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01372 {
01373 int res;
01374 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01375 ast_mutex_lock(&p->lock);
01376 p->inalarm = alarm ? 1 : 0;
01377 if (p->inalarm) {
01378 res = get_alarms(p);
01379
01380 handle_alarms(p, res);
01381 } else {
01382 if (!p->unknown_alarm) {
01383 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01384 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01385 } else {
01386 p->unknown_alarm = 0;
01387 }
01388 }
01389 ast_mutex_unlock(&p->lock);
01390 ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan));
01391 }
01392
01393 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01394 {
01395 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01396 }
01397
01398 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01399 {
01400 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01401 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01402 if (p->owner) {
01403 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01404 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01405 }
01406 ast_mutex_lock(&p->lock);
01407 p->mfcr2call = 0;
01408 ast_mutex_unlock(&p->lock);
01409 }
01410
01411 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01412 {
01413 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01414 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01415 p->channel, openr2_proto_get_disconnect_string(cause));
01416
01417 openr2_chan_set_idle(p->r2chan);
01418 ast_mutex_lock(&p->lock);
01419 p->mfcr2call = 0;
01420 ast_mutex_unlock(&p->lock);
01421 }
01422 }
01423
01424 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01425 {
01426 struct dahdi_pvt *p;
01427 struct ast_channel *c;
01428 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01429 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category));
01430 p = openr2_chan_get_client_data(r2chan);
01431 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01432 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel);
01433 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01434 return;
01435 }
01436 ast_mutex_lock(&p->lock);
01437 p->mfcr2_recvd_category = category;
01438
01439 if (!p->use_callerid) {
01440 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01441 p->cid_num[0] = 0;
01442 p->cid_name[0] = 0;
01443 }
01444
01445 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01446 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01447 p->exten[0] = 's';
01448 p->exten[1] = 0;
01449 }
01450 ast_mutex_unlock(&p->lock);
01451 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01452 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01453 p->channel, p->exten, p->context);
01454 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01455 } else {
01456
01457 if (!p->mfcr2_accept_on_offer) {
01458 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01459 if (!c) {
01460 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01461 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01462 }
01463
01464
01465 } else if (p->mfcr2_charge_calls) {
01466 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel);
01467 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01468 } else {
01469 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel);
01470 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01471 }
01472 }
01473 }
01474
01475 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01476 {
01477 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01478 ast_verbose("MFC/R2 call end on chan %d\n", p->channel);
01479 ast_mutex_lock(&p->lock);
01480 p->mfcr2call = 0;
01481 ast_mutex_unlock(&p->lock);
01482 }
01483
01484 static void dahdi_enable_ec(struct dahdi_pvt *p);
01485 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01486 {
01487 struct dahdi_pvt *p = NULL;
01488 struct ast_channel *c = NULL;
01489 p = openr2_chan_get_client_data(r2chan);
01490 dahdi_enable_ec(p);
01491 p->mfcr2_call_accepted = 1;
01492 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01493 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01494
01495
01496
01497
01498 if (!p->mfcr2_accept_on_offer) {
01499 openr2_chan_disable_read(r2chan);
01500 ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01501 dahdi_r2_answer(p);
01502 return;
01503 }
01504 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01505 if (c) {
01506
01507 openr2_chan_disable_read(r2chan);
01508 } else {
01509 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01510 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01511 return;
01512 }
01513 } else {
01514 ast_verbose("Call accepted on forward channel %d\n", p->channel);
01515 p->subs[SUB_REAL].needringing = 1;
01516 p->dialing = 0;
01517
01518 openr2_chan_disable_read(r2chan);
01519 }
01520 }
01521
01522 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01523 {
01524 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01525 ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan));
01526 p->subs[SUB_REAL].needanswer = 1;
01527 }
01528
01529 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01530 {
01531
01532 }
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01556 {
01557 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01558 ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan));
01559 ast_mutex_lock(&p->lock);
01560 if (p->owner) {
01561
01562
01563 if (p->owner->_state == AST_STATE_UP) {
01564 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01565 ast_mutex_unlock(&p->lock);
01566 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01567
01568 switch (cause) {
01569 case OR2_CAUSE_BUSY_NUMBER:
01570 p->owner->hangupcause = AST_CAUSE_BUSY;
01571 p->subs[SUB_REAL].needbusy = 1;
01572 break;
01573 case OR2_CAUSE_NUMBER_CHANGED:
01574 p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED;
01575 p->subs[SUB_REAL].needcongestion = 1;
01576 break;
01577 case OR2_CAUSE_NETWORK_CONGESTION:
01578 p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
01579 p->subs[SUB_REAL].needcongestion = 1;
01580 break;
01581 case OR2_CAUSE_OUT_OF_ORDER:
01582 p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01583 p->subs[SUB_REAL].needcongestion = 1;
01584 break;
01585 case OR2_CAUSE_UNALLOCATED_NUMBER:
01586 p->owner->hangupcause = AST_CAUSE_UNALLOCATED;
01587 p->subs[SUB_REAL].needcongestion = 1;
01588 break;
01589 case OR2_CAUSE_NO_ANSWER:
01590 p->owner->hangupcause = AST_CAUSE_NO_ANSWER;
01591 p->subs[SUB_REAL].needcongestion = 1;
01592 break;
01593 case OR2_CAUSE_UNSPECIFIED:
01594 p->owner->hangupcause = AST_CAUSE_NOTDEFINED;
01595 p->subs[SUB_REAL].needcongestion = 1;
01596 break;
01597 case OR2_CAUSE_NORMAL_CLEARING:
01598 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01599 p->subs[SUB_REAL].needcongestion = 1;
01600 break;
01601 default:
01602 ast_log(LOG_WARNING, "Unhandled cause %d\n", cause);
01603 }
01604 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01605 ast_mutex_unlock(&p->lock);
01606 } else {
01607 ast_mutex_unlock(&p->lock);
01608
01609
01610 ast_queue_hangup(p->owner);
01611 }
01612 } else {
01613 ast_mutex_unlock(&p->lock);
01614
01615 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01616 }
01617 }
01618
01619 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01620 {
01621 switch (level) {
01622 case OR2_LOG_NOTICE:
01623 ast_verbose("%s", logmessage);
01624 break;
01625 case OR2_LOG_WARNING:
01626 ast_log(LOG_WARNING, "%s", logmessage);
01627 break;
01628 case OR2_LOG_ERROR:
01629 ast_log(LOG_ERROR, "%s", logmessage);
01630 break;
01631 case OR2_LOG_STACK_TRACE:
01632 case OR2_LOG_MF_TRACE:
01633 case OR2_LOG_CAS_TRACE:
01634 case OR2_LOG_DEBUG:
01635 case OR2_LOG_EX_DEBUG:
01636 ast_log(LOG_DEBUG, "%s", logmessage);
01637 break;
01638 default:
01639 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01640 ast_log(LOG_NOTICE, "%s", logmessage);
01641 break;
01642 }
01643 }
01644
01645 #define DAHDI_R2_REMOTE_BLOCK (1 << 0)
01646 #define DAHDI_R2_LOCAL_BLOCK (1 << 1)
01647 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01648 {
01649 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01650 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel);
01651 ast_mutex_lock(&p->lock);
01652 p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK;
01653 ast_mutex_unlock(&p->lock);
01654 }
01655
01656 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01657 {
01658 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01659 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01660 ast_mutex_lock(&p->lock);
01661 p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK;
01662 ast_mutex_unlock(&p->lock);
01663 }
01664
01665 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01666 __attribute__((format (printf, 3, 0)));
01667 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01668 {
01669 char logmsg[256];
01670 char completemsg[sizeof(logmsg)+50];
01671 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01672 snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg);
01673 dahdi_r2_write_log(level, completemsg);
01674 }
01675
01676 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01677 __attribute__((format (printf, 3, 0)));
01678 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01679 {
01680 char logmsg[256];
01681 char completemsg[sizeof(logmsg)+50];
01682 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01683 snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg);
01684 dahdi_r2_write_log(level, completemsg);
01685 }
01686
01687 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01688 {
01689 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01690
01691 if (p->immediate) {
01692 return 0;
01693 }
01694 p->exten[p->mfcr2_dnis_index] = digit;
01695 p->rdnis[p->mfcr2_dnis_index] = digit;
01696 p->mfcr2_dnis_index++;
01697 p->exten[p->mfcr2_dnis_index] = 0;
01698 p->rdnis[p->mfcr2_dnis_index] = 0;
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708 if ((p->mfcr2_dnis_matched ||
01709 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
01710 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01711 return 0;
01712 }
01713
01714 return 1;
01715 }
01716
01717 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
01718 {
01719 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01720 p->cid_num[p->mfcr2_ani_index] = digit;
01721 p->cid_name[p->mfcr2_ani_index] = digit;
01722 p->mfcr2_ani_index++;
01723 p->cid_num[p->mfcr2_ani_index] = 0;
01724 p->cid_name[p->mfcr2_ani_index] = 0;
01725 }
01726
01727 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
01728 {
01729 ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
01730 }
01731
01732 static openr2_event_interface_t dahdi_r2_event_iface = {
01733 .on_call_init = dahdi_r2_on_call_init,
01734 .on_call_offered = dahdi_r2_on_call_offered,
01735 .on_call_accepted = dahdi_r2_on_call_accepted,
01736 .on_call_answered = dahdi_r2_on_call_answered,
01737 .on_call_disconnect = dahdi_r2_on_call_disconnect,
01738 .on_call_end = dahdi_r2_on_call_end,
01739 .on_call_read = dahdi_r2_on_call_read,
01740 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
01741 .on_os_error = dahdi_r2_on_os_error,
01742 .on_protocol_error = dahdi_r2_on_protocol_error,
01743 .on_line_blocked = dahdi_r2_on_line_blocked,
01744 .on_line_idle = dahdi_r2_on_line_idle,
01745
01746 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
01747 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
01748 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
01749
01750 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
01751 };
01752
01753 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
01754 {
01755 return AST_ALAW(sample);
01756 }
01757
01758 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
01759 {
01760 return AST_LIN2A(sample);
01761 }
01762
01763 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
01764 dahdi_r2_alaw_to_linear,
01765 dahdi_r2_linear_to_alaw
01766 };
01767
01768 #endif
01769
01770 static int restore_gains(struct dahdi_pvt *p);
01771
01772 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01773 {
01774 int tchan;
01775 int tinthreeway;
01776 struct ast_channel *towner;
01777
01778 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01779
01780 tchan = p->subs[a].chan;
01781 towner = p->subs[a].owner;
01782 tinthreeway = p->subs[a].inthreeway;
01783
01784 p->subs[a].chan = p->subs[b].chan;
01785 p->subs[a].owner = p->subs[b].owner;
01786 p->subs[a].inthreeway = p->subs[b].inthreeway;
01787
01788 p->subs[b].chan = tchan;
01789 p->subs[b].owner = towner;
01790 p->subs[b].inthreeway = tinthreeway;
01791
01792 if (p->subs[a].owner)
01793 p->subs[a].owner->fds[0] = p->subs[a].dfd;
01794 if (p->subs[b].owner)
01795 p->subs[b].owner->fds[0] = p->subs[b].dfd;
01796 wakeup_sub(p, a, NULL);
01797 wakeup_sub(p, b, NULL);
01798 }
01799
01800 static int dahdi_open(char *fn)
01801 {
01802 int fd;
01803 int isnum;
01804 int chan = 0;
01805 int bs;
01806 int x;
01807 isnum = 1;
01808 for (x = 0; x < strlen(fn); x++) {
01809 if (!isdigit(fn[x])) {
01810 isnum = 0;
01811 break;
01812 }
01813 }
01814 if (isnum) {
01815 chan = atoi(fn);
01816 if (chan < 1) {
01817 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01818 return -1;
01819 }
01820 fn = DAHDI_FILE_CHANNEL;
01821 }
01822 fd = open(fn, O_RDWR | O_NONBLOCK);
01823 if (fd < 0) {
01824 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01825 return -1;
01826 }
01827 if (chan) {
01828 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01829 x = errno;
01830 close(fd);
01831 errno = x;
01832 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01833 return -1;
01834 }
01835 }
01836 bs = READ_SIZE;
01837 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01838 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01839 x = errno;
01840 close(fd);
01841 errno = x;
01842 return -1;
01843 }
01844 return fd;
01845 }
01846
01847 static void dahdi_close(int fd)
01848 {
01849 if (fd > 0)
01850 close(fd);
01851 }
01852
01853 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01854 {
01855 dahdi_close(chan_pvt->subs[sub_num].dfd);
01856 chan_pvt->subs[sub_num].dfd = -1;
01857 }
01858
01859 #ifdef HAVE_PRI
01860 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01861 {
01862 dahdi_close(pri->fds[fd_num]);
01863 pri->fds[fd_num] = -1;
01864 }
01865 #endif
01866
01867 static int dahdi_setlinear(int dfd, int linear)
01868 {
01869 int res;
01870 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01871 if (res)
01872 return res;
01873 return 0;
01874 }
01875
01876
01877 static int alloc_sub(struct dahdi_pvt *p, int x)
01878 {
01879 struct dahdi_bufferinfo bi;
01880 int res;
01881 if (p->subs[x].dfd < 0) {
01882 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01883 if (p->subs[x].dfd > -1) {
01884 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01885 if (!res) {
01886 bi.txbufpolicy = p->buf_policy;
01887 bi.rxbufpolicy = p->buf_policy;
01888 bi.numbufs = p->buf_no;
01889 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01890 if (res < 0) {
01891 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01892 }
01893 } else
01894 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01895 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01896 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01897 dahdi_close_sub(p, x);
01898 return -1;
01899 }
01900 if (option_debug)
01901 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01902 return 0;
01903 } else
01904 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01905 return -1;
01906 }
01907 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01908 return -1;
01909 }
01910
01911 static int unalloc_sub(struct dahdi_pvt *p, int x)
01912 {
01913 if (!x) {
01914 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01915 return -1;
01916 }
01917 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01918 dahdi_close_sub(p, x);
01919 p->subs[x].linear = 0;
01920 p->subs[x].chan = 0;
01921 p->subs[x].owner = NULL;
01922 p->subs[x].inthreeway = 0;
01923 p->polarity = POLARITY_IDLE;
01924 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01925 return 0;
01926 }
01927
01928 static int digit_to_dtmfindex(char digit)
01929 {
01930 if (isdigit(digit))
01931 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01932 else if (digit >= 'A' && digit <= 'D')
01933 return DAHDI_TONE_DTMF_A + (digit - 'A');
01934 else if (digit >= 'a' && digit <= 'd')
01935 return DAHDI_TONE_DTMF_A + (digit - 'a');
01936 else if (digit == '*')
01937 return DAHDI_TONE_DTMF_s;
01938 else if (digit == '#')
01939 return DAHDI_TONE_DTMF_p;
01940 else
01941 return -1;
01942 }
01943
01944 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01945 {
01946 struct dahdi_pvt *pvt;
01947 int index;
01948 int dtmf = -1;
01949
01950 pvt = chan->tech_pvt;
01951
01952 ast_mutex_lock(&pvt->lock);
01953
01954 index = dahdi_get_index(chan, pvt, 0);
01955
01956 if ((index != SUB_REAL) || !pvt->owner)
01957 goto out;
01958
01959 #ifdef HAVE_PRI
01960 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01961 if (pvt->setup_ack) {
01962 if (!pri_grab(pvt, pvt->pri)) {
01963 pri_information(pvt->pri->pri, pvt->call, digit);
01964 pri_rel(pvt->pri);
01965 } else
01966 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01967 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01968 int res;
01969 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01970 res = strlen(pvt->dialdest);
01971 pvt->dialdest[res++] = digit;
01972 pvt->dialdest[res] = '\0';
01973 }
01974 goto out;
01975 }
01976 #endif
01977 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01978 goto out;
01979
01980 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01981 int res;
01982 struct dahdi_dialoperation zo = {
01983 .op = DAHDI_DIAL_OP_APPEND,
01984 .dialstr[0] = 'T',
01985 .dialstr[1] = digit,
01986 .dialstr[2] = 0,
01987 };
01988 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01989 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01990 else
01991 pvt->dialing = 1;
01992 } else {
01993 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01994 pvt->dialing = 1;
01995 pvt->begindigit = digit;
01996 }
01997
01998 out:
01999 ast_mutex_unlock(&pvt->lock);
02000
02001 return 0;
02002 }
02003
02004 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02005 {
02006 struct dahdi_pvt *pvt;
02007 int res = 0;
02008 int index;
02009 int x;
02010
02011 pvt = chan->tech_pvt;
02012
02013 ast_mutex_lock(&pvt->lock);
02014
02015 index = dahdi_get_index(chan, pvt, 0);
02016
02017 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
02018 goto out;
02019
02020 #ifdef HAVE_PRI
02021
02022 if (pvt->sig == SIG_PRI && !pvt->begindigit)
02023 goto out;
02024 #endif
02025
02026 if (pvt->begindigit) {
02027 x = -1;
02028 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
02029 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02030 pvt->dialing = 0;
02031 pvt->begindigit = 0;
02032 }
02033
02034 out:
02035 ast_mutex_unlock(&pvt->lock);
02036
02037 return res;
02038 }
02039
02040 static char *events[] = {
02041 "No event",
02042 "On hook",
02043 "Ring/Answered",
02044 "Wink/Flash",
02045 "Alarm",
02046 "No more alarm",
02047 "HDLC Abort",
02048 "HDLC Overrun",
02049 "HDLC Bad FCS",
02050 "Dial Complete",
02051 "Ringer On",
02052 "Ringer Off",
02053 "Hook Transition Complete",
02054 "Bits Changed",
02055 "Pulse Start",
02056 "Timer Expired",
02057 "Timer Ping",
02058 "Polarity Reversal",
02059 "Ring Begin",
02060 };
02061
02062 static struct {
02063 int alarm;
02064 char *name;
02065 } alarms[] = {
02066 { DAHDI_ALARM_RED, "Red Alarm" },
02067 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02068 { DAHDI_ALARM_BLUE, "Blue Alarm" },
02069 { DAHDI_ALARM_RECOVER, "Recovering" },
02070 { DAHDI_ALARM_LOOPBACK, "Loopback" },
02071 { DAHDI_ALARM_NOTOPEN, "Not Open" },
02072 { DAHDI_ALARM_NONE, "None" },
02073 };
02074
02075 static char *alarm2str(int alarm)
02076 {
02077 int x;
02078 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
02079 if (alarms[x].alarm & alarm)
02080 return alarms[x].name;
02081 }
02082 return alarm ? "Unknown Alarm" : "No Alarm";
02083 }
02084
02085 static char *event2str(int event)
02086 {
02087 static char buf[256];
02088 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
02089 return events[event];
02090 sprintf(buf, "Event %d", event);
02091 return buf;
02092 }
02093
02094 #ifdef HAVE_PRI
02095 static char *dialplan2str(int dialplan)
02096 {
02097 if (dialplan == -1) {
02098 return("Dynamically set dialplan in ISDN");
02099 }
02100 return (pri_plan2str(dialplan));
02101 }
02102 #endif
02103
02104 static char *dahdi_sig2str(int sig)
02105 {
02106 static char buf[256];
02107 switch (sig) {
02108 case SIG_EM:
02109 return "E & M Immediate";
02110 case SIG_EMWINK:
02111 return "E & M Wink";
02112 case SIG_EM_E1:
02113 return "E & M E1";
02114 case SIG_FEATD:
02115 return "Feature Group D (DTMF)";
02116 case SIG_FEATDMF:
02117 return "Feature Group D (MF)";
02118 case SIG_FEATDMF_TA:
02119 return "Feature Groud D (MF) Tandem Access";
02120 case SIG_FEATB:
02121 return "Feature Group B (MF)";
02122 case SIG_E911:
02123 return "E911 (MF)";
02124 case SIG_FGC_CAMA:
02125 return "FGC/CAMA (Dialpulse)";
02126 case SIG_FGC_CAMAMF:
02127 return "FGC/CAMA (MF)";
02128 case SIG_FXSLS:
02129 return "FXS Loopstart";
02130 case SIG_FXSGS:
02131 return "FXS Groundstart";
02132 case SIG_FXSKS:
02133 return "FXS Kewlstart";
02134 case SIG_FXOLS:
02135 return "FXO Loopstart";
02136 case SIG_FXOGS:
02137 return "FXO Groundstart";
02138 case SIG_FXOKS:
02139 return "FXO Kewlstart";
02140 case SIG_PRI:
02141 return "ISDN PRI";
02142 case SIG_MFCR2:
02143 return "MFC/R2";
02144 case SIG_SF:
02145 return "SF (Tone) Immediate";
02146 case SIG_SFWINK:
02147 return "SF (Tone) Wink";
02148 case SIG_SF_FEATD:
02149 return "SF (Tone) with Feature Group D (DTMF)";
02150 case SIG_SF_FEATDMF:
02151 return "SF (Tone) with Feature Group D (MF)";
02152 case SIG_SF_FEATB:
02153 return "SF (Tone) with Feature Group B (MF)";
02154 case SIG_GR303FXOKS:
02155 return "GR-303 with FXOKS";
02156 case SIG_GR303FXSKS:
02157 return "GR-303 with FXSKS";
02158 case 0:
02159 return "Pseudo";
02160 default:
02161 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02162 return buf;
02163 }
02164 }
02165
02166 #define sig2str dahdi_sig2str
02167
02168 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
02169 {
02170
02171
02172 struct dahdi_confinfo zi;
02173
02174 memset(&zi, 0, sizeof(zi));
02175 zi.chan = 0;
02176
02177 if (slavechannel > 0) {
02178
02179 zi.confmode = DAHDI_CONF_DIGITALMON;
02180 zi.confno = slavechannel;
02181 } else {
02182 if (!index) {
02183
02184 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02185 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02186 } else
02187 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02188 zi.confno = p->confno;
02189 }
02190 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02191 return 0;
02192 if (c->dfd < 0)
02193 return 0;
02194 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02195 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02196 return -1;
02197 }
02198 if (slavechannel < 1) {
02199 p->confno = zi.confno;
02200 }
02201 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02202 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02203 return 0;
02204 }
02205
02206 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02207 {
02208
02209 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02210 return 1;
02211
02212 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02213 return 1;
02214 return 0;
02215 }
02216
02217 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
02218 {
02219 struct dahdi_confinfo zi;
02220 if (
02221 (c->dfd < 0) ||
02222
02223 !isourconf(p, c)
02224
02225 ) return 0;
02226 memset(&zi, 0, sizeof(zi));
02227 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02228 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02229 return -1;
02230 }
02231 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02232 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02233 return 0;
02234 }
02235
02236 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02237 {
02238 int x;
02239 int useslavenative;
02240 struct dahdi_pvt *slave = NULL;
02241
02242 useslavenative = 1;
02243
02244 for (x = 0; x < 3; x++) {
02245
02246
02247 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02248 useslavenative = 0;
02249 }
02250
02251
02252 if (useslavenative) {
02253 for (x = 0; x < MAX_SLAVES; x++) {
02254 if (p->slaves[x]) {
02255 if (slave) {
02256
02257
02258 slave = NULL;
02259 useslavenative = 0;
02260 break;
02261 } else {
02262
02263 slave = p->slaves[x];
02264 }
02265 }
02266 }
02267 }
02268
02269 if (!slave)
02270 useslavenative = 0;
02271 else if (slave->law != p->law) {
02272 useslavenative = 0;
02273 slave = NULL;
02274 }
02275 if (out)
02276 *out = slave;
02277 return useslavenative;
02278 }
02279
02280 static int reset_conf(struct dahdi_pvt *p)
02281 {
02282 p->confno = -1;
02283 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02284 if (p->subs[SUB_REAL].dfd > -1) {
02285 struct dahdi_confinfo zi;
02286
02287 memset(&zi, 0, sizeof(zi));
02288 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02289 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02290 }
02291 return 0;
02292 }
02293
02294 static int update_conf(struct dahdi_pvt *p)
02295 {
02296 int needconf = 0;
02297 int x;
02298 int useslavenative;
02299 struct dahdi_pvt *slave = NULL;
02300
02301 useslavenative = isslavenative(p, &slave);
02302
02303 for (x = 0; x < 3; x++) {
02304
02305 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02306 conf_add(p, &p->subs[x], x, 0);
02307 needconf++;
02308 } else {
02309 conf_del(p, &p->subs[x], x);
02310 }
02311 }
02312
02313
02314 for (x = 0; x < MAX_SLAVES; x++) {
02315 if (p->slaves[x]) {
02316 if (useslavenative)
02317 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02318 else {
02319 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02320 needconf++;
02321 }
02322 }
02323 }
02324
02325 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02326 if (useslavenative)
02327 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02328 else {
02329 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02330 needconf++;
02331 }
02332 }
02333
02334 if (p->master) {
02335 if (isslavenative(p->master, NULL)) {
02336 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02337 } else {
02338 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02339 }
02340 }
02341 if (!needconf) {
02342
02343
02344 p->confno = -1;
02345 }
02346 if (option_debug)
02347 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02348 return 0;
02349 }
02350
02351 static void dahdi_enable_ec(struct dahdi_pvt *p)
02352 {
02353 int x;
02354 int res;
02355 if (!p)
02356 return;
02357 if (p->echocanon) {
02358 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
02359 return;
02360 }
02361 if (p->digital) {
02362 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
02363 return;
02364 }
02365 if (p->echocancel) {
02366 if (p->sig == SIG_PRI) {
02367 x = 1;
02368 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02369 if (res)
02370 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02371 }
02372 x = p->echocancel;
02373 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02374 if (res)
02375 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02376 else {
02377 p->echocanon = 1;
02378 if (option_debug)
02379 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
02380 }
02381 } else if (option_debug)
02382 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
02383 }
02384
02385 static void dahdi_train_ec(struct dahdi_pvt *p)
02386 {
02387 int x;
02388 int res;
02389 if (p && p->echocancel && p->echotraining) {
02390 x = p->echotraining;
02391 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02392 if (res)
02393 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02394 else {
02395 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
02396 }
02397 } else
02398 ast_log(LOG_DEBUG, "No echo training requested\n");
02399 }
02400
02401 static void dahdi_disable_ec(struct dahdi_pvt *p)
02402 {
02403 int x;
02404 int res;
02405 if (p->echocancel) {
02406 x = 0;
02407 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02408 if (res)
02409 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02410 else if (option_debug)
02411 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
02412 }
02413 p->echocanon = 0;
02414 }
02415
02416 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02417 {
02418 int j;
02419 int k;
02420 float linear_gain = pow(10.0, gain / 20.0);
02421
02422 switch (law) {
02423 case DAHDI_LAW_ALAW:
02424 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02425 if (gain) {
02426 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02427 if (k > 32767) k = 32767;
02428 if (k < -32767) k = -32767;
02429 g->txgain[j] = AST_LIN2A(k);
02430 } else {
02431 g->txgain[j] = j;
02432 }
02433 }
02434 break;
02435 case DAHDI_LAW_MULAW:
02436 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02437 if (gain) {
02438 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02439 if (k > 32767) k = 32767;
02440 if (k < -32767) k = -32767;
02441 g->txgain[j] = AST_LIN2MU(k);
02442 } else {
02443 g->txgain[j] = j;
02444 }
02445 }
02446 break;
02447 }
02448 }
02449
02450 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02451 {
02452 int j;
02453 int k;
02454 float linear_gain = pow(10.0, gain / 20.0);
02455
02456 switch (law) {
02457 case DAHDI_LAW_ALAW:
02458 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02459 if (gain) {
02460 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02461 if (k > 32767) k = 32767;
02462 if (k < -32767) k = -32767;
02463 g->rxgain[j] = AST_LIN2A(k);
02464 } else {
02465 g->rxgain[j] = j;
02466 }
02467 }
02468 break;
02469 case DAHDI_LAW_MULAW:
02470 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02471 if (gain) {
02472 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02473 if (k > 32767) k = 32767;
02474 if (k < -32767) k = -32767;
02475 g->rxgain[j] = AST_LIN2MU(k);
02476 } else {
02477 g->rxgain[j] = j;
02478 }
02479 }
02480 break;
02481 }
02482 }
02483
02484 static int set_actual_txgain(int fd, int chan, float gain, int law)
02485 {
02486 struct dahdi_gains g;
02487 int res;
02488
02489 memset(&g, 0, sizeof(g));
02490 g.chan = chan;
02491 res = ioctl(fd, DAHDI_GETGAINS, &g);
02492 if (res) {
02493 if (option_debug)
02494 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02495 return res;
02496 }
02497
02498 fill_txgain(&g, gain, law);
02499
02500 return ioctl(fd, DAHDI_SETGAINS, &g);
02501 }
02502
02503 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02504 {
02505 struct dahdi_gains g;
02506 int res;
02507
02508 memset(&g, 0, sizeof(g));
02509 g.chan = chan;
02510 res = ioctl(fd, DAHDI_GETGAINS, &g);
02511 if (res) {
02512 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02513 return res;
02514 }
02515
02516 fill_rxgain(&g, gain, law);
02517
02518 return ioctl(fd, DAHDI_SETGAINS, &g);
02519 }
02520
02521 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02522 {
02523 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02524 }
02525
02526 static int bump_gains(struct dahdi_pvt *p)
02527 {
02528 int res;
02529
02530
02531 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
02532 if (res) {
02533 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02534 return -1;
02535 }
02536
02537 return 0;
02538 }
02539
02540 static int restore_gains(struct dahdi_pvt *p)
02541 {
02542 int res;
02543
02544 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02545 if (res) {
02546 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02547 return -1;
02548 }
02549
02550 return 0;
02551 }
02552
02553 static inline int dahdi_set_hook(int fd, int hs)
02554 {
02555 int x, res;
02556
02557 x = hs;
02558 res = ioctl(fd, DAHDI_HOOK, &x);
02559
02560 if (res < 0) {
02561 if (errno == EINPROGRESS)
02562 return 0;
02563 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02564
02565 }
02566
02567 return res;
02568 }
02569
02570 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02571 {
02572 int x, y, res;
02573 x = muted;
02574 if (p->sig == SIG_PRI) {
02575 y = 1;
02576 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02577 if (res)
02578 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02579 }
02580 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02581 if (res < 0)
02582 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02583 return res;
02584 }
02585
02586 static int save_conference(struct dahdi_pvt *p)
02587 {
02588 struct dahdi_confinfo c;
02589 int res;
02590 if (p->saveconf.confmode) {
02591 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02592 return -1;
02593 }
02594 p->saveconf.chan = 0;
02595 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02596 if (res) {
02597 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02598 p->saveconf.confmode = 0;
02599 return -1;
02600 }
02601 memset(&c, 0, sizeof(c));
02602 c.confmode = DAHDI_CONF_NORMAL;
02603 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02604 if (res) {
02605 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02606 return -1;
02607 }
02608 if (option_debug)
02609 ast_log(LOG_DEBUG, "Disabled conferencing\n");
02610 return 0;
02611 }
02612
02613 static int restore_conference(struct dahdi_pvt *p)
02614 {
02615 int res;
02616 if (p->saveconf.confmode) {
02617 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02618 p->saveconf.confmode = 0;
02619 if (res) {
02620 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02621 return -1;
02622 }
02623 }
02624 if (option_debug)
02625 ast_log(LOG_DEBUG, "Restored conferencing\n");
02626 return 0;
02627 }
02628
02629 static int send_callerid(struct dahdi_pvt *p);
02630
02631 static int send_cwcidspill(struct dahdi_pvt *p)
02632 {
02633 p->callwaitcas = 0;
02634 p->cidcwexpire = 0;
02635 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02636 return -1;
02637 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02638
02639 p->cidlen += READ_SIZE * 4;
02640 p->cidpos = 0;
02641 send_callerid(p);
02642 if (option_verbose > 2)
02643 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02644 return 0;
02645 }
02646
02647 static int has_voicemail(struct dahdi_pvt *p)
02648 {
02649
02650 return ast_app_has_voicemail(p->mailbox, NULL);
02651 }
02652
02653 static int send_callerid(struct dahdi_pvt *p)
02654 {
02655
02656 int res;
02657
02658 if (p->subs[SUB_REAL].linear) {
02659 p->subs[SUB_REAL].linear = 0;
02660 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02661 }
02662 while (p->cidpos < p->cidlen) {
02663 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02664 if (res < 0) {
02665 if (errno == EAGAIN)
02666 return 0;
02667 else {
02668 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02669 return -1;
02670 }
02671 }
02672 if (!res)
02673 return 0;
02674 p->cidpos += res;
02675 }
02676 free(p->cidspill);
02677 p->cidspill = NULL;
02678 if (p->callwaitcas) {
02679
02680 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02681 } else
02682 restore_conference(p);
02683 return 0;
02684 }
02685
02686 static int dahdi_callwait(struct ast_channel *ast)
02687 {
02688 struct dahdi_pvt *p = ast->tech_pvt;
02689 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02690 if (p->cidspill) {
02691 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02692 free(p->cidspill);
02693 }
02694 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02695 return -1;
02696 save_conference(p);
02697
02698 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02699 if (!p->callwaitrings && p->callwaitingcallerid) {
02700 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02701 p->callwaitcas = 1;
02702 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02703 } else {
02704 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02705 p->callwaitcas = 0;
02706 p->cidlen = 2400 + READ_SIZE * 4;
02707 }
02708 p->cidpos = 0;
02709 send_callerid(p);
02710
02711 return 0;
02712 }
02713
02714 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02715 {
02716 struct dahdi_pvt *p = ast->tech_pvt;
02717 int x, res, index,mysig;
02718 char *c, *n, *l;
02719 #ifdef HAVE_PRI
02720 char *s = NULL;
02721 #endif
02722 char dest[256];
02723 ast_mutex_lock(&p->lock);
02724 ast_copy_string(dest, rdest, sizeof(dest));
02725 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02726 if ((ast->_state == AST_STATE_BUSY)) {
02727 p->subs[SUB_REAL].needbusy = 1;
02728 ast_mutex_unlock(&p->lock);
02729 return 0;
02730 }
02731 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02732 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02733 ast_mutex_unlock(&p->lock);
02734 return -1;
02735 }
02736 p->dialednone = 0;
02737 if ((p->radio || (p->oprmode < 0)))
02738 {
02739
02740 ast_setstate(ast, AST_STATE_UP);
02741 ast_mutex_unlock(&p->lock);
02742 return 0;
02743 }
02744 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02745 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02746 if (res)
02747 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02748 p->outgoing = 1;
02749
02750 if (IS_DIGITAL(ast->transfercapability)) {
02751 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02752 } else {
02753 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02754 }
02755
02756 mysig = p->sig;
02757 if (p->outsigmod > -1)
02758 mysig = p->outsigmod;
02759
02760 switch (mysig) {
02761 case SIG_FXOLS:
02762 case SIG_FXOGS:
02763 case SIG_FXOKS:
02764 if (p->owner == ast) {
02765
02766
02767
02768 p->dialing = 1;
02769 if (p->use_callerid) {
02770
02771 if (p->cidspill) {
02772 ast_log(LOG_WARNING, "cidspill already exists??\n");
02773 free(p->cidspill);
02774 }
02775 p->callwaitcas = 0;
02776 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02777 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02778 p->cidpos = 0;
02779 send_callerid(p);
02780 }
02781 }
02782
02783 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02784 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02785 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02786 p->cidrings = cidrings[p->distinctivering - 1];
02787 } else {
02788 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02789 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02790 p->cidrings = p->sendcalleridafter;
02791 }
02792
02793
02794 c = strchr(dest, '/');
02795 if (c)
02796 c++;
02797 if (c && (strlen(c) < p->stripmsd)) {
02798 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02799 c = NULL;
02800 }
02801 if (c) {
02802 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02803 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02804 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02805 } else {
02806 p->dop.dialstr[0] = '\0';
02807 }
02808 x = DAHDI_RING;
02809 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02810 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02811 ast_mutex_unlock(&p->lock);
02812 return -1;
02813 }
02814 p->dialing = 1;
02815 } else {
02816
02817 p->callwaitrings = 0;
02818 if (ast->cid.cid_num)
02819 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02820 else
02821 p->callwait_num[0] = '\0';
02822 if (ast->cid.cid_name)
02823 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02824 else
02825 p->callwait_name[0] = '\0';
02826
02827 if (dahdi_callwait(ast)) {
02828 ast_mutex_unlock(&p->lock);
02829 return -1;
02830 }
02831
02832 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02833 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02834
02835 }
02836 n = ast->cid.cid_name;
02837 l = ast->cid.cid_num;
02838 if (l)
02839 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02840 else
02841 p->lastcid_num[0] = '\0';
02842 if (n)
02843 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02844 else
02845 p->lastcid_name[0] = '\0';
02846 ast_setstate(ast, AST_STATE_RINGING);
02847 index = dahdi_get_index(ast, p, 0);
02848 if (index > -1) {
02849 p->subs[index].needringing = 1;
02850 }
02851 break;
02852 case SIG_FXSLS:
02853 case SIG_FXSGS:
02854 case SIG_FXSKS:
02855 case SIG_EMWINK:
02856 case SIG_EM:
02857 case SIG_EM_E1:
02858 case SIG_FEATD:
02859 case SIG_FEATDMF:
02860 case SIG_E911:
02861 case SIG_FGC_CAMA:
02862 case SIG_FGC_CAMAMF:
02863 case SIG_FEATB:
02864 case SIG_SFWINK:
02865 case SIG_SF:
02866 case SIG_SF_FEATD:
02867 case SIG_SF_FEATDMF:
02868 case SIG_FEATDMF_TA:
02869 case SIG_SF_FEATB:
02870 c = strchr(dest, '/');
02871 if (c)
02872 c++;
02873 else
02874 c = "";
02875 if (strlen(c) < p->stripmsd) {
02876 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02877 ast_mutex_unlock(&p->lock);
02878 return -1;
02879 }
02880 #ifdef HAVE_PRI
02881
02882 if (!p->pri) {
02883 #endif
02884 x = DAHDI_START;
02885 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02886 if (res < 0) {
02887 if (errno != EINPROGRESS) {
02888 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02889 ast_mutex_unlock(&p->lock);
02890 return -1;
02891 }
02892 }
02893 #ifdef HAVE_PRI
02894 }
02895 #endif
02896 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02897 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02898
02899 c += p->stripmsd;
02900
02901 switch (mysig) {
02902 case SIG_FEATD:
02903 l = ast->cid.cid_num;
02904 if (l)
02905 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02906 else
02907 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02908 break;
02909 case SIG_FEATDMF:
02910 l = ast->cid.cid_num;
02911 if (l)
02912 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02913 else
02914 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02915 break;
02916 case SIG_FEATDMF_TA:
02917 {
02918 const char *cic, *ozz;
02919
02920
02921 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02922 if (!ozz)
02923 ozz = defaultozz;
02924 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02925 if (!cic)
02926 cic = defaultcic;
02927 if (!ozz || !cic) {
02928 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02929 ast_mutex_unlock(&p->lock);
02930 return -1;
02931 }
02932 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02933 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02934 p->whichwink = 0;
02935 }
02936 break;
02937 case SIG_E911:
02938 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02939 break;
02940 case SIG_FGC_CAMA:
02941 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02942 break;
02943 case SIG_FGC_CAMAMF:
02944 case SIG_FEATB:
02945 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02946 break;
02947 default:
02948 if (p->pulse)
02949 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02950 else
02951 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02952 break;
02953 }
02954
02955 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02956 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02957 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02958 p->echorest[sizeof(p->echorest) - 1] = '\0';
02959 p->echobreak = 1;
02960 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02961 } else
02962 p->echobreak = 0;
02963 if (!res) {
02964 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02965 int saveerr = errno;
02966
02967 x = DAHDI_ONHOOK;
02968 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02969 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02970 ast_mutex_unlock(&p->lock);
02971 return -1;
02972 }
02973 } else
02974 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res);
02975 p->dialing = 1;
02976 if (ast_strlen_zero(c))
02977 p->dialednone = 1;
02978 ast_setstate(ast, AST_STATE_DIALING);
02979 break;
02980 case 0:
02981
02982 ast_setstate(ast, AST_STATE_UP);
02983 break;
02984 case SIG_PRI:
02985 case SIG_MFCR2:
02986
02987 p->dialdest[0] = '\0';
02988 p->dialing = 1;
02989 break;
02990 default:
02991 ast_log(LOG_DEBUG, "not yet implemented\n");
02992 ast_mutex_unlock(&p->lock);
02993 return -1;
02994 }
02995 #ifdef HAVE_OPENR2
02996 if (p->mfcr2) {
02997 int strip = p->stripmsd;
02998 int callres = 0;
02999 c = strchr(dest, '/');
03000 if (c) {
03001 c++;
03002 } else {
03003 c = dest;
03004 }
03005 if (!p->hidecallerid) {
03006 l = ast->cid.cid_num;
03007 } else {
03008 l = NULL;
03009 }
03010 if (strlen(c) < strip) {
03011 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
03012 strip = 0;
03013 }
03014 p->dialing = 1;
03015 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast));
03016 if (-1 == callres) {
03017 ast_mutex_unlock(&p->lock);
03018 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03019 return -1;
03020 }
03021 ast_setstate(ast, AST_STATE_DIALING);
03022 }
03023 #endif
03024 #ifdef HAVE_PRI
03025 if (p->pri) {
03026 struct pri_sr *sr;
03027 #ifdef SUPPORT_USERUSER
03028 const char *useruser;
03029 #endif
03030 int pridialplan;
03031 int dp_strip;
03032 int prilocaldialplan;
03033 int ldp_strip;
03034 int exclusive;
03035 const char *rr_str;
03036 int redirect_reason;
03037
03038 c = strchr(dest, '/');
03039 if (c) {
03040 c++;
03041 } else {
03042 c = "";
03043 }
03044
03045 l = NULL;
03046 n = NULL;
03047 if (!p->hidecallerid) {
03048 l = ast->cid.cid_num;
03049 if (!p->hidecalleridname) {
03050 n = ast->cid.cid_name;
03051 }
03052 }
03053
03054
03055 if (strlen(c) < p->stripmsd) {
03056 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03057 ast_mutex_unlock(&p->lock);
03058 return -1;
03059 }
03060 if (mysig != SIG_FXSKS) {
03061 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03062 s = strchr(c + p->stripmsd, 'w');
03063 if (s) {
03064 if (strlen(s) > 1)
03065 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03066 else
03067 p->dop.dialstr[0] = '\0';
03068 *s = '\0';
03069 } else {
03070 p->dop.dialstr[0] = '\0';
03071 }
03072 }
03073 if (pri_grab(p, p->pri)) {
03074 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03075 ast_mutex_unlock(&p->lock);
03076 return -1;
03077 }
03078 if (!(p->call = pri_new_call(p->pri->pri))) {
03079 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03080 pri_rel(p->pri);
03081 ast_mutex_unlock(&p->lock);
03082 return -1;
03083 }
03084 if (!(sr = pri_sr_new())) {
03085 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03086 pri_destroycall(p->pri->pri, p->call);
03087 p->call = NULL;
03088 pri_rel(p->pri);
03089 ast_mutex_unlock(&p->lock);
03090 return -1;
03091 }
03092 if (p->bearer || (mysig == SIG_FXSKS)) {
03093 if (p->bearer) {
03094 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);
03095 p->bearer->call = p->call;
03096 } else
03097 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
03098 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03099 }
03100 p->digital = IS_DIGITAL(ast->transfercapability);
03101
03102
03103 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03104 exclusive = 1;
03105 } else {
03106 exclusive = 0;
03107 }
03108
03109 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03110 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03111 (p->digital ? -1 :
03112 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03113 if (p->pri->facilityenable)
03114 pri_facility_enable(p->pri->pri);
03115
03116 if (option_verbose > 2)
03117 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03118 dp_strip = 0;
03119 pridialplan = p->pri->dialplan - 1;
03120 if (pridialplan == -2) {
03121 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03122 dp_strip = strlen(p->pri->internationalprefix);
03123 pridialplan = PRI_INTERNATIONAL_ISDN;
03124 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03125 dp_strip = strlen(p->pri->nationalprefix);
03126 pridialplan = PRI_NATIONAL_ISDN;
03127 } else {
03128 pridialplan = PRI_LOCAL_ISDN;
03129 }
03130 }
03131 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03132
03133 ldp_strip = 0;
03134 prilocaldialplan = p->pri->localdialplan - 1;
03135 if ((l != NULL) && (prilocaldialplan == -2)) {
03136 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03137 ldp_strip = strlen(p->pri->internationalprefix);
03138 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03139 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03140 ldp_strip = strlen(p->pri->nationalprefix);
03141 prilocaldialplan = PRI_NATIONAL_ISDN;
03142 } else {
03143 prilocaldialplan = PRI_LOCAL_ISDN;
03144 }
03145 }
03146 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03147 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03148 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03149 if (!strcasecmp(rr_str, "UNKNOWN"))
03150 redirect_reason = 0;
03151 else if (!strcasecmp(rr_str, "BUSY"))
03152 redirect_reason = 1;
03153 else if (!strcasecmp(rr_str, "NO_REPLY"))
03154 redirect_reason = 2;
03155 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03156 redirect_reason = 15;
03157 else
03158 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03159 } else
03160 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03161 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03162
03163 #ifdef SUPPORT_USERUSER
03164
03165 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03166
03167 if (useruser)
03168 pri_sr_set_useruser(sr, useruser);
03169 #endif
03170
03171 if (pri_setup(p->pri->pri, p->call, sr)) {
03172 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03173 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03174 pri_rel(p->pri);
03175 ast_mutex_unlock(&p->lock);
03176 pri_sr_free(sr);
03177 return -1;
03178 }
03179 pri_sr_free(sr);
03180 ast_setstate(ast, AST_STATE_DIALING);
03181 pri_rel(p->pri);
03182 }
03183 #endif
03184 ast_mutex_unlock(&p->lock);
03185 return 0;
03186 }
03187
03188 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03189 {
03190 struct dahdi_pvt *p = *pvt;
03191
03192 if (p->prev)
03193 p->prev->next = p->next;
03194 if (p->next)
03195 p->next->prev = p->prev;
03196 if (p->use_smdi)
03197 ast_smdi_interface_unref(p->smdi_iface);
03198 ast_mutex_destroy(&p->lock);
03199 dahdi_close_sub(p, SUB_REAL);
03200 if (p->owner)
03201 p->owner->tech_pvt = NULL;
03202 free(p);
03203 *pvt = NULL;
03204 }
03205
03206 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03207 {
03208 int owned = 0;
03209 int i = 0;
03210
03211 if (!now) {
03212 if (cur->owner) {
03213 owned = 1;
03214 }
03215
03216 for (i = 0; i < 3; i++) {
03217 if (cur->subs[i].owner) {
03218 owned = 1;
03219 }
03220 }
03221 if (!owned) {
03222 if (prev) {
03223 prev->next = cur->next;
03224 if (prev->next)
03225 prev->next->prev = prev;
03226 else
03227 ifend = prev;
03228 } else {
03229 iflist = cur->next;
03230 if (iflist)
03231 iflist->prev = NULL;
03232 else
03233 ifend = NULL;
03234 }
03235 destroy_dahdi_pvt(&cur);
03236 }
03237 } else {
03238 if (prev) {
03239 prev->next = cur->next;
03240 if (prev->next)
03241 prev->next->prev = prev;
03242 else
03243 ifend = prev;
03244 } else {
03245 iflist = cur->next;
03246 if (iflist)
03247 iflist->prev = NULL;
03248 else
03249 ifend = NULL;
03250 }
03251 destroy_dahdi_pvt(&cur);
03252 }
03253 return 0;
03254 }
03255
03256 static void destroy_all_channels(void)
03257 {
03258 int x;
03259 struct dahdi_pvt *p, *pl;
03260
03261 while (num_restart_pending) {
03262 usleep(1);
03263 }
03264
03265 ast_mutex_lock(&iflock);
03266
03267 p = iflist;
03268 while (p) {
03269
03270 if (p->cidspill)
03271 ast_free(p->cidspill);
03272 pl = p;
03273 p = p->next;
03274 x = pl->channel;
03275
03276 if (pl)
03277 destroy_dahdi_pvt(&pl);
03278 if (option_verbose > 2)
03279 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03280 }
03281 iflist = NULL;
03282 ifcount = 0;
03283 ast_mutex_unlock(&iflock);
03284 }
03285
03286 #ifdef HAVE_PRI
03287 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03288 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
03289
03290 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03291 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03292
03293 static char *dahdi_send_keypad_facility_descrip =
03294 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03295 " IE over the current channel.\n";
03296 static char *zap_send_keypad_facility_descrip =
03297 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03298 " IE over the current channel.\n";
03299
03300 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
03301 {
03302
03303 struct dahdi_pvt *p;
03304 char *digits = (char *) data;
03305
03306 if (ast_strlen_zero(digits)) {
03307 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
03308 return -1;
03309 }
03310
03311 p = (struct dahdi_pvt *)chan->tech_pvt;
03312
03313 if (!p) {
03314 ast_log(LOG_DEBUG, "Unable to find technology private\n");
03315 return -1;
03316 }
03317
03318 ast_mutex_lock(&p->lock);
03319
03320 if (!p->pri || !p->call) {
03321 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
03322 ast_mutex_unlock(&p->lock);
03323 return -1;
03324 }
03325
03326 if (!pri_grab(p, p->pri)) {
03327 pri_keypad_facility(p->pri->pri, p->call, digits);
03328 pri_rel(p->pri);
03329 } else {
03330 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
03331 ast_mutex_unlock(&p->lock);
03332 return -1;
03333 }
03334
03335 ast_mutex_unlock(&p->lock);
03336
03337 return 0;
03338 }
03339
03340 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03341 {
03342 return send_keypad_facility_exec(chan, data);
03343 }
03344
03345 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03346 {
03347 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);
03348 return send_keypad_facility_exec(chan, data);
03349 }
03350
03351 static int pri_is_up(struct dahdi_pri *pri)
03352 {
03353 int x;
03354 for (x = 0; x < NUM_DCHANS; x++) {
03355 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03356 return 1;
03357 }
03358 return 0;
03359 }
03360
03361 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03362 {
03363 bearer->owner = &inuse;
03364 bearer->realcall = crv;
03365 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03366 if (crv->subs[SUB_REAL].owner)
03367 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03368 crv->bearer = bearer;
03369 crv->call = bearer->call;
03370 crv->pri = pri;
03371 return 0;
03372 }
03373
03374 static char *pri_order(int level)
03375 {
03376 switch (level) {
03377 case 0:
03378 return "Primary";
03379 case 1:
03380 return "Secondary";
03381 case 2:
03382 return "Tertiary";
03383 case 3:
03384 return "Quaternary";
03385 default:
03386 return "<Unknown>";
03387 }
03388 }
03389
03390
03391 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03392 {
03393 int x = -1;
03394
03395 for (x = 0; x < NUM_DCHANS; x++) {
03396 if ((pri->dchans[x] == pri->pri))
03397 break;
03398 }
03399
03400 return pri->fds[x];
03401 }
03402
03403 static int pri_find_dchan(struct dahdi_pri *pri)
03404 {
03405 int oldslot = -1;
03406 struct pri *old;
03407 int newslot = -1;
03408 int x;
03409 old = pri->pri;
03410 for (x = 0; x < NUM_DCHANS; x++) {
03411 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03412 newslot = x;
03413 if (pri->dchans[x] == old) {
03414 oldslot = x;
03415 }
03416 }
03417 if (newslot < 0) {
03418 newslot = 0;
03419 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03420 pri->dchannels[newslot]);
03421 }
03422 if (old && (oldslot != newslot))
03423 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03424 pri->dchannels[oldslot], pri->dchannels[newslot]);
03425 pri->pri = pri->dchans[newslot];
03426 return 0;
03427 }
03428 #endif
03429
03430 #ifdef HAVE_OPENR2
03431 static char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
03432 static char *zap_accept_r2_call_app = "ZapAcceptR2Call";
03433
03434 static char *dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03435 static char *zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03436
03437 static char *dahdi_accept_r2_call_descrip =
03438 " DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03439 " You can specify yes or no as argument to accept with or without charge.\n";
03440
03441 static char *zap_accept_r2_call_descrip =
03442 " ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03443 " You can specify yes or no as argument to accept with or without charge.\n";
03444
03445 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
03446 {
03447
03448 openr2_call_mode_t accept_mode;
03449 int res, timeout, maxloops;
03450 struct ast_frame *f;
03451 struct dahdi_pvt *p;
03452 char *parse;
03453 AST_DECLARE_APP_ARGS(args,
03454 AST_APP_ARG(charge);
03455 );
03456
03457 if (ast_strlen_zero(data)) {
03458 ast_log(LOG_DEBUG, "No data sent to application!\n");
03459 return -1;
03460 }
03461
03462 if (chan->tech != &dahdi_tech) {
03463 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
03464 return -1;
03465 }
03466
03467 p = (struct dahdi_pvt *)chan->tech_pvt;
03468 if (!p) {
03469 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
03470 return -1;
03471 }
03472
03473 parse = ast_strdupa(data);
03474 AST_STANDARD_APP_ARGS(args, parse);
03475
03476 if (ast_strlen_zero(args.charge)) {
03477 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
03478 return -1;
03479 }
03480
03481 ast_mutex_lock(&p->lock);
03482 if (!p->mfcr2 || !p->mfcr2call) {
03483 ast_mutex_unlock(&p->lock);
03484 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
03485 return -1;
03486 }
03487
03488 if (p->mfcr2_call_accepted) {
03489 ast_mutex_unlock(&p->lock);
03490 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
03491 return 0;
03492 }
03493 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
03494 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
03495 ast_mutex_unlock(&p->lock);
03496 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03497 return -1;
03498 }
03499 ast_mutex_unlock(&p->lock);
03500
03501 res = 0;
03502 timeout = 100;
03503 maxloops = 50;
03504
03505 while (maxloops > 0) {
03506 maxloops--;
03507 if (ast_check_hangup(chan)) {
03508 break;
03509 }
03510 res = ast_waitfor(chan, timeout);
03511 if (res < 0) {
03512 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
03513 res = -1;
03514 break;
03515 }
03516 if (res == 0) {
03517 continue;
03518 }
03519 f = ast_read(chan);
03520 if (!f) {
03521 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
03522 res = -1;
03523 break;
03524 }
03525 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
03526 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
03527 ast_frfree(f);
03528 res = -1;
03529 break;
03530 }
03531 ast_frfree(f);
03532 ast_mutex_lock(&p->lock);
03533 if (p->mfcr2_call_accepted) {
03534 ast_mutex_unlock(&p->lock);
03535 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
03536 break;
03537 }
03538 ast_mutex_unlock(&p->lock);
03539 }
03540 if (res == -1) {
03541 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03542 }
03543 return res;
03544 }
03545
03546 static int zap_accept_r2_call_exec(struct ast_channel *chan, void *data)
03547 {
03548 return dahdi_accept_r2_call_exec(chan, data);
03549 }
03550
03551 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
03552 {
03553 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
03554 switch (cause) {
03555 case AST_CAUSE_USER_BUSY:
03556 case AST_CAUSE_CALL_REJECTED:
03557 case AST_CAUSE_INTERWORKING:
03558 r2cause = OR2_CAUSE_BUSY_NUMBER;
03559 break;
03560
03561 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
03562 case AST_CAUSE_SWITCH_CONGESTION:
03563 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
03564 break;
03565
03566 case AST_CAUSE_UNALLOCATED:
03567 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
03568 break;
03569
03570 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
03571 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03572 r2cause = OR2_CAUSE_OUT_OF_ORDER;
03573 break;
03574
03575 case AST_CAUSE_NO_ANSWER:
03576 case AST_CAUSE_NO_USER_RESPONSE:
03577 r2cause = OR2_CAUSE_NO_ANSWER;
03578 break;
03579
03580 default:
03581 r2cause = OR2_CAUSE_NORMAL_CLEARING;
03582 break;
03583 }
03584 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n",
03585 r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
03586 return r2cause;
03587 }
03588 #endif
03589
03590 static int dahdi_hangup(struct ast_channel *ast)
03591 {
03592 int res;
03593 int index,x, law;
03594
03595 struct dahdi_pvt *p = ast->tech_pvt;
03596 struct dahdi_pvt *tmp = NULL;
03597 struct dahdi_pvt *prev = NULL;
03598 struct dahdi_params par;
03599
03600 if (option_debug)
03601 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
03602 if (!ast->tech_pvt) {
03603 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03604 return 0;
03605 }
03606
03607 ast_mutex_lock(&p->lock);
03608
03609 index = dahdi_get_index(ast, p, 1);
03610
03611 if (p->sig == SIG_PRI) {
03612 x = 1;
03613 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03614 p->cid_num[0] = '\0';
03615 p->cid_name[0] = '\0';
03616 }
03617
03618 x = 0;
03619 dahdi_confmute(p, 0);
03620 restore_gains(p);
03621 if (p->origcid_num) {
03622 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03623 free(p->origcid_num);
03624 p->origcid_num = NULL;
03625 }
03626 if (p->origcid_name) {
03627 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03628 free(p->origcid_name);
03629 p->origcid_name = NULL;
03630 }
03631 if (p->dsp)
03632 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03633 p->exten[0] = '\0';
03634
03635 if (option_debug)
03636 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03637 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03638 p->ignoredtmf = 0;
03639
03640 if (index > -1) {
03641
03642 p->subs[index].owner = NULL;
03643 p->subs[index].needanswer = 0;
03644 p->subs[index].needflash = 0;
03645 p->subs[index].needringing = 0;
03646 p->subs[index].needbusy = 0;
03647 p->subs[index].needcongestion = 0;
03648 p->subs[index].linear = 0;
03649 p->subs[index].needcallerid = 0;
03650 p->polarity = POLARITY_IDLE;
03651 dahdi_setlinear(p->subs[index].dfd, 0);
03652 if (index == SUB_REAL) {
03653 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03654 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
03655 if (p->subs[SUB_CALLWAIT].inthreeway) {
03656
03657 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
03658
03659 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03660 unalloc_sub(p, SUB_CALLWAIT);
03661 p->owner = NULL;
03662 } else {
03663
03664 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03665 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03666 unalloc_sub(p, SUB_THREEWAY);
03667 if (p->subs[SUB_REAL].inthreeway) {
03668
03669
03670 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03671 p->owner = p->subs[SUB_REAL].owner;
03672 } else {
03673
03674 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03675 p->owner = NULL;
03676 }
03677 p->subs[SUB_REAL].inthreeway = 0;
03678 }
03679 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03680
03681 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03682 unalloc_sub(p, SUB_CALLWAIT);
03683 p->owner = p->subs[SUB_REAL].owner;
03684 if (p->owner->_state != AST_STATE_UP)
03685 p->subs[SUB_REAL].needanswer = 1;
03686 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03687 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03688 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03689 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03690 unalloc_sub(p, SUB_THREEWAY);
03691 if (p->subs[SUB_REAL].inthreeway) {
03692
03693
03694 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03695 p->owner = p->subs[SUB_REAL].owner;
03696 } else {
03697
03698 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03699 p->owner = NULL;
03700 }
03701 p->subs[SUB_REAL].inthreeway = 0;
03702 }
03703 } else if (index == SUB_CALLWAIT) {
03704
03705 if (p->subs[SUB_CALLWAIT].inthreeway) {
03706
03707
03708 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03709 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03710 S_OR(p->mohsuggest, NULL),
03711 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03712 }
03713 p->subs[SUB_THREEWAY].inthreeway = 0;
03714
03715 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03716 unalloc_sub(p, SUB_THREEWAY);
03717 } else
03718 unalloc_sub(p, SUB_CALLWAIT);
03719 } else if (index == SUB_THREEWAY) {
03720 if (p->subs[SUB_CALLWAIT].inthreeway) {
03721
03722
03723 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03724 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03725 S_OR(p->mohsuggest, NULL),
03726 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03727 }
03728 p->subs[SUB_CALLWAIT].inthreeway = 0;
03729 }
03730 p->subs[SUB_REAL].inthreeway = 0;
03731
03732
03733 unalloc_sub(p, SUB_THREEWAY);
03734 } else {
03735
03736 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03737 }
03738 }
03739
03740 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03741 p->owner = NULL;
03742 p->ringt = 0;
03743 p->distinctivering = 0;
03744 p->confirmanswer = 0;
03745 p->cidrings = 1;
03746 p->outgoing = 0;
03747 p->digital = 0;
03748 p->faxhandled = 0;
03749 p->pulsedial = 0;
03750 p->onhooktime = time(NULL);
03751 #ifdef HAVE_PRI
03752 p->proceeding = 0;
03753 p->dialing = 0;
03754 p->progress = 0;
03755 p->alerting = 0;
03756 p->setup_ack = 0;
03757 #endif
03758 if (p->dsp) {
03759 ast_dsp_free(p->dsp);
03760 p->dsp = NULL;
03761 }
03762
03763 law = DAHDI_LAW_DEFAULT;
03764 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03765 if (res < 0)
03766 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03767
03768 #ifdef HAVE_OPENR2
03769 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
03770 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
03771 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
03772 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
03773 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
03774 } else {
03775 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
03776 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
03777 openr2_call_disconnect_cause_t r2cause = r2cause_user
03778 ? dahdi_ast_cause_to_r2_cause(r2cause_user)
03779 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
03780 dahdi_r2_disconnect_call(p, r2cause);
03781 }
03782 } else if (p->mfcr2call) {
03783 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
03784 p->mfcr2call = 0;
03785 }
03786 #endif
03787 #ifdef HAVE_PRI
03788 if (p->pri) {
03789 #ifdef SUPPORT_USERUSER
03790 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03791 #endif
03792
03793
03794 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03795 if (!pri_grab(p, p->pri)) {
03796 if (p->alreadyhungup) {
03797 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
03798
03799 #ifdef SUPPORT_USERUSER
03800 pri_call_set_useruser(p->call, useruser);
03801 #endif
03802
03803 pri_hangup(p->pri->pri, p->call, -1);
03804 p->call = NULL;
03805 if (p->bearer)
03806 p->bearer->call = NULL;
03807 } else {
03808 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03809 int icause = ast->hangupcause ? ast->hangupcause : -1;
03810 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03811
03812 #ifdef SUPPORT_USERUSER
03813 pri_call_set_useruser(p->call, useruser);
03814 #endif
03815
03816 p->alreadyhungup = 1;
03817 if (p->bearer)
03818 p->bearer->alreadyhungup = 1;
03819 if (cause) {
03820 if (atoi(cause))
03821 icause = atoi(cause);
03822 }
03823 pri_hangup(p->pri->pri, p->call, icause);
03824 }
03825 if (res < 0)
03826 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03827 pri_rel(p->pri);
03828 } else {
03829 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03830 res = -1;
03831 }
03832 } else {
03833 if (p->bearer)
03834 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03835 p->call = NULL;
03836 res = 0;
03837 }
03838 }
03839 #endif
03840 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
03841 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03842 if (res < 0) {
03843 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03844 }
03845 switch (p->sig) {
03846 case SIG_FXOGS:
03847 case SIG_FXOLS:
03848 case SIG_FXOKS:
03849 memset(&par, 0, sizeof(par));
03850 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03851 if (!res) {
03852 #if 0
03853 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03854 #endif
03855
03856 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03857 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03858 else
03859 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03860 }
03861 break;
03862 case SIG_FXSGS:
03863 case SIG_FXSLS:
03864 case SIG_FXSKS:
03865
03866
03867 if (ast->_state != AST_STATE_RESERVED) {
03868 time(&p->guardtime);
03869 p->guardtime += 2;
03870 }
03871 break;
03872 default:
03873 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03874 }
03875 if (p->cidspill)
03876 free(p->cidspill);
03877 if (p->sig)
03878 dahdi_disable_ec(p);
03879 x = 0;
03880 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03881 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03882 p->didtdd = 0;
03883 p->cidspill = NULL;
03884 p->callwaitcas = 0;
03885 p->callwaiting = p->permcallwaiting;
03886 p->hidecallerid = p->permhidecallerid;
03887 p->dialing = 0;
03888 p->rdnis[0] = '\0';
03889 update_conf(p);
03890 reset_conf(p);
03891
03892 if (p->sig == SIG_PRI) {
03893 x = 0;
03894 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03895 }
03896 #ifdef HAVE_PRI
03897 if (p->bearer) {
03898 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03899
03900
03901 update_conf(p->bearer);
03902 reset_conf(p->bearer);
03903 p->bearer->owner = NULL;
03904 p->bearer->realcall = NULL;
03905 p->bearer = NULL;
03906 p->subs[SUB_REAL].dfd = -1;
03907 p->pri = NULL;
03908 }
03909 #endif
03910 if (num_restart_pending == 0)
03911 restart_monitor();
03912 }
03913
03914 p->callwaitingrepeat = 0;
03915 p->cidcwexpire = 0;
03916 p->oprmode = 0;
03917 ast->tech_pvt = NULL;
03918 ast_mutex_unlock(&p->lock);
03919 ast_module_unref(ast_module_info->self);
03920 if (option_verbose > 2)
03921 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03922
03923 ast_mutex_lock(&iflock);
03924
03925 if (p->restartpending) {
03926 num_restart_pending--;
03927 }
03928
03929 tmp = iflist;
03930 prev = NULL;
03931 if (p->destroy) {
03932 while (tmp) {
03933 if (tmp == p) {
03934 destroy_channel(prev, tmp, 0);
03935 break;
03936 } else {
03937 prev = tmp;
03938 tmp = tmp->next;
03939 }
03940 }
03941 }
03942 ast_mutex_unlock(&iflock);
03943 return 0;
03944 }
03945
03946 static int dahdi_answer(struct ast_channel *ast)
03947 {
03948 struct dahdi_pvt *p = ast->tech_pvt;
03949 int res = 0;
03950 int index;
03951 int oldstate = ast->_state;
03952 ast_setstate(ast, AST_STATE_UP);
03953 ast_mutex_lock(&p->lock);
03954 index = dahdi_get_index(ast, p, 0);
03955 if (index < 0)
03956 index = SUB_REAL;
03957
03958 if ((p->radio || (p->oprmode < 0))) {
03959 ast_mutex_unlock(&p->lock);
03960 return 0;
03961 }
03962 switch (p->sig) {
03963 case SIG_FXSLS:
03964 case SIG_FXSGS:
03965 case SIG_FXSKS:
03966 p->ringt = 0;
03967
03968 case SIG_EM:
03969 case SIG_EM_E1:
03970 case SIG_EMWINK:
03971 case SIG_FEATD:
03972 case SIG_FEATDMF:
03973 case SIG_FEATDMF_TA:
03974 case SIG_E911:
03975 case SIG_FGC_CAMA:
03976 case SIG_FGC_CAMAMF:
03977 case SIG_FEATB:
03978 case SIG_SF:
03979 case SIG_SFWINK:
03980 case SIG_SF_FEATD:
03981 case SIG_SF_FEATDMF:
03982 case SIG_SF_FEATB:
03983 case SIG_FXOLS:
03984 case SIG_FXOGS:
03985 case SIG_FXOKS:
03986
03987 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03988 if (p->hanguponpolarityswitch) {
03989 gettimeofday(&p->polaritydelaytv, NULL);
03990 }
03991 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03992 tone_zone_play_tone(p->subs[index].dfd, -1);
03993 p->dialing = 0;
03994 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03995 if (oldstate == AST_STATE_RINGING) {
03996 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03997 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03998 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03999 p->owner = p->subs[SUB_REAL].owner;
04000 }
04001 }
04002 if (p->sig & __DAHDI_SIG_FXS) {
04003 dahdi_enable_ec(p);
04004 dahdi_train_ec(p);
04005 }
04006 break;
04007 #ifdef HAVE_PRI
04008 case SIG_PRI:
04009
04010 if (!pri_grab(p, p->pri)) {
04011 p->proceeding = 1;
04012 p->dialing = 0;
04013 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04014 pri_rel(p->pri);
04015 } else {
04016 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04017 res = -1;
04018 }
04019 break;
04020 #endif
04021 #ifdef HAVE_OPENR2
04022 case SIG_MFCR2:
04023 if (!p->mfcr2_accept_on_offer) {
04024
04025
04026 if (p->mfcr2_charge_calls) {
04027 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
04028 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04029 } else {
04030 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
04031 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04032 }
04033 } else {
04034 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04035 res = dahdi_r2_answer(p);
04036 }
04037 break;
04038 #endif
04039 case 0:
04040 ast_mutex_unlock(&p->lock);
04041 return 0;
04042 default:
04043 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04044 res = -1;
04045 }
04046 ast_mutex_unlock(&p->lock);
04047 return res;
04048 }
04049
04050 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04051 {
04052 char *cp;
04053 signed char *scp;
04054 int x;
04055 int index;
04056 struct dahdi_pvt *p = chan->tech_pvt, *pp;
04057 struct oprmode *oprmode;
04058
04059
04060
04061 if (!data || (datalen < 1)) {
04062 errno = EINVAL;
04063 return -1;
04064 }
04065
04066 switch (option) {
04067 case AST_OPTION_TXGAIN:
04068 scp = (signed char *) data;
04069 index = dahdi_get_index(chan, p, 0);
04070 if (index < 0) {
04071 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04072 return -1;
04073 }
04074 if (option_debug)
04075 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04076 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
04077 case AST_OPTION_RXGAIN:
04078 scp = (signed char *) data;
04079 index = dahdi_get_index(chan, p, 0);
04080 if (index < 0) {
04081 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04082 return -1;
04083 }
04084 if (option_debug)
04085 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04086 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
04087 case AST_OPTION_TONE_VERIFY:
04088 if (!p->dsp)
04089 break;
04090 cp = (char *) data;
04091 switch (*cp) {
04092 case 1:
04093 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04094 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
04095 break;
04096 case 2:
04097 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04098 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
04099 break;
04100 default:
04101 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04102 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
04103 break;
04104 }
04105 break;
04106 case AST_OPTION_TDD:
04107
04108 cp = (char *) data;
04109 p->mate = 0;
04110 if (!*cp) {
04111 if (option_debug)
04112 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04113 if (p->tdd)
04114 tdd_free(p->tdd);
04115 p->tdd = 0;
04116 break;
04117 }
04118 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
04119 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04120 dahdi_disable_ec(p);
04121
04122 if (!p->didtdd) {
04123 unsigned char mybuf[41000];
04124 unsigned char *buf;
04125 int size, res, fd, len;
04126 struct pollfd fds[1];
04127
04128 buf = mybuf;
04129 memset(buf, 0x7f, sizeof(mybuf));
04130 ast_tdd_gen_ecdisa(buf + 16000, 16000);
04131 len = 40000;
04132 index = dahdi_get_index(chan, p, 0);
04133 if (index < 0) {
04134 ast_log(LOG_WARNING, "No index in TDD?\n");
04135 return -1;
04136 }
04137 fd = p->subs[index].dfd;
04138 while (len) {
04139 if (ast_check_hangup(chan))
04140 return -1;
04141 size = len;
04142 if (size > READ_SIZE)
04143 size = READ_SIZE;
04144 fds[0].fd = fd;
04145 fds[0].events = POLLPRI | POLLOUT;
04146 fds[0].revents = 0;
04147 res = poll(fds, 1, -1);
04148 if (!res) {
04149 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
04150 continue;
04151 }
04152
04153 if (fds[0].revents & POLLPRI)
04154 return -1;
04155 if (!(fds[0].revents & POLLOUT)) {
04156 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
04157 continue;
04158 }
04159 res = write(fd, buf, size);
04160 if (res != size) {
04161 if (res == -1) return -1;
04162 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04163 break;
04164 }
04165 len -= size;
04166 buf += size;
04167 }
04168 p->didtdd = 1;
04169 }
04170 if (*cp == 2) {
04171 if (p->tdd)
04172 tdd_free(p->tdd);
04173 p->tdd = 0;
04174 p->mate = 1;
04175 break;
04176 }
04177 if (!p->tdd) {
04178 p->tdd = tdd_new();
04179 }
04180 break;
04181 case AST_OPTION_RELAXDTMF:
04182 if (!p->dsp)
04183 break;
04184 cp = (char *) data;
04185 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04186 *cp ? "ON" : "OFF", (int) *cp, chan->name);
04187 p->dtmfrelax = 0;
04188 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
04189 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04190 break;
04191 case AST_OPTION_AUDIO_MODE:
04192 cp = (char *) data;
04193 if (!*cp) {
04194 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04195 x = 0;
04196 dahdi_disable_ec(p);
04197 } else {
04198 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04199 x = 1;
04200 }
04201 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04202 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04203 break;
04204 case AST_OPTION_OPRMODE:
04205 oprmode = (struct oprmode *) data;
04206 pp = oprmode->peer->tech_pvt;
04207 p->oprmode = pp->oprmode = 0;
04208
04209 p->oprpeer = pp;
04210 pp->oprpeer = p;
04211
04212 if (oprmode->mode)
04213 {
04214 pp->oprmode = oprmode->mode;
04215 p->oprmode = -oprmode->mode;
04216 }
04217 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
04218 oprmode->mode, chan->name,oprmode->peer->name);;
04219 break;
04220 case AST_OPTION_ECHOCAN:
04221 cp = (char *) data;
04222 if (*cp) {
04223 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
04224 dahdi_enable_ec(p);
04225 } else {
04226 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
04227 dahdi_disable_ec(p);
04228 }
04229 break;
04230 }
04231 errno = 0;
04232
04233 return 0;
04234 }
04235
04236 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
04237 {
04238 struct dahdi_pvt *p = chan->tech_pvt;
04239
04240 if (!strcasecmp(data, "rxgain")) {
04241 ast_mutex_lock(&p->lock);
04242 snprintf(buf, len, "%f", p->rxgain);
04243 ast_mutex_unlock(&p->lock);
04244 } else if (!strcasecmp(data, "txgain")) {
04245 ast_mutex_lock(&p->lock);
04246 snprintf(buf, len, "%f", p->txgain);
04247 ast_mutex_unlock(&p->lock);
04248 } else {
04249 ast_copy_string(buf, "", len);
04250 }
04251 return 0;
04252 }
04253
04254
04255 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04256 {
04257
04258 int x;
04259 int hasslaves;
04260 if (!master)
04261 return;
04262 if (needlock) {
04263 ast_mutex_lock(&master->lock);
04264 if (slave) {
04265 while (ast_mutex_trylock(&slave->lock)) {
04266 DEADLOCK_AVOIDANCE(&master->lock);
04267 }
04268 }
04269 }
04270 hasslaves = 0;
04271 for (x = 0; x < MAX_SLAVES; x++) {
04272 if (master->slaves[x]) {
04273 if (!slave || (master->slaves[x] == slave)) {
04274
04275 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04276 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04277 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04278 master->slaves[x]->master = NULL;
04279 master->slaves[x] = NULL;
04280 } else
04281 hasslaves = 1;
04282 }
04283 if (!hasslaves)
04284 master->inconference = 0;
04285 }
04286 if (!slave) {
04287 if (master->master) {
04288
04289 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04290 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04291 hasslaves = 0;
04292 for (x = 0; x < MAX_SLAVES; x++) {
04293 if (master->master->slaves[x] == master)
04294 master->master->slaves[x] = NULL;
04295 else if (master->master->slaves[x])
04296 hasslaves = 1;
04297 }
04298 if (!hasslaves)
04299 master->master->inconference = 0;
04300 }
04301 master->master = NULL;
04302 }
04303 update_conf(master);
04304 if (needlock) {
04305 if (slave)
04306 ast_mutex_unlock(&slave->lock);
04307 ast_mutex_unlock(&master->lock);
04308 }
04309 }
04310
04311 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04312 int x;
04313 if (!slave || !master) {
04314 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04315 return;
04316 }
04317 for (x = 0; x < MAX_SLAVES; x++) {
04318 if (!master->slaves[x]) {
04319 master->slaves[x] = slave;
04320 break;
04321 }
04322 }
04323 if (x >= MAX_SLAVES) {
04324 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04325 master->slaves[MAX_SLAVES - 1] = slave;
04326 }
04327 if (slave->master)
04328 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04329 slave->master = master;
04330
04331 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04332 }
04333
04334 static void disable_dtmf_detect(struct dahdi_pvt *p)
04335 {
04336 #ifdef DAHDI_TONEDETECT
04337 int val;
04338 #endif
04339
04340 p->ignoredtmf = 1;
04341
04342 #ifdef DAHDI_TONEDETECT
04343 val = 0;
04344 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04345 #endif
04346 if (!p->hardwaredtmf && p->dsp) {
04347 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04348 ast_dsp_set_features(p->dsp, p->dsp_features);
04349 }
04350 }
04351
04352 static void enable_dtmf_detect(struct dahdi_pvt *p)
04353 {
04354 #ifdef DAHDI_TONEDETECT
04355 int val;
04356 #endif
04357
04358 if (p->channel == CHAN_PSEUDO)
04359 return;
04360
04361 p->ignoredtmf = 0;
04362
04363 #ifdef DAHDI_TONEDETECT
04364 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04365 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04366 #endif
04367 if (!p->hardwaredtmf && p->dsp) {
04368 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04369 ast_dsp_set_features(p->dsp, p->dsp_features);
04370 }
04371 }
04372
04373 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)
04374 {
04375 struct ast_channel *who;
04376 struct dahdi_pvt *p0, *p1, *op0, *op1;
04377 struct dahdi_pvt *master = NULL, *slave = NULL;
04378 struct ast_frame *f;
04379 int inconf = 0;
04380 int nothingok = 1;
04381 int ofd0, ofd1;
04382 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04383 int os0 = -1, os1 = -1;
04384 int priority = 0;
04385 struct ast_channel *oc0, *oc1;
04386 enum ast_bridge_result res;
04387
04388 #ifdef PRI_2BCT
04389 int triedtopribridge = 0;
04390 q931_call *q931c0 = NULL, *q931c1 = NULL;
04391 #endif
04392
04393
04394
04395
04396
04397
04398 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04399 return AST_BRIDGE_FAILED_NOWARN;
04400
04401 ast_mutex_lock(&c0->lock);
04402 while (ast_mutex_trylock(&c1->lock)) {
04403 DEADLOCK_AVOIDANCE(&c0->lock);
04404 }
04405
04406 p0 = c0->tech_pvt;
04407 p1 = c1->tech_pvt;
04408
04409 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04410 ast_mutex_unlock(&c0->lock);
04411 ast_mutex_unlock(&c1->lock);
04412 return AST_BRIDGE_FAILED_NOWARN;
04413 }
04414
04415 oi0 = dahdi_get_index(c0, p0, 0);
04416 oi1 = dahdi_get_index(c1, p1, 0);
04417 if ((oi0 < 0) || (oi1 < 0)) {
04418 ast_mutex_unlock(&c0->lock);
04419 ast_mutex_unlock(&c1->lock);
04420 return AST_BRIDGE_FAILED;
04421 }
04422
04423 op0 = p0 = c0->tech_pvt;
04424 op1 = p1 = c1->tech_pvt;
04425 ofd0 = c0->fds[0];
04426 ofd1 = c1->fds[0];
04427 oc0 = p0->owner;
04428 oc1 = p1->owner;
04429
04430 if (ast_mutex_trylock(&p0->lock)) {
04431
04432 ast_mutex_unlock(&c0->lock);
04433 ast_mutex_unlock(&c1->lock);
04434 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04435 return AST_BRIDGE_RETRY;
04436 }
04437 if (ast_mutex_trylock(&p1->lock)) {
04438
04439 ast_mutex_unlock(&p0->lock);
04440 ast_mutex_unlock(&c0->lock);
04441 ast_mutex_unlock(&c1->lock);
04442 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04443 return AST_BRIDGE_RETRY;
04444 }
04445
04446 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04447 if (p0->owner && p1->owner) {
04448
04449 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04450 master = p0;
04451 slave = p1;
04452 inconf = 1;
04453 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04454 master = p1;
04455 slave = p0;
04456 inconf = 1;
04457 } else {
04458 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04459 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04460 p0->channel,
04461 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04462 p0->subs[SUB_REAL].inthreeway, p0->channel,
04463 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04464 p1->subs[SUB_REAL].inthreeway);
04465 }
04466 nothingok = 0;
04467 }
04468 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04469 if (p1->subs[SUB_THREEWAY].inthreeway) {
04470 master = p1;
04471 slave = p0;
04472 nothingok = 0;
04473 }
04474 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04475 if (p0->subs[SUB_THREEWAY].inthreeway) {
04476 master = p0;
04477 slave = p1;
04478 nothingok = 0;
04479 }
04480 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04481
04482
04483 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04484 master = p1;
04485 slave = p0;
04486 nothingok = 0;
04487 }
04488 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04489
04490 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04491 master = p0;
04492 slave = p1;
04493 nothingok = 0;
04494 }
04495 }
04496 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
04497 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04498 if (master && slave) {
04499
04500
04501
04502 if ((oi1 == SUB_THREEWAY) &&
04503 p1->subs[SUB_THREEWAY].inthreeway &&
04504 p1->subs[SUB_REAL].owner &&
04505 p1->subs[SUB_REAL].inthreeway &&
04506 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04507 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04508 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04509 os1 = p1->subs[SUB_REAL].owner->_state;
04510 } else {
04511 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04512 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04513 }
04514 if ((oi0 == SUB_THREEWAY) &&
04515 p0->subs[SUB_THREEWAY].inthreeway &&
04516 p0->subs[SUB_REAL].owner &&
04517 p0->subs[SUB_REAL].inthreeway &&
04518 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04519 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04520 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04521 os0 = p0->subs[SUB_REAL].owner->_state;
04522 } else {
04523 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04524 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04525 }
04526 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04527 if (!p0->echocanbridged || !p1->echocanbridged) {
04528
04529 dahdi_disable_ec(p0);
04530 dahdi_disable_ec(p1);
04531 }
04532 }
04533 dahdi_link(slave, master);
04534 master->inconference = inconf;
04535 } else if (!nothingok)
04536 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04537
04538 update_conf(p0);
04539 update_conf(p1);
04540 t0 = p0->subs[SUB_REAL].inthreeway;
04541 t1 = p1->subs[SUB_REAL].inthreeway;
04542
04543 ast_mutex_unlock(&p0->lock);
04544 ast_mutex_unlock(&p1->lock);
04545
04546 ast_mutex_unlock(&c0->lock);
04547 ast_mutex_unlock(&c1->lock);
04548
04549
04550 if ((!master || !slave) && !nothingok) {
04551 dahdi_enable_ec(p0);
04552 dahdi_enable_ec(p1);
04553 return AST_BRIDGE_FAILED;
04554 }
04555
04556 if (option_verbose > 2)
04557 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
04558
04559 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04560 disable_dtmf_detect(op0);
04561
04562 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04563 disable_dtmf_detect(op1);
04564
04565 for (;;) {
04566 struct ast_channel *c0_priority[2] = {c0, c1};
04567 struct ast_channel *c1_priority[2] = {c1, c0};
04568
04569
04570
04571 ast_mutex_lock(&c0->lock);
04572 while (ast_mutex_trylock(&c1->lock)) {
04573 DEADLOCK_AVOIDANCE(&c0->lock);
04574 }
04575
04576 p0 = c0->tech_pvt;
04577 p1 = c1->tech_pvt;
04578
04579 if (op0 == p0)
04580 i0 = dahdi_get_index(c0, p0, 1);
04581 if (op1 == p1)
04582 i1 = dahdi_get_index(c1, p1, 1);
04583 ast_mutex_unlock(&c0->lock);
04584 ast_mutex_unlock(&c1->lock);
04585
04586 if (!timeoutms ||
04587 (op0 != p0) ||
04588 (op1 != p1) ||
04589 (ofd0 != c0->fds[0]) ||
04590 (ofd1 != c1->fds[0]) ||
04591 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04592 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04593 (oc0 != p0->owner) ||
04594 (oc1 != p1->owner) ||
04595 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04596 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04597 (oi0 != i0) ||
04598 (oi1 != i1)) {
04599 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04600 op0->channel, oi0, op1->channel, oi1);
04601 res = AST_BRIDGE_RETRY;
04602 goto return_from_bridge;
04603 }
04604
04605 #ifdef PRI_2BCT
04606 q931c0 = p0->call;
04607 q931c1 = p1->call;
04608 if (p0->transfer && p1->transfer
04609 && q931c0 && q931c1
04610 && !triedtopribridge) {
04611 pri_channel_bridge(q931c0, q931c1);
04612 triedtopribridge = 1;
04613 }
04614 #endif
04615
04616 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04617 if (!who) {
04618 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
04619 continue;
04620 }
04621 f = ast_read(who);
04622 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04623 *fo = f;
04624 *rc = who;
04625 res = AST_BRIDGE_COMPLETE;
04626 goto return_from_bridge;
04627 }
04628 if (f->frametype == AST_FRAME_DTMF) {
04629 if ((who == c0) && p0->pulsedial) {
04630 ast_write(c1, f);
04631 } else if ((who == c1) && p1->pulsedial) {
04632 ast_write(c0, f);
04633 } else {
04634 *fo = f;
04635 *rc = who;
04636 res = AST_BRIDGE_COMPLETE;
04637 goto return_from_bridge;
04638 }
04639 }
04640 ast_frfree(f);
04641
04642
04643 priority = !priority;
04644 }
04645
04646 return_from_bridge:
04647 if (op0 == p0)
04648 dahdi_enable_ec(p0);
04649
04650 if (op1 == p1)
04651 dahdi_enable_ec(p1);
04652
04653 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04654 enable_dtmf_detect(op0);
04655
04656 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04657 enable_dtmf_detect(op1);
04658
04659 dahdi_unlink(slave, master, 1);
04660
04661 return res;
04662 }
04663
04664 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04665 {
04666 struct dahdi_pvt *p = newchan->tech_pvt;
04667 int x;
04668 ast_mutex_lock(&p->lock);
04669 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
04670 if (p->owner == oldchan) {
04671 p->owner = newchan;
04672 }
04673 for (x = 0; x < 3; x++)
04674 if (p->subs[x].owner == oldchan) {
04675 if (!x)
04676 dahdi_unlink(NULL, p, 0);
04677 p->subs[x].owner = newchan;
04678 }
04679 if (newchan->_state == AST_STATE_RINGING)
04680 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04681 update_conf(p);
04682 ast_mutex_unlock(&p->lock);
04683 return 0;
04684 }
04685
04686 static int dahdi_ring_phone(struct dahdi_pvt *p)
04687 {
04688 int x;
04689 int res;
04690
04691 x = 0;
04692 x = DAHDI_ONHOOK;
04693 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04694 do {
04695 x = DAHDI_RING;
04696 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04697 if (res) {
04698 switch (errno) {
04699 case EBUSY:
04700 case EINTR:
04701
04702 usleep(10000);
04703 continue;
04704 case EINPROGRESS:
04705 res = 0;
04706 break;
04707 default:
04708 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04709 res = 0;
04710 }
04711 }
04712 } while (res);
04713 return res;
04714 }
04715
04716 static void *ss_thread(void *data);
04717
04718 static int attempt_transfer(struct dahdi_pvt *p)
04719 {
04720
04721
04722
04723 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04724
04725
04726 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04727 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04728 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04729 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04730 }
04731 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04732 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04733 }
04734 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04735 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04736 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04737 return -1;
04738 }
04739
04740 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04741 unalloc_sub(p, SUB_THREEWAY);
04742 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04743 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04744 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04745 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04746 }
04747 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04748 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04749 }
04750 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04751 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04752 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04753 return -1;
04754 }
04755
04756 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04757 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
04758 unalloc_sub(p, SUB_THREEWAY);
04759
04760 return 1;
04761 } else {
04762 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04763 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04764 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04765 return -1;
04766 }
04767 return 0;
04768 }
04769
04770 static int check_for_conference(struct dahdi_pvt *p)
04771 {
04772 struct dahdi_confinfo ci;
04773
04774 if (p->master || (p->confno > -1))
04775 return 0;
04776 memset(&ci, 0, sizeof(ci));
04777 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04778 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04779 return 0;
04780 }
04781
04782
04783
04784 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04785 if (option_verbose > 2)
04786 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
04787 return 1;
04788 }
04789 return 0;
04790 }
04791
04792 static int get_alarms(struct dahdi_pvt *p)
04793 {
04794 int res;
04795 struct dahdi_spaninfo zi;
04796 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04797
04798
04799
04800
04801
04802 struct dahdi_params params;
04803 #endif
04804
04805 memset(&zi, 0, sizeof(zi));
04806 zi.spanno = p->span;
04807
04808
04809 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
04810 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04811 return 0;
04812 }
04813 if (zi.alarms != DAHDI_ALARM_NONE)
04814 return zi.alarms;
04815 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04816
04817 memset(¶ms, 0, sizeof(params));
04818 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04819 return params.chan_alarms;
04820
04821 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04822 #endif
04823 return DAHDI_ALARM_NONE;
04824 }
04825
04826 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04827 {
04828 struct dahdi_pvt *p = ast->tech_pvt;
04829 struct ast_frame *f = *dest;
04830
04831 if (option_debug)
04832 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04833
04834 if (p->confirmanswer) {
04835 if (option_debug)
04836 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04837
04838
04839 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04840 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04841 *dest = &p->subs[index].f;
04842
04843 p->confirmanswer = 0;
04844 } else if (p->callwaitcas) {
04845 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04846 if (option_debug)
04847 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04848 if (p->cidspill)
04849 free(p->cidspill);
04850 send_cwcidspill(p);
04851 }
04852 if ((f->subclass != 'm') && (f->subclass != 'u'))
04853 p->callwaitcas = 0;
04854 p->subs[index].f.frametype = AST_FRAME_NULL;
04855 p->subs[index].f.subclass = 0;
04856 *dest = &p->subs[index].f;
04857 } else if (f->subclass == 'f') {
04858
04859 if ((p->callprogress & 0x6) && !p->faxhandled) {
04860 p->faxhandled = 1;
04861 if (strcmp(ast->exten, "fax")) {
04862 const char *target_context = S_OR(ast->macrocontext, ast->context);
04863
04864
04865
04866
04867
04868 ast_mutex_unlock(&p->lock);
04869 ast_channel_unlock(ast);
04870 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04871 ast_channel_lock(ast);
04872 ast_mutex_lock(&p->lock);
04873 if (option_verbose > 2)
04874 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04875
04876 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04877 if (ast_async_goto(ast, target_context, "fax", 1))
04878 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04879 } else {
04880 ast_channel_lock(ast);
04881 ast_mutex_lock(&p->lock);
04882 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04883 }
04884 } else if (option_debug)
04885 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04886 } else if (option_debug)
04887 ast_log(LOG_DEBUG, "Fax already handled\n");
04888 dahdi_confmute(p, 0);
04889 p->subs[index].f.frametype = AST_FRAME_NULL;
04890 p->subs[index].f.subclass = 0;
04891 *dest = &p->subs[index].f;
04892 } else if (f->subclass == 'm') {
04893
04894 dahdi_confmute(p, 1);
04895 p->subs[index].f.frametype = AST_FRAME_NULL;
04896 p->subs[index].f.subclass = 0;
04897 *dest = &p->subs[index].f;
04898 } else if (f->subclass == 'u') {
04899
04900 dahdi_confmute(p, 0);
04901 p->subs[index].f.frametype = AST_FRAME_NULL;
04902 p->subs[index].f.subclass = 0;
04903 *dest = &p->subs[index].f;
04904 } else
04905 dahdi_confmute(p, 0);
04906 }
04907
04908 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04909 {
04910 const char *alarm_str = alarm2str(alarms);
04911
04912
04913
04914 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04915 p->unknown_alarm = 1;
04916 return;
04917 } else {
04918 p->unknown_alarm = 0;
04919 }
04920
04921 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04922 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04923 "Alarm: %s\r\n"
04924 "Channel: %d\r\n",
04925 alarm_str, p->channel);
04926 }
04927
04928 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04929 {
04930 int res, x;
04931 int index, mysig;
04932 char *c;
04933 struct dahdi_pvt *p = ast->tech_pvt;
04934 pthread_t threadid;
04935 pthread_attr_t attr;
04936 struct ast_channel *chan;
04937 struct ast_frame *f;
04938
04939 index = dahdi_get_index(ast, p, 0);
04940 mysig = p->sig;
04941 if (p->outsigmod > -1)
04942 mysig = p->outsigmod;
04943 p->subs[index].f.frametype = AST_FRAME_NULL;
04944 p->subs[index].f.subclass = 0;
04945 p->subs[index].f.datalen = 0;
04946 p->subs[index].f.samples = 0;
04947 p->subs[index].f.mallocd = 0;
04948 p->subs[index].f.offset = 0;
04949 p->subs[index].f.src = "dahdi_handle_event";
04950 p->subs[index].f.data = NULL;
04951 f = &p->subs[index].f;
04952
04953 if (index < 0)
04954 return &p->subs[index].f;
04955 if (p->fake_event) {
04956 res = p->fake_event;
04957 p->fake_event = 0;
04958 } else
04959 res = dahdi_get_event(p->subs[index].dfd);
04960
04961 if (option_debug)
04962 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04963
04964 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04965 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04966
04967 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04968 #ifdef HAVE_PRI
04969 if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04970
04971 } else {
04972 #endif
04973 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04974 p->subs[index].f.subclass = res & 0xff;
04975 #ifdef HAVE_PRI
04976 }
04977 #endif
04978 dahdi_handle_dtmfup(ast, index, &f);
04979 return f;
04980 }
04981
04982 if (res & DAHDI_EVENT_DTMFDOWN) {
04983 if (option_debug)
04984 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04985
04986 dahdi_confmute(p, 1);
04987 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04988 p->subs[index].f.subclass = res & 0xff;
04989 return &p->subs[index].f;
04990 }
04991
04992 switch (res) {
04993 #ifdef DAHDI_EVENT_EC_DISABLED
04994 case DAHDI_EVENT_EC_DISABLED:
04995 if (option_verbose > 2)
04996 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04997 p->echocanon = 0;
04998 break;
04999 #endif
05000 case DAHDI_EVENT_BITSCHANGED:
05001 #ifdef HAVE_OPENR2
05002 if (p->sig != SIG_MFCR2) {
05003 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05004 } else {
05005 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05006 openr2_chan_handle_cas(p->r2chan);
05007 }
05008 #else
05009 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05010 #endif
05011 case DAHDI_EVENT_PULSE_START:
05012
05013 if (!ast->pbx)
05014 tone_zone_play_tone(p->subs[index].dfd, -1);
05015 break;
05016 case DAHDI_EVENT_DIALCOMPLETE:
05017 #ifdef HAVE_OPENR2
05018 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05019
05020
05021 break;
05022 }
05023 #endif
05024 if (p->inalarm) break;
05025 if ((p->radio || (p->oprmode < 0))) break;
05026 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
05027 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05028 return NULL;
05029 }
05030 if (!x) {
05031 dahdi_enable_ec(p);
05032 if (p->echobreak) {
05033 dahdi_train_ec(p);
05034 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05035 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05036 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05037 p->echobreak = 0;
05038 } else {
05039 p->dialing = 0;
05040 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05041
05042 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05043 ast_setstate(ast, AST_STATE_UP);
05044 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05045 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05046 break;
05047 } else {
05048
05049 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05050 }
05051 }
05052 if (ast->_state == AST_STATE_DIALING) {
05053 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05054 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
05055 } 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)))) {
05056 ast_setstate(ast, AST_STATE_RINGING);
05057 } else if (!p->answeronpolarityswitch) {
05058 ast_setstate(ast, AST_STATE_UP);
05059 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05060 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05061
05062 p->polarity = POLARITY_REV;
05063 } else {
05064
05065 p->polarity = POLARITY_IDLE;
05066 }
05067 }
05068 }
05069 }
05070 break;
05071 case DAHDI_EVENT_ALARM:
05072 #ifdef HAVE_PRI
05073 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05074
05075 if (p->call) {
05076 if (p->pri && p->pri->pri) {
05077 if (!pri_grab(p, p->pri)) {
05078 pri_hangup(p->pri->pri, p->call, -1);
05079 pri_destroycall(p->pri->pri, p->call);
05080 p->call = NULL;
05081 pri_rel(p->pri);
05082 } else
05083 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05084 } else
05085 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05086 }
05087 if (p->owner)
05088 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05089 }
05090 if (p->bearer)
05091 p->bearer->inalarm = 1;
05092 else
05093 #endif
05094 p->inalarm = 1;
05095 res = get_alarms(p);
05096 handle_alarms(p, res);
05097 #ifdef HAVE_PRI
05098 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05099
05100 } else {
05101 break;
05102 }
05103 #endif
05104 #ifdef HAVE_OPENR2
05105 if (p->sig == SIG_MFCR2)
05106 break;
05107 #endif
05108 case DAHDI_EVENT_ONHOOK:
05109 if (p->radio) {
05110 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05111 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05112 break;
05113 }
05114 if (p->oprmode < 0)
05115 {
05116 if (p->oprmode != -1) break;
05117 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05118 {
05119
05120 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05121 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05122 save_conference(p->oprpeer);
05123 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05124 }
05125 break;
05126 }
05127 switch (p->sig) {
05128 case SIG_FXOLS:
05129 case SIG_FXOGS:
05130 case SIG_FXOKS:
05131 p->onhooktime = time(NULL);
05132 p->msgstate = -1;
05133
05134 if (index == SUB_REAL) {
05135
05136 if (p->subs[SUB_CALLWAIT].owner) {
05137
05138 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05139 if (option_verbose > 2)
05140 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05141 unalloc_sub(p, SUB_CALLWAIT);
05142 #if 0
05143 p->subs[index].needanswer = 0;
05144 p->subs[index].needringing = 0;
05145 #endif
05146 p->callwaitingrepeat = 0;
05147 p->cidcwexpire = 0;
05148 p->owner = NULL;
05149
05150 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05151 p->dialing = 1;
05152 dahdi_ring_phone(p);
05153 } else if (p->subs[SUB_THREEWAY].owner) {
05154 unsigned int mssinceflash;
05155
05156
05157 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
05158
05159 ast_mutex_unlock(&p->lock);
05160 DEADLOCK_AVOIDANCE(&ast->lock);
05161
05162
05163
05164 ast_mutex_lock(&p->lock);
05165 if (p->owner != ast) {
05166 ast_log(LOG_WARNING, "This isn't good...\n");
05167 return NULL;
05168 }
05169 }
05170 if (!p->subs[SUB_THREEWAY].owner) {
05171 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05172 return NULL;
05173 }
05174 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05175 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
05176 if (mssinceflash < MIN_MS_SINCE_FLASH) {
05177
05178
05179 if (p->subs[SUB_THREEWAY].owner)
05180 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
05181 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05182 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05183 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05184 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05185 if (p->transfer) {
05186
05187 p->subs[SUB_REAL].inthreeway = 0;
05188 p->subs[SUB_THREEWAY].inthreeway = 0;
05189
05190 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05191 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05192
05193 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05194 p->owner = NULL;
05195
05196 dahdi_ring_phone(p);
05197 } else {
05198 if ((res = attempt_transfer(p)) < 0) {
05199 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05200 if (p->subs[SUB_THREEWAY].owner)
05201 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05202 } else if (res) {
05203
05204 if (p->subs[SUB_THREEWAY].owner)
05205 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05206 break;
05207 }
05208 }
05209 } else {
05210 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05211 if (p->subs[SUB_THREEWAY].owner)
05212 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05213 }
05214 } else {
05215 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05216
05217 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05218 p->owner = NULL;
05219
05220 dahdi_ring_phone(p);
05221 }
05222 }
05223 } else {
05224 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
05225 }
05226
05227 default:
05228 dahdi_disable_ec(p);
05229 return NULL;
05230 }
05231 break;
05232 case DAHDI_EVENT_RINGOFFHOOK:
05233 if (p->inalarm) break;
05234 if (p->oprmode < 0)
05235 {
05236 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05237 {
05238
05239 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05240 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
05241 restore_conference(p->oprpeer);
05242 }
05243 break;
05244 }
05245 if (p->radio)
05246 {
05247 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05248 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05249 break;
05250 }
05251
05252
05253 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05254 c = strchr(p->dialdest, '/');
05255 if (c)
05256 c++;
05257 else
05258 c = p->dialdest;
05259 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05260 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05261 if (strlen(p->dop.dialstr) > 4) {
05262 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05263 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05264 p->echorest[sizeof(p->echorest) - 1] = '\0';
05265 p->echobreak = 1;
05266 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05267 } else
05268 p->echobreak = 0;
05269 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05270 int saveerr = errno;
05271
05272 x = DAHDI_ONHOOK;
05273 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05274 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05275 return NULL;
05276 }
05277 p->dialing = 1;
05278 return &p->subs[index].f;
05279 }
05280 switch (p->sig) {
05281 case SIG_FXOLS:
05282 case SIG_FXOGS:
05283 case SIG_FXOKS:
05284 switch (ast->_state) {
05285 case AST_STATE_RINGING:
05286 dahdi_enable_ec(p);
05287 dahdi_train_ec(p);
05288 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05289 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05290
05291 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05292 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
05293 if (p->cidspill) {
05294
05295 free(p->cidspill);
05296 p->cidspill = NULL;
05297 }
05298 p->dialing = 0;
05299 p->callwaitcas = 0;
05300 if (p->confirmanswer) {
05301
05302 p->subs[index].f.frametype = AST_FRAME_NULL;
05303 p->subs[index].f.subclass = 0;
05304 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05305
05306 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05307 if (res < 0) {
05308 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05309 p->dop.dialstr[0] = '\0';
05310 return NULL;
05311 } else {
05312 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05313 p->subs[index].f.frametype = AST_FRAME_NULL;
05314 p->subs[index].f.subclass = 0;
05315 p->dialing = 1;
05316 }
05317 p->dop.dialstr[0] = '\0';
05318 ast_setstate(ast, AST_STATE_DIALING);
05319 } else
05320 ast_setstate(ast, AST_STATE_UP);
05321 return &p->subs[index].f;
05322 case AST_STATE_DOWN:
05323 ast_setstate(ast, AST_STATE_RING);
05324 ast->rings = 1;
05325 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05326 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05327 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
05328 return &p->subs[index].f;
05329 case AST_STATE_UP:
05330
05331 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05332
05333 if (ast_bridged_channel(p->owner))
05334 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05335 p->subs[index].needunhold = 1;
05336 break;
05337 case AST_STATE_RESERVED:
05338
05339 if (has_voicemail(p))
05340 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05341 else
05342 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05343 break;
05344 default:
05345 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05346 }
05347 break;
05348 case SIG_FXSLS:
05349 case SIG_FXSGS:
05350 case SIG_FXSKS:
05351 if (ast->_state == AST_STATE_RING) {
05352 p->ringt = p->ringt_base;
05353 }
05354
05355
05356 case SIG_EM:
05357 case SIG_EM_E1:
05358 case SIG_EMWINK:
05359 case SIG_FEATD:
05360 case SIG_FEATDMF:
05361 case SIG_FEATDMF_TA:
05362 case SIG_E911:
05363 case SIG_FGC_CAMA:
05364 case SIG_FGC_CAMAMF:
05365 case SIG_FEATB:
05366 case SIG_SF:
05367 case SIG_SFWINK:
05368 case SIG_SF_FEATD:
05369 case SIG_SF_FEATDMF:
05370 case SIG_SF_FEATB:
05371 if (ast->_state == AST_STATE_PRERING)
05372 ast_setstate(ast, AST_STATE_RING);
05373 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05374 if (option_debug)
05375 ast_log(LOG_DEBUG, "Ring detected\n");
05376 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05377 p->subs[index].f.subclass = AST_CONTROL_RING;
05378 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05379 if (option_debug)
05380 ast_log(LOG_DEBUG, "Line answered\n");
05381 if (p->confirmanswer) {
05382 p->subs[index].f.frametype = AST_FRAME_NULL;
05383 p->subs[index].f.subclass = 0;
05384 } else {
05385 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05386 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05387 ast_setstate(ast, AST_STATE_UP);
05388 }
05389 } else if (ast->_state != AST_STATE_RING)
05390 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05391 break;
05392 default:
05393 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05394 }
05395 break;
05396 #ifdef DAHDI_EVENT_RINGBEGIN
05397 case DAHDI_EVENT_RINGBEGIN:
05398 switch (p->sig) {
05399 case SIG_FXSLS:
05400 case SIG_FXSGS:
05401 case SIG_FXSKS:
05402 if (ast->_state == AST_STATE_RING) {
05403 p->ringt = p->ringt_base;
05404 }
05405 break;
05406 }
05407 break;
05408 #endif
05409 case DAHDI_EVENT_RINGEROFF:
05410 if (p->inalarm) break;
05411 if ((p->radio || (p->oprmode < 0))) break;
05412 ast->rings++;
05413 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05414 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05415 free(p->cidspill);
05416 p->cidspill = NULL;
05417 p->callwaitcas = 0;
05418 }
05419 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05420 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05421 break;
05422 case DAHDI_EVENT_RINGERON:
05423 break;
05424 case DAHDI_EVENT_NOALARM:
05425 p->inalarm = 0;
05426 #ifdef HAVE_PRI
05427
05428 if (p->bearer)
05429 p->bearer->inalarm = 0;
05430 #endif
05431 if (!p->unknown_alarm) {
05432 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05433 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05434 "Channel: %d\r\n", p->channel);
05435 } else {
05436 p->unknown_alarm = 0;
05437 }
05438 break;
05439 case DAHDI_EVENT_WINKFLASH:
05440 if (p->inalarm) break;
05441 if (p->radio) break;
05442 if (p->oprmode < 0) break;
05443 if (p->oprmode > 1)
05444 {
05445 struct dahdi_params par;
05446
05447 memset(&par, 0, sizeof(par));
05448 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05449 {
05450 if (!par.rxisoffhook)
05451 {
05452
05453 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05454 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05455 save_conference(p);
05456 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05457 }
05458 }
05459 break;
05460 }
05461
05462 gettimeofday(&p->flashtime, NULL);
05463 switch (mysig) {
05464 case SIG_FXOLS:
05465 case SIG_FXOGS:
05466 case SIG_FXOKS:
05467 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05468 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05469 p->callwaitcas = 0;
05470
05471 if (index != SUB_REAL) {
05472 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05473 goto winkflashdone;
05474 }
05475
05476 if (p->subs[SUB_CALLWAIT].owner) {
05477
05478 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05479 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05480 p->owner = p->subs[SUB_REAL].owner;
05481 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
05482 if (p->owner->_state == AST_STATE_RINGING) {
05483 ast_setstate(p->owner, AST_STATE_UP);
05484 p->subs[SUB_REAL].needanswer = 1;
05485 }
05486 p->callwaitingrepeat = 0;
05487 p->cidcwexpire = 0;
05488
05489 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05490 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05491 S_OR(p->mohsuggest, NULL),
05492 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05493 }
05494 p->subs[SUB_CALLWAIT].needhold = 1;
05495 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05496 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05497 S_OR(p->mohsuggest, NULL),
05498 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05499 }
05500 p->subs[SUB_REAL].needunhold = 1;
05501 } else if (!p->subs[SUB_THREEWAY].owner) {
05502 if (!p->threewaycalling) {
05503
05504 p->subs[SUB_REAL].needflash = 1;
05505 goto winkflashdone;
05506 } else if (!check_for_conference(p)) {
05507 char cid_num[256];
05508 char cid_name[256];
05509
05510 cid_num[0] = 0;
05511 cid_name[0] = 0;
05512 if (p->dahditrcallerid && p->owner) {
05513 if (p->owner->cid.cid_num)
05514 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05515 if (p->owner->cid.cid_name)
05516 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05517 }
05518
05519
05520 if (!((ast->pbx) ||
05521 (ast->_state == AST_STATE_UP) ||
05522 (ast->_state == AST_STATE_RING))) {
05523 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
05524 goto winkflashdone;
05525 }
05526 if (alloc_sub(p, SUB_THREEWAY)) {
05527 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05528 goto winkflashdone;
05529 }
05530
05531 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05532 if (p->dahditrcallerid) {
05533 if (!p->origcid_num)
05534 p->origcid_num = ast_strdup(p->cid_num);
05535 if (!p->origcid_name)
05536 p->origcid_name = ast_strdup(p->cid_name);
05537 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05538 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05539 }
05540
05541 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05542
05543 dahdi_disable_ec(p);
05544 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05545 if (res)
05546 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05547 p->owner = chan;
05548 pthread_attr_init(&attr);
05549 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05550 if (!chan) {
05551 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05552 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
05553 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05554 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05555 dahdi_enable_ec(p);
05556 ast_hangup(chan);
05557 } else {
05558 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05559 int way3bridge = 0, cdr3way = 0;
05560
05561 if (!other) {
05562 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05563 } else
05564 way3bridge = 1;
05565
05566 if (p->subs[SUB_THREEWAY].owner->cdr)
05567 cdr3way = 1;
05568
05569 if (option_verbose > 2)
05570 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
05571
05572 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05573 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05574 S_OR(p->mohsuggest, NULL),
05575 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05576 }
05577 p->subs[SUB_THREEWAY].needhold = 1;
05578 }
05579 pthread_attr_destroy(&attr);
05580 }
05581 } else {
05582
05583 if (p->subs[SUB_THREEWAY].inthreeway) {
05584
05585 if (option_debug)
05586 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05587
05588 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05589
05590 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05591 p->owner = p->subs[SUB_REAL].owner;
05592 }
05593
05594 if (option_verbose > 2)
05595 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05596 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05597 p->subs[SUB_REAL].inthreeway = 0;
05598 p->subs[SUB_THREEWAY].inthreeway = 0;
05599 } else {
05600
05601 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05602 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05603 int otherindex = SUB_THREEWAY;
05604 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05605 int way3bridge = 0, cdr3way = 0;
05606
05607 if (!other) {
05608 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05609 } else
05610 way3bridge = 1;
05611
05612 if (p->subs[SUB_THREEWAY].owner->cdr)
05613 cdr3way = 1;
05614
05615 if (option_verbose > 2)
05616 ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05617
05618 p->subs[SUB_THREEWAY].inthreeway = 1;
05619 p->subs[SUB_REAL].inthreeway = 1;
05620 if (ast->_state == AST_STATE_UP) {
05621 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05622 otherindex = SUB_REAL;
05623 }
05624 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05625 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05626 p->subs[otherindex].needunhold = 1;
05627 p->owner = p->subs[SUB_REAL].owner;
05628 if (ast->_state == AST_STATE_RINGING) {
05629 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
05630 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05631 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05632 }
05633 } else {
05634 if (option_verbose > 2)
05635 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05636 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05637 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05638 p->owner = p->subs[SUB_REAL].owner;
05639 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05640 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05641 p->subs[SUB_REAL].needunhold = 1;
05642 dahdi_enable_ec(p);
05643 }
05644
05645 }
05646 }
05647 winkflashdone:
05648 update_conf(p);
05649 break;
05650 case SIG_EM:
05651 case SIG_EM_E1:
05652 case SIG_FEATD:
05653 case SIG_SF:
05654 case SIG_SFWINK:
05655 case SIG_SF_FEATD:
05656 case SIG_FXSLS:
05657 case SIG_FXSGS:
05658 if (p->dialing)
05659 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
05660 else
05661 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05662 break;
05663 case SIG_FEATDMF_TA:
05664 switch (p->whichwink) {
05665 case 0:
05666 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05667 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05668 break;
05669 case 1:
05670 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05671 break;
05672 case 2:
05673 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05674 return NULL;
05675 }
05676 p->whichwink++;
05677
05678 case SIG_FEATDMF:
05679 case SIG_E911:
05680 case SIG_FGC_CAMAMF:
05681 case SIG_FGC_CAMA:
05682 case SIG_FEATB:
05683 case SIG_SF_FEATDMF:
05684 case SIG_SF_FEATB:
05685 case SIG_EMWINK:
05686
05687 if (!ast_strlen_zero(p->dop.dialstr)) {
05688 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05689 if (res < 0) {
05690 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05691 p->dop.dialstr[0] = '\0';
05692 return NULL;
05693 } else
05694 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05695 }
05696 p->dop.dialstr[0] = '\0';
05697 break;
05698 default:
05699 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
05700 }
05701 break;
05702 case DAHDI_EVENT_HOOKCOMPLETE:
05703 if (p->inalarm) break;
05704 if ((p->radio || (p->oprmode < 0))) break;
05705 switch (mysig) {
05706 case SIG_FXSLS:
05707 case SIG_FXSGS:
05708 case SIG_FXSKS:
05709 case SIG_EM:
05710 case SIG_EM_E1:
05711 case SIG_EMWINK:
05712 case SIG_FEATD:
05713 case SIG_SF:
05714 case SIG_SFWINK:
05715 case SIG_SF_FEATD:
05716 if (!ast_strlen_zero(p->dop.dialstr)) {
05717 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05718 if (res < 0) {
05719 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05720 p->dop.dialstr[0] = '\0';
05721 return NULL;
05722 } else
05723 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05724 }
05725 p->dop.dialstr[0] = '\0';
05726 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05727 break;
05728 case SIG_FEATDMF:
05729 case SIG_FEATDMF_TA:
05730 case SIG_E911:
05731 case SIG_FGC_CAMA:
05732 case SIG_FGC_CAMAMF:
05733 case SIG_FEATB:
05734 case SIG_SF_FEATDMF:
05735 case SIG_SF_FEATB:
05736 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05737 break;
05738 default:
05739 break;
05740 }
05741 break;
05742 case DAHDI_EVENT_POLARITY:
05743
05744
05745
05746
05747
05748
05749 if (p->polarity == POLARITY_IDLE) {
05750 p->polarity = POLARITY_REV;
05751 if (p->answeronpolarityswitch &&
05752 ((ast->_state == AST_STATE_DIALING) ||
05753 (ast->_state == AST_STATE_RINGING))) {
05754 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
05755 ast_setstate(p->owner, AST_STATE_UP);
05756 if (p->hanguponpolarityswitch) {
05757 gettimeofday(&p->polaritydelaytv, NULL);
05758 }
05759 } else
05760 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
05761 }
05762
05763
05764 if (p->hanguponpolarityswitch &&
05765 (p->polarityonanswerdelay > 0) &&
05766 (p->polarity == POLARITY_REV) &&
05767 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
05768
05769 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) );
05770
05771 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05772 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
05773 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05774 p->polarity = POLARITY_IDLE;
05775 } else {
05776 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);
05777 }
05778 } else {
05779 p->polarity = POLARITY_IDLE;
05780 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
05781 }
05782
05783 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) );
05784 break;
05785 default:
05786 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05787 }
05788 return &p->subs[index].f;
05789 }
05790
05791 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05792 {
05793 struct dahdi_pvt *p = ast->tech_pvt;
05794 int res;
05795 int usedindex=-1;
05796 int index;
05797 struct ast_frame *f;
05798
05799
05800 index = dahdi_get_index(ast, p, 1);
05801
05802 p->subs[index].f.frametype = AST_FRAME_NULL;
05803 p->subs[index].f.datalen = 0;
05804 p->subs[index].f.samples = 0;
05805 p->subs[index].f.mallocd = 0;
05806 p->subs[index].f.offset = 0;
05807 p->subs[index].f.subclass = 0;
05808 p->subs[index].f.delivery = ast_tv(0,0);
05809 p->subs[index].f.src = "dahdi_exception";
05810 p->subs[index].f.data = NULL;
05811
05812
05813 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05814
05815
05816
05817
05818
05819 if (p->fake_event) {
05820 res = p->fake_event;
05821 p->fake_event = 0;
05822 } else
05823 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05824
05825 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05826 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05827 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
05828 p->owner = p->subs[SUB_REAL].owner;
05829 if (p->owner && ast_bridged_channel(p->owner))
05830 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05831 p->subs[SUB_REAL].needunhold = 1;
05832 }
05833 switch (res) {
05834 case DAHDI_EVENT_ONHOOK:
05835 dahdi_disable_ec(p);
05836 if (p->owner) {
05837 if (option_verbose > 2)
05838 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
05839 dahdi_ring_phone(p);
05840 p->callwaitingrepeat = 0;
05841 p->cidcwexpire = 0;
05842 } else
05843 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05844 update_conf(p);
05845 break;
05846 case DAHDI_EVENT_RINGOFFHOOK:
05847 dahdi_enable_ec(p);
05848 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05849 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05850 p->subs[SUB_REAL].needanswer = 1;
05851 p->dialing = 0;
05852 }
05853 break;
05854 case DAHDI_EVENT_HOOKCOMPLETE:
05855 case DAHDI_EVENT_RINGERON:
05856 case DAHDI_EVENT_RINGEROFF:
05857
05858 break;
05859 case DAHDI_EVENT_WINKFLASH:
05860 gettimeofday(&p->flashtime, NULL);
05861 if (p->owner) {
05862 if (option_verbose > 2)
05863 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05864 if (p->owner->_state != AST_STATE_UP) {
05865
05866 usedindex = dahdi_get_index(p->owner, p, 0);
05867 if (usedindex > -1) {
05868 p->subs[usedindex].needanswer = 1;
05869 }
05870 ast_setstate(p->owner, AST_STATE_UP);
05871 }
05872 p->callwaitingrepeat = 0;
05873 p->cidcwexpire = 0;
05874 if (ast_bridged_channel(p->owner))
05875 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05876 p->subs[SUB_REAL].needunhold = 1;
05877 } else
05878 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05879 update_conf(p);
05880 break;
05881 default:
05882 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05883 }
05884 f = &p->subs[index].f;
05885 return f;
05886 }
05887 if (!(p->radio || (p->oprmode < 0)) && option_debug)
05888 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05889
05890 if (ast != p->owner) {
05891 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05892 f = &p->subs[index].f;
05893 return f;
05894 }
05895 f = dahdi_handle_event(ast);
05896 return f;
05897 }
05898
05899 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05900 {
05901 struct dahdi_pvt *p = ast->tech_pvt;
05902 struct ast_frame *f;
05903 ast_mutex_lock(&p->lock);
05904 f = __dahdi_exception(ast);
05905 ast_mutex_unlock(&p->lock);
05906 return f;
05907 }
05908
05909 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05910 {
05911 struct dahdi_pvt *p = ast->tech_pvt;
05912 int res;
05913 int index;
05914 void *readbuf;
05915 struct ast_frame *f;
05916
05917 while (ast_mutex_trylock(&p->lock)) {
05918 DEADLOCK_AVOIDANCE(&ast->lock);
05919 }
05920
05921 index = dahdi_get_index(ast, p, 0);
05922
05923
05924 if (index < 0) {
05925 ast_log(LOG_WARNING, "We dont exist?\n");
05926 ast_mutex_unlock(&p->lock);
05927 return NULL;
05928 }
05929
05930 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05931 ast_mutex_unlock(&p->lock);
05932 return NULL;
05933 }
05934
05935 p->subs[index].f.frametype = AST_FRAME_NULL;
05936 p->subs[index].f.datalen = 0;
05937 p->subs[index].f.samples = 0;
05938 p->subs[index].f.mallocd = 0;
05939 p->subs[index].f.offset = 0;
05940 p->subs[index].f.subclass = 0;
05941 p->subs[index].f.delivery = ast_tv(0,0);
05942 p->subs[index].f.src = "dahdi_read";
05943 p->subs[index].f.data = NULL;
05944
05945
05946 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05947 {
05948 struct dahdi_params ps;
05949
05950 memset(&ps, 0, sizeof(ps));
05951 ps.channo = p->channel;
05952 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05953 ast_mutex_unlock(&p->lock);
05954 return NULL;
05955 }
05956 p->firstradio = 1;
05957 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05958 if (ps.rxisoffhook)
05959 {
05960 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05961 }
05962 else
05963 {
05964 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05965 }
05966 ast_mutex_unlock(&p->lock);
05967 return &p->subs[index].f;
05968 }
05969 if (p->ringt == 1) {
05970 ast_mutex_unlock(&p->lock);
05971 return NULL;
05972 }
05973 else if (p->ringt > 0)
05974 p->ringt--;
05975
05976 #ifdef HAVE_OPENR2
05977 if (p->mfcr2) {
05978 openr2_chan_process_event(p->r2chan);
05979 }
05980 #endif
05981
05982 if (p->subs[index].needringing) {
05983
05984 p->subs[index].needringing = 0;
05985 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05986 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05987 ast_setstate(ast, AST_STATE_RINGING);
05988 ast_mutex_unlock(&p->lock);
05989 return &p->subs[index].f;
05990 }
05991
05992 if (p->subs[index].needbusy) {
05993
05994 p->subs[index].needbusy = 0;
05995 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05996 p->subs[index].f.subclass = AST_CONTROL_BUSY;
05997 ast_mutex_unlock(&p->lock);
05998 return &p->subs[index].f;
05999 }
06000
06001 if (p->subs[index].needcongestion) {
06002
06003 p->subs[index].needcongestion = 0;
06004 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06005 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
06006 ast_mutex_unlock(&p->lock);
06007 return &p->subs[index].f;
06008 }
06009
06010 if (p->subs[index].needcallerid) {
06011 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06012 S_OR(p->lastcid_name, NULL),
06013 S_OR(p->lastcid_num, NULL)
06014 );
06015 p->subs[index].needcallerid = 0;
06016 }
06017
06018 if (p->subs[index].needanswer) {
06019
06020 p->subs[index].needanswer = 0;
06021 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06022 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
06023 ast_mutex_unlock(&p->lock);
06024 return &p->subs[index].f;
06025 }
06026
06027 #ifdef HAVE_OPENR2
06028 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06029
06030
06031
06032
06033 p->subs[index].f.frametype = AST_FRAME_NULL;
06034 p->subs[index].f.subclass = 0;
06035 p->subs[index].f.samples = 0;
06036 p->subs[index].f.mallocd = 0;
06037 p->subs[index].f.offset = 0;
06038 p->subs[index].f.data = NULL;
06039 p->subs[index].f.datalen= 0;
06040 ast_mutex_unlock(&p->lock);
06041 return &p->subs[index].f;
06042 }
06043 #endif
06044
06045 if (p->subs[index].needflash) {
06046
06047 p->subs[index].needflash = 0;
06048 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06049 p->subs[index].f.subclass = AST_CONTROL_FLASH;
06050 ast_mutex_unlock(&p->lock);
06051 return &p->subs[index].f;
06052 }
06053
06054 if (p->subs[index].needhold) {
06055
06056 p->subs[index].needhold = 0;
06057 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06058 p->subs[index].f.subclass = AST_CONTROL_HOLD;
06059 ast_mutex_unlock(&p->lock);
06060 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
06061 return &p->subs[index].f;
06062 }
06063
06064 if (p->subs[index].needunhold) {
06065
06066 p->subs[index].needunhold = 0;
06067 p->subs[index].f.frametype = AST_FRAME_CONTROL;
06068 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
06069 ast_mutex_unlock(&p->lock);
06070 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
06071 return &p->subs[index].f;
06072 }
06073
06074 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06075 if (!p->subs[index].linear) {
06076 p->subs[index].linear = 1;
06077 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06078 if (res)
06079 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
06080 }
06081 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06082 (ast->rawreadformat == AST_FORMAT_ALAW)) {
06083 if (p->subs[index].linear) {
06084 p->subs[index].linear = 0;
06085 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06086 if (res)
06087 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
06088 }
06089 } else {
06090 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06091 ast_mutex_unlock(&p->lock);
06092 return NULL;
06093 }
06094 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
06095 CHECK_BLOCKING(ast);
06096 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06097 ast_clear_flag(ast, AST_FLAG_BLOCKING);
06098
06099 if (p->use_callerid && (ast->_state == AST_STATE_PRERING &&
06100 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
06101
06102 if (!p->subs[index].linear) {
06103 int x, samplin;
06104 int mean, ssum;
06105
06106
06107 for (x = 0, ssum = 0; x < READ_SIZE; x++) {
06108
06109 ssum += AST_MULAW(((u_char *)readbuf)[x]);
06110 if (option_verbose > 5 && (x % 10 == 0))
06111 ast_log(LOG_NOTICE, "dahdi_read ssum %i, mean %i \n", ssum, ssum / READ_SIZE);
06112 }
06113 mean = ssum / READ_SIZE;
06114
06115 if (option_verbose > 5)
06116 ast_log(LOG_WARNING, "dahdi_read channel %s, mean %i \n", ast->name, mean);
06117 if (ast->rawreadformat == AST_FORMAT_ULAW) {
06118 for (x = 0; x < READ_SIZE; x++) {
06119 samplin = AST_MULAW(((u_char *)readbuf)[x]);
06120 if (option_verbose > 6 && (x % 10 == 0))
06121 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));
06122 ((u_char *)readbuf)[x] = AST_LIN2MU(samplin - mean);
06123 }
06124 }
06125 }
06126 }
06127
06128
06129 if (res < 0) {
06130 f = NULL;
06131 if (res == -1) {
06132 if (errno == EAGAIN) {
06133
06134 ast_mutex_unlock(&p->lock);
06135 return &p->subs[index].f;
06136 } else if (errno == ELAST) {
06137 f = __dahdi_exception(ast);
06138 } else
06139 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06140 }
06141 ast_mutex_unlock(&p->lock);
06142 return f;
06143 }
06144 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06145 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06146 f = __dahdi_exception(ast);
06147 ast_mutex_unlock(&p->lock);
06148 return f;
06149 }
06150 if (p->tdd) {
06151 int c;
06152
06153 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06154 if (c < 0) {
06155 ast_log(LOG_DEBUG,"tdd_feed failed\n");
06156 ast_mutex_unlock(&p->lock);
06157 return NULL;
06158 }
06159 if (c) {
06160 p->subs[index].f.subclass = 0;
06161 p->subs[index].f.frametype = AST_FRAME_TEXT;
06162 p->subs[index].f.mallocd = 0;
06163 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06164 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06165 p->subs[index].f.datalen = 1;
06166 *((char *) p->subs[index].f.data) = c;
06167 ast_mutex_unlock(&p->lock);
06168 return &p->subs[index].f;
06169 }
06170 }
06171
06172 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06173 p->callwaitingrepeat--;
06174 }
06175 if (p->cidcwexpire)
06176 p->cidcwexpire--;
06177
06178 if (p->callwaitingrepeat == 1) {
06179 p->callwaitrings++;
06180 dahdi_callwait(ast);
06181 }
06182
06183 if (p->cidcwexpire == 1) {
06184 if (option_verbose > 2)
06185 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06186 restore_conference(p);
06187 }
06188 if (p->subs[index].linear) {
06189 p->subs[index].f.datalen = READ_SIZE * 2;
06190 } else
06191 p->subs[index].f.datalen = READ_SIZE;
06192
06193
06194 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06195 send_callerid(p);
06196 }
06197
06198 p->subs[index].f.frametype = AST_FRAME_VOICE;
06199 p->subs[index].f.subclass = ast->rawreadformat;
06200 p->subs[index].f.samples = READ_SIZE;
06201 p->subs[index].f.mallocd = 0;
06202 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06203 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06204 #if 0
06205 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06206 #endif
06207 if (p->dialing ||
06208 (index && (ast->_state != AST_STATE_UP)) ||
06209 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
06210 ) {
06211
06212
06213 p->subs[index].f.frametype = AST_FRAME_NULL;
06214 p->subs[index].f.subclass = 0;
06215 p->subs[index].f.samples = 0;
06216 p->subs[index].f.mallocd = 0;
06217 p->subs[index].f.offset = 0;
06218 p->subs[index].f.data = NULL;
06219 p->subs[index].f.datalen= 0;
06220 }
06221 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
06222
06223 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06224 if (f) {
06225 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06226 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06227
06228
06229 f = NULL;
06230 }
06231 } else if (f->frametype == AST_FRAME_DTMF) {
06232 #ifdef HAVE_PRI
06233 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial &&
06234 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
06235 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06236
06237 f->frametype = AST_FRAME_NULL;
06238 f->subclass = 0;
06239 }
06240 #endif
06241
06242 p->pulsedial = 0;
06243 }
06244 }
06245 } else
06246 f = &p->subs[index].f;
06247
06248 if (f && (f->frametype == AST_FRAME_DTMF))
06249 dahdi_handle_dtmfup(ast, index, &f);
06250
06251
06252 if (p->fake_event)
06253 ast_set_flag(ast, AST_FLAG_EXCEPTION);
06254
06255 ast_mutex_unlock(&p->lock);
06256 return f;
06257 }
06258
06259 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
06260 {
06261 int sent=0;
06262 int size;
06263 int res;
06264 int fd;
06265 fd = p->subs[index].dfd;
06266 while (len) {
06267 size = len;
06268 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06269 size = (linear ? READ_SIZE * 2 : READ_SIZE);
06270 res = write(fd, buf, size);
06271 if (res != size) {
06272 if (option_debug)
06273 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06274 return sent;
06275 }
06276 len -= size;
06277 buf += size;
06278 }
06279 return sent;
06280 }
06281
06282 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06283 {
06284 struct dahdi_pvt *p = ast->tech_pvt;
06285 int res;
06286 int index;
06287 index = dahdi_get_index(ast, p, 0);
06288 if (index < 0) {
06289 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06290 return -1;
06291 }
06292
06293 #if 0
06294 #ifdef HAVE_PRI
06295 ast_mutex_lock(&p->lock);
06296 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06297 if (p->pri->pri) {
06298 if (!pri_grab(p, p->pri)) {
06299 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06300 pri_rel(p->pri);
06301 } else
06302 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06303 }
06304 p->proceeding=1;
06305 }
06306 ast_mutex_unlock(&p->lock);
06307 #endif
06308 #endif
06309
06310 if (frame->frametype != AST_FRAME_VOICE) {
06311 if (frame->frametype != AST_FRAME_IMAGE)
06312 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06313 return 0;
06314 }
06315 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06316 (frame->subclass != AST_FORMAT_ULAW) &&
06317 (frame->subclass != AST_FORMAT_ALAW)) {
06318 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06319 return -1;
06320 }
06321 if (p->dialing) {
06322 if (option_debug)
06323 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06324 return 0;
06325 }
06326 if (!p->owner) {
06327 if (option_debug)
06328 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06329 return 0;
06330 }
06331 if (p->cidspill) {
06332 if (option_debug)
06333 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
06334 return 0;
06335 }
06336
06337 if (!frame->data || !frame->datalen)
06338 return 0;
06339
06340 if (frame->subclass == AST_FORMAT_SLINEAR) {
06341 if (!p->subs[index].linear) {
06342 p->subs[index].linear = 1;
06343 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06344 if (res)
06345 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06346 }
06347 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06348 } else {
06349
06350 if (p->subs[index].linear) {
06351 p->subs[index].linear = 0;
06352 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06353 if (res)
06354 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06355 }
06356 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06357 }
06358 if (res < 0) {
06359 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06360 return -1;
06361 }
06362 return 0;
06363 }
06364
06365 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06366 {
06367 struct dahdi_pvt *p = chan->tech_pvt;
06368 int res=-1;
06369 int index;
06370 int func = DAHDI_FLASH;
06371 ast_mutex_lock(&p->lock);
06372 index = dahdi_get_index(chan, p, 0);
06373 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06374 #ifdef HAVE_OPENR2
06375 if (p->mfcr2 && !p->mfcr2_call_accepted) {
06376 ast_mutex_unlock(&p->lock);
06377
06378
06379 return 0;
06380 }
06381 #endif
06382 if (index == SUB_REAL) {
06383 switch (condition) {
06384 case AST_CONTROL_BUSY:
06385 #ifdef HAVE_PRI
06386 if (p->priindication_oob && p->sig == SIG_PRI) {
06387 chan->hangupcause = AST_CAUSE_USER_BUSY;
06388 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06389 res = 0;
06390 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06391 if (p->pri->pri) {
06392 if (!pri_grab(p, p->pri)) {
06393 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06394 pri_rel(p->pri);
06395 }
06396 else
06397 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06398 }
06399 p->progress = 1;
06400 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06401 } else
06402 #endif
06403 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06404 break;
06405 case AST_CONTROL_RINGING:
06406 #ifdef HAVE_PRI
06407 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06408 if (p->pri->pri) {
06409 if (!pri_grab(p, p->pri)) {
06410 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06411 pri_rel(p->pri);
06412 }
06413 else
06414 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06415 }
06416 p->alerting = 1;
06417 }
06418 #endif
06419 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06420 if (chan->_state != AST_STATE_UP) {
06421 if ((chan->_state != AST_STATE_RING) ||
06422 ((p->sig != SIG_FXSKS) &&
06423 (p->sig != SIG_FXSLS) &&
06424 (p->sig != SIG_FXSGS)))
06425 ast_setstate(chan, AST_STATE_RINGING);
06426 }
06427 break;
06428 case AST_CONTROL_PROCEEDING:
06429 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06430 #ifdef HAVE_PRI
06431 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06432 if (p->pri->pri) {
06433 if (!pri_grab(p, p->pri)) {
06434 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06435 pri_rel(p->pri);
06436 }
06437 else
06438 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06439 }
06440 p->proceeding = 1;
06441 p->dialing = 0;
06442 }
06443 #endif
06444
06445 res = 0;
06446 break;
06447 case AST_CONTROL_PROGRESS:
06448 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06449 #ifdef HAVE_PRI
06450 p->digital = 0;
06451 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06452 if (p->pri->pri) {
06453 if (!pri_grab(p, p->pri)) {
06454 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06455 pri_rel(p->pri);
06456 }
06457 else
06458 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06459 }
06460 p->progress = 1;
06461 }
06462 #endif
06463
06464 res = 0;
06465 break;
06466 case AST_CONTROL_CONGESTION:
06467 chan->hangupcause = AST_CAUSE_CONGESTION;
06468 #ifdef HAVE_PRI
06469 if (p->priindication_oob && p->sig == SIG_PRI) {
06470 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06471 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06472 res = 0;
06473 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06474 if (p->pri) {
06475 if (!pri_grab(p, p->pri)) {
06476 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06477 pri_rel(p->pri);
06478 } else
06479 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06480 }
06481 p->progress = 1;
06482 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06483 } else
06484 #endif
06485 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06486 break;
06487 case AST_CONTROL_HOLD:
06488 #ifdef HAVE_PRI
06489 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06490 if (!pri_grab(p, p->pri)) {
06491 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06492 pri_rel(p->pri);
06493 } else
06494 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06495 } else
06496 #endif
06497 ast_moh_start(chan, data, p->mohinterpret);
06498 break;
06499 case AST_CONTROL_UNHOLD:
06500 #ifdef HAVE_PRI
06501 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06502 if (!pri_grab(p, p->pri)) {
06503 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06504 pri_rel(p->pri);
06505 } else
06506 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06507 } else
06508 #endif
06509 ast_moh_stop(chan);
06510 break;
06511 case AST_CONTROL_RADIO_KEY:
06512 if (p->radio)
06513 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06514 res = 0;
06515 break;
06516 case AST_CONTROL_RADIO_UNKEY:
06517 if (p->radio)
06518 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06519 res = 0;
06520 break;
06521 case AST_CONTROL_FLASH:
06522
06523 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06524
06525 p->dop.dialstr[0] = '\0';
06526 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06527 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06528 chan->name, strerror(errno));
06529 } else
06530 res = 0;
06531 } else
06532 res = 0;
06533 break;
06534 case AST_CONTROL_SRCUPDATE:
06535 res = 0;
06536 break;
06537 case -1:
06538 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06539 break;
06540 }
06541 } else
06542 res = 0;
06543 ast_mutex_unlock(&p->lock);
06544 return res;
06545 }
06546
06547 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
06548 {
06549 struct ast_channel *tmp;
06550 int deflaw;
06551 int res;
06552 int x,y;
06553 int features;
06554 char *b2 = NULL;
06555 struct dahdi_params ps;
06556 char chanprefix[*dahdi_chan_name_len + 4];
06557
06558 if (i->subs[index].owner) {
06559 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
06560 return NULL;
06561 }
06562 y = 1;
06563 do {
06564 if (b2)
06565 free(b2);
06566 #ifdef HAVE_PRI
06567 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06568 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06569 else
06570 #endif
06571 if (i->channel == CHAN_PSEUDO)
06572 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
06573 else
06574 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
06575 for (x = 0; x < 3; x++) {
06576 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
06577 break;
06578 }
06579 y++;
06580 } while (x < 3);
06581 strcpy(chanprefix, dahdi_chan_name);
06582 strcat(chanprefix, "/%s");
06583 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
06584 if (b2)
06585 free(b2);
06586 if (!tmp)
06587 return NULL;
06588 tmp->tech = chan_tech;
06589 memset(&ps, 0, sizeof(ps));
06590 ps.channo = i->channel;
06591 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06592 if (res) {
06593 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06594 ps.curlaw = DAHDI_LAW_MULAW;
06595 }
06596 if (ps.curlaw == DAHDI_LAW_ALAW)
06597 deflaw = AST_FORMAT_ALAW;
06598 else
06599 deflaw = AST_FORMAT_ULAW;
06600 if (law) {
06601 if (law == DAHDI_LAW_ALAW)
06602 deflaw = AST_FORMAT_ALAW;
06603 else
06604 deflaw = AST_FORMAT_ULAW;
06605 }
06606 tmp->fds[0] = i->subs[index].dfd;
06607 tmp->nativeformats = deflaw;
06608
06609 tmp->rawreadformat = deflaw;
06610 tmp->readformat = deflaw;
06611 tmp->rawwriteformat = deflaw;
06612 tmp->writeformat = deflaw;
06613 i->subs[index].linear = 0;
06614 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
06615 features = 0;
06616 if (index == SUB_REAL) {
06617 if (i->busydetect && CANBUSYDETECT(i))
06618 features |= DSP_FEATURE_BUSY_DETECT;
06619 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
06620 features |= DSP_FEATURE_CALL_PROGRESS;
06621 if ((!i->outgoing && (i->callprogress & 4)) ||
06622 (i->outgoing && (i->callprogress & 2))) {
06623 features |= DSP_FEATURE_FAX_DETECT;
06624 }
06625 #ifdef DAHDI_TONEDETECT
06626 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06627 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
06628 #endif
06629 i->hardwaredtmf = 0;
06630 features |= DSP_FEATURE_DTMF_DETECT;
06631 #ifdef DAHDI_TONEDETECT
06632 } else if (NEED_MFDETECT(i)) {
06633 i->hardwaredtmf = 1;
06634 features |= DSP_FEATURE_DTMF_DETECT;
06635 }
06636 #endif
06637 }
06638 if (features) {
06639 if (i->dsp) {
06640 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
06641 } else {
06642 if (i->channel != CHAN_PSEUDO)
06643 i->dsp = ast_dsp_new();
06644 else
06645 i->dsp = NULL;
06646 if (i->dsp) {
06647 i->dsp_features = features;
06648 #ifdef HAVE_PRI
06649
06650 if (i->outgoing && (i->sig == SIG_PRI)) {
06651
06652
06653 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06654 features = 0;
06655 }
06656 #endif
06657 ast_dsp_set_features(i->dsp, features);
06658 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06659 if (!ast_strlen_zero(progzone))
06660 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06661 if (i->busydetect && CANBUSYDETECT(i)) {
06662 if(i->silencethreshold > 0)
06663 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06664 ast_dsp_set_busy_count(i->dsp, i->busycount);
06665 if(i->busytonelength > 0)
06666 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06667 if((i->busytonelength == i->busyquietlength) && i->busycompare)
06668 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06669 }
06670 }
06671 }
06672 }
06673
06674 if (state == AST_STATE_RING)
06675 tmp->rings = 1;
06676 tmp->tech_pvt = i;
06677 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06678
06679 tmp->callgroup = i->callgroup;
06680 tmp->pickupgroup = i->pickupgroup;
06681 }
06682 if (!ast_strlen_zero(i->language))
06683 ast_string_field_set(tmp, language, i->language);
06684 if (!i->owner)
06685 i->owner = tmp;
06686 if (!ast_strlen_zero(i->accountcode))
06687 ast_string_field_set(tmp, accountcode, i->accountcode);
06688 if (i->amaflags)
06689 tmp->amaflags = i->amaflags;
06690 i->subs[index].owner = tmp;
06691 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06692 ast_string_field_set(tmp, call_forward, i->call_forward);
06693
06694 if (!i->adsi)
06695 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06696 if (!ast_strlen_zero(i->exten))
06697 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06698 if (!ast_strlen_zero(i->rdnis))
06699 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06700 if (!ast_strlen_zero(i->dnid))
06701 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06702
06703
06704
06705 #ifdef PRI_ANI
06706 if (!ast_strlen_zero(i->cid_ani))
06707 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06708 else
06709 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06710 #else
06711 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06712 #endif
06713 tmp->cid.cid_pres = i->callingpres;
06714 tmp->cid.cid_ton = i->cid_ton;
06715 #ifdef HAVE_PRI
06716 tmp->transfercapability = transfercapability;
06717 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06718 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
06719 i->digital = 1;
06720
06721 i->isidlecall = 0;
06722 i->alreadyhungup = 0;
06723 #endif
06724
06725 i->fake_event = 0;
06726
06727 dahdi_confmute(i, 0);
06728
06729 ast_jb_configure(tmp, &global_jbconf);
06730 if (startpbx) {
06731 #ifdef HAVE_OPENR2
06732 if (i->mfcr2call) {
06733 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
06734 }
06735 #endif
06736 if (ast_pbx_start(tmp)) {
06737 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06738 ast_hangup(tmp);
06739 i->owner = NULL;
06740 return NULL;
06741 }
06742 }
06743
06744 ast_module_ref(ast_module_info->self);
06745
06746 return tmp;
06747 }
06748
06749
06750 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06751 {
06752 char c;
06753
06754 *str = 0;
06755 for (;;)
06756 {
06757
06758 c = ast_waitfordigit(chan, ms);
06759
06760 if (c < 1)
06761 return c;
06762 *str++ = c;
06763 *str = 0;
06764 if (strchr(term, c))
06765 return 1;
06766 }
06767 }
06768
06769 static int dahdi_wink(struct dahdi_pvt *p, int index)
06770 {
06771 int j;
06772 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06773 for (;;)
06774 {
06775
06776 j = DAHDI_IOMUX_SIGEVENT;
06777
06778 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06779
06780 if (j & DAHDI_IOMUX_SIGEVENT) break;
06781 }
06782
06783 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06784 return 0;
06785 }
06786
06787 static void *ss_thread(void *data)
06788 {
06789 struct ast_channel *chan = data;
06790 struct dahdi_pvt *p = chan->tech_pvt;
06791 char exten[AST_MAX_EXTENSION] = "";
06792 char exten2[AST_MAX_EXTENSION] = "";
06793 unsigned char buf[256];
06794 char dtmfcid[300];
06795 char dtmfbuf[300];
06796 struct callerid_state *cs = NULL;
06797 char *name = NULL, *number = NULL;
06798 int distMatches;
06799 int curRingData[3];
06800 int receivedRingT;
06801 int counter1;
06802 int counter;
06803 int samples = 0;
06804 struct ast_smdi_md_message *smdi_msg = NULL;
06805 int flags = 0;
06806 int i;
06807 int timeout;
06808 int getforward = 0;
06809 char *s1, *s2;
06810 int len = 0;
06811 int res;
06812 int index;
06813
06814 ast_mutex_lock(&ss_thread_lock);
06815 ss_thread_count++;
06816 ast_mutex_unlock(&ss_thread_lock);
06817
06818
06819
06820 if (!p) {
06821 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06822 ast_hangup(chan);
06823 goto quit;
06824 }
06825 if (option_verbose > 2)
06826 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
06827 index = dahdi_get_index(chan, p, 1);
06828 if (index < 0) {
06829 ast_log(LOG_WARNING, "Huh?\n");
06830 ast_hangup(chan);
06831 goto quit;
06832 }
06833 if (p->dsp)
06834 ast_dsp_digitreset(p->dsp);
06835 switch (p->sig) {
06836 #ifdef HAVE_PRI
06837 case SIG_PRI:
06838
06839 ast_copy_string(exten, p->exten, sizeof(exten));
06840 len = strlen(exten);
06841 res = 0;
06842 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06843 if (len && !ast_ignore_pattern(chan->context, exten))
06844 tone_zone_play_tone(p->subs[index].dfd, -1);
06845 else
06846 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06847 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06848 timeout = matchdigittimeout;
06849 else
06850 timeout = gendigittimeout;
06851 res = ast_waitfordigit(chan, timeout);
06852 if (res < 0) {
06853 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06854 ast_hangup(chan);
06855 goto quit;
06856 } else if (res) {
06857 exten[len++] = res;
06858 exten[len] = '\0';
06859 } else
06860 break;
06861 }
06862
06863 if (ast_strlen_zero(exten)) {
06864 if (option_verbose > 2)
06865 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
06866 exten[0] = 's';
06867 exten[1] = '\0';
06868 }
06869 tone_zone_play_tone(p->subs[index].dfd, -1);
06870 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06871
06872 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06873 if (p->dsp) ast_dsp_digitreset(p->dsp);
06874 dahdi_enable_ec(p);
06875 ast_setstate(chan, AST_STATE_RING);
06876 res = ast_pbx_run(chan);
06877 if (res) {
06878 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06879 }
06880 } else {
06881 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06882 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06883 ast_hangup(chan);
06884 p->exten[0] = '\0';
06885
06886 p->call = NULL;
06887 }
06888 goto quit;
06889 break;
06890 #endif
06891 case SIG_FEATD:
06892 case SIG_FEATDMF:
06893 case SIG_FEATDMF_TA:
06894 case SIG_E911:
06895 case SIG_FGC_CAMAMF:
06896 case SIG_FEATB:
06897 case SIG_EMWINK:
06898 case SIG_SF_FEATD:
06899 case SIG_SF_FEATDMF:
06900 case SIG_SF_FEATB:
06901 case SIG_SFWINK:
06902 if (dahdi_wink(p, index))
06903 goto quit;
06904
06905 case SIG_EM:
06906 case SIG_EM_E1:
06907 case SIG_SF:
06908 case SIG_FGC_CAMA:
06909 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06910 if (p->dsp)
06911 ast_dsp_digitreset(p->dsp);
06912
06913 if (p->dsp) {
06914 if (NEED_MFDETECT(p))
06915 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06916 else
06917 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06918 }
06919 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06920
06921 if (!p->immediate)
06922
06923 res = ast_waitfordigit(chan, 5000);
06924 else
06925 res = 0;
06926 if (res > 0) {
06927
06928 dtmfbuf[0] = res;
06929 switch (p->sig) {
06930 case SIG_FEATD:
06931 case SIG_SF_FEATD:
06932 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06933 if (res > 0)
06934 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06935 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06936 break;
06937 case SIG_FEATDMF_TA:
06938 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06939 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06940 if (dahdi_wink(p, index)) goto quit;
06941 dtmfbuf[0] = 0;
06942
06943 res = ast_waitfordigit(chan, 5000);
06944 if (res <= 0) break;
06945 dtmfbuf[0] = res;
06946
06947 case SIG_FEATDMF:
06948 case SIG_E911:
06949 case SIG_FGC_CAMAMF:
06950 case SIG_SF_FEATDMF:
06951 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06952
06953 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06954 {
06955 if (dahdi_wink(p, index)) goto quit;
06956 dtmfbuf[0] = 0;
06957
06958 res = ast_waitfordigit(chan, 5000);
06959 if (res <= 0) break;
06960 dtmfbuf[0] = res;
06961 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06962 }
06963 if (res > 0) {
06964
06965 if (p->sig == SIG_E911)
06966 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06967 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06968 }
06969 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06970 break;
06971 case SIG_FEATB:
06972 case SIG_SF_FEATB:
06973 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06974 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06975 break;
06976 case SIG_EMWINK:
06977
06978
06979
06980
06981 if (res == '*') {
06982 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06983 if (res > 0)
06984 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06985 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06986 break;
06987 }
06988 default:
06989
06990 len = 1;
06991 dtmfbuf[len] = '\0';
06992 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06993 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06994 timeout = matchdigittimeout;
06995 } else {
06996 timeout = gendigittimeout;
06997 }
06998 res = ast_waitfordigit(chan, timeout);
06999 if (res < 0) {
07000 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07001 ast_hangup(chan);
07002 goto quit;
07003 } else if (res) {
07004 dtmfbuf[len++] = res;
07005 dtmfbuf[len] = '\0';
07006 } else {
07007 break;
07008 }
07009 }
07010 break;
07011 }
07012 }
07013 if (res == -1) {
07014 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
07015 ast_hangup(chan);
07016 goto quit;
07017 } else if (res < 0) {
07018 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
07019 ast_hangup(chan);
07020 goto quit;
07021 }
07022
07023 if (p->sig == SIG_FGC_CAMA) {
07024 char anibuf[100];
07025
07026 if (ast_safe_sleep(chan,1000) == -1) {
07027 ast_hangup(chan);
07028 goto quit;
07029 }
07030 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07031 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
07032 res = my_getsigstr(chan, anibuf, "#", 10000);
07033 if ((res > 0) && (strlen(anibuf) > 2)) {
07034 if (anibuf[strlen(anibuf) - 1] == '#')
07035 anibuf[strlen(anibuf) - 1] = 0;
07036 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07037 }
07038 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07039 }
07040
07041 ast_copy_string(exten, dtmfbuf, sizeof(exten));
07042 if (ast_strlen_zero(exten))
07043 ast_copy_string(exten, "s", sizeof(exten));
07044 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07045
07046 if (exten[0] == '*') {
07047 char *stringp=NULL;
07048 ast_copy_string(exten2, exten, sizeof(exten2));
07049
07050 stringp=exten2 +1;
07051 s1 = strsep(&stringp, "*");
07052 s2 = strsep(&stringp, "*");
07053 if (s2) {
07054 if (!ast_strlen_zero(p->cid_num))
07055 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07056 else
07057 ast_set_callerid(chan, s1, NULL, s1);
07058 ast_copy_string(exten, s2, sizeof(exten));
07059 } else
07060 ast_copy_string(exten, s1, sizeof(exten));
07061 } else if (p->sig == SIG_FEATD)
07062 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07063 }
07064 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07065 if (exten[0] == '*') {
07066 char *stringp=NULL;
07067 ast_copy_string(exten2, exten, sizeof(exten2));
07068
07069 stringp=exten2 +1;
07070 s1 = strsep(&stringp, "#");
07071 s2 = strsep(&stringp, "#");
07072 if (s2) {
07073 if (!ast_strlen_zero(p->cid_num))
07074 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07075 else
07076 if (*(s1 + 2))
07077 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07078 ast_copy_string(exten, s2 + 1, sizeof(exten));
07079 } else
07080 ast_copy_string(exten, s1 + 2, sizeof(exten));
07081 } else
07082 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07083 }
07084 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07085 if (exten[0] == '*') {
07086 char *stringp=NULL;
07087 ast_copy_string(exten2, exten, sizeof(exten2));
07088
07089 stringp=exten2 +1;
07090 s1 = strsep(&stringp, "#");
07091 s2 = strsep(&stringp, "#");
07092 if (s2 && (*(s2 + 1) == '0')) {
07093 if (*(s2 + 2))
07094 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07095 }
07096 if (s1) ast_copy_string(exten, s1, sizeof(exten));
07097 else ast_copy_string(exten, "911", sizeof(exten));
07098 } else
07099 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
07100 }
07101 if (p->sig == SIG_FEATB) {
07102 if (exten[0] == '*') {
07103 char *stringp=NULL;
07104 ast_copy_string(exten2, exten, sizeof(exten2));
07105
07106 stringp=exten2 +1;
07107 s1 = strsep(&stringp, "#");
07108 ast_copy_string(exten, exten2 + 1, sizeof(exten));
07109 } else
07110 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
07111 }
07112 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07113 dahdi_wink(p, index);
07114
07115
07116
07117 if (ast_safe_sleep(chan,100)) goto quit;
07118 }
07119 dahdi_enable_ec(p);
07120 if (NEED_MFDETECT(p)) {
07121 if (p->dsp) {
07122 if (!p->hardwaredtmf)
07123 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07124 else {
07125 ast_dsp_free(p->dsp);
07126 p->dsp = NULL;
07127 }
07128 }
07129 }
07130
07131 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07132 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07133 if (p->dsp) ast_dsp_digitreset(p->dsp);
07134 res = ast_pbx_run(chan);
07135 if (res) {
07136 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07137 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07138 }
07139 goto quit;
07140 } else {
07141 if (option_verbose > 2)
07142 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07143 sleep(2);
07144 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07145 if (res < 0)
07146 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07147 else
07148 sleep(1);
07149 res = ast_streamfile(chan, "ss-noservice", chan->language);
07150 if (res >= 0)
07151 ast_waitstream(chan, "");
07152 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07153 ast_hangup(chan);
07154 goto quit;
07155 }
07156 break;
07157 case SIG_FXOLS:
07158 case SIG_FXOGS:
07159 case SIG_FXOKS:
07160
07161 timeout = firstdigittimeout;
07162
07163
07164 if (p->subs[SUB_THREEWAY].owner)
07165 timeout = 999999;
07166 while (len < AST_MAX_EXTENSION-1) {
07167
07168
07169 if (p->immediate)
07170 res = 's';
07171 else
07172 res = ast_waitfordigit(chan, timeout);
07173 timeout = 0;
07174 if (res < 0) {
07175 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07176 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07177 ast_hangup(chan);
07178 goto quit;
07179 } else if (res) {
07180 exten[len++]=res;
07181 exten[len] = '\0';
07182 }
07183 if (!ast_ignore_pattern(chan->context, exten))
07184 tone_zone_play_tone(p->subs[index].dfd, -1);
07185 else
07186 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07187 if (!strcmp(exten,ast_pickup_ext())) {
07188
07189
07190
07191
07192 if (index == SUB_REAL) {
07193
07194 if (p->subs[SUB_THREEWAY].owner) {
07195
07196
07197 alloc_sub(p, SUB_CALLWAIT);
07198 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07199 unalloc_sub(p, SUB_THREEWAY);
07200 }
07201 dahdi_enable_ec(p);
07202 if (ast_pickup_call(chan)) {
07203 ast_log(LOG_DEBUG, "No call pickup possible...\n");
07204 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07205 dahdi_wait_event(p->subs[index].dfd);
07206 }
07207 ast_hangup(chan);
07208 goto quit;
07209 } else {
07210 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07211 ast_hangup(chan);
07212 goto quit;
07213 }
07214
07215 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07216 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07217 if (getforward) {
07218
07219 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
07220 if (option_verbose > 2)
07221 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07222 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07223 if (res)
07224 break;
07225 usleep(500000);
07226 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07227 sleep(1);
07228 memset(exten, 0, sizeof(exten));
07229 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07230 len = 0;
07231 getforward = 0;
07232 } else {
07233 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07234 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07235 if (!ast_strlen_zero(p->cid_num)) {
07236 if (!p->hidecallerid)
07237 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07238 else
07239 ast_set_callerid(chan, NULL, NULL, p->cid_num);
07240 }
07241 if (!ast_strlen_zero(p->cid_name)) {
07242 if (!p->hidecallerid)
07243 ast_set_callerid(chan, NULL, p->cid_name, NULL);
07244 }
07245 ast_setstate(chan, AST_STATE_RING);
07246 dahdi_enable_ec(p);
07247 res = ast_pbx_run(chan);
07248 if (res) {
07249 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07250 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07251 }
07252 goto quit;
07253 }
07254 } else {
07255
07256
07257 timeout = matchdigittimeout;
07258 }
07259 } else if (res == 0) {
07260 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07261 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07262 dahdi_wait_event(p->subs[index].dfd);
07263 ast_hangup(chan);
07264 goto quit;
07265 } else if (p->callwaiting && !strcmp(exten, "*70")) {
07266 if (option_verbose > 2)
07267 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07268
07269 p->callwaiting = 0;
07270 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07271 if (res) {
07272 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07273 chan->name, strerror(errno));
07274 }
07275 len = 0;
07276 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07277 memset(exten, 0, sizeof(exten));
07278 timeout = firstdigittimeout;
07279
07280 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07281 if (option_verbose > 2)
07282 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07283
07284 p->hidecallerid = 1;
07285 if (chan->cid.cid_num)
07286 free(chan->cid.cid_num);
07287 chan->cid.cid_num = NULL;
07288 if (chan->cid.cid_name)
07289 free(chan->cid.cid_name);
07290 chan->cid.cid_name = NULL;
07291 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07292 if (res) {
07293 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07294 chan->name, strerror(errno));
07295 }
07296 len = 0;
07297 memset(exten, 0, sizeof(exten));
07298 timeout = firstdigittimeout;
07299 } else if (p->callreturn && !strcmp(exten, "*69")) {
07300 res = 0;
07301 if (!ast_strlen_zero(p->lastcid_num)) {
07302 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07303 }
07304 if (!res)
07305 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07306 break;
07307 } else if (!strcmp(exten, "*78")) {
07308
07309 if (option_verbose > 2)
07310 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07311 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07312 "Channel: %s/%d\r\n"
07313 "Status: enabled\r\n", dahdi_chan_name, p->channel);
07314 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07315 p->dnd = 1;
07316 getforward = 0;
07317 memset(exten, 0, sizeof(exten));
07318 len = 0;
07319 } else if (!strcmp(exten, "*79")) {
07320
07321 if (option_verbose > 2)
07322 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07323 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07324 "Channel: %s/%d\r\n"
07325 "Status: disabled\r\n", dahdi_chan_name, p->channel);
07326 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07327 p->dnd = 0;
07328 getforward = 0;
07329 memset(exten, 0, sizeof(exten));
07330 len = 0;
07331 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07332 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07333 getforward = 1;
07334 memset(exten, 0, sizeof(exten));
07335 len = 0;
07336 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07337 if (option_verbose > 2)
07338 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07339 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07340 memset(p->call_forward, 0, sizeof(p->call_forward));
07341 getforward = 0;
07342 memset(exten, 0, sizeof(exten));
07343 len = 0;
07344 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07345 p->subs[SUB_THREEWAY].owner &&
07346 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07347
07348
07349 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07350 if (option_verbose > 2)
07351 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07352 break;
07353 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07354 if (option_verbose > 2)
07355 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07356 res = ast_db_put("blacklist", p->lastcid_num, "1");
07357 if (!res) {
07358 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07359 memset(exten, 0, sizeof(exten));
07360 len = 0;
07361 }
07362 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07363 if (option_verbose > 2)
07364 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07365
07366 p->hidecallerid = 0;
07367 if (chan->cid.cid_num)
07368 free(chan->cid.cid_num);
07369 chan->cid.cid_num = NULL;
07370 if (chan->cid.cid_name)
07371 free(chan->cid.cid_name);
07372 chan->cid.cid_name = NULL;
07373 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07374 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07375 if (res) {
07376 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07377 chan->name, strerror(errno));
07378 }
07379 len = 0;
07380 memset(exten, 0, sizeof(exten));
07381 timeout = firstdigittimeout;
07382 } else if (!strcmp(exten, "*0")) {
07383 struct ast_channel *nbridge =
07384 p->subs[SUB_THREEWAY].owner;
07385 struct dahdi_pvt *pbridge = NULL;
07386
07387 if (nbridge && ast_bridged_channel(nbridge))
07388 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07389 if (nbridge && pbridge &&
07390 (nbridge->tech == chan_tech) &&
07391 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07392 ISTRUNK(pbridge)) {
07393 int func = DAHDI_FLASH;
07394
07395 p->dop.dialstr[0] = '\0';
07396
07397 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07398 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07399 nbridge->name, strerror(errno));
07400 }
07401 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07402 unalloc_sub(p, SUB_THREEWAY);
07403 p->owner = p->subs[SUB_REAL].owner;
07404 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07405 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07406 ast_hangup(chan);
07407 goto quit;
07408 } else {
07409 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07410 dahdi_wait_event(p->subs[index].dfd);
07411 tone_zone_play_tone(p->subs[index].dfd, -1);
07412 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07413 unalloc_sub(p, SUB_THREEWAY);
07414 p->owner = p->subs[SUB_REAL].owner;
07415 ast_hangup(chan);
07416 goto quit;
07417 }
07418 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07419 ((exten[0] != '*') || (strlen(exten) > 2))) {
07420 if (option_debug)
07421 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);
07422 break;
07423 }
07424 if (!timeout)
07425 timeout = gendigittimeout;
07426 if (len && !ast_ignore_pattern(chan->context, exten))
07427 tone_zone_play_tone(p->subs[index].dfd, -1);
07428 }
07429 break;
07430 case SIG_FXSLS:
07431 case SIG_FXSGS:
07432 case SIG_FXSKS:
07433 #ifdef HAVE_PRI
07434 if (p->pri) {
07435
07436 struct ast_frame *f;
07437 int res;
07438 time_t start;
07439
07440 time(&start);
07441 ast_setstate(chan, AST_STATE_RING);
07442 while (time(NULL) < start + 3) {
07443 res = ast_waitfor(chan, 1000);
07444 if (res) {
07445 f = ast_read(chan);
07446 if (!f) {
07447 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07448 ast_hangup(chan);
07449 goto quit;
07450 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07451 res = 1;
07452 } else
07453 res = 0;
07454 ast_frfree(f);
07455 if (res) {
07456 ast_log(LOG_DEBUG, "Got ring!\n");
07457 res = 0;
07458 break;
07459 }
07460 }
07461 }
07462 }
07463 #endif
07464
07465 if (p->use_smdi && p->smdi_iface) {
07466 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07467
07468 if (smdi_msg != NULL) {
07469 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07470
07471 if (smdi_msg->type == 'B')
07472 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07473 else if (smdi_msg->type == 'N')
07474 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07475
07476 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
07477 } else {
07478 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07479 }
07480 }
07481
07482 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07483 number = smdi_msg->calling_st;
07484
07485
07486
07487
07488 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
07489 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
07490
07491 if (p->cid_signalling == CID_SIG_DTMF) {
07492 int i = 0;
07493 cs = NULL;
07494 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
07495 "channel %s\n", chan->name);
07496 dahdi_setlinear(p->subs[index].dfd, 0);
07497 res = 2000;
07498 for (;;) {
07499 struct ast_frame *f;
07500 res = ast_waitfor(chan, res);
07501 if (res <= 0) {
07502 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07503 "Exiting simple switch\n");
07504 ast_hangup(chan);
07505 goto quit;
07506 }
07507 f = ast_read(chan);
07508 if (!f)
07509 break;
07510 if (f->frametype == AST_FRAME_DTMF) {
07511 dtmfbuf[i++] = f->subclass;
07512 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07513 res = 2000;
07514 }
07515 ast_frfree(f);
07516 if (chan->_state == AST_STATE_RING ||
07517 chan->_state == AST_STATE_RINGING)
07518 break;
07519 }
07520 dtmfbuf[i] = '\0';
07521 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07522
07523 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
07524 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07525 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07526 dtmfcid, flags);
07527
07528 if (!ast_strlen_zero(dtmfcid))
07529 number = dtmfcid;
07530 else
07531 number = NULL;
07532
07533 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07534 cs = callerid_new(p->cid_signalling);
07535 if (cs) {
07536 samples = 0;
07537 #if 1
07538 bump_gains(p);
07539 #endif
07540
07541 dahdi_setlinear(p->subs[index].dfd, 0);
07542
07543
07544 for (;;) {
07545 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07546 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07547 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07548 callerid_free(cs);
07549 ast_hangup(chan);
07550 goto quit;
07551 }
07552 if (i & DAHDI_IOMUX_SIGEVENT) {
07553 res = dahdi_get_event(p->subs[index].dfd);
07554 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07555
07556 if (p->cid_signalling == CID_SIG_V23_JP) {
07557 #ifdef DAHDI_EVENT_RINGBEGIN
07558 if (res == DAHDI_EVENT_RINGBEGIN) {
07559 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07560 usleep(1);
07561 }
07562 #endif
07563 } else {
07564 res = 0;
07565 break;
07566 }
07567 } else if (i & DAHDI_IOMUX_READ) {
07568 res = read(p->subs[index].dfd, buf, sizeof(buf));
07569 if (res < 0) {
07570 if (errno != ELAST) {
07571 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07572 callerid_free(cs);
07573 ast_hangup(chan);
07574 goto quit;
07575 }
07576 break;
07577 }
07578 samples += res;
07579
07580 if (p->cid_signalling == CID_SIG_V23_JP) {
07581 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07582 } else {
07583 res = callerid_feed(cs, buf, res, AST_LAW(p));
07584 }
07585
07586 if (res < 0) {
07587 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07588 break;
07589 } else if (res)
07590 break;
07591 else if (samples > (8000 * 10))
07592 break;
07593 }
07594 }
07595 if (res == 1) {
07596 callerid_get(cs, &name, &number, &flags);
07597 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07598 }
07599
07600 if (p->cid_signalling == CID_SIG_V23_JP) {
07601 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07602 usleep(1);
07603 res = 4000;
07604 } else {
07605
07606
07607 res = 2000;
07608 }
07609
07610 for (;;) {
07611 struct ast_frame *f;
07612 res = ast_waitfor(chan, res);
07613 if (res <= 0) {
07614 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07615 "Exiting simple switch\n");
07616 ast_hangup(chan);
07617 goto quit;
07618 }
07619 if (!(f = ast_read(chan))) {
07620 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07621 ast_hangup(chan);
07622 goto quit;
07623 }
07624 ast_frfree(f);
07625 if (chan->_state == AST_STATE_RING ||
07626 chan->_state == AST_STATE_RINGING)
07627 break;
07628 }
07629
07630
07631
07632 if (p->usedistinctiveringdetection) {
07633 len = 0;
07634 distMatches = 0;
07635
07636 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07637 curRingData[receivedRingT] = 0;
07638 receivedRingT = 0;
07639 counter = 0;
07640 counter1 = 0;
07641
07642 if (strcmp(p->context,p->defcontext) != 0) {
07643 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07644 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07645 }
07646
07647 for (;;) {
07648 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07649 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07650 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07651 callerid_free(cs);
07652 ast_hangup(chan);
07653 goto quit;
07654 }
07655 if (i & DAHDI_IOMUX_SIGEVENT) {
07656 res = dahdi_get_event(p->subs[index].dfd);
07657 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07658 res = 0;
07659
07660
07661 curRingData[receivedRingT] = p->ringt;
07662
07663 if (p->ringt < p->ringt_base/2)
07664 break;
07665
07666
07667 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07668 break;
07669 } else if (i & DAHDI_IOMUX_READ) {
07670 res = read(p->subs[index].dfd, buf, sizeof(buf));
07671 if (res < 0) {
07672 if (errno != ELAST) {
07673 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07674 callerid_free(cs);
07675 ast_hangup(chan);
07676 goto quit;
07677 }
07678 break;
07679 }
07680 if (p->ringt)
07681 p->ringt--;
07682 if (p->ringt == 1) {
07683 res = -1;
07684 break;
07685 }
07686 }
07687 }
07688 if (option_verbose > 2)
07689
07690 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07691
07692 for (counter = 0; counter < 3; counter++) {
07693
07694
07695 distMatches = 0;
07696 for (counter1 = 0; counter1 < 3; counter1++) {
07697 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07698 (p->drings.ringnum[counter].ring[counter1]-10)) {
07699 distMatches++;
07700 }
07701 }
07702 if (distMatches == 3) {
07703
07704 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07705 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07706 if (option_verbose > 2)
07707 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07708 break;
07709 }
07710 }
07711 }
07712
07713 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07714 #if 1
07715 restore_gains(p);
07716 #endif
07717 } else
07718 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07719 } else {
07720 ast_log(LOG_WARNING, "Channel %s in prering "
07721 "state, but I have nothing to do. "
07722 "Terminating simple switch, should be "
07723 "restarted by the actual ring.\n",
07724 chan->name);
07725 ast_hangup(chan);
07726 goto quit;
07727 }
07728 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07729
07730 cs = callerid_new(p->cid_signalling);
07731 if (cs) {
07732 #if 1
07733 bump_gains(p);
07734 #endif
07735 samples = 0;
07736 len = 0;
07737 distMatches = 0;
07738
07739 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07740 curRingData[receivedRingT] = 0;
07741 receivedRingT = 0;
07742 counter = 0;
07743 counter1 = 0;
07744
07745 if (strcmp(p->context,p->defcontext) != 0) {
07746 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07747 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07748 }
07749
07750
07751 dahdi_setlinear(p->subs[index].dfd, 0);
07752 for (;;) {
07753 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07754 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07755 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07756 callerid_free(cs);
07757 ast_hangup(chan);
07758 goto quit;
07759 }
07760 if (i & DAHDI_IOMUX_SIGEVENT) {
07761 res = dahdi_get_event(p->subs[index].dfd);
07762 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07763
07764 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07765 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07766 p->polarity = POLARITY_IDLE;
07767 callerid_free(cs);
07768 ast_hangup(chan);
07769 goto quit;
07770 }
07771 res = 0;
07772
07773
07774 curRingData[receivedRingT] = p->ringt;
07775
07776 if (p->ringt < p->ringt_base/2)
07777 break;
07778
07779
07780 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07781 break;
07782 } else if (i & DAHDI_IOMUX_READ) {
07783 res = read(p->subs[index].dfd, buf, sizeof(buf));
07784 if (res < 0) {
07785 if (errno != ELAST) {
07786 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07787 callerid_free(cs);
07788 ast_hangup(chan);
07789 goto quit;
07790 }
07791 break;
07792 }
07793 if (p->ringt)
07794 p->ringt--;
07795 if (p->ringt == 1) {
07796 res = -1;
07797 break;
07798 }
07799 samples += res;
07800 res = callerid_feed(cs, buf, res, AST_LAW(p));
07801 if (res < 0) {
07802 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07803 break;
07804 } else if (res)
07805 break;
07806 else if (samples > (8000 * 10))
07807 break;
07808 }
07809 }
07810 if (res == 1) {
07811 callerid_get(cs, &name, &number, &flags);
07812 if (option_debug)
07813 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07814 }
07815 if (distinctiveringaftercid == 1) {
07816
07817 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07818 curRingData[receivedRingT] = 0;
07819 }
07820 receivedRingT = 0;
07821 if (option_verbose > 2)
07822 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
07823 for (;;) {
07824 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07825 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07826 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07827 callerid_free(cs);
07828 ast_hangup(chan);
07829 goto quit;
07830 }
07831 if (i & DAHDI_IOMUX_SIGEVENT) {
07832 res = dahdi_get_event(p->subs[index].dfd);
07833 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07834 res = 0;
07835
07836
07837 curRingData[receivedRingT] = p->ringt;
07838
07839 if (p->ringt < p->ringt_base/2)
07840 break;
07841
07842
07843 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07844 break;
07845 } else if (i & DAHDI_IOMUX_READ) {
07846 res = read(p->subs[index].dfd, buf, sizeof(buf));
07847 if (res < 0) {
07848 if (errno != ELAST) {
07849 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07850 callerid_free(cs);
07851 ast_hangup(chan);
07852 goto quit;
07853 }
07854 break;
07855 }
07856 if (p->ringt)
07857 p->ringt--;
07858 if (p->ringt == 1) {
07859 res = -1;
07860 break;
07861 }
07862 }
07863 }
07864 }
07865 if (p->usedistinctiveringdetection) {
07866 if (option_verbose > 2)
07867
07868 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07869
07870 for (counter = 0; counter < 3; counter++) {
07871
07872
07873 if (option_verbose > 2)
07874
07875 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
07876 p->drings.ringnum[counter].ring[0],
07877 p->drings.ringnum[counter].ring[1],
07878 p->drings.ringnum[counter].ring[2]);
07879 distMatches = 0;
07880 for (counter1 = 0; counter1 < 3; counter1++) {
07881 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07882 (p->drings.ringnum[counter].ring[counter1]-10)) {
07883 distMatches++;
07884 }
07885 }
07886 if (distMatches == 3) {
07887
07888 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07889 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07890 if (option_verbose > 2)
07891 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07892 break;
07893 }
07894 }
07895 }
07896
07897 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07898 #if 1
07899 restore_gains(p);
07900 #endif
07901 if (res < 0) {
07902 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07903 }
07904 } else
07905 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07906 }
07907 else
07908 cs = NULL;
07909
07910 if (number)
07911 ast_shrink_phone_number(number);
07912 ast_set_callerid(chan, number, name, number);
07913
07914 if (smdi_msg)
07915 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07916
07917 if (cs)
07918 callerid_free(cs);
07919
07920 ast_setstate(chan, AST_STATE_RING);
07921 chan->rings = 1;
07922 p->ringt = p->ringt_base;
07923 res = ast_pbx_run(chan);
07924 if (res) {
07925 ast_hangup(chan);
07926 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07927 }
07928 goto quit;
07929 default:
07930 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07931 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07932 if (res < 0)
07933 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07934 }
07935 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07936 if (res < 0)
07937 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07938 ast_hangup(chan);
07939 quit:
07940 ast_mutex_lock(&ss_thread_lock);
07941 ss_thread_count--;
07942 ast_cond_signal(&ss_thread_complete);
07943 ast_mutex_unlock(&ss_thread_lock);
07944 return NULL;
07945 }
07946
07947 static int calc_energy(const unsigned char *buf, int len, int law)
07948 {
07949 int x;
07950 int sum = 0;
07951 int ssum = 0, mean = 0;
07952
07953 if (!len)
07954 return 0;
07955
07956
07957 for (x = 0; x < len; x++)
07958 ssum += (law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07959
07960 mean = ssum / len;
07961
07962 for (x = 0; x < len; x++) {
07963 sum += abs((law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])) - mean);
07964 if (option_verbose > 7)
07965 ast_log(LOG_WARNING, "x %i, bufx: %i sum %i, ssum %i\n", x, buf[x], sum, ssum);
07966 }
07967
07968 if (option_verbose > 5)
07969 ast_log(LOG_WARNING, "mean %i, energy %i\n", mean, sum/len);
07970
07971 return sum / len;
07972 }
07973
07974
07975 static int dahdi_destroy_channel_bynum(int channel)
07976 {
07977 struct dahdi_pvt *tmp = NULL;
07978 struct dahdi_pvt *prev = NULL;
07979
07980 ast_mutex_lock(&iflock);
07981 tmp = iflist;
07982 while (tmp) {
07983 if (tmp->channel == channel) {
07984 int x = DAHDI_FLASH;
07985 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07986 destroy_channel(prev, tmp, 1);
07987 ast_mutex_unlock(&iflock);
07988 ast_module_unref(ast_module_info->self);
07989 return RESULT_SUCCESS;
07990 }
07991 prev = tmp;
07992 tmp = tmp->next;
07993 }
07994 ast_mutex_unlock(&iflock);
07995 return RESULT_FAILURE;
07996 }
07997
07998 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
07999 {
08000 int res;
08001 pthread_t threadid;
08002 pthread_attr_t attr;
08003 struct ast_channel *chan;
08004 pthread_attr_init(&attr);
08005 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08006
08007 switch (event) {
08008 case DAHDI_EVENT_NONE:
08009 case DAHDI_EVENT_BITSCHANGED:
08010 break;
08011 case DAHDI_EVENT_WINKFLASH:
08012 case DAHDI_EVENT_RINGOFFHOOK:
08013 if (i->inalarm) break;
08014 if (i->radio) break;
08015
08016 switch (i->sig) {
08017 case SIG_FXOLS:
08018 case SIG_FXOGS:
08019 case SIG_FXOKS:
08020 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08021 if (res && (errno == EBUSY))
08022 break;
08023 if (i->cidspill) {
08024
08025 free(i->cidspill);
08026 i->cidspill = NULL;
08027 }
08028 if (i->immediate) {
08029 dahdi_enable_ec(i);
08030
08031 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08032 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08033 if (!chan) {
08034 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08035 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08036 if (res < 0)
08037 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08038 }
08039 } else {
08040
08041 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08042 if (chan) {
08043 if (has_voicemail(i))
08044 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08045 else
08046 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08047 if (res < 0)
08048 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08049 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08050 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08051 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08052 if (res < 0)
08053 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08054 ast_hangup(chan);
08055 }
08056 } else
08057 ast_log(LOG_WARNING, "Unable to create channel\n");
08058 }
08059 break;
08060 case SIG_FXSLS:
08061 case SIG_FXSGS:
08062 case SIG_FXSKS:
08063 i->ringt = i->ringt_base;
08064
08065 case SIG_EMWINK:
08066 case SIG_FEATD:
08067 case SIG_FEATDMF:
08068 case SIG_FEATDMF_TA:
08069 case SIG_E911:
08070 case SIG_FGC_CAMA:
08071 case SIG_FGC_CAMAMF:
08072 case SIG_FEATB:
08073 case SIG_EM:
08074 case SIG_EM_E1:
08075 case SIG_SFWINK:
08076 case SIG_SF_FEATD:
08077 case SIG_SF_FEATDMF:
08078 case SIG_SF_FEATB:
08079 case SIG_SF:
08080
08081 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08082 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08083 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08084 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08085 if (res < 0)
08086 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08087 ast_hangup(chan);
08088 } else if (!chan) {
08089 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08090 }
08091 break;
08092 default:
08093 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08094 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08095 if (res < 0)
08096 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08097 pthread_attr_destroy(&attr);
08098 return NULL;
08099 }
08100 break;
08101 case DAHDI_EVENT_NOALARM:
08102 i->inalarm = 0;
08103 if (!i->unknown_alarm) {
08104 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08105 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08106 "Channel: %d\r\n", i->channel);
08107 } else {
08108 i->unknown_alarm = 0;
08109 }
08110 break;
08111 case DAHDI_EVENT_ALARM:
08112 i->inalarm = 1;
08113 res = get_alarms(i);
08114 handle_alarms(i, res);
08115
08116 case DAHDI_EVENT_ONHOOK:
08117 if (i->radio)
08118 break;
08119
08120 switch (i->sig) {
08121 case SIG_FXOLS:
08122 case SIG_FXOGS:
08123 case SIG_FEATD:
08124 case SIG_FEATDMF:
08125 case SIG_FEATDMF_TA:
08126 case SIG_E911:
08127 case SIG_FGC_CAMA:
08128 case SIG_FGC_CAMAMF:
08129 case SIG_FEATB:
08130 case SIG_EM:
08131 case SIG_EM_E1:
08132 case SIG_EMWINK:
08133 case SIG_SF_FEATD:
08134 case SIG_SF_FEATDMF:
08135 case SIG_SF_FEATB:
08136 case SIG_SF:
08137 case SIG_SFWINK:
08138 case SIG_FXSLS:
08139 case SIG_FXSGS:
08140 case SIG_FXSKS:
08141 case SIG_GR303FXSKS:
08142 dahdi_disable_ec(i);
08143 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08144 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08145 break;
08146 case SIG_GR303FXOKS:
08147 case SIG_FXOKS:
08148 dahdi_disable_ec(i);
08149
08150 #ifdef ZHONE_HACK
08151 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08152 usleep(1);
08153 #endif
08154 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08155 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08156 break;
08157 case SIG_PRI:
08158 dahdi_disable_ec(i);
08159 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08160 break;
08161 default:
08162 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08163 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08164 pthread_attr_destroy(&attr);
08165 return NULL;
08166 }
08167 break;
08168 case DAHDI_EVENT_POLARITY:
08169 switch (i->sig) {
08170 case SIG_FXSLS:
08171 case SIG_FXSKS:
08172 case SIG_FXSGS:
08173
08174
08175
08176
08177 if (i->hanguponpolarityswitch)
08178 i->polarity = POLARITY_REV;
08179
08180 if (i->cid_start == CID_START_POLARITY) {
08181 i->polarity = POLARITY_REV;
08182 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08183 "CID detection on channel %d\n",
08184 i->channel);
08185 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08186 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08187 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08188 }
08189 }
08190 break;
08191 default:
08192 ast_log(LOG_WARNING, "handle_init_event detected "
08193 "polarity reversal on non-FXO (SIG_FXS) "
08194 "interface %d\n", i->channel);
08195 }
08196 break;
08197 case DAHDI_EVENT_REMOVED:
08198 ast_log(LOG_NOTICE,
08199 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08200 i->channel);
08201 pthread_attr_destroy(&attr);
08202 return i;
08203 }
08204 pthread_attr_destroy(&attr);
08205 return NULL;
08206 }
08207
08208 static void *do_monitor(void *data)
08209 {
08210 int count, res, res2, spoint, pollres=0;
08211 struct dahdi_pvt *i;
08212 struct dahdi_pvt *last = NULL;
08213 struct dahdi_pvt *doomed;
08214 time_t thispass = 0, lastpass = 0;
08215 int found;
08216 char buf[1024];
08217 struct pollfd *pfds=NULL;
08218 int lastalloc = -1;
08219
08220
08221
08222 #if 0
08223 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08224 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08225 return NULL;
08226 }
08227 ast_log(LOG_DEBUG, "Monitor starting...\n");
08228 #endif
08229 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08230
08231 for (;;) {
08232
08233 ast_mutex_lock(&iflock);
08234 if (!pfds || (lastalloc != ifcount)) {
08235 if (pfds) {
08236 free(pfds);
08237 pfds = NULL;
08238 }
08239 if (ifcount) {
08240 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08241 ast_mutex_unlock(&iflock);
08242 return NULL;
08243 }
08244 }
08245 lastalloc = ifcount;
08246 }
08247
08248
08249 count = 0;
08250 i = iflist;
08251 while (i) {
08252 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08253 if (!i->owner && !i->subs[SUB_REAL].owner) {
08254
08255 pfds[count].fd = i->subs[SUB_REAL].dfd;
08256 pfds[count].events = POLLPRI;
08257 pfds[count].revents = 0;
08258
08259 if (i->cidspill ||
08260 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
08261 pfds[count].events |= POLLIN;
08262 }
08263 count++;
08264 }
08265 }
08266 i = i->next;
08267 }
08268
08269 ast_mutex_unlock(&iflock);
08270
08271 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08272 pthread_testcancel();
08273
08274 res = poll(pfds, count, 1000);
08275 pthread_testcancel();
08276 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08277
08278
08279 if (res < 0) {
08280 if ((errno != EAGAIN) && (errno != EINTR))
08281 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08282 continue;
08283 }
08284
08285
08286 ast_mutex_lock(&iflock);
08287 found = 0;
08288 spoint = 0;
08289 lastpass = thispass;
08290 thispass = time(NULL);
08291 doomed = NULL;
08292 for (i = iflist;; i = i->next) {
08293 if (doomed) {
08294 int res;
08295 res = dahdi_destroy_channel_bynum(doomed->channel);
08296 if (!res) {
08297 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08298 }
08299 doomed = NULL;
08300 }
08301 if (!i) {
08302 break;
08303 }
08304 if (thispass != lastpass) {
08305 if (!found && ((i == last) || ((i == iflist) && !last))) {
08306 last = i;
08307 if (last) {
08308 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08309 (last->sig & __DAHDI_SIG_FXO)) {
08310 res = ast_app_has_voicemail(last->mailbox, NULL);
08311 if (last->msgstate != res) {
08312 int x;
08313 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08314 x = DAHDI_FLUSH_BOTH;
08315 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08316 if (res2)
08317 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08318 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08319
08320 x = 4000;
08321 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08322 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08323 last->cidpos = 0;
08324 last->msgstate = res;
08325 last->onhooktime = thispass;
08326 }
08327 found ++;
08328 }
08329 }
08330 last = last->next;
08331 }
08332 }
08333 }
08334 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08335 if (i->radio && !i->owner)
08336 {
08337 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08338 if (res)
08339 {
08340 if (option_debug)
08341 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08342
08343 ast_mutex_unlock(&iflock);
08344 doomed = handle_init_event(i, res);
08345 ast_mutex_lock(&iflock);
08346 }
08347 continue;
08348 }
08349 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08350 if (pollres & POLLIN) {
08351 if (i->owner || i->subs[SUB_REAL].owner) {
08352 #ifdef HAVE_PRI
08353 if (!i->pri)
08354 #endif
08355 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08356 continue;
08357 }
08358
08359
08360
08361
08362 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08363 if (res > 0) {
08364
08365
08366
08367
08368
08369
08370
08371
08372
08373
08374
08375
08376 if (i->cid_start == CID_START_DTMF_NOALERT) {
08377 int energy;
08378 struct timeval now;
08379
08380
08381
08382 if (1 == i->dtmfcid_holdoff_state) {
08383 gettimeofday(&i->dtmfcid_delay, NULL);
08384 i->dtmfcid_holdoff_state = 2;
08385 } else if (2 == i->dtmfcid_holdoff_state) {
08386 gettimeofday(&now, NULL);
08387 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
08388 i->dtmfcid_holdoff_state = 0;
08389 }
08390 } else {
08391 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
08392 if (energy > dtmfcid_level) {
08393 pthread_t threadid;
08394 struct ast_channel *chan;
08395 ast_mutex_unlock(&iflock);
08396 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08397 if (!chan) {
08398 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08399 } else {
08400 pthread_attr_t attr;
08401 pthread_attr_init(&attr);
08402 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08403 res = ast_pthread_create(&threadid, &attr, ss_thread, chan);
08404 if (res) {
08405 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08406 } else {
08407 i->dtmfcid_holdoff_state = 1;
08408 }
08409 }
08410 ast_mutex_lock(&iflock);
08411 }
08412 }
08413
08414
08415
08416 }
08417 } else {
08418 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08419 }
08420 }
08421 if (pollres & POLLPRI) {
08422 if (i->owner || i->subs[SUB_REAL].owner) {
08423 #ifdef HAVE_PRI
08424 if (!i->pri)
08425 #endif
08426 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08427 continue;
08428 }
08429 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08430 if (option_debug)
08431 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08432
08433 ast_mutex_unlock(&iflock);
08434 doomed = handle_init_event(i, res);
08435 ast_mutex_lock(&iflock);
08436 }
08437 }
08438 }
08439 ast_mutex_unlock(&iflock);
08440 }
08441
08442 return NULL;
08443
08444 }
08445
08446 static int restart_monitor(void)
08447 {
08448 pthread_attr_t attr;
08449 pthread_attr_init(&attr);
08450 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08451
08452 if (monitor_thread == AST_PTHREADT_STOP)
08453 return 0;
08454 ast_mutex_lock(&monlock);
08455 if (monitor_thread == pthread_self()) {
08456 ast_mutex_unlock(&monlock);
08457 ast_log(LOG_WARNING, "Cannot kill myself\n");
08458 return -1;
08459 }
08460 if (monitor_thread != AST_PTHREADT_NULL) {
08461
08462 pthread_kill(monitor_thread, SIGURG);
08463 } else {
08464
08465 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08466 ast_mutex_unlock(&monlock);
08467 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08468 pthread_attr_destroy(&attr);
08469 return -1;
08470 }
08471 }
08472 ast_mutex_unlock(&monlock);
08473 pthread_attr_destroy(&attr);
08474 return 0;
08475 }
08476
08477 #ifdef HAVE_OPENR2
08478 static struct dahdi_mfcr2 *mfcr2_get_context(int id)
08479 {
08480 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08481 ast_log(LOG_ERROR, "No more R2 links available!.\n");
08482 return NULL;
08483 }
08484 return &r2links[id];
08485 }
08486 #endif
08487
08488 #ifdef HAVE_PRI
08489 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08490 {
08491 int x;
08492 int trunkgroup;
08493
08494 trunkgroup = pris[*span].mastertrunkgroup;
08495 if (trunkgroup) {
08496
08497 for (x = 0; x < NUM_SPANS; x++) {
08498 if (pris[x].trunkgroup == trunkgroup) {
08499 *span = x;
08500 return 0;
08501 }
08502 }
08503 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08504 *span = -1;
08505 } else {
08506 if (pris[*span].trunkgroup) {
08507 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08508 *span = -1;
08509 } else if (pris[*span].mastertrunkgroup) {
08510 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08511 *span = -1;
08512 } else {
08513 if (si->totalchans == 31) {
08514
08515 pris[*span].dchannels[0] = 16 + offset;
08516 } else if (si->totalchans == 24) {
08517
08518 pris[*span].dchannels[0] = 24 + offset;
08519 } else if (si->totalchans == 3) {
08520
08521 pris[*span].dchannels[0] = 3 + offset;
08522 } else {
08523 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);
08524 *span = -1;
08525 return 0;
08526 }
08527 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08528 pris[*span].offset = offset;
08529 pris[*span].span = *span + 1;
08530 }
08531 }
08532 return 0;
08533 }
08534
08535 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08536 {
08537 struct dahdi_spaninfo si;
08538 struct dahdi_params p;
08539 int fd;
08540 int span;
08541 int ospan=0;
08542 int x,y;
08543 for (x = 0; x < NUM_SPANS; x++) {
08544 if (pris[x].trunkgroup == trunkgroup) {
08545 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08546 return -1;
08547 }
08548 }
08549 for (y = 0; y < NUM_DCHANS; y++) {
08550 if (!channels[y])
08551 break;
08552 memset(&si, 0, sizeof(si));
08553 memset(&p, 0, sizeof(p));
08554 fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
08555 if (fd < 0) {
08556 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08557 return -1;
08558 }
08559 x = channels[y];
08560 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08561 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08562 close(fd);
08563 return -1;
08564 }
08565 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08566 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08567 return -1;
08568 }
08569 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08570 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08571 close(fd);
08572 return -1;
08573 }
08574 span = p.spanno - 1;
08575 if (pris[span].trunkgroup) {
08576 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08577 close(fd);
08578 return -1;
08579 }
08580 if (pris[span].pvts[0]) {
08581 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08582 close(fd);
08583 return -1;
08584 }
08585 if (!y) {
08586 pris[span].trunkgroup = trunkgroup;
08587 pris[span].offset = channels[y] - p.chanpos;
08588 ospan = span;
08589 }
08590 pris[ospan].dchannels[y] = channels[y];
08591 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08592 pris[span].span = span + 1;
08593 close(fd);
08594 }
08595 return 0;
08596 }
08597
08598 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08599 {
08600 if (pris[span].mastertrunkgroup) {
08601 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);
08602 return -1;
08603 }
08604 pris[span].mastertrunkgroup = trunkgroup;
08605 pris[span].prilogicalspan = logicalspan;
08606 return 0;
08607 }
08608
08609 #endif
08610
08611 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08612 {
08613
08614 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08615 char fn[80];
08616 #if 1
08617 struct dahdi_bufferinfo bi;
08618 #endif
08619 int res;
08620 int span=0;
08621 int here = 0;
08622 int x;
08623 struct dahdi_pvt **wlist;
08624 struct dahdi_pvt **wend;
08625 struct dahdi_params p;
08626
08627 wlist = &iflist;
08628 wend = &ifend;
08629
08630 #ifdef HAVE_PRI
08631 if (pri) {
08632 wlist = &pri->crvs;
08633 wend = &pri->crvend;
08634 }
08635 #endif
08636
08637 tmp2 = *wlist;
08638 prev = NULL;
08639
08640 while (tmp2) {
08641 if (!tmp2->destroy) {
08642 if (tmp2->channel == channel) {
08643 tmp = tmp2;
08644 here = 1;
08645 break;
08646 }
08647 if (tmp2->channel > channel) {
08648 break;
08649 }
08650 }
08651 prev = tmp2;
08652 tmp2 = tmp2->next;
08653 }
08654
08655 if (!here && reloading != 1) {
08656 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08657 if (tmp)
08658 free(tmp);
08659 return NULL;
08660 }
08661 ast_mutex_init(&tmp->lock);
08662 ifcount++;
08663 for (x = 0; x < 3; x++)
08664 tmp->subs[x].dfd = -1;
08665 tmp->channel = channel;
08666 tmp->priindication_oob = conf->chan.priindication_oob;
08667 }
08668
08669 if (tmp) {
08670 int chan_sig = conf->chan.sig;
08671 if (!here) {
08672 if ((channel != CHAN_PSEUDO) && !pri) {
08673 int count = 0;
08674 snprintf(fn, sizeof(fn), "%d", channel);
08675
08676 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08677 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08678 usleep(1);
08679 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08680 count++;
08681 }
08682
08683 if (tmp->subs[SUB_REAL].dfd < 0) {
08684 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);
08685 destroy_dahdi_pvt(&tmp);
08686 return NULL;
08687 }
08688 memset(&p, 0, sizeof(p));
08689 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08690 if (res < 0) {
08691 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08692 destroy_dahdi_pvt(&tmp);
08693 return NULL;
08694 }
08695 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
08696 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));
08697 destroy_dahdi_pvt(&tmp);
08698 return NULL;
08699 }
08700 tmp->law = p.curlaw;
08701 tmp->span = p.spanno;
08702 span = p.spanno - 1;
08703 } else {
08704 if (channel == CHAN_PSEUDO)
08705 chan_sig = 0;
08706 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08707 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08708 return NULL;
08709 }
08710 }
08711 #ifdef HAVE_PRI
08712 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08713 int offset;
08714 int myswitchtype;
08715 int matchesdchan;
08716 int x,y;
08717 offset = 0;
08718 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08719 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08720 destroy_dahdi_pvt(&tmp);
08721 return NULL;
08722 }
08723 if (span >= NUM_SPANS) {
08724 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08725 destroy_dahdi_pvt(&tmp);
08726 return NULL;
08727 } else {
08728 struct dahdi_spaninfo si;
08729 si.spanno = 0;
08730 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08731 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08732 destroy_dahdi_pvt(&tmp);
08733 return NULL;
08734 }
08735
08736 tmp->logicalspan = pris[span].prilogicalspan;
08737 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08738 if (span < 0) {
08739 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08740 destroy_dahdi_pvt(&tmp);
08741 return NULL;
08742 }
08743 if (chan_sig == SIG_PRI)
08744 myswitchtype = conf->pri.switchtype;
08745 else
08746 myswitchtype = PRI_SWITCH_GR303_TMC;
08747
08748 matchesdchan=0;
08749 for (x = 0; x < NUM_SPANS; x++) {
08750 for (y = 0; y < NUM_DCHANS; y++) {
08751 if (pris[x].dchannels[y] == tmp->channel) {
08752 matchesdchan = 1;
08753 break;
08754 }
08755 }
08756 }
08757 offset = p.chanpos;
08758 if (!matchesdchan) {
08759 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08760 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08761 destroy_dahdi_pvt(&tmp);
08762 return NULL;
08763 }
08764 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08765 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08766 destroy_dahdi_pvt(&tmp);
08767 return NULL;
08768 }
08769 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08770 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08771 destroy_dahdi_pvt(&tmp);
08772 return NULL;
08773 }
08774 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08775 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08776 destroy_dahdi_pvt(&tmp);
08777 return NULL;
08778 }
08779 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08780 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08781 destroy_dahdi_pvt(&tmp);
08782 return NULL;
08783 }
08784 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08785 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08786 destroy_dahdi_pvt(&tmp);
08787 return NULL;
08788 }
08789 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08790 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08791 destroy_dahdi_pvt(&tmp);
08792 return NULL;
08793 }
08794 if (pris[span].numchans >= MAX_CHANNELS) {
08795 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08796 pris[span].trunkgroup);
08797 destroy_dahdi_pvt(&tmp);
08798 return NULL;
08799 }
08800 pris[span].nodetype = conf->pri.nodetype;
08801 pris[span].switchtype = myswitchtype;
08802 pris[span].nsf = conf->pri.nsf;
08803 pris[span].dialplan = conf->pri.dialplan;
08804 pris[span].localdialplan = conf->pri.localdialplan;
08805 pris[span].pvts[pris[span].numchans++] = tmp;
08806 pris[span].minunused = conf->pri.minunused;
08807 pris[span].minidle = conf->pri.minidle;
08808 pris[span].overlapdial = conf->pri.overlapdial;
08809 #ifdef HAVE_PRI_INBANDDISCONNECT
08810 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08811 #endif
08812 pris[span].facilityenable = conf->pri.facilityenable;
08813 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08814 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08815 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08816 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08817 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08818 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08819 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08820 pris[span].resetinterval = conf->pri.resetinterval;
08821
08822 tmp->pri = &pris[span];
08823 tmp->prioffset = offset;
08824 tmp->call = NULL;
08825 } else {
08826 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08827 destroy_dahdi_pvt(&tmp);
08828 return NULL;
08829 }
08830 }
08831 } else {
08832 tmp->prioffset = 0;
08833 }
08834 #endif
08835 #ifdef HAVE_OPENR2
08836 if (chan_sig == SIG_MFCR2 && reloading != 1) {
08837 char logdir[OR2_MAX_PATH];
08838 struct dahdi_mfcr2 *dahdi_r2;
08839 int threshold = 0;
08840 int snres = 0;
08841 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
08842 if (!dahdi_r2) {
08843 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
08844 } else if (!dahdi_r2->protocol_context){
08845 char tmplogdir[] = "/tmp";
08846 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
08847 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
08848 if (!dahdi_r2->protocol_context) {
08849 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
08850 destroy_dahdi_pvt(&tmp);
08851 return NULL;
08852 }
08853 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
08854 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
08855 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
08856 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
08857 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
08858 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
08859 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
08860 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
08861 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
08862 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
08863 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
08864 #endif
08865 if (ast_strlen_zero(mfcr2_cur_logdir)) {
08866 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
08867 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08868 }
08869 } else {
08870 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
08871 if (snres >= sizeof(logdir)) {
08872 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
08873 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08874 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08875 }
08876 } else {
08877 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08878 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
08879 }
08880 }
08881 }
08882 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
08883 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
08884 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
08885 }
08886 }
08887 }
08888 if (dahdi_r2) {
08889
08890 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
08891 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
08892 tmp->subs[SUB_REAL].dfd, NULL, NULL);
08893 if (!tmp->r2chan) {
08894 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
08895 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
08896 destroy_dahdi_pvt(&tmp);
08897 return NULL;
08898 }
08899 openr2_chan_set_client_data(tmp->r2chan, tmp);
08900
08901 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
08902 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
08903 if (mfcr2_cur_call_files) {
08904 openr2_chan_enable_call_files(tmp->r2chan);
08905 }
08906 tmp->mfcr2_category = mfcr2_cur_category;
08907 tmp->mfcr2 = dahdi_r2;
08908 tmp->mfcr2call = 0;
08909 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
08910 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
08911 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
08912 tmp->mfcr2_ani_index = 0;
08913 tmp->mfcr2_dnis_index = 0;
08914 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
08915 tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
08916 }
08917 }
08918 #endif
08919 } else {
08920 chan_sig = tmp->sig;
08921 if (tmp->subs[SUB_REAL].dfd > -1) {
08922 memset(&p, 0, sizeof(p));
08923 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08924 }
08925 }
08926
08927 switch (chan_sig) {
08928 case SIG_FXSKS:
08929 case SIG_FXSLS:
08930 case SIG_EM:
08931 case SIG_EM_E1:
08932 case SIG_EMWINK:
08933 case SIG_FEATD:
08934 case SIG_FEATDMF:
08935 case SIG_FEATDMF_TA:
08936 case SIG_FEATB:
08937 case SIG_E911:
08938 case SIG_SF:
08939 case SIG_SFWINK:
08940 case SIG_FGC_CAMA:
08941 case SIG_FGC_CAMAMF:
08942 case SIG_SF_FEATD:
08943 case SIG_SF_FEATDMF:
08944 case SIG_SF_FEATB:
08945 p.starttime = 250;
08946 break;
08947 }
08948
08949 if (tmp->radio) {
08950
08951 p.channo = channel;
08952 p.rxwinktime = 1;
08953 p.rxflashtime = 1;
08954 p.starttime = 1;
08955 p.debouncetime = 5;
08956 }
08957 if (!tmp->radio) {
08958 p.channo = channel;
08959
08960 if (conf->timing.prewinktime >= 0)
08961 p.prewinktime = conf->timing.prewinktime;
08962 if (conf->timing.preflashtime >= 0)
08963 p.preflashtime = conf->timing.preflashtime;
08964 if (conf->timing.winktime >= 0)
08965 p.winktime = conf->timing.winktime;
08966 if (conf->timing.flashtime >= 0)
08967 p.flashtime = conf->timing.flashtime;
08968 if (conf->timing.starttime >= 0)
08969 p.starttime = conf->timing.starttime;
08970 if (conf->timing.rxwinktime >= 0)
08971 p.rxwinktime = conf->timing.rxwinktime;
08972 if (conf->timing.rxflashtime >= 0)
08973 p.rxflashtime = conf->timing.rxflashtime;
08974 if (conf->timing.debouncetime >= 0)
08975 p.debouncetime = conf->timing.debouncetime;
08976 }
08977
08978
08979 if (tmp->subs[SUB_REAL].dfd >= 0)
08980 {
08981 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
08982 if (res < 0) {
08983 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
08984 destroy_dahdi_pvt(&tmp);
08985 return NULL;
08986 }
08987 }
08988 #if 1
08989 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
08990 memset(&bi, 0, sizeof(bi));
08991 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08992 if (!res) {
08993 bi.txbufpolicy = conf->chan.buf_policy;
08994 bi.rxbufpolicy = conf->chan.buf_policy;
08995 bi.numbufs = conf->chan.buf_no;
08996 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08997 if (res < 0) {
08998 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
08999 }
09000 } else
09001 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09002 }
09003 #endif
09004 tmp->immediate = conf->chan.immediate;
09005 tmp->transfertobusy = conf->chan.transfertobusy;
09006 tmp->sig = chan_sig;
09007 tmp->outsigmod = conf->chan.outsigmod;
09008 tmp->ringt_base = ringt_base;
09009 tmp->firstradio = 0;
09010 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09011 tmp->permcallwaiting = conf->chan.callwaiting;
09012 else
09013 tmp->permcallwaiting = 0;
09014
09015 tmp->destroy = 0;
09016 tmp->drings = drings;
09017 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
09018 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09019 tmp->threewaycalling = conf->chan.threewaycalling;
09020 tmp->adsi = conf->chan.adsi;
09021 tmp->use_smdi = conf->chan.use_smdi;
09022 tmp->permhidecallerid = conf->chan.hidecallerid;
09023 tmp->callreturn = conf->chan.callreturn;
09024 tmp->echocancel = conf->chan.echocancel;
09025 tmp->echotraining = conf->chan.echotraining;
09026 tmp->pulse = conf->chan.pulse;
09027 if (tmp->echocancel)
09028 tmp->echocanbridged = conf->chan.echocanbridged;
09029 else {
09030 if (conf->chan.echocanbridged)
09031 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09032 tmp->echocanbridged = 0;
09033 }
09034 tmp->busydetect = conf->chan.busydetect;
09035 tmp->busycount = conf->chan.busycount;
09036 tmp->busycompare = conf->chan.busycompare;
09037 tmp->busytonelength = conf->chan.busytonelength;
09038 tmp->busyquietlength = conf->chan.busyquietlength;
09039 tmp->busyfuzziness = conf->chan.busyfuzziness;
09040 tmp->silencethreshold = conf->chan.silencethreshold;
09041 tmp->callprogress = conf->chan.callprogress;
09042 tmp->cancallforward = conf->chan.cancallforward;
09043 tmp->dtmfrelax = conf->chan.dtmfrelax;
09044 tmp->callwaiting = tmp->permcallwaiting;
09045 tmp->hidecallerid = tmp->permhidecallerid;
09046 tmp->channel = channel;
09047 tmp->stripmsd = conf->chan.stripmsd;
09048 tmp->use_callerid = conf->chan.use_callerid;
09049 tmp->cid_signalling = conf->chan.cid_signalling;
09050 tmp->cid_start = conf->chan.cid_start;
09051 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09052 tmp->restrictcid = conf->chan.restrictcid;
09053 tmp->use_callingpres = conf->chan.use_callingpres;
09054 tmp->priexclusive = conf->chan.priexclusive;
09055 if (tmp->usedistinctiveringdetection) {
09056 if (!tmp->use_callerid) {
09057 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09058 tmp->use_callerid = 1;
09059 }
09060 }
09061
09062 if (tmp->cid_signalling == CID_SIG_SMDI) {
09063 if (!tmp->use_smdi) {
09064 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09065 tmp->use_smdi = 1;
09066 }
09067 }
09068 if (tmp->use_smdi) {
09069 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09070 if (!(tmp->smdi_iface)) {
09071 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09072 tmp->use_smdi = 0;
09073 }
09074 }
09075
09076 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09077 tmp->amaflags = conf->chan.amaflags;
09078 if (!here) {
09079 tmp->confno = -1;
09080 tmp->propconfno = -1;
09081 }
09082 tmp->canpark = conf->chan.canpark;
09083 tmp->transfer = conf->chan.transfer;
09084 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09085 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09086 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09087 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09088 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09089 tmp->cid_ton = 0;
09090 if (chan_sig != SIG_PRI) {
09091 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09092 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09093 } else {
09094 tmp->cid_num[0] = '\0';
09095 tmp->cid_name[0] = '\0';
09096 }
09097 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09098 tmp->msgstate = -1;
09099 tmp->group = conf->chan.group;
09100 tmp->callgroup = conf->chan.callgroup;
09101 tmp->pickupgroup= conf->chan.pickupgroup;
09102 tmp->rxgain = conf->chan.rxgain;
09103 tmp->txgain = conf->chan.txgain;
09104 tmp->tonezone = conf->chan.tonezone;
09105 tmp->onhooktime = time(NULL);
09106 if (tmp->subs[SUB_REAL].dfd > -1) {
09107 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09108 if (tmp->dsp)
09109 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09110 update_conf(tmp);
09111 if (!here) {
09112 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09113
09114 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09115 }
09116 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09117 #ifdef HAVE_PRI
09118
09119 if (tmp->pri && !pri_is_up(tmp->pri)) {
09120 tmp->inalarm = 1;
09121 }
09122 #endif
09123 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09124 tmp->inalarm = 1;
09125 handle_alarms(tmp, res);
09126 } else {
09127
09128
09129
09130
09131
09132
09133
09134
09135
09136
09137 tmp->unknown_alarm = 1;
09138 }
09139 }
09140
09141 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09142 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09143 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09144 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09145
09146 }
09147 if (tmp && !here) {
09148
09149 if (!*wlist) {
09150 *wlist = tmp;
09151 tmp->prev = NULL;
09152 tmp->next = NULL;
09153 *wend = tmp;
09154 } else {
09155
09156 struct dahdi_pvt *working = *wlist;
09157
09158
09159 if (working->channel > tmp->channel) {
09160 tmp->next = *wlist;
09161 tmp->prev = NULL;
09162 (*wlist)->prev = tmp;
09163 *wlist = tmp;
09164 } else {
09165
09166 while (working) {
09167
09168 if (working->next) {
09169 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09170 tmp->next = working->next;
09171 tmp->prev = working;
09172 working->next->prev = tmp;
09173 working->next = tmp;
09174 break;
09175 }
09176 } else {
09177
09178 if (working->channel < tmp->channel) {
09179 working->next = tmp;
09180 tmp->next = NULL;
09181 tmp->prev = working;
09182 *wend = tmp;
09183 break;
09184 }
09185 }
09186 working = working->next;
09187 }
09188 }
09189 }
09190 }
09191 return tmp;
09192 }
09193
09194 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09195 {
09196 int res;
09197 struct dahdi_params par;
09198
09199
09200 if (groupmatch) {
09201 if ((p->group & groupmatch) != groupmatch)
09202 return 0;
09203 *groupmatched = 1;
09204 }
09205
09206 if (channelmatch != -1) {
09207 if (p->channel != channelmatch)
09208 return 0;
09209 *channelmatched = 1;
09210 }
09211
09212 if (busy) {
09213 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09214 *busy = 1;
09215 }
09216
09217 if (p->dnd)
09218 return 0;
09219
09220 if (p->guardtime && (time(NULL) < p->guardtime))
09221 return 0;
09222
09223
09224 if (!p->owner) {
09225 #ifdef HAVE_PRI
09226
09227 if (p->pri) {
09228 if (p->resetting || p->call)
09229 return 0;
09230 else
09231 return 1;
09232 }
09233 #endif
09234 #ifdef HAVE_OPENR2
09235
09236 if (p->mfcr2) {
09237 if (p->mfcr2call || p->mfcr2block)
09238 return 0;
09239 else
09240 return 1;
09241 }
09242 #endif
09243 if (!(p->radio || (p->oprmode < 0)))
09244 {
09245 if (!p->sig || (p->sig == SIG_FXSLS))
09246 return 1;
09247
09248 if (p->subs[SUB_REAL].dfd > -1) {
09249 memset(&par, 0, sizeof(par));
09250 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09251 } else {
09252
09253 res = 0;
09254 par.rxisoffhook = 0;
09255 }
09256 if (res) {
09257 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09258 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09259
09260
09261
09262 if (par.rxbits > -1)
09263 return 1;
09264 if (par.rxisoffhook)
09265 return 1;
09266 else
09267 #ifdef DAHDI_CHECK_HOOKSTATE
09268 return 0;
09269 #else
09270 return 1;
09271 #endif
09272 } else if (par.rxisoffhook) {
09273 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09274
09275 return 0;
09276 }
09277 }
09278 return 1;
09279 }
09280
09281
09282 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09283 return 0;
09284
09285 if (!p->callwaiting) {
09286
09287 return 0;
09288 }
09289
09290 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09291
09292 return 0;
09293 }
09294
09295 if ((p->owner->_state != AST_STATE_UP) &&
09296 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09297
09298 return 0;
09299 }
09300 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09301
09302 return 0;
09303 }
09304
09305 return 1;
09306 }
09307
09308 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09309 {
09310 struct dahdi_pvt *p;
09311 struct dahdi_bufferinfo bi;
09312 int res;
09313
09314 if ((p = ast_malloc(sizeof(*p)))) {
09315 memcpy(p, src, sizeof(struct dahdi_pvt));
09316 ast_mutex_init(&p->lock);
09317 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09318
09319 if (p->subs[SUB_REAL].dfd < 0) {
09320 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09321 destroy_dahdi_pvt(&p);
09322 return NULL;
09323 }
09324 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09325 if (!res) {
09326 bi.txbufpolicy = p->buf_policy;
09327 bi.rxbufpolicy = p->buf_policy;
09328 bi.numbufs = p->buf_no;
09329 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09330 if (res < 0) {
09331 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09332 }
09333 } else
09334 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09335 }
09336 p->destroy = 1;
09337 p->next = iflist;
09338 p->prev = NULL;
09339 iflist = p;
09340 if (iflist->next)
09341 iflist->next->prev = p;
09342 return p;
09343 }
09344
09345
09346 #ifdef HAVE_PRI
09347 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09348 {
09349 int x;
09350 if (backwards)
09351 x = pri->numchans;
09352 else
09353 x = 0;
09354 for (;;) {
09355 if (backwards && (x < 0))
09356 break;
09357 if (!backwards && (x >= pri->numchans))
09358 break;
09359 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09360 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
09361 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09362 return x;
09363 }
09364 if (backwards)
09365 x--;
09366 else
09367 x++;
09368 }
09369 return -1;
09370 }
09371 #endif
09372
09373 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09374 {
09375 ast_group_t groupmatch = 0;
09376 int channelmatch = -1;
09377 int roundrobin = 0;
09378 int callwait = 0;
09379 int busy = 0;
09380 struct dahdi_pvt *p;
09381 struct ast_channel *tmp = NULL;
09382 char *dest=NULL;
09383 int x;
09384 char *s;
09385 char opt=0;
09386 int res=0, y=0;
09387 int backwards = 0;
09388 #ifdef HAVE_PRI
09389 int crv;
09390 int bearer = -1;
09391 int trunkgroup;
09392 struct dahdi_pri *pri=NULL;
09393 #endif
09394 struct dahdi_pvt *exit, *start, *end;
09395 ast_mutex_t *lock;
09396 int channelmatched = 0;
09397 int groupmatched = 0;
09398
09399
09400
09401
09402
09403
09404
09405
09406
09407
09408
09409
09410
09411
09412
09413
09414
09415
09416
09417 lock = &iflock;
09418 start = iflist;
09419 end = ifend;
09420 if (data) {
09421 dest = ast_strdupa((char *)data);
09422 } else {
09423 ast_log(LOG_WARNING, "Channel requested with no data\n");
09424 return NULL;
09425 }
09426 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09427
09428 char *stringp;
09429
09430 stringp = dest + 1;
09431 s = strsep(&stringp, "/");
09432 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09433 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09434 return NULL;
09435 }
09436 groupmatch = ((ast_group_t) 1 << x);
09437 if (toupper(dest[0]) == 'G') {
09438 if (dest[0] == 'G') {
09439 backwards = 1;
09440 p = ifend;
09441 } else
09442 p = iflist;
09443 } else {
09444 if (dest[0] == 'R') {
09445 backwards = 1;
09446 p = round_robin[x]?round_robin[x]->prev:ifend;
09447 if (!p)
09448 p = ifend;
09449 } else {
09450 p = round_robin[x]?round_robin[x]->next:iflist;
09451 if (!p)
09452 p = iflist;
09453 }
09454 roundrobin = 1;
09455 }
09456 } else {
09457 char *stringp;
09458
09459 stringp = dest;
09460 s = strsep(&stringp, "/");
09461 p = iflist;
09462 if (!strcasecmp(s, "pseudo")) {
09463
09464 x = CHAN_PSEUDO;
09465 channelmatch = x;
09466 }
09467 #ifdef HAVE_PRI
09468 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09469 if ((trunkgroup < 1) || (crv < 1)) {
09470 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09471 return NULL;
09472 }
09473 res--;
09474 for (x = 0; x < NUM_SPANS; x++) {
09475 if (pris[x].trunkgroup == trunkgroup) {
09476 pri = pris + x;
09477 lock = &pri->lock;
09478 start = pri->crvs;
09479 end = pri->crvend;
09480 break;
09481 }
09482 }
09483 if (!pri) {
09484 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09485 return NULL;
09486 }
09487 channelmatch = crv;
09488 p = pris[x].crvs;
09489 }
09490 #endif
09491 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09492 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09493 return NULL;
09494 } else {
09495 channelmatch = x;
09496 }
09497 }
09498
09499 ast_mutex_lock(lock);
09500 exit = p;
09501 while (p && !tmp) {
09502 if (roundrobin)
09503 round_robin[x] = p;
09504 #if 0
09505 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09506 #endif
09507
09508 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09509 if (option_debug)
09510 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
09511 if (p->inalarm)
09512 goto next;
09513
09514 callwait = (p->owner != NULL);
09515 #ifdef HAVE_PRI
09516 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09517 if (p->sig != SIG_FXSKS) {
09518
09519
09520 bearer = pri_find_empty_chan(pri, 0);
09521 if (bearer < 0) {
09522 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09523 p = NULL;
09524 break;
09525 }
09526 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09527 } else {
09528 if (alloc_sub(p, 0)) {
09529 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09530 p = NULL;
09531 break;
09532 } else
09533 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
09534 p->pri = pri;
09535 }
09536 }
09537 #endif
09538 #ifdef HAVE_OPENR2
09539 if (p->mfcr2) {
09540 ast_mutex_lock(&p->lock);
09541 if (p->mfcr2call) {
09542 ast_mutex_unlock(&p->lock);
09543 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
09544 goto next;
09545 }
09546 if (p->mfcr2block) {
09547 ast_mutex_unlock(&p->lock);
09548 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
09549 goto next;
09550 }
09551 p->mfcr2call = 1;
09552 ast_mutex_unlock(&p->lock);
09553 }
09554 #endif
09555 if (p->channel == CHAN_PSEUDO) {
09556 p = chandup(p);
09557 if (!p) {
09558 break;
09559 }
09560 }
09561 if (p->owner) {
09562 if (alloc_sub(p, SUB_CALLWAIT)) {
09563 p = NULL;
09564 break;
09565 }
09566 }
09567 p->outgoing = 1;
09568 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09569 if (!tmp) {
09570 p->outgoing = 0;
09571 }
09572 #ifdef HAVE_PRI
09573 if (p->bearer) {
09574
09575 p->bearer->owner = tmp;
09576 }
09577 #endif
09578
09579 if (res > 1) {
09580 if (opt == 'c') {
09581
09582 p->confirmanswer = 1;
09583 } else if (opt == 'r') {
09584
09585 if (res < 3)
09586 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09587 else
09588 p->distinctivering = y;
09589 } else if (opt == 'd') {
09590
09591 p->digital = 1;
09592 if (tmp)
09593 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09594 } else {
09595 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09596 }
09597 }
09598
09599 if (tmp && callwait)
09600 tmp->cdrflags |= AST_CDR_CALLWAIT;
09601 break;
09602 }
09603 next:
09604 if (backwards) {
09605 p = p->prev;
09606 if (!p)
09607 p = end;
09608 } else {
09609 p = p->next;
09610 if (!p)
09611 p = start;
09612 }
09613
09614 if (p == exit)
09615 break;
09616 }
09617 ast_mutex_unlock(lock);
09618 restart_monitor();
09619 if (callwait)
09620 *cause = AST_CAUSE_BUSY;
09621 else if (!tmp) {
09622 if (channelmatched) {
09623 if (busy)
09624 *cause = AST_CAUSE_BUSY;
09625 } else if (groupmatched) {
09626 *cause = AST_CAUSE_CONGESTION;
09627 }
09628 }
09629
09630 return tmp;
09631 }
09632
09633 #ifdef HAVE_OPENR2
09634 static void *mfcr2_monitor(void *data)
09635 {
09636 struct dahdi_pvt *p;
09637 struct dahdi_mfcr2 *mfcr2 = data;
09638
09639
09640
09641
09642
09643 struct pollfd pollers[mfcr2->numchans];
09644 int maxsleep = 20;
09645 int res = 0;
09646 int i = 0;
09647 int pollsize = 0;
09648 int oldstate = 0;
09649 int was_idle = 0;
09650 int quit_loop = 0;
09651
09652
09653 for (i = 0; i < mfcr2->numchans; i++) {
09654 p = mfcr2->pvts[i];
09655 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
09656 if (openr2_chan_set_idle(p->r2chan)) {
09657 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
09658 } else {
09659 ast_mutex_lock(&p->lock);
09660 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
09661 mfcr2->pvts[i]->mfcr2call = 0;
09662 ast_mutex_unlock(&p->lock);
09663 }
09664 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
09665 }
09666 while(1) {
09667
09668
09669 pollsize = 0;
09670 for (i = 0; i < mfcr2->numchans; i++) {
09671 pollers[i].events = 0;
09672 pollers[i].revents = 0;
09673 if (mfcr2->pvts[i]->owner) {
09674 continue;
09675 }
09676 if (!mfcr2->pvts[i]->r2chan) {
09677 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
09678 quit_loop = 1;
09679 break;
09680 }
09681 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
09682 pollers[i].events = POLLIN | POLLPRI;
09683 pollsize++;
09684 }
09685 if (quit_loop) {
09686 break;
09687 }
09688
09689 if (pollsize == 0) {
09690 if (!was_idle) {
09691 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
09692 was_idle = 1;
09693 }
09694 poll(NULL, 0, maxsleep);
09695 continue;
09696 }
09697 was_idle = 0;
09698
09699
09700
09701 pthread_testcancel();
09702 res = poll(pollers, mfcr2->numchans, maxsleep);
09703 pthread_testcancel();
09704 if ((res < 0) && (errno != EINTR)) {
09705 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
09706 break;
09707 }
09708
09709 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
09710 for (i = 0; i < mfcr2->numchans; i++) {
09711 if ((pollers[i].revents & POLLPRI) || (pollers[i].revents & POLLIN)) {
09712 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
09713 }
09714 }
09715 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
09716 }
09717 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
09718 return 0;
09719 }
09720 #endif
09721
09722
09723 #ifdef HAVE_PRI
09724 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
09725 {
09726 struct dahdi_pvt *p;
09727 p = pri->crvs;
09728 while (p) {
09729 if (p->channel == crv)
09730 return p;
09731 p = p->next;
09732 }
09733 return NULL;
09734 }
09735
09736
09737 static int pri_find_principle(struct dahdi_pri *pri, int channel)
09738 {
09739 int x;
09740 int span = PRI_SPAN(channel);
09741 int spanfd;
09742 struct dahdi_params param;
09743 int principle = -1;
09744 int explicit = PRI_EXPLICIT(channel);
09745 channel = PRI_CHANNEL(channel);
09746
09747 if (!explicit) {
09748 spanfd = pri_active_dchan_fd(pri);
09749 memset(¶m, 0, sizeof(param));
09750 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
09751 return -1;
09752 span = pris[param.spanno - 1].prilogicalspan;
09753 }
09754
09755 for (x = 0; x < pri->numchans; x++) {
09756 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
09757 principle = x;
09758 break;
09759 }
09760 }
09761
09762 return principle;
09763 }
09764
09765 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
09766 {
09767 int x;
09768 struct dahdi_pvt *crv;
09769 if (!c) {
09770 if (principle < 0)
09771 return -1;
09772 return principle;
09773 }
09774 if ((principle > -1) &&
09775 (principle < pri->numchans) &&
09776 (pri->pvts[principle]) &&
09777 (pri->pvts[principle]->call == c))
09778 return principle;
09779
09780 for (x = 0; x < pri->numchans; x++) {
09781 if (!pri->pvts[x])
09782 continue;
09783 if (pri->pvts[x]->call == c) {
09784
09785 if (principle != x) {
09786 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
09787
09788 if (option_verbose > 2)
09789 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
09790 old->channel, new->channel);
09791 if (new->owner) {
09792 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
09793 old->channel, new->channel, new->channel);
09794 return -1;
09795 }
09796
09797 new->owner = old->owner;
09798 old->owner = NULL;
09799 if (new->owner) {
09800 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
09801 new->owner->tech_pvt = new;
09802 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
09803 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
09804 old->subs[SUB_REAL].owner = NULL;
09805 } else
09806 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);
09807 new->call = old->call;
09808 old->call = NULL;
09809
09810
09811 new->dsp = old->dsp;
09812 new->dsp_features = old->dsp_features;
09813 old->dsp = NULL;
09814 old->dsp_features = 0;
09815 }
09816 return principle;
09817 }
09818 }
09819
09820 crv = pri->crvs;
09821 while (crv) {
09822 if (crv->call == c) {
09823
09824 if (crv->bearer)
09825 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
09826 else if (pri->pvts[principle]->owner)
09827 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
09828 else {
09829
09830
09831 dahdi_close_sub(crv, SUB_REAL);
09832 pri->pvts[principle]->call = crv->call;
09833 pri_assign_bearer(crv, pri, pri->pvts[principle]);
09834 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
09835 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
09836 pri->trunkgroup, crv->channel);
09837 wakeup_sub(crv, SUB_REAL, pri);
09838 }
09839 return principle;
09840 }
09841 crv = crv->next;
09842 }
09843 ast_log(LOG_WARNING, "Call specified, but not found?\n");
09844 return -1;
09845 }
09846
09847 static void *do_idle_thread(void *vchan)
09848 {
09849 struct ast_channel *chan = vchan;
09850 struct dahdi_pvt *pvt = chan->tech_pvt;
09851 struct ast_frame *f;
09852 char ex[80];
09853
09854 int newms, ms = 30000;
09855 if (option_verbose > 2)
09856 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
09857 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
09858 if (ast_call(chan, ex, 0)) {
09859 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
09860 ast_hangup(chan);
09861 return NULL;
09862 }
09863 while ((newms = ast_waitfor(chan, ms)) > 0) {
09864 f = ast_read(chan);
09865 if (!f) {
09866
09867 break;
09868 }
09869 if (f->frametype == AST_FRAME_CONTROL) {
09870 switch (f->subclass) {
09871 case AST_CONTROL_ANSWER:
09872
09873 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
09874 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
09875 chan->priority = 1;
09876 if (option_verbose > 3)
09877 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
09878 ast_pbx_run(chan);
09879
09880 return NULL;
09881 case AST_CONTROL_BUSY:
09882 if (option_verbose > 3)
09883 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
09884 break;
09885 case AST_CONTROL_CONGESTION:
09886 if (option_verbose > 3)
09887 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
09888 break;
09889 };
09890 }
09891 ast_frfree(f);
09892 ms = newms;
09893 }
09894
09895 ast_hangup(chan);
09896 return NULL;
09897 }
09898
09899 #ifndef PRI_RESTART
09900 #error "Upgrade your libpri"
09901 #endif
09902 static void dahdi_pri_message(struct pri *pri, char *s)
09903 {
09904 int x, y;
09905 int dchan = -1, span = -1;
09906 int dchancount = 0;
09907
09908 if (pri) {
09909 for (x = 0; x < NUM_SPANS; x++) {
09910 for (y = 0; y < NUM_DCHANS; y++) {
09911 if (pris[x].dchans[y])
09912 dchancount++;
09913
09914 if (pris[x].dchans[y] == pri)
09915 dchan = y;
09916 }
09917 if (dchan >= 0) {
09918 span = x;
09919 break;
09920 }
09921 dchancount = 0;
09922 }
09923 if ((dchan >= 0) && (span >= 0)) {
09924 if (dchancount > 1)
09925 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
09926 else
09927 ast_verbose("%s", s);
09928 } else
09929 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09930 } else
09931 ast_verbose("%s", s);
09932
09933 ast_mutex_lock(&pridebugfdlock);
09934
09935 if (pridebugfd >= 0) {
09936 if (write(pridebugfd, s, strlen(s)) < 0) {
09937 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09938 }
09939 }
09940
09941 ast_mutex_unlock(&pridebugfdlock);
09942 }
09943
09944 static void dahdi_pri_error(struct pri *pri, char *s)
09945 {
09946 int x, y;
09947 int dchan = -1, span = -1;
09948 int dchancount = 0;
09949
09950 if (pri) {
09951 for (x = 0; x < NUM_SPANS; x++) {
09952 for (y = 0; y < NUM_DCHANS; y++) {
09953 if (pris[x].dchans[y])
09954 dchancount++;
09955
09956 if (pris[x].dchans[y] == pri)
09957 dchan = y;
09958 }
09959 if (dchan >= 0) {
09960 span = x;
09961 break;
09962 }
09963 dchancount = 0;
09964 }
09965 if ((dchan >= 0) && (span >= 0)) {
09966 if (dchancount > 1)
09967 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
09968 else
09969 ast_log(LOG_ERROR, "%s", s);
09970 } else
09971 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09972 } else
09973 ast_log(LOG_ERROR, "%s", s);
09974
09975 ast_mutex_lock(&pridebugfdlock);
09976
09977 if (pridebugfd >= 0) {
09978 if (write(pridebugfd, s, strlen(s)) < 0) {
09979 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09980 }
09981 }
09982
09983 ast_mutex_unlock(&pridebugfdlock);
09984 }
09985
09986 static int pri_check_restart(struct dahdi_pri *pri)
09987 {
09988 do {
09989 pri->resetpos++;
09990 } while ((pri->resetpos < pri->numchans) &&
09991 (!pri->pvts[pri->resetpos] ||
09992 pri->pvts[pri->resetpos]->call ||
09993 pri->pvts[pri->resetpos]->resetting));
09994 if (pri->resetpos < pri->numchans) {
09995
09996 pri->pvts[pri->resetpos]->resetting = 1;
09997 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
09998 } else {
09999 pri->resetting = 0;
10000 time(&pri->lastreset);
10001 }
10002 return 0;
10003 }
10004
10005 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10006 {
10007 int x;
10008 int redo;
10009 ast_mutex_unlock(&pri->lock);
10010 ast_mutex_lock(&p->lock);
10011 do {
10012 redo = 0;
10013 for (x = 0; x < 3; x++) {
10014 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
10015 redo++;
10016 DEADLOCK_AVOIDANCE(&p->lock);
10017 }
10018 if (p->subs[x].owner) {
10019 ast_queue_hangup(p->subs[x].owner);
10020 ast_mutex_unlock(&p->subs[x].owner->lock);
10021 }
10022 }
10023 } while (redo);
10024 ast_mutex_unlock(&p->lock);
10025 ast_mutex_lock(&pri->lock);
10026 return 0;
10027 }
10028
10029 static char * redirectingreason2str(int redirectingreason)
10030 {
10031 switch (redirectingreason) {
10032 case 0:
10033 return "UNKNOWN";
10034 case 1:
10035 return "BUSY";
10036 case 2:
10037 return "NO_REPLY";
10038 case 0xF:
10039 return "UNCONDITIONAL";
10040 default:
10041 return "NOREDIRECT";
10042 }
10043 }
10044
10045 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10046 {
10047 if (ast_strlen_zero(number)) {
10048 if (size) {
10049 *buf = '\0';
10050 }
10051 return;
10052 }
10053
10054 switch (plan) {
10055 case PRI_INTERNATIONAL_ISDN:
10056 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10057 break;
10058 case PRI_NATIONAL_ISDN:
10059 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10060 break;
10061 case PRI_LOCAL_ISDN:
10062 snprintf(buf, size, "%s%s", pri->localprefix, number);
10063 break;
10064 case PRI_PRIVATE:
10065 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10066 break;
10067 case PRI_UNKNOWN:
10068 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10069 break;
10070 default:
10071 snprintf(buf, size, "%s", number);
10072 break;
10073 }
10074 }
10075
10076 static int dahdi_setlaw(int dfd, int law)
10077 {
10078 int res;
10079 res = ioctl(dfd, DAHDI_SETLAW, &law);
10080 if (res)
10081 return res;
10082 return 0;
10083 }
10084
10085 static void *pri_dchannel(void *vpri)
10086 {
10087 struct dahdi_pri *pri = vpri;
10088 pri_event *e;
10089 struct pollfd fds[NUM_DCHANS];
10090 int res;
10091 int chanpos = 0;
10092 int x;
10093 int haveidles;
10094 int activeidles;
10095 int nextidle = -1;
10096 struct ast_channel *c;
10097 struct timeval tv, lowest, *next;
10098 struct timeval lastidle = { 0, 0 };
10099 int doidling=0;
10100 char *cc;
10101 char idlen[80];
10102 struct ast_channel *idle;
10103 pthread_t p;
10104 time_t t;
10105 int i, which=-1;
10106 int numdchans;
10107 int cause=0;
10108 struct dahdi_pvt *crv;
10109 pthread_t threadid;
10110 pthread_attr_t attr;
10111 char ani2str[6];
10112 char plancallingnum[256];
10113 char plancallingani[256];
10114 char calledtonstr[10];
10115
10116 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10117
10118 gettimeofday(&lastidle, NULL);
10119 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10120
10121 cc = strchr(pri->idleext, '@');
10122 if (cc) {
10123 *cc = '\0';
10124 cc++;
10125 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10126 #if 0
10127
10128 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10129 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10130 else
10131 #endif
10132 doidling = 1;
10133 } else
10134 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10135 }
10136 for (;;) {
10137 for (i = 0; i < NUM_DCHANS; i++) {
10138 if (!pri->dchannels[i])
10139 break;
10140 fds[i].fd = pri->fds[i];
10141 fds[i].events = POLLIN | POLLPRI;
10142 fds[i].revents = 0;
10143 }
10144 numdchans = i;
10145 time(&t);
10146 ast_mutex_lock(&pri->lock);
10147 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10148 if (pri->resetting && pri_is_up(pri)) {
10149 if (pri->resetpos < 0)
10150 pri_check_restart(pri);
10151 } else {
10152 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10153 pri->resetting = 1;
10154 pri->resetpos = -1;
10155 }
10156 }
10157 }
10158
10159 if (doidling && pri_is_up(pri)) {
10160 nextidle = -1;
10161 haveidles = 0;
10162 activeidles = 0;
10163 for (x = pri->numchans; x >= 0; x--) {
10164 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10165 !pri->pvts[x]->call) {
10166 if (haveidles < pri->minunused) {
10167 haveidles++;
10168 } else if (!pri->pvts[x]->resetting) {
10169 nextidle = x;
10170 break;
10171 }
10172 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10173 activeidles++;
10174 }
10175 if (nextidle > -1) {
10176 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10177
10178 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10179 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
10180 if (idle) {
10181 pri->pvts[nextidle]->isidlecall = 1;
10182 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10183 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10184 dahdi_hangup(idle);
10185 }
10186 } else
10187 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10188 gettimeofday(&lastidle, NULL);
10189 }
10190 } else if ((haveidles < pri->minunused) &&
10191 (activeidles > pri->minidle)) {
10192
10193
10194 for (x = pri->numchans; x >= 0; x--) {
10195
10196 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10197 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10198 haveidles++;
10199
10200
10201 if ((haveidles >= pri->minunused) ||
10202 (activeidles <= pri->minidle))
10203 break;
10204 }
10205 }
10206 }
10207 }
10208
10209 lowest = ast_tv(60, 0);
10210 for (i = 0; i < NUM_DCHANS; i++) {
10211
10212 if (!pri->dchannels[i])
10213 break;
10214 if ((next = pri_schedule_next(pri->dchans[i]))) {
10215
10216 tv = ast_tvsub(*next, ast_tvnow());
10217 if (tv.tv_sec < 0) {
10218 tv = ast_tv(0,0);
10219 }
10220 if (doidling || pri->resetting) {
10221 if (tv.tv_sec > 1) {
10222 tv = ast_tv(1, 0);
10223 }
10224 } else {
10225 if (tv.tv_sec > 60) {
10226 tv = ast_tv(60, 0);
10227 }
10228 }
10229 } else if (doidling || pri->resetting) {
10230
10231
10232 tv = ast_tv(1,0);
10233 } else {
10234
10235 tv = ast_tv(60, 0);
10236 }
10237 if (!i || ast_tvcmp(tv, lowest) < 0) {
10238 lowest = tv;
10239 }
10240 }
10241 ast_mutex_unlock(&pri->lock);
10242
10243 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10244 pthread_testcancel();
10245 e = NULL;
10246 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10247 pthread_testcancel();
10248 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10249
10250 ast_mutex_lock(&pri->lock);
10251 if (!res) {
10252 for (which = 0; which < NUM_DCHANS; which++) {
10253 if (!pri->dchans[which])
10254 break;
10255
10256 e = pri_schedule_run(pri->dchans[which]);
10257 if (e)
10258 break;
10259 }
10260 } else if (res > -1) {
10261 for (which = 0; which < NUM_DCHANS; which++) {
10262 if (!pri->dchans[which])
10263 break;
10264 if (fds[which].revents & POLLPRI) {
10265
10266 x = 0;
10267 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10268 if (x)
10269 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);
10270
10271 if (x == DAHDI_EVENT_ALARM) {
10272 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10273 pri_find_dchan(pri);
10274 } else if (x == DAHDI_EVENT_NOALARM) {
10275 pri->dchanavail[which] |= DCHAN_NOTINALARM;
10276 pri_restart(pri->dchans[which]);
10277 }
10278
10279 if (option_debug)
10280 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10281 } else if (fds[which].revents & POLLIN) {
10282 e = pri_check_event(pri->dchans[which]);
10283 }
10284 if (e)
10285 break;
10286 }
10287 } else if (errno != EINTR)
10288 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10289
10290 if (e) {
10291 if (pri->debug)
10292 pri_dump_event(pri->dchans[which], e);
10293
10294 if (e->e != PRI_EVENT_DCHAN_DOWN) {
10295 if (!(pri->dchanavail[which] & DCHAN_UP)) {
10296 if (option_verbose > 1)
10297 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10298 }
10299 pri->dchanavail[which] |= DCHAN_UP;
10300 } else {
10301 if (pri->dchanavail[which] & DCHAN_UP) {
10302 if (option_verbose > 1)
10303 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10304 }
10305 pri->dchanavail[which] &= ~DCHAN_UP;
10306 }
10307
10308 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10309
10310 pri->pri = pri->dchans[which];
10311
10312 switch (e->e) {
10313 case PRI_EVENT_DCHAN_UP:
10314 if (!pri->pri) pri_find_dchan(pri);
10315
10316
10317 time(&pri->lastreset);
10318
10319
10320 if (pri->resetinterval > -1) {
10321 pri->lastreset -= pri->resetinterval;
10322 pri->lastreset += 5;
10323 }
10324 pri->resetting = 0;
10325
10326 for (i = 0; i < pri->numchans; i++)
10327 if (pri->pvts[i]) {
10328 pri->pvts[i]->inalarm = 0;
10329 }
10330 break;
10331 case PRI_EVENT_DCHAN_DOWN:
10332 pri_find_dchan(pri);
10333 if (!pri_is_up(pri)) {
10334 pri->resetting = 0;
10335
10336 for (i = 0; i < pri->numchans; i++) {
10337 struct dahdi_pvt *p = pri->pvts[i];
10338 if (p) {
10339 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10340
10341 if (p->call) {
10342 if (p->pri && p->pri->pri) {
10343 pri_hangup(p->pri->pri, p->call, -1);
10344 pri_destroycall(p->pri->pri, p->call);
10345 p->call = NULL;
10346 } else
10347 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10348 }
10349 if (p->realcall) {
10350 pri_hangup_all(p->realcall, pri);
10351 } else if (p->owner)
10352 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10353 }
10354 p->inalarm = 1;
10355 }
10356 }
10357 }
10358 break;
10359 case PRI_EVENT_RESTART:
10360 if (e->restart.channel > -1) {
10361 chanpos = pri_find_principle(pri, e->restart.channel);
10362 if (chanpos < 0)
10363 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10364 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10365 else {
10366 if (option_verbose > 2)
10367 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
10368 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10369 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10370 if (pri->pvts[chanpos]->call) {
10371 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10372 pri->pvts[chanpos]->call = NULL;
10373 }
10374
10375 if (pri->pvts[chanpos]->realcall)
10376 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10377 else if (pri->pvts[chanpos]->owner)
10378 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10379 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10380 }
10381 } else {
10382 if (option_verbose > 2)
10383 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
10384 for (x = 0; x < pri->numchans; x++)
10385 if (pri->pvts[x]) {
10386 ast_mutex_lock(&pri->pvts[x]->lock);
10387 if (pri->pvts[x]->call) {
10388 pri_destroycall(pri->pri, pri->pvts[x]->call);
10389 pri->pvts[x]->call = NULL;
10390 }
10391 if (pri->pvts[x]->realcall)
10392 pri_hangup_all(pri->pvts[x]->realcall, pri);
10393 else if (pri->pvts[x]->owner)
10394 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10395 ast_mutex_unlock(&pri->pvts[x]->lock);
10396 }
10397 }
10398 break;
10399 case PRI_EVENT_KEYPAD_DIGIT:
10400 chanpos = pri_find_principle(pri, e->digit.channel);
10401 if (chanpos < 0) {
10402 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10403 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10404 } else {
10405 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10406 if (chanpos > -1) {
10407 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10408
10409 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
10410
10411 int digitlen = strlen(e->digit.digits);
10412 char digit;
10413 int i;
10414 for (i = 0; i < digitlen; i++) {
10415 digit = e->digit.digits[i];
10416 {
10417 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10418 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10419 }
10420 }
10421 }
10422 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10423 }
10424 }
10425 break;
10426
10427 case PRI_EVENT_INFO_RECEIVED:
10428 chanpos = pri_find_principle(pri, e->ring.channel);
10429 if (chanpos < 0) {
10430 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
10431 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10432 } else {
10433 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
10434 if (chanpos > -1) {
10435 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10436
10437 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
10438
10439 int digitlen = strlen(e->ring.callednum);
10440 char digit;
10441 int i;
10442 for (i = 0; i < digitlen; i++) {
10443 digit = e->ring.callednum[i];
10444 {
10445 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10446 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10447 }
10448 }
10449 }
10450 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10451 }
10452 }
10453 break;
10454 case PRI_EVENT_RING:
10455 crv = NULL;
10456 if (e->ring.channel == -1)
10457 chanpos = pri_find_empty_chan(pri, 1);
10458 else
10459 chanpos = pri_find_principle(pri, e->ring.channel);
10460
10461 if (chanpos < 0) {
10462 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
10463 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10464 } else {
10465 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10466 if (pri->pvts[chanpos]->owner) {
10467 if (pri->pvts[chanpos]->call == e->ring.call) {
10468 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
10469 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10470 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10471 break;
10472 } else {
10473
10474 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
10475 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10476 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10477 chanpos = -1;
10478 }
10479 }
10480 if (chanpos > -1)
10481 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10482 }
10483 if ((chanpos < 0) && (e->ring.flexible))
10484 chanpos = pri_find_empty_chan(pri, 1);
10485 if (chanpos > -1) {
10486 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10487 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
10488
10489 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
10490 if (crv)
10491 ast_mutex_lock(&crv->lock);
10492 if (!crv || crv->owner) {
10493 pri->pvts[chanpos]->call = NULL;
10494 if (crv) {
10495 if (crv->owner)
10496 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10497 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);
10498 } else
10499 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);
10500 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
10501 if (crv)
10502 ast_mutex_unlock(&crv->lock);
10503 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10504 break;
10505 }
10506 }
10507 pri->pvts[chanpos]->call = e->ring.call;
10508 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
10509 if (pri->pvts[chanpos]->use_callerid) {
10510 ast_shrink_phone_number(plancallingnum);
10511 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
10512 #ifdef PRI_ANI
10513 if (!ast_strlen_zero(e->ring.callingani)) {
10514 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
10515 ast_shrink_phone_number(plancallingani);
10516 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
10517 } else {
10518 pri->pvts[chanpos]->cid_ani[0] = '\0';
10519 }
10520 #endif
10521 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
10522 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
10523 } else {
10524 pri->pvts[chanpos]->cid_num[0] = '\0';
10525 pri->pvts[chanpos]->cid_ani[0] = '\0';
10526 pri->pvts[chanpos]->cid_name[0] = '\0';
10527 pri->pvts[chanpos]->cid_ton = 0;
10528 }
10529 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
10530 e->ring.redirectingnum, e->ring.callingplanrdnis);
10531
10532 if (pri->pvts[chanpos]->immediate) {
10533 if (option_verbose > 2)
10534 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
10535 pri->pvts[chanpos]->exten[0] = 's';
10536 pri->pvts[chanpos]->exten[1] = '\0';
10537 }
10538
10539 else if (!ast_strlen_zero(e->ring.callednum)) {
10540 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
10541 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10542 } else if (pri->overlapdial)
10543 pri->pvts[chanpos]->exten[0] = '\0';
10544 else {
10545
10546 pri->pvts[chanpos]->exten[0] = 's';
10547 pri->pvts[chanpos]->exten[1] = '\0';
10548 }
10549
10550 if (!ast_strlen_zero(e->ring.callednum))
10551 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10552
10553 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
10554 if (option_verbose > 2)
10555 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
10556 pri->pvts[chanpos]->exten[0] = 's';
10557 pri->pvts[chanpos]->exten[1] = '\0';
10558 }
10559
10560
10561 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
10562 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10563
10564 int law;
10565 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
10566
10567 law = 1;
10568 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
10569 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
10570 }
10571 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
10572 law = DAHDI_LAW_ALAW;
10573 else
10574 law = DAHDI_LAW_MULAW;
10575 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
10576 if (res < 0)
10577 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
10578 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10579 if (res < 0)
10580 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
10581 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
10582
10583 pri->pvts[chanpos]->proceeding = 1;
10584 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
10585 } else {
10586 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
10587 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10588 else
10589 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10590 }
10591
10592 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
10593
10594
10595 if (!e->ring.complete
10596 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
10597 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10598
10599
10600
10601
10602 ast_mutex_unlock(&pri->lock);
10603 if (crv) {
10604
10605 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
10606 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10607 pri->pvts[chanpos]->owner = &inuse;
10608 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
10609 } else {
10610 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10611 }
10612 ast_mutex_lock(&pri->lock);
10613 if (c) {
10614 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10615 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10616 }
10617 if (e->ring.ani2 >= 0) {
10618 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10619 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10620 }
10621
10622 #ifdef SUPPORT_USERUSER
10623 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10624 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10625 }
10626 #endif
10627
10628 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10629 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10630 if (e->ring.redirectingreason >= 0)
10631 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10632 }
10633
10634 pthread_attr_init(&attr);
10635 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10636 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
10637 if (option_verbose > 2)
10638 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10639 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
10640 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10641 } else {
10642 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10643 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10644 if (c)
10645 ast_hangup(c);
10646 else {
10647 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10648 pri->pvts[chanpos]->call = NULL;
10649 }
10650 }
10651 pthread_attr_destroy(&attr);
10652 } else {
10653
10654
10655
10656
10657 ast_mutex_unlock(&pri->lock);
10658 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
10659 ast_mutex_lock(&pri->lock);
10660 if (c) {
10661
10662
10663
10664
10665
10666
10667
10668
10669 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10670 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10671 }
10672 if (e->ring.ani2 >= 0) {
10673 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10674 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10675 }
10676
10677 #ifdef SUPPORT_USERUSER
10678 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10679 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10680 }
10681 #endif
10682
10683 if (e->ring.redirectingreason >= 0)
10684 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10685
10686 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10687 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10688 }
10689 if (c && !ast_pbx_start(c)) {
10690 if (option_verbose > 2)
10691 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10692 plancallingnum, pri->pvts[chanpos]->exten,
10693 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10694
10695 dahdi_enable_ec(pri->pvts[chanpos]);
10696 } else {
10697 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10698 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10699 if (c) {
10700 ast_hangup(c);
10701 } else {
10702 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10703 pri->pvts[chanpos]->call = NULL;
10704 }
10705 }
10706 }
10707 } else {
10708 if (option_verbose > 2)
10709 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
10710 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
10711 pri->pvts[chanpos]->prioffset, pri->span);
10712 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
10713 pri->pvts[chanpos]->call = NULL;
10714 pri->pvts[chanpos]->exten[0] = '\0';
10715 }
10716 if (crv)
10717 ast_mutex_unlock(&crv->lock);
10718 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10719 } else {
10720 if (e->ring.flexible)
10721 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
10722 else
10723 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
10724 }
10725 break;
10726 case PRI_EVENT_RINGING:
10727 chanpos = pri_find_principle(pri, e->ringing.channel);
10728 if (chanpos < 0) {
10729 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
10730 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10731 } else {
10732 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
10733 if (chanpos < 0) {
10734 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
10735 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10736 } else {
10737 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10738 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10739 dahdi_enable_ec(pri->pvts[chanpos]);
10740 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
10741 pri->pvts[chanpos]->alerting = 1;
10742 } else
10743 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
10744 #ifdef PRI_PROGRESS_MASK
10745 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10746 #else
10747 if (e->ringing.progress == 8) {
10748 #endif
10749
10750 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10751
10752 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
10753 pri->pvts[chanpos]->dsp_features = 0;
10754 }
10755 }
10756
10757 #ifdef SUPPORT_USERUSER
10758 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
10759 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10760 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10761 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
10762 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10763 }
10764 #endif
10765
10766 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10767 }
10768 }
10769 break;
10770 case PRI_EVENT_PROGRESS:
10771
10772 chanpos = pri_find_principle(pri, e->proceeding.channel);
10773 if (chanpos > -1) {
10774 #ifdef PRI_PROGRESS_MASK
10775 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
10776 #else
10777 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
10778 #endif
10779 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10780
10781 if (e->proceeding.cause > -1) {
10782 if (option_verbose > 2)
10783 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
10784
10785
10786 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
10787 if (pri->pvts[chanpos]->owner) {
10788 if (option_verbose > 2)
10789 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
10790
10791 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
10792 f.subclass = AST_CONTROL_BUSY;
10793 }
10794 }
10795 }
10796
10797 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10798 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
10799 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10800 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10801 #ifdef PRI_PROGRESS_MASK
10802 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10803 #else
10804 if (e->proceeding.progress == 8) {
10805 #endif
10806
10807 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10808 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10809 pri->pvts[chanpos]->dsp_features = 0;
10810 }
10811
10812 f.subclass = AST_CONTROL_PROGRESS;
10813 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10814 }
10815 pri->pvts[chanpos]->progress = 1;
10816 pri->pvts[chanpos]->dialing = 0;
10817 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10818 }
10819 }
10820 break;
10821 case PRI_EVENT_PROCEEDING:
10822 chanpos = pri_find_principle(pri, e->proceeding.channel);
10823 if (chanpos > -1) {
10824 if (!pri->pvts[chanpos]->proceeding) {
10825 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10826
10827 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10828 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
10829 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10830 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10831 #ifdef PRI_PROGRESS_MASK
10832 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10833 #else
10834 if (e->proceeding.progress == 8) {
10835 #endif
10836
10837 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10838 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10839 pri->pvts[chanpos]->dsp_features = 0;
10840 }
10841
10842 f.subclass = AST_CONTROL_PROGRESS;
10843 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10844 }
10845 pri->pvts[chanpos]->proceeding = 1;
10846 pri->pvts[chanpos]->dialing = 0;
10847 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10848 }
10849 }
10850 break;
10851 case PRI_EVENT_FACNAME:
10852 chanpos = pri_find_principle(pri, e->facname.channel);
10853 if (chanpos < 0) {
10854 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
10855 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10856 } else {
10857 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
10858 if (chanpos < 0) {
10859 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
10860 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10861 } else {
10862
10863 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10864 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
10865 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
10866 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
10867 dahdi_enable_ec(pri->pvts[chanpos]);
10868 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10869 }
10870 }
10871 break;
10872 case PRI_EVENT_ANSWER:
10873 chanpos = pri_find_principle(pri, e->answer.channel);
10874 if (chanpos < 0) {
10875 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
10876 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10877 } else {
10878 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
10879 if (chanpos < 0) {
10880 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
10881 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10882 } else {
10883 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10884
10885
10886
10887
10888
10889 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10890 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10891 pri->pvts[chanpos]->dsp_features = 0;
10892 }
10893 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
10894 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
10895 x = DAHDI_START;
10896 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10897 if (res < 0) {
10898 if (errno != EINPROGRESS) {
10899 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
10900 }
10901 }
10902 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10903 pri->pvts[chanpos]->dialing = 1;
10904
10905 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
10906 if (res < 0) {
10907 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
10908 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10909 } else
10910 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
10911 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10912 } else if (pri->pvts[chanpos]->confirmanswer) {
10913 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
10914 } else {
10915 pri->pvts[chanpos]->dialing = 0;
10916 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
10917
10918 dahdi_enable_ec(pri->pvts[chanpos]);
10919 }
10920
10921 #ifdef SUPPORT_USERUSER
10922 if (!ast_strlen_zero(e->answer.useruserinfo)) {
10923 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10924 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10925 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
10926 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10927 }
10928 #endif
10929
10930 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10931 }
10932 }
10933 break;
10934 case PRI_EVENT_HANGUP:
10935 chanpos = pri_find_principle(pri, e->hangup.channel);
10936 if (chanpos < 0) {
10937 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
10938 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10939 } else {
10940 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10941 if (chanpos > -1) {
10942 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10943 if (!pri->pvts[chanpos]->alreadyhungup) {
10944
10945 pri->pvts[chanpos]->alreadyhungup = 1;
10946 if (pri->pvts[chanpos]->realcall)
10947 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10948 else if (pri->pvts[chanpos]->owner) {
10949
10950 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10951 switch (pri->pvts[chanpos]->owner->_state) {
10952 case AST_STATE_BUSY:
10953 case AST_STATE_UP:
10954 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10955 break;
10956 default:
10957 switch (e->hangup.cause) {
10958 case PRI_CAUSE_USER_BUSY:
10959 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10960 break;
10961 case PRI_CAUSE_CALL_REJECTED:
10962 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10963 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10964 case PRI_CAUSE_SWITCH_CONGESTION:
10965 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10966 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10967 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10968 break;
10969 default:
10970 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10971 }
10972 break;
10973 }
10974 }
10975 if (option_verbose > 2)
10976 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
10977 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
10978 } else {
10979 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10980 pri->pvts[chanpos]->call = NULL;
10981 }
10982 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10983 if (option_verbose > 2)
10984 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
10985 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10986 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10987 pri->pvts[chanpos]->resetting = 1;
10988 }
10989 if (e->hangup.aoc_units > -1)
10990 if (option_verbose > 2)
10991 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10992 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10993
10994 #ifdef SUPPORT_USERUSER
10995 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
10996 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10997 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10998 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10999 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11000 }
11001 #endif
11002
11003 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11004 } else {
11005 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
11006 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11007 }
11008 }
11009 break;
11010 #ifndef PRI_EVENT_HANGUP_REQ
11011 #error please update libpri
11012 #endif
11013 case PRI_EVENT_HANGUP_REQ:
11014 chanpos = pri_find_principle(pri, e->hangup.channel);
11015 if (chanpos < 0) {
11016 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11017 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11018 } else {
11019 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11020 if (chanpos > -1) {
11021 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11022 if (pri->pvts[chanpos]->realcall)
11023 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11024 else if (pri->pvts[chanpos]->owner) {
11025 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11026 switch (pri->pvts[chanpos]->owner->_state) {
11027 case AST_STATE_BUSY:
11028 case AST_STATE_UP:
11029 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11030 break;
11031 default:
11032 switch (e->hangup.cause) {
11033 case PRI_CAUSE_USER_BUSY:
11034 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11035 break;
11036 case PRI_CAUSE_CALL_REJECTED:
11037 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11038 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11039 case PRI_CAUSE_SWITCH_CONGESTION:
11040 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11041 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11042 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11043 break;
11044 default:
11045 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11046 }
11047 break;
11048 }
11049 if (option_verbose > 2)
11050 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
11051 if (e->hangup.aoc_units > -1)
11052 if (option_verbose > 2)
11053 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11054 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11055 } else {
11056 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11057 pri->pvts[chanpos]->call = NULL;
11058 }
11059 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11060 if (option_verbose > 2)
11061 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11062 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11063 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11064 pri->pvts[chanpos]->resetting = 1;
11065 }
11066
11067 #ifdef SUPPORT_USERUSER
11068 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11069 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11070 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11071 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11072 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11073 }
11074 #endif
11075
11076 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11077 } else {
11078 ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11079 }
11080 }
11081 break;
11082 case PRI_EVENT_HANGUP_ACK:
11083 chanpos = pri_find_principle(pri, e->hangup.channel);
11084 if (chanpos < 0) {
11085 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11086 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11087 } else {
11088 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11089 if (chanpos > -1) {
11090 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11091 pri->pvts[chanpos]->call = NULL;
11092 pri->pvts[chanpos]->resetting = 0;
11093 if (pri->pvts[chanpos]->owner) {
11094 if (option_verbose > 2)
11095 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11096 }
11097
11098 #ifdef SUPPORT_USERUSER
11099 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11100 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11101 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11102 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11103 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11104 }
11105 #endif
11106
11107 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11108 }
11109 }
11110 break;
11111 case PRI_EVENT_CONFIG_ERR:
11112 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11113 break;
11114 case PRI_EVENT_RESTART_ACK:
11115 chanpos = pri_find_principle(pri, e->restartack.channel);
11116 if (chanpos < 0) {
11117
11118
11119
11120 for (x = 0; x < pri->numchans; x++) {
11121 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11122 chanpos = x;
11123 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11124 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11125 pri->pvts[chanpos]->prioffset, pri->span);
11126 if (pri->pvts[chanpos]->realcall)
11127 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11128 else if (pri->pvts[chanpos]->owner) {
11129 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11130 pri->pvts[chanpos]->prioffset, pri->span);
11131 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11132 }
11133 pri->pvts[chanpos]->resetting = 0;
11134 if (option_verbose > 2)
11135 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11136 pri->pvts[chanpos]->prioffset, pri->span);
11137 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11138 if (pri->resetting)
11139 pri_check_restart(pri);
11140 break;
11141 }
11142 }
11143 if (chanpos < 0) {
11144 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11145 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11146 }
11147 } else {
11148 if (pri->pvts[chanpos]) {
11149 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11150 if (pri->pvts[chanpos]->realcall)
11151 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11152 else if (pri->pvts[chanpos]->owner) {
11153 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11154 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11155 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11156 }
11157 pri->pvts[chanpos]->resetting = 0;
11158 if (option_verbose > 2)
11159 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11160 pri->pvts[chanpos]->prioffset, pri->span);
11161 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11162 if (pri->resetting)
11163 pri_check_restart(pri);
11164 }
11165 }
11166 break;
11167 case PRI_EVENT_SETUP_ACK:
11168 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11169 if (chanpos < 0) {
11170 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11171 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11172 } else {
11173 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11174 if (chanpos > -1) {
11175 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11176 pri->pvts[chanpos]->setup_ack = 1;
11177
11178 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11179 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11180 pri_information(pri->pri, pri->pvts[chanpos]->call,
11181 pri->pvts[chanpos]->dialdest[x]);
11182 }
11183 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11184 } else
11185 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11186 }
11187 break;
11188 case PRI_EVENT_NOTIFY:
11189 chanpos = pri_find_principle(pri, e->notify.channel);
11190 if (chanpos < 0) {
11191 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11192 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11193 } else {
11194 struct ast_frame f = { AST_FRAME_CONTROL, };
11195 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11196 switch (e->notify.info) {
11197 case PRI_NOTIFY_REMOTE_HOLD:
11198 f.subclass = AST_CONTROL_HOLD;
11199 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11200 break;
11201 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11202 f.subclass = AST_CONTROL_UNHOLD;
11203 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11204 break;
11205 }
11206 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11207 }
11208 break;
11209 default:
11210 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
11211 }
11212 }
11213 ast_mutex_unlock(&pri->lock);
11214 }
11215
11216 return NULL;
11217 }
11218
11219 static int start_pri(struct dahdi_pri *pri)
11220 {
11221 int res, x;
11222 struct dahdi_params p;
11223 struct dahdi_bufferinfo bi;
11224 struct dahdi_spaninfo si;
11225 int i;
11226
11227 for (i = 0; i < NUM_DCHANS; i++) {
11228 if (!pri->dchannels[i])
11229 break;
11230 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
11231 x = pri->dchannels[i];
11232 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11233 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11234 return -1;
11235 }
11236 memset(&p, 0, sizeof(p));
11237 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11238 if (res) {
11239 dahdi_close_pri_fd(pri, i);
11240 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11241 return -1;
11242 }
11243 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11244 dahdi_close_pri_fd(pri, i);
11245 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
11246 return -1;
11247 }
11248 memset(&si, 0, sizeof(si));
11249 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11250 if (res) {
11251 dahdi_close_pri_fd(pri, i);
11252 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11253 }
11254 if (!si.alarms)
11255 pri->dchanavail[i] |= DCHAN_NOTINALARM;
11256 else
11257 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11258 memset(&bi, 0, sizeof(bi));
11259 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11260 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11261 bi.numbufs = 32;
11262 bi.bufsize = 1024;
11263 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11264 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11265 dahdi_close_pri_fd(pri, i);
11266 return -1;
11267 }
11268 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11269
11270 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11271 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11272 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11273 #ifdef HAVE_PRI_INBANDDISCONNECT
11274 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11275 #endif
11276
11277 if (i)
11278 pri_enslave(pri->dchans[0], pri->dchans[i]);
11279 if (!pri->dchans[i]) {
11280 dahdi_close_pri_fd(pri, i);
11281 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11282 return -1;
11283 }
11284 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11285 pri_set_nsf(pri->dchans[i], pri->nsf);
11286 #ifdef PRI_GETSET_TIMERS
11287 for (x = 0; x < PRI_MAX_TIMERS; x++) {
11288 if (pritimers[x] != 0)
11289 pri_set_timer(pri->dchans[i], x, pritimers[x]);
11290 }
11291 #endif
11292 }
11293
11294 pri->pri = pri->dchans[0];
11295 pri->resetpos = -1;
11296 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11297 for (i = 0; i < NUM_DCHANS; i++) {
11298 if (!pri->dchannels[i])
11299 break;
11300 dahdi_close_pri_fd(pri, i);
11301 }
11302 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11303 return -1;
11304 }
11305 return 0;
11306 }
11307
11308 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
11309 {
11310 int which, span;
11311 char *ret = NULL;
11312
11313 if (pos != rpos)
11314 return ret;
11315
11316 for (which = span = 0; span < NUM_SPANS; span++) {
11317 if (pris[span].pri && ++which > state) {
11318 if (asprintf(&ret, "%d", span + 1) < 0) {
11319 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11320 }
11321 break;
11322 }
11323 }
11324 return ret;
11325 }
11326
11327 static char *complete_span_4(const char *line, const char *word, int pos, int state)
11328 {
11329 return complete_span_helper(line,word,pos,state,3);
11330 }
11331
11332 static char *complete_span_5(const char *line, const char *word, int pos, int state)
11333 {
11334 return complete_span_helper(line,word,pos,state,4);
11335 }
11336
11337 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
11338 {
11339 int myfd;
11340
11341 if (!strncasecmp(argv[1], "set", 3)) {
11342 if (argc < 5)
11343 return RESULT_SHOWUSAGE;
11344
11345 if (ast_strlen_zero(argv[4]))
11346 return RESULT_SHOWUSAGE;
11347
11348 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
11349 if (myfd < 0) {
11350 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
11351 return RESULT_SUCCESS;
11352 }
11353
11354 ast_mutex_lock(&pridebugfdlock);
11355
11356 if (pridebugfd >= 0)
11357 close(pridebugfd);
11358
11359 pridebugfd = myfd;
11360 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
11361
11362 ast_mutex_unlock(&pridebugfdlock);
11363
11364 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
11365 } else {
11366
11367 ast_mutex_lock(&pridebugfdlock);
11368 close(pridebugfd);
11369 pridebugfd = -1;
11370 ast_cli(fd, "PRI debug output to file disabled\n");
11371 ast_mutex_unlock(&pridebugfdlock);
11372 }
11373
11374 return RESULT_SUCCESS;
11375 }
11376
11377 #ifdef HAVE_PRI_VERSION
11378 static int handle_pri_version(int fd, int agc, char *argv[]) {
11379 ast_cli(fd, "libpri version: %s\n", pri_get_version());
11380 return RESULT_SUCCESS;
11381 }
11382 #endif
11383
11384 static int handle_pri_debug(int fd, int argc, char *argv[])
11385 {
11386 int span;
11387 int x;
11388 if (argc < 4) {
11389 return RESULT_SHOWUSAGE;
11390 }
11391 span = atoi(argv[3]);
11392 if ((span < 1) || (span > NUM_SPANS)) {
11393 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11394 return RESULT_SUCCESS;
11395 }
11396 if (!pris[span-1].pri) {
11397 ast_cli(fd, "No PRI running on span %d\n", span);
11398 return RESULT_SUCCESS;
11399 }
11400 for (x = 0; x < NUM_DCHANS; x++) {
11401 if (pris[span-1].dchans[x])
11402 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11403 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11404 PRI_DEBUG_Q921_STATE);
11405 }
11406 ast_cli(fd, "Enabled debugging on span %d\n", span);
11407 return RESULT_SUCCESS;
11408 }
11409
11410
11411
11412 static int handle_pri_no_debug(int fd, int argc, char *argv[])
11413 {
11414 int span;
11415 int x;
11416 if (argc < 5)
11417 return RESULT_SHOWUSAGE;
11418 span = atoi(argv[4]);
11419 if ((span < 1) || (span > NUM_SPANS)) {
11420 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11421 return RESULT_SUCCESS;
11422 }
11423 if (!pris[span-1].pri) {
11424 ast_cli(fd, "No PRI running on span %d\n", span);
11425 return RESULT_SUCCESS;
11426 }
11427 for (x = 0; x < NUM_DCHANS; x++) {
11428 if (pris[span-1].dchans[x])
11429 pri_set_debug(pris[span-1].dchans[x], 0);
11430 }
11431 ast_cli(fd, "Disabled debugging on span %d\n", span);
11432 return RESULT_SUCCESS;
11433 }
11434
11435 static int handle_pri_really_debug(int fd, int argc, char *argv[])
11436 {
11437 int span;
11438 int x;
11439 if (argc < 5)
11440 return RESULT_SHOWUSAGE;
11441 span = atoi(argv[4]);
11442 if ((span < 1) || (span > NUM_SPANS)) {
11443 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11444 return RESULT_SUCCESS;
11445 }
11446 if (!pris[span-1].pri) {
11447 ast_cli(fd, "No PRI running on span %d\n", span);
11448 return RESULT_SUCCESS;
11449 }
11450 for (x = 0; x < NUM_DCHANS; x++) {
11451 if (pris[span-1].dchans[x])
11452 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11453 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11454 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11455 }
11456 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11457 return RESULT_SUCCESS;
11458 }
11459
11460 static void build_status(char *s, size_t len, int status, int active)
11461 {
11462 if (!s || len < 1) {
11463 return;
11464 }
11465 s[0] = '\0';
11466 if (status & DCHAN_PROVISIONED)
11467 strncat(s, "Provisioned, ", len - strlen(s) - 1);
11468 if (!(status & DCHAN_NOTINALARM))
11469 strncat(s, "In Alarm, ", len - strlen(s) - 1);
11470 if (status & DCHAN_UP)
11471 strncat(s, "Up", len - strlen(s) - 1);
11472 else
11473 strncat(s, "Down", len - strlen(s) - 1);
11474 if (active)
11475 strncat(s, ", Active", len - strlen(s) - 1);
11476 else
11477 strncat(s, ", Standby", len - strlen(s) - 1);
11478 s[len - 1] = '\0';
11479 }
11480
11481 static int handle_pri_show_spans(int fd, int argc, char *argv[])
11482 {
11483 int span;
11484 int x;
11485 char status[256];
11486 if (argc != 3)
11487 return RESULT_SHOWUSAGE;
11488
11489 for (span = 0; span < NUM_SPANS; span++) {
11490 if (pris[span].pri) {
11491 for (x = 0; x < NUM_DCHANS; x++) {
11492 if (pris[span].dchannels[x]) {
11493 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11494 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11495 }
11496 }
11497 }
11498 }
11499 return RESULT_SUCCESS;
11500 }
11501
11502 static int handle_pri_show_span(int fd, int argc, char *argv[])
11503 {
11504 int span;
11505 int x;
11506 char status[256];
11507 if (argc < 4)
11508 return RESULT_SHOWUSAGE;
11509 span = atoi(argv[3]);
11510 if ((span < 1) || (span > NUM_SPANS)) {
11511 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11512 return RESULT_SUCCESS;
11513 }
11514 if (!pris[span-1].pri) {
11515 ast_cli(fd, "No PRI running on span %d\n", span);
11516 return RESULT_SUCCESS;
11517 }
11518 for (x = 0; x < NUM_DCHANS; x++) {
11519 if (pris[span-1].dchannels[x]) {
11520 #ifdef PRI_DUMP_INFO_STR
11521 char *info_str = NULL;
11522 #endif
11523 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11524 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11525 ast_cli(fd, "Status: %s\n", status);
11526 #ifdef PRI_DUMP_INFO_STR
11527 info_str = pri_dump_info_str(pris[span-1].pri);
11528 if (info_str) {
11529 ast_cli(fd, "%s", info_str);
11530 free(info_str);
11531 }
11532 #else
11533 pri_dump_info(pris[span-1].pri);
11534 #endif
11535 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11536 }
11537 }
11538 return RESULT_SUCCESS;
11539 }
11540
11541 static int handle_pri_show_debug(int fd, int argc, char *argv[])
11542 {
11543 int x;
11544 int span;
11545 int count=0;
11546 int debug=0;
11547
11548 for (span = 0; span < NUM_SPANS; span++) {
11549 if (pris[span].pri) {
11550 for (x = 0; x < NUM_DCHANS; x++) {
11551 debug = 0;
11552 if (pris[span].dchans[x]) {
11553 debug = pri_get_debug(pris[span].dchans[x]);
11554 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" );
11555 count++;
11556 }
11557 }
11558 }
11559
11560 }
11561 ast_mutex_lock(&pridebugfdlock);
11562 if (pridebugfd >= 0)
11563 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
11564 ast_mutex_unlock(&pridebugfdlock);
11565
11566 if (!count)
11567 ast_cli(fd, "No debug set or no PRI running\n");
11568 return RESULT_SUCCESS;
11569 }
11570
11571 static const char pri_debug_help[] =
11572 "Usage: pri debug span <span>\n"
11573 " Enables debugging on a given PRI span\n";
11574
11575 static const char pri_no_debug_help[] =
11576 "Usage: pri no debug span <span>\n"
11577 " Disables debugging on a given PRI span\n";
11578
11579 static const char pri_really_debug_help[] =
11580 "Usage: pri intensive debug span <span>\n"
11581 " Enables debugging down to the Q.921 level\n";
11582
11583 static const char pri_show_span_help[] =
11584 "Usage: pri show span <span>\n"
11585 " Displays PRI Information on a given PRI span\n";
11586
11587 static const char pri_show_spans_help[] =
11588 "Usage: pri show spans\n"
11589 " Displays PRI Information\n";
11590
11591 static struct ast_cli_entry dahdi_pri_cli[] = {
11592 { { "pri", "debug", "span", NULL },
11593 handle_pri_debug, "Enables PRI debugging on a span",
11594 pri_debug_help, complete_span_4 },
11595
11596 { { "pri", "no", "debug", "span", NULL },
11597 handle_pri_no_debug, "Disables PRI debugging on a span",
11598 pri_no_debug_help, complete_span_5 },
11599
11600 { { "pri", "intense", "debug", "span", NULL },
11601 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
11602 pri_really_debug_help, complete_span_5 },
11603
11604 { { "pri", "show", "spans", NULL },
11605 handle_pri_show_spans, "Displays PRI Information",
11606 pri_show_spans_help },
11607
11608 { { "pri", "show", "span", NULL },
11609 handle_pri_show_span, "Displays PRI Information",
11610 pri_show_span_help, complete_span_4 },
11611
11612 { { "pri", "show", "debug", NULL },
11613 handle_pri_show_debug, "Displays current PRI debug settings" },
11614
11615 { { "pri", "set", "debug", "file", NULL },
11616 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
11617
11618 { { "pri", "unset", "debug", "file", NULL },
11619 handle_pri_set_debug_file, "Ends PRI debug output to file" },
11620
11621 #ifdef HAVE_PRI_VERSION
11622 { { "pri", "show", "version", NULL },
11623 handle_pri_version, "Displays version of libpri" },
11624 #endif
11625 };
11626
11627 #endif
11628
11629 #ifdef HAVE_OPENR2
11630
11631 static int handle_mfcr2_version(int fd, int argc, char *argv[])
11632 {
11633 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11634 return RESULT_SUCCESS;
11635 }
11636
11637 static int handle_mfcr2_show_variants(int fd, int argc, char *argv[])
11638 {
11639 #define FORMAT "%4s %40s\n"
11640 int numvariants = 0;
11641 int i;
11642 const openr2_variant_entry_t *variants;
11643 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
11644 ast_cli(fd, "Failed to get list of variants.\n");
11645 return RESULT_FAILURE;
11646 }
11647 ast_cli(fd, FORMAT, "Variant Code", "Country");
11648 for (i = 0; i < numvariants; i++) {
11649 ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
11650 }
11651 return RESULT_SUCCESS;
11652 #undef FORMAT
11653 }
11654
11655 static int handle_mfcr2_show_channels(int fd, int argc, char *argv[])
11656 {
11657 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
11658 int filtertype = 0;
11659 int targetnum = 0;
11660 char channo[5];
11661 char anino[5];
11662 char dnisno[5];
11663 struct dahdi_pvt *p;
11664 openr2_context_t *r2context;
11665 openr2_variant_t r2variant;
11666 if (!((argc == 3) || (argc == 5))) {
11667 return RESULT_SHOWUSAGE;
11668 }
11669 if (argc == 5) {
11670 if (!strcasecmp(argv[3], "group")) {
11671 targetnum = atoi(argv[4]);
11672 if ((targetnum < 0) || (targetnum > 63))
11673 return RESULT_SHOWUSAGE;
11674 targetnum = 1 << targetnum;
11675 filtertype = 1;
11676 } else if (!strcasecmp(argv[3], "context")) {
11677 filtertype = 2;
11678 } else {
11679 return RESULT_SHOWUSAGE;
11680 }
11681 }
11682 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
11683 ast_mutex_lock(&iflock);
11684 p = iflist;
11685 while (p) {
11686 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11687 p = p->next;
11688 continue;
11689 }
11690 if (filtertype) {
11691 switch(filtertype) {
11692 case 1:
11693 if (p->group != targetnum) {
11694 p = p->next;
11695 continue;
11696 }
11697 break;
11698 case 2:
11699 if (strcasecmp(p->context, argv[4])) {
11700 p= p->next;
11701 continue;
11702 }
11703 break;
11704 default:
11705 ;
11706 }
11707 }
11708 r2context = openr2_chan_get_context(p->r2chan);
11709 r2variant = openr2_context_get_variant(r2context);
11710 snprintf(channo, sizeof(channo), "%d", p->channel);
11711 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
11712 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
11713 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
11714 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
11715 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
11716 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
11717 p = p->next;
11718 }
11719 ast_mutex_unlock(&iflock);
11720 return RESULT_SUCCESS;
11721 #undef FORMAT
11722 }
11723
11724 static int handle_mfcr2_set_debug(int fd, int argc, char *argv[])
11725 {
11726 struct dahdi_pvt *p = NULL;
11727 int channo = 0;
11728 char *toklevel = NULL;
11729 char *saveptr = NULL;
11730 char *logval = NULL;
11731 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
11732 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
11733 if (argc < 4) {
11734 return RESULT_SHOWUSAGE;
11735 }
11736 channo = (argc == 5) ? atoi(argv[4]) : -1;
11737 logval = ast_strdupa(argv[3]);
11738 toklevel = strtok_r(logval, ",", &saveptr);
11739 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11740 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
11741 return RESULT_FAILURE;
11742 } else if (OR2_LOG_NOTHING == tmplevel) {
11743 loglevel = tmplevel;
11744 } else {
11745 loglevel |= tmplevel;
11746 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
11747 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11748 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
11749 continue;
11750 }
11751 loglevel |= tmplevel;
11752 }
11753 }
11754 ast_mutex_lock(&iflock);
11755 p = iflist;
11756 while (p) {
11757 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11758 p = p->next;
11759 continue;
11760 }
11761 if ((channo != -1) && (p->channel != channo )) {
11762 p = p->next;
11763 continue;
11764 }
11765 openr2_chan_set_log_level(p->r2chan, loglevel);
11766 if (channo != -1) {
11767 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
11768 break;
11769 } else {
11770 p = p->next;
11771 }
11772 }
11773 if ((channo != -1) && !p) {
11774 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11775 }
11776 if (channo == -1) {
11777 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
11778 }
11779 ast_mutex_unlock(&iflock);
11780 return RESULT_SUCCESS;
11781 }
11782
11783 static int handle_mfcr2_call_files(int fd, int argc, char *argv[])
11784 {
11785 struct dahdi_pvt *p = NULL;
11786 int channo = 0;
11787 if (argc < 4) {
11788 return RESULT_SHOWUSAGE;
11789 }
11790 channo = (argc == 5) ? atoi(argv[4]) : -1;
11791 ast_mutex_lock(&iflock);
11792 p = iflist;
11793 while (p) {
11794 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11795 p = p->next;
11796 continue;
11797 }
11798 if ((channo != -1) && (p->channel != channo )) {
11799 p = p->next;
11800 continue;
11801 }
11802 if (ast_true(argv[3])) {
11803 openr2_chan_enable_call_files(p->r2chan);
11804 } else {
11805 openr2_chan_disable_call_files(p->r2chan);
11806 }
11807 if (channo != -1) {
11808 if (ast_true(argv[3])) {
11809 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
11810 } else {
11811 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
11812 }
11813 break;
11814 } else {
11815 p = p->next;
11816 }
11817 }
11818 if ((channo != -1) && !p) {
11819 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11820 }
11821 if (channo == -1) {
11822 if (ast_true(argv[3])) {
11823 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
11824 } else {
11825 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
11826 }
11827 }
11828 ast_mutex_unlock(&iflock);
11829 return RESULT_SUCCESS;
11830 }
11831
11832 static int handle_mfcr2_set_idle(int fd, int argc, char *argv[])
11833 {
11834 struct dahdi_pvt *p = NULL;
11835 int channo = 0;
11836 channo = (argc == 4) ? atoi(argv[3]) : -1;
11837 ast_mutex_lock(&iflock);
11838 p = iflist;
11839 while (p) {
11840 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11841 p = p->next;
11842 continue;
11843 }
11844 if ((channo != -1) && (p->channel != channo )) {
11845 p = p->next;
11846 continue;
11847 }
11848 if (!openr2_chan_set_idle(p->r2chan)) {
11849 ast_mutex_lock(&p->lock);
11850 p->mfcr2call = 0;
11851 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
11852 ast_mutex_unlock(&p->lock);
11853 }
11854 if (channo != -1) {
11855 break;
11856 } else {
11857 p = p->next;
11858 }
11859 }
11860 if ((channo != -1) && !p) {
11861 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11862 }
11863 ast_mutex_unlock(&iflock);
11864 return RESULT_SUCCESS;
11865 }
11866
11867 static int handle_mfcr2_set_blocked(int fd, int argc, char *argv[])
11868 {
11869 struct dahdi_pvt *p = NULL;
11870 int channo = 0;
11871 channo = (argc == 4) ? atoi(argv[3]) : -1;
11872 ast_mutex_lock(&iflock);
11873 p = iflist;
11874 while (p) {
11875 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11876 p = p->next;
11877 continue;
11878 }
11879 if ((channo != -1) && (p->channel != channo )) {
11880 p = p->next;
11881 continue;
11882 }
11883 if (!openr2_chan_set_blocked(p->r2chan)) {
11884 ast_mutex_lock(&p->lock);
11885 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
11886 ast_mutex_unlock(&p->lock);
11887 } else {
11888 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
11889 }
11890 if (channo != -1) {
11891 break;
11892 } else {
11893 p = p->next;
11894 }
11895 }
11896 if ((channo != -1) && !p) {
11897 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11898 }
11899 ast_mutex_unlock(&iflock);
11900 return RESULT_SUCCESS;
11901 }
11902
11903 static const char dahdi_r2_version_help[] =
11904 "Usage: mfcr2 show version\n"
11905 " Shows the version of the OpenR2 library being used.\n";
11906 static const char dahdi_r2_variants_help[] =
11907 "Usage: mfcr2 show variants\n"
11908 " Show supported MFC/R2 variants.\n";
11909 static const char dahdi_r2_showchannels_help[] =
11910 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
11911 " Shows the zap channels configured with MFC/R2 signaling.\n";
11912 static const char dahdi_r2_setdebug_help[] =
11913 "Usage: mfcr2 set debug <loglevel> <channel>\n"
11914 " Set a new logging level for the specified channel.\n"
11915 " If no channel is specified the logging level will be applied to all channels.\n";
11916 static const char dahdi_r2_callfiles_help[] =
11917 "Usage: mfcr2 call files [on|off] <channel>\n"
11918 " Enable call files creation on the specified channel.\n"
11919 " If no channel is specified call files creation policy will be applied to all channels.\n";
11920 static const char dahdi_r2_setidle_help[] =
11921 "Usage: mfcr2 set idle <channel>\n"
11922 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11923 " Force the given channel into IDLE state.\n"
11924 " If no channel is specified, all channels will be set to IDLE.\n";
11925 static const char dahdi_r2_setblocked_help[] =
11926 "Usage: mfcr2 set blocked <channel>\n"
11927 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11928 " Force the given channel into BLOCKED state.\n"
11929 " If no channel is specified, all channels will be set to BLOCKED.\n";
11930
11931 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
11932 { { "mfcr2", "show", "version", NULL },
11933 handle_mfcr2_version, "Show OpenR2 library version",
11934 dahdi_r2_version_help },
11935
11936 { { "mfcr2", "show", "variants", NULL },
11937 handle_mfcr2_show_variants, "Show supported MFC/R2 variants",
11938 dahdi_r2_variants_help },
11939
11940 { { "mfcr2", "show", "channels", NULL },
11941 handle_mfcr2_show_channels, "Show MFC/R2 channels",
11942 dahdi_r2_showchannels_help },
11943
11944 { { "mfcr2", "set", "debug", NULL },
11945 handle_mfcr2_set_debug, "Set MFC/R2 channel logging level",
11946 dahdi_r2_setdebug_help },
11947
11948 { { "mfcr2", "call", "files", NULL },
11949 handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files",
11950 dahdi_r2_callfiles_help },
11951
11952 { { "mfcr2", "set", "idle", NULL },
11953 handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE",
11954 dahdi_r2_setidle_help },
11955
11956 { { "mfcr2", "set", "blocked", NULL },
11957 handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED",
11958 dahdi_r2_setblocked_help }
11959
11960 };
11961
11962 #endif
11963
11964 static int dahdi_destroy_channel(int fd, int argc, char **argv)
11965 {
11966 int channel;
11967
11968 if (argc != 4)
11969 return RESULT_SHOWUSAGE;
11970
11971 channel = atoi(argv[3]);
11972
11973 return dahdi_destroy_channel_bynum(channel);
11974 }
11975
11976 static void dahdi_softhangup_all(void)
11977 {
11978 struct dahdi_pvt *p;
11979 retry:
11980 ast_mutex_lock(&iflock);
11981 for (p = iflist; p; p = p->next) {
11982 ast_mutex_lock(&p->lock);
11983 if (p->owner && !p->restartpending) {
11984 if (ast_channel_trylock(p->owner)) {
11985 if (option_debug > 2)
11986 ast_verbose("Avoiding deadlock\n");
11987
11988 ast_mutex_unlock(&p->lock);
11989 ast_mutex_unlock(&iflock);
11990 goto retry;
11991 }
11992 if (option_debug > 2)
11993 ast_verbose("Softhanging up on %s\n", p->owner->name);
11994 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11995 p->restartpending = 1;
11996 num_restart_pending++;
11997 ast_channel_unlock(p->owner);
11998 }
11999 ast_mutex_unlock(&p->lock);
12000 }
12001 ast_mutex_unlock(&iflock);
12002 }
12003
12004 static int setup_dahdi(int reload);
12005 static int dahdi_restart(void)
12006 {
12007 #ifdef HAVE_OPENR2
12008 int r;
12009 #endif
12010 #if defined(HAVE_PRI)
12011 int i, j;
12012 #endif
12013 int cancel_code;
12014 struct dahdi_pvt *p;
12015
12016 ast_mutex_lock(&restart_lock);
12017
12018 if (option_verbose)
12019 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
12020 dahdi_softhangup_all();
12021 if (option_verbose > 3)
12022 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
12023
12024 #ifdef HAVE_OPENR2
12025 for (r = 0; r < NUM_SPANS; r++) {
12026 if (r2links[r].master != AST_PTHREADT_NULL) {
12027 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
12028 pthread_cancel(r2links[r].master);
12029 pthread_join(r2links[r].master, NULL);
12030 openr2_context_delete(r2links[r].protocol_context);
12031 }
12032 }
12033 init_mfcr2_globals();
12034 #endif
12035
12036 #if defined(HAVE_PRI)
12037 for (i = 0; i < NUM_SPANS; i++) {
12038 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12039 cancel_code = pthread_cancel(pris[i].master);
12040 pthread_kill(pris[i].master, SIGURG);
12041 if (option_debug > 3)
12042 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12043 pthread_join(pris[i].master, NULL);
12044 if (option_debug > 3)
12045 ast_verbose("Joined thread of span %d\n", i);
12046 }
12047 }
12048 #endif
12049
12050 ast_mutex_lock(&monlock);
12051 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12052 cancel_code = pthread_cancel(monitor_thread);
12053 pthread_kill(monitor_thread, SIGURG);
12054 if (option_debug > 3)
12055 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12056 pthread_join(monitor_thread, NULL);
12057 if (option_debug > 3)
12058 ast_verbose("Joined monitor thread\n");
12059 }
12060 monitor_thread = AST_PTHREADT_NULL;
12061
12062 ast_mutex_lock(&ss_thread_lock);
12063 while (ss_thread_count > 0) {
12064 int x = DAHDI_FLASH;
12065 if (option_debug > 2)
12066 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12067
12068 for (p = iflist; p; p = p->next) {
12069 if (p->owner)
12070 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
12071 }
12072 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12073 }
12074
12075
12076 dahdi_softhangup_all();
12077 if (option_verbose > 3)
12078 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
12079 destroy_all_channels();
12080 if (option_debug)
12081 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12082
12083 ast_mutex_unlock(&monlock);
12084
12085 #ifdef HAVE_PRI
12086 for (i = 0; i < NUM_SPANS; i++) {
12087 for (j = 0; j < NUM_DCHANS; j++)
12088 dahdi_close_pri_fd(&(pris[i]), j);
12089 }
12090
12091 memset(pris, 0, sizeof(pris));
12092 for (i = 0; i < NUM_SPANS; i++) {
12093 ast_mutex_init(&pris[i].lock);
12094 pris[i].offset = -1;
12095 pris[i].master = AST_PTHREADT_NULL;
12096 for (j = 0; j < NUM_DCHANS; j++)
12097 pris[i].fds[j] = -1;
12098 }
12099 pri_set_error(dahdi_pri_error);
12100 pri_set_message(dahdi_pri_message);
12101 #endif
12102
12103 if (setup_dahdi(2) != 0) {
12104 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12105 ast_mutex_unlock(&ss_thread_lock);
12106 return 1;
12107 }
12108 ast_mutex_unlock(&ss_thread_lock);
12109 ast_mutex_unlock(&restart_lock);
12110 return 0;
12111 }
12112
12113 static int dahdi_restart_cmd(int fd, int argc, char **argv)
12114 {
12115 if (argc != 2) {
12116 return RESULT_SHOWUSAGE;
12117 }
12118
12119 if (dahdi_restart() != 0)
12120 return RESULT_FAILURE;
12121 return RESULT_SUCCESS;
12122 }
12123
12124 static int dahdi_show_channels(int fd, int argc, char **argv)
12125 {
12126 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12127 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12128 struct dahdi_pvt *tmp = NULL;
12129 char tmps[20] = "";
12130 ast_mutex_t *lock;
12131 struct dahdi_pvt *start;
12132 #ifdef HAVE_PRI
12133 int trunkgroup;
12134 struct dahdi_pri *pri = NULL;
12135 int x;
12136 #endif
12137
12138 lock = &iflock;
12139 start = iflist;
12140
12141 #ifdef HAVE_PRI
12142 if (argc == 4) {
12143 if ((trunkgroup = atoi(argv[3])) < 1)
12144 return RESULT_SHOWUSAGE;
12145 for (x = 0; x < NUM_SPANS; x++) {
12146 if (pris[x].trunkgroup == trunkgroup) {
12147 pri = pris + x;
12148 break;
12149 }
12150 }
12151 if (pri) {
12152 start = pri->crvs;
12153 lock = &pri->lock;
12154 } else {
12155 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12156 return RESULT_FAILURE;
12157 }
12158 } else
12159 #endif
12160 if (argc != 3)
12161 return RESULT_SHOWUSAGE;
12162
12163 ast_mutex_lock(lock);
12164 #ifdef HAVE_PRI
12165 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
12166 #else
12167 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
12168 #endif
12169
12170 tmp = start;
12171 while (tmp) {
12172 if (tmp->channel > 0) {
12173 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12174 } else
12175 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12176 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
12177 tmp = tmp->next;
12178 }
12179 ast_mutex_unlock(lock);
12180 return RESULT_SUCCESS;
12181 #undef FORMAT
12182 #undef FORMAT2
12183 }
12184
12185 static int dahdi_show_channel(int fd, int argc, char **argv)
12186 {
12187 int channel;
12188 struct dahdi_pvt *tmp = NULL;
12189 struct dahdi_confinfo ci;
12190 struct dahdi_params ps;
12191 int x;
12192 ast_mutex_t *lock;
12193 struct dahdi_pvt *start;
12194 #ifdef HAVE_PRI
12195 char *c;
12196 int trunkgroup;
12197 struct dahdi_pri *pri=NULL;
12198 #endif
12199
12200 lock = &iflock;
12201 start = iflist;
12202
12203 if (argc != 4)
12204 return RESULT_SHOWUSAGE;
12205 #ifdef HAVE_PRI
12206 if ((c = strchr(argv[3], ':'))) {
12207 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12208 return RESULT_SHOWUSAGE;
12209 if ((trunkgroup < 1) || (channel < 1))
12210 return RESULT_SHOWUSAGE;
12211 for (x = 0; x < NUM_SPANS; x++) {
12212 if (pris[x].trunkgroup == trunkgroup) {
12213 pri = pris + x;
12214 break;
12215 }
12216 }
12217 if (pri) {
12218 start = pri->crvs;
12219 lock = &pri->lock;
12220 } else {
12221 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12222 return RESULT_FAILURE;
12223 }
12224 } else
12225 #endif
12226 channel = atoi(argv[3]);
12227
12228 ast_mutex_lock(lock);
12229 tmp = start;
12230 while (tmp) {
12231 if (tmp->channel == channel) {
12232 #ifdef HAVE_PRI
12233 if (pri)
12234 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12235 else
12236 #endif
12237 ast_cli(fd, "Channel: %d\n", tmp->channel);
12238 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12239 ast_cli(fd, "Span: %d\n", tmp->span);
12240 ast_cli(fd, "Extension: %s\n", tmp->exten);
12241 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12242 ast_cli(fd, "Context: %s\n", tmp->context);
12243 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
12244 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
12245 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
12246 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
12247 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
12248 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12249 ast_cli(fd, "Radio: %d\n", tmp->radio);
12250 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12251 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)" : "");
12252 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)" : "");
12253 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)" : "");
12254 ast_cli(fd, "Confno: %d\n", tmp->confno);
12255 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
12256 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
12257 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12258 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12259 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12260 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12261 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12262 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12263 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
12264 if (tmp->master)
12265 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
12266 for (x = 0; x < MAX_SLAVES; x++) {
12267 if (tmp->slaves[x])
12268 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12269 }
12270 #ifdef HAVE_OPENR2
12271 if (tmp->mfcr2) {
12272 char calldir[OR2_MAX_PATH];
12273 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
12274 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
12275 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
12276 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
12277 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
12278 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
12279 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
12280 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
12281 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
12282 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
12283 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
12284 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
12285 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12286 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
12287 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
12288 #endif
12289 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
12290 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
12291 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
12292 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
12293 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
12294 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
12295 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
12296 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
12297 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
12298 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
12299 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
12300 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
12301 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
12302 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
12303 }
12304 #endif
12305 #ifdef HAVE_PRI
12306 if (tmp->pri) {
12307 ast_cli(fd, "PRI Flags: ");
12308 if (tmp->resetting)
12309 ast_cli(fd, "Resetting ");
12310 if (tmp->call)
12311 ast_cli(fd, "Call ");
12312 if (tmp->bearer)
12313 ast_cli(fd, "Bearer ");
12314 ast_cli(fd, "\n");
12315 if (tmp->logicalspan)
12316 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12317 else
12318 ast_cli(fd, "PRI Logical Span: Implicit\n");
12319 }
12320
12321 #endif
12322 memset(&ci, 0, sizeof(ci));
12323 ps.channo = tmp->channel;
12324 if (tmp->subs[SUB_REAL].dfd > -1) {
12325 memset(&ci, 0, sizeof(ci));
12326 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12327 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12328 }
12329 #ifdef DAHDI_GETCONFMUTE
12330 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12331 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12332 }
12333 #endif
12334 memset(&ps, 0, sizeof(ps));
12335 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12336 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12337 } else {
12338 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12339 }
12340 }
12341 if (ISTRUNK(tmp)) {
12342 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
12343 if (!ast_strlen_zero(progzone))
12344 ast_cli(fd, "Progress Zone: %s\n", progzone);
12345 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
12346 if(tmp->busydetect) {
12347 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
12348 if(tmp->busytonelength > 0) {
12349 ast_cli(fd, "Busy Pattern:\n");
12350 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12351 if (tmp->busyquietlength > 0)
12352 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12353 else
12354 ast_cli(fd, " -- Detect Tone Only\n");
12355 if(tmp->busyfuzziness > 0)
12356 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12357 }
12358 }
12359 }
12360 ast_mutex_unlock(lock);
12361 return RESULT_SUCCESS;
12362 }
12363 tmp = tmp->next;
12364 }
12365
12366 ast_cli(fd, "Unable to find given channel %d\n", channel);
12367 ast_mutex_unlock(lock);
12368 return RESULT_FAILURE;
12369 }
12370
12371 static char dahdi_show_cadences_usage[] =
12372 "Usage: dahdi show cadences\n"
12373 " Shows all cadences currently defined\n";
12374
12375 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
12376 {
12377 int i, j;
12378 for (i = 0; i < num_cadence; i++) {
12379 char output[1024];
12380 char tmp[16], tmp2[64];
12381 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12382 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12383
12384 for (j = 0; j < 16; j++) {
12385 if (cadences[i].ringcadence[j] == 0)
12386 break;
12387 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12388 if (cidrings[i] * 2 - 1 == j)
12389 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12390 else
12391 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12392 if (j != 0)
12393 strncat(output, ",", sizeof(output) - strlen(output) - 1);
12394 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12395 }
12396 ast_cli(fd,"%s\n",output);
12397 }
12398 return 0;
12399 }
12400
12401
12402 static int dahdi_show_status(int fd, int argc, char *argv[]) {
12403 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12404 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12405
12406 int span;
12407 int res;
12408 char alarms[50];
12409
12410 int ctl;
12411 struct dahdi_spaninfo s;
12412
12413 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
12414 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
12415 ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
12416 return RESULT_FAILURE;
12417 }
12418 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
12419
12420 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12421 s.spanno = span;
12422 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12423 if (res) {
12424 continue;
12425 }
12426 alarms[0] = '\0';
12427 if (s.alarms > 0) {
12428 if (s.alarms & DAHDI_ALARM_BLUE)
12429 strcat(alarms, "BLU/");
12430 if (s.alarms & DAHDI_ALARM_YELLOW)
12431 strcat(alarms, "YEL/");
12432 if (s.alarms & DAHDI_ALARM_RED)
12433 strcat(alarms, "RED/");
12434 if (s.alarms & DAHDI_ALARM_LOOPBACK)
12435 strcat(alarms, "LB/");
12436 if (s.alarms & DAHDI_ALARM_RECOVER)
12437 strcat(alarms, "REC/");
12438 if (s.alarms & DAHDI_ALARM_NOTOPEN)
12439 strcat(alarms, "NOP/");
12440 if (!strlen(alarms))
12441 strcat(alarms, "UUU/");
12442 if (strlen(alarms)) {
12443
12444 alarms[strlen(alarms) - 1] = '\0';
12445 }
12446 } else {
12447 if (s.numchans)
12448 strcpy(alarms, "OK");
12449 else
12450 strcpy(alarms, "UNCONFIGURED");
12451 }
12452
12453 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12454 }
12455 close(ctl);
12456
12457 return RESULT_SUCCESS;
12458 #undef FORMAT
12459 #undef FORMAT2
12460 }
12461
12462 static char show_channels_usage[] =
12463 "Usage: dahdi show channels\n"
12464 " Shows a list of available channels\n";
12465
12466 static char show_channel_usage[] =
12467 "Usage: dahdi show channel <chan num>\n"
12468 " Detailed information about a given channel\n";
12469
12470 static char dahdi_show_status_usage[] =
12471 "Usage: dahdi show status\n"
12472 " Shows a list of DAHDI cards with status\n";
12473
12474 static char destroy_channel_usage[] =
12475 "Usage: dahdi destroy channel <chan num>\n"
12476 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12477
12478 static char dahdi_restart_usage[] =
12479 "Usage: dahdi restart\n"
12480 " Restarts the DAHDI channels: destroys them all and then\n"
12481 " re-reads them from chan_dahdi.conf.\n"
12482 " Note that this will STOP any running CALL on DAHDI channels.\n"
12483 "";
12484
12485 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
12486 { "zap", "show", "cadences", NULL },
12487 handle_dahdi_show_cadences, NULL,
12488 NULL };
12489
12490 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
12491 { "zap", "show", "channels", NULL },
12492 dahdi_show_channels, NULL,
12493 NULL };
12494
12495 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
12496 { "zap", "show", "channel", NULL },
12497 dahdi_show_channel, NULL,
12498 NULL };
12499
12500 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
12501 { "zap", "destroy", "channel", NULL },
12502 dahdi_destroy_channel, NULL,
12503 NULL };
12504
12505 static struct ast_cli_entry cli_zap_restart_deprecated = {
12506 { "zap", "restart", NULL },
12507 dahdi_restart_cmd, NULL,
12508 NULL };
12509
12510 static struct ast_cli_entry cli_zap_show_status_deprecated = {
12511 { "zap", "show", "status", NULL },
12512 dahdi_show_status, NULL,
12513 NULL };
12514
12515 static struct ast_cli_entry dahdi_cli[] = {
12516 { { "dahdi", "show", "cadences", NULL },
12517 handle_dahdi_show_cadences, "List cadences",
12518 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
12519
12520 { { "dahdi", "show", "channels", NULL},
12521 dahdi_show_channels, "Show active DAHDI channels",
12522 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
12523
12524 { { "dahdi", "show", "channel", NULL},
12525 dahdi_show_channel, "Show information on a channel",
12526 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
12527
12528 { { "dahdi", "destroy", "channel", NULL},
12529 dahdi_destroy_channel, "Destroy a channel",
12530 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
12531
12532 { { "dahdi", "restart", NULL},
12533 dahdi_restart_cmd, "Fully restart DAHDI channels",
12534 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
12535
12536 { { "dahdi", "show", "status", NULL},
12537 dahdi_show_status, "Show all DAHDI cards status",
12538 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
12539 };
12540
12541 #define TRANSFER 0
12542 #define HANGUP 1
12543
12544 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
12545 {
12546 if (p) {
12547 switch (mode) {
12548 case TRANSFER:
12549 p->fake_event = DAHDI_EVENT_WINKFLASH;
12550 break;
12551 case HANGUP:
12552 p->fake_event = DAHDI_EVENT_ONHOOK;
12553 break;
12554 default:
12555 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
12556 }
12557 }
12558 return 0;
12559 }
12560 static struct dahdi_pvt *find_channel(int channel)
12561 {
12562 struct dahdi_pvt *p = iflist;
12563 while (p) {
12564 if (p->channel == channel) {
12565 break;
12566 }
12567 p = p->next;
12568 }
12569 return p;
12570 }
12571
12572 #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)
12573 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
12574
12575 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
12576 {
12577 struct dahdi_pvt *p = NULL;
12578 const char *channel = local_astman_header(m, "Channel", zap_mode);
12579
12580 if (ast_strlen_zero(channel)) {
12581 astman_send_error(s, m, "No channel specified");
12582 return 0;
12583 }
12584 if (!(p = find_channel(atoi(channel)))) {
12585 astman_send_error(s, m, "No such channel");
12586 return 0;
12587 }
12588 p->dnd = dnd;
12589 local_astman_ack(s, m, "DND", zap_mode);
12590
12591 return 0;
12592 }
12593
12594 static int zap_action_dndon(struct mansession *s, const struct message *m)
12595 {
12596 return __action_dnd(s, m, 1, 1);
12597 }
12598
12599 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
12600 {
12601 return __action_dnd(s, m, 0, 1);
12602 }
12603
12604 static int zap_action_dndoff(struct mansession *s, const struct message *m)
12605 {
12606 return __action_dnd(s, m, 1, 0);
12607 }
12608
12609 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
12610 {
12611 return __action_dnd(s, m, 0, 0);
12612 }
12613
12614 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
12615 {
12616 struct dahdi_pvt *p = NULL;
12617 const char *channel = local_astman_header(m, "Channel", zap_mode);
12618
12619 if (ast_strlen_zero(channel)) {
12620 astman_send_error(s, m, "No channel specified");
12621 return 0;
12622 }
12623 if (!(p = find_channel(atoi(channel)))) {
12624 astman_send_error(s, m, "No such channel");
12625 return 0;
12626 }
12627 dahdi_fake_event(p,TRANSFER);
12628 local_astman_ack(s, m, "Transfer", zap_mode);
12629
12630 return 0;
12631 }
12632
12633 static int zap_action_transfer(struct mansession *s, const struct message *m)
12634 {
12635 return __action_transfer(s, m, 1);
12636 }
12637
12638 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
12639 {
12640 return __action_transfer(s, m, 0);
12641 }
12642
12643 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
12644 {
12645 struct dahdi_pvt *p = NULL;
12646 const char *channel = local_astman_header(m, "Channel", zap_mode);
12647
12648 if (ast_strlen_zero(channel)) {
12649 astman_send_error(s, m, "No channel specified");
12650 return 0;
12651 }
12652 if (!(p = find_channel(atoi(channel)))) {
12653 astman_send_error(s, m, "No such channel");
12654 return 0;
12655 }
12656 dahdi_fake_event(p, HANGUP);
12657 local_astman_ack(s, m, "Hangup", zap_mode);
12658 return 0;
12659 }
12660
12661 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
12662 {
12663 return __action_transferhangup(s, m, 1);
12664 }
12665
12666 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
12667 {
12668 return __action_transferhangup(s, m, 0);
12669 }
12670
12671 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
12672 {
12673 struct dahdi_pvt *p = NULL;
12674 const char *channel = local_astman_header(m, "Channel", zap_mode);
12675 const char *number = astman_get_header(m, "Number");
12676 int i;
12677
12678 if (ast_strlen_zero(channel)) {
12679 astman_send_error(s, m, "No channel specified");
12680 return 0;
12681 }
12682 if (ast_strlen_zero(number)) {
12683 astman_send_error(s, m, "No number specified");
12684 return 0;
12685 }
12686 if (!(p = find_channel(atoi(channel)))) {
12687 astman_send_error(s, m, "No such channel");
12688 return 0;
12689 }
12690 if (!p->owner) {
12691 astman_send_error(s, m, "Channel does not have an owner");
12692 return 0;
12693 }
12694 for (i = 0; i < strlen(number); i++) {
12695 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12696
12697 dahdi_queue_frame(p, &f, NULL);
12698 }
12699 local_astman_ack(s, m, "DialOffHook", zap_mode);
12700
12701 return 0;
12702 }
12703
12704 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
12705 {
12706 return __action_dialoffhook(s, m, 1);
12707 }
12708
12709 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
12710 {
12711 return __action_dialoffhook(s, m, 0);
12712 }
12713
12714 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
12715 {
12716 struct dahdi_pvt *tmp = NULL;
12717 const char *id = astman_get_header(m, "ActionID");
12718 char idText[256] = "";
12719
12720 local_astman_ack(s, m, " channel status will follow", zap_mode);
12721 if (!ast_strlen_zero(id))
12722 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12723
12724 ast_mutex_lock(&iflock);
12725
12726 tmp = iflist;
12727 while (tmp) {
12728 if (tmp->channel > 0) {
12729 int alarm = get_alarms(tmp);
12730 astman_append(s,
12731 "Event: %sShowChannels\r\n"
12732 "Channel: %d\r\n"
12733 "Signalling: %s\r\n"
12734 "Context: %s\r\n"
12735 "DND: %s\r\n"
12736 "Alarm: %s\r\n"
12737 "%s"
12738 "\r\n",
12739 dahdi_chan_name,
12740 tmp->channel, sig2str(tmp->sig), tmp->context,
12741 tmp->dnd ? "Enabled" : "Disabled",
12742 alarm2str(alarm), idText);
12743 }
12744
12745 tmp = tmp->next;
12746 }
12747
12748 ast_mutex_unlock(&iflock);
12749
12750 astman_append(s,
12751 "Event: %sShowChannelsComplete\r\n"
12752 "%s"
12753 "\r\n",
12754 dahdi_chan_name,
12755 idText);
12756 return 0;
12757 }
12758
12759 static int zap_action_showchannels(struct mansession *s, const struct message *m)
12760 {
12761 return __action_showchannels(s, m, 1);
12762 }
12763
12764 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
12765 {
12766 return __action_showchannels(s, m, 0);
12767 }
12768
12769 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
12770 {
12771 if (dahdi_restart() != 0) {
12772 if (zap_mode) {
12773 astman_send_error(s, m, "Failed to restart Zap");
12774 } else {
12775 astman_send_error(s, m, "Failed to restart DAHDI");
12776 }
12777 return 1;
12778 }
12779 local_astman_ack(s, m, "Restart: Success", zap_mode);
12780 return 0;
12781 }
12782
12783 static int zap_action_restart(struct mansession *s, const struct message *m)
12784 {
12785 return __action_restart(s, m, 1);
12786 }
12787
12788 static int dahdi_action_restart(struct mansession *s, const struct message *m)
12789 {
12790 return __action_restart(s, m, 0);
12791 }
12792
12793 #define local_astman_unregister(a) do { \
12794 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12795 ast_manager_unregister("DAHDI" a); \
12796 } \
12797 ast_manager_unregister("Zap" a); \
12798 } while (0)
12799
12800 static int __unload_module(void)
12801 {
12802 struct dahdi_pvt *p;
12803 #ifdef HAVE_OPENR2
12804 int r;
12805 #endif
12806 #ifdef HAVE_PRI
12807 int i, j;
12808 for (i = 0; i < NUM_SPANS; i++) {
12809 if (pris[i].master != AST_PTHREADT_NULL)
12810 pthread_cancel(pris[i].master);
12811 }
12812 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12813
12814 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12815 ast_unregister_application(dahdi_send_keypad_facility_app);
12816 }
12817 ast_unregister_application(zap_send_keypad_facility_app);
12818 #endif
12819 #ifdef HAVE_OPENR2
12820 for (r = 0; r < NUM_SPANS; r++) {
12821 if (r2links[r].master != AST_PTHREADT_NULL) {
12822 pthread_cancel(r2links[r].master);
12823 pthread_join(r2links[r].master, NULL);
12824 }
12825 }
12826 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
12827 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12828 ast_unregister_application(dahdi_accept_r2_call_app);
12829 }
12830 ast_unregister_application(zap_accept_r2_call_app);
12831 #endif
12832 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12833 local_astman_unregister("DialOffHook");
12834 local_astman_unregister("Hangup");
12835 local_astman_unregister("Transfer");
12836 local_astman_unregister("DNDoff");
12837 local_astman_unregister("DNDon");
12838 local_astman_unregister("ShowChannels");
12839 local_astman_unregister("Restart");
12840 ast_channel_unregister(chan_tech);
12841 ast_mutex_lock(&iflock);
12842
12843 p = iflist;
12844 while (p) {
12845 if (p->owner)
12846 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12847 p = p->next;
12848 }
12849 ast_mutex_unlock(&iflock);
12850 ast_mutex_lock(&monlock);
12851 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12852 pthread_cancel(monitor_thread);
12853 pthread_kill(monitor_thread, SIGURG);
12854 pthread_join(monitor_thread, NULL);
12855 }
12856 monitor_thread = AST_PTHREADT_STOP;
12857 ast_mutex_unlock(&monlock);
12858
12859 destroy_all_channels();
12860 #ifdef HAVE_PRI
12861 for (i = 0; i < NUM_SPANS; i++) {
12862 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12863 pthread_join(pris[i].master, NULL);
12864 for (j = 0; j < NUM_DCHANS; j++) {
12865 dahdi_close_pri_fd(&(pris[i]), j);
12866 }
12867 }
12868 #endif
12869 #ifdef HAVE_OPENR2
12870 for (r = 0; r < NUM_SPANS; r++) {
12871 if (r2links[r].protocol_context) {
12872 openr2_context_delete(r2links[r].protocol_context);
12873 }
12874 }
12875 #endif
12876 ast_cond_destroy(&ss_thread_complete);
12877 return 0;
12878 }
12879
12880 static int unload_module(void)
12881 {
12882 #ifdef HAVE_PRI
12883 int y;
12884 for (y = 0; y < NUM_SPANS; y++)
12885 ast_mutex_destroy(&pris[y].lock);
12886 #endif
12887 return __unload_module();
12888 }
12889
12890 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
12891 {
12892 char *c, *chan;
12893 int x, start, finish;
12894 struct dahdi_pvt *tmp;
12895 #ifdef HAVE_PRI
12896 struct dahdi_pri *pri;
12897 int trunkgroup, y;
12898 #endif
12899
12900 if ((reload == 0) && (conf->chan.sig < 0)) {
12901 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12902 return -1;
12903 }
12904
12905 c = ast_strdupa(value);
12906
12907 #ifdef HAVE_PRI
12908 pri = NULL;
12909 if (iscrv) {
12910 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
12911 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12912 return -1;
12913 }
12914 if (trunkgroup < 1) {
12915 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12916 return -1;
12917 }
12918 c += y;
12919 for (y = 0; y < NUM_SPANS; y++) {
12920 if (pris[y].trunkgroup == trunkgroup) {
12921 pri = pris + y;
12922 break;
12923 }
12924 }
12925 if (!pri) {
12926 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12927 return -1;
12928 }
12929 }
12930 #endif
12931
12932 while ((chan = strsep(&c, ","))) {
12933 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
12934
12935 } else if (sscanf(chan, "%30d", &start)) {
12936
12937 finish = start;
12938 } else if (!strcasecmp(chan, "pseudo")) {
12939 finish = start = CHAN_PSEUDO;
12940 if (found_pseudo)
12941 *found_pseudo = 1;
12942 } else {
12943 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12944 return -1;
12945 }
12946 if (finish < start) {
12947 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12948 x = finish;
12949 finish = start;
12950 start = x;
12951 }
12952
12953 for (x = start; x <= finish; x++) {
12954 #ifdef HAVE_PRI
12955 tmp = mkintf(x, conf, pri, reload);
12956 #else
12957 tmp = mkintf(x, conf, NULL, reload);
12958 #endif
12959
12960 if (tmp) {
12961 if (option_verbose > 2) {
12962 #ifdef HAVE_PRI
12963 if (pri)
12964 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12965 else
12966 #endif
12967 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12968 }
12969 } else {
12970 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12971 (reload == 1) ? "reconfigure" : "register", value);
12972 return -1;
12973 }
12974 }
12975 #ifdef HAVE_OPENR2
12976 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
12977 mfcr2_cur_context_index++;
12978 }
12979 #endif
12980 }
12981
12982 return 0;
12983 }
12984
12985
12986
12987 #define MAX_CHANLIST_LEN 80
12988 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
12989 {
12990 struct dahdi_pvt *tmp;
12991 int y;
12992 int found_pseudo = 0;
12993 char dahdichan[MAX_CHANLIST_LEN] = {};
12994
12995 for (; v; v = v->next) {
12996 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
12997 continue;
12998
12999
13000 if (!strcasecmp(v->name, "channel")
13001 #ifdef HAVE_PRI
13002 || !strcasecmp(v->name, "crv")
13003 #endif
13004 ) {
13005 int iscrv;
13006 if (skipchannels)
13007 continue;
13008 iscrv = !strcasecmp(v->name, "crv");
13009 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
13010 return -1;
13011 } else if (!strcasecmp(v->name, "buffers")) {
13012 int res;
13013 char policy[21] = "";
13014
13015 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
13016 if (res != 2) {
13017 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
13018 confp->chan.buf_no = numbufs;
13019 continue;
13020 }
13021 if (confp->chan.buf_no < 0)
13022 confp->chan.buf_no = numbufs;
13023 if (!strcasecmp(policy, "full")) {
13024 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
13025 } else if (!strcasecmp(policy, "immediate")) {
13026 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
13027 } else {
13028 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
13029 }
13030 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
13031 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
13032 if (v->name[0] == 'z' || v->name[0] == 'Z') {
13033 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
13034 }
13035 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
13036 if (ast_true(v->value))
13037 confp->chan.usedistinctiveringdetection = 1;
13038 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
13039 if (ast_true(v->value))
13040 distinctiveringaftercid = 1;
13041 } else if (!strcasecmp(v->name, "dring1context")) {
13042 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
13043 } else if (!strcasecmp(v->name, "dring2context")) {
13044 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
13045 } else if (!strcasecmp(v->name, "dring3context")) {
13046 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
13047 } else if (!strcasecmp(v->name, "dring1")) {
13048 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
13049 } else if (!strcasecmp(v->name, "dring2")) {
13050 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
13051 } else if (!strcasecmp(v->name, "dring3")) {
13052 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
13053 } else if (!strcasecmp(v->name, "usecallerid")) {
13054 confp->chan.use_callerid = ast_true(v->value);
13055 } else if (!strcasecmp(v->name, "cidsignalling")) {
13056 if (!strcasecmp(v->value, "bell"))
13057 confp->chan.cid_signalling = CID_SIG_BELL;
13058 else if (!strcasecmp(v->value, "v23"))
13059 confp->chan.cid_signalling = CID_SIG_V23;
13060 else if (!strcasecmp(v->value, "dtmf"))
13061 confp->chan.cid_signalling = CID_SIG_DTMF;
13062 else if (!strcasecmp(v->value, "smdi"))
13063 confp->chan.cid_signalling = CID_SIG_SMDI;
13064 else if (!strcasecmp(v->value, "v23_jp"))
13065 confp->chan.cid_signalling = CID_SIG_V23_JP;
13066 else if (ast_true(v->value))
13067 confp->chan.cid_signalling = CID_SIG_BELL;
13068 } else if (!strcasecmp(v->name, "cidstart")) {
13069 if (!strcasecmp(v->value, "ring"))
13070 confp->chan.cid_start = CID_START_RING;
13071 else if (!strcasecmp(v->value, "polarity"))
13072 confp->chan.cid_start = CID_START_POLARITY;
13073 else if (!strcasecmp(v->value, "dtmf"))
13074 confp->chan.cid_start = CID_START_DTMF_NOALERT;
13075 else if (ast_true(v->value))
13076 confp->chan.cid_start = CID_START_RING;
13077 } else if (!strcasecmp(v->name, "threewaycalling")) {
13078 confp->chan.threewaycalling = ast_true(v->value);
13079 } else if (!strcasecmp(v->name, "cancallforward")) {
13080 confp->chan.cancallforward = ast_true(v->value);
13081 } else if (!strcasecmp(v->name, "relaxdtmf")) {
13082 if (ast_true(v->value))
13083 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
13084 else
13085 confp->chan.dtmfrelax = 0;
13086 } else if (!strcasecmp(v->name, "mailbox")) {
13087 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
13088 } else if (!strcasecmp(v->name, "hasvoicemail")) {
13089 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
13090 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
13091 }
13092 } else if (!strcasecmp(v->name, "adsi")) {
13093 confp->chan.adsi = ast_true(v->value);
13094 } else if (!strcasecmp(v->name, "usesmdi")) {
13095 confp->chan.use_smdi = ast_true(v->value);
13096 } else if (!strcasecmp(v->name, "smdiport")) {
13097 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
13098 } else if (!strcasecmp(v->name, "transfer")) {
13099 confp->chan.transfer = ast_true(v->value);
13100 } else if (!strcasecmp(v->name, "canpark")) {
13101 confp->chan.canpark = ast_true(v->value);
13102 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
13103 confp->chan.echocanbridged = ast_true(v->value);
13104 } else if (!strcasecmp(v->name, "busydetect")) {
13105 confp->chan.busydetect = ast_true(v->value);
13106 } else if (!strcasecmp(v->name, "busycount")) {
13107 confp->chan.busycount = atoi(v->value);
13108 } else if (!strcasecmp(v->name, "silencethreshold")) {
13109 confp->chan.silencethreshold = atoi(v->value);
13110 } else if (!strcasecmp(v->name, "busycompare")) {
13111 confp->chan.busycompare = ast_true(v->value);
13112 } else if (!strcasecmp(v->name, "busypattern")) {
13113 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
13114 if (count == 1)
13115 confp->chan.busyquietlength = 0;
13116 else if (count < 1)
13117 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
13118 } else if (!strcasecmp(v->name, "busyfuzziness")) {
13119 confp->chan.busyfuzziness = atoi(v->value);
13120 } else if (!strcasecmp(v->name, "callprogress")) {
13121 if (ast_true(v->value))
13122 confp->chan.callprogress |= 1;
13123 else
13124 confp->chan.callprogress &= ~1;
13125 } else if (!strcasecmp(v->name, "faxdetect")) {
13126 if (!strcasecmp(v->value, "incoming")) {
13127 confp->chan.callprogress |= 4;
13128 confp->chan.callprogress &= ~2;
13129 } else if (!strcasecmp(v->value, "outgoing")) {
13130 confp->chan.callprogress &= ~4;
13131 confp->chan.callprogress |= 2;
13132 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
13133 confp->chan.callprogress |= 6;
13134 else
13135 confp->chan.callprogress &= ~6;
13136 } else if (!strcasecmp(v->name, "echocancel")) {
13137 if (!ast_strlen_zero(v->value)) {
13138 y = atoi(v->value);
13139 } else
13140 y = 0;
13141 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
13142 confp->chan.echocancel = y;
13143 else {
13144 confp->chan.echocancel = ast_true(v->value);
13145 if (confp->chan.echocancel)
13146 confp->chan.echocancel=128;
13147 }
13148 } else if (!strcasecmp(v->name, "echotraining")) {
13149 if (sscanf(v->value, "%30d", &y) == 1) {
13150 if ((y < 10) || (y > 4000)) {
13151 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
13152 } else {
13153 confp->chan.echotraining = y;
13154 }
13155 } else if (ast_true(v->value)) {
13156 confp->chan.echotraining = 400;
13157 } else
13158 confp->chan.echotraining = 0;
13159 } else if (!strcasecmp(v->name, "hidecallerid")) {
13160 confp->chan.hidecallerid = ast_true(v->value);
13161 } else if (!strcasecmp(v->name, "hidecalleridname")) {
13162 confp->chan.hidecalleridname = ast_true(v->value);
13163 } else if (!strcasecmp(v->name, "pulsedial")) {
13164 confp->chan.pulse = ast_true(v->value);
13165 } else if (!strcasecmp(v->name, "callreturn")) {
13166 confp->chan.callreturn = ast_true(v->value);
13167 } else if (!strcasecmp(v->name, "callwaiting")) {
13168 confp->chan.callwaiting = ast_true(v->value);
13169 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
13170 confp->chan.callwaitingcallerid = ast_true(v->value);
13171 } else if (!strcasecmp(v->name, "context")) {
13172 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
13173 } else if (!strcasecmp(v->name, "language")) {
13174 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
13175 } else if (!strcasecmp(v->name, "progzone")) {
13176 ast_copy_string(progzone, v->value, sizeof(progzone));
13177 } else if (!strcasecmp(v->name, "mohinterpret")
13178 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
13179 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
13180 } else if (!strcasecmp(v->name, "mohsuggest")) {
13181 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
13182 } else if (!strcasecmp(v->name, "stripmsd")) {
13183 confp->chan.stripmsd = atoi(v->value);
13184 } else if (!strcasecmp(v->name, "jitterbuffers")) {
13185 numbufs = atoi(v->value);
13186 } else if (!strcasecmp(v->name, "group")) {
13187 confp->chan.group = ast_get_group(v->value);
13188 } else if (!strcasecmp(v->name, "callgroup")) {
13189 confp->chan.callgroup = ast_get_group(v->value);
13190 } else if (!strcasecmp(v->name, "pickupgroup")) {
13191 confp->chan.pickupgroup = ast_get_group(v->value);
13192 } else if (!strcasecmp(v->name, "immediate")) {
13193 confp->chan.immediate = ast_true(v->value);
13194 } else if (!strcasecmp(v->name, "transfertobusy")) {
13195 confp->chan.transfertobusy = ast_true(v->value);
13196 } else if (!strcasecmp(v->name, "rxgain")) {
13197 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
13198 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
13199 }
13200 } else if (!strcasecmp(v->name, "txgain")) {
13201 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
13202 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
13203 }
13204 } else if (!strcasecmp(v->name, "tonezone")) {
13205 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
13206 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
13207 }
13208 } else if (!strcasecmp(v->name, "callerid")) {
13209 if (!strcasecmp(v->value, "asreceived")) {
13210 confp->chan.cid_num[0] = '\0';
13211 confp->chan.cid_name[0] = '\0';
13212 } else {
13213 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
13214 }
13215 } else if (!strcasecmp(v->name, "fullname")) {
13216 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
13217 } else if (!strcasecmp(v->name, "cid_number")) {
13218 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
13219 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
13220 confp->chan.dahditrcallerid = ast_true(v->value);
13221 if (strstr(v->name, "zap")) {
13222 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
13223 }
13224 } else if (!strcasecmp(v->name, "restrictcid")) {
13225 confp->chan.restrictcid = ast_true(v->value);
13226 } else if (!strcasecmp(v->name, "usecallingpres")) {
13227 confp->chan.use_callingpres = ast_true(v->value);
13228 } else if (!strcasecmp(v->name, "accountcode")) {
13229 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
13230 } else if (!strcasecmp(v->name, "amaflags")) {
13231 y = ast_cdr_amaflags2int(v->value);
13232 if (y < 0)
13233 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
13234 else
13235 confp->chan.amaflags = y;
13236 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
13237 confp->chan.polarityonanswerdelay = atoi(v->value);
13238 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
13239 confp->chan.answeronpolarityswitch = ast_true(v->value);
13240 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
13241 confp->chan.hanguponpolarityswitch = ast_true(v->value);
13242 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
13243 confp->chan.sendcalleridafter = atoi(v->value);
13244 } else if (reload != 1) {
13245 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
13246 confp->chan.outsigmod = -1;
13247 if (!strcasecmp(v->value, "em")) {
13248 confp->chan.sig = SIG_EM;
13249 } else if (!strcasecmp(v->value, "em_e1")) {
13250 confp->chan.sig = SIG_EM_E1;
13251 } else if (!strcasecmp(v->value, "em_w")) {
13252 confp->chan.sig = SIG_EMWINK;
13253 confp->chan.radio = 0;
13254 } else if (!strcasecmp(v->value, "fxs_ls")) {
13255 confp->chan.sig = SIG_FXSLS;
13256 confp->chan.radio = 0;
13257 } else if (!strcasecmp(v->value, "fxs_gs")) {
13258 confp->chan.sig = SIG_FXSGS;
13259 confp->chan.radio = 0;
13260 } else if (!strcasecmp(v->value, "fxs_ks")) {
13261 confp->chan.sig = SIG_FXSKS;
13262 confp->chan.radio = 0;
13263 } else if (!strcasecmp(v->value, "fxo_ls")) {
13264 confp->chan.sig = SIG_FXOLS;
13265 confp->chan.radio = 0;
13266 } else if (!strcasecmp(v->value, "fxo_gs")) {
13267 confp->chan.sig = SIG_FXOGS;
13268 confp->chan.radio = 0;
13269 } else if (!strcasecmp(v->value, "fxo_ks")) {
13270 confp->chan.sig = SIG_FXOKS;
13271 confp->chan.radio = 0;
13272 } else if (!strcasecmp(v->value, "fxs_rx")) {
13273 confp->chan.sig = SIG_FXSKS;
13274 confp->chan.radio = 1;
13275 } else if (!strcasecmp(v->value, "fxo_rx")) {
13276 confp->chan.sig = SIG_FXOLS;
13277 confp->chan.radio = 1;
13278 } else if (!strcasecmp(v->value, "fxs_tx")) {
13279 confp->chan.sig = SIG_FXSLS;
13280 confp->chan.radio = 1;
13281 } else if (!strcasecmp(v->value, "fxo_tx")) {
13282 confp->chan.sig = SIG_FXOGS;
13283 confp->chan.radio = 1;
13284 } else if (!strcasecmp(v->value, "em_rx")) {
13285 confp->chan.sig = SIG_EM;
13286 confp->chan.radio = 1;
13287 } else if (!strcasecmp(v->value, "em_tx")) {
13288 confp->chan.sig = SIG_EM;
13289 confp->chan.radio = 1;
13290 } else if (!strcasecmp(v->value, "em_rxtx")) {
13291 confp->chan.sig = SIG_EM;
13292 confp->chan.radio = 2;
13293 } else if (!strcasecmp(v->value, "em_txrx")) {
13294 confp->chan.sig = SIG_EM;
13295 confp->chan.radio = 2;
13296 } else if (!strcasecmp(v->value, "sf")) {
13297 confp->chan.sig = SIG_SF;
13298 confp->chan.radio = 0;
13299 } else if (!strcasecmp(v->value, "sf_w")) {
13300 confp->chan.sig = SIG_SFWINK;
13301 confp->chan.radio = 0;
13302 } else if (!strcasecmp(v->value, "sf_featd")) {
13303 confp->chan.sig = SIG_FEATD;
13304 confp->chan.radio = 0;
13305 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13306 confp->chan.sig = SIG_FEATDMF;
13307 confp->chan.radio = 0;
13308 } else if (!strcasecmp(v->value, "sf_featb")) {
13309 confp->chan.sig = SIG_SF_FEATB;
13310 confp->chan.radio = 0;
13311 } else if (!strcasecmp(v->value, "sf")) {
13312 confp->chan.sig = SIG_SF;
13313 confp->chan.radio = 0;
13314 } else if (!strcasecmp(v->value, "sf_rx")) {
13315 confp->chan.sig = SIG_SF;
13316 confp->chan.radio = 1;
13317 } else if (!strcasecmp(v->value, "sf_tx")) {
13318 confp->chan.sig = SIG_SF;
13319 confp->chan.radio = 1;
13320 } else if (!strcasecmp(v->value, "sf_rxtx")) {
13321 confp->chan.sig = SIG_SF;
13322 confp->chan.radio = 2;
13323 } else if (!strcasecmp(v->value, "sf_txrx")) {
13324 confp->chan.sig = SIG_SF;
13325 confp->chan.radio = 2;
13326 } else if (!strcasecmp(v->value, "featd")) {
13327 confp->chan.sig = SIG_FEATD;
13328 confp->chan.radio = 0;
13329 } else if (!strcasecmp(v->value, "featdmf")) {
13330 confp->chan.sig = SIG_FEATDMF;
13331 confp->chan.radio = 0;
13332 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13333 confp->chan.sig = SIG_FEATDMF_TA;
13334 confp->chan.radio = 0;
13335 } else if (!strcasecmp(v->value, "e911")) {
13336 confp->chan.sig = SIG_E911;
13337 confp->chan.radio = 0;
13338 } else if (!strcasecmp(v->value, "fgccama")) {
13339 confp->chan.sig = SIG_FGC_CAMA;
13340 confp->chan.radio = 0;
13341 } else if (!strcasecmp(v->value, "fgccamamf")) {
13342 confp->chan.sig = SIG_FGC_CAMAMF;
13343 confp->chan.radio = 0;
13344 } else if (!strcasecmp(v->value, "featb")) {
13345 confp->chan.sig = SIG_FEATB;
13346 confp->chan.radio = 0;
13347 #ifdef HAVE_OPENR2
13348 } else if (!strcasecmp(v->value, "mfcr2")) {
13349 confp->chan.sig = SIG_MFCR2;
13350 #endif
13351 #ifdef HAVE_PRI
13352 } else if (!strcasecmp(v->value, "pri_net")) {
13353 confp->chan.radio = 0;
13354 confp->chan.sig = SIG_PRI;
13355 confp->pri.nodetype = PRI_NETWORK;
13356 } else if (!strcasecmp(v->value, "pri_cpe")) {
13357 confp->chan.sig = SIG_PRI;
13358 confp->chan.radio = 0;
13359 confp->pri.nodetype = PRI_CPE;
13360 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
13361 confp->chan.sig = SIG_GR303FXOKS;
13362 confp->chan.radio = 0;
13363 confp->pri.nodetype = PRI_NETWORK;
13364 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
13365 confp->chan.sig = SIG_GR303FXSKS;
13366 confp->chan.radio = 0;
13367 confp->pri.nodetype = PRI_CPE;
13368 #endif
13369 } else {
13370 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13371 }
13372 } else if (!strcasecmp(v->name, "outsignalling")) {
13373 if (!strcasecmp(v->value, "em")) {
13374 confp->chan.outsigmod = SIG_EM;
13375 } else if (!strcasecmp(v->value, "em_e1")) {
13376 confp->chan.outsigmod = SIG_EM_E1;
13377 } else if (!strcasecmp(v->value, "em_w")) {
13378 confp->chan.outsigmod = SIG_EMWINK;
13379 } else if (!strcasecmp(v->value, "sf")) {
13380 confp->chan.outsigmod = SIG_SF;
13381 } else if (!strcasecmp(v->value, "sf_w")) {
13382 confp->chan.outsigmod = SIG_SFWINK;
13383 } else if (!strcasecmp(v->value, "sf_featd")) {
13384 confp->chan.outsigmod = SIG_FEATD;
13385 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13386 confp->chan.outsigmod = SIG_FEATDMF;
13387 } else if (!strcasecmp(v->value, "sf_featb")) {
13388 confp->chan.outsigmod = SIG_SF_FEATB;
13389 } else if (!strcasecmp(v->value, "sf")) {
13390 confp->chan.outsigmod = SIG_SF;
13391 } else if (!strcasecmp(v->value, "featd")) {
13392 confp->chan.outsigmod = SIG_FEATD;
13393 } else if (!strcasecmp(v->value, "featdmf")) {
13394 confp->chan.outsigmod = SIG_FEATDMF;
13395 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13396 confp->chan.outsigmod = SIG_FEATDMF_TA;
13397 } else if (!strcasecmp(v->value, "e911")) {
13398 confp->chan.outsigmod = SIG_E911;
13399 } else if (!strcasecmp(v->value, "fgccama")) {
13400 confp->chan.outsigmod = SIG_FGC_CAMA;
13401 } else if (!strcasecmp(v->value, "fgccamamf")) {
13402 confp->chan.outsigmod = SIG_FGC_CAMAMF;
13403 } else if (!strcasecmp(v->value, "featb")) {
13404 confp->chan.outsigmod = SIG_FEATB;
13405 } else {
13406 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13407 }
13408 #ifdef HAVE_PRI
13409 } else if (!strcasecmp(v->name, "pridialplan")) {
13410 if (!strcasecmp(v->value, "national")) {
13411 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
13412 } else if (!strcasecmp(v->value, "unknown")) {
13413 confp->pri.dialplan = PRI_UNKNOWN + 1;
13414 } else if (!strcasecmp(v->value, "private")) {
13415 confp->pri.dialplan = PRI_PRIVATE + 1;
13416 } else if (!strcasecmp(v->value, "international")) {
13417 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
13418 } else if (!strcasecmp(v->value, "local")) {
13419 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
13420 } else if (!strcasecmp(v->value, "dynamic")) {
13421 confp->pri.dialplan = -1;
13422 } else {
13423 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13424 }
13425 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
13426 if (!strcasecmp(v->value, "national")) {
13427 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
13428 } else if (!strcasecmp(v->value, "unknown")) {
13429 confp->pri.localdialplan = PRI_UNKNOWN + 1;
13430 } else if (!strcasecmp(v->value, "private")) {
13431 confp->pri.localdialplan = PRI_PRIVATE + 1;
13432 } else if (!strcasecmp(v->value, "international")) {
13433 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
13434 } else if (!strcasecmp(v->value, "local")) {
13435 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
13436 } else if (!strcasecmp(v->value, "dynamic")) {
13437 confp->pri.localdialplan = -1;
13438 } else {
13439 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13440 }
13441 } else if (!strcasecmp(v->name, "switchtype")) {
13442 if (!strcasecmp(v->value, "national"))
13443 confp->pri.switchtype = PRI_SWITCH_NI2;
13444 else if (!strcasecmp(v->value, "ni1"))
13445 confp->pri.switchtype = PRI_SWITCH_NI1;
13446 else if (!strcasecmp(v->value, "dms100"))
13447 confp->pri.switchtype = PRI_SWITCH_DMS100;
13448 else if (!strcasecmp(v->value, "4ess"))
13449 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
13450 else if (!strcasecmp(v->value, "5ess"))
13451 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
13452 else if (!strcasecmp(v->value, "euroisdn"))
13453 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
13454 else if (!strcasecmp(v->value, "qsig"))
13455 confp->pri.switchtype = PRI_SWITCH_QSIG;
13456 else {
13457 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
13458 return -1;
13459 }
13460 } else if (!strcasecmp(v->name, "nsf")) {
13461 if (!strcasecmp(v->value, "sdn"))
13462 confp->pri.nsf = PRI_NSF_SDN;
13463 else if (!strcasecmp(v->value, "megacom"))
13464 confp->pri.nsf = PRI_NSF_MEGACOM;
13465 else if (!strcasecmp(v->value, "tollfreemegacom"))
13466 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
13467 else if (!strcasecmp(v->value, "accunet"))
13468 confp->pri.nsf = PRI_NSF_ACCUNET;
13469 else if (!strcasecmp(v->value, "none"))
13470 confp->pri.nsf = PRI_NSF_NONE;
13471 else {
13472 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
13473 confp->pri.nsf = PRI_NSF_NONE;
13474 }
13475 } else if (!strcasecmp(v->name, "priindication")) {
13476 if (!strcasecmp(v->value, "outofband"))
13477 confp->chan.priindication_oob = 1;
13478 else if (!strcasecmp(v->value, "inband"))
13479 confp->chan.priindication_oob = 0;
13480 else
13481 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
13482 v->value, v->lineno);
13483 } else if (!strcasecmp(v->name, "priexclusive")) {
13484 confp->chan.priexclusive = ast_true(v->value);
13485 } else if (!strcasecmp(v->name, "internationalprefix")) {
13486 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
13487 } else if (!strcasecmp(v->name, "nationalprefix")) {
13488 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
13489 } else if (!strcasecmp(v->name, "localprefix")) {
13490 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
13491 } else if (!strcasecmp(v->name, "privateprefix")) {
13492 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
13493 } else if (!strcasecmp(v->name, "unknownprefix")) {
13494 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
13495 } else if (!strcasecmp(v->name, "resetinterval")) {
13496 if (!strcasecmp(v->value, "never"))
13497 confp->pri.resetinterval = -1;
13498 else if (atoi(v->value) >= 60)
13499 confp->pri.resetinterval = atoi(v->value);
13500 else
13501 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
13502 v->value, v->lineno);
13503 } else if (!strcasecmp(v->name, "minunused")) {
13504 confp->pri.minunused = atoi(v->value);
13505 } else if (!strcasecmp(v->name, "minidle")) {
13506 confp->pri.minidle = atoi(v->value);
13507 } else if (!strcasecmp(v->name, "idleext")) {
13508 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
13509 } else if (!strcasecmp(v->name, "idledial")) {
13510 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
13511 } else if (!strcasecmp(v->name, "overlapdial")) {
13512 if (ast_true(v->value)) {
13513 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13514 } else if (!strcasecmp(v->value, "incoming")) {
13515 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
13516 } else if (!strcasecmp(v->value, "outgoing")) {
13517 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
13518 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
13519 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13520 } else {
13521 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
13522 }
13523 #ifdef HAVE_PRI_INBANDDISCONNECT
13524 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
13525 confp->pri.inbanddisconnect = ast_true(v->value);
13526 #endif
13527 } else if (!strcasecmp(v->name, "pritimer")) {
13528 #ifdef PRI_GETSET_TIMERS
13529 char tmp[20];
13530 char *timerc;
13531 char *c;
13532 int timer;
13533 int timeridx;
13534
13535 ast_copy_string(tmp, v->value, sizeof(tmp));
13536 c = tmp;
13537 timerc = strsep(&c, ",");
13538 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
13539 timeridx = pri_timer2idx(timerc);
13540 timer = atoi(c);
13541 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
13542 ast_log(LOG_WARNING,
13543 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
13544 v->lineno);
13545 } else if (!timer) {
13546 ast_log(LOG_WARNING,
13547 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
13548 c, timerc, v->lineno);
13549 } else {
13550 pritimers[timeridx] = timer;
13551 }
13552 } else {
13553 ast_log(LOG_WARNING,
13554 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
13555 v->value, v->lineno);
13556 }
13557 #endif
13558 } else if (!strcasecmp(v->name, "facilityenable")) {
13559 confp->pri.facilityenable = ast_true(v->value);
13560 #endif
13561 #ifdef HAVE_OPENR2
13562 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
13563 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
13564 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);
13565 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
13566 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
13567 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
13568 mfcr2_cur_variant = openr2_proto_get_variant(v->value);
13569 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
13570 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
13571 }
13572 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
13573 mfcr2_cur_mfback_timeout = atoi(v->value);
13574 if (!mfcr2_cur_mfback_timeout) {
13575 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
13576 mfcr2_cur_mfback_timeout = -1;
13577 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
13578 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
13579 }
13580 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
13581 mfcr2_cur_metering_pulse_timeout = atoi(v->value);
13582 if (mfcr2_cur_metering_pulse_timeout > 500) {
13583 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
13584 }
13585 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13586 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
13587 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
13588 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
13589 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
13590 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
13591 mfcr2_cur_dtmf_time_on = atoi(v->value);
13592 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
13593 mfcr2_cur_dtmf_time_off = atoi(v->value);
13594 #endif
13595 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
13596 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
13597 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
13598 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
13599 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
13600 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
13601 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
13602 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
13603 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
13604 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
13605 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
13606 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
13607 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
13608 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
13609 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
13610 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
13611 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
13612 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
13613 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
13614 mfcr2_cur_max_ani = atoi(v->value);
13615 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
13616 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
13617 }
13618 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
13619 mfcr2_cur_max_dnis = atoi(v->value);
13620 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
13621 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
13622 }
13623 } else if (!strcasecmp(v->name, "mfcr2_category")) {
13624 mfcr2_cur_category = openr2_proto_get_category(v->value);
13625 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
13626 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
13627 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
13628 v->value, v->lineno);
13629 }
13630 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
13631 openr2_log_level_t tmplevel;
13632 char *toklevel = NULL;
13633 char *saveptr = NULL;
13634 char *logval = ast_strdupa(v->value);
13635 toklevel = strtok_r(logval, ",", &saveptr);
13636 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13637 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
13638 } else if (OR2_LOG_NOTHING == tmplevel) {
13639 mfcr2_cur_loglevel = tmplevel;
13640 } else {
13641 mfcr2_cur_loglevel |= tmplevel;
13642 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
13643 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13644 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
13645 continue;
13646 }
13647 mfcr2_cur_loglevel |= tmplevel;
13648 }
13649 }
13650 #endif
13651
13652 } else if (!strcasecmp(v->name, "cadence")) {
13653
13654 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
13655 int i;
13656 struct dahdi_ring_cadence new_cadence;
13657 int cid_location = -1;
13658 int firstcadencepos = 0;
13659 char original_args[80];
13660 int cadence_is_ok = 1;
13661
13662 ast_copy_string(original_args, v->value, sizeof(original_args));
13663
13664 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]);
13665
13666
13667 if (element_count % 2 == 1) {
13668 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
13669 cadence_is_ok = 0;
13670 }
13671
13672
13673 for (i = 0; i < element_count; i++) {
13674 if (c[i] == 0) {
13675 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
13676 cadence_is_ok = 0;
13677 break;
13678 } else if (c[i] < 0) {
13679 if (i % 2 == 1) {
13680
13681 if (cid_location == -1) {
13682 cid_location = i;
13683 c[i] *= -1;
13684 } else {
13685 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
13686 cadence_is_ok = 0;
13687 break;
13688 }
13689 } else {
13690 if (firstcadencepos == 0) {
13691 firstcadencepos = i;
13692
13693 } else {
13694 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
13695 cadence_is_ok = 0;
13696 break;
13697 }
13698 }
13699 }
13700 }
13701
13702
13703 for (i = 0; i < 16; i++) {
13704 new_cadence.ringcadence[i] = c[i];
13705 }
13706
13707 if (cadence_is_ok) {
13708
13709 if (element_count < 2) {
13710 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
13711 } else {
13712 if (cid_location == -1) {
13713
13714 cid_location = 1;
13715 } else {
13716
13717 cid_location = (cid_location + 1) / 2;
13718 }
13719
13720 if (!user_has_defined_cadences++)
13721
13722 num_cadence = 0;
13723 if ((num_cadence+1) >= NUM_CADENCE_MAX)
13724 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
13725 else {
13726 cadences[num_cadence] = new_cadence;
13727 cidrings[num_cadence++] = cid_location;
13728 if (option_verbose > 2)
13729 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
13730 }
13731 }
13732 }
13733 } else if (!strcasecmp(v->name, "ringtimeout")) {
13734 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
13735 } else if (!strcasecmp(v->name, "prewink")) {
13736 confp->timing.prewinktime = atoi(v->value);
13737 } else if (!strcasecmp(v->name, "preflash")) {
13738 confp->timing.preflashtime = atoi(v->value);
13739 } else if (!strcasecmp(v->name, "wink")) {
13740 confp->timing.winktime = atoi(v->value);
13741 } else if (!strcasecmp(v->name, "flash")) {
13742 confp->timing.flashtime = atoi(v->value);
13743 } else if (!strcasecmp(v->name, "start")) {
13744 confp->timing.starttime = atoi(v->value);
13745 } else if (!strcasecmp(v->name, "rxwink")) {
13746 confp->timing.rxwinktime = atoi(v->value);
13747 } else if (!strcasecmp(v->name, "rxflash")) {
13748 confp->timing.rxflashtime = atoi(v->value);
13749 } else if (!strcasecmp(v->name, "debounce")) {
13750 confp->timing.debouncetime = atoi(v->value);
13751 } else if (!strcasecmp(v->name, "toneduration")) {
13752 int toneduration;
13753 int ctlfd;
13754 int res;
13755 struct dahdi_dialparams dps;
13756
13757 ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
13758
13759 if (ctlfd == -1) {
13760 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
13761 return -1;
13762 }
13763
13764 toneduration = atoi(v->value);
13765 if (toneduration > -1) {
13766 memset(&dps, 0, sizeof(dps));
13767
13768 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
13769 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
13770 if (res < 0) {
13771 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
13772 return -1;
13773 }
13774 }
13775 close(ctlfd);
13776 } else if (!strcasecmp(v->name, "defaultcic")) {
13777 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
13778 } else if (!strcasecmp(v->name, "defaultozz")) {
13779 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
13780 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
13781 dtmfcid_level = atoi(v->value);
13782 }
13783 } else if (!skipchannels)
13784 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
13785 }
13786 if (dahdichan[0]) {
13787
13788
13789 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
13790 return -1;
13791 }
13792 }
13793
13794
13795 if (!found_pseudo && reload != 1) {
13796
13797
13798
13799
13800 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13801
13802 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
13803
13804 if (tmp) {
13805 if (option_verbose > 2)
13806 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
13807 } else {
13808 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
13809 }
13810 }
13811 return 0;
13812 }
13813
13814 static int setup_dahdi(int reload)
13815 {
13816 struct ast_config *cfg;
13817 struct ast_variable *v;
13818 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13819 int res;
13820
13821 #ifdef HAVE_PRI
13822 char *c;
13823 int spanno;
13824 int i, x;
13825 int logicalspan;
13826 int trunkgroup;
13827 int dchannels[NUM_DCHANS];
13828 #endif
13829
13830 #ifdef HAVE_ZAPTEL
13831 int load_from_zapata_conf = 1;
13832 #else
13833 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
13834 #endif
13835
13836 if (load_from_zapata_conf) {
13837 if (!(cfg = ast_config_load("zapata.conf"))) {
13838 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13839 return 0;
13840 }
13841 } else {
13842 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13843 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13844 return 0;
13845 }
13846 }
13847
13848
13849 ast_mutex_lock(&iflock);
13850 #ifdef HAVE_PRI
13851 if (reload != 1) {
13852
13853 v = ast_variable_browse(cfg, "trunkgroups");
13854 while (v) {
13855 if (!strcasecmp(v->name, "trunkgroup")) {
13856 trunkgroup = atoi(v->value);
13857 if (trunkgroup > 0) {
13858 if ((c = strchr(v->value, ','))) {
13859 i = 0;
13860 memset(dchannels, 0, sizeof(dchannels));
13861 while (c && (i < NUM_DCHANS)) {
13862 dchannels[i] = atoi(c + 1);
13863 if (dchannels[i] < 0) {
13864 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);
13865 } else
13866 i++;
13867 c = strchr(c + 1, ',');
13868 }
13869 if (i) {
13870 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13871 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);
13872 } else if (option_verbose > 1)
13873 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");
13874 } else
13875 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13876 } else
13877 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13878 } else
13879 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13880 } else if (!strcasecmp(v->name, "spanmap")) {
13881 spanno = atoi(v->value);
13882 if (spanno > 0) {
13883 if ((c = strchr(v->value, ','))) {
13884 trunkgroup = atoi(c + 1);
13885 if (trunkgroup > 0) {
13886 if ((c = strchr(c + 1, ',')))
13887 logicalspan = atoi(c + 1);
13888 else
13889 logicalspan = 0;
13890 if (logicalspan >= 0) {
13891 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13892 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13893 } else if (option_verbose > 1)
13894 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13895 } else
13896 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);
13897 } else
13898 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13899 } else
13900 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13901 } else
13902 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13903 } else {
13904 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13905 }
13906 v = v->next;
13907 }
13908 }
13909 #endif
13910
13911
13912 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13913
13914 v = ast_variable_browse(cfg, "channels");
13915 res = process_dahdi(&conf, "", v, reload, 0);
13916 ast_mutex_unlock(&iflock);
13917 ast_config_destroy(cfg);
13918 if (res)
13919 return res;
13920 cfg = ast_config_load("users.conf");
13921 if (cfg) {
13922 char *cat;
13923 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13924 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13925 if (!strcasecmp(cat, "general"))
13926 continue;
13927 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
13928 struct dahdi_chan_conf sect_conf;
13929 memcpy(§_conf, &conf, sizeof(sect_conf));
13930
13931 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13932 }
13933 }
13934 ast_config_destroy(cfg);
13935 }
13936 #ifdef HAVE_PRI
13937 if (reload != 1) {
13938 for (x = 0; x < NUM_SPANS; x++) {
13939 if (pris[x].pvts[0]) {
13940 if (start_pri(pris + x)) {
13941 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13942 return -1;
13943 } else if (option_verbose > 1)
13944 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13945 }
13946 }
13947 }
13948 #endif
13949 #ifdef HAVE_OPENR2
13950 if (reload != 1) {
13951 int x;
13952 for (x = 0; x < NUM_SPANS; x++) {
13953 if (r2links[x].protocol_context) {
13954 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
13955 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
13956 return -1;
13957 } else {
13958 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
13959 }
13960 }
13961 }
13962 }
13963 #endif
13964
13965 restart_monitor();
13966 return 0;
13967 }
13968
13969 #define local_astman_register(a, b, c, d) do { \
13970 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13971 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
13972 } \
13973 ast_manager_register("Zap" a, b, zap_ ## c, d); \
13974 } while (0)
13975
13976 static int load_module(void)
13977 {
13978 int res;
13979
13980 #ifdef HAVE_PRI
13981 int y,i;
13982 memset(pris, 0, sizeof(pris));
13983 for (y = 0; y < NUM_SPANS; y++) {
13984 ast_mutex_init(&pris[y].lock);
13985 pris[y].offset = -1;
13986 pris[y].master = AST_PTHREADT_NULL;
13987 for (i = 0; i < NUM_DCHANS; i++)
13988 pris[y].fds[i] = -1;
13989 }
13990 pri_set_error(dahdi_pri_error);
13991 pri_set_message(dahdi_pri_message);
13992 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13993 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13994 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13995 }
13996 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13997 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13998 #endif
13999 #ifdef HAVE_OPENR2
14000 init_mfcr2_globals();
14001 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
14002 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
14003 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
14004 }
14005 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
14006 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
14007 #endif
14008 if ((res = setup_dahdi(0))) {
14009 return AST_MODULE_LOAD_DECLINE;
14010 }
14011 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
14012 chan_tech = &dahdi_tech;
14013 } else {
14014 chan_tech = &zap_tech;
14015 }
14016 if (ast_channel_register(chan_tech)) {
14017 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
14018 __unload_module();
14019 return -1;
14020 }
14021 #ifdef HAVE_PRI
14022 ast_string_field_init(&inuse, 16);
14023 ast_string_field_set(&inuse, name, "GR-303InUse");
14024 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
14025 #endif
14026 #ifdef HAVE_OPENR2
14027 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
14028 #endif
14029 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14030
14031 memset(round_robin, 0, sizeof(round_robin));
14032 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
14033 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
14034 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
14035 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
14036 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
14037 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
14038 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
14039
14040 ast_cond_init(&ss_thread_complete, NULL);
14041
14042 return res;
14043 }
14044
14045 static int dahdi_sendtext(struct ast_channel *c, const char *text)
14046 {
14047 #define END_SILENCE_LEN 400
14048 #define HEADER_MS 50
14049 #define TRAILER_MS 5
14050 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14051 #define ASCII_BYTES_PER_CHAR 80
14052
14053 unsigned char *buf,*mybuf;
14054 struct dahdi_pvt *p = c->tech_pvt;
14055 struct pollfd fds[1];
14056 int size,res,fd,len,x;
14057 int bytes=0;
14058
14059 float cr = 1.0;
14060 float ci = 0.0;
14061 float scont = 0.0;
14062 int index;
14063
14064 index = dahdi_get_index(c, p, 0);
14065 if (index < 0) {
14066 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
14067 return -1;
14068 }
14069 if (!text[0]) return(0);
14070 if ((!p->tdd) && (!p->mate)) return(0);
14071 if (p->mate)
14072 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
14073 else
14074 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
14075 if (!buf)
14076 return -1;
14077 mybuf = buf;
14078 if (p->mate) {
14079 int codec = AST_LAW(p);
14080 for (x = 0; x < HEADER_MS; x++) {
14081 PUT_CLID_MARKMS;
14082 }
14083
14084 for (x = 0; text[x]; x++) {
14085 PUT_CLID(text[x]);
14086 }
14087 for (x = 0; x < TRAILER_MS; x++) {
14088 PUT_CLID_MARKMS;
14089 }
14090 len = bytes;
14091 buf = mybuf;
14092 } else {
14093 len = tdd_generate(p->tdd, buf, text);
14094 if (len < 1) {
14095 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
14096 free(mybuf);
14097 return -1;
14098 }
14099 }
14100 memset(buf + len, 0x7f, END_SILENCE_LEN);
14101 len += END_SILENCE_LEN;
14102 fd = p->subs[index].dfd;
14103 while (len) {
14104 if (ast_check_hangup(c)) {
14105 free(mybuf);
14106 return -1;
14107 }
14108 size = len;
14109 if (size > READ_SIZE)
14110 size = READ_SIZE;
14111 fds[0].fd = fd;
14112 fds[0].events = POLLOUT | POLLPRI;
14113 fds[0].revents = 0;
14114 res = poll(fds, 1, -1);
14115 if (!res) {
14116 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
14117 continue;
14118 }
14119
14120 if (fds[0].revents & POLLPRI) {
14121 ast_free(mybuf);
14122 return -1;
14123 }
14124 if (!(fds[0].revents & POLLOUT)) {
14125 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
14126 continue;
14127 }
14128 res = write(fd, buf, size);
14129 if (res != size) {
14130 if (res == -1) {
14131 free(mybuf);
14132 return -1;
14133 }
14134 if (option_debug)
14135 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14136 break;
14137 }
14138 len -= size;
14139 buf += size;
14140 }
14141 free(mybuf);
14142 return(0);
14143 }
14144
14145
14146 static int reload(void)
14147 {
14148 int res = 0;
14149
14150 res = setup_dahdi(1);
14151 if (res) {
14152 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14153 return -1;
14154 }
14155 return 0;
14156 }
14157
14158
14159
14160
14161
14162 #ifdef HAVE_PRI
14163 #define tdesc "DAHDI Telephony w/PRI"
14164 #else
14165 #define tdesc "DAHDI Telephony"
14166 #endif
14167
14168 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
14169 .load = load_module,
14170 .unload = unload_module,
14171 .reload = reload,
14172 );
14173
14174