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 (res < 0) {
06100 f = NULL;
06101 if (res == -1) {
06102 if (errno == EAGAIN) {
06103
06104 ast_mutex_unlock(&p->lock);
06105 return &p->subs[index].f;
06106 } else if (errno == ELAST) {
06107 f = __dahdi_exception(ast);
06108 } else
06109 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06110 }
06111 ast_mutex_unlock(&p->lock);
06112 return f;
06113 }
06114 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06115 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06116 f = __dahdi_exception(ast);
06117 ast_mutex_unlock(&p->lock);
06118 return f;
06119 }
06120 if (p->tdd) {
06121 int c;
06122
06123 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06124 if (c < 0) {
06125 ast_log(LOG_DEBUG,"tdd_feed failed\n");
06126 ast_mutex_unlock(&p->lock);
06127 return NULL;
06128 }
06129 if (c) {
06130 p->subs[index].f.subclass = 0;
06131 p->subs[index].f.frametype = AST_FRAME_TEXT;
06132 p->subs[index].f.mallocd = 0;
06133 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06134 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06135 p->subs[index].f.datalen = 1;
06136 *((char *) p->subs[index].f.data) = c;
06137 ast_mutex_unlock(&p->lock);
06138 return &p->subs[index].f;
06139 }
06140 }
06141
06142 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06143 p->callwaitingrepeat--;
06144 }
06145 if (p->cidcwexpire)
06146 p->cidcwexpire--;
06147
06148 if (p->callwaitingrepeat == 1) {
06149 p->callwaitrings++;
06150 dahdi_callwait(ast);
06151 }
06152
06153 if (p->cidcwexpire == 1) {
06154 if (option_verbose > 2)
06155 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06156 restore_conference(p);
06157 }
06158 if (p->subs[index].linear) {
06159 p->subs[index].f.datalen = READ_SIZE * 2;
06160 } else
06161 p->subs[index].f.datalen = READ_SIZE;
06162
06163
06164 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06165 send_callerid(p);
06166 }
06167
06168 p->subs[index].f.frametype = AST_FRAME_VOICE;
06169 p->subs[index].f.subclass = ast->rawreadformat;
06170 p->subs[index].f.samples = READ_SIZE;
06171 p->subs[index].f.mallocd = 0;
06172 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06173 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06174 #if 0
06175 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06176 #endif
06177 if (p->dialing ||
06178 (index && (ast->_state != AST_STATE_UP)) ||
06179 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
06180 ) {
06181
06182
06183 p->subs[index].f.frametype = AST_FRAME_NULL;
06184 p->subs[index].f.subclass = 0;
06185 p->subs[index].f.samples = 0;
06186 p->subs[index].f.mallocd = 0;
06187 p->subs[index].f.offset = 0;
06188 p->subs[index].f.data = NULL;
06189 p->subs[index].f.datalen= 0;
06190 }
06191 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
06192
06193 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06194 if (f) {
06195 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06196 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06197
06198
06199 f = NULL;
06200 }
06201 } else if (f->frametype == AST_FRAME_DTMF) {
06202 #ifdef HAVE_PRI
06203 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial &&
06204 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
06205 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06206
06207 f->frametype = AST_FRAME_NULL;
06208 f->subclass = 0;
06209 }
06210 #endif
06211
06212 p->pulsedial = 0;
06213 }
06214 }
06215 } else
06216 f = &p->subs[index].f;
06217
06218 if (f && (f->frametype == AST_FRAME_DTMF))
06219 dahdi_handle_dtmfup(ast, index, &f);
06220
06221
06222 if (p->fake_event)
06223 ast_set_flag(ast, AST_FLAG_EXCEPTION);
06224
06225 ast_mutex_unlock(&p->lock);
06226 return f;
06227 }
06228
06229 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
06230 {
06231 int sent=0;
06232 int size;
06233 int res;
06234 int fd;
06235 fd = p->subs[index].dfd;
06236 while (len) {
06237 size = len;
06238 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06239 size = (linear ? READ_SIZE * 2 : READ_SIZE);
06240 res = write(fd, buf, size);
06241 if (res != size) {
06242 if (option_debug)
06243 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06244 return sent;
06245 }
06246 len -= size;
06247 buf += size;
06248 }
06249 return sent;
06250 }
06251
06252 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06253 {
06254 struct dahdi_pvt *p = ast->tech_pvt;
06255 int res;
06256 int index;
06257 index = dahdi_get_index(ast, p, 0);
06258 if (index < 0) {
06259 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06260 return -1;
06261 }
06262
06263 #if 0
06264 #ifdef HAVE_PRI
06265 ast_mutex_lock(&p->lock);
06266 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06267 if (p->pri->pri) {
06268 if (!pri_grab(p, p->pri)) {
06269 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06270 pri_rel(p->pri);
06271 } else
06272 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06273 }
06274 p->proceeding=1;
06275 }
06276 ast_mutex_unlock(&p->lock);
06277 #endif
06278 #endif
06279
06280 if (frame->frametype != AST_FRAME_VOICE) {
06281 if (frame->frametype != AST_FRAME_IMAGE)
06282 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06283 return 0;
06284 }
06285 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06286 (frame->subclass != AST_FORMAT_ULAW) &&
06287 (frame->subclass != AST_FORMAT_ALAW)) {
06288 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06289 return -1;
06290 }
06291 if (p->dialing) {
06292 if (option_debug)
06293 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06294 return 0;
06295 }
06296 if (!p->owner) {
06297 if (option_debug)
06298 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06299 return 0;
06300 }
06301 if (p->cidspill) {
06302 if (option_debug)
06303 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
06304 return 0;
06305 }
06306
06307 if (!frame->data || !frame->datalen)
06308 return 0;
06309
06310 if (frame->subclass == AST_FORMAT_SLINEAR) {
06311 if (!p->subs[index].linear) {
06312 p->subs[index].linear = 1;
06313 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06314 if (res)
06315 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06316 }
06317 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06318 } else {
06319
06320 if (p->subs[index].linear) {
06321 p->subs[index].linear = 0;
06322 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06323 if (res)
06324 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06325 }
06326 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06327 }
06328 if (res < 0) {
06329 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06330 return -1;
06331 }
06332 return 0;
06333 }
06334
06335 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06336 {
06337 struct dahdi_pvt *p = chan->tech_pvt;
06338 int res=-1;
06339 int index;
06340 int func = DAHDI_FLASH;
06341 ast_mutex_lock(&p->lock);
06342 index = dahdi_get_index(chan, p, 0);
06343 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06344 #ifdef HAVE_OPENR2
06345 if (p->mfcr2 && !p->mfcr2_call_accepted) {
06346 ast_mutex_unlock(&p->lock);
06347
06348
06349 return 0;
06350 }
06351 #endif
06352 if (index == SUB_REAL) {
06353 switch (condition) {
06354 case AST_CONTROL_BUSY:
06355 #ifdef HAVE_PRI
06356 if (p->priindication_oob && p->sig == SIG_PRI) {
06357 chan->hangupcause = AST_CAUSE_USER_BUSY;
06358 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06359 res = 0;
06360 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06361 if (p->pri->pri) {
06362 if (!pri_grab(p, p->pri)) {
06363 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06364 pri_rel(p->pri);
06365 }
06366 else
06367 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06368 }
06369 p->progress = 1;
06370 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06371 } else
06372 #endif
06373 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06374 break;
06375 case AST_CONTROL_RINGING:
06376 #ifdef HAVE_PRI
06377 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06378 if (p->pri->pri) {
06379 if (!pri_grab(p, p->pri)) {
06380 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06381 pri_rel(p->pri);
06382 }
06383 else
06384 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06385 }
06386 p->alerting = 1;
06387 }
06388 #endif
06389 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06390 if (chan->_state != AST_STATE_UP) {
06391 if ((chan->_state != AST_STATE_RING) ||
06392 ((p->sig != SIG_FXSKS) &&
06393 (p->sig != SIG_FXSLS) &&
06394 (p->sig != SIG_FXSGS)))
06395 ast_setstate(chan, AST_STATE_RINGING);
06396 }
06397 break;
06398 case AST_CONTROL_PROCEEDING:
06399 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06400 #ifdef HAVE_PRI
06401 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06402 if (p->pri->pri) {
06403 if (!pri_grab(p, p->pri)) {
06404 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06405 pri_rel(p->pri);
06406 }
06407 else
06408 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06409 }
06410 p->proceeding = 1;
06411 p->dialing = 0;
06412 }
06413 #endif
06414
06415 res = 0;
06416 break;
06417 case AST_CONTROL_PROGRESS:
06418 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06419 #ifdef HAVE_PRI
06420 p->digital = 0;
06421 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06422 if (p->pri->pri) {
06423 if (!pri_grab(p, p->pri)) {
06424 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06425 pri_rel(p->pri);
06426 }
06427 else
06428 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06429 }
06430 p->progress = 1;
06431 }
06432 #endif
06433
06434 res = 0;
06435 break;
06436 case AST_CONTROL_CONGESTION:
06437 chan->hangupcause = AST_CAUSE_CONGESTION;
06438 #ifdef HAVE_PRI
06439 if (p->priindication_oob && p->sig == SIG_PRI) {
06440 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06441 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06442 res = 0;
06443 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06444 if (p->pri) {
06445 if (!pri_grab(p, p->pri)) {
06446 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06447 pri_rel(p->pri);
06448 } else
06449 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06450 }
06451 p->progress = 1;
06452 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06453 } else
06454 #endif
06455 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06456 break;
06457 case AST_CONTROL_HOLD:
06458 #ifdef HAVE_PRI
06459 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06460 if (!pri_grab(p, p->pri)) {
06461 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06462 pri_rel(p->pri);
06463 } else
06464 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06465 } else
06466 #endif
06467 ast_moh_start(chan, data, p->mohinterpret);
06468 break;
06469 case AST_CONTROL_UNHOLD:
06470 #ifdef HAVE_PRI
06471 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06472 if (!pri_grab(p, p->pri)) {
06473 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06474 pri_rel(p->pri);
06475 } else
06476 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06477 } else
06478 #endif
06479 ast_moh_stop(chan);
06480 break;
06481 case AST_CONTROL_RADIO_KEY:
06482 if (p->radio)
06483 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06484 res = 0;
06485 break;
06486 case AST_CONTROL_RADIO_UNKEY:
06487 if (p->radio)
06488 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06489 res = 0;
06490 break;
06491 case AST_CONTROL_FLASH:
06492
06493 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06494
06495 p->dop.dialstr[0] = '\0';
06496 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06497 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06498 chan->name, strerror(errno));
06499 } else
06500 res = 0;
06501 } else
06502 res = 0;
06503 break;
06504 case AST_CONTROL_SRCUPDATE:
06505 res = 0;
06506 break;
06507 case -1:
06508 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06509 break;
06510 }
06511 } else
06512 res = 0;
06513 ast_mutex_unlock(&p->lock);
06514 return res;
06515 }
06516
06517 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
06518 {
06519 struct ast_channel *tmp;
06520 int deflaw;
06521 int res;
06522 int x,y;
06523 int features;
06524 char *b2 = NULL;
06525 struct dahdi_params ps;
06526 char chanprefix[*dahdi_chan_name_len + 4];
06527
06528 if (i->subs[index].owner) {
06529 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
06530 return NULL;
06531 }
06532 y = 1;
06533 do {
06534 if (b2)
06535 free(b2);
06536 #ifdef HAVE_PRI
06537 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06538 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06539 else
06540 #endif
06541 if (i->channel == CHAN_PSEUDO)
06542 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
06543 else
06544 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
06545 for (x = 0; x < 3; x++) {
06546 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
06547 break;
06548 }
06549 y++;
06550 } while (x < 3);
06551 strcpy(chanprefix, dahdi_chan_name);
06552 strcat(chanprefix, "/%s");
06553 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
06554 if (b2)
06555 free(b2);
06556 if (!tmp)
06557 return NULL;
06558 tmp->tech = chan_tech;
06559 memset(&ps, 0, sizeof(ps));
06560 ps.channo = i->channel;
06561 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06562 if (res) {
06563 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06564 ps.curlaw = DAHDI_LAW_MULAW;
06565 }
06566 if (ps.curlaw == DAHDI_LAW_ALAW)
06567 deflaw = AST_FORMAT_ALAW;
06568 else
06569 deflaw = AST_FORMAT_ULAW;
06570 if (law) {
06571 if (law == DAHDI_LAW_ALAW)
06572 deflaw = AST_FORMAT_ALAW;
06573 else
06574 deflaw = AST_FORMAT_ULAW;
06575 }
06576 tmp->fds[0] = i->subs[index].dfd;
06577 tmp->nativeformats = deflaw;
06578
06579 tmp->rawreadformat = deflaw;
06580 tmp->readformat = deflaw;
06581 tmp->rawwriteformat = deflaw;
06582 tmp->writeformat = deflaw;
06583 i->subs[index].linear = 0;
06584 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
06585 features = 0;
06586 if (index == SUB_REAL) {
06587 if (i->busydetect && CANBUSYDETECT(i))
06588 features |= DSP_FEATURE_BUSY_DETECT;
06589 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
06590 features |= DSP_FEATURE_CALL_PROGRESS;
06591 if ((!i->outgoing && (i->callprogress & 4)) ||
06592 (i->outgoing && (i->callprogress & 2))) {
06593 features |= DSP_FEATURE_FAX_DETECT;
06594 }
06595 #ifdef DAHDI_TONEDETECT
06596 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06597 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
06598 #endif
06599 i->hardwaredtmf = 0;
06600 features |= DSP_FEATURE_DTMF_DETECT;
06601 #ifdef DAHDI_TONEDETECT
06602 } else if (NEED_MFDETECT(i)) {
06603 i->hardwaredtmf = 1;
06604 features |= DSP_FEATURE_DTMF_DETECT;
06605 }
06606 #endif
06607 }
06608 if (features) {
06609 if (i->dsp) {
06610 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
06611 } else {
06612 if (i->channel != CHAN_PSEUDO)
06613 i->dsp = ast_dsp_new();
06614 else
06615 i->dsp = NULL;
06616 if (i->dsp) {
06617 i->dsp_features = features;
06618 #ifdef HAVE_PRI
06619
06620 if (i->outgoing && (i->sig == SIG_PRI)) {
06621
06622
06623 i->dsp_features = features & ~DSP_PROGRESS_TALK;
06624 features = 0;
06625 }
06626 #endif
06627 ast_dsp_set_features(i->dsp, features);
06628 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06629 if (!ast_strlen_zero(progzone))
06630 ast_dsp_set_call_progress_zone(i->dsp, progzone);
06631 if (i->busydetect && CANBUSYDETECT(i)) {
06632 if(i->silencethreshold > 0)
06633 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06634 ast_dsp_set_busy_count(i->dsp, i->busycount);
06635 if(i->busytonelength > 0)
06636 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06637 if((i->busytonelength == i->busyquietlength) && i->busycompare)
06638 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06639 }
06640 }
06641 }
06642 }
06643
06644 if (state == AST_STATE_RING)
06645 tmp->rings = 1;
06646 tmp->tech_pvt = i;
06647 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06648
06649 tmp->callgroup = i->callgroup;
06650 tmp->pickupgroup = i->pickupgroup;
06651 }
06652 if (!ast_strlen_zero(i->language))
06653 ast_string_field_set(tmp, language, i->language);
06654 if (!i->owner)
06655 i->owner = tmp;
06656 if (!ast_strlen_zero(i->accountcode))
06657 ast_string_field_set(tmp, accountcode, i->accountcode);
06658 if (i->amaflags)
06659 tmp->amaflags = i->amaflags;
06660 i->subs[index].owner = tmp;
06661 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06662 ast_string_field_set(tmp, call_forward, i->call_forward);
06663
06664 if (!i->adsi)
06665 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06666 if (!ast_strlen_zero(i->exten))
06667 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06668 if (!ast_strlen_zero(i->rdnis))
06669 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06670 if (!ast_strlen_zero(i->dnid))
06671 tmp->cid.cid_dnid = ast_strdup(i->dnid);
06672
06673
06674
06675 #ifdef PRI_ANI
06676 if (!ast_strlen_zero(i->cid_ani))
06677 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06678 else
06679 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06680 #else
06681 tmp->cid.cid_ani = ast_strdup(i->cid_num);
06682 #endif
06683 tmp->cid.cid_pres = i->callingpres;
06684 tmp->cid.cid_ton = i->cid_ton;
06685 #ifdef HAVE_PRI
06686 tmp->transfercapability = transfercapability;
06687 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06688 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
06689 i->digital = 1;
06690
06691 i->isidlecall = 0;
06692 i->alreadyhungup = 0;
06693 #endif
06694
06695 i->fake_event = 0;
06696
06697 dahdi_confmute(i, 0);
06698
06699 ast_jb_configure(tmp, &global_jbconf);
06700 if (startpbx) {
06701 #ifdef HAVE_OPENR2
06702 if (i->mfcr2call) {
06703 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
06704 }
06705 #endif
06706 if (ast_pbx_start(tmp)) {
06707 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06708 ast_hangup(tmp);
06709 i->owner = NULL;
06710 return NULL;
06711 }
06712 }
06713
06714 ast_module_ref(ast_module_info->self);
06715
06716 return tmp;
06717 }
06718
06719
06720 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06721 {
06722 char c;
06723
06724 *str = 0;
06725 for (;;)
06726 {
06727
06728 c = ast_waitfordigit(chan, ms);
06729
06730 if (c < 1)
06731 return c;
06732 *str++ = c;
06733 *str = 0;
06734 if (strchr(term, c))
06735 return 1;
06736 }
06737 }
06738
06739 static int dahdi_wink(struct dahdi_pvt *p, int index)
06740 {
06741 int j;
06742 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06743 for (;;)
06744 {
06745
06746 j = DAHDI_IOMUX_SIGEVENT;
06747
06748 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06749
06750 if (j & DAHDI_IOMUX_SIGEVENT) break;
06751 }
06752
06753 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06754 return 0;
06755 }
06756
06757 static void *ss_thread(void *data)
06758 {
06759 struct ast_channel *chan = data;
06760 struct dahdi_pvt *p = chan->tech_pvt;
06761 char exten[AST_MAX_EXTENSION] = "";
06762 char exten2[AST_MAX_EXTENSION] = "";
06763 unsigned char buf[256];
06764 char dtmfcid[300];
06765 char dtmfbuf[300];
06766 struct callerid_state *cs = NULL;
06767 char *name = NULL, *number = NULL;
06768 int distMatches;
06769 int curRingData[3];
06770 int receivedRingT;
06771 int counter1;
06772 int counter;
06773 int samples = 0;
06774 struct ast_smdi_md_message *smdi_msg = NULL;
06775 int flags = 0;
06776 int i;
06777 int timeout;
06778 int getforward = 0;
06779 char *s1, *s2;
06780 int len = 0;
06781 int res;
06782 int index;
06783
06784 ast_mutex_lock(&ss_thread_lock);
06785 ss_thread_count++;
06786 ast_mutex_unlock(&ss_thread_lock);
06787
06788
06789
06790 if (!p) {
06791 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06792 ast_hangup(chan);
06793 goto quit;
06794 }
06795 if (option_verbose > 2)
06796 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
06797 index = dahdi_get_index(chan, p, 1);
06798 if (index < 0) {
06799 ast_log(LOG_WARNING, "Huh?\n");
06800 ast_hangup(chan);
06801 goto quit;
06802 }
06803 if (p->dsp)
06804 ast_dsp_digitreset(p->dsp);
06805 switch (p->sig) {
06806 #ifdef HAVE_PRI
06807 case SIG_PRI:
06808
06809 ast_copy_string(exten, p->exten, sizeof(exten));
06810 len = strlen(exten);
06811 res = 0;
06812 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06813 if (len && !ast_ignore_pattern(chan->context, exten))
06814 tone_zone_play_tone(p->subs[index].dfd, -1);
06815 else
06816 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06817 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06818 timeout = matchdigittimeout;
06819 else
06820 timeout = gendigittimeout;
06821 res = ast_waitfordigit(chan, timeout);
06822 if (res < 0) {
06823 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06824 ast_hangup(chan);
06825 goto quit;
06826 } else if (res) {
06827 exten[len++] = res;
06828 exten[len] = '\0';
06829 } else
06830 break;
06831 }
06832
06833 if (ast_strlen_zero(exten)) {
06834 if (option_verbose > 2)
06835 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
06836 exten[0] = 's';
06837 exten[1] = '\0';
06838 }
06839 tone_zone_play_tone(p->subs[index].dfd, -1);
06840 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06841
06842 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06843 if (p->dsp) ast_dsp_digitreset(p->dsp);
06844 dahdi_enable_ec(p);
06845 ast_setstate(chan, AST_STATE_RING);
06846 res = ast_pbx_run(chan);
06847 if (res) {
06848 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06849 }
06850 } else {
06851 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06852 chan->hangupcause = AST_CAUSE_UNALLOCATED;
06853 ast_hangup(chan);
06854 p->exten[0] = '\0';
06855
06856 p->call = NULL;
06857 }
06858 goto quit;
06859 break;
06860 #endif
06861 case SIG_FEATD:
06862 case SIG_FEATDMF:
06863 case SIG_FEATDMF_TA:
06864 case SIG_E911:
06865 case SIG_FGC_CAMAMF:
06866 case SIG_FEATB:
06867 case SIG_EMWINK:
06868 case SIG_SF_FEATD:
06869 case SIG_SF_FEATDMF:
06870 case SIG_SF_FEATB:
06871 case SIG_SFWINK:
06872 if (dahdi_wink(p, index))
06873 goto quit;
06874
06875 case SIG_EM:
06876 case SIG_EM_E1:
06877 case SIG_SF:
06878 case SIG_FGC_CAMA:
06879 res = tone_zone_play_tone(p->subs[index].dfd, -1);
06880 if (p->dsp)
06881 ast_dsp_digitreset(p->dsp);
06882
06883 if (p->dsp) {
06884 if (NEED_MFDETECT(p))
06885 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06886 else
06887 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06888 }
06889 memset(dtmfbuf, 0, sizeof(dtmfbuf));
06890
06891 if (!p->immediate)
06892
06893 res = ast_waitfordigit(chan, 5000);
06894 else
06895 res = 0;
06896 if (res > 0) {
06897
06898 dtmfbuf[0] = res;
06899 switch (p->sig) {
06900 case SIG_FEATD:
06901 case SIG_SF_FEATD:
06902 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06903 if (res > 0)
06904 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06905 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06906 break;
06907 case SIG_FEATDMF_TA:
06908 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06909 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06910 if (dahdi_wink(p, index)) goto quit;
06911 dtmfbuf[0] = 0;
06912
06913 res = ast_waitfordigit(chan, 5000);
06914 if (res <= 0) break;
06915 dtmfbuf[0] = res;
06916
06917 case SIG_FEATDMF:
06918 case SIG_E911:
06919 case SIG_FGC_CAMAMF:
06920 case SIG_SF_FEATDMF:
06921 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06922
06923 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06924 {
06925 if (dahdi_wink(p, index)) goto quit;
06926 dtmfbuf[0] = 0;
06927
06928 res = ast_waitfordigit(chan, 5000);
06929 if (res <= 0) break;
06930 dtmfbuf[0] = res;
06931 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06932 }
06933 if (res > 0) {
06934
06935 if (p->sig == SIG_E911)
06936 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06937 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06938 }
06939 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06940 break;
06941 case SIG_FEATB:
06942 case SIG_SF_FEATB:
06943 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06944 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06945 break;
06946 case SIG_EMWINK:
06947
06948
06949
06950
06951 if (res == '*') {
06952 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06953 if (res > 0)
06954 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06955 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06956 break;
06957 }
06958 default:
06959
06960 len = 1;
06961 dtmfbuf[len] = '\0';
06962 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06963 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06964 timeout = matchdigittimeout;
06965 } else {
06966 timeout = gendigittimeout;
06967 }
06968 res = ast_waitfordigit(chan, timeout);
06969 if (res < 0) {
06970 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06971 ast_hangup(chan);
06972 goto quit;
06973 } else if (res) {
06974 dtmfbuf[len++] = res;
06975 dtmfbuf[len] = '\0';
06976 } else {
06977 break;
06978 }
06979 }
06980 break;
06981 }
06982 }
06983 if (res == -1) {
06984 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06985 ast_hangup(chan);
06986 goto quit;
06987 } else if (res < 0) {
06988 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06989 ast_hangup(chan);
06990 goto quit;
06991 }
06992
06993 if (p->sig == SIG_FGC_CAMA) {
06994 char anibuf[100];
06995
06996 if (ast_safe_sleep(chan,1000) == -1) {
06997 ast_hangup(chan);
06998 goto quit;
06999 }
07000 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07001 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
07002 res = my_getsigstr(chan, anibuf, "#", 10000);
07003 if ((res > 0) && (strlen(anibuf) > 2)) {
07004 if (anibuf[strlen(anibuf) - 1] == '#')
07005 anibuf[strlen(anibuf) - 1] = 0;
07006 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07007 }
07008 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07009 }
07010
07011 ast_copy_string(exten, dtmfbuf, sizeof(exten));
07012 if (ast_strlen_zero(exten))
07013 ast_copy_string(exten, "s", sizeof(exten));
07014 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07015
07016 if (exten[0] == '*') {
07017 char *stringp=NULL;
07018 ast_copy_string(exten2, exten, sizeof(exten2));
07019
07020 stringp=exten2 +1;
07021 s1 = strsep(&stringp, "*");
07022 s2 = strsep(&stringp, "*");
07023 if (s2) {
07024 if (!ast_strlen_zero(p->cid_num))
07025 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07026 else
07027 ast_set_callerid(chan, s1, NULL, s1);
07028 ast_copy_string(exten, s2, sizeof(exten));
07029 } else
07030 ast_copy_string(exten, s1, sizeof(exten));
07031 } else if (p->sig == SIG_FEATD)
07032 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07033 }
07034 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07035 if (exten[0] == '*') {
07036 char *stringp=NULL;
07037 ast_copy_string(exten2, exten, sizeof(exten2));
07038
07039 stringp=exten2 +1;
07040 s1 = strsep(&stringp, "#");
07041 s2 = strsep(&stringp, "#");
07042 if (s2) {
07043 if (!ast_strlen_zero(p->cid_num))
07044 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07045 else
07046 if (*(s1 + 2))
07047 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07048 ast_copy_string(exten, s2 + 1, sizeof(exten));
07049 } else
07050 ast_copy_string(exten, s1 + 2, sizeof(exten));
07051 } else
07052 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07053 }
07054 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07055 if (exten[0] == '*') {
07056 char *stringp=NULL;
07057 ast_copy_string(exten2, exten, sizeof(exten2));
07058
07059 stringp=exten2 +1;
07060 s1 = strsep(&stringp, "#");
07061 s2 = strsep(&stringp, "#");
07062 if (s2 && (*(s2 + 1) == '0')) {
07063 if (*(s2 + 2))
07064 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07065 }
07066 if (s1) ast_copy_string(exten, s1, sizeof(exten));
07067 else ast_copy_string(exten, "911", sizeof(exten));
07068 } else
07069 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
07070 }
07071 if (p->sig == SIG_FEATB) {
07072 if (exten[0] == '*') {
07073 char *stringp=NULL;
07074 ast_copy_string(exten2, exten, sizeof(exten2));
07075
07076 stringp=exten2 +1;
07077 s1 = strsep(&stringp, "#");
07078 ast_copy_string(exten, exten2 + 1, sizeof(exten));
07079 } else
07080 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
07081 }
07082 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07083 dahdi_wink(p, index);
07084
07085
07086
07087 if (ast_safe_sleep(chan,100)) goto quit;
07088 }
07089 dahdi_enable_ec(p);
07090 if (NEED_MFDETECT(p)) {
07091 if (p->dsp) {
07092 if (!p->hardwaredtmf)
07093 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07094 else {
07095 ast_dsp_free(p->dsp);
07096 p->dsp = NULL;
07097 }
07098 }
07099 }
07100
07101 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07102 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07103 if (p->dsp) ast_dsp_digitreset(p->dsp);
07104 res = ast_pbx_run(chan);
07105 if (res) {
07106 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07107 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07108 }
07109 goto quit;
07110 } else {
07111 if (option_verbose > 2)
07112 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07113 sleep(2);
07114 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07115 if (res < 0)
07116 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07117 else
07118 sleep(1);
07119 res = ast_streamfile(chan, "ss-noservice", chan->language);
07120 if (res >= 0)
07121 ast_waitstream(chan, "");
07122 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07123 ast_hangup(chan);
07124 goto quit;
07125 }
07126 break;
07127 case SIG_FXOLS:
07128 case SIG_FXOGS:
07129 case SIG_FXOKS:
07130
07131 timeout = firstdigittimeout;
07132
07133
07134 if (p->subs[SUB_THREEWAY].owner)
07135 timeout = 999999;
07136 while (len < AST_MAX_EXTENSION-1) {
07137
07138
07139 if (p->immediate)
07140 res = 's';
07141 else
07142 res = ast_waitfordigit(chan, timeout);
07143 timeout = 0;
07144 if (res < 0) {
07145 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07146 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07147 ast_hangup(chan);
07148 goto quit;
07149 } else if (res) {
07150 exten[len++]=res;
07151 exten[len] = '\0';
07152 }
07153 if (!ast_ignore_pattern(chan->context, exten))
07154 tone_zone_play_tone(p->subs[index].dfd, -1);
07155 else
07156 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07157 if (!strcmp(exten,ast_pickup_ext())) {
07158
07159
07160
07161
07162 if (index == SUB_REAL) {
07163
07164 if (p->subs[SUB_THREEWAY].owner) {
07165
07166
07167 alloc_sub(p, SUB_CALLWAIT);
07168 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07169 unalloc_sub(p, SUB_THREEWAY);
07170 }
07171 dahdi_enable_ec(p);
07172 if (ast_pickup_call(chan)) {
07173 ast_log(LOG_DEBUG, "No call pickup possible...\n");
07174 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07175 dahdi_wait_event(p->subs[index].dfd);
07176 }
07177 ast_hangup(chan);
07178 goto quit;
07179 } else {
07180 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
07181 ast_hangup(chan);
07182 goto quit;
07183 }
07184
07185 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07186 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07187 if (getforward) {
07188
07189 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
07190 if (option_verbose > 2)
07191 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07192 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07193 if (res)
07194 break;
07195 usleep(500000);
07196 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07197 sleep(1);
07198 memset(exten, 0, sizeof(exten));
07199 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07200 len = 0;
07201 getforward = 0;
07202 } else {
07203 res = tone_zone_play_tone(p->subs[index].dfd, -1);
07204 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07205 if (!ast_strlen_zero(p->cid_num)) {
07206 if (!p->hidecallerid)
07207 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07208 else
07209 ast_set_callerid(chan, NULL, NULL, p->cid_num);
07210 }
07211 if (!ast_strlen_zero(p->cid_name)) {
07212 if (!p->hidecallerid)
07213 ast_set_callerid(chan, NULL, p->cid_name, NULL);
07214 }
07215 ast_setstate(chan, AST_STATE_RING);
07216 dahdi_enable_ec(p);
07217 res = ast_pbx_run(chan);
07218 if (res) {
07219 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07220 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07221 }
07222 goto quit;
07223 }
07224 } else {
07225
07226
07227 timeout = matchdigittimeout;
07228 }
07229 } else if (res == 0) {
07230 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07231 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07232 dahdi_wait_event(p->subs[index].dfd);
07233 ast_hangup(chan);
07234 goto quit;
07235 } else if (p->callwaiting && !strcmp(exten, "*70")) {
07236 if (option_verbose > 2)
07237 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07238
07239 p->callwaiting = 0;
07240 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07241 if (res) {
07242 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07243 chan->name, strerror(errno));
07244 }
07245 len = 0;
07246 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07247 memset(exten, 0, sizeof(exten));
07248 timeout = firstdigittimeout;
07249
07250 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07251 if (option_verbose > 2)
07252 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07253
07254 p->hidecallerid = 1;
07255 if (chan->cid.cid_num)
07256 free(chan->cid.cid_num);
07257 chan->cid.cid_num = NULL;
07258 if (chan->cid.cid_name)
07259 free(chan->cid.cid_name);
07260 chan->cid.cid_name = NULL;
07261 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07262 if (res) {
07263 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07264 chan->name, strerror(errno));
07265 }
07266 len = 0;
07267 memset(exten, 0, sizeof(exten));
07268 timeout = firstdigittimeout;
07269 } else if (p->callreturn && !strcmp(exten, "*69")) {
07270 res = 0;
07271 if (!ast_strlen_zero(p->lastcid_num)) {
07272 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07273 }
07274 if (!res)
07275 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07276 break;
07277 } else if (!strcmp(exten, "*78")) {
07278
07279 if (option_verbose > 2)
07280 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07281 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07282 "Channel: %s/%d\r\n"
07283 "Status: enabled\r\n", dahdi_chan_name, p->channel);
07284 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07285 p->dnd = 1;
07286 getforward = 0;
07287 memset(exten, 0, sizeof(exten));
07288 len = 0;
07289 } else if (!strcmp(exten, "*79")) {
07290
07291 if (option_verbose > 2)
07292 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07293 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07294 "Channel: %s/%d\r\n"
07295 "Status: disabled\r\n", dahdi_chan_name, p->channel);
07296 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07297 p->dnd = 0;
07298 getforward = 0;
07299 memset(exten, 0, sizeof(exten));
07300 len = 0;
07301 } else if (p->cancallforward && !strcmp(exten, "*72")) {
07302 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07303 getforward = 1;
07304 memset(exten, 0, sizeof(exten));
07305 len = 0;
07306 } else if (p->cancallforward && !strcmp(exten, "*73")) {
07307 if (option_verbose > 2)
07308 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07309 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07310 memset(p->call_forward, 0, sizeof(p->call_forward));
07311 getforward = 0;
07312 memset(exten, 0, sizeof(exten));
07313 len = 0;
07314 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
07315 p->subs[SUB_THREEWAY].owner &&
07316 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07317
07318
07319 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07320 if (option_verbose > 2)
07321 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07322 break;
07323 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07324 if (option_verbose > 2)
07325 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07326 res = ast_db_put("blacklist", p->lastcid_num, "1");
07327 if (!res) {
07328 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07329 memset(exten, 0, sizeof(exten));
07330 len = 0;
07331 }
07332 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07333 if (option_verbose > 2)
07334 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07335
07336 p->hidecallerid = 0;
07337 if (chan->cid.cid_num)
07338 free(chan->cid.cid_num);
07339 chan->cid.cid_num = NULL;
07340 if (chan->cid.cid_name)
07341 free(chan->cid.cid_name);
07342 chan->cid.cid_name = NULL;
07343 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07344 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07345 if (res) {
07346 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
07347 chan->name, strerror(errno));
07348 }
07349 len = 0;
07350 memset(exten, 0, sizeof(exten));
07351 timeout = firstdigittimeout;
07352 } else if (!strcmp(exten, "*0")) {
07353 struct ast_channel *nbridge =
07354 p->subs[SUB_THREEWAY].owner;
07355 struct dahdi_pvt *pbridge = NULL;
07356
07357 if (nbridge && ast_bridged_channel(nbridge))
07358 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07359 if (nbridge && pbridge &&
07360 (nbridge->tech == chan_tech) &&
07361 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07362 ISTRUNK(pbridge)) {
07363 int func = DAHDI_FLASH;
07364
07365 p->dop.dialstr[0] = '\0';
07366
07367 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07368 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07369 nbridge->name, strerror(errno));
07370 }
07371 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07372 unalloc_sub(p, SUB_THREEWAY);
07373 p->owner = p->subs[SUB_REAL].owner;
07374 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07375 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07376 ast_hangup(chan);
07377 goto quit;
07378 } else {
07379 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07380 dahdi_wait_event(p->subs[index].dfd);
07381 tone_zone_play_tone(p->subs[index].dfd, -1);
07382 swap_subs(p, SUB_REAL, SUB_THREEWAY);
07383 unalloc_sub(p, SUB_THREEWAY);
07384 p->owner = p->subs[SUB_REAL].owner;
07385 ast_hangup(chan);
07386 goto quit;
07387 }
07388 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07389 ((exten[0] != '*') || (strlen(exten) > 2))) {
07390 if (option_debug)
07391 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);
07392 break;
07393 }
07394 if (!timeout)
07395 timeout = gendigittimeout;
07396 if (len && !ast_ignore_pattern(chan->context, exten))
07397 tone_zone_play_tone(p->subs[index].dfd, -1);
07398 }
07399 break;
07400 case SIG_FXSLS:
07401 case SIG_FXSGS:
07402 case SIG_FXSKS:
07403 #ifdef HAVE_PRI
07404 if (p->pri) {
07405
07406 struct ast_frame *f;
07407 int res;
07408 time_t start;
07409
07410 time(&start);
07411 ast_setstate(chan, AST_STATE_RING);
07412 while (time(NULL) < start + 3) {
07413 res = ast_waitfor(chan, 1000);
07414 if (res) {
07415 f = ast_read(chan);
07416 if (!f) {
07417 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07418 ast_hangup(chan);
07419 goto quit;
07420 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07421 res = 1;
07422 } else
07423 res = 0;
07424 ast_frfree(f);
07425 if (res) {
07426 ast_log(LOG_DEBUG, "Got ring!\n");
07427 res = 0;
07428 break;
07429 }
07430 }
07431 }
07432 }
07433 #endif
07434
07435 if (p->use_smdi && p->smdi_iface) {
07436 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07437
07438 if (smdi_msg != NULL) {
07439 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07440
07441 if (smdi_msg->type == 'B')
07442 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07443 else if (smdi_msg->type == 'N')
07444 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07445
07446 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
07447 } else {
07448 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07449 }
07450 }
07451
07452 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07453 number = smdi_msg->calling_st;
07454
07455
07456
07457
07458 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
07459 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
07460
07461 if (p->cid_signalling == CID_SIG_DTMF) {
07462 int i = 0;
07463 cs = NULL;
07464 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
07465 "channel %s\n", chan->name);
07466 dahdi_setlinear(p->subs[index].dfd, 0);
07467 res = 2000;
07468 for (;;) {
07469 struct ast_frame *f;
07470 res = ast_waitfor(chan, res);
07471 if (res <= 0) {
07472 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07473 "Exiting simple switch\n");
07474 ast_hangup(chan);
07475 goto quit;
07476 }
07477 f = ast_read(chan);
07478 if (!f)
07479 break;
07480 if (f->frametype == AST_FRAME_DTMF) {
07481 dtmfbuf[i++] = f->subclass;
07482 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07483 res = 2000;
07484 }
07485 ast_frfree(f);
07486 if (chan->_state == AST_STATE_RING ||
07487 chan->_state == AST_STATE_RINGING)
07488 break;
07489 }
07490 dtmfbuf[i] = '\0';
07491 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07492
07493 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
07494 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07495 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07496 dtmfcid, flags);
07497
07498 if (!ast_strlen_zero(dtmfcid))
07499 number = dtmfcid;
07500 else
07501 number = NULL;
07502
07503 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07504 cs = callerid_new(p->cid_signalling);
07505 if (cs) {
07506 samples = 0;
07507 #if 1
07508 bump_gains(p);
07509 #endif
07510
07511 dahdi_setlinear(p->subs[index].dfd, 0);
07512
07513
07514 for (;;) {
07515 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07516 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07517 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07518 callerid_free(cs);
07519 ast_hangup(chan);
07520 goto quit;
07521 }
07522 if (i & DAHDI_IOMUX_SIGEVENT) {
07523 res = dahdi_get_event(p->subs[index].dfd);
07524 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07525
07526 if (p->cid_signalling == CID_SIG_V23_JP) {
07527 #ifdef DAHDI_EVENT_RINGBEGIN
07528 if (res == DAHDI_EVENT_RINGBEGIN) {
07529 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07530 usleep(1);
07531 }
07532 #endif
07533 } else {
07534 res = 0;
07535 break;
07536 }
07537 } else if (i & DAHDI_IOMUX_READ) {
07538 res = read(p->subs[index].dfd, buf, sizeof(buf));
07539 if (res < 0) {
07540 if (errno != ELAST) {
07541 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07542 callerid_free(cs);
07543 ast_hangup(chan);
07544 goto quit;
07545 }
07546 break;
07547 }
07548 samples += res;
07549
07550 if (p->cid_signalling == CID_SIG_V23_JP) {
07551 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07552 } else {
07553 res = callerid_feed(cs, buf, res, AST_LAW(p));
07554 }
07555
07556 if (res < 0) {
07557 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07558 break;
07559 } else if (res)
07560 break;
07561 else if (samples > (8000 * 10))
07562 break;
07563 }
07564 }
07565 if (res == 1) {
07566 callerid_get(cs, &name, &number, &flags);
07567 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07568 }
07569
07570 if (p->cid_signalling == CID_SIG_V23_JP) {
07571 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07572 usleep(1);
07573 res = 4000;
07574 } else {
07575
07576
07577 res = 2000;
07578 }
07579
07580 for (;;) {
07581 struct ast_frame *f;
07582 res = ast_waitfor(chan, res);
07583 if (res <= 0) {
07584 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07585 "Exiting simple switch\n");
07586 ast_hangup(chan);
07587 goto quit;
07588 }
07589 if (!(f = ast_read(chan))) {
07590 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07591 ast_hangup(chan);
07592 goto quit;
07593 }
07594 ast_frfree(f);
07595 if (chan->_state == AST_STATE_RING ||
07596 chan->_state == AST_STATE_RINGING)
07597 break;
07598 }
07599
07600
07601
07602 if (p->usedistinctiveringdetection) {
07603 len = 0;
07604 distMatches = 0;
07605
07606 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07607 curRingData[receivedRingT] = 0;
07608 receivedRingT = 0;
07609 counter = 0;
07610 counter1 = 0;
07611
07612 if (strcmp(p->context,p->defcontext) != 0) {
07613 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07614 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07615 }
07616
07617 for (;;) {
07618 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07619 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07620 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07621 callerid_free(cs);
07622 ast_hangup(chan);
07623 goto quit;
07624 }
07625 if (i & DAHDI_IOMUX_SIGEVENT) {
07626 res = dahdi_get_event(p->subs[index].dfd);
07627 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07628 res = 0;
07629
07630
07631 curRingData[receivedRingT] = p->ringt;
07632
07633 if (p->ringt < p->ringt_base/2)
07634 break;
07635
07636
07637 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07638 break;
07639 } else if (i & DAHDI_IOMUX_READ) {
07640 res = read(p->subs[index].dfd, buf, sizeof(buf));
07641 if (res < 0) {
07642 if (errno != ELAST) {
07643 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07644 callerid_free(cs);
07645 ast_hangup(chan);
07646 goto quit;
07647 }
07648 break;
07649 }
07650 if (p->ringt)
07651 p->ringt--;
07652 if (p->ringt == 1) {
07653 res = -1;
07654 break;
07655 }
07656 }
07657 }
07658 if (option_verbose > 2)
07659
07660 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07661
07662 for (counter = 0; counter < 3; counter++) {
07663
07664
07665 distMatches = 0;
07666 for (counter1 = 0; counter1 < 3; counter1++) {
07667 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07668 (p->drings.ringnum[counter].ring[counter1]-10)) {
07669 distMatches++;
07670 }
07671 }
07672 if (distMatches == 3) {
07673
07674 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07675 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07676 if (option_verbose > 2)
07677 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07678 break;
07679 }
07680 }
07681 }
07682
07683 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07684 #if 1
07685 restore_gains(p);
07686 #endif
07687 } else
07688 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07689 } else {
07690 ast_log(LOG_WARNING, "Channel %s in prering "
07691 "state, but I have nothing to do. "
07692 "Terminating simple switch, should be "
07693 "restarted by the actual ring.\n",
07694 chan->name);
07695 ast_hangup(chan);
07696 goto quit;
07697 }
07698 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07699
07700 cs = callerid_new(p->cid_signalling);
07701 if (cs) {
07702 #if 1
07703 bump_gains(p);
07704 #endif
07705 samples = 0;
07706 len = 0;
07707 distMatches = 0;
07708
07709 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07710 curRingData[receivedRingT] = 0;
07711 receivedRingT = 0;
07712 counter = 0;
07713 counter1 = 0;
07714
07715 if (strcmp(p->context,p->defcontext) != 0) {
07716 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07717 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07718 }
07719
07720
07721 dahdi_setlinear(p->subs[index].dfd, 0);
07722 for (;;) {
07723 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07724 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07725 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07726 callerid_free(cs);
07727 ast_hangup(chan);
07728 goto quit;
07729 }
07730 if (i & DAHDI_IOMUX_SIGEVENT) {
07731 res = dahdi_get_event(p->subs[index].dfd);
07732 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07733
07734 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07735 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07736 p->polarity = POLARITY_IDLE;
07737 callerid_free(cs);
07738 ast_hangup(chan);
07739 goto quit;
07740 }
07741 res = 0;
07742
07743
07744 curRingData[receivedRingT] = p->ringt;
07745
07746 if (p->ringt < p->ringt_base/2)
07747 break;
07748
07749
07750 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07751 break;
07752 } else if (i & DAHDI_IOMUX_READ) {
07753 res = read(p->subs[index].dfd, buf, sizeof(buf));
07754 if (res < 0) {
07755 if (errno != ELAST) {
07756 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07757 callerid_free(cs);
07758 ast_hangup(chan);
07759 goto quit;
07760 }
07761 break;
07762 }
07763 if (p->ringt)
07764 p->ringt--;
07765 if (p->ringt == 1) {
07766 res = -1;
07767 break;
07768 }
07769 samples += res;
07770 res = callerid_feed(cs, buf, res, AST_LAW(p));
07771 if (res < 0) {
07772 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07773 break;
07774 } else if (res)
07775 break;
07776 else if (samples > (8000 * 10))
07777 break;
07778 }
07779 }
07780 if (res == 1) {
07781 callerid_get(cs, &name, &number, &flags);
07782 if (option_debug)
07783 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07784 }
07785 if (distinctiveringaftercid == 1) {
07786
07787 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07788 curRingData[receivedRingT] = 0;
07789 }
07790 receivedRingT = 0;
07791 if (option_verbose > 2)
07792 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
07793 for (;;) {
07794 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07795 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
07796 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07797 callerid_free(cs);
07798 ast_hangup(chan);
07799 goto quit;
07800 }
07801 if (i & DAHDI_IOMUX_SIGEVENT) {
07802 res = dahdi_get_event(p->subs[index].dfd);
07803 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07804 res = 0;
07805
07806
07807 curRingData[receivedRingT] = p->ringt;
07808
07809 if (p->ringt < p->ringt_base/2)
07810 break;
07811
07812
07813 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07814 break;
07815 } else if (i & DAHDI_IOMUX_READ) {
07816 res = read(p->subs[index].dfd, buf, sizeof(buf));
07817 if (res < 0) {
07818 if (errno != ELAST) {
07819 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07820 callerid_free(cs);
07821 ast_hangup(chan);
07822 goto quit;
07823 }
07824 break;
07825 }
07826 if (p->ringt)
07827 p->ringt--;
07828 if (p->ringt == 1) {
07829 res = -1;
07830 break;
07831 }
07832 }
07833 }
07834 }
07835 if (p->usedistinctiveringdetection) {
07836 if (option_verbose > 2)
07837
07838 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07839
07840 for (counter = 0; counter < 3; counter++) {
07841
07842
07843 if (option_verbose > 2)
07844
07845 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
07846 p->drings.ringnum[counter].ring[0],
07847 p->drings.ringnum[counter].ring[1],
07848 p->drings.ringnum[counter].ring[2]);
07849 distMatches = 0;
07850 for (counter1 = 0; counter1 < 3; counter1++) {
07851 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07852 (p->drings.ringnum[counter].ring[counter1]-10)) {
07853 distMatches++;
07854 }
07855 }
07856 if (distMatches == 3) {
07857
07858 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07859 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07860 if (option_verbose > 2)
07861 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07862 break;
07863 }
07864 }
07865 }
07866
07867 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07868 #if 1
07869 restore_gains(p);
07870 #endif
07871 if (res < 0) {
07872 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07873 }
07874 } else
07875 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07876 }
07877 else
07878 cs = NULL;
07879
07880 if (number)
07881 ast_shrink_phone_number(number);
07882 ast_set_callerid(chan, number, name, number);
07883
07884 if (smdi_msg)
07885 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07886
07887 if (cs)
07888 callerid_free(cs);
07889
07890 ast_setstate(chan, AST_STATE_RING);
07891 chan->rings = 1;
07892 p->ringt = p->ringt_base;
07893 res = ast_pbx_run(chan);
07894 if (res) {
07895 ast_hangup(chan);
07896 ast_log(LOG_WARNING, "PBX exited non-zero\n");
07897 }
07898 goto quit;
07899 default:
07900 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07901 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07902 if (res < 0)
07903 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07904 }
07905 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07906 if (res < 0)
07907 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07908 ast_hangup(chan);
07909 quit:
07910 ast_mutex_lock(&ss_thread_lock);
07911 ss_thread_count--;
07912 ast_cond_signal(&ss_thread_complete);
07913 ast_mutex_unlock(&ss_thread_lock);
07914 return NULL;
07915 }
07916
07917 static int calc_energy(const unsigned char *buf, int len, int law)
07918 {
07919 int x;
07920 int sum = 0;
07921
07922 if (!len)
07923 return 0;
07924
07925 for (x = 0; x < len; x++)
07926 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07927
07928 return sum / len;
07929 }
07930
07931
07932 static int dahdi_destroy_channel_bynum(int channel)
07933 {
07934 struct dahdi_pvt *tmp = NULL;
07935 struct dahdi_pvt *prev = NULL;
07936
07937 ast_mutex_lock(&iflock);
07938 tmp = iflist;
07939 while (tmp) {
07940 if (tmp->channel == channel) {
07941 int x = DAHDI_FLASH;
07942 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07943 destroy_channel(prev, tmp, 1);
07944 ast_mutex_unlock(&iflock);
07945 ast_module_unref(ast_module_info->self);
07946 return RESULT_SUCCESS;
07947 }
07948 prev = tmp;
07949 tmp = tmp->next;
07950 }
07951 ast_mutex_unlock(&iflock);
07952 return RESULT_FAILURE;
07953 }
07954
07955 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
07956 {
07957 int res;
07958 pthread_t threadid;
07959 pthread_attr_t attr;
07960 struct ast_channel *chan;
07961 pthread_attr_init(&attr);
07962 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07963
07964 switch (event) {
07965 case DAHDI_EVENT_NONE:
07966 case DAHDI_EVENT_BITSCHANGED:
07967 break;
07968 case DAHDI_EVENT_WINKFLASH:
07969 case DAHDI_EVENT_RINGOFFHOOK:
07970 if (i->inalarm) break;
07971 if (i->radio) break;
07972
07973 switch (i->sig) {
07974 case SIG_FXOLS:
07975 case SIG_FXOGS:
07976 case SIG_FXOKS:
07977 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07978 if (res && (errno == EBUSY))
07979 break;
07980 if (i->cidspill) {
07981
07982 free(i->cidspill);
07983 i->cidspill = NULL;
07984 }
07985 if (i->immediate) {
07986 dahdi_enable_ec(i);
07987
07988 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07989 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07990 if (!chan) {
07991 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07992 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07993 if (res < 0)
07994 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07995 }
07996 } else {
07997
07998 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07999 if (chan) {
08000 if (has_voicemail(i))
08001 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08002 else
08003 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08004 if (res < 0)
08005 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08006 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08007 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08008 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08009 if (res < 0)
08010 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08011 ast_hangup(chan);
08012 }
08013 } else
08014 ast_log(LOG_WARNING, "Unable to create channel\n");
08015 }
08016 break;
08017 case SIG_FXSLS:
08018 case SIG_FXSGS:
08019 case SIG_FXSKS:
08020 i->ringt = i->ringt_base;
08021
08022 case SIG_EMWINK:
08023 case SIG_FEATD:
08024 case SIG_FEATDMF:
08025 case SIG_FEATDMF_TA:
08026 case SIG_E911:
08027 case SIG_FGC_CAMA:
08028 case SIG_FGC_CAMAMF:
08029 case SIG_FEATB:
08030 case SIG_EM:
08031 case SIG_EM_E1:
08032 case SIG_SFWINK:
08033 case SIG_SF_FEATD:
08034 case SIG_SF_FEATDMF:
08035 case SIG_SF_FEATB:
08036 case SIG_SF:
08037
08038 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08039 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08040 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08041 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08042 if (res < 0)
08043 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08044 ast_hangup(chan);
08045 } else if (!chan) {
08046 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08047 }
08048 break;
08049 default:
08050 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), 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 pthread_attr_destroy(&attr);
08055 return NULL;
08056 }
08057 break;
08058 case DAHDI_EVENT_NOALARM:
08059 i->inalarm = 0;
08060 if (!i->unknown_alarm) {
08061 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08062 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08063 "Channel: %d\r\n", i->channel);
08064 } else {
08065 i->unknown_alarm = 0;
08066 }
08067 break;
08068 case DAHDI_EVENT_ALARM:
08069 i->inalarm = 1;
08070 res = get_alarms(i);
08071 handle_alarms(i, res);
08072
08073 case DAHDI_EVENT_ONHOOK:
08074 if (i->radio)
08075 break;
08076
08077 switch (i->sig) {
08078 case SIG_FXOLS:
08079 case SIG_FXOGS:
08080 case SIG_FEATD:
08081 case SIG_FEATDMF:
08082 case SIG_FEATDMF_TA:
08083 case SIG_E911:
08084 case SIG_FGC_CAMA:
08085 case SIG_FGC_CAMAMF:
08086 case SIG_FEATB:
08087 case SIG_EM:
08088 case SIG_EM_E1:
08089 case SIG_EMWINK:
08090 case SIG_SF_FEATD:
08091 case SIG_SF_FEATDMF:
08092 case SIG_SF_FEATB:
08093 case SIG_SF:
08094 case SIG_SFWINK:
08095 case SIG_FXSLS:
08096 case SIG_FXSGS:
08097 case SIG_FXSKS:
08098 case SIG_GR303FXSKS:
08099 dahdi_disable_ec(i);
08100 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08101 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08102 break;
08103 case SIG_GR303FXOKS:
08104 case SIG_FXOKS:
08105 dahdi_disable_ec(i);
08106
08107 #ifdef ZHONE_HACK
08108 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08109 usleep(1);
08110 #endif
08111 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08112 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08113 break;
08114 case SIG_PRI:
08115 dahdi_disable_ec(i);
08116 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08117 break;
08118 default:
08119 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08120 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08121 pthread_attr_destroy(&attr);
08122 return NULL;
08123 }
08124 break;
08125 case DAHDI_EVENT_POLARITY:
08126 switch (i->sig) {
08127 case SIG_FXSLS:
08128 case SIG_FXSKS:
08129 case SIG_FXSGS:
08130
08131
08132
08133
08134 if (i->hanguponpolarityswitch)
08135 i->polarity = POLARITY_REV;
08136
08137 if (i->cid_start == CID_START_POLARITY) {
08138 i->polarity = POLARITY_REV;
08139 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08140 "CID detection on channel %d\n",
08141 i->channel);
08142 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08143 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08144 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08145 }
08146 }
08147 break;
08148 default:
08149 ast_log(LOG_WARNING, "handle_init_event detected "
08150 "polarity reversal on non-FXO (SIG_FXS) "
08151 "interface %d\n", i->channel);
08152 }
08153 break;
08154 case DAHDI_EVENT_REMOVED:
08155 ast_log(LOG_NOTICE,
08156 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
08157 i->channel);
08158 pthread_attr_destroy(&attr);
08159 return i;
08160 }
08161 pthread_attr_destroy(&attr);
08162 return NULL;
08163 }
08164
08165 static void *do_monitor(void *data)
08166 {
08167 int count, res, res2, spoint, pollres=0;
08168 struct dahdi_pvt *i;
08169 struct dahdi_pvt *last = NULL;
08170 struct dahdi_pvt *doomed;
08171 time_t thispass = 0, lastpass = 0;
08172 int found;
08173 char buf[1024];
08174 struct pollfd *pfds=NULL;
08175 int lastalloc = -1;
08176
08177
08178
08179 #if 0
08180 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08181 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08182 return NULL;
08183 }
08184 ast_log(LOG_DEBUG, "Monitor starting...\n");
08185 #endif
08186 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08187
08188 for (;;) {
08189
08190 ast_mutex_lock(&iflock);
08191 if (!pfds || (lastalloc != ifcount)) {
08192 if (pfds) {
08193 free(pfds);
08194 pfds = NULL;
08195 }
08196 if (ifcount) {
08197 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08198 ast_mutex_unlock(&iflock);
08199 return NULL;
08200 }
08201 }
08202 lastalloc = ifcount;
08203 }
08204
08205
08206 count = 0;
08207 i = iflist;
08208 while (i) {
08209 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08210 if (!i->owner && !i->subs[SUB_REAL].owner) {
08211
08212 pfds[count].fd = i->subs[SUB_REAL].dfd;
08213 pfds[count].events = POLLPRI;
08214 pfds[count].revents = 0;
08215
08216 if (i->cidspill ||
08217 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
08218 pfds[count].events |= POLLIN;
08219 }
08220 count++;
08221 }
08222 }
08223 i = i->next;
08224 }
08225
08226 ast_mutex_unlock(&iflock);
08227
08228 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08229 pthread_testcancel();
08230
08231 res = poll(pfds, count, 1000);
08232 pthread_testcancel();
08233 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08234
08235
08236 if (res < 0) {
08237 if ((errno != EAGAIN) && (errno != EINTR))
08238 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08239 continue;
08240 }
08241
08242
08243 ast_mutex_lock(&iflock);
08244 found = 0;
08245 spoint = 0;
08246 lastpass = thispass;
08247 thispass = time(NULL);
08248 doomed = NULL;
08249 for (i = iflist;; i = i->next) {
08250 if (doomed) {
08251 int res;
08252 res = dahdi_destroy_channel_bynum(doomed->channel);
08253 if (!res) {
08254 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08255 }
08256 doomed = NULL;
08257 }
08258 if (!i) {
08259 break;
08260 }
08261 if (thispass != lastpass) {
08262 if (!found && ((i == last) || ((i == iflist) && !last))) {
08263 last = i;
08264 if (last) {
08265 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08266 (last->sig & __DAHDI_SIG_FXO)) {
08267 res = ast_app_has_voicemail(last->mailbox, NULL);
08268 if (last->msgstate != res) {
08269 int x;
08270 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08271 x = DAHDI_FLUSH_BOTH;
08272 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08273 if (res2)
08274 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08275 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08276
08277 x = 4000;
08278 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08279 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08280 last->cidpos = 0;
08281 last->msgstate = res;
08282 last->onhooktime = thispass;
08283 }
08284 found ++;
08285 }
08286 }
08287 last = last->next;
08288 }
08289 }
08290 }
08291 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08292 if (i->radio && !i->owner)
08293 {
08294 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08295 if (res)
08296 {
08297 if (option_debug)
08298 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08299
08300 ast_mutex_unlock(&iflock);
08301 doomed = handle_init_event(i, res);
08302 ast_mutex_lock(&iflock);
08303 }
08304 continue;
08305 }
08306 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08307 if (pollres & POLLIN) {
08308 if (i->owner || i->subs[SUB_REAL].owner) {
08309 #ifdef HAVE_PRI
08310 if (!i->pri)
08311 #endif
08312 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08313 continue;
08314 }
08315
08316
08317
08318
08319 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08320 if (res > 0) {
08321
08322
08323
08324
08325
08326
08327
08328
08329
08330
08331
08332
08333 if (i->cid_start == CID_START_DTMF_NOALERT) {
08334 int energy;
08335 struct timeval now;
08336
08337
08338
08339 if (1 == i->dtmfcid_holdoff_state) {
08340 gettimeofday(&i->dtmfcid_delay, NULL);
08341 i->dtmfcid_holdoff_state = 2;
08342 } else if (2 == i->dtmfcid_holdoff_state) {
08343 gettimeofday(&now, NULL);
08344 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
08345 i->dtmfcid_holdoff_state = 0;
08346 }
08347 } else {
08348 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
08349 if (energy > dtmfcid_level) {
08350 pthread_t threadid;
08351 struct ast_channel *chan;
08352 ast_mutex_unlock(&iflock);
08353 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08354 if (!chan) {
08355 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08356 } else {
08357 pthread_attr_t attr;
08358 pthread_attr_init(&attr);
08359 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08360 res = ast_pthread_create(&threadid, &attr, ss_thread, chan);
08361 if (res) {
08362 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08363 } else {
08364 i->dtmfcid_holdoff_state = 1;
08365 }
08366 }
08367 ast_mutex_lock(&iflock);
08368 }
08369 }
08370
08371
08372
08373 }
08374 } else {
08375 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08376 }
08377 }
08378 if (pollres & POLLPRI) {
08379 if (i->owner || i->subs[SUB_REAL].owner) {
08380 #ifdef HAVE_PRI
08381 if (!i->pri)
08382 #endif
08383 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08384 continue;
08385 }
08386 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08387 if (option_debug)
08388 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08389
08390 ast_mutex_unlock(&iflock);
08391 doomed = handle_init_event(i, res);
08392 ast_mutex_lock(&iflock);
08393 }
08394 }
08395 }
08396 ast_mutex_unlock(&iflock);
08397 }
08398
08399 return NULL;
08400
08401 }
08402
08403 static int restart_monitor(void)
08404 {
08405 pthread_attr_t attr;
08406 pthread_attr_init(&attr);
08407 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08408
08409 if (monitor_thread == AST_PTHREADT_STOP)
08410 return 0;
08411 ast_mutex_lock(&monlock);
08412 if (monitor_thread == pthread_self()) {
08413 ast_mutex_unlock(&monlock);
08414 ast_log(LOG_WARNING, "Cannot kill myself\n");
08415 return -1;
08416 }
08417 if (monitor_thread != AST_PTHREADT_NULL) {
08418
08419 pthread_kill(monitor_thread, SIGURG);
08420 } else {
08421
08422 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08423 ast_mutex_unlock(&monlock);
08424 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08425 pthread_attr_destroy(&attr);
08426 return -1;
08427 }
08428 }
08429 ast_mutex_unlock(&monlock);
08430 pthread_attr_destroy(&attr);
08431 return 0;
08432 }
08433
08434 #ifdef HAVE_OPENR2
08435 static struct dahdi_mfcr2 *mfcr2_get_context(int id)
08436 {
08437 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08438 ast_log(LOG_ERROR, "No more R2 links available!.\n");
08439 return NULL;
08440 }
08441 return &r2links[id];
08442 }
08443 #endif
08444
08445 #ifdef HAVE_PRI
08446 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08447 {
08448 int x;
08449 int trunkgroup;
08450
08451 trunkgroup = pris[*span].mastertrunkgroup;
08452 if (trunkgroup) {
08453
08454 for (x = 0; x < NUM_SPANS; x++) {
08455 if (pris[x].trunkgroup == trunkgroup) {
08456 *span = x;
08457 return 0;
08458 }
08459 }
08460 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08461 *span = -1;
08462 } else {
08463 if (pris[*span].trunkgroup) {
08464 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08465 *span = -1;
08466 } else if (pris[*span].mastertrunkgroup) {
08467 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08468 *span = -1;
08469 } else {
08470 if (si->totalchans == 31) {
08471
08472 pris[*span].dchannels[0] = 16 + offset;
08473 } else if (si->totalchans == 24) {
08474
08475 pris[*span].dchannels[0] = 24 + offset;
08476 } else if (si->totalchans == 3) {
08477
08478 pris[*span].dchannels[0] = 3 + offset;
08479 } else {
08480 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);
08481 *span = -1;
08482 return 0;
08483 }
08484 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08485 pris[*span].offset = offset;
08486 pris[*span].span = *span + 1;
08487 }
08488 }
08489 return 0;
08490 }
08491
08492 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08493 {
08494 struct dahdi_spaninfo si;
08495 struct dahdi_params p;
08496 int fd;
08497 int span;
08498 int ospan=0;
08499 int x,y;
08500 for (x = 0; x < NUM_SPANS; x++) {
08501 if (pris[x].trunkgroup == trunkgroup) {
08502 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08503 return -1;
08504 }
08505 }
08506 for (y = 0; y < NUM_DCHANS; y++) {
08507 if (!channels[y])
08508 break;
08509 memset(&si, 0, sizeof(si));
08510 memset(&p, 0, sizeof(p));
08511 fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
08512 if (fd < 0) {
08513 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08514 return -1;
08515 }
08516 x = channels[y];
08517 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08518 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08519 close(fd);
08520 return -1;
08521 }
08522 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08523 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08524 return -1;
08525 }
08526 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08527 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08528 close(fd);
08529 return -1;
08530 }
08531 span = p.spanno - 1;
08532 if (pris[span].trunkgroup) {
08533 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08534 close(fd);
08535 return -1;
08536 }
08537 if (pris[span].pvts[0]) {
08538 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08539 close(fd);
08540 return -1;
08541 }
08542 if (!y) {
08543 pris[span].trunkgroup = trunkgroup;
08544 pris[span].offset = channels[y] - p.chanpos;
08545 ospan = span;
08546 }
08547 pris[ospan].dchannels[y] = channels[y];
08548 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08549 pris[span].span = span + 1;
08550 close(fd);
08551 }
08552 return 0;
08553 }
08554
08555 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08556 {
08557 if (pris[span].mastertrunkgroup) {
08558 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);
08559 return -1;
08560 }
08561 pris[span].mastertrunkgroup = trunkgroup;
08562 pris[span].prilogicalspan = logicalspan;
08563 return 0;
08564 }
08565
08566 #endif
08567
08568 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08569 {
08570
08571 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
08572 char fn[80];
08573 #if 1
08574 struct dahdi_bufferinfo bi;
08575 #endif
08576 int res;
08577 int span=0;
08578 int here = 0;
08579 int x;
08580 struct dahdi_pvt **wlist;
08581 struct dahdi_pvt **wend;
08582 struct dahdi_params p;
08583
08584 wlist = &iflist;
08585 wend = &ifend;
08586
08587 #ifdef HAVE_PRI
08588 if (pri) {
08589 wlist = &pri->crvs;
08590 wend = &pri->crvend;
08591 }
08592 #endif
08593
08594 tmp2 = *wlist;
08595 prev = NULL;
08596
08597 while (tmp2) {
08598 if (!tmp2->destroy) {
08599 if (tmp2->channel == channel) {
08600 tmp = tmp2;
08601 here = 1;
08602 break;
08603 }
08604 if (tmp2->channel > channel) {
08605 break;
08606 }
08607 }
08608 prev = tmp2;
08609 tmp2 = tmp2->next;
08610 }
08611
08612 if (!here && reloading != 1) {
08613 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08614 if (tmp)
08615 free(tmp);
08616 return NULL;
08617 }
08618 ast_mutex_init(&tmp->lock);
08619 ifcount++;
08620 for (x = 0; x < 3; x++)
08621 tmp->subs[x].dfd = -1;
08622 tmp->channel = channel;
08623 tmp->priindication_oob = conf->chan.priindication_oob;
08624 }
08625
08626 if (tmp) {
08627 int chan_sig = conf->chan.sig;
08628 if (!here) {
08629 if ((channel != CHAN_PSEUDO) && !pri) {
08630 int count = 0;
08631 snprintf(fn, sizeof(fn), "%d", channel);
08632
08633 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08634 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
08635 usleep(1);
08636 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08637 count++;
08638 }
08639
08640 if (tmp->subs[SUB_REAL].dfd < 0) {
08641 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);
08642 destroy_dahdi_pvt(&tmp);
08643 return NULL;
08644 }
08645 memset(&p, 0, sizeof(p));
08646 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08647 if (res < 0) {
08648 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08649 destroy_dahdi_pvt(&tmp);
08650 return NULL;
08651 }
08652 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
08653 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));
08654 destroy_dahdi_pvt(&tmp);
08655 return NULL;
08656 }
08657 tmp->law = p.curlaw;
08658 tmp->span = p.spanno;
08659 span = p.spanno - 1;
08660 } else {
08661 if (channel == CHAN_PSEUDO)
08662 chan_sig = 0;
08663 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08664 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08665 return NULL;
08666 }
08667 }
08668 #ifdef HAVE_PRI
08669 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08670 int offset;
08671 int myswitchtype;
08672 int matchesdchan;
08673 int x,y;
08674 offset = 0;
08675 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08676 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08677 destroy_dahdi_pvt(&tmp);
08678 return NULL;
08679 }
08680 if (span >= NUM_SPANS) {
08681 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08682 destroy_dahdi_pvt(&tmp);
08683 return NULL;
08684 } else {
08685 struct dahdi_spaninfo si;
08686 si.spanno = 0;
08687 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08688 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08689 destroy_dahdi_pvt(&tmp);
08690 return NULL;
08691 }
08692
08693 tmp->logicalspan = pris[span].prilogicalspan;
08694 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08695 if (span < 0) {
08696 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08697 destroy_dahdi_pvt(&tmp);
08698 return NULL;
08699 }
08700 if (chan_sig == SIG_PRI)
08701 myswitchtype = conf->pri.switchtype;
08702 else
08703 myswitchtype = PRI_SWITCH_GR303_TMC;
08704
08705 matchesdchan=0;
08706 for (x = 0; x < NUM_SPANS; x++) {
08707 for (y = 0; y < NUM_DCHANS; y++) {
08708 if (pris[x].dchannels[y] == tmp->channel) {
08709 matchesdchan = 1;
08710 break;
08711 }
08712 }
08713 }
08714 offset = p.chanpos;
08715 if (!matchesdchan) {
08716 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08717 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08718 destroy_dahdi_pvt(&tmp);
08719 return NULL;
08720 }
08721 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08722 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08723 destroy_dahdi_pvt(&tmp);
08724 return NULL;
08725 }
08726 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08727 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08728 destroy_dahdi_pvt(&tmp);
08729 return NULL;
08730 }
08731 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08732 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08733 destroy_dahdi_pvt(&tmp);
08734 return NULL;
08735 }
08736 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08737 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08738 destroy_dahdi_pvt(&tmp);
08739 return NULL;
08740 }
08741 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08742 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08743 destroy_dahdi_pvt(&tmp);
08744 return NULL;
08745 }
08746 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08747 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08748 destroy_dahdi_pvt(&tmp);
08749 return NULL;
08750 }
08751 if (pris[span].numchans >= MAX_CHANNELS) {
08752 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08753 pris[span].trunkgroup);
08754 destroy_dahdi_pvt(&tmp);
08755 return NULL;
08756 }
08757 pris[span].nodetype = conf->pri.nodetype;
08758 pris[span].switchtype = myswitchtype;
08759 pris[span].nsf = conf->pri.nsf;
08760 pris[span].dialplan = conf->pri.dialplan;
08761 pris[span].localdialplan = conf->pri.localdialplan;
08762 pris[span].pvts[pris[span].numchans++] = tmp;
08763 pris[span].minunused = conf->pri.minunused;
08764 pris[span].minidle = conf->pri.minidle;
08765 pris[span].overlapdial = conf->pri.overlapdial;
08766 #ifdef HAVE_PRI_INBANDDISCONNECT
08767 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08768 #endif
08769 pris[span].facilityenable = conf->pri.facilityenable;
08770 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08771 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08772 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08773 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08774 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08775 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08776 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08777 pris[span].resetinterval = conf->pri.resetinterval;
08778
08779 tmp->pri = &pris[span];
08780 tmp->prioffset = offset;
08781 tmp->call = NULL;
08782 } else {
08783 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08784 destroy_dahdi_pvt(&tmp);
08785 return NULL;
08786 }
08787 }
08788 } else {
08789 tmp->prioffset = 0;
08790 }
08791 #endif
08792 #ifdef HAVE_OPENR2
08793 if (chan_sig == SIG_MFCR2 && reloading != 1) {
08794 char logdir[OR2_MAX_PATH];
08795 struct dahdi_mfcr2 *dahdi_r2;
08796 int threshold = 0;
08797 int snres = 0;
08798 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
08799 if (!dahdi_r2) {
08800 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
08801 } else if (!dahdi_r2->protocol_context){
08802 char tmplogdir[] = "/tmp";
08803 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
08804 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
08805 if (!dahdi_r2->protocol_context) {
08806 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
08807 destroy_dahdi_pvt(&tmp);
08808 return NULL;
08809 }
08810 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
08811 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
08812 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
08813 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
08814 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
08815 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
08816 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
08817 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
08818 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
08819 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
08820 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
08821 #endif
08822 if (ast_strlen_zero(mfcr2_cur_logdir)) {
08823 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
08824 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08825 }
08826 } else {
08827 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
08828 if (snres >= sizeof(logdir)) {
08829 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
08830 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08831 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08832 }
08833 } else {
08834 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08835 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
08836 }
08837 }
08838 }
08839 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
08840 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
08841 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
08842 }
08843 }
08844 }
08845 if (dahdi_r2) {
08846
08847 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
08848 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
08849 tmp->subs[SUB_REAL].dfd, NULL, NULL);
08850 if (!tmp->r2chan) {
08851 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
08852 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
08853 destroy_dahdi_pvt(&tmp);
08854 return NULL;
08855 }
08856 openr2_chan_set_client_data(tmp->r2chan, tmp);
08857
08858 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
08859 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
08860 if (mfcr2_cur_call_files) {
08861 openr2_chan_enable_call_files(tmp->r2chan);
08862 }
08863 tmp->mfcr2_category = mfcr2_cur_category;
08864 tmp->mfcr2 = dahdi_r2;
08865 tmp->mfcr2call = 0;
08866 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
08867 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
08868 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
08869 tmp->mfcr2_ani_index = 0;
08870 tmp->mfcr2_dnis_index = 0;
08871 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
08872 tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
08873 }
08874 }
08875 #endif
08876 } else {
08877 chan_sig = tmp->sig;
08878 if (tmp->subs[SUB_REAL].dfd > -1) {
08879 memset(&p, 0, sizeof(p));
08880 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08881 }
08882 }
08883
08884 switch (chan_sig) {
08885 case SIG_FXSKS:
08886 case SIG_FXSLS:
08887 case SIG_EM:
08888 case SIG_EM_E1:
08889 case SIG_EMWINK:
08890 case SIG_FEATD:
08891 case SIG_FEATDMF:
08892 case SIG_FEATDMF_TA:
08893 case SIG_FEATB:
08894 case SIG_E911:
08895 case SIG_SF:
08896 case SIG_SFWINK:
08897 case SIG_FGC_CAMA:
08898 case SIG_FGC_CAMAMF:
08899 case SIG_SF_FEATD:
08900 case SIG_SF_FEATDMF:
08901 case SIG_SF_FEATB:
08902 p.starttime = 250;
08903 break;
08904 }
08905
08906 if (tmp->radio) {
08907
08908 p.channo = channel;
08909 p.rxwinktime = 1;
08910 p.rxflashtime = 1;
08911 p.starttime = 1;
08912 p.debouncetime = 5;
08913 }
08914 if (!tmp->radio) {
08915 p.channo = channel;
08916
08917 if (conf->timing.prewinktime >= 0)
08918 p.prewinktime = conf->timing.prewinktime;
08919 if (conf->timing.preflashtime >= 0)
08920 p.preflashtime = conf->timing.preflashtime;
08921 if (conf->timing.winktime >= 0)
08922 p.winktime = conf->timing.winktime;
08923 if (conf->timing.flashtime >= 0)
08924 p.flashtime = conf->timing.flashtime;
08925 if (conf->timing.starttime >= 0)
08926 p.starttime = conf->timing.starttime;
08927 if (conf->timing.rxwinktime >= 0)
08928 p.rxwinktime = conf->timing.rxwinktime;
08929 if (conf->timing.rxflashtime >= 0)
08930 p.rxflashtime = conf->timing.rxflashtime;
08931 if (conf->timing.debouncetime >= 0)
08932 p.debouncetime = conf->timing.debouncetime;
08933 }
08934
08935
08936 if (tmp->subs[SUB_REAL].dfd >= 0)
08937 {
08938 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
08939 if (res < 0) {
08940 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
08941 destroy_dahdi_pvt(&tmp);
08942 return NULL;
08943 }
08944 }
08945 #if 1
08946 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
08947 memset(&bi, 0, sizeof(bi));
08948 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08949 if (!res) {
08950 bi.txbufpolicy = conf->chan.buf_policy;
08951 bi.rxbufpolicy = conf->chan.buf_policy;
08952 bi.numbufs = conf->chan.buf_no;
08953 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08954 if (res < 0) {
08955 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
08956 }
08957 } else
08958 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
08959 }
08960 #endif
08961 tmp->immediate = conf->chan.immediate;
08962 tmp->transfertobusy = conf->chan.transfertobusy;
08963 tmp->sig = chan_sig;
08964 tmp->outsigmod = conf->chan.outsigmod;
08965 tmp->ringt_base = ringt_base;
08966 tmp->firstradio = 0;
08967 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
08968 tmp->permcallwaiting = conf->chan.callwaiting;
08969 else
08970 tmp->permcallwaiting = 0;
08971
08972 tmp->destroy = 0;
08973 tmp->drings = drings;
08974 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
08975 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
08976 tmp->threewaycalling = conf->chan.threewaycalling;
08977 tmp->adsi = conf->chan.adsi;
08978 tmp->use_smdi = conf->chan.use_smdi;
08979 tmp->permhidecallerid = conf->chan.hidecallerid;
08980 tmp->callreturn = conf->chan.callreturn;
08981 tmp->echocancel = conf->chan.echocancel;
08982 tmp->echotraining = conf->chan.echotraining;
08983 tmp->pulse = conf->chan.pulse;
08984 if (tmp->echocancel)
08985 tmp->echocanbridged = conf->chan.echocanbridged;
08986 else {
08987 if (conf->chan.echocanbridged)
08988 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
08989 tmp->echocanbridged = 0;
08990 }
08991 tmp->busydetect = conf->chan.busydetect;
08992 tmp->busycount = conf->chan.busycount;
08993 tmp->busycompare = conf->chan.busycompare;
08994 tmp->busytonelength = conf->chan.busytonelength;
08995 tmp->busyquietlength = conf->chan.busyquietlength;
08996 tmp->busyfuzziness = conf->chan.busyfuzziness;
08997 tmp->silencethreshold = conf->chan.silencethreshold;
08998 tmp->callprogress = conf->chan.callprogress;
08999 tmp->cancallforward = conf->chan.cancallforward;
09000 tmp->dtmfrelax = conf->chan.dtmfrelax;
09001 tmp->callwaiting = tmp->permcallwaiting;
09002 tmp->hidecallerid = tmp->permhidecallerid;
09003 tmp->channel = channel;
09004 tmp->stripmsd = conf->chan.stripmsd;
09005 tmp->use_callerid = conf->chan.use_callerid;
09006 tmp->cid_signalling = conf->chan.cid_signalling;
09007 tmp->cid_start = conf->chan.cid_start;
09008 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09009 tmp->restrictcid = conf->chan.restrictcid;
09010 tmp->use_callingpres = conf->chan.use_callingpres;
09011 tmp->priexclusive = conf->chan.priexclusive;
09012 if (tmp->usedistinctiveringdetection) {
09013 if (!tmp->use_callerid) {
09014 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09015 tmp->use_callerid = 1;
09016 }
09017 }
09018
09019 if (tmp->cid_signalling == CID_SIG_SMDI) {
09020 if (!tmp->use_smdi) {
09021 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09022 tmp->use_smdi = 1;
09023 }
09024 }
09025 if (tmp->use_smdi) {
09026 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09027 if (!(tmp->smdi_iface)) {
09028 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09029 tmp->use_smdi = 0;
09030 }
09031 }
09032
09033 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09034 tmp->amaflags = conf->chan.amaflags;
09035 if (!here) {
09036 tmp->confno = -1;
09037 tmp->propconfno = -1;
09038 }
09039 tmp->canpark = conf->chan.canpark;
09040 tmp->transfer = conf->chan.transfer;
09041 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09042 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09043 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09044 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09045 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09046 tmp->cid_ton = 0;
09047 if (chan_sig != SIG_PRI) {
09048 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09049 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09050 } else {
09051 tmp->cid_num[0] = '\0';
09052 tmp->cid_name[0] = '\0';
09053 }
09054 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09055 tmp->msgstate = -1;
09056 tmp->group = conf->chan.group;
09057 tmp->callgroup = conf->chan.callgroup;
09058 tmp->pickupgroup= conf->chan.pickupgroup;
09059 tmp->rxgain = conf->chan.rxgain;
09060 tmp->txgain = conf->chan.txgain;
09061 tmp->tonezone = conf->chan.tonezone;
09062 tmp->onhooktime = time(NULL);
09063 if (tmp->subs[SUB_REAL].dfd > -1) {
09064 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09065 if (tmp->dsp)
09066 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09067 update_conf(tmp);
09068 if (!here) {
09069 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09070
09071 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09072 }
09073 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09074 #ifdef HAVE_PRI
09075
09076 if (tmp->pri && !pri_is_up(tmp->pri)) {
09077 tmp->inalarm = 1;
09078 }
09079 #endif
09080 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09081 tmp->inalarm = 1;
09082 handle_alarms(tmp, res);
09083 } else {
09084
09085
09086
09087
09088
09089
09090
09091
09092
09093
09094 tmp->unknown_alarm = 1;
09095 }
09096 }
09097
09098 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09099 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09100 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09101 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09102
09103 }
09104 if (tmp && !here) {
09105
09106 if (!*wlist) {
09107 *wlist = tmp;
09108 tmp->prev = NULL;
09109 tmp->next = NULL;
09110 *wend = tmp;
09111 } else {
09112
09113 struct dahdi_pvt *working = *wlist;
09114
09115
09116 if (working->channel > tmp->channel) {
09117 tmp->next = *wlist;
09118 tmp->prev = NULL;
09119 (*wlist)->prev = tmp;
09120 *wlist = tmp;
09121 } else {
09122
09123 while (working) {
09124
09125 if (working->next) {
09126 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09127 tmp->next = working->next;
09128 tmp->prev = working;
09129 working->next->prev = tmp;
09130 working->next = tmp;
09131 break;
09132 }
09133 } else {
09134
09135 if (working->channel < tmp->channel) {
09136 working->next = tmp;
09137 tmp->next = NULL;
09138 tmp->prev = working;
09139 *wend = tmp;
09140 break;
09141 }
09142 }
09143 working = working->next;
09144 }
09145 }
09146 }
09147 }
09148 return tmp;
09149 }
09150
09151 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09152 {
09153 int res;
09154 struct dahdi_params par;
09155
09156
09157 if (groupmatch) {
09158 if ((p->group & groupmatch) != groupmatch)
09159 return 0;
09160 *groupmatched = 1;
09161 }
09162
09163 if (channelmatch != -1) {
09164 if (p->channel != channelmatch)
09165 return 0;
09166 *channelmatched = 1;
09167 }
09168
09169 if (busy) {
09170 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09171 *busy = 1;
09172 }
09173
09174 if (p->dnd)
09175 return 0;
09176
09177 if (p->guardtime && (time(NULL) < p->guardtime))
09178 return 0;
09179
09180
09181 if (!p->owner) {
09182 #ifdef HAVE_PRI
09183
09184 if (p->pri) {
09185 if (p->resetting || p->call)
09186 return 0;
09187 else
09188 return 1;
09189 }
09190 #endif
09191 #ifdef HAVE_OPENR2
09192
09193 if (p->mfcr2) {
09194 if (p->mfcr2call || p->mfcr2block)
09195 return 0;
09196 else
09197 return 1;
09198 }
09199 #endif
09200 if (!(p->radio || (p->oprmode < 0)))
09201 {
09202 if (!p->sig || (p->sig == SIG_FXSLS))
09203 return 1;
09204
09205 if (p->subs[SUB_REAL].dfd > -1) {
09206 memset(&par, 0, sizeof(par));
09207 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09208 } else {
09209
09210 res = 0;
09211 par.rxisoffhook = 0;
09212 }
09213 if (res) {
09214 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09215 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09216
09217
09218
09219 if (par.rxbits > -1)
09220 return 1;
09221 if (par.rxisoffhook)
09222 return 1;
09223 else
09224 #ifdef DAHDI_CHECK_HOOKSTATE
09225 return 0;
09226 #else
09227 return 1;
09228 #endif
09229 } else if (par.rxisoffhook) {
09230 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09231
09232 return 0;
09233 }
09234 }
09235 return 1;
09236 }
09237
09238
09239 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
09240 return 0;
09241
09242 if (!p->callwaiting) {
09243
09244 return 0;
09245 }
09246
09247 if (p->subs[SUB_CALLWAIT].dfd > -1) {
09248
09249 return 0;
09250 }
09251
09252 if ((p->owner->_state != AST_STATE_UP) &&
09253 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09254
09255 return 0;
09256 }
09257 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09258
09259 return 0;
09260 }
09261
09262 return 1;
09263 }
09264
09265 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09266 {
09267 struct dahdi_pvt *p;
09268 struct dahdi_bufferinfo bi;
09269 int res;
09270
09271 if ((p = ast_malloc(sizeof(*p)))) {
09272 memcpy(p, src, sizeof(struct dahdi_pvt));
09273 ast_mutex_init(&p->lock);
09274 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09275
09276 if (p->subs[SUB_REAL].dfd < 0) {
09277 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
09278 destroy_dahdi_pvt(&p);
09279 return NULL;
09280 }
09281 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09282 if (!res) {
09283 bi.txbufpolicy = p->buf_policy;
09284 bi.rxbufpolicy = p->buf_policy;
09285 bi.numbufs = p->buf_no;
09286 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09287 if (res < 0) {
09288 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09289 }
09290 } else
09291 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09292 }
09293 p->destroy = 1;
09294 p->next = iflist;
09295 p->prev = NULL;
09296 iflist = p;
09297 if (iflist->next)
09298 iflist->next->prev = p;
09299 return p;
09300 }
09301
09302
09303 #ifdef HAVE_PRI
09304 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09305 {
09306 int x;
09307 if (backwards)
09308 x = pri->numchans;
09309 else
09310 x = 0;
09311 for (;;) {
09312 if (backwards && (x < 0))
09313 break;
09314 if (!backwards && (x >= pri->numchans))
09315 break;
09316 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09317 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
09318 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09319 return x;
09320 }
09321 if (backwards)
09322 x--;
09323 else
09324 x++;
09325 }
09326 return -1;
09327 }
09328 #endif
09329
09330 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09331 {
09332 ast_group_t groupmatch = 0;
09333 int channelmatch = -1;
09334 int roundrobin = 0;
09335 int callwait = 0;
09336 int busy = 0;
09337 struct dahdi_pvt *p;
09338 struct ast_channel *tmp = NULL;
09339 char *dest=NULL;
09340 int x;
09341 char *s;
09342 char opt=0;
09343 int res=0, y=0;
09344 int backwards = 0;
09345 #ifdef HAVE_PRI
09346 int crv;
09347 int bearer = -1;
09348 int trunkgroup;
09349 struct dahdi_pri *pri=NULL;
09350 #endif
09351 struct dahdi_pvt *exit, *start, *end;
09352 ast_mutex_t *lock;
09353 int channelmatched = 0;
09354 int groupmatched = 0;
09355
09356
09357
09358
09359
09360
09361
09362
09363
09364
09365
09366
09367
09368
09369
09370
09371
09372
09373
09374 lock = &iflock;
09375 start = iflist;
09376 end = ifend;
09377 if (data) {
09378 dest = ast_strdupa((char *)data);
09379 } else {
09380 ast_log(LOG_WARNING, "Channel requested with no data\n");
09381 return NULL;
09382 }
09383 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09384
09385 char *stringp;
09386
09387 stringp = dest + 1;
09388 s = strsep(&stringp, "/");
09389 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09390 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09391 return NULL;
09392 }
09393 groupmatch = ((ast_group_t) 1 << x);
09394 if (toupper(dest[0]) == 'G') {
09395 if (dest[0] == 'G') {
09396 backwards = 1;
09397 p = ifend;
09398 } else
09399 p = iflist;
09400 } else {
09401 if (dest[0] == 'R') {
09402 backwards = 1;
09403 p = round_robin[x]?round_robin[x]->prev:ifend;
09404 if (!p)
09405 p = ifend;
09406 } else {
09407 p = round_robin[x]?round_robin[x]->next:iflist;
09408 if (!p)
09409 p = iflist;
09410 }
09411 roundrobin = 1;
09412 }
09413 } else {
09414 char *stringp;
09415
09416 stringp = dest;
09417 s = strsep(&stringp, "/");
09418 p = iflist;
09419 if (!strcasecmp(s, "pseudo")) {
09420
09421 x = CHAN_PSEUDO;
09422 channelmatch = x;
09423 }
09424 #ifdef HAVE_PRI
09425 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09426 if ((trunkgroup < 1) || (crv < 1)) {
09427 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09428 return NULL;
09429 }
09430 res--;
09431 for (x = 0; x < NUM_SPANS; x++) {
09432 if (pris[x].trunkgroup == trunkgroup) {
09433 pri = pris + x;
09434 lock = &pri->lock;
09435 start = pri->crvs;
09436 end = pri->crvend;
09437 break;
09438 }
09439 }
09440 if (!pri) {
09441 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09442 return NULL;
09443 }
09444 channelmatch = crv;
09445 p = pris[x].crvs;
09446 }
09447 #endif
09448 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09449 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09450 return NULL;
09451 } else {
09452 channelmatch = x;
09453 }
09454 }
09455
09456 ast_mutex_lock(lock);
09457 exit = p;
09458 while (p && !tmp) {
09459 if (roundrobin)
09460 round_robin[x] = p;
09461 #if 0
09462 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09463 #endif
09464
09465 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09466 if (option_debug)
09467 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
09468 if (p->inalarm)
09469 goto next;
09470
09471 callwait = (p->owner != NULL);
09472 #ifdef HAVE_PRI
09473 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09474 if (p->sig != SIG_FXSKS) {
09475
09476
09477 bearer = pri_find_empty_chan(pri, 0);
09478 if (bearer < 0) {
09479 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09480 p = NULL;
09481 break;
09482 }
09483 pri_assign_bearer(p, pri, pri->pvts[bearer]);
09484 } else {
09485 if (alloc_sub(p, 0)) {
09486 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09487 p = NULL;
09488 break;
09489 } else
09490 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
09491 p->pri = pri;
09492 }
09493 }
09494 #endif
09495 #ifdef HAVE_OPENR2
09496 if (p->mfcr2) {
09497 ast_mutex_lock(&p->lock);
09498 if (p->mfcr2call) {
09499 ast_mutex_unlock(&p->lock);
09500 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
09501 goto next;
09502 }
09503 if (p->mfcr2block) {
09504 ast_mutex_unlock(&p->lock);
09505 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
09506 goto next;
09507 }
09508 p->mfcr2call = 1;
09509 ast_mutex_unlock(&p->lock);
09510 }
09511 #endif
09512 if (p->channel == CHAN_PSEUDO) {
09513 p = chandup(p);
09514 if (!p) {
09515 break;
09516 }
09517 }
09518 if (p->owner) {
09519 if (alloc_sub(p, SUB_CALLWAIT)) {
09520 p = NULL;
09521 break;
09522 }
09523 }
09524 p->outgoing = 1;
09525 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09526 if (!tmp) {
09527 p->outgoing = 0;
09528 }
09529 #ifdef HAVE_PRI
09530 if (p->bearer) {
09531
09532 p->bearer->owner = tmp;
09533 }
09534 #endif
09535
09536 if (res > 1) {
09537 if (opt == 'c') {
09538
09539 p->confirmanswer = 1;
09540 } else if (opt == 'r') {
09541
09542 if (res < 3)
09543 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09544 else
09545 p->distinctivering = y;
09546 } else if (opt == 'd') {
09547
09548 p->digital = 1;
09549 if (tmp)
09550 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09551 } else {
09552 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09553 }
09554 }
09555
09556 if (tmp && callwait)
09557 tmp->cdrflags |= AST_CDR_CALLWAIT;
09558 break;
09559 }
09560 next:
09561 if (backwards) {
09562 p = p->prev;
09563 if (!p)
09564 p = end;
09565 } else {
09566 p = p->next;
09567 if (!p)
09568 p = start;
09569 }
09570
09571 if (p == exit)
09572 break;
09573 }
09574 ast_mutex_unlock(lock);
09575 restart_monitor();
09576 if (callwait)
09577 *cause = AST_CAUSE_BUSY;
09578 else if (!tmp) {
09579 if (channelmatched) {
09580 if (busy)
09581 *cause = AST_CAUSE_BUSY;
09582 } else if (groupmatched) {
09583 *cause = AST_CAUSE_CONGESTION;
09584 }
09585 }
09586
09587 return tmp;
09588 }
09589
09590 #ifdef HAVE_OPENR2
09591 static void *mfcr2_monitor(void *data)
09592 {
09593 struct dahdi_pvt *p;
09594 struct dahdi_mfcr2 *mfcr2 = data;
09595
09596
09597
09598
09599
09600 struct pollfd pollers[sizeof(mfcr2->pvts)];
09601 int maxsleep = 20;
09602 int res = 0;
09603 int i = 0;
09604 int pollsize = 0;
09605 int oldstate = 0;
09606 int was_idle = 0;
09607 int quit_loop = 0;
09608
09609
09610 for (i = 0; i < mfcr2->numchans; i++) {
09611 p = mfcr2->pvts[i];
09612 if (openr2_chan_set_idle(p->r2chan)) {
09613 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
09614 } else {
09615 ast_mutex_lock(&p->lock);
09616 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
09617 mfcr2->pvts[i]->mfcr2call = 0;
09618 ast_mutex_unlock(&p->lock);
09619 }
09620 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
09621 }
09622 while(1) {
09623
09624
09625 pollsize = 0;
09626 for (i = 0; i < mfcr2->numchans; i++) {
09627 pollers[i].revents = 0;
09628 pollers[i].events = 0;
09629 if (mfcr2->pvts[i]->owner) {
09630 continue;
09631 }
09632 if (!mfcr2->pvts[i]->r2chan) {
09633 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
09634 quit_loop = 1;
09635 break;
09636 }
09637 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
09638 pollers[i].events = POLLIN | POLLPRI;
09639 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
09640 pollsize++;
09641 }
09642 if (quit_loop) {
09643 break;
09644 }
09645
09646 if (pollsize == 0) {
09647 if (!was_idle) {
09648 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
09649 was_idle = 1;
09650 }
09651 poll(NULL, 0, maxsleep);
09652 continue;
09653 }
09654 was_idle = 0;
09655
09656
09657
09658 pthread_testcancel();
09659 res = poll(pollers, pollsize, maxsleep);
09660 pthread_testcancel();
09661 if ((res < 0) && (errno != EINTR)) {
09662 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
09663 break;
09664 }
09665
09666 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
09667 for (i = 0; i < mfcr2->numchans; i++) {
09668 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
09669 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
09670 }
09671 }
09672 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
09673 }
09674 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
09675 return 0;
09676 }
09677 #endif
09678
09679
09680 #ifdef HAVE_PRI
09681 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
09682 {
09683 struct dahdi_pvt *p;
09684 p = pri->crvs;
09685 while (p) {
09686 if (p->channel == crv)
09687 return p;
09688 p = p->next;
09689 }
09690 return NULL;
09691 }
09692
09693
09694 static int pri_find_principle(struct dahdi_pri *pri, int channel)
09695 {
09696 int x;
09697 int span = PRI_SPAN(channel);
09698 int spanfd;
09699 struct dahdi_params param;
09700 int principle = -1;
09701 int explicit = PRI_EXPLICIT(channel);
09702 channel = PRI_CHANNEL(channel);
09703
09704 if (!explicit) {
09705 spanfd = pri_active_dchan_fd(pri);
09706 memset(¶m, 0, sizeof(param));
09707 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
09708 return -1;
09709 span = pris[param.spanno - 1].prilogicalspan;
09710 }
09711
09712 for (x = 0; x < pri->numchans; x++) {
09713 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
09714 principle = x;
09715 break;
09716 }
09717 }
09718
09719 return principle;
09720 }
09721
09722 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
09723 {
09724 int x;
09725 struct dahdi_pvt *crv;
09726 if (!c) {
09727 if (principle < 0)
09728 return -1;
09729 return principle;
09730 }
09731 if ((principle > -1) &&
09732 (principle < pri->numchans) &&
09733 (pri->pvts[principle]) &&
09734 (pri->pvts[principle]->call == c))
09735 return principle;
09736
09737 for (x = 0; x < pri->numchans; x++) {
09738 if (!pri->pvts[x])
09739 continue;
09740 if (pri->pvts[x]->call == c) {
09741
09742 if (principle != x) {
09743 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
09744
09745 if (option_verbose > 2)
09746 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
09747 old->channel, new->channel);
09748 if (new->owner) {
09749 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
09750 old->channel, new->channel, new->channel);
09751 return -1;
09752 }
09753
09754 new->owner = old->owner;
09755 old->owner = NULL;
09756 if (new->owner) {
09757 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
09758 new->owner->tech_pvt = new;
09759 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
09760 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
09761 old->subs[SUB_REAL].owner = NULL;
09762 } else
09763 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);
09764 new->call = old->call;
09765 old->call = NULL;
09766
09767
09768 new->dsp = old->dsp;
09769 new->dsp_features = old->dsp_features;
09770 old->dsp = NULL;
09771 old->dsp_features = 0;
09772 }
09773 return principle;
09774 }
09775 }
09776
09777 crv = pri->crvs;
09778 while (crv) {
09779 if (crv->call == c) {
09780
09781 if (crv->bearer)
09782 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
09783 else if (pri->pvts[principle]->owner)
09784 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
09785 else {
09786
09787
09788 dahdi_close_sub(crv, SUB_REAL);
09789 pri->pvts[principle]->call = crv->call;
09790 pri_assign_bearer(crv, pri, pri->pvts[principle]);
09791 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
09792 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
09793 pri->trunkgroup, crv->channel);
09794 wakeup_sub(crv, SUB_REAL, pri);
09795 }
09796 return principle;
09797 }
09798 crv = crv->next;
09799 }
09800 ast_log(LOG_WARNING, "Call specified, but not found?\n");
09801 return -1;
09802 }
09803
09804 static void *do_idle_thread(void *vchan)
09805 {
09806 struct ast_channel *chan = vchan;
09807 struct dahdi_pvt *pvt = chan->tech_pvt;
09808 struct ast_frame *f;
09809 char ex[80];
09810
09811 int newms, ms = 30000;
09812 if (option_verbose > 2)
09813 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
09814 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
09815 if (ast_call(chan, ex, 0)) {
09816 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
09817 ast_hangup(chan);
09818 return NULL;
09819 }
09820 while ((newms = ast_waitfor(chan, ms)) > 0) {
09821 f = ast_read(chan);
09822 if (!f) {
09823
09824 break;
09825 }
09826 if (f->frametype == AST_FRAME_CONTROL) {
09827 switch (f->subclass) {
09828 case AST_CONTROL_ANSWER:
09829
09830 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
09831 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
09832 chan->priority = 1;
09833 if (option_verbose > 3)
09834 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
09835 ast_pbx_run(chan);
09836
09837 return NULL;
09838 case AST_CONTROL_BUSY:
09839 if (option_verbose > 3)
09840 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
09841 break;
09842 case AST_CONTROL_CONGESTION:
09843 if (option_verbose > 3)
09844 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
09845 break;
09846 };
09847 }
09848 ast_frfree(f);
09849 ms = newms;
09850 }
09851
09852 ast_hangup(chan);
09853 return NULL;
09854 }
09855
09856 #ifndef PRI_RESTART
09857 #error "Upgrade your libpri"
09858 #endif
09859 static void dahdi_pri_message(struct pri *pri, char *s)
09860 {
09861 int x, y;
09862 int dchan = -1, span = -1;
09863 int dchancount = 0;
09864
09865 if (pri) {
09866 for (x = 0; x < NUM_SPANS; x++) {
09867 for (y = 0; y < NUM_DCHANS; y++) {
09868 if (pris[x].dchans[y])
09869 dchancount++;
09870
09871 if (pris[x].dchans[y] == pri)
09872 dchan = y;
09873 }
09874 if (dchan >= 0) {
09875 span = x;
09876 break;
09877 }
09878 dchancount = 0;
09879 }
09880 if ((dchan >= 0) && (span >= 0)) {
09881 if (dchancount > 1)
09882 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
09883 else
09884 ast_verbose("%s", s);
09885 } else
09886 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09887 } else
09888 ast_verbose("%s", s);
09889
09890 ast_mutex_lock(&pridebugfdlock);
09891
09892 if (pridebugfd >= 0) {
09893 if (write(pridebugfd, s, strlen(s)) < 0) {
09894 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09895 }
09896 }
09897
09898 ast_mutex_unlock(&pridebugfdlock);
09899 }
09900
09901 static void dahdi_pri_error(struct pri *pri, char *s)
09902 {
09903 int x, y;
09904 int dchan = -1, span = -1;
09905 int dchancount = 0;
09906
09907 if (pri) {
09908 for (x = 0; x < NUM_SPANS; x++) {
09909 for (y = 0; y < NUM_DCHANS; y++) {
09910 if (pris[x].dchans[y])
09911 dchancount++;
09912
09913 if (pris[x].dchans[y] == pri)
09914 dchan = y;
09915 }
09916 if (dchan >= 0) {
09917 span = x;
09918 break;
09919 }
09920 dchancount = 0;
09921 }
09922 if ((dchan >= 0) && (span >= 0)) {
09923 if (dchancount > 1)
09924 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
09925 else
09926 ast_log(LOG_ERROR, "%s", s);
09927 } else
09928 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09929 } else
09930 ast_log(LOG_ERROR, "%s", s);
09931
09932 ast_mutex_lock(&pridebugfdlock);
09933
09934 if (pridebugfd >= 0) {
09935 if (write(pridebugfd, s, strlen(s)) < 0) {
09936 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09937 }
09938 }
09939
09940 ast_mutex_unlock(&pridebugfdlock);
09941 }
09942
09943 static int pri_check_restart(struct dahdi_pri *pri)
09944 {
09945 do {
09946 pri->resetpos++;
09947 } while ((pri->resetpos < pri->numchans) &&
09948 (!pri->pvts[pri->resetpos] ||
09949 pri->pvts[pri->resetpos]->call ||
09950 pri->pvts[pri->resetpos]->resetting));
09951 if (pri->resetpos < pri->numchans) {
09952
09953 pri->pvts[pri->resetpos]->resetting = 1;
09954 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
09955 } else {
09956 pri->resetting = 0;
09957 time(&pri->lastreset);
09958 }
09959 return 0;
09960 }
09961
09962 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
09963 {
09964 int x;
09965 int redo;
09966 ast_mutex_unlock(&pri->lock);
09967 ast_mutex_lock(&p->lock);
09968 do {
09969 redo = 0;
09970 for (x = 0; x < 3; x++) {
09971 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
09972 redo++;
09973 DEADLOCK_AVOIDANCE(&p->lock);
09974 }
09975 if (p->subs[x].owner) {
09976 ast_queue_hangup(p->subs[x].owner);
09977 ast_mutex_unlock(&p->subs[x].owner->lock);
09978 }
09979 }
09980 } while (redo);
09981 ast_mutex_unlock(&p->lock);
09982 ast_mutex_lock(&pri->lock);
09983 return 0;
09984 }
09985
09986 static char * redirectingreason2str(int redirectingreason)
09987 {
09988 switch (redirectingreason) {
09989 case 0:
09990 return "UNKNOWN";
09991 case 1:
09992 return "BUSY";
09993 case 2:
09994 return "NO_REPLY";
09995 case 0xF:
09996 return "UNCONDITIONAL";
09997 default:
09998 return "NOREDIRECT";
09999 }
10000 }
10001
10002 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10003 {
10004 if (ast_strlen_zero(number)) {
10005 if (size) {
10006 *buf = '\0';
10007 }
10008 return;
10009 }
10010
10011 switch (plan) {
10012 case PRI_INTERNATIONAL_ISDN:
10013 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10014 break;
10015 case PRI_NATIONAL_ISDN:
10016 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10017 break;
10018 case PRI_LOCAL_ISDN:
10019 snprintf(buf, size, "%s%s", pri->localprefix, number);
10020 break;
10021 case PRI_PRIVATE:
10022 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10023 break;
10024 case PRI_UNKNOWN:
10025 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10026 break;
10027 default:
10028 snprintf(buf, size, "%s", number);
10029 break;
10030 }
10031 }
10032
10033 static int dahdi_setlaw(int dfd, int law)
10034 {
10035 int res;
10036 res = ioctl(dfd, DAHDI_SETLAW, &law);
10037 if (res)
10038 return res;
10039 return 0;
10040 }
10041
10042 static void *pri_dchannel(void *vpri)
10043 {
10044 struct dahdi_pri *pri = vpri;
10045 pri_event *e;
10046 struct pollfd fds[NUM_DCHANS];
10047 int res;
10048 int chanpos = 0;
10049 int x;
10050 int haveidles;
10051 int activeidles;
10052 int nextidle = -1;
10053 struct ast_channel *c;
10054 struct timeval tv, lowest, *next;
10055 struct timeval lastidle = { 0, 0 };
10056 int doidling=0;
10057 char *cc;
10058 char idlen[80];
10059 struct ast_channel *idle;
10060 pthread_t p;
10061 time_t t;
10062 int i, which=-1;
10063 int numdchans;
10064 int cause=0;
10065 struct dahdi_pvt *crv;
10066 pthread_t threadid;
10067 pthread_attr_t attr;
10068 char ani2str[6];
10069 char plancallingnum[256];
10070 char plancallingani[256];
10071 char calledtonstr[10];
10072
10073 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10074
10075 gettimeofday(&lastidle, NULL);
10076 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10077
10078 cc = strchr(pri->idleext, '@');
10079 if (cc) {
10080 *cc = '\0';
10081 cc++;
10082 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10083 #if 0
10084
10085 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10086 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10087 else
10088 #endif
10089 doidling = 1;
10090 } else
10091 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10092 }
10093 for (;;) {
10094 for (i = 0; i < NUM_DCHANS; i++) {
10095 if (!pri->dchannels[i])
10096 break;
10097 fds[i].fd = pri->fds[i];
10098 fds[i].events = POLLIN | POLLPRI;
10099 fds[i].revents = 0;
10100 }
10101 numdchans = i;
10102 time(&t);
10103 ast_mutex_lock(&pri->lock);
10104 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10105 if (pri->resetting && pri_is_up(pri)) {
10106 if (pri->resetpos < 0)
10107 pri_check_restart(pri);
10108 } else {
10109 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10110 pri->resetting = 1;
10111 pri->resetpos = -1;
10112 }
10113 }
10114 }
10115
10116 if (doidling && pri_is_up(pri)) {
10117 nextidle = -1;
10118 haveidles = 0;
10119 activeidles = 0;
10120 for (x = pri->numchans; x >= 0; x--) {
10121 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10122 !pri->pvts[x]->call) {
10123 if (haveidles < pri->minunused) {
10124 haveidles++;
10125 } else if (!pri->pvts[x]->resetting) {
10126 nextidle = x;
10127 break;
10128 }
10129 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10130 activeidles++;
10131 }
10132 if (nextidle > -1) {
10133 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10134
10135 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10136 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
10137 if (idle) {
10138 pri->pvts[nextidle]->isidlecall = 1;
10139 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10140 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10141 dahdi_hangup(idle);
10142 }
10143 } else
10144 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10145 gettimeofday(&lastidle, NULL);
10146 }
10147 } else if ((haveidles < pri->minunused) &&
10148 (activeidles > pri->minidle)) {
10149
10150
10151 for (x = pri->numchans; x >= 0; x--) {
10152
10153 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10154 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10155 haveidles++;
10156
10157
10158 if ((haveidles >= pri->minunused) ||
10159 (activeidles <= pri->minidle))
10160 break;
10161 }
10162 }
10163 }
10164 }
10165
10166 lowest = ast_tv(60, 0);
10167 for (i = 0; i < NUM_DCHANS; i++) {
10168
10169 if (!pri->dchannels[i])
10170 break;
10171 if ((next = pri_schedule_next(pri->dchans[i]))) {
10172
10173 tv = ast_tvsub(*next, ast_tvnow());
10174 if (tv.tv_sec < 0) {
10175 tv = ast_tv(0,0);
10176 }
10177 if (doidling || pri->resetting) {
10178 if (tv.tv_sec > 1) {
10179 tv = ast_tv(1, 0);
10180 }
10181 } else {
10182 if (tv.tv_sec > 60) {
10183 tv = ast_tv(60, 0);
10184 }
10185 }
10186 } else if (doidling || pri->resetting) {
10187
10188
10189 tv = ast_tv(1,0);
10190 } else {
10191
10192 tv = ast_tv(60, 0);
10193 }
10194 if (!i || ast_tvcmp(tv, lowest) < 0) {
10195 lowest = tv;
10196 }
10197 }
10198 ast_mutex_unlock(&pri->lock);
10199
10200 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10201 pthread_testcancel();
10202 e = NULL;
10203 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10204 pthread_testcancel();
10205 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10206
10207 ast_mutex_lock(&pri->lock);
10208 if (!res) {
10209 for (which = 0; which < NUM_DCHANS; which++) {
10210 if (!pri->dchans[which])
10211 break;
10212
10213 e = pri_schedule_run(pri->dchans[which]);
10214 if (e)
10215 break;
10216 }
10217 } else if (res > -1) {
10218 for (which = 0; which < NUM_DCHANS; which++) {
10219 if (!pri->dchans[which])
10220 break;
10221 if (fds[which].revents & POLLPRI) {
10222
10223 x = 0;
10224 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10225 if (x)
10226 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);
10227
10228 if (x == DAHDI_EVENT_ALARM) {
10229 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10230 pri_find_dchan(pri);
10231 } else if (x == DAHDI_EVENT_NOALARM) {
10232 pri->dchanavail[which] |= DCHAN_NOTINALARM;
10233 pri_restart(pri->dchans[which]);
10234 }
10235
10236 if (option_debug)
10237 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10238 } else if (fds[which].revents & POLLIN) {
10239 e = pri_check_event(pri->dchans[which]);
10240 }
10241 if (e)
10242 break;
10243 }
10244 } else if (errno != EINTR)
10245 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10246
10247 if (e) {
10248 if (pri->debug)
10249 pri_dump_event(pri->dchans[which], e);
10250
10251 if (e->e != PRI_EVENT_DCHAN_DOWN) {
10252 if (!(pri->dchanavail[which] & DCHAN_UP)) {
10253 if (option_verbose > 1)
10254 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10255 }
10256 pri->dchanavail[which] |= DCHAN_UP;
10257 } else {
10258 if (pri->dchanavail[which] & DCHAN_UP) {
10259 if (option_verbose > 1)
10260 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10261 }
10262 pri->dchanavail[which] &= ~DCHAN_UP;
10263 }
10264
10265 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10266
10267 pri->pri = pri->dchans[which];
10268
10269 switch (e->e) {
10270 case PRI_EVENT_DCHAN_UP:
10271 if (!pri->pri) pri_find_dchan(pri);
10272
10273
10274 time(&pri->lastreset);
10275
10276
10277 if (pri->resetinterval > -1) {
10278 pri->lastreset -= pri->resetinterval;
10279 pri->lastreset += 5;
10280 }
10281 pri->resetting = 0;
10282
10283 for (i = 0; i < pri->numchans; i++)
10284 if (pri->pvts[i]) {
10285 pri->pvts[i]->inalarm = 0;
10286 }
10287 break;
10288 case PRI_EVENT_DCHAN_DOWN:
10289 pri_find_dchan(pri);
10290 if (!pri_is_up(pri)) {
10291 pri->resetting = 0;
10292
10293 for (i = 0; i < pri->numchans; i++) {
10294 struct dahdi_pvt *p = pri->pvts[i];
10295 if (p) {
10296 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10297
10298 if (p->call) {
10299 if (p->pri && p->pri->pri) {
10300 pri_hangup(p->pri->pri, p->call, -1);
10301 pri_destroycall(p->pri->pri, p->call);
10302 p->call = NULL;
10303 } else
10304 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10305 }
10306 if (p->realcall) {
10307 pri_hangup_all(p->realcall, pri);
10308 } else if (p->owner)
10309 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10310 }
10311 p->inalarm = 1;
10312 }
10313 }
10314 }
10315 break;
10316 case PRI_EVENT_RESTART:
10317 if (e->restart.channel > -1) {
10318 chanpos = pri_find_principle(pri, e->restart.channel);
10319 if (chanpos < 0)
10320 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10321 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10322 else {
10323 if (option_verbose > 2)
10324 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
10325 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10326 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10327 if (pri->pvts[chanpos]->call) {
10328 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10329 pri->pvts[chanpos]->call = NULL;
10330 }
10331
10332 if (pri->pvts[chanpos]->realcall)
10333 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10334 else if (pri->pvts[chanpos]->owner)
10335 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10336 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10337 }
10338 } else {
10339 if (option_verbose > 2)
10340 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
10341 for (x = 0; x < pri->numchans; x++)
10342 if (pri->pvts[x]) {
10343 ast_mutex_lock(&pri->pvts[x]->lock);
10344 if (pri->pvts[x]->call) {
10345 pri_destroycall(pri->pri, pri->pvts[x]->call);
10346 pri->pvts[x]->call = NULL;
10347 }
10348 if (pri->pvts[x]->realcall)
10349 pri_hangup_all(pri->pvts[x]->realcall, pri);
10350 else if (pri->pvts[x]->owner)
10351 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10352 ast_mutex_unlock(&pri->pvts[x]->lock);
10353 }
10354 }
10355 break;
10356 case PRI_EVENT_KEYPAD_DIGIT:
10357 chanpos = pri_find_principle(pri, e->digit.channel);
10358 if (chanpos < 0) {
10359 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10360 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10361 } else {
10362 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10363 if (chanpos > -1) {
10364 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10365
10366 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
10367
10368 int digitlen = strlen(e->digit.digits);
10369 char digit;
10370 int i;
10371 for (i = 0; i < digitlen; i++) {
10372 digit = e->digit.digits[i];
10373 {
10374 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10375 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10376 }
10377 }
10378 }
10379 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10380 }
10381 }
10382 break;
10383
10384 case PRI_EVENT_INFO_RECEIVED:
10385 chanpos = pri_find_principle(pri, e->ring.channel);
10386 if (chanpos < 0) {
10387 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
10388 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10389 } else {
10390 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
10391 if (chanpos > -1) {
10392 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10393
10394 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
10395
10396 int digitlen = strlen(e->ring.callednum);
10397 char digit;
10398 int i;
10399 for (i = 0; i < digitlen; i++) {
10400 digit = e->ring.callednum[i];
10401 {
10402 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10403 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10404 }
10405 }
10406 }
10407 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10408 }
10409 }
10410 break;
10411 case PRI_EVENT_RING:
10412 crv = NULL;
10413 if (e->ring.channel == -1)
10414 chanpos = pri_find_empty_chan(pri, 1);
10415 else
10416 chanpos = pri_find_principle(pri, e->ring.channel);
10417
10418 if (chanpos < 0) {
10419 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
10420 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10421 } else {
10422 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10423 if (pri->pvts[chanpos]->owner) {
10424 if (pri->pvts[chanpos]->call == e->ring.call) {
10425 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
10426 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10427 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10428 break;
10429 } else {
10430
10431 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
10432 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10433 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10434 chanpos = -1;
10435 }
10436 }
10437 if (chanpos > -1)
10438 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10439 }
10440 if ((chanpos < 0) && (e->ring.flexible))
10441 chanpos = pri_find_empty_chan(pri, 1);
10442 if (chanpos > -1) {
10443 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10444 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
10445
10446 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
10447 if (crv)
10448 ast_mutex_lock(&crv->lock);
10449 if (!crv || crv->owner) {
10450 pri->pvts[chanpos]->call = NULL;
10451 if (crv) {
10452 if (crv->owner)
10453 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10454 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);
10455 } else
10456 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);
10457 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
10458 if (crv)
10459 ast_mutex_unlock(&crv->lock);
10460 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10461 break;
10462 }
10463 }
10464 pri->pvts[chanpos]->call = e->ring.call;
10465 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
10466 if (pri->pvts[chanpos]->use_callerid) {
10467 ast_shrink_phone_number(plancallingnum);
10468 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
10469 #ifdef PRI_ANI
10470 if (!ast_strlen_zero(e->ring.callingani)) {
10471 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
10472 ast_shrink_phone_number(plancallingani);
10473 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
10474 } else {
10475 pri->pvts[chanpos]->cid_ani[0] = '\0';
10476 }
10477 #endif
10478 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
10479 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
10480 } else {
10481 pri->pvts[chanpos]->cid_num[0] = '\0';
10482 pri->pvts[chanpos]->cid_ani[0] = '\0';
10483 pri->pvts[chanpos]->cid_name[0] = '\0';
10484 pri->pvts[chanpos]->cid_ton = 0;
10485 }
10486 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
10487 e->ring.redirectingnum, e->ring.callingplanrdnis);
10488
10489 if (pri->pvts[chanpos]->immediate) {
10490 if (option_verbose > 2)
10491 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
10492 pri->pvts[chanpos]->exten[0] = 's';
10493 pri->pvts[chanpos]->exten[1] = '\0';
10494 }
10495
10496 else if (!ast_strlen_zero(e->ring.callednum)) {
10497 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
10498 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10499 } else if (pri->overlapdial)
10500 pri->pvts[chanpos]->exten[0] = '\0';
10501 else {
10502
10503 pri->pvts[chanpos]->exten[0] = 's';
10504 pri->pvts[chanpos]->exten[1] = '\0';
10505 }
10506
10507 if (!ast_strlen_zero(e->ring.callednum))
10508 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10509
10510 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
10511 if (option_verbose > 2)
10512 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
10513 pri->pvts[chanpos]->exten[0] = 's';
10514 pri->pvts[chanpos]->exten[1] = '\0';
10515 }
10516
10517
10518 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
10519 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10520
10521 int law;
10522 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
10523
10524 law = 1;
10525 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
10526 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
10527 }
10528 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
10529 law = DAHDI_LAW_ALAW;
10530 else
10531 law = DAHDI_LAW_MULAW;
10532 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
10533 if (res < 0)
10534 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
10535 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10536 if (res < 0)
10537 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
10538 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
10539
10540 pri->pvts[chanpos]->proceeding = 1;
10541 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
10542 } else {
10543 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
10544 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10545 else
10546 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10547 }
10548
10549 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
10550
10551
10552 if (!e->ring.complete
10553 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
10554 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10555
10556
10557
10558
10559 ast_mutex_unlock(&pri->lock);
10560 if (crv) {
10561
10562 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
10563 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10564 pri->pvts[chanpos]->owner = &inuse;
10565 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
10566 } else {
10567 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10568 }
10569 ast_mutex_lock(&pri->lock);
10570 if (c) {
10571 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10572 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10573 }
10574 if (e->ring.ani2 >= 0) {
10575 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10576 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10577 }
10578
10579 #ifdef SUPPORT_USERUSER
10580 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10581 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10582 }
10583 #endif
10584
10585 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10586 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10587 if (e->ring.redirectingreason >= 0)
10588 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10589 }
10590
10591 pthread_attr_init(&attr);
10592 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10593 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
10594 if (option_verbose > 2)
10595 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10596 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
10597 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10598 } else {
10599 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10600 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10601 if (c)
10602 ast_hangup(c);
10603 else {
10604 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10605 pri->pvts[chanpos]->call = NULL;
10606 }
10607 }
10608 pthread_attr_destroy(&attr);
10609 } else {
10610
10611
10612
10613
10614 ast_mutex_unlock(&pri->lock);
10615 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
10616 ast_mutex_lock(&pri->lock);
10617 if (c) {
10618
10619
10620
10621
10622
10623
10624
10625
10626 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10627 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10628 }
10629 if (e->ring.ani2 >= 0) {
10630 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10631 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10632 }
10633
10634 #ifdef SUPPORT_USERUSER
10635 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10636 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10637 }
10638 #endif
10639
10640 if (e->ring.redirectingreason >= 0)
10641 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10642
10643 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10644 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10645 }
10646 if (c && !ast_pbx_start(c)) {
10647 if (option_verbose > 2)
10648 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10649 plancallingnum, pri->pvts[chanpos]->exten,
10650 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10651
10652 dahdi_enable_ec(pri->pvts[chanpos]);
10653 } else {
10654 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10655 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10656 if (c) {
10657 ast_hangup(c);
10658 } else {
10659 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10660 pri->pvts[chanpos]->call = NULL;
10661 }
10662 }
10663 }
10664 } else {
10665 if (option_verbose > 2)
10666 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
10667 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
10668 pri->pvts[chanpos]->prioffset, pri->span);
10669 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
10670 pri->pvts[chanpos]->call = NULL;
10671 pri->pvts[chanpos]->exten[0] = '\0';
10672 }
10673 if (crv)
10674 ast_mutex_unlock(&crv->lock);
10675 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10676 } else {
10677 if (e->ring.flexible)
10678 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
10679 else
10680 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
10681 }
10682 break;
10683 case PRI_EVENT_RINGING:
10684 chanpos = pri_find_principle(pri, e->ringing.channel);
10685 if (chanpos < 0) {
10686 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
10687 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10688 } else {
10689 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
10690 if (chanpos < 0) {
10691 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
10692 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10693 } else {
10694 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10695 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10696 dahdi_enable_ec(pri->pvts[chanpos]);
10697 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
10698 pri->pvts[chanpos]->alerting = 1;
10699 } else
10700 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
10701 #ifdef PRI_PROGRESS_MASK
10702 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10703 #else
10704 if (e->ringing.progress == 8) {
10705 #endif
10706
10707 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10708
10709 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
10710 pri->pvts[chanpos]->dsp_features = 0;
10711 }
10712 }
10713
10714 #ifdef SUPPORT_USERUSER
10715 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
10716 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10717 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10718 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
10719 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10720 }
10721 #endif
10722
10723 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10724 }
10725 }
10726 break;
10727 case PRI_EVENT_PROGRESS:
10728
10729 chanpos = pri_find_principle(pri, e->proceeding.channel);
10730 if (chanpos > -1) {
10731 #ifdef PRI_PROGRESS_MASK
10732 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
10733 #else
10734 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
10735 #endif
10736 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10737
10738 if (e->proceeding.cause > -1) {
10739 if (option_verbose > 2)
10740 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
10741
10742
10743 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
10744 if (pri->pvts[chanpos]->owner) {
10745 if (option_verbose > 2)
10746 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
10747
10748 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
10749 f.subclass = AST_CONTROL_BUSY;
10750 }
10751 }
10752 }
10753
10754 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10755 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
10756 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10757 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10758 #ifdef PRI_PROGRESS_MASK
10759 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10760 #else
10761 if (e->proceeding.progress == 8) {
10762 #endif
10763
10764 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10765 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10766 pri->pvts[chanpos]->dsp_features = 0;
10767 }
10768
10769 f.subclass = AST_CONTROL_PROGRESS;
10770 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10771 }
10772 pri->pvts[chanpos]->progress = 1;
10773 pri->pvts[chanpos]->dialing = 0;
10774 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10775 }
10776 }
10777 break;
10778 case PRI_EVENT_PROCEEDING:
10779 chanpos = pri_find_principle(pri, e->proceeding.channel);
10780 if (chanpos > -1) {
10781 if (!pri->pvts[chanpos]->proceeding) {
10782 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10783
10784 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10785 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
10786 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10787 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10788 #ifdef PRI_PROGRESS_MASK
10789 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10790 #else
10791 if (e->proceeding.progress == 8) {
10792 #endif
10793
10794 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10795 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10796 pri->pvts[chanpos]->dsp_features = 0;
10797 }
10798
10799 f.subclass = AST_CONTROL_PROGRESS;
10800 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10801 }
10802 pri->pvts[chanpos]->proceeding = 1;
10803 pri->pvts[chanpos]->dialing = 0;
10804 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10805 }
10806 }
10807 break;
10808 case PRI_EVENT_FACNAME:
10809 chanpos = pri_find_principle(pri, e->facname.channel);
10810 if (chanpos < 0) {
10811 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
10812 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10813 } else {
10814 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
10815 if (chanpos < 0) {
10816 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
10817 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10818 } else {
10819
10820 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10821 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
10822 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
10823 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
10824 dahdi_enable_ec(pri->pvts[chanpos]);
10825 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10826 }
10827 }
10828 break;
10829 case PRI_EVENT_ANSWER:
10830 chanpos = pri_find_principle(pri, e->answer.channel);
10831 if (chanpos < 0) {
10832 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
10833 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10834 } else {
10835 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
10836 if (chanpos < 0) {
10837 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
10838 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10839 } else {
10840 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10841
10842
10843
10844
10845
10846 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10847 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10848 pri->pvts[chanpos]->dsp_features = 0;
10849 }
10850 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
10851 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
10852 x = DAHDI_START;
10853 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10854 if (res < 0) {
10855 if (errno != EINPROGRESS) {
10856 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
10857 }
10858 }
10859 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10860 pri->pvts[chanpos]->dialing = 1;
10861
10862 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
10863 if (res < 0) {
10864 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
10865 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10866 } else
10867 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
10868 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10869 } else if (pri->pvts[chanpos]->confirmanswer) {
10870 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
10871 } else {
10872 pri->pvts[chanpos]->dialing = 0;
10873 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
10874
10875 dahdi_enable_ec(pri->pvts[chanpos]);
10876 }
10877
10878 #ifdef SUPPORT_USERUSER
10879 if (!ast_strlen_zero(e->answer.useruserinfo)) {
10880 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10881 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10882 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
10883 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10884 }
10885 #endif
10886
10887 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10888 }
10889 }
10890 break;
10891 case PRI_EVENT_HANGUP:
10892 chanpos = pri_find_principle(pri, e->hangup.channel);
10893 if (chanpos < 0) {
10894 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
10895 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10896 } else {
10897 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10898 if (chanpos > -1) {
10899 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10900 if (!pri->pvts[chanpos]->alreadyhungup) {
10901
10902 pri->pvts[chanpos]->alreadyhungup = 1;
10903 if (pri->pvts[chanpos]->realcall)
10904 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10905 else if (pri->pvts[chanpos]->owner) {
10906
10907 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10908 switch (pri->pvts[chanpos]->owner->_state) {
10909 case AST_STATE_BUSY:
10910 case AST_STATE_UP:
10911 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10912 break;
10913 default:
10914 switch (e->hangup.cause) {
10915 case PRI_CAUSE_USER_BUSY:
10916 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10917 break;
10918 case PRI_CAUSE_CALL_REJECTED:
10919 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10920 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10921 case PRI_CAUSE_SWITCH_CONGESTION:
10922 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10923 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10924 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10925 break;
10926 default:
10927 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10928 }
10929 break;
10930 }
10931 }
10932 if (option_verbose > 2)
10933 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
10934 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
10935 } else {
10936 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10937 pri->pvts[chanpos]->call = NULL;
10938 }
10939 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10940 if (option_verbose > 2)
10941 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
10942 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10943 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10944 pri->pvts[chanpos]->resetting = 1;
10945 }
10946 if (e->hangup.aoc_units > -1)
10947 if (option_verbose > 2)
10948 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10949 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10950
10951 #ifdef SUPPORT_USERUSER
10952 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
10953 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10954 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10955 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10956 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10957 }
10958 #endif
10959
10960 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10961 } else {
10962 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
10963 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10964 }
10965 }
10966 break;
10967 #ifndef PRI_EVENT_HANGUP_REQ
10968 #error please update libpri
10969 #endif
10970 case PRI_EVENT_HANGUP_REQ:
10971 chanpos = pri_find_principle(pri, e->hangup.channel);
10972 if (chanpos < 0) {
10973 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
10974 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10975 } else {
10976 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10977 if (chanpos > -1) {
10978 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10979 if (pri->pvts[chanpos]->realcall)
10980 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10981 else if (pri->pvts[chanpos]->owner) {
10982 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10983 switch (pri->pvts[chanpos]->owner->_state) {
10984 case AST_STATE_BUSY:
10985 case AST_STATE_UP:
10986 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10987 break;
10988 default:
10989 switch (e->hangup.cause) {
10990 case PRI_CAUSE_USER_BUSY:
10991 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10992 break;
10993 case PRI_CAUSE_CALL_REJECTED:
10994 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10995 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10996 case PRI_CAUSE_SWITCH_CONGESTION:
10997 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10998 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10999 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11000 break;
11001 default:
11002 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11003 }
11004 break;
11005 }
11006 if (option_verbose > 2)
11007 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);
11008 if (e->hangup.aoc_units > -1)
11009 if (option_verbose > 2)
11010 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11011 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11012 } else {
11013 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11014 pri->pvts[chanpos]->call = NULL;
11015 }
11016 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11017 if (option_verbose > 2)
11018 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11019 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11020 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11021 pri->pvts[chanpos]->resetting = 1;
11022 }
11023
11024 #ifdef SUPPORT_USERUSER
11025 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11026 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11027 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11028 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11029 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11030 }
11031 #endif
11032
11033 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11034 } else {
11035 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);
11036 }
11037 }
11038 break;
11039 case PRI_EVENT_HANGUP_ACK:
11040 chanpos = pri_find_principle(pri, e->hangup.channel);
11041 if (chanpos < 0) {
11042 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11043 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11044 } else {
11045 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11046 if (chanpos > -1) {
11047 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11048 pri->pvts[chanpos]->call = NULL;
11049 pri->pvts[chanpos]->resetting = 0;
11050 if (pri->pvts[chanpos]->owner) {
11051 if (option_verbose > 2)
11052 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);
11053 }
11054
11055 #ifdef SUPPORT_USERUSER
11056 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11057 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11058 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11059 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11060 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11061 }
11062 #endif
11063
11064 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11065 }
11066 }
11067 break;
11068 case PRI_EVENT_CONFIG_ERR:
11069 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11070 break;
11071 case PRI_EVENT_RESTART_ACK:
11072 chanpos = pri_find_principle(pri, e->restartack.channel);
11073 if (chanpos < 0) {
11074
11075
11076
11077 for (x = 0; x < pri->numchans; x++) {
11078 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11079 chanpos = x;
11080 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11081 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11082 pri->pvts[chanpos]->prioffset, pri->span);
11083 if (pri->pvts[chanpos]->realcall)
11084 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11085 else if (pri->pvts[chanpos]->owner) {
11086 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11087 pri->pvts[chanpos]->prioffset, pri->span);
11088 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11089 }
11090 pri->pvts[chanpos]->resetting = 0;
11091 if (option_verbose > 2)
11092 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11093 pri->pvts[chanpos]->prioffset, pri->span);
11094 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11095 if (pri->resetting)
11096 pri_check_restart(pri);
11097 break;
11098 }
11099 }
11100 if (chanpos < 0) {
11101 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11102 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11103 }
11104 } else {
11105 if (pri->pvts[chanpos]) {
11106 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11107 if (pri->pvts[chanpos]->realcall)
11108 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11109 else if (pri->pvts[chanpos]->owner) {
11110 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11111 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11112 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11113 }
11114 pri->pvts[chanpos]->resetting = 0;
11115 if (option_verbose > 2)
11116 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11117 pri->pvts[chanpos]->prioffset, pri->span);
11118 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11119 if (pri->resetting)
11120 pri_check_restart(pri);
11121 }
11122 }
11123 break;
11124 case PRI_EVENT_SETUP_ACK:
11125 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11126 if (chanpos < 0) {
11127 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11128 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11129 } else {
11130 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11131 if (chanpos > -1) {
11132 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11133 pri->pvts[chanpos]->setup_ack = 1;
11134
11135 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11136 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11137 pri_information(pri->pri, pri->pvts[chanpos]->call,
11138 pri->pvts[chanpos]->dialdest[x]);
11139 }
11140 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11141 } else
11142 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11143 }
11144 break;
11145 case PRI_EVENT_NOTIFY:
11146 chanpos = pri_find_principle(pri, e->notify.channel);
11147 if (chanpos < 0) {
11148 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11149 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11150 } else {
11151 struct ast_frame f = { AST_FRAME_CONTROL, };
11152 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11153 switch (e->notify.info) {
11154 case PRI_NOTIFY_REMOTE_HOLD:
11155 f.subclass = AST_CONTROL_HOLD;
11156 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11157 break;
11158 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11159 f.subclass = AST_CONTROL_UNHOLD;
11160 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11161 break;
11162 }
11163 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11164 }
11165 break;
11166 default:
11167 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
11168 }
11169 }
11170 ast_mutex_unlock(&pri->lock);
11171 }
11172
11173 return NULL;
11174 }
11175
11176 static int start_pri(struct dahdi_pri *pri)
11177 {
11178 int res, x;
11179 struct dahdi_params p;
11180 struct dahdi_bufferinfo bi;
11181 struct dahdi_spaninfo si;
11182 int i;
11183
11184 for (i = 0; i < NUM_DCHANS; i++) {
11185 if (!pri->dchannels[i])
11186 break;
11187 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
11188 x = pri->dchannels[i];
11189 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11190 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11191 return -1;
11192 }
11193 memset(&p, 0, sizeof(p));
11194 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11195 if (res) {
11196 dahdi_close_pri_fd(pri, i);
11197 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11198 return -1;
11199 }
11200 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11201 dahdi_close_pri_fd(pri, i);
11202 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
11203 return -1;
11204 }
11205 memset(&si, 0, sizeof(si));
11206 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11207 if (res) {
11208 dahdi_close_pri_fd(pri, i);
11209 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11210 }
11211 if (!si.alarms)
11212 pri->dchanavail[i] |= DCHAN_NOTINALARM;
11213 else
11214 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11215 memset(&bi, 0, sizeof(bi));
11216 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11217 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11218 bi.numbufs = 32;
11219 bi.bufsize = 1024;
11220 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11221 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11222 dahdi_close_pri_fd(pri, i);
11223 return -1;
11224 }
11225 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11226
11227 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11228 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11229 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11230 #ifdef HAVE_PRI_INBANDDISCONNECT
11231 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11232 #endif
11233
11234 if (i)
11235 pri_enslave(pri->dchans[0], pri->dchans[i]);
11236 if (!pri->dchans[i]) {
11237 dahdi_close_pri_fd(pri, i);
11238 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11239 return -1;
11240 }
11241 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11242 pri_set_nsf(pri->dchans[i], pri->nsf);
11243 #ifdef PRI_GETSET_TIMERS
11244 for (x = 0; x < PRI_MAX_TIMERS; x++) {
11245 if (pritimers[x] != 0)
11246 pri_set_timer(pri->dchans[i], x, pritimers[x]);
11247 }
11248 #endif
11249 }
11250
11251 pri->pri = pri->dchans[0];
11252 pri->resetpos = -1;
11253 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11254 for (i = 0; i < NUM_DCHANS; i++) {
11255 if (!pri->dchannels[i])
11256 break;
11257 dahdi_close_pri_fd(pri, i);
11258 }
11259 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11260 return -1;
11261 }
11262 return 0;
11263 }
11264
11265 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
11266 {
11267 int which, span;
11268 char *ret = NULL;
11269
11270 if (pos != rpos)
11271 return ret;
11272
11273 for (which = span = 0; span < NUM_SPANS; span++) {
11274 if (pris[span].pri && ++which > state) {
11275 if (asprintf(&ret, "%d", span + 1) < 0) {
11276 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11277 }
11278 break;
11279 }
11280 }
11281 return ret;
11282 }
11283
11284 static char *complete_span_4(const char *line, const char *word, int pos, int state)
11285 {
11286 return complete_span_helper(line,word,pos,state,3);
11287 }
11288
11289 static char *complete_span_5(const char *line, const char *word, int pos, int state)
11290 {
11291 return complete_span_helper(line,word,pos,state,4);
11292 }
11293
11294 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
11295 {
11296 int myfd;
11297
11298 if (!strncasecmp(argv[1], "set", 3)) {
11299 if (argc < 5)
11300 return RESULT_SHOWUSAGE;
11301
11302 if (ast_strlen_zero(argv[4]))
11303 return RESULT_SHOWUSAGE;
11304
11305 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
11306 if (myfd < 0) {
11307 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
11308 return RESULT_SUCCESS;
11309 }
11310
11311 ast_mutex_lock(&pridebugfdlock);
11312
11313 if (pridebugfd >= 0)
11314 close(pridebugfd);
11315
11316 pridebugfd = myfd;
11317 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
11318
11319 ast_mutex_unlock(&pridebugfdlock);
11320
11321 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
11322 } else {
11323
11324 ast_mutex_lock(&pridebugfdlock);
11325 close(pridebugfd);
11326 pridebugfd = -1;
11327 ast_cli(fd, "PRI debug output to file disabled\n");
11328 ast_mutex_unlock(&pridebugfdlock);
11329 }
11330
11331 return RESULT_SUCCESS;
11332 }
11333
11334 #ifdef HAVE_PRI_VERSION
11335 static int handle_pri_version(int fd, int agc, char *argv[]) {
11336 ast_cli(fd, "libpri version: %s\n", pri_get_version());
11337 return RESULT_SUCCESS;
11338 }
11339 #endif
11340
11341 static int handle_pri_debug(int fd, int argc, char *argv[])
11342 {
11343 int span;
11344 int x;
11345 if (argc < 4) {
11346 return RESULT_SHOWUSAGE;
11347 }
11348 span = atoi(argv[3]);
11349 if ((span < 1) || (span > NUM_SPANS)) {
11350 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11351 return RESULT_SUCCESS;
11352 }
11353 if (!pris[span-1].pri) {
11354 ast_cli(fd, "No PRI running on span %d\n", span);
11355 return RESULT_SUCCESS;
11356 }
11357 for (x = 0; x < NUM_DCHANS; x++) {
11358 if (pris[span-1].dchans[x])
11359 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11360 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11361 PRI_DEBUG_Q921_STATE);
11362 }
11363 ast_cli(fd, "Enabled debugging on span %d\n", span);
11364 return RESULT_SUCCESS;
11365 }
11366
11367
11368
11369 static int handle_pri_no_debug(int fd, int argc, char *argv[])
11370 {
11371 int span;
11372 int x;
11373 if (argc < 5)
11374 return RESULT_SHOWUSAGE;
11375 span = atoi(argv[4]);
11376 if ((span < 1) || (span > NUM_SPANS)) {
11377 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11378 return RESULT_SUCCESS;
11379 }
11380 if (!pris[span-1].pri) {
11381 ast_cli(fd, "No PRI running on span %d\n", span);
11382 return RESULT_SUCCESS;
11383 }
11384 for (x = 0; x < NUM_DCHANS; x++) {
11385 if (pris[span-1].dchans[x])
11386 pri_set_debug(pris[span-1].dchans[x], 0);
11387 }
11388 ast_cli(fd, "Disabled debugging on span %d\n", span);
11389 return RESULT_SUCCESS;
11390 }
11391
11392 static int handle_pri_really_debug(int fd, int argc, char *argv[])
11393 {
11394 int span;
11395 int x;
11396 if (argc < 5)
11397 return RESULT_SHOWUSAGE;
11398 span = atoi(argv[4]);
11399 if ((span < 1) || (span > NUM_SPANS)) {
11400 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11401 return RESULT_SUCCESS;
11402 }
11403 if (!pris[span-1].pri) {
11404 ast_cli(fd, "No PRI running on span %d\n", span);
11405 return RESULT_SUCCESS;
11406 }
11407 for (x = 0; x < NUM_DCHANS; x++) {
11408 if (pris[span-1].dchans[x])
11409 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11410 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11411 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11412 }
11413 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11414 return RESULT_SUCCESS;
11415 }
11416
11417 static void build_status(char *s, size_t len, int status, int active)
11418 {
11419 if (!s || len < 1) {
11420 return;
11421 }
11422 s[0] = '\0';
11423 if (status & DCHAN_PROVISIONED)
11424 strncat(s, "Provisioned, ", len - strlen(s) - 1);
11425 if (!(status & DCHAN_NOTINALARM))
11426 strncat(s, "In Alarm, ", len - strlen(s) - 1);
11427 if (status & DCHAN_UP)
11428 strncat(s, "Up", len - strlen(s) - 1);
11429 else
11430 strncat(s, "Down", len - strlen(s) - 1);
11431 if (active)
11432 strncat(s, ", Active", len - strlen(s) - 1);
11433 else
11434 strncat(s, ", Standby", len - strlen(s) - 1);
11435 s[len - 1] = '\0';
11436 }
11437
11438 static int handle_pri_show_spans(int fd, int argc, char *argv[])
11439 {
11440 int span;
11441 int x;
11442 char status[256];
11443 if (argc != 3)
11444 return RESULT_SHOWUSAGE;
11445
11446 for (span = 0; span < NUM_SPANS; span++) {
11447 if (pris[span].pri) {
11448 for (x = 0; x < NUM_DCHANS; x++) {
11449 if (pris[span].dchannels[x]) {
11450 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11451 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11452 }
11453 }
11454 }
11455 }
11456 return RESULT_SUCCESS;
11457 }
11458
11459 static int handle_pri_show_span(int fd, int argc, char *argv[])
11460 {
11461 int span;
11462 int x;
11463 char status[256];
11464 if (argc < 4)
11465 return RESULT_SHOWUSAGE;
11466 span = atoi(argv[3]);
11467 if ((span < 1) || (span > NUM_SPANS)) {
11468 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11469 return RESULT_SUCCESS;
11470 }
11471 if (!pris[span-1].pri) {
11472 ast_cli(fd, "No PRI running on span %d\n", span);
11473 return RESULT_SUCCESS;
11474 }
11475 for (x = 0; x < NUM_DCHANS; x++) {
11476 if (pris[span-1].dchannels[x]) {
11477 #ifdef PRI_DUMP_INFO_STR
11478 char *info_str = NULL;
11479 #endif
11480 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11481 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11482 ast_cli(fd, "Status: %s\n", status);
11483 #ifdef PRI_DUMP_INFO_STR
11484 info_str = pri_dump_info_str(pris[span-1].pri);
11485 if (info_str) {
11486 ast_cli(fd, "%s", info_str);
11487 free(info_str);
11488 }
11489 #else
11490 pri_dump_info(pris[span-1].pri);
11491 #endif
11492 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11493 }
11494 }
11495 return RESULT_SUCCESS;
11496 }
11497
11498 static int handle_pri_show_debug(int fd, int argc, char *argv[])
11499 {
11500 int x;
11501 int span;
11502 int count=0;
11503 int debug=0;
11504
11505 for (span = 0; span < NUM_SPANS; span++) {
11506 if (pris[span].pri) {
11507 for (x = 0; x < NUM_DCHANS; x++) {
11508 debug = 0;
11509 if (pris[span].dchans[x]) {
11510 debug = pri_get_debug(pris[span].dchans[x]);
11511 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" );
11512 count++;
11513 }
11514 }
11515 }
11516
11517 }
11518 ast_mutex_lock(&pridebugfdlock);
11519 if (pridebugfd >= 0)
11520 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
11521 ast_mutex_unlock(&pridebugfdlock);
11522
11523 if (!count)
11524 ast_cli(fd, "No debug set or no PRI running\n");
11525 return RESULT_SUCCESS;
11526 }
11527
11528 static const char pri_debug_help[] =
11529 "Usage: pri debug span <span>\n"
11530 " Enables debugging on a given PRI span\n";
11531
11532 static const char pri_no_debug_help[] =
11533 "Usage: pri no debug span <span>\n"
11534 " Disables debugging on a given PRI span\n";
11535
11536 static const char pri_really_debug_help[] =
11537 "Usage: pri intensive debug span <span>\n"
11538 " Enables debugging down to the Q.921 level\n";
11539
11540 static const char pri_show_span_help[] =
11541 "Usage: pri show span <span>\n"
11542 " Displays PRI Information on a given PRI span\n";
11543
11544 static const char pri_show_spans_help[] =
11545 "Usage: pri show spans\n"
11546 " Displays PRI Information\n";
11547
11548 static struct ast_cli_entry dahdi_pri_cli[] = {
11549 { { "pri", "debug", "span", NULL },
11550 handle_pri_debug, "Enables PRI debugging on a span",
11551 pri_debug_help, complete_span_4 },
11552
11553 { { "pri", "no", "debug", "span", NULL },
11554 handle_pri_no_debug, "Disables PRI debugging on a span",
11555 pri_no_debug_help, complete_span_5 },
11556
11557 { { "pri", "intense", "debug", "span", NULL },
11558 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
11559 pri_really_debug_help, complete_span_5 },
11560
11561 { { "pri", "show", "spans", NULL },
11562 handle_pri_show_spans, "Displays PRI Information",
11563 pri_show_spans_help },
11564
11565 { { "pri", "show", "span", NULL },
11566 handle_pri_show_span, "Displays PRI Information",
11567 pri_show_span_help, complete_span_4 },
11568
11569 { { "pri", "show", "debug", NULL },
11570 handle_pri_show_debug, "Displays current PRI debug settings" },
11571
11572 { { "pri", "set", "debug", "file", NULL },
11573 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
11574
11575 { { "pri", "unset", "debug", "file", NULL },
11576 handle_pri_set_debug_file, "Ends PRI debug output to file" },
11577
11578 #ifdef HAVE_PRI_VERSION
11579 { { "pri", "show", "version", NULL },
11580 handle_pri_version, "Displays version of libpri" },
11581 #endif
11582 };
11583
11584 #endif
11585
11586 #ifdef HAVE_OPENR2
11587
11588 static int handle_mfcr2_version(int fd, int argc, char *argv[])
11589 {
11590 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11591 return RESULT_SUCCESS;
11592 }
11593
11594 static int handle_mfcr2_show_variants(int fd, int argc, char *argv[])
11595 {
11596 #define FORMAT "%4s %40s\n"
11597 int numvariants = 0;
11598 int i;
11599 const openr2_variant_entry_t *variants;
11600 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
11601 ast_cli(fd, "Failed to get list of variants.\n");
11602 return RESULT_FAILURE;
11603 }
11604 ast_cli(fd, FORMAT, "Variant Code", "Country");
11605 for (i = 0; i < numvariants; i++) {
11606 ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
11607 }
11608 return RESULT_SUCCESS;
11609 #undef FORMAT
11610 }
11611
11612 static int handle_mfcr2_show_channels(int fd, int argc, char *argv[])
11613 {
11614 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
11615 int filtertype = 0;
11616 int targetnum = 0;
11617 char channo[5];
11618 char anino[5];
11619 char dnisno[5];
11620 struct dahdi_pvt *p;
11621 openr2_context_t *r2context;
11622 openr2_variant_t r2variant;
11623 if (!((argc == 3) || (argc == 5))) {
11624 return RESULT_SHOWUSAGE;
11625 }
11626 if (argc == 5) {
11627 if (!strcasecmp(argv[3], "group")) {
11628 targetnum = atoi(argv[4]);
11629 if ((targetnum < 0) || (targetnum > 63))
11630 return RESULT_SHOWUSAGE;
11631 targetnum = 1 << targetnum;
11632 filtertype = 1;
11633 } else if (!strcasecmp(argv[3], "context")) {
11634 filtertype = 2;
11635 } else {
11636 return RESULT_SHOWUSAGE;
11637 }
11638 }
11639 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
11640 ast_mutex_lock(&iflock);
11641 p = iflist;
11642 while (p) {
11643 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11644 p = p->next;
11645 continue;
11646 }
11647 if (filtertype) {
11648 switch(filtertype) {
11649 case 1:
11650 if (p->group != targetnum) {
11651 p = p->next;
11652 continue;
11653 }
11654 break;
11655 case 2:
11656 if (strcasecmp(p->context, argv[4])) {
11657 p= p->next;
11658 continue;
11659 }
11660 break;
11661 default:
11662 ;
11663 }
11664 }
11665 r2context = openr2_chan_get_context(p->r2chan);
11666 r2variant = openr2_context_get_variant(r2context);
11667 snprintf(channo, sizeof(channo), "%d", p->channel);
11668 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
11669 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
11670 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
11671 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
11672 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
11673 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
11674 p = p->next;
11675 }
11676 ast_mutex_unlock(&iflock);
11677 return RESULT_SUCCESS;
11678 #undef FORMAT
11679 }
11680
11681 static int handle_mfcr2_set_debug(int fd, int argc, char *argv[])
11682 {
11683 struct dahdi_pvt *p = NULL;
11684 int channo = 0;
11685 char *toklevel = NULL;
11686 char *saveptr = NULL;
11687 char *logval = NULL;
11688 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
11689 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
11690 if (argc < 4) {
11691 return RESULT_SHOWUSAGE;
11692 }
11693 channo = (argc == 5) ? atoi(argv[4]) : -1;
11694 logval = ast_strdupa(argv[3]);
11695 toklevel = strtok_r(logval, ",", &saveptr);
11696 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11697 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
11698 return RESULT_FAILURE;
11699 } else if (OR2_LOG_NOTHING == tmplevel) {
11700 loglevel = tmplevel;
11701 } else {
11702 loglevel |= tmplevel;
11703 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
11704 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11705 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
11706 continue;
11707 }
11708 loglevel |= tmplevel;
11709 }
11710 }
11711 ast_mutex_lock(&iflock);
11712 p = iflist;
11713 while (p) {
11714 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11715 p = p->next;
11716 continue;
11717 }
11718 if ((channo != -1) && (p->channel != channo )) {
11719 p = p->next;
11720 continue;
11721 }
11722 openr2_chan_set_log_level(p->r2chan, loglevel);
11723 if (channo != -1) {
11724 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
11725 break;
11726 } else {
11727 p = p->next;
11728 }
11729 }
11730 if ((channo != -1) && !p) {
11731 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11732 }
11733 if (channo == -1) {
11734 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
11735 }
11736 ast_mutex_unlock(&iflock);
11737 return RESULT_SUCCESS;
11738 }
11739
11740 static int handle_mfcr2_call_files(int fd, int argc, char *argv[])
11741 {
11742 struct dahdi_pvt *p = NULL;
11743 int channo = 0;
11744 if (argc < 4) {
11745 return RESULT_SHOWUSAGE;
11746 }
11747 channo = (argc == 5) ? atoi(argv[4]) : -1;
11748 ast_mutex_lock(&iflock);
11749 p = iflist;
11750 while (p) {
11751 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11752 p = p->next;
11753 continue;
11754 }
11755 if ((channo != -1) && (p->channel != channo )) {
11756 p = p->next;
11757 continue;
11758 }
11759 if (ast_true(argv[3])) {
11760 openr2_chan_enable_call_files(p->r2chan);
11761 } else {
11762 openr2_chan_disable_call_files(p->r2chan);
11763 }
11764 if (channo != -1) {
11765 if (ast_true(argv[3])) {
11766 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
11767 } else {
11768 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
11769 }
11770 break;
11771 } else {
11772 p = p->next;
11773 }
11774 }
11775 if ((channo != -1) && !p) {
11776 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11777 }
11778 if (channo == -1) {
11779 if (ast_true(argv[3])) {
11780 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
11781 } else {
11782 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
11783 }
11784 }
11785 ast_mutex_unlock(&iflock);
11786 return RESULT_SUCCESS;
11787 }
11788
11789 static int handle_mfcr2_set_idle(int fd, int argc, char *argv[])
11790 {
11791 struct dahdi_pvt *p = NULL;
11792 int channo = 0;
11793 channo = (argc == 4) ? atoi(argv[3]) : -1;
11794 ast_mutex_lock(&iflock);
11795 p = iflist;
11796 while (p) {
11797 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11798 p = p->next;
11799 continue;
11800 }
11801 if ((channo != -1) && (p->channel != channo )) {
11802 p = p->next;
11803 continue;
11804 }
11805 if (!openr2_chan_set_idle(p->r2chan)) {
11806 ast_mutex_lock(&p->lock);
11807 p->mfcr2call = 0;
11808 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
11809 ast_mutex_unlock(&p->lock);
11810 }
11811 if (channo != -1) {
11812 break;
11813 } else {
11814 p = p->next;
11815 }
11816 }
11817 if ((channo != -1) && !p) {
11818 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11819 }
11820 ast_mutex_unlock(&iflock);
11821 return RESULT_SUCCESS;
11822 }
11823
11824 static int handle_mfcr2_set_blocked(int fd, int argc, char *argv[])
11825 {
11826 struct dahdi_pvt *p = NULL;
11827 int channo = 0;
11828 channo = (argc == 4) ? atoi(argv[3]) : -1;
11829 ast_mutex_lock(&iflock);
11830 p = iflist;
11831 while (p) {
11832 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11833 p = p->next;
11834 continue;
11835 }
11836 if ((channo != -1) && (p->channel != channo )) {
11837 p = p->next;
11838 continue;
11839 }
11840 if (!openr2_chan_set_blocked(p->r2chan)) {
11841 ast_mutex_lock(&p->lock);
11842 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
11843 ast_mutex_unlock(&p->lock);
11844 } else {
11845 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
11846 }
11847 if (channo != -1) {
11848 break;
11849 } else {
11850 p = p->next;
11851 }
11852 }
11853 if ((channo != -1) && !p) {
11854 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11855 }
11856 ast_mutex_unlock(&iflock);
11857 return RESULT_SUCCESS;
11858 }
11859
11860 static const char dahdi_r2_version_help[] =
11861 "Usage: mfcr2 show version\n"
11862 " Shows the version of the OpenR2 library being used.\n";
11863 static const char dahdi_r2_variants_help[] =
11864 "Usage: mfcr2 show variants\n"
11865 " Show supported MFC/R2 variants.\n";
11866 static const char dahdi_r2_showchannels_help[] =
11867 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
11868 " Shows the zap channels configured with MFC/R2 signaling.\n";
11869 static const char dahdi_r2_setdebug_help[] =
11870 "Usage: mfcr2 set debug <loglevel> <channel>\n"
11871 " Set a new logging level for the specified channel.\n"
11872 " If no channel is specified the logging level will be applied to all channels.\n";
11873 static const char dahdi_r2_callfiles_help[] =
11874 "Usage: mfcr2 call files [on|off] <channel>\n"
11875 " Enable call files creation on the specified channel.\n"
11876 " If no channel is specified call files creation policy will be applied to all channels.\n";
11877 static const char dahdi_r2_setidle_help[] =
11878 "Usage: mfcr2 set idle <channel>\n"
11879 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11880 " Force the given channel into IDLE state.\n"
11881 " If no channel is specified, all channels will be set to IDLE.\n";
11882 static const char dahdi_r2_setblocked_help[] =
11883 "Usage: mfcr2 set blocked <channel>\n"
11884 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11885 " Force the given channel into BLOCKED state.\n"
11886 " If no channel is specified, all channels will be set to BLOCKED.\n";
11887
11888 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
11889 { { "mfcr2", "show", "version", NULL },
11890 handle_mfcr2_version, "Show OpenR2 library version",
11891 dahdi_r2_version_help },
11892
11893 { { "mfcr2", "show", "variants", NULL },
11894 handle_mfcr2_show_variants, "Show supported MFC/R2 variants",
11895 dahdi_r2_variants_help },
11896
11897 { { "mfcr2", "show", "channels", NULL },
11898 handle_mfcr2_show_channels, "Show MFC/R2 channels",
11899 dahdi_r2_showchannels_help },
11900
11901 { { "mfcr2", "set", "debug", NULL },
11902 handle_mfcr2_set_debug, "Set MFC/R2 channel logging level",
11903 dahdi_r2_setdebug_help },
11904
11905 { { "mfcr2", "call", "files", NULL },
11906 handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files",
11907 dahdi_r2_callfiles_help },
11908
11909 { { "mfcr2", "set", "idle", NULL },
11910 handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE",
11911 dahdi_r2_setidle_help },
11912
11913 { { "mfcr2", "set", "blocked", NULL },
11914 handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED",
11915 dahdi_r2_setblocked_help }
11916
11917 };
11918
11919 #endif
11920
11921 static int dahdi_destroy_channel(int fd, int argc, char **argv)
11922 {
11923 int channel;
11924
11925 if (argc != 4)
11926 return RESULT_SHOWUSAGE;
11927
11928 channel = atoi(argv[3]);
11929
11930 return dahdi_destroy_channel_bynum(channel);
11931 }
11932
11933 static void dahdi_softhangup_all(void)
11934 {
11935 struct dahdi_pvt *p;
11936 retry:
11937 ast_mutex_lock(&iflock);
11938 for (p = iflist; p; p = p->next) {
11939 ast_mutex_lock(&p->lock);
11940 if (p->owner && !p->restartpending) {
11941 if (ast_channel_trylock(p->owner)) {
11942 if (option_debug > 2)
11943 ast_verbose("Avoiding deadlock\n");
11944
11945 ast_mutex_unlock(&p->lock);
11946 ast_mutex_unlock(&iflock);
11947 goto retry;
11948 }
11949 if (option_debug > 2)
11950 ast_verbose("Softhanging up on %s\n", p->owner->name);
11951 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11952 p->restartpending = 1;
11953 num_restart_pending++;
11954 ast_channel_unlock(p->owner);
11955 }
11956 ast_mutex_unlock(&p->lock);
11957 }
11958 ast_mutex_unlock(&iflock);
11959 }
11960
11961 static int setup_dahdi(int reload);
11962 static int dahdi_restart(void)
11963 {
11964 #ifdef HAVE_OPENR2
11965 int r;
11966 #endif
11967 #if defined(HAVE_PRI)
11968 int i, j;
11969 #endif
11970 int cancel_code;
11971 struct dahdi_pvt *p;
11972
11973 ast_mutex_lock(&restart_lock);
11974
11975 if (option_verbose)
11976 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
11977 dahdi_softhangup_all();
11978 if (option_verbose > 3)
11979 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
11980
11981 #ifdef HAVE_OPENR2
11982 for (r = 0; r < NUM_SPANS; r++) {
11983 if (r2links[r].master != AST_PTHREADT_NULL) {
11984 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
11985 pthread_cancel(r2links[r].master);
11986 pthread_join(r2links[r].master, NULL);
11987 openr2_context_delete(r2links[r].protocol_context);
11988 }
11989 }
11990 init_mfcr2_globals();
11991 #endif
11992
11993 #if defined(HAVE_PRI)
11994 for (i = 0; i < NUM_SPANS; i++) {
11995 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
11996 cancel_code = pthread_cancel(pris[i].master);
11997 pthread_kill(pris[i].master, SIGURG);
11998 if (option_debug > 3)
11999 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12000 pthread_join(pris[i].master, NULL);
12001 if (option_debug > 3)
12002 ast_verbose("Joined thread of span %d\n", i);
12003 }
12004 }
12005 #endif
12006
12007 ast_mutex_lock(&monlock);
12008 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12009 cancel_code = pthread_cancel(monitor_thread);
12010 pthread_kill(monitor_thread, SIGURG);
12011 if (option_debug > 3)
12012 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12013 pthread_join(monitor_thread, NULL);
12014 if (option_debug > 3)
12015 ast_verbose("Joined monitor thread\n");
12016 }
12017 monitor_thread = AST_PTHREADT_NULL;
12018
12019 ast_mutex_lock(&ss_thread_lock);
12020 while (ss_thread_count > 0) {
12021 int x = DAHDI_FLASH;
12022 if (option_debug > 2)
12023 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12024
12025 for (p = iflist; p; p = p->next) {
12026 if (p->owner)
12027 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
12028 }
12029 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12030 }
12031
12032
12033 dahdi_softhangup_all();
12034 if (option_verbose > 3)
12035 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
12036 destroy_all_channels();
12037 if (option_debug)
12038 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12039
12040 ast_mutex_unlock(&monlock);
12041
12042 #ifdef HAVE_PRI
12043 for (i = 0; i < NUM_SPANS; i++) {
12044 for (j = 0; j < NUM_DCHANS; j++)
12045 dahdi_close_pri_fd(&(pris[i]), j);
12046 }
12047
12048 memset(pris, 0, sizeof(pris));
12049 for (i = 0; i < NUM_SPANS; i++) {
12050 ast_mutex_init(&pris[i].lock);
12051 pris[i].offset = -1;
12052 pris[i].master = AST_PTHREADT_NULL;
12053 for (j = 0; j < NUM_DCHANS; j++)
12054 pris[i].fds[j] = -1;
12055 }
12056 pri_set_error(dahdi_pri_error);
12057 pri_set_message(dahdi_pri_message);
12058 #endif
12059
12060 if (setup_dahdi(2) != 0) {
12061 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12062 ast_mutex_unlock(&ss_thread_lock);
12063 return 1;
12064 }
12065 ast_mutex_unlock(&ss_thread_lock);
12066 ast_mutex_unlock(&restart_lock);
12067 return 0;
12068 }
12069
12070 static int dahdi_restart_cmd(int fd, int argc, char **argv)
12071 {
12072 if (argc != 2) {
12073 return RESULT_SHOWUSAGE;
12074 }
12075
12076 if (dahdi_restart() != 0)
12077 return RESULT_FAILURE;
12078 return RESULT_SUCCESS;
12079 }
12080
12081 static int dahdi_show_channels(int fd, int argc, char **argv)
12082 {
12083 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12084 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12085 struct dahdi_pvt *tmp = NULL;
12086 char tmps[20] = "";
12087 ast_mutex_t *lock;
12088 struct dahdi_pvt *start;
12089 #ifdef HAVE_PRI
12090 int trunkgroup;
12091 struct dahdi_pri *pri = NULL;
12092 int x;
12093 #endif
12094
12095 lock = &iflock;
12096 start = iflist;
12097
12098 #ifdef HAVE_PRI
12099 if (argc == 4) {
12100 if ((trunkgroup = atoi(argv[3])) < 1)
12101 return RESULT_SHOWUSAGE;
12102 for (x = 0; x < NUM_SPANS; x++) {
12103 if (pris[x].trunkgroup == trunkgroup) {
12104 pri = pris + x;
12105 break;
12106 }
12107 }
12108 if (pri) {
12109 start = pri->crvs;
12110 lock = &pri->lock;
12111 } else {
12112 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12113 return RESULT_FAILURE;
12114 }
12115 } else
12116 #endif
12117 if (argc != 3)
12118 return RESULT_SHOWUSAGE;
12119
12120 ast_mutex_lock(lock);
12121 #ifdef HAVE_PRI
12122 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
12123 #else
12124 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
12125 #endif
12126
12127 tmp = start;
12128 while (tmp) {
12129 if (tmp->channel > 0) {
12130 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12131 } else
12132 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12133 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
12134 tmp = tmp->next;
12135 }
12136 ast_mutex_unlock(lock);
12137 return RESULT_SUCCESS;
12138 #undef FORMAT
12139 #undef FORMAT2
12140 }
12141
12142 static int dahdi_show_channel(int fd, int argc, char **argv)
12143 {
12144 int channel;
12145 struct dahdi_pvt *tmp = NULL;
12146 struct dahdi_confinfo ci;
12147 struct dahdi_params ps;
12148 int x;
12149 ast_mutex_t *lock;
12150 struct dahdi_pvt *start;
12151 #ifdef HAVE_PRI
12152 char *c;
12153 int trunkgroup;
12154 struct dahdi_pri *pri=NULL;
12155 #endif
12156
12157 lock = &iflock;
12158 start = iflist;
12159
12160 if (argc != 4)
12161 return RESULT_SHOWUSAGE;
12162 #ifdef HAVE_PRI
12163 if ((c = strchr(argv[3], ':'))) {
12164 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12165 return RESULT_SHOWUSAGE;
12166 if ((trunkgroup < 1) || (channel < 1))
12167 return RESULT_SHOWUSAGE;
12168 for (x = 0; x < NUM_SPANS; x++) {
12169 if (pris[x].trunkgroup == trunkgroup) {
12170 pri = pris + x;
12171 break;
12172 }
12173 }
12174 if (pri) {
12175 start = pri->crvs;
12176 lock = &pri->lock;
12177 } else {
12178 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12179 return RESULT_FAILURE;
12180 }
12181 } else
12182 #endif
12183 channel = atoi(argv[3]);
12184
12185 ast_mutex_lock(lock);
12186 tmp = start;
12187 while (tmp) {
12188 if (tmp->channel == channel) {
12189 #ifdef HAVE_PRI
12190 if (pri)
12191 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12192 else
12193 #endif
12194 ast_cli(fd, "Channel: %d\n", tmp->channel);
12195 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12196 ast_cli(fd, "Span: %d\n", tmp->span);
12197 ast_cli(fd, "Extension: %s\n", tmp->exten);
12198 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12199 ast_cli(fd, "Context: %s\n", tmp->context);
12200 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
12201 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
12202 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
12203 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
12204 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
12205 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12206 ast_cli(fd, "Radio: %d\n", tmp->radio);
12207 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12208 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)" : "");
12209 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)" : "");
12210 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)" : "");
12211 ast_cli(fd, "Confno: %d\n", tmp->confno);
12212 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
12213 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
12214 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12215 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12216 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12217 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12218 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12219 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12220 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
12221 if (tmp->master)
12222 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
12223 for (x = 0; x < MAX_SLAVES; x++) {
12224 if (tmp->slaves[x])
12225 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12226 }
12227 #ifdef HAVE_OPENR2
12228 if (tmp->mfcr2) {
12229 char calldir[OR2_MAX_PATH];
12230 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
12231 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
12232 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
12233 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
12234 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
12235 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
12236 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
12237 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
12238 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
12239 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
12240 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
12241 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
12242 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12243 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
12244 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
12245 #endif
12246 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
12247 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
12248 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
12249 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
12250 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
12251 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
12252 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
12253 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
12254 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
12255 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
12256 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
12257 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
12258 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
12259 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
12260 }
12261 #endif
12262 #ifdef HAVE_PRI
12263 if (tmp->pri) {
12264 ast_cli(fd, "PRI Flags: ");
12265 if (tmp->resetting)
12266 ast_cli(fd, "Resetting ");
12267 if (tmp->call)
12268 ast_cli(fd, "Call ");
12269 if (tmp->bearer)
12270 ast_cli(fd, "Bearer ");
12271 ast_cli(fd, "\n");
12272 if (tmp->logicalspan)
12273 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12274 else
12275 ast_cli(fd, "PRI Logical Span: Implicit\n");
12276 }
12277
12278 #endif
12279 memset(&ci, 0, sizeof(ci));
12280 ps.channo = tmp->channel;
12281 if (tmp->subs[SUB_REAL].dfd > -1) {
12282 memset(&ci, 0, sizeof(ci));
12283 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12284 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12285 }
12286 #ifdef DAHDI_GETCONFMUTE
12287 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12288 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12289 }
12290 #endif
12291 memset(&ps, 0, sizeof(ps));
12292 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12293 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12294 } else {
12295 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12296 }
12297 }
12298 if (ISTRUNK(tmp)) {
12299 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
12300 if (!ast_strlen_zero(progzone))
12301 ast_cli(fd, "Progress Zone: %s\n", progzone);
12302 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
12303 if(tmp->busydetect) {
12304 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
12305 if(tmp->busytonelength > 0) {
12306 ast_cli(fd, "Busy Pattern:\n");
12307 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12308 if (tmp->busyquietlength > 0)
12309 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12310 else
12311 ast_cli(fd, " -- Detect Tone Only\n");
12312 if(tmp->busyfuzziness > 0)
12313 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12314 }
12315 }
12316 }
12317 ast_mutex_unlock(lock);
12318 return RESULT_SUCCESS;
12319 }
12320 tmp = tmp->next;
12321 }
12322
12323 ast_cli(fd, "Unable to find given channel %d\n", channel);
12324 ast_mutex_unlock(lock);
12325 return RESULT_FAILURE;
12326 }
12327
12328 static char dahdi_show_cadences_usage[] =
12329 "Usage: dahdi show cadences\n"
12330 " Shows all cadences currently defined\n";
12331
12332 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
12333 {
12334 int i, j;
12335 for (i = 0; i < num_cadence; i++) {
12336 char output[1024];
12337 char tmp[16], tmp2[64];
12338 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12339 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12340
12341 for (j = 0; j < 16; j++) {
12342 if (cadences[i].ringcadence[j] == 0)
12343 break;
12344 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12345 if (cidrings[i] * 2 - 1 == j)
12346 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12347 else
12348 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12349 if (j != 0)
12350 strncat(output, ",", sizeof(output) - strlen(output) - 1);
12351 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12352 }
12353 ast_cli(fd,"%s\n",output);
12354 }
12355 return 0;
12356 }
12357
12358
12359 static int dahdi_show_status(int fd, int argc, char *argv[]) {
12360 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12361 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12362
12363 int span;
12364 int res;
12365 char alarms[50];
12366
12367 int ctl;
12368 struct dahdi_spaninfo s;
12369
12370 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
12371 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
12372 ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
12373 return RESULT_FAILURE;
12374 }
12375 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
12376
12377 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12378 s.spanno = span;
12379 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12380 if (res) {
12381 continue;
12382 }
12383 alarms[0] = '\0';
12384 if (s.alarms > 0) {
12385 if (s.alarms & DAHDI_ALARM_BLUE)
12386 strcat(alarms, "BLU/");
12387 if (s.alarms & DAHDI_ALARM_YELLOW)
12388 strcat(alarms, "YEL/");
12389 if (s.alarms & DAHDI_ALARM_RED)
12390 strcat(alarms, "RED/");
12391 if (s.alarms & DAHDI_ALARM_LOOPBACK)
12392 strcat(alarms, "LB/");
12393 if (s.alarms & DAHDI_ALARM_RECOVER)
12394 strcat(alarms, "REC/");
12395 if (s.alarms & DAHDI_ALARM_NOTOPEN)
12396 strcat(alarms, "NOP/");
12397 if (!strlen(alarms))
12398 strcat(alarms, "UUU/");
12399 if (strlen(alarms)) {
12400
12401 alarms[strlen(alarms) - 1] = '\0';
12402 }
12403 } else {
12404 if (s.numchans)
12405 strcpy(alarms, "OK");
12406 else
12407 strcpy(alarms, "UNCONFIGURED");
12408 }
12409
12410 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12411 }
12412 close(ctl);
12413
12414 return RESULT_SUCCESS;
12415 #undef FORMAT
12416 #undef FORMAT2
12417 }
12418
12419 static char show_channels_usage[] =
12420 "Usage: dahdi show channels\n"
12421 " Shows a list of available channels\n";
12422
12423 static char show_channel_usage[] =
12424 "Usage: dahdi show channel <chan num>\n"
12425 " Detailed information about a given channel\n";
12426
12427 static char dahdi_show_status_usage[] =
12428 "Usage: dahdi show status\n"
12429 " Shows a list of DAHDI cards with status\n";
12430
12431 static char destroy_channel_usage[] =
12432 "Usage: dahdi destroy channel <chan num>\n"
12433 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12434
12435 static char dahdi_restart_usage[] =
12436 "Usage: dahdi restart\n"
12437 " Restarts the DAHDI channels: destroys them all and then\n"
12438 " re-reads them from chan_dahdi.conf.\n"
12439 " Note that this will STOP any running CALL on DAHDI channels.\n"
12440 "";
12441
12442 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
12443 { "zap", "show", "cadences", NULL },
12444 handle_dahdi_show_cadences, NULL,
12445 NULL };
12446
12447 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
12448 { "zap", "show", "channels", NULL },
12449 dahdi_show_channels, NULL,
12450 NULL };
12451
12452 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
12453 { "zap", "show", "channel", NULL },
12454 dahdi_show_channel, NULL,
12455 NULL };
12456
12457 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
12458 { "zap", "destroy", "channel", NULL },
12459 dahdi_destroy_channel, NULL,
12460 NULL };
12461
12462 static struct ast_cli_entry cli_zap_restart_deprecated = {
12463 { "zap", "restart", NULL },
12464 dahdi_restart_cmd, NULL,
12465 NULL };
12466
12467 static struct ast_cli_entry cli_zap_show_status_deprecated = {
12468 { "zap", "show", "status", NULL },
12469 dahdi_show_status, NULL,
12470 NULL };
12471
12472 static struct ast_cli_entry dahdi_cli[] = {
12473 { { "dahdi", "show", "cadences", NULL },
12474 handle_dahdi_show_cadences, "List cadences",
12475 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
12476
12477 { { "dahdi", "show", "channels", NULL},
12478 dahdi_show_channels, "Show active DAHDI channels",
12479 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
12480
12481 { { "dahdi", "show", "channel", NULL},
12482 dahdi_show_channel, "Show information on a channel",
12483 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
12484
12485 { { "dahdi", "destroy", "channel", NULL},
12486 dahdi_destroy_channel, "Destroy a channel",
12487 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
12488
12489 { { "dahdi", "restart", NULL},
12490 dahdi_restart_cmd, "Fully restart DAHDI channels",
12491 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
12492
12493 { { "dahdi", "show", "status", NULL},
12494 dahdi_show_status, "Show all DAHDI cards status",
12495 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
12496 };
12497
12498 #define TRANSFER 0
12499 #define HANGUP 1
12500
12501 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
12502 {
12503 if (p) {
12504 switch (mode) {
12505 case TRANSFER:
12506 p->fake_event = DAHDI_EVENT_WINKFLASH;
12507 break;
12508 case HANGUP:
12509 p->fake_event = DAHDI_EVENT_ONHOOK;
12510 break;
12511 default:
12512 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
12513 }
12514 }
12515 return 0;
12516 }
12517 static struct dahdi_pvt *find_channel(int channel)
12518 {
12519 struct dahdi_pvt *p = iflist;
12520 while (p) {
12521 if (p->channel == channel) {
12522 break;
12523 }
12524 p = p->next;
12525 }
12526 return p;
12527 }
12528
12529 #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)
12530 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
12531
12532 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
12533 {
12534 struct dahdi_pvt *p = NULL;
12535 const char *channel = local_astman_header(m, "Channel", zap_mode);
12536
12537 if (ast_strlen_zero(channel)) {
12538 astman_send_error(s, m, "No channel specified");
12539 return 0;
12540 }
12541 if (!(p = find_channel(atoi(channel)))) {
12542 astman_send_error(s, m, "No such channel");
12543 return 0;
12544 }
12545 p->dnd = dnd;
12546 local_astman_ack(s, m, "DND", zap_mode);
12547
12548 return 0;
12549 }
12550
12551 static int zap_action_dndon(struct mansession *s, const struct message *m)
12552 {
12553 return __action_dnd(s, m, 1, 1);
12554 }
12555
12556 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
12557 {
12558 return __action_dnd(s, m, 0, 1);
12559 }
12560
12561 static int zap_action_dndoff(struct mansession *s, const struct message *m)
12562 {
12563 return __action_dnd(s, m, 1, 0);
12564 }
12565
12566 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
12567 {
12568 return __action_dnd(s, m, 0, 0);
12569 }
12570
12571 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
12572 {
12573 struct dahdi_pvt *p = NULL;
12574 const char *channel = local_astman_header(m, "Channel", zap_mode);
12575
12576 if (ast_strlen_zero(channel)) {
12577 astman_send_error(s, m, "No channel specified");
12578 return 0;
12579 }
12580 if (!(p = find_channel(atoi(channel)))) {
12581 astman_send_error(s, m, "No such channel");
12582 return 0;
12583 }
12584 dahdi_fake_event(p,TRANSFER);
12585 local_astman_ack(s, m, "Transfer", zap_mode);
12586
12587 return 0;
12588 }
12589
12590 static int zap_action_transfer(struct mansession *s, const struct message *m)
12591 {
12592 return __action_transfer(s, m, 1);
12593 }
12594
12595 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
12596 {
12597 return __action_transfer(s, m, 0);
12598 }
12599
12600 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
12601 {
12602 struct dahdi_pvt *p = NULL;
12603 const char *channel = local_astman_header(m, "Channel", zap_mode);
12604
12605 if (ast_strlen_zero(channel)) {
12606 astman_send_error(s, m, "No channel specified");
12607 return 0;
12608 }
12609 if (!(p = find_channel(atoi(channel)))) {
12610 astman_send_error(s, m, "No such channel");
12611 return 0;
12612 }
12613 dahdi_fake_event(p, HANGUP);
12614 local_astman_ack(s, m, "Hangup", zap_mode);
12615 return 0;
12616 }
12617
12618 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
12619 {
12620 return __action_transferhangup(s, m, 1);
12621 }
12622
12623 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
12624 {
12625 return __action_transferhangup(s, m, 0);
12626 }
12627
12628 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
12629 {
12630 struct dahdi_pvt *p = NULL;
12631 const char *channel = local_astman_header(m, "Channel", zap_mode);
12632 const char *number = astman_get_header(m, "Number");
12633 int i;
12634
12635 if (ast_strlen_zero(channel)) {
12636 astman_send_error(s, m, "No channel specified");
12637 return 0;
12638 }
12639 if (ast_strlen_zero(number)) {
12640 astman_send_error(s, m, "No number specified");
12641 return 0;
12642 }
12643 if (!(p = find_channel(atoi(channel)))) {
12644 astman_send_error(s, m, "No such channel");
12645 return 0;
12646 }
12647 if (!p->owner) {
12648 astman_send_error(s, m, "Channel does not have an owner");
12649 return 0;
12650 }
12651 for (i = 0; i < strlen(number); i++) {
12652 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12653
12654 dahdi_queue_frame(p, &f, NULL);
12655 }
12656 local_astman_ack(s, m, "DialOffHook", zap_mode);
12657
12658 return 0;
12659 }
12660
12661 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
12662 {
12663 return __action_dialoffhook(s, m, 1);
12664 }
12665
12666 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
12667 {
12668 return __action_dialoffhook(s, m, 0);
12669 }
12670
12671 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
12672 {
12673 struct dahdi_pvt *tmp = NULL;
12674 const char *id = astman_get_header(m, "ActionID");
12675 char idText[256] = "";
12676
12677 local_astman_ack(s, m, " channel status will follow", zap_mode);
12678 if (!ast_strlen_zero(id))
12679 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12680
12681 ast_mutex_lock(&iflock);
12682
12683 tmp = iflist;
12684 while (tmp) {
12685 if (tmp->channel > 0) {
12686 int alarm = get_alarms(tmp);
12687 astman_append(s,
12688 "Event: %sShowChannels\r\n"
12689 "Channel: %d\r\n"
12690 "Signalling: %s\r\n"
12691 "Context: %s\r\n"
12692 "DND: %s\r\n"
12693 "Alarm: %s\r\n"
12694 "%s"
12695 "\r\n",
12696 dahdi_chan_name,
12697 tmp->channel, sig2str(tmp->sig), tmp->context,
12698 tmp->dnd ? "Enabled" : "Disabled",
12699 alarm2str(alarm), idText);
12700 }
12701
12702 tmp = tmp->next;
12703 }
12704
12705 ast_mutex_unlock(&iflock);
12706
12707 astman_append(s,
12708 "Event: %sShowChannelsComplete\r\n"
12709 "%s"
12710 "\r\n",
12711 dahdi_chan_name,
12712 idText);
12713 return 0;
12714 }
12715
12716 static int zap_action_showchannels(struct mansession *s, const struct message *m)
12717 {
12718 return __action_showchannels(s, m, 1);
12719 }
12720
12721 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
12722 {
12723 return __action_showchannels(s, m, 0);
12724 }
12725
12726 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
12727 {
12728 if (dahdi_restart() != 0) {
12729 if (zap_mode) {
12730 astman_send_error(s, m, "Failed to restart Zap");
12731 } else {
12732 astman_send_error(s, m, "Failed to restart DAHDI");
12733 }
12734 return 1;
12735 }
12736 local_astman_ack(s, m, "Restart: Success", zap_mode);
12737 return 0;
12738 }
12739
12740 static int zap_action_restart(struct mansession *s, const struct message *m)
12741 {
12742 return __action_restart(s, m, 1);
12743 }
12744
12745 static int dahdi_action_restart(struct mansession *s, const struct message *m)
12746 {
12747 return __action_restart(s, m, 0);
12748 }
12749
12750 #define local_astman_unregister(a) do { \
12751 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12752 ast_manager_unregister("DAHDI" a); \
12753 } \
12754 ast_manager_unregister("Zap" a); \
12755 } while (0)
12756
12757 static int __unload_module(void)
12758 {
12759 struct dahdi_pvt *p;
12760 #ifdef HAVE_OPENR2
12761 int r;
12762 #endif
12763 #ifdef HAVE_PRI
12764 int i, j;
12765 for (i = 0; i < NUM_SPANS; i++) {
12766 if (pris[i].master != AST_PTHREADT_NULL)
12767 pthread_cancel(pris[i].master);
12768 }
12769 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12770
12771 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12772 ast_unregister_application(dahdi_send_keypad_facility_app);
12773 }
12774 ast_unregister_application(zap_send_keypad_facility_app);
12775 #endif
12776 #ifdef HAVE_OPENR2
12777 for (r = 0; r < NUM_SPANS; r++) {
12778 if (r2links[r].master != AST_PTHREADT_NULL) {
12779 pthread_cancel(r2links[r].master);
12780 pthread_join(r2links[r].master, NULL);
12781 }
12782 }
12783 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
12784 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12785 ast_unregister_application(dahdi_accept_r2_call_app);
12786 }
12787 ast_unregister_application(zap_accept_r2_call_app);
12788 #endif
12789 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12790 local_astman_unregister("DialOffHook");
12791 local_astman_unregister("Hangup");
12792 local_astman_unregister("Transfer");
12793 local_astman_unregister("DNDoff");
12794 local_astman_unregister("DNDon");
12795 local_astman_unregister("ShowChannels");
12796 local_astman_unregister("Restart");
12797 ast_channel_unregister(chan_tech);
12798 ast_mutex_lock(&iflock);
12799
12800 p = iflist;
12801 while (p) {
12802 if (p->owner)
12803 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12804 p = p->next;
12805 }
12806 ast_mutex_unlock(&iflock);
12807 ast_mutex_lock(&monlock);
12808 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12809 pthread_cancel(monitor_thread);
12810 pthread_kill(monitor_thread, SIGURG);
12811 pthread_join(monitor_thread, NULL);
12812 }
12813 monitor_thread = AST_PTHREADT_STOP;
12814 ast_mutex_unlock(&monlock);
12815
12816 destroy_all_channels();
12817 #ifdef HAVE_PRI
12818 for (i = 0; i < NUM_SPANS; i++) {
12819 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12820 pthread_join(pris[i].master, NULL);
12821 for (j = 0; j < NUM_DCHANS; j++) {
12822 dahdi_close_pri_fd(&(pris[i]), j);
12823 }
12824 }
12825 #endif
12826 #ifdef HAVE_OPENR2
12827 for (r = 0; r < NUM_SPANS; r++) {
12828 if (r2links[r].protocol_context) {
12829 openr2_context_delete(r2links[r].protocol_context);
12830 }
12831 }
12832 #endif
12833 ast_cond_destroy(&ss_thread_complete);
12834 return 0;
12835 }
12836
12837 static int unload_module(void)
12838 {
12839 #ifdef HAVE_PRI
12840 int y;
12841 for (y = 0; y < NUM_SPANS; y++)
12842 ast_mutex_destroy(&pris[y].lock);
12843 #endif
12844 return __unload_module();
12845 }
12846
12847 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
12848 {
12849 char *c, *chan;
12850 int x, start, finish;
12851 struct dahdi_pvt *tmp;
12852 #ifdef HAVE_PRI
12853 struct dahdi_pri *pri;
12854 int trunkgroup, y;
12855 #endif
12856
12857 if ((reload == 0) && (conf->chan.sig < 0)) {
12858 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12859 return -1;
12860 }
12861
12862 c = ast_strdupa(value);
12863
12864 #ifdef HAVE_PRI
12865 pri = NULL;
12866 if (iscrv) {
12867 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
12868 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12869 return -1;
12870 }
12871 if (trunkgroup < 1) {
12872 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12873 return -1;
12874 }
12875 c += y;
12876 for (y = 0; y < NUM_SPANS; y++) {
12877 if (pris[y].trunkgroup == trunkgroup) {
12878 pri = pris + y;
12879 break;
12880 }
12881 }
12882 if (!pri) {
12883 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12884 return -1;
12885 }
12886 }
12887 #endif
12888
12889 while ((chan = strsep(&c, ","))) {
12890 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
12891
12892 } else if (sscanf(chan, "%30d", &start)) {
12893
12894 finish = start;
12895 } else if (!strcasecmp(chan, "pseudo")) {
12896 finish = start = CHAN_PSEUDO;
12897 if (found_pseudo)
12898 *found_pseudo = 1;
12899 } else {
12900 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12901 return -1;
12902 }
12903 if (finish < start) {
12904 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12905 x = finish;
12906 finish = start;
12907 start = x;
12908 }
12909
12910 for (x = start; x <= finish; x++) {
12911 #ifdef HAVE_PRI
12912 tmp = mkintf(x, conf, pri, reload);
12913 #else
12914 tmp = mkintf(x, conf, NULL, reload);
12915 #endif
12916
12917 if (tmp) {
12918 if (option_verbose > 2) {
12919 #ifdef HAVE_PRI
12920 if (pri)
12921 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12922 else
12923 #endif
12924 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12925 }
12926 } else {
12927 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12928 (reload == 1) ? "reconfigure" : "register", value);
12929 return -1;
12930 }
12931 }
12932 #ifdef HAVE_OPENR2
12933 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
12934 mfcr2_cur_context_index++;
12935 }
12936 #endif
12937 }
12938
12939 return 0;
12940 }
12941
12942
12943
12944 #define MAX_CHANLIST_LEN 80
12945 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
12946 {
12947 struct dahdi_pvt *tmp;
12948 int y;
12949 int found_pseudo = 0;
12950 char dahdichan[MAX_CHANLIST_LEN] = {};
12951
12952 for (; v; v = v->next) {
12953 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
12954 continue;
12955
12956
12957 if (!strcasecmp(v->name, "channel")
12958 #ifdef HAVE_PRI
12959 || !strcasecmp(v->name, "crv")
12960 #endif
12961 ) {
12962 int iscrv;
12963 if (skipchannels)
12964 continue;
12965 iscrv = !strcasecmp(v->name, "crv");
12966 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
12967 return -1;
12968 } else if (!strcasecmp(v->name, "buffers")) {
12969 int res;
12970 char policy[21] = "";
12971
12972 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
12973 if (res != 2) {
12974 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
12975 confp->chan.buf_no = numbufs;
12976 continue;
12977 }
12978 if (confp->chan.buf_no < 0)
12979 confp->chan.buf_no = numbufs;
12980 if (!strcasecmp(policy, "full")) {
12981 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
12982 } else if (!strcasecmp(policy, "immediate")) {
12983 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
12984 } else {
12985 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
12986 }
12987 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
12988 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
12989 if (v->name[0] == 'z' || v->name[0] == 'Z') {
12990 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
12991 }
12992 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
12993 if (ast_true(v->value))
12994 confp->chan.usedistinctiveringdetection = 1;
12995 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
12996 if (ast_true(v->value))
12997 distinctiveringaftercid = 1;
12998 } else if (!strcasecmp(v->name, "dring1context")) {
12999 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
13000 } else if (!strcasecmp(v->name, "dring2context")) {
13001 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
13002 } else if (!strcasecmp(v->name, "dring3context")) {
13003 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
13004 } else if (!strcasecmp(v->name, "dring1")) {
13005 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
13006 } else if (!strcasecmp(v->name, "dring2")) {
13007 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
13008 } else if (!strcasecmp(v->name, "dring3")) {
13009 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
13010 } else if (!strcasecmp(v->name, "usecallerid")) {
13011 confp->chan.use_callerid = ast_true(v->value);
13012 } else if (!strcasecmp(v->name, "cidsignalling")) {
13013 if (!strcasecmp(v->value, "bell"))
13014 confp->chan.cid_signalling = CID_SIG_BELL;
13015 else if (!strcasecmp(v->value, "v23"))
13016 confp->chan.cid_signalling = CID_SIG_V23;
13017 else if (!strcasecmp(v->value, "dtmf"))
13018 confp->chan.cid_signalling = CID_SIG_DTMF;
13019 else if (!strcasecmp(v->value, "smdi"))
13020 confp->chan.cid_signalling = CID_SIG_SMDI;
13021 else if (!strcasecmp(v->value, "v23_jp"))
13022 confp->chan.cid_signalling = CID_SIG_V23_JP;
13023 else if (ast_true(v->value))
13024 confp->chan.cid_signalling = CID_SIG_BELL;
13025 } else if (!strcasecmp(v->name, "cidstart")) {
13026 if (!strcasecmp(v->value, "ring"))
13027 confp->chan.cid_start = CID_START_RING;
13028 else if (!strcasecmp(v->value, "polarity"))
13029 confp->chan.cid_start = CID_START_POLARITY;
13030 else if (!strcasecmp(v->value, "dtmf"))
13031 confp->chan.cid_start = CID_START_DTMF_NOALERT;
13032 else if (ast_true(v->value))
13033 confp->chan.cid_start = CID_START_RING;
13034 } else if (!strcasecmp(v->name, "threewaycalling")) {
13035 confp->chan.threewaycalling = ast_true(v->value);
13036 } else if (!strcasecmp(v->name, "cancallforward")) {
13037 confp->chan.cancallforward = ast_true(v->value);
13038 } else if (!strcasecmp(v->name, "relaxdtmf")) {
13039 if (ast_true(v->value))
13040 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
13041 else
13042 confp->chan.dtmfrelax = 0;
13043 } else if (!strcasecmp(v->name, "mailbox")) {
13044 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
13045 } else if (!strcasecmp(v->name, "hasvoicemail")) {
13046 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
13047 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
13048 }
13049 } else if (!strcasecmp(v->name, "adsi")) {
13050 confp->chan.adsi = ast_true(v->value);
13051 } else if (!strcasecmp(v->name, "usesmdi")) {
13052 confp->chan.use_smdi = ast_true(v->value);
13053 } else if (!strcasecmp(v->name, "smdiport")) {
13054 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
13055 } else if (!strcasecmp(v->name, "transfer")) {
13056 confp->chan.transfer = ast_true(v->value);
13057 } else if (!strcasecmp(v->name, "canpark")) {
13058 confp->chan.canpark = ast_true(v->value);
13059 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
13060 confp->chan.echocanbridged = ast_true(v->value);
13061 } else if (!strcasecmp(v->name, "busydetect")) {
13062 confp->chan.busydetect = ast_true(v->value);
13063 } else if (!strcasecmp(v->name, "busycount")) {
13064 confp->chan.busycount = atoi(v->value);
13065 } else if (!strcasecmp(v->name, "silencethreshold")) {
13066 confp->chan.silencethreshold = atoi(v->value);
13067 } else if (!strcasecmp(v->name, "busycompare")) {
13068 confp->chan.busycompare = ast_true(v->value);
13069 } else if (!strcasecmp(v->name, "busypattern")) {
13070 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
13071 if (count == 1)
13072 confp->chan.busyquietlength = 0;
13073 else if (count < 1)
13074 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
13075 } else if (!strcasecmp(v->name, "busyfuzziness")) {
13076 confp->chan.busyfuzziness = atoi(v->value);
13077 } else if (!strcasecmp(v->name, "callprogress")) {
13078 if (ast_true(v->value))
13079 confp->chan.callprogress |= 1;
13080 else
13081 confp->chan.callprogress &= ~1;
13082 } else if (!strcasecmp(v->name, "faxdetect")) {
13083 if (!strcasecmp(v->value, "incoming")) {
13084 confp->chan.callprogress |= 4;
13085 confp->chan.callprogress &= ~2;
13086 } else if (!strcasecmp(v->value, "outgoing")) {
13087 confp->chan.callprogress &= ~4;
13088 confp->chan.callprogress |= 2;
13089 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
13090 confp->chan.callprogress |= 6;
13091 else
13092 confp->chan.callprogress &= ~6;
13093 } else if (!strcasecmp(v->name, "echocancel")) {
13094 if (!ast_strlen_zero(v->value)) {
13095 y = atoi(v->value);
13096 } else
13097 y = 0;
13098 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
13099 confp->chan.echocancel = y;
13100 else {
13101 confp->chan.echocancel = ast_true(v->value);
13102 if (confp->chan.echocancel)
13103 confp->chan.echocancel=128;
13104 }
13105 } else if (!strcasecmp(v->name, "echotraining")) {
13106 if (sscanf(v->value, "%30d", &y) == 1) {
13107 if ((y < 10) || (y > 4000)) {
13108 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
13109 } else {
13110 confp->chan.echotraining = y;
13111 }
13112 } else if (ast_true(v->value)) {
13113 confp->chan.echotraining = 400;
13114 } else
13115 confp->chan.echotraining = 0;
13116 } else if (!strcasecmp(v->name, "hidecallerid")) {
13117 confp->chan.hidecallerid = ast_true(v->value);
13118 } else if (!strcasecmp(v->name, "hidecalleridname")) {
13119 confp->chan.hidecalleridname = ast_true(v->value);
13120 } else if (!strcasecmp(v->name, "pulsedial")) {
13121 confp->chan.pulse = ast_true(v->value);
13122 } else if (!strcasecmp(v->name, "callreturn")) {
13123 confp->chan.callreturn = ast_true(v->value);
13124 } else if (!strcasecmp(v->name, "callwaiting")) {
13125 confp->chan.callwaiting = ast_true(v->value);
13126 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
13127 confp->chan.callwaitingcallerid = ast_true(v->value);
13128 } else if (!strcasecmp(v->name, "context")) {
13129 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
13130 } else if (!strcasecmp(v->name, "language")) {
13131 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
13132 } else if (!strcasecmp(v->name, "progzone")) {
13133 ast_copy_string(progzone, v->value, sizeof(progzone));
13134 } else if (!strcasecmp(v->name, "mohinterpret")
13135 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
13136 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
13137 } else if (!strcasecmp(v->name, "mohsuggest")) {
13138 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
13139 } else if (!strcasecmp(v->name, "stripmsd")) {
13140 confp->chan.stripmsd = atoi(v->value);
13141 } else if (!strcasecmp(v->name, "jitterbuffers")) {
13142 numbufs = atoi(v->value);
13143 } else if (!strcasecmp(v->name, "group")) {
13144 confp->chan.group = ast_get_group(v->value);
13145 } else if (!strcasecmp(v->name, "callgroup")) {
13146 confp->chan.callgroup = ast_get_group(v->value);
13147 } else if (!strcasecmp(v->name, "pickupgroup")) {
13148 confp->chan.pickupgroup = ast_get_group(v->value);
13149 } else if (!strcasecmp(v->name, "immediate")) {
13150 confp->chan.immediate = ast_true(v->value);
13151 } else if (!strcasecmp(v->name, "transfertobusy")) {
13152 confp->chan.transfertobusy = ast_true(v->value);
13153 } else if (!strcasecmp(v->name, "rxgain")) {
13154 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
13155 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
13156 }
13157 } else if (!strcasecmp(v->name, "txgain")) {
13158 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
13159 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
13160 }
13161 } else if (!strcasecmp(v->name, "tonezone")) {
13162 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
13163 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
13164 }
13165 } else if (!strcasecmp(v->name, "callerid")) {
13166 if (!strcasecmp(v->value, "asreceived")) {
13167 confp->chan.cid_num[0] = '\0';
13168 confp->chan.cid_name[0] = '\0';
13169 } else {
13170 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
13171 }
13172 } else if (!strcasecmp(v->name, "fullname")) {
13173 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
13174 } else if (!strcasecmp(v->name, "cid_number")) {
13175 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
13176 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
13177 confp->chan.dahditrcallerid = ast_true(v->value);
13178 if (strstr(v->name, "zap")) {
13179 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
13180 }
13181 } else if (!strcasecmp(v->name, "restrictcid")) {
13182 confp->chan.restrictcid = ast_true(v->value);
13183 } else if (!strcasecmp(v->name, "usecallingpres")) {
13184 confp->chan.use_callingpres = ast_true(v->value);
13185 } else if (!strcasecmp(v->name, "accountcode")) {
13186 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
13187 } else if (!strcasecmp(v->name, "amaflags")) {
13188 y = ast_cdr_amaflags2int(v->value);
13189 if (y < 0)
13190 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
13191 else
13192 confp->chan.amaflags = y;
13193 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
13194 confp->chan.polarityonanswerdelay = atoi(v->value);
13195 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
13196 confp->chan.answeronpolarityswitch = ast_true(v->value);
13197 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
13198 confp->chan.hanguponpolarityswitch = ast_true(v->value);
13199 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
13200 confp->chan.sendcalleridafter = atoi(v->value);
13201 } else if (reload != 1) {
13202 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
13203 confp->chan.outsigmod = -1;
13204 if (!strcasecmp(v->value, "em")) {
13205 confp->chan.sig = SIG_EM;
13206 } else if (!strcasecmp(v->value, "em_e1")) {
13207 confp->chan.sig = SIG_EM_E1;
13208 } else if (!strcasecmp(v->value, "em_w")) {
13209 confp->chan.sig = SIG_EMWINK;
13210 confp->chan.radio = 0;
13211 } else if (!strcasecmp(v->value, "fxs_ls")) {
13212 confp->chan.sig = SIG_FXSLS;
13213 confp->chan.radio = 0;
13214 } else if (!strcasecmp(v->value, "fxs_gs")) {
13215 confp->chan.sig = SIG_FXSGS;
13216 confp->chan.radio = 0;
13217 } else if (!strcasecmp(v->value, "fxs_ks")) {
13218 confp->chan.sig = SIG_FXSKS;
13219 confp->chan.radio = 0;
13220 } else if (!strcasecmp(v->value, "fxo_ls")) {
13221 confp->chan.sig = SIG_FXOLS;
13222 confp->chan.radio = 0;
13223 } else if (!strcasecmp(v->value, "fxo_gs")) {
13224 confp->chan.sig = SIG_FXOGS;
13225 confp->chan.radio = 0;
13226 } else if (!strcasecmp(v->value, "fxo_ks")) {
13227 confp->chan.sig = SIG_FXOKS;
13228 confp->chan.radio = 0;
13229 } else if (!strcasecmp(v->value, "fxs_rx")) {
13230 confp->chan.sig = SIG_FXSKS;
13231 confp->chan.radio = 1;
13232 } else if (!strcasecmp(v->value, "fxo_rx")) {
13233 confp->chan.sig = SIG_FXOLS;
13234 confp->chan.radio = 1;
13235 } else if (!strcasecmp(v->value, "fxs_tx")) {
13236 confp->chan.sig = SIG_FXSLS;
13237 confp->chan.radio = 1;
13238 } else if (!strcasecmp(v->value, "fxo_tx")) {
13239 confp->chan.sig = SIG_FXOGS;
13240 confp->chan.radio = 1;
13241 } else if (!strcasecmp(v->value, "em_rx")) {
13242 confp->chan.sig = SIG_EM;
13243 confp->chan.radio = 1;
13244 } else if (!strcasecmp(v->value, "em_tx")) {
13245 confp->chan.sig = SIG_EM;
13246 confp->chan.radio = 1;
13247 } else if (!strcasecmp(v->value, "em_rxtx")) {
13248 confp->chan.sig = SIG_EM;
13249 confp->chan.radio = 2;
13250 } else if (!strcasecmp(v->value, "em_txrx")) {
13251 confp->chan.sig = SIG_EM;
13252 confp->chan.radio = 2;
13253 } else if (!strcasecmp(v->value, "sf")) {
13254 confp->chan.sig = SIG_SF;
13255 confp->chan.radio = 0;
13256 } else if (!strcasecmp(v->value, "sf_w")) {
13257 confp->chan.sig = SIG_SFWINK;
13258 confp->chan.radio = 0;
13259 } else if (!strcasecmp(v->value, "sf_featd")) {
13260 confp->chan.sig = SIG_FEATD;
13261 confp->chan.radio = 0;
13262 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13263 confp->chan.sig = SIG_FEATDMF;
13264 confp->chan.radio = 0;
13265 } else if (!strcasecmp(v->value, "sf_featb")) {
13266 confp->chan.sig = SIG_SF_FEATB;
13267 confp->chan.radio = 0;
13268 } else if (!strcasecmp(v->value, "sf")) {
13269 confp->chan.sig = SIG_SF;
13270 confp->chan.radio = 0;
13271 } else if (!strcasecmp(v->value, "sf_rx")) {
13272 confp->chan.sig = SIG_SF;
13273 confp->chan.radio = 1;
13274 } else if (!strcasecmp(v->value, "sf_tx")) {
13275 confp->chan.sig = SIG_SF;
13276 confp->chan.radio = 1;
13277 } else if (!strcasecmp(v->value, "sf_rxtx")) {
13278 confp->chan.sig = SIG_SF;
13279 confp->chan.radio = 2;
13280 } else if (!strcasecmp(v->value, "sf_txrx")) {
13281 confp->chan.sig = SIG_SF;
13282 confp->chan.radio = 2;
13283 } else if (!strcasecmp(v->value, "featd")) {
13284 confp->chan.sig = SIG_FEATD;
13285 confp->chan.radio = 0;
13286 } else if (!strcasecmp(v->value, "featdmf")) {
13287 confp->chan.sig = SIG_FEATDMF;
13288 confp->chan.radio = 0;
13289 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13290 confp->chan.sig = SIG_FEATDMF_TA;
13291 confp->chan.radio = 0;
13292 } else if (!strcasecmp(v->value, "e911")) {
13293 confp->chan.sig = SIG_E911;
13294 confp->chan.radio = 0;
13295 } else if (!strcasecmp(v->value, "fgccama")) {
13296 confp->chan.sig = SIG_FGC_CAMA;
13297 confp->chan.radio = 0;
13298 } else if (!strcasecmp(v->value, "fgccamamf")) {
13299 confp->chan.sig = SIG_FGC_CAMAMF;
13300 confp->chan.radio = 0;
13301 } else if (!strcasecmp(v->value, "featb")) {
13302 confp->chan.sig = SIG_FEATB;
13303 confp->chan.radio = 0;
13304 #ifdef HAVE_OPENR2
13305 } else if (!strcasecmp(v->value, "mfcr2")) {
13306 confp->chan.sig = SIG_MFCR2;
13307 #endif
13308 #ifdef HAVE_PRI
13309 } else if (!strcasecmp(v->value, "pri_net")) {
13310 confp->chan.radio = 0;
13311 confp->chan.sig = SIG_PRI;
13312 confp->pri.nodetype = PRI_NETWORK;
13313 } else if (!strcasecmp(v->value, "pri_cpe")) {
13314 confp->chan.sig = SIG_PRI;
13315 confp->chan.radio = 0;
13316 confp->pri.nodetype = PRI_CPE;
13317 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
13318 confp->chan.sig = SIG_GR303FXOKS;
13319 confp->chan.radio = 0;
13320 confp->pri.nodetype = PRI_NETWORK;
13321 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
13322 confp->chan.sig = SIG_GR303FXSKS;
13323 confp->chan.radio = 0;
13324 confp->pri.nodetype = PRI_CPE;
13325 #endif
13326 } else {
13327 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13328 }
13329 } else if (!strcasecmp(v->name, "outsignalling")) {
13330 if (!strcasecmp(v->value, "em")) {
13331 confp->chan.outsigmod = SIG_EM;
13332 } else if (!strcasecmp(v->value, "em_e1")) {
13333 confp->chan.outsigmod = SIG_EM_E1;
13334 } else if (!strcasecmp(v->value, "em_w")) {
13335 confp->chan.outsigmod = SIG_EMWINK;
13336 } else if (!strcasecmp(v->value, "sf")) {
13337 confp->chan.outsigmod = SIG_SF;
13338 } else if (!strcasecmp(v->value, "sf_w")) {
13339 confp->chan.outsigmod = SIG_SFWINK;
13340 } else if (!strcasecmp(v->value, "sf_featd")) {
13341 confp->chan.outsigmod = SIG_FEATD;
13342 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13343 confp->chan.outsigmod = SIG_FEATDMF;
13344 } else if (!strcasecmp(v->value, "sf_featb")) {
13345 confp->chan.outsigmod = SIG_SF_FEATB;
13346 } else if (!strcasecmp(v->value, "sf")) {
13347 confp->chan.outsigmod = SIG_SF;
13348 } else if (!strcasecmp(v->value, "featd")) {
13349 confp->chan.outsigmod = SIG_FEATD;
13350 } else if (!strcasecmp(v->value, "featdmf")) {
13351 confp->chan.outsigmod = SIG_FEATDMF;
13352 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13353 confp->chan.outsigmod = SIG_FEATDMF_TA;
13354 } else if (!strcasecmp(v->value, "e911")) {
13355 confp->chan.outsigmod = SIG_E911;
13356 } else if (!strcasecmp(v->value, "fgccama")) {
13357 confp->chan.outsigmod = SIG_FGC_CAMA;
13358 } else if (!strcasecmp(v->value, "fgccamamf")) {
13359 confp->chan.outsigmod = SIG_FGC_CAMAMF;
13360 } else if (!strcasecmp(v->value, "featb")) {
13361 confp->chan.outsigmod = SIG_FEATB;
13362 } else {
13363 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13364 }
13365 #ifdef HAVE_PRI
13366 } else if (!strcasecmp(v->name, "pridialplan")) {
13367 if (!strcasecmp(v->value, "national")) {
13368 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
13369 } else if (!strcasecmp(v->value, "unknown")) {
13370 confp->pri.dialplan = PRI_UNKNOWN + 1;
13371 } else if (!strcasecmp(v->value, "private")) {
13372 confp->pri.dialplan = PRI_PRIVATE + 1;
13373 } else if (!strcasecmp(v->value, "international")) {
13374 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
13375 } else if (!strcasecmp(v->value, "local")) {
13376 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
13377 } else if (!strcasecmp(v->value, "dynamic")) {
13378 confp->pri.dialplan = -1;
13379 } else {
13380 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13381 }
13382 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
13383 if (!strcasecmp(v->value, "national")) {
13384 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
13385 } else if (!strcasecmp(v->value, "unknown")) {
13386 confp->pri.localdialplan = PRI_UNKNOWN + 1;
13387 } else if (!strcasecmp(v->value, "private")) {
13388 confp->pri.localdialplan = PRI_PRIVATE + 1;
13389 } else if (!strcasecmp(v->value, "international")) {
13390 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
13391 } else if (!strcasecmp(v->value, "local")) {
13392 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
13393 } else if (!strcasecmp(v->value, "dynamic")) {
13394 confp->pri.localdialplan = -1;
13395 } else {
13396 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13397 }
13398 } else if (!strcasecmp(v->name, "switchtype")) {
13399 if (!strcasecmp(v->value, "national"))
13400 confp->pri.switchtype = PRI_SWITCH_NI2;
13401 else if (!strcasecmp(v->value, "ni1"))
13402 confp->pri.switchtype = PRI_SWITCH_NI1;
13403 else if (!strcasecmp(v->value, "dms100"))
13404 confp->pri.switchtype = PRI_SWITCH_DMS100;
13405 else if (!strcasecmp(v->value, "4ess"))
13406 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
13407 else if (!strcasecmp(v->value, "5ess"))
13408 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
13409 else if (!strcasecmp(v->value, "euroisdn"))
13410 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
13411 else if (!strcasecmp(v->value, "qsig"))
13412 confp->pri.switchtype = PRI_SWITCH_QSIG;
13413 else {
13414 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
13415 return -1;
13416 }
13417 } else if (!strcasecmp(v->name, "nsf")) {
13418 if (!strcasecmp(v->value, "sdn"))
13419 confp->pri.nsf = PRI_NSF_SDN;
13420 else if (!strcasecmp(v->value, "megacom"))
13421 confp->pri.nsf = PRI_NSF_MEGACOM;
13422 else if (!strcasecmp(v->value, "tollfreemegacom"))
13423 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
13424 else if (!strcasecmp(v->value, "accunet"))
13425 confp->pri.nsf = PRI_NSF_ACCUNET;
13426 else if (!strcasecmp(v->value, "none"))
13427 confp->pri.nsf = PRI_NSF_NONE;
13428 else {
13429 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
13430 confp->pri.nsf = PRI_NSF_NONE;
13431 }
13432 } else if (!strcasecmp(v->name, "priindication")) {
13433 if (!strcasecmp(v->value, "outofband"))
13434 confp->chan.priindication_oob = 1;
13435 else if (!strcasecmp(v->value, "inband"))
13436 confp->chan.priindication_oob = 0;
13437 else
13438 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
13439 v->value, v->lineno);
13440 } else if (!strcasecmp(v->name, "priexclusive")) {
13441 confp->chan.priexclusive = ast_true(v->value);
13442 } else if (!strcasecmp(v->name, "internationalprefix")) {
13443 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
13444 } else if (!strcasecmp(v->name, "nationalprefix")) {
13445 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
13446 } else if (!strcasecmp(v->name, "localprefix")) {
13447 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
13448 } else if (!strcasecmp(v->name, "privateprefix")) {
13449 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
13450 } else if (!strcasecmp(v->name, "unknownprefix")) {
13451 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
13452 } else if (!strcasecmp(v->name, "resetinterval")) {
13453 if (!strcasecmp(v->value, "never"))
13454 confp->pri.resetinterval = -1;
13455 else if (atoi(v->value) >= 60)
13456 confp->pri.resetinterval = atoi(v->value);
13457 else
13458 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
13459 v->value, v->lineno);
13460 } else if (!strcasecmp(v->name, "minunused")) {
13461 confp->pri.minunused = atoi(v->value);
13462 } else if (!strcasecmp(v->name, "minidle")) {
13463 confp->pri.minidle = atoi(v->value);
13464 } else if (!strcasecmp(v->name, "idleext")) {
13465 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
13466 } else if (!strcasecmp(v->name, "idledial")) {
13467 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
13468 } else if (!strcasecmp(v->name, "overlapdial")) {
13469 if (ast_true(v->value)) {
13470 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13471 } else if (!strcasecmp(v->value, "incoming")) {
13472 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
13473 } else if (!strcasecmp(v->value, "outgoing")) {
13474 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
13475 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
13476 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13477 } else {
13478 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
13479 }
13480 #ifdef HAVE_PRI_INBANDDISCONNECT
13481 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
13482 confp->pri.inbanddisconnect = ast_true(v->value);
13483 #endif
13484 } else if (!strcasecmp(v->name, "pritimer")) {
13485 #ifdef PRI_GETSET_TIMERS
13486 char tmp[20];
13487 char *timerc;
13488 char *c;
13489 int timer;
13490 int timeridx;
13491
13492 ast_copy_string(tmp, v->value, sizeof(tmp));
13493 c = tmp;
13494 timerc = strsep(&c, ",");
13495 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
13496 timeridx = pri_timer2idx(timerc);
13497 timer = atoi(c);
13498 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
13499 ast_log(LOG_WARNING,
13500 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
13501 v->lineno);
13502 } else if (!timer) {
13503 ast_log(LOG_WARNING,
13504 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
13505 c, timerc, v->lineno);
13506 } else {
13507 pritimers[timeridx] = timer;
13508 }
13509 } else {
13510 ast_log(LOG_WARNING,
13511 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
13512 v->value, v->lineno);
13513 }
13514 #endif
13515 } else if (!strcasecmp(v->name, "facilityenable")) {
13516 confp->pri.facilityenable = ast_true(v->value);
13517 #endif
13518 #ifdef HAVE_OPENR2
13519 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
13520 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
13521 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);
13522 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
13523 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
13524 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
13525 mfcr2_cur_variant = openr2_proto_get_variant(v->value);
13526 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
13527 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
13528 }
13529 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
13530 mfcr2_cur_mfback_timeout = atoi(v->value);
13531 if (!mfcr2_cur_mfback_timeout) {
13532 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
13533 mfcr2_cur_mfback_timeout = -1;
13534 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
13535 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
13536 }
13537 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
13538 mfcr2_cur_metering_pulse_timeout = atoi(v->value);
13539 if (mfcr2_cur_metering_pulse_timeout > 500) {
13540 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
13541 }
13542 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13543 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
13544 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
13545 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
13546 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
13547 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
13548 mfcr2_cur_dtmf_time_on = atoi(v->value);
13549 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
13550 mfcr2_cur_dtmf_time_off = atoi(v->value);
13551 #endif
13552 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
13553 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
13554 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
13555 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
13556 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
13557 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
13558 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
13559 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
13560 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
13561 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
13562 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
13563 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
13564 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
13565 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
13566 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
13567 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
13568 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
13569 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
13570 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
13571 mfcr2_cur_max_ani = atoi(v->value);
13572 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
13573 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
13574 }
13575 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
13576 mfcr2_cur_max_dnis = atoi(v->value);
13577 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
13578 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
13579 }
13580 } else if (!strcasecmp(v->name, "mfcr2_category")) {
13581 mfcr2_cur_category = openr2_proto_get_category(v->value);
13582 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
13583 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
13584 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
13585 v->value, v->lineno);
13586 }
13587 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
13588 openr2_log_level_t tmplevel;
13589 char *toklevel = NULL;
13590 char *saveptr = NULL;
13591 char *logval = ast_strdupa(v->value);
13592 toklevel = strtok_r(logval, ",", &saveptr);
13593 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13594 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
13595 } else if (OR2_LOG_NOTHING == tmplevel) {
13596 mfcr2_cur_loglevel = tmplevel;
13597 } else {
13598 mfcr2_cur_loglevel |= tmplevel;
13599 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
13600 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13601 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
13602 continue;
13603 }
13604 mfcr2_cur_loglevel |= tmplevel;
13605 }
13606 }
13607 #endif
13608
13609 } else if (!strcasecmp(v->name, "cadence")) {
13610
13611 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
13612 int i;
13613 struct dahdi_ring_cadence new_cadence;
13614 int cid_location = -1;
13615 int firstcadencepos = 0;
13616 char original_args[80];
13617 int cadence_is_ok = 1;
13618
13619 ast_copy_string(original_args, v->value, sizeof(original_args));
13620
13621 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]);
13622
13623
13624 if (element_count % 2 == 1) {
13625 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
13626 cadence_is_ok = 0;
13627 }
13628
13629
13630 for (i = 0; i < element_count; i++) {
13631 if (c[i] == 0) {
13632 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
13633 cadence_is_ok = 0;
13634 break;
13635 } else if (c[i] < 0) {
13636 if (i % 2 == 1) {
13637
13638 if (cid_location == -1) {
13639 cid_location = i;
13640 c[i] *= -1;
13641 } else {
13642 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
13643 cadence_is_ok = 0;
13644 break;
13645 }
13646 } else {
13647 if (firstcadencepos == 0) {
13648 firstcadencepos = i;
13649
13650 } else {
13651 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
13652 cadence_is_ok = 0;
13653 break;
13654 }
13655 }
13656 }
13657 }
13658
13659
13660 for (i = 0; i < 16; i++) {
13661 new_cadence.ringcadence[i] = c[i];
13662 }
13663
13664 if (cadence_is_ok) {
13665
13666 if (element_count < 2) {
13667 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
13668 } else {
13669 if (cid_location == -1) {
13670
13671 cid_location = 1;
13672 } else {
13673
13674 cid_location = (cid_location + 1) / 2;
13675 }
13676
13677 if (!user_has_defined_cadences++)
13678
13679 num_cadence = 0;
13680 if ((num_cadence+1) >= NUM_CADENCE_MAX)
13681 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
13682 else {
13683 cadences[num_cadence] = new_cadence;
13684 cidrings[num_cadence++] = cid_location;
13685 if (option_verbose > 2)
13686 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
13687 }
13688 }
13689 }
13690 } else if (!strcasecmp(v->name, "ringtimeout")) {
13691 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
13692 } else if (!strcasecmp(v->name, "prewink")) {
13693 confp->timing.prewinktime = atoi(v->value);
13694 } else if (!strcasecmp(v->name, "preflash")) {
13695 confp->timing.preflashtime = atoi(v->value);
13696 } else if (!strcasecmp(v->name, "wink")) {
13697 confp->timing.winktime = atoi(v->value);
13698 } else if (!strcasecmp(v->name, "flash")) {
13699 confp->timing.flashtime = atoi(v->value);
13700 } else if (!strcasecmp(v->name, "start")) {
13701 confp->timing.starttime = atoi(v->value);
13702 } else if (!strcasecmp(v->name, "rxwink")) {
13703 confp->timing.rxwinktime = atoi(v->value);
13704 } else if (!strcasecmp(v->name, "rxflash")) {
13705 confp->timing.rxflashtime = atoi(v->value);
13706 } else if (!strcasecmp(v->name, "debounce")) {
13707 confp->timing.debouncetime = atoi(v->value);
13708 } else if (!strcasecmp(v->name, "toneduration")) {
13709 int toneduration;
13710 int ctlfd;
13711 int res;
13712 struct dahdi_dialparams dps;
13713
13714 ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
13715
13716 if (ctlfd == -1) {
13717 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
13718 return -1;
13719 }
13720
13721 toneduration = atoi(v->value);
13722 if (toneduration > -1) {
13723 memset(&dps, 0, sizeof(dps));
13724
13725 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
13726 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
13727 if (res < 0) {
13728 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
13729 return -1;
13730 }
13731 }
13732 close(ctlfd);
13733 } else if (!strcasecmp(v->name, "defaultcic")) {
13734 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
13735 } else if (!strcasecmp(v->name, "defaultozz")) {
13736 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
13737 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
13738 dtmfcid_level = atoi(v->value);
13739 }
13740 } else if (!skipchannels)
13741 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
13742 }
13743 if (dahdichan[0]) {
13744
13745
13746 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
13747 return -1;
13748 }
13749 }
13750
13751
13752 if (!found_pseudo && reload != 1) {
13753
13754
13755
13756
13757 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13758
13759 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
13760
13761 if (tmp) {
13762 if (option_verbose > 2)
13763 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
13764 } else {
13765 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
13766 }
13767 }
13768 return 0;
13769 }
13770
13771 static int setup_dahdi(int reload)
13772 {
13773 struct ast_config *cfg;
13774 struct ast_variable *v;
13775 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13776 int res;
13777
13778 #ifdef HAVE_PRI
13779 char *c;
13780 int spanno;
13781 int i, x;
13782 int logicalspan;
13783 int trunkgroup;
13784 int dchannels[NUM_DCHANS];
13785 #endif
13786
13787 #ifdef HAVE_ZAPTEL
13788 int load_from_zapata_conf = 1;
13789 #else
13790 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
13791 #endif
13792
13793 if (load_from_zapata_conf) {
13794 if (!(cfg = ast_config_load("zapata.conf"))) {
13795 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13796 return 0;
13797 }
13798 } else {
13799 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13800 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13801 return 0;
13802 }
13803 }
13804
13805
13806 ast_mutex_lock(&iflock);
13807 #ifdef HAVE_PRI
13808 if (reload != 1) {
13809
13810 v = ast_variable_browse(cfg, "trunkgroups");
13811 while (v) {
13812 if (!strcasecmp(v->name, "trunkgroup")) {
13813 trunkgroup = atoi(v->value);
13814 if (trunkgroup > 0) {
13815 if ((c = strchr(v->value, ','))) {
13816 i = 0;
13817 memset(dchannels, 0, sizeof(dchannels));
13818 while (c && (i < NUM_DCHANS)) {
13819 dchannels[i] = atoi(c + 1);
13820 if (dchannels[i] < 0) {
13821 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);
13822 } else
13823 i++;
13824 c = strchr(c + 1, ',');
13825 }
13826 if (i) {
13827 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13828 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);
13829 } else if (option_verbose > 1)
13830 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");
13831 } else
13832 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13833 } else
13834 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13835 } else
13836 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13837 } else if (!strcasecmp(v->name, "spanmap")) {
13838 spanno = atoi(v->value);
13839 if (spanno > 0) {
13840 if ((c = strchr(v->value, ','))) {
13841 trunkgroup = atoi(c + 1);
13842 if (trunkgroup > 0) {
13843 if ((c = strchr(c + 1, ',')))
13844 logicalspan = atoi(c + 1);
13845 else
13846 logicalspan = 0;
13847 if (logicalspan >= 0) {
13848 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13849 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13850 } else if (option_verbose > 1)
13851 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13852 } else
13853 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);
13854 } else
13855 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13856 } else
13857 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13858 } else
13859 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13860 } else {
13861 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13862 }
13863 v = v->next;
13864 }
13865 }
13866 #endif
13867
13868
13869 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13870
13871 v = ast_variable_browse(cfg, "channels");
13872 res = process_dahdi(&conf, "", v, reload, 0);
13873 ast_mutex_unlock(&iflock);
13874 ast_config_destroy(cfg);
13875 if (res)
13876 return res;
13877 cfg = ast_config_load("users.conf");
13878 if (cfg) {
13879 char *cat;
13880 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13881 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13882 if (!strcasecmp(cat, "general"))
13883 continue;
13884 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
13885 struct dahdi_chan_conf sect_conf;
13886 memcpy(§_conf, &conf, sizeof(sect_conf));
13887
13888 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13889 }
13890 }
13891 ast_config_destroy(cfg);
13892 }
13893 #ifdef HAVE_PRI
13894 if (reload != 1) {
13895 for (x = 0; x < NUM_SPANS; x++) {
13896 if (pris[x].pvts[0]) {
13897 if (start_pri(pris + x)) {
13898 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13899 return -1;
13900 } else if (option_verbose > 1)
13901 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13902 }
13903 }
13904 }
13905 #endif
13906 #ifdef HAVE_OPENR2
13907 if (reload != 1) {
13908 int x;
13909 for (x = 0; x < NUM_SPANS; x++) {
13910 if (r2links[x].protocol_context) {
13911 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
13912 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
13913 return -1;
13914 } else {
13915 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
13916 }
13917 }
13918 }
13919 }
13920 #endif
13921
13922 restart_monitor();
13923 return 0;
13924 }
13925
13926 #define local_astman_register(a, b, c, d) do { \
13927 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13928 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
13929 } \
13930 ast_manager_register("Zap" a, b, zap_ ## c, d); \
13931 } while (0)
13932
13933 static int load_module(void)
13934 {
13935 int res;
13936
13937 #ifdef HAVE_PRI
13938 int y,i;
13939 memset(pris, 0, sizeof(pris));
13940 for (y = 0; y < NUM_SPANS; y++) {
13941 ast_mutex_init(&pris[y].lock);
13942 pris[y].offset = -1;
13943 pris[y].master = AST_PTHREADT_NULL;
13944 for (i = 0; i < NUM_DCHANS; i++)
13945 pris[y].fds[i] = -1;
13946 }
13947 pri_set_error(dahdi_pri_error);
13948 pri_set_message(dahdi_pri_message);
13949 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13950 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13951 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13952 }
13953 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13954 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13955 #endif
13956 #ifdef HAVE_OPENR2
13957 init_mfcr2_globals();
13958 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13959 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
13960 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
13961 }
13962 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
13963 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
13964 #endif
13965 if ((res = setup_dahdi(0))) {
13966 return AST_MODULE_LOAD_DECLINE;
13967 }
13968 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13969 chan_tech = &dahdi_tech;
13970 } else {
13971 chan_tech = &zap_tech;
13972 }
13973 if (ast_channel_register(chan_tech)) {
13974 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
13975 __unload_module();
13976 return -1;
13977 }
13978 #ifdef HAVE_PRI
13979 ast_string_field_init(&inuse, 16);
13980 ast_string_field_set(&inuse, name, "GR-303InUse");
13981 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13982 #endif
13983 #ifdef HAVE_OPENR2
13984 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
13985 #endif
13986 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13987
13988 memset(round_robin, 0, sizeof(round_robin));
13989 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
13990 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
13991 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
13992 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
13993 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
13994 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
13995 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
13996
13997 ast_cond_init(&ss_thread_complete, NULL);
13998
13999 return res;
14000 }
14001
14002 static int dahdi_sendtext(struct ast_channel *c, const char *text)
14003 {
14004 #define END_SILENCE_LEN 400
14005 #define HEADER_MS 50
14006 #define TRAILER_MS 5
14007 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14008 #define ASCII_BYTES_PER_CHAR 80
14009
14010 unsigned char *buf,*mybuf;
14011 struct dahdi_pvt *p = c->tech_pvt;
14012 struct pollfd fds[1];
14013 int size,res,fd,len,x;
14014 int bytes=0;
14015
14016 float cr = 1.0;
14017 float ci = 0.0;
14018 float scont = 0.0;
14019 int index;
14020
14021 index = dahdi_get_index(c, p, 0);
14022 if (index < 0) {
14023 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
14024 return -1;
14025 }
14026 if (!text[0]) return(0);
14027 if ((!p->tdd) && (!p->mate)) return(0);
14028 if (p->mate)
14029 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
14030 else
14031 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
14032 if (!buf)
14033 return -1;
14034 mybuf = buf;
14035 if (p->mate) {
14036 int codec = AST_LAW(p);
14037 for (x = 0; x < HEADER_MS; x++) {
14038 PUT_CLID_MARKMS;
14039 }
14040
14041 for (x = 0; text[x]; x++) {
14042 PUT_CLID(text[x]);
14043 }
14044 for (x = 0; x < TRAILER_MS; x++) {
14045 PUT_CLID_MARKMS;
14046 }
14047 len = bytes;
14048 buf = mybuf;
14049 } else {
14050 len = tdd_generate(p->tdd, buf, text);
14051 if (len < 1) {
14052 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
14053 free(mybuf);
14054 return -1;
14055 }
14056 }
14057 memset(buf + len, 0x7f, END_SILENCE_LEN);
14058 len += END_SILENCE_LEN;
14059 fd = p->subs[index].dfd;
14060 while (len) {
14061 if (ast_check_hangup(c)) {
14062 free(mybuf);
14063 return -1;
14064 }
14065 size = len;
14066 if (size > READ_SIZE)
14067 size = READ_SIZE;
14068 fds[0].fd = fd;
14069 fds[0].events = POLLOUT | POLLPRI;
14070 fds[0].revents = 0;
14071 res = poll(fds, 1, -1);
14072 if (!res) {
14073 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
14074 continue;
14075 }
14076
14077 if (fds[0].revents & POLLPRI) {
14078 ast_free(mybuf);
14079 return -1;
14080 }
14081 if (!(fds[0].revents & POLLOUT)) {
14082 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
14083 continue;
14084 }
14085 res = write(fd, buf, size);
14086 if (res != size) {
14087 if (res == -1) {
14088 free(mybuf);
14089 return -1;
14090 }
14091 if (option_debug)
14092 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14093 break;
14094 }
14095 len -= size;
14096 buf += size;
14097 }
14098 free(mybuf);
14099 return(0);
14100 }
14101
14102
14103 static int reload(void)
14104 {
14105 int res = 0;
14106
14107 res = setup_dahdi(1);
14108 if (res) {
14109 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14110 return -1;
14111 }
14112 return 0;
14113 }
14114
14115
14116
14117
14118
14119 #ifdef HAVE_PRI
14120 #define tdesc "DAHDI Telephony w/PRI"
14121 #else
14122 #define tdesc "DAHDI Telephony"
14123 #endif
14124
14125 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
14126 .load = load_module,
14127 .unload = unload_module,
14128 .reload = reload,
14129 );
14130
14131