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
00050 #include "asterisk.h"
00051
00052 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 417956 $")
00053
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068
00069
00070
00071
00072
00073
00074 #if defined(HAVE_PRI)
00075 #include "sig_pri.h"
00076 #ifndef PRI_RESTART
00077 #error "Upgrade your libpri"
00078 #endif
00079 #endif
00080
00081 #if defined(HAVE_SS7)
00082 #include "sig_ss7.h"
00083 #if defined(LIBSS7_ABI_COMPATIBILITY)
00084 #error "Your installed libss7 is not compatible"
00085 #endif
00086 #endif
00087
00088 #ifdef HAVE_OPENR2
00089
00090 #define SIG_MFCR2_MAX_CHANNELS 672
00091 #include <openr2.h>
00092 #endif
00093
00094 #include "asterisk/lock.h"
00095 #include "asterisk/channel.h"
00096 #include "asterisk/config.h"
00097 #include "asterisk/module.h"
00098 #include "asterisk/pbx.h"
00099 #include "asterisk/file.h"
00100 #include "asterisk/ulaw.h"
00101 #include "asterisk/alaw.h"
00102 #include "asterisk/callerid.h"
00103 #include "asterisk/adsi.h"
00104 #include "asterisk/cli.h"
00105 #include "asterisk/cdr.h"
00106 #include "asterisk/cel.h"
00107 #include "asterisk/features.h"
00108 #include "asterisk/musiconhold.h"
00109 #include "asterisk/say.h"
00110 #include "asterisk/tdd.h"
00111 #include "asterisk/app.h"
00112 #include "asterisk/dsp.h"
00113 #include "asterisk/astdb.h"
00114 #include "asterisk/manager.h"
00115 #include "asterisk/causes.h"
00116 #include "asterisk/term.h"
00117 #include "asterisk/utils.h"
00118 #include "asterisk/transcap.h"
00119 #include "asterisk/stringfields.h"
00120 #include "asterisk/abstract_jb.h"
00121 #include "asterisk/smdi.h"
00122 #include "asterisk/astobj.h"
00123 #include "asterisk/event.h"
00124 #include "asterisk/devicestate.h"
00125 #include "asterisk/paths.h"
00126 #include "asterisk/ccss.h"
00127 #include "asterisk/data.h"
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 #define SMDI_MD_WAIT_TIMEOUT 1500
00282
00283 static const char * const lbostr[] = {
00284 "0 db (CSU)/0-133 feet (DSX-1)",
00285 "133-266 feet (DSX-1)",
00286 "266-399 feet (DSX-1)",
00287 "399-533 feet (DSX-1)",
00288 "533-655 feet (DSX-1)",
00289 "-7.5db (CSU)",
00290 "-15db (CSU)",
00291 "-22.5db (CSU)"
00292 };
00293
00294
00295
00296 static struct ast_jb_conf default_jbconf =
00297 {
00298 .flags = 0,
00299 .max_size = 200,
00300 .resync_threshold = 1000,
00301 .impl = "fixed",
00302 .target_extra = 40,
00303 };
00304 static struct ast_jb_conf global_jbconf;
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 #define DEFAULT_CIDRINGS 1
00319
00320 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00321
00322
00323
00324 #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))
00325
00326 static const char tdesc[] = "DAHDI Telephony Driver"
00327 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00328 " w/"
00329 #if defined(HAVE_PRI)
00330 "PRI"
00331 #endif
00332 #if defined(HAVE_SS7)
00333 #if defined(HAVE_PRI)
00334 " & "
00335 #endif
00336 "SS7"
00337 #endif
00338 #if defined(HAVE_OPENR2)
00339 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00340 " & "
00341 #endif
00342 "MFC/R2"
00343 #endif
00344 #endif
00345 ;
00346
00347 static const char config[] = "chan_dahdi.conf";
00348
00349 #define SIG_EM DAHDI_SIG_EM
00350 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00351 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00352 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00353 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00354 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00355 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00356 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00357 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00358 #define SIG_FXSLS DAHDI_SIG_FXSLS
00359 #define SIG_FXSGS DAHDI_SIG_FXSGS
00360 #define SIG_FXSKS DAHDI_SIG_FXSKS
00361 #define SIG_FXOLS DAHDI_SIG_FXOLS
00362 #define SIG_FXOGS DAHDI_SIG_FXOGS
00363 #define SIG_FXOKS DAHDI_SIG_FXOKS
00364 #define SIG_PRI DAHDI_SIG_CLEAR
00365 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00366 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00367 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00368 #define SIG_MFCR2 DAHDI_SIG_CAS
00369 #define SIG_SF DAHDI_SIG_SF
00370 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00371 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00372 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00373 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00374 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00375
00376 #ifdef LOTS_OF_SPANS
00377 #define NUM_SPANS DAHDI_MAX_SPANS
00378 #else
00379 #define NUM_SPANS 32
00380 #endif
00381
00382 #define CHAN_PSEUDO -2
00383
00384 #define CALLPROGRESS_PROGRESS 1
00385 #define CALLPROGRESS_FAX_OUTGOING 2
00386 #define CALLPROGRESS_FAX_INCOMING 4
00387 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00388
00389 #define NUM_CADENCE_MAX 25
00390 static int num_cadence = 4;
00391 static int user_has_defined_cadences = 0;
00392
00393 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00394 { { 125, 125, 2000, 4000 } },
00395 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00396 { { 125, 125, 125, 125, 125, 4000 } },
00397 { { 1000, 500, 2500, 5000 } },
00398 };
00399
00400
00401
00402
00403
00404 static int cidrings[NUM_CADENCE_MAX] = {
00405 2,
00406 4,
00407 3,
00408 2,
00409 };
00410
00411
00412 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00413
00414 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00415 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00416
00417 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00418 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00419
00420 static char defaultcic[64] = "";
00421 static char defaultozz[64] = "";
00422
00423
00424 static char mwimonitornotify[PATH_MAX] = "";
00425 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00426 static int mwisend_rpas = 0;
00427 #endif
00428
00429 static char progzone[10] = "";
00430
00431 static int usedistinctiveringdetection = 0;
00432 static int distinctiveringaftercid = 0;
00433
00434 static int numbufs = 4;
00435
00436 static int mwilevel = 512;
00437 static int dtmfcid_level = 256;
00438
00439 #define REPORT_CHANNEL_ALARMS 1
00440 #define REPORT_SPAN_ALARMS 2
00441 static int report_alarms = REPORT_CHANNEL_ALARMS;
00442
00443 #ifdef HAVE_PRI
00444 static int pridebugfd = -1;
00445 static char pridebugfilename[1024] = "";
00446 #endif
00447
00448
00449 static int firstdigittimeout = 16000;
00450
00451
00452 static int gendigittimeout = 8000;
00453
00454
00455 static int matchdigittimeout = 3000;
00456
00457
00458 AST_MUTEX_DEFINE_STATIC(iflock);
00459
00460
00461 static int ifcount = 0;
00462
00463 #ifdef HAVE_PRI
00464 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00465 #endif
00466
00467
00468
00469 AST_MUTEX_DEFINE_STATIC(monlock);
00470
00471
00472
00473 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00474 static ast_cond_t ss_thread_complete;
00475 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00476 AST_MUTEX_DEFINE_STATIC(restart_lock);
00477 static int ss_thread_count = 0;
00478 static int num_restart_pending = 0;
00479
00480 static int restart_monitor(void);
00481
00482 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);
00483
00484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00485
00486 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00487 {
00488
00489
00490
00491
00492 }
00493
00494
00495 static inline int dahdi_get_event(int fd)
00496 {
00497 int j;
00498 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00499 return -1;
00500 return j;
00501 }
00502
00503
00504 static inline int dahdi_wait_event(int fd)
00505 {
00506 int i, j = 0;
00507 i = DAHDI_IOMUX_SIGEVENT;
00508 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00509 return -1;
00510 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00511 return -1;
00512 return j;
00513 }
00514
00515
00516 #define READ_SIZE 160
00517
00518 #define MASK_AVAIL (1 << 0)
00519 #define MASK_INUSE (1 << 1)
00520
00521 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00522 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00523 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00524 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00525 #define MIN_MS_SINCE_FLASH ((2000) )
00526 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00527
00528 struct dahdi_pvt;
00529
00530
00531
00532
00533
00534 static int ringt_base = DEFAULT_RINGT;
00535
00536 #if defined(HAVE_SS7)
00537
00538 struct dahdi_ss7 {
00539 struct sig_ss7_linkset ss7;
00540 };
00541
00542 static struct dahdi_ss7 linksets[NUM_SPANS];
00543
00544 static int cur_ss7type = -1;
00545 static int cur_linkset = -1;
00546 static int cur_pointcode = -1;
00547 static int cur_cicbeginswith = -1;
00548 static int cur_adjpointcode = -1;
00549 static int cur_networkindicator = -1;
00550 static int cur_defaultdpc = -1;
00551 #endif
00552
00553 #ifdef HAVE_OPENR2
00554 struct dahdi_mfcr2_conf {
00555 openr2_variant_t variant;
00556 int mfback_timeout;
00557 int metering_pulse_timeout;
00558 int max_ani;
00559 int max_dnis;
00560 signed int get_ani_first:2;
00561 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00562 signed int skip_category_request:2;
00563 #endif
00564 unsigned int call_files:1;
00565 unsigned int allow_collect_calls:1;
00566 unsigned int charge_calls:1;
00567 unsigned int accept_on_offer:1;
00568 unsigned int forced_release:1;
00569 unsigned int double_answer:1;
00570 signed int immediate_accept:2;
00571 char logdir[OR2_MAX_PATH];
00572 char r2proto_file[OR2_MAX_PATH];
00573 openr2_log_level_t loglevel;
00574 openr2_calling_party_category_t category;
00575 };
00576
00577
00578 struct dahdi_mfcr2 {
00579 pthread_t r2master;
00580 openr2_context_t *protocol_context;
00581 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00582 int numchans;
00583 struct dahdi_mfcr2_conf conf;
00584 };
00585
00586
00587 static struct dahdi_mfcr2 **r2links;
00588
00589 static int r2links_count = 0;
00590
00591 #endif
00592
00593 #ifdef HAVE_PRI
00594
00595 struct dahdi_pri {
00596 int dchannels[SIG_PRI_NUM_DCHANS];
00597 int mastertrunkgroup;
00598 int prilogicalspan;
00599 struct sig_pri_span pri;
00600 };
00601
00602 static struct dahdi_pri pris[NUM_SPANS];
00603
00604 #if defined(HAVE_PRI_CCSS)
00605
00606 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00607 #endif
00608
00609 #else
00610
00611 struct dahdi_pri;
00612 #endif
00613
00614 #define SUB_REAL 0
00615 #define SUB_CALLWAIT 1
00616 #define SUB_THREEWAY 2
00617
00618
00619 #define POLARITY_IDLE 0
00620 #define POLARITY_REV 1
00621
00622
00623 struct distRingData {
00624 int ring[3];
00625 int range;
00626 };
00627 struct ringContextData {
00628 char contextData[AST_MAX_CONTEXT];
00629 };
00630 struct dahdi_distRings {
00631 struct distRingData ringnum[3];
00632 struct ringContextData ringContext[3];
00633 };
00634
00635 static const char * const subnames[] = {
00636 "Real",
00637 "Callwait",
00638 "Threeway"
00639 };
00640
00641 struct dahdi_subchannel {
00642 int dfd;
00643 struct ast_channel *owner;
00644 int chan;
00645 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00646 struct ast_frame f;
00647 unsigned int needringing:1;
00648 unsigned int needbusy:1;
00649 unsigned int needcongestion:1;
00650 unsigned int needanswer:1;
00651 unsigned int needflash:1;
00652 unsigned int needhold:1;
00653 unsigned int needunhold:1;
00654 unsigned int linear:1;
00655 unsigned int inthreeway:1;
00656 struct dahdi_confinfo curconf;
00657 };
00658
00659 #define CONF_USER_REAL (1 << 0)
00660 #define CONF_USER_THIRDCALL (1 << 1)
00661
00662 #define MAX_SLAVES 4
00663
00664
00665
00666
00667 typedef enum {
00668 MWI_SEND_NULL = 0,
00669 MWI_SEND_SA,
00670 MWI_SEND_SA_WAIT,
00671 MWI_SEND_PAUSE,
00672 MWI_SEND_SPILL,
00673 MWI_SEND_CLEANUP,
00674 MWI_SEND_DONE,
00675 } mwisend_states;
00676
00677 struct mwisend_info {
00678 struct timeval pause;
00679 mwisend_states mwisend_current;
00680 };
00681
00682
00683 enum DAHDI_IFLIST {
00684 DAHDI_IFLIST_NONE,
00685 DAHDI_IFLIST_MAIN,
00686 #if defined(HAVE_PRI)
00687 DAHDI_IFLIST_NO_B_CHAN,
00688 #endif
00689 };
00690
00691 struct dahdi_pvt {
00692 ast_mutex_t lock;
00693 struct callerid_state *cs;
00694 struct ast_channel *owner;
00695
00696
00697 struct dahdi_subchannel sub_unused;
00698 struct dahdi_subchannel subs[3];
00699 struct dahdi_confinfo saveconf;
00700
00701 struct dahdi_pvt *slaves[MAX_SLAVES];
00702 struct dahdi_pvt *master;
00703 int inconference;
00704
00705 int bufsize;
00706 int buf_no;
00707 int buf_policy;
00708 int faxbuf_no;
00709 int faxbuf_policy;
00710 int sig;
00711
00712
00713
00714
00715 int radio;
00716 int outsigmod;
00717 int oprmode;
00718 struct dahdi_pvt *oprpeer;
00719
00720 float cid_rxgain;
00721
00722 float rxgain;
00723
00724 float txgain;
00725
00726 float txdrc;
00727 float rxdrc;
00728
00729 int tonezone;
00730 enum DAHDI_IFLIST which_iflist;
00731 struct dahdi_pvt *next;
00732 struct dahdi_pvt *prev;
00733
00734
00735
00736
00737
00738
00739
00740 unsigned int adsi:1;
00741
00742
00743
00744
00745
00746 unsigned int answeronpolarityswitch:1;
00747
00748
00749
00750
00751
00752 unsigned int busydetect:1;
00753
00754
00755
00756
00757
00758 unsigned int callreturn:1;
00759
00760
00761
00762
00763
00764
00765 unsigned int callwaiting:1;
00766
00767
00768
00769
00770 unsigned int callwaitingcallerid:1;
00771
00772
00773
00774
00775
00776
00777 unsigned int cancallforward:1;
00778
00779
00780
00781
00782 unsigned int canpark:1;
00783
00784 unsigned int confirmanswer:1;
00785
00786
00787
00788
00789 unsigned int destroy:1;
00790 unsigned int didtdd:1;
00791
00792 unsigned int dialednone:1;
00793
00794
00795
00796
00797 unsigned int dialing:1;
00798
00799 unsigned int digital:1;
00800
00801 unsigned int dnd:1;
00802
00803 unsigned int echobreak:1;
00804
00805
00806
00807
00808
00809 unsigned int echocanbridged:1;
00810
00811 unsigned int echocanon:1;
00812
00813 unsigned int faxhandled:1;
00814
00815 unsigned int usefaxbuffers:1;
00816
00817 unsigned int bufferoverrideinuse:1;
00818
00819 unsigned int firstradio:1;
00820
00821
00822
00823
00824 unsigned int hanguponpolarityswitch:1;
00825
00826 unsigned int hardwaredtmf:1;
00827
00828
00829
00830
00831
00832
00833 unsigned int hidecallerid:1;
00834
00835
00836
00837
00838
00839 unsigned int hidecalleridname:1;
00840
00841 unsigned int ignoredtmf:1;
00842
00843
00844
00845
00846
00847 unsigned int immediate:1;
00848
00849 unsigned int inalarm:1;
00850
00851 unsigned int mate:1;
00852
00853 unsigned int outgoing:1;
00854
00855
00856
00857
00858
00859
00860 unsigned int permcallwaiting:1;
00861
00862
00863
00864
00865 unsigned int permhidecallerid:1;
00866
00867
00868
00869
00870 unsigned int priindication_oob:1;
00871
00872
00873
00874
00875 unsigned int priexclusive:1;
00876
00877
00878
00879
00880 unsigned int pulse:1;
00881
00882 unsigned int pulsedial:1;
00883 unsigned int restartpending:1;
00884
00885
00886
00887
00888
00889 unsigned int restrictcid:1;
00890
00891
00892
00893
00894 unsigned int threewaycalling:1;
00895
00896
00897
00898
00899
00900
00901
00902
00903 unsigned int transfer:1;
00904
00905
00906
00907
00908
00909
00910
00911 unsigned int use_callerid:1;
00912
00913
00914
00915
00916
00917
00918 unsigned int use_callingpres:1;
00919
00920
00921
00922
00923
00924 unsigned int usedistinctiveringdetection:1;
00925
00926
00927
00928
00929 unsigned int dahditrcallerid:1;
00930
00931
00932
00933
00934 unsigned int transfertobusy:1;
00935
00936
00937
00938
00939 unsigned int mwimonitor_neon:1;
00940
00941
00942
00943
00944 unsigned int mwimonitor_fsk:1;
00945
00946
00947
00948
00949
00950 unsigned int mwimonitor_rpas:1;
00951
00952 unsigned int mwimonitoractive:1;
00953
00954 unsigned int mwisendactive:1;
00955
00956
00957
00958
00959 unsigned int inservice:1;
00960
00961
00962
00963
00964 unsigned int locallyblocked:1;
00965
00966
00967
00968
00969 unsigned int remotelyblocked:1;
00970
00971
00972
00973
00974 unsigned int manages_span_alarms:1;
00975
00976 #if defined(HAVE_PRI)
00977 struct sig_pri_span *pri;
00978 int logicalspan;
00979 #endif
00980
00981
00982
00983
00984 unsigned int use_smdi:1;
00985 struct mwisend_info mwisend_data;
00986
00987 struct ast_smdi_interface *smdi_iface;
00988
00989
00990 struct dahdi_distRings drings;
00991
00992
00993
00994
00995
00996 char context[AST_MAX_CONTEXT];
00997
00998
00999
01000 char defcontext[AST_MAX_CONTEXT];
01001
01002 char exten[AST_MAX_EXTENSION];
01003
01004
01005
01006
01007 char language[MAX_LANGUAGE];
01008
01009
01010
01011
01012 char mohinterpret[MAX_MUSICCLASS];
01013
01014
01015
01016
01017 char mohsuggest[MAX_MUSICCLASS];
01018 char parkinglot[AST_MAX_EXTENSION];
01019 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01020
01021 char cid_ani[AST_MAX_EXTENSION];
01022 #endif
01023
01024 int cid_ani2;
01025
01026 char cid_num[AST_MAX_EXTENSION];
01027
01028
01029
01030
01031 char cid_tag[AST_MAX_EXTENSION];
01032
01033 int cid_ton;
01034
01035 char cid_name[AST_MAX_EXTENSION];
01036
01037 char cid_subaddr[AST_MAX_EXTENSION];
01038 char *origcid_num;
01039 char *origcid_name;
01040
01041 char callwait_num[AST_MAX_EXTENSION];
01042
01043 char callwait_name[AST_MAX_EXTENSION];
01044
01045 char rdnis[AST_MAX_EXTENSION];
01046
01047 char dnid[AST_MAX_EXTENSION];
01048
01049
01050
01051
01052 ast_group_t group;
01053
01054 int law_default;
01055
01056 int law;
01057 int confno;
01058 int confusers;
01059 int propconfno;
01060
01061
01062
01063
01064 ast_group_t callgroup;
01065
01066
01067
01068
01069 ast_group_t pickupgroup;
01070
01071
01072
01073
01074 struct ast_variable *vars;
01075 int channel;
01076 int span;
01077 time_t guardtime;
01078 int cid_signalling;
01079 int cid_start;
01080 int dtmfcid_holdoff_state;
01081 struct timeval dtmfcid_delay;
01082 int callingpres;
01083 int callwaitingrepeat;
01084 int cidcwexpire;
01085 int cid_suppress_expire;
01086
01087 unsigned char *cidspill;
01088
01089 int cidpos;
01090
01091 int cidlen;
01092
01093 int ringt;
01094
01095
01096
01097
01098 int ringt_base;
01099
01100
01101
01102
01103
01104
01105 int stripmsd;
01106
01107
01108
01109
01110
01111
01112 int callwaitcas;
01113
01114 int callwaitrings;
01115
01116 struct {
01117 struct dahdi_echocanparams head;
01118 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01119 } echocancel;
01120
01121
01122
01123
01124 int echotraining;
01125
01126 char echorest[20];
01127
01128
01129
01130
01131 int busycount;
01132
01133
01134
01135
01136 int busycompare;
01137
01138
01139
01140
01141 int busytonelength;
01142
01143
01144
01145
01146 int busyquietlength;
01147
01148
01149
01150
01151 int busyfuzziness;
01152
01153
01154
01155
01156 int silencethreshold;
01157
01158
01159
01160
01161 int callprogress;
01162
01163
01164
01165
01166 int waitfordialtone;
01167 struct timeval waitingfordt;
01168 struct timeval flashtime;
01169
01170 struct ast_dsp *dsp;
01171
01172 struct dahdi_dialoperation dop;
01173 int whichwink;
01174
01175 char finaldial[64];
01176 char accountcode[AST_MAX_ACCOUNT_CODE];
01177 int amaflags;
01178 struct tdd_state *tdd;
01179
01180 char call_forward[AST_MAX_EXTENSION];
01181
01182
01183
01184
01185 char mailbox[AST_MAX_EXTENSION];
01186
01187 struct ast_event_sub *mwi_event_sub;
01188
01189 char dialdest[256];
01190 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01191 struct dahdi_vmwi_info mwisend_setting;
01192 unsigned int mwisend_fsk: 1;
01193 unsigned int mwisend_rpas:1;
01194 #endif
01195 int distinctivering;
01196 int dtmfrelax;
01197
01198 int fake_event;
01199
01200
01201
01202
01203 int polarityonanswerdelay;
01204
01205 struct timeval polaritydelaytv;
01206
01207
01208
01209
01210 int sendcalleridafter;
01211
01212 int polarity;
01213
01214 int dsp_features;
01215 #if defined(HAVE_SS7)
01216
01217 struct sig_ss7_linkset *ss7;
01218 #endif
01219 #ifdef HAVE_OPENR2
01220 struct dahdi_mfcr2 *mfcr2;
01221 openr2_chan_t *r2chan;
01222 openr2_calling_party_category_t mfcr2_recvd_category;
01223 openr2_calling_party_category_t mfcr2_category;
01224 int mfcr2_dnis_index;
01225 int mfcr2_ani_index;
01226 int mfcr2call:1;
01227 int mfcr2_answer_pending:1;
01228 int mfcr2_charge_calls:1;
01229 int mfcr2_allow_collect_calls:1;
01230 int mfcr2_forced_release:1;
01231 int mfcr2_dnis_matched:1;
01232 int mfcr2_call_accepted:1;
01233 int mfcr2_progress:1;
01234 int mfcr2_accept_on_offer:1;
01235 #endif
01236
01237 char begindigit;
01238
01239 int muting;
01240 void *sig_pvt;
01241 struct ast_cc_config_params *cc_params;
01242
01243
01244
01245
01246
01247
01248 char dialstring[AST_CHANNEL_NAME];
01249 };
01250
01251 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01252 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01253 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01254 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01255 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01256 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01257 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01287 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01288 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01289 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01291 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01292 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01293 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01294 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01295 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01296 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01297 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01298 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01299 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01300 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01301 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01302 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01303 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01304 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01305 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01306 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01307 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01308 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01309 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01310 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01311 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01312 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01313 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01314 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01315 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01316 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01317 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01318 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01319
01320 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01321
01322 static struct dahdi_pvt *iflist = NULL;
01323 static struct dahdi_pvt *ifend = NULL;
01324
01325 #if defined(HAVE_PRI)
01326 static struct dahdi_parms_pseudo {
01327 int buf_no;
01328 int buf_policy;
01329 int faxbuf_no;
01330 int faxbuf_policy;
01331 } dahdi_pseudo_parms;
01332 #endif
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344 struct dahdi_chan_conf {
01345 struct dahdi_pvt chan;
01346 #ifdef HAVE_PRI
01347 struct dahdi_pri pri;
01348 #endif
01349
01350 #if defined(HAVE_SS7)
01351 struct dahdi_ss7 ss7;
01352 #endif
01353
01354 #ifdef HAVE_OPENR2
01355 struct dahdi_mfcr2_conf mfcr2;
01356 #endif
01357 struct dahdi_params timing;
01358 int is_sig_auto;
01359
01360 int ignore_failed_channels;
01361
01362
01363
01364
01365
01366 char smdi_port[SMDI_MAX_FILENAME_LEN];
01367 };
01368
01369
01370 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01371 {
01372
01373
01374
01375 struct dahdi_chan_conf conf = {
01376 #ifdef HAVE_PRI
01377 .pri.pri = {
01378 .nsf = PRI_NSF_NONE,
01379 .switchtype = PRI_SWITCH_NI2,
01380 .dialplan = PRI_UNKNOWN + 1,
01381 .localdialplan = PRI_NATIONAL_ISDN + 1,
01382 .nodetype = PRI_CPE,
01383 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01384 .inband_on_setup_ack = 1,
01385 .inband_on_proceeding = 1,
01386
01387 #if defined(HAVE_PRI_CCSS)
01388 .cc_ptmp_recall_mode = 1,
01389 .cc_qsig_signaling_link_req = 1,
01390 .cc_qsig_signaling_link_rsp = 1,
01391 #endif
01392
01393 .minunused = 2,
01394 .idleext = "",
01395 .idledial = "",
01396 .internationalprefix = "",
01397 .nationalprefix = "",
01398 .localprefix = "",
01399 .privateprefix = "",
01400 .unknownprefix = "",
01401 .resetinterval = -1,
01402 },
01403 #endif
01404 #if defined(HAVE_SS7)
01405 .ss7.ss7 = {
01406 .called_nai = SS7_NAI_NATIONAL,
01407 .calling_nai = SS7_NAI_NATIONAL,
01408 .internationalprefix = "",
01409 .nationalprefix = "",
01410 .subscriberprefix = "",
01411 .unknownprefix = ""
01412 },
01413 #endif
01414 #ifdef HAVE_OPENR2
01415 .mfcr2 = {
01416 .variant = OR2_VAR_ITU,
01417 .mfback_timeout = -1,
01418 .metering_pulse_timeout = -1,
01419 .max_ani = 10,
01420 .max_dnis = 4,
01421 .get_ani_first = -1,
01422 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01423 .skip_category_request = -1,
01424 #endif
01425 .call_files = 0,
01426 .allow_collect_calls = 0,
01427 .charge_calls = 1,
01428 .accept_on_offer = 1,
01429 .forced_release = 0,
01430 .double_answer = 0,
01431 .immediate_accept = -1,
01432 .logdir = "",
01433 .r2proto_file = "",
01434 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01435 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01436 },
01437 #endif
01438 .chan = {
01439 .context = "default",
01440 .cid_num = "",
01441 .cid_name = "",
01442 .cid_tag = "",
01443 .mohinterpret = "default",
01444 .mohsuggest = "",
01445 .parkinglot = "",
01446 .transfertobusy = 1,
01447
01448 .cid_signalling = CID_SIG_BELL,
01449 .cid_start = CID_START_RING,
01450 .dahditrcallerid = 0,
01451 .use_callerid = 1,
01452 .sig = -1,
01453 .outsigmod = -1,
01454
01455 .cid_rxgain = +5.0,
01456
01457 .tonezone = -1,
01458
01459 .echocancel.head.tap_length = 1,
01460
01461 .busycount = 3,
01462 .busycompare = 0,
01463 .busytonelength = 0,
01464 .busyquietlength = 0,
01465 .busyfuzziness = 0,
01466 .silencethreshold = 0,
01467
01468 .accountcode = "",
01469
01470 .mailbox = "",
01471
01472 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01473 .mwisend_fsk = 1,
01474 #endif
01475 .polarityonanswerdelay = 600,
01476
01477 .sendcalleridafter = DEFAULT_CIDRINGS,
01478
01479 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01480 .buf_no = numbufs,
01481 .usefaxbuffers = 0,
01482 .cc_params = ast_cc_config_params_init(),
01483 },
01484 .timing = {
01485 .prewinktime = -1,
01486 .preflashtime = -1,
01487 .winktime = -1,
01488 .flashtime = -1,
01489 .starttime = -1,
01490 .rxwinktime = -1,
01491 .rxflashtime = -1,
01492 .debouncetime = -1
01493 },
01494 .is_sig_auto = 1,
01495 .smdi_port = "/dev/ttyS0",
01496 };
01497
01498 return conf;
01499 }
01500
01501
01502 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01503 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01504 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01505 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01506 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01507 static int dahdi_hangup(struct ast_channel *ast);
01508 static int dahdi_answer(struct ast_channel *ast);
01509 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01510 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01511 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01512 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01513 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01514 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01515 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01516 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01517 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01518 static int dahdi_devicestate(void *data);
01519 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01520
01521 static const struct ast_channel_tech dahdi_tech = {
01522 .type = "DAHDI",
01523 .description = tdesc,
01524 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01525 .requester = dahdi_request,
01526 .send_digit_begin = dahdi_digit_begin,
01527 .send_digit_end = dahdi_digit_end,
01528 .send_text = dahdi_sendtext,
01529 .call = dahdi_call,
01530 .hangup = dahdi_hangup,
01531 .answer = dahdi_answer,
01532 .read = dahdi_read,
01533 .write = dahdi_write,
01534 .bridge = dahdi_bridge,
01535 .exception = dahdi_exception,
01536 .indicate = dahdi_indicate,
01537 .fixup = dahdi_fixup,
01538 .setoption = dahdi_setoption,
01539 .queryoption = dahdi_queryoption,
01540 .func_channel_read = dahdi_func_read,
01541 .func_channel_write = dahdi_func_write,
01542 .devicestate = dahdi_devicestate,
01543 .cc_callback = dahdi_cc_callback,
01544 };
01545
01546 #define GET_CHANNEL(p) ((p)->channel)
01547
01548 #define SIG_PRI_LIB_HANDLE_CASES \
01549 SIG_PRI: \
01550 case SIG_BRI: \
01551 case SIG_BRI_PTMP
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 static inline int dahdi_sig_pri_lib_handles(int signaling)
01563 {
01564 int handles;
01565
01566 switch (signaling) {
01567 case SIG_PRI_LIB_HANDLE_CASES:
01568 handles = 1;
01569 break;
01570 default:
01571 handles = 0;
01572 break;
01573 }
01574
01575 return handles;
01576 }
01577
01578 static int analog_lib_handles(int signalling, int radio, int oprmode)
01579 {
01580 switch (signalling) {
01581 case SIG_FXOLS:
01582 case SIG_FXOGS:
01583 case SIG_FXOKS:
01584 case SIG_FXSLS:
01585 case SIG_FXSGS:
01586 case SIG_FXSKS:
01587 case SIG_EMWINK:
01588 case SIG_EM:
01589 case SIG_EM_E1:
01590 case SIG_FEATD:
01591 case SIG_FEATDMF:
01592 case SIG_E911:
01593 case SIG_FGC_CAMA:
01594 case SIG_FGC_CAMAMF:
01595 case SIG_FEATB:
01596 case SIG_SFWINK:
01597 case SIG_SF:
01598 case SIG_SF_FEATD:
01599 case SIG_SF_FEATDMF:
01600 case SIG_FEATDMF_TA:
01601 case SIG_SF_FEATB:
01602 break;
01603 default:
01604
01605 return 0;
01606 }
01607
01608 if (radio) {
01609 return 0;
01610 }
01611
01612 if (oprmode) {
01613 return 0;
01614 }
01615
01616 return 1;
01617 }
01618
01619 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01620 {
01621 switch (sig) {
01622 case SIG_FXOLS:
01623 return ANALOG_SIG_FXOLS;
01624 case SIG_FXOGS:
01625 return ANALOG_SIG_FXOGS;
01626 case SIG_FXOKS:
01627 return ANALOG_SIG_FXOKS;
01628 case SIG_FXSLS:
01629 return ANALOG_SIG_FXSLS;
01630 case SIG_FXSGS:
01631 return ANALOG_SIG_FXSGS;
01632 case SIG_FXSKS:
01633 return ANALOG_SIG_FXSKS;
01634 case SIG_EMWINK:
01635 return ANALOG_SIG_EMWINK;
01636 case SIG_EM:
01637 return ANALOG_SIG_EM;
01638 case SIG_EM_E1:
01639 return ANALOG_SIG_EM_E1;
01640 case SIG_FEATD:
01641 return ANALOG_SIG_FEATD;
01642 case SIG_FEATDMF:
01643 return ANALOG_SIG_FEATDMF;
01644 case SIG_E911:
01645 return SIG_E911;
01646 case SIG_FGC_CAMA:
01647 return ANALOG_SIG_FGC_CAMA;
01648 case SIG_FGC_CAMAMF:
01649 return ANALOG_SIG_FGC_CAMAMF;
01650 case SIG_FEATB:
01651 return ANALOG_SIG_FEATB;
01652 case SIG_SFWINK:
01653 return ANALOG_SIG_SFWINK;
01654 case SIG_SF:
01655 return ANALOG_SIG_SF;
01656 case SIG_SF_FEATD:
01657 return ANALOG_SIG_SF_FEATD;
01658 case SIG_SF_FEATDMF:
01659 return ANALOG_SIG_SF_FEATDMF;
01660 case SIG_FEATDMF_TA:
01661 return ANALOG_SIG_FEATDMF_TA;
01662 case SIG_SF_FEATB:
01663 return ANALOG_SIG_FEATB;
01664 default:
01665 return -1;
01666 }
01667 }
01668
01669
01670 static int analog_tone_to_dahditone(enum analog_tone tone)
01671 {
01672 switch (tone) {
01673 case ANALOG_TONE_RINGTONE:
01674 return DAHDI_TONE_RINGTONE;
01675 case ANALOG_TONE_STUTTER:
01676 return DAHDI_TONE_STUTTER;
01677 case ANALOG_TONE_CONGESTION:
01678 return DAHDI_TONE_CONGESTION;
01679 case ANALOG_TONE_DIALTONE:
01680 return DAHDI_TONE_DIALTONE;
01681 case ANALOG_TONE_DIALRECALL:
01682 return DAHDI_TONE_DIALRECALL;
01683 case ANALOG_TONE_INFO:
01684 return DAHDI_TONE_INFO;
01685 default:
01686 return -1;
01687 }
01688 }
01689
01690 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01691 {
01692 int index;
01693
01694 switch (analogsub) {
01695 case ANALOG_SUB_REAL:
01696 index = SUB_REAL;
01697 break;
01698 case ANALOG_SUB_CALLWAIT:
01699 index = SUB_CALLWAIT;
01700 break;
01701 case ANALOG_SUB_THREEWAY:
01702 index = SUB_THREEWAY;
01703 break;
01704 default:
01705 ast_log(LOG_ERROR, "Unidentified sub!\n");
01706 index = SUB_REAL;
01707 }
01708
01709 return index;
01710 }
01711
01712 static enum analog_event dahdievent_to_analogevent(int event);
01713 static int bump_gains(struct dahdi_pvt *p);
01714 static int dahdi_setlinear(int dfd, int linear);
01715
01716 static int my_start_cid_detect(void *pvt, int cid_signalling)
01717 {
01718 struct dahdi_pvt *p = pvt;
01719 int index = SUB_REAL;
01720 p->cs = callerid_new(cid_signalling);
01721 if (!p->cs) {
01722 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01723 return -1;
01724 }
01725 bump_gains(p);
01726 dahdi_setlinear(p->subs[index].dfd, 0);
01727
01728 return 0;
01729 }
01730
01731 static int my_stop_cid_detect(void *pvt)
01732 {
01733 struct dahdi_pvt *p = pvt;
01734 int index = SUB_REAL;
01735 if (p->cs)
01736 callerid_free(p->cs);
01737 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01738 return 0;
01739 }
01740
01741 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01742 {
01743 struct dahdi_pvt *p = pvt;
01744 struct analog_pvt *analog_p = p->sig_pvt;
01745 struct pollfd poller;
01746 char *name, *num;
01747 int index = SUB_REAL;
01748 int res;
01749 unsigned char buf[256];
01750 int flags;
01751
01752 poller.fd = p->subs[SUB_REAL].dfd;
01753 poller.events = POLLPRI | POLLIN;
01754 poller.revents = 0;
01755
01756 res = poll(&poller, 1, timeout);
01757
01758 if (poller.revents & POLLPRI) {
01759 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01760 return 1;
01761 }
01762
01763 if (poller.revents & POLLIN) {
01764
01765
01766
01767
01768
01769 res = read(p->subs[index].dfd, buf, sizeof(buf));
01770 if (res < 0) {
01771 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01772 return -1;
01773 }
01774
01775 if (analog_p->ringt > 0) {
01776 if (!(--analog_p->ringt)) {
01777
01778 return -1;
01779 }
01780 }
01781
01782 if (p->cid_signalling == CID_SIG_V23_JP) {
01783 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01784 } else {
01785 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01786 }
01787 if (res < 0) {
01788
01789
01790
01791
01792 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01793 return -1;
01794 }
01795
01796 if (res == 1) {
01797 callerid_get(p->cs, &name, &num, &flags);
01798 if (name)
01799 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01800 if (num)
01801 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01802
01803 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01804 return 0;
01805 }
01806 }
01807
01808 *ev = ANALOG_EVENT_NONE;
01809 return 2;
01810 }
01811
01812 static const char *event2str(int event);
01813 static int restore_gains(struct dahdi_pvt *p);
01814
01815 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01816 {
01817 unsigned char buf[256];
01818 int distMatches;
01819 int curRingData[RING_PATTERNS];
01820 int receivedRingT;
01821 int counter1;
01822 int counter;
01823 int i;
01824 int res;
01825 int checkaftercid = 0;
01826
01827 struct dahdi_pvt *p = pvt;
01828 struct analog_pvt *analog_p = p->sig_pvt;
01829
01830 if (ringdata == NULL) {
01831 ringdata = curRingData;
01832 } else {
01833 checkaftercid = 1;
01834 }
01835
01836
01837
01838 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01839
01840 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01841 ringdata[receivedRingT] = 0;
01842 receivedRingT = 0;
01843 if (checkaftercid && distinctiveringaftercid)
01844 ast_verb(3, "Detecting post-CID distinctive ring\n");
01845
01846 else if (strcmp(p->context,p->defcontext) != 0) {
01847 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01848 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01849 }
01850
01851 for (;;) {
01852 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01853 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01854 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01855 ast_hangup(chan);
01856 return 1;
01857 }
01858 if (i & DAHDI_IOMUX_SIGEVENT) {
01859 res = dahdi_get_event(p->subs[idx].dfd);
01860 if (res == DAHDI_EVENT_NOALARM) {
01861 p->inalarm = 0;
01862 analog_p->inalarm = 0;
01863 }
01864 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01865 res = 0;
01866
01867
01868 ringdata[receivedRingT] = analog_p->ringt;
01869
01870 if (analog_p->ringt < analog_p->ringt_base/2)
01871 break;
01872
01873
01874 if (++receivedRingT == RING_PATTERNS)
01875 break;
01876 } else if (i & DAHDI_IOMUX_READ) {
01877 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01878 if (res < 0) {
01879 if (errno != ELAST) {
01880 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01881 ast_hangup(chan);
01882 return 1;
01883 }
01884 break;
01885 }
01886 if (analog_p->ringt > 0) {
01887 if (!(--analog_p->ringt)) {
01888 res = -1;
01889 break;
01890 }
01891 }
01892 }
01893 }
01894 }
01895 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01896
01897 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01898 for (counter = 0; counter < 3; counter++) {
01899
01900 distMatches = 0;
01901
01902 ast_verb(3, "Checking %d,%d,%d\n",
01903 p->drings.ringnum[counter].ring[0],
01904 p->drings.ringnum[counter].ring[1],
01905 p->drings.ringnum[counter].ring[2]);
01906 for (counter1 = 0; counter1 < 3; counter1++) {
01907 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01908 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01909 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01910 ringdata[counter1]);
01911 distMatches++;
01912 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01913 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01914 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01915 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01916 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01917 distMatches++;
01918 }
01919 }
01920
01921 if (distMatches == 3) {
01922
01923 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01924 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01925 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01926 break;
01927 }
01928 }
01929 }
01930
01931 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01932 restore_gains(p);
01933
01934 return 0;
01935 }
01936
01937 static int my_stop_callwait(void *pvt)
01938 {
01939 struct dahdi_pvt *p = pvt;
01940 p->callwaitingrepeat = 0;
01941 p->cidcwexpire = 0;
01942 p->cid_suppress_expire = 0;
01943
01944 return 0;
01945 }
01946
01947 static int send_callerid(struct dahdi_pvt *p);
01948 static int save_conference(struct dahdi_pvt *p);
01949 static int restore_conference(struct dahdi_pvt *p);
01950
01951 static int my_callwait(void *pvt)
01952 {
01953 struct dahdi_pvt *p = pvt;
01954 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01955 if (p->cidspill) {
01956 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01957 ast_free(p->cidspill);
01958 }
01959
01960
01961
01962
01963
01964 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01965 return -1;
01966 save_conference(p);
01967
01968 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01969 if (!p->callwaitrings && p->callwaitingcallerid) {
01970 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01971 p->callwaitcas = 1;
01972 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01973 } else {
01974 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01975 p->callwaitcas = 0;
01976 p->cidlen = 2400 + READ_SIZE * 4;
01977 }
01978 p->cidpos = 0;
01979 send_callerid(p);
01980
01981 return 0;
01982 }
01983
01984 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01985 {
01986 struct dahdi_pvt *p = pvt;
01987
01988 ast_debug(2, "Starting cid spill\n");
01989
01990 if (p->cidspill) {
01991 ast_log(LOG_WARNING, "cidspill already exists??\n");
01992 ast_free(p->cidspill);
01993 }
01994
01995 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01996 if (cwcid == 0) {
01997 p->cidlen = ast_callerid_generate(p->cidspill,
01998 caller->id.name.str,
01999 caller->id.number.str,
02000 AST_LAW(p));
02001 } else {
02002 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
02003 caller->id.name.str, caller->id.number.str);
02004 p->callwaitcas = 0;
02005 p->cidcwexpire = 0;
02006 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02007 caller->id.name.str,
02008 caller->id.number.str,
02009 AST_LAW(p));
02010 p->cidlen += READ_SIZE * 4;
02011 }
02012 p->cidpos = 0;
02013 p->cid_suppress_expire = 0;
02014 send_callerid(p);
02015 }
02016 return 0;
02017 }
02018
02019 static int my_dsp_reset_and_flush_digits(void *pvt)
02020 {
02021 struct dahdi_pvt *p = pvt;
02022 if (p->dsp)
02023 ast_dsp_digitreset(p->dsp);
02024
02025 return 0;
02026 }
02027
02028 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02029 {
02030 struct dahdi_pvt *p = pvt;
02031
02032 if (p->channel == CHAN_PSEUDO)
02033 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02034
02035 if (mode == ANALOG_DIGITMODE_DTMF) {
02036
02037 if (p->hardwaredtmf) {
02038 if (p->dsp) {
02039 ast_dsp_free(p->dsp);
02040 p->dsp = NULL;
02041 }
02042 return 0;
02043 }
02044
02045 if (!p->dsp) {
02046 p->dsp = ast_dsp_new();
02047 if (!p->dsp) {
02048 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02049 return -1;
02050 }
02051 }
02052
02053 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02054 } else if (mode == ANALOG_DIGITMODE_MF) {
02055 if (!p->dsp) {
02056 p->dsp = ast_dsp_new();
02057 if (!p->dsp) {
02058 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02059 return -1;
02060 }
02061 }
02062 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02063 }
02064 return 0;
02065 }
02066
02067 static int dahdi_wink(struct dahdi_pvt *p, int index);
02068
02069 static int my_wink(void *pvt, enum analog_sub sub)
02070 {
02071 struct dahdi_pvt *p = pvt;
02072 int index = analogsub_to_dahdisub(sub);
02073 if (index != SUB_REAL) {
02074 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02075 }
02076 return dahdi_wink(p, index);
02077 }
02078
02079 static void wakeup_sub(struct dahdi_pvt *p, int a);
02080
02081 static int reset_conf(struct dahdi_pvt *p);
02082
02083 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02084
02085 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02086 {
02087 struct ast_frame *f = *dest;
02088 struct dahdi_pvt *p = pvt;
02089 int idx = analogsub_to_dahdisub(analog_index);
02090
02091 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02092 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02093 (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
02094
02095 if (f->subclass.integer == 'f') {
02096 if (f->frametype == AST_FRAME_DTMF_END) {
02097
02098 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02099
02100 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02101 struct dahdi_bufferinfo bi = {
02102 .txbufpolicy = p->faxbuf_policy,
02103 .bufsize = p->bufsize,
02104 .numbufs = p->faxbuf_no
02105 };
02106 int res;
02107
02108 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02109 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02110 } else {
02111 p->bufferoverrideinuse = 1;
02112 }
02113 }
02114 p->faxhandled = 1;
02115 if (p->dsp) {
02116 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02117 ast_dsp_set_features(p->dsp, p->dsp_features);
02118 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02119 }
02120 if (strcmp(ast->exten, "fax")) {
02121 const char *target_context = S_OR(ast->macrocontext, ast->context);
02122
02123
02124
02125
02126
02127 ast_mutex_unlock(&p->lock);
02128 ast_channel_unlock(ast);
02129 if (ast_exists_extension(ast, target_context, "fax", 1,
02130 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02131 ast_channel_lock(ast);
02132 ast_mutex_lock(&p->lock);
02133 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02134
02135 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02136 if (ast_async_goto(ast, target_context, "fax", 1))
02137 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02138 } else {
02139 ast_channel_lock(ast);
02140 ast_mutex_lock(&p->lock);
02141 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02142 }
02143 } else {
02144 ast_debug(1, "Already in a fax extension, not redirecting\n");
02145 }
02146 } else {
02147 ast_debug(1, "Fax already handled\n");
02148 }
02149 dahdi_confmute(p, 0);
02150 }
02151 p->subs[idx].f.frametype = AST_FRAME_NULL;
02152 p->subs[idx].f.subclass.integer = 0;
02153 *dest = &p->subs[idx].f;
02154 }
02155 }
02156
02157 static void my_lock_private(void *pvt)
02158 {
02159 struct dahdi_pvt *p = pvt;
02160 ast_mutex_lock(&p->lock);
02161 }
02162
02163 static void my_unlock_private(void *pvt)
02164 {
02165 struct dahdi_pvt *p = pvt;
02166 ast_mutex_unlock(&p->lock);
02167 }
02168
02169 static void my_deadlock_avoidance_private(void *pvt)
02170 {
02171 struct dahdi_pvt *p = pvt;
02172
02173 DEADLOCK_AVOIDANCE(&p->lock);
02174 }
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02187 {
02188 char ch_name[20];
02189
02190 if (p->channel < CHAN_PSEUDO) {
02191
02192 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02193 } else if (p->channel == CHAN_PSEUDO) {
02194
02195 strcpy(ch_name, "pseudo");
02196 } else {
02197
02198 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02199 }
02200 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02201 "Channel: %s\r\n"
02202 "Uniqueid: %s\r\n"
02203 "DAHDISpan: %d\r\n"
02204 "DAHDIChannel: %s\r\n",
02205 chan->name,
02206 chan->uniqueid,
02207 p->span,
02208 ch_name);
02209 }
02210
02211 #ifdef HAVE_PRI
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02223 {
02224 struct dahdi_pvt *p = pvt;
02225
02226 dahdi_ami_channel_event(p, chan);
02227 }
02228 #endif
02229
02230
02231
02232
02233 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02234 {
02235 struct dahdi_pvt *p = pvt;
02236 int oldval;
02237 int idx = analogsub_to_dahdisub(sub);
02238
02239 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02240 oldval = p->subs[idx].linear;
02241 p->subs[idx].linear = linear_mode ? 1 : 0;
02242 return oldval;
02243 }
02244
02245 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02246 {
02247 struct dahdi_pvt *p = pvt;
02248 int idx = analogsub_to_dahdisub(sub);
02249
02250 p->subs[idx].inthreeway = inthreeway;
02251 }
02252
02253 static int get_alarms(struct dahdi_pvt *p);
02254 static void handle_alarms(struct dahdi_pvt *p, int alms);
02255 static void my_get_and_handle_alarms(void *pvt)
02256 {
02257 int res;
02258 struct dahdi_pvt *p = pvt;
02259
02260 res = get_alarms(p);
02261 handle_alarms(p, res);
02262 }
02263
02264 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02265 {
02266 struct ast_channel *bridged = ast_bridged_channel(chan);
02267
02268 if (bridged && bridged->tech == &dahdi_tech) {
02269 struct dahdi_pvt *p = bridged->tech_pvt;
02270
02271 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02272 return p->sig_pvt;
02273 }
02274 }
02275 return NULL;
02276 }
02277
02278 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02279 {
02280 struct dahdi_pvt *p = pvt;
02281 int dahdi_sub = analogsub_to_dahdisub(sub);
02282 return p->subs[dahdi_sub].dfd;
02283 }
02284
02285 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02286 {
02287 struct dahdi_pvt *p = pvt;
02288
02289
02290 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02291 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02292 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02293 *cid_rings = cidrings[p->distinctivering - 1];
02294 } else {
02295 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02296 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02297 *cid_rings = p->sendcalleridafter;
02298 }
02299 }
02300
02301 static void my_set_alarm(void *pvt, int in_alarm)
02302 {
02303 struct dahdi_pvt *p = pvt;
02304
02305 p->inalarm = in_alarm;
02306 }
02307
02308 static void my_set_dialing(void *pvt, int is_dialing)
02309 {
02310 struct dahdi_pvt *p = pvt;
02311
02312 p->dialing = is_dialing;
02313 }
02314
02315 static void my_set_outgoing(void *pvt, int is_outgoing)
02316 {
02317 struct dahdi_pvt *p = pvt;
02318
02319 p->outgoing = is_outgoing;
02320 }
02321
02322 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02323 static void my_set_digital(void *pvt, int is_digital)
02324 {
02325 struct dahdi_pvt *p = pvt;
02326
02327 p->digital = is_digital;
02328 }
02329 #endif
02330
02331 #if defined(HAVE_SS7)
02332 static void my_set_inservice(void *pvt, int is_inservice)
02333 {
02334 struct dahdi_pvt *p = pvt;
02335
02336 p->inservice = is_inservice;
02337 }
02338 #endif
02339
02340 #if defined(HAVE_SS7)
02341 static void my_set_locallyblocked(void *pvt, int is_blocked)
02342 {
02343 struct dahdi_pvt *p = pvt;
02344
02345 p->locallyblocked = is_blocked;
02346 }
02347 #endif
02348
02349 #if defined(HAVE_SS7)
02350 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02351 {
02352 struct dahdi_pvt *p = pvt;
02353
02354 p->remotelyblocked = is_blocked;
02355 }
02356 #endif
02357
02358 static void my_set_ringtimeout(void *pvt, int ringt)
02359 {
02360 struct dahdi_pvt *p = pvt;
02361 p->ringt = ringt;
02362 }
02363
02364 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02365 {
02366 struct dahdi_pvt *p = pvt;
02367
02368 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02369 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02370 gettimeofday(&p->waitingfordt, NULL);
02371 ast_setstate(ast, AST_STATE_OFFHOOK);
02372 }
02373 }
02374
02375 static int my_check_waitingfordt(void *pvt)
02376 {
02377 struct dahdi_pvt *p = pvt;
02378
02379 if (p->waitingfordt.tv_sec) {
02380 return 1;
02381 }
02382
02383 return 0;
02384 }
02385
02386 static void my_set_confirmanswer(void *pvt, int flag)
02387 {
02388 struct dahdi_pvt *p = pvt;
02389 p->confirmanswer = flag;
02390 }
02391
02392 static int my_check_confirmanswer(void *pvt)
02393 {
02394 struct dahdi_pvt *p = pvt;
02395 if (p->confirmanswer) {
02396 return 1;
02397 }
02398
02399 return 0;
02400 }
02401
02402 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02403 {
02404 struct dahdi_pvt *p = pvt;
02405
02406 p->callwaiting = callwaiting_enable;
02407 }
02408
02409 static void my_cancel_cidspill(void *pvt)
02410 {
02411 struct dahdi_pvt *p = pvt;
02412
02413 ast_free(p->cidspill);
02414 p->cidspill = NULL;
02415 restore_conference(p);
02416 }
02417
02418 static int my_confmute(void *pvt, int mute)
02419 {
02420 struct dahdi_pvt *p = pvt;
02421 return dahdi_confmute(p, mute);
02422 }
02423
02424 static void my_set_pulsedial(void *pvt, int flag)
02425 {
02426 struct dahdi_pvt *p = pvt;
02427 p->pulsedial = flag;
02428 }
02429
02430 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02431 {
02432 struct dahdi_pvt *p = pvt;
02433
02434 p->owner = new_owner;
02435 }
02436
02437 static const char *my_get_orig_dialstring(void *pvt)
02438 {
02439 struct dahdi_pvt *p = pvt;
02440
02441 return p->dialstring;
02442 }
02443
02444 static void my_increase_ss_count(void)
02445 {
02446 ast_mutex_lock(&ss_thread_lock);
02447 ss_thread_count++;
02448 ast_mutex_unlock(&ss_thread_lock);
02449 }
02450
02451 static void my_decrease_ss_count(void)
02452 {
02453 ast_mutex_lock(&ss_thread_lock);
02454 ss_thread_count--;
02455 ast_cond_signal(&ss_thread_complete);
02456 ast_mutex_unlock(&ss_thread_lock);
02457 }
02458
02459 static void my_all_subchannels_hungup(void *pvt)
02460 {
02461 struct dahdi_pvt *p = pvt;
02462 int res, law;
02463
02464 p->faxhandled = 0;
02465 p->didtdd = 0;
02466
02467 if (p->dsp) {
02468 ast_dsp_free(p->dsp);
02469 p->dsp = NULL;
02470 }
02471
02472 p->law = p->law_default;
02473 law = p->law_default;
02474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02475 if (res < 0)
02476 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02477
02478 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02479
02480 #if 1
02481 {
02482 int i;
02483 p->owner = NULL;
02484
02485 for (i = 0; i < 3; i++) {
02486 p->subs[i].owner = NULL;
02487 }
02488 }
02489 #endif
02490
02491 reset_conf(p);
02492 if (num_restart_pending == 0) {
02493 restart_monitor();
02494 }
02495 }
02496
02497 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02498
02499 static int my_conf_del(void *pvt, enum analog_sub sub)
02500 {
02501 struct dahdi_pvt *p = pvt;
02502 int x = analogsub_to_dahdisub(sub);
02503
02504 return conf_del(p, &p->subs[x], x);
02505 }
02506
02507 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02508
02509 static int my_conf_add(void *pvt, enum analog_sub sub)
02510 {
02511 struct dahdi_pvt *p = pvt;
02512 int x = analogsub_to_dahdisub(sub);
02513
02514 return conf_add(p, &p->subs[x], x, 0);
02515 }
02516
02517 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02518
02519 static int my_complete_conference_update(void *pvt, int needconference)
02520 {
02521 struct dahdi_pvt *p = pvt;
02522 int needconf = needconference;
02523 int x;
02524 int useslavenative;
02525 struct dahdi_pvt *slave = NULL;
02526
02527 useslavenative = isslavenative(p, &slave);
02528
02529
02530
02531 for (x = 0; x < MAX_SLAVES; x++) {
02532 if (p->slaves[x]) {
02533 if (useslavenative)
02534 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02535 else {
02536 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02537 needconf++;
02538 }
02539 }
02540 }
02541
02542 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02543 if (useslavenative)
02544 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02545 else {
02546 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02547 needconf++;
02548 }
02549 }
02550
02551 if (p->master) {
02552 if (isslavenative(p->master, NULL)) {
02553 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02554 } else {
02555 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02556 }
02557 }
02558 if (!needconf) {
02559
02560
02561 p->confno = -1;
02562 }
02563
02564 return 0;
02565 }
02566
02567 static int check_for_conference(struct dahdi_pvt *p);
02568
02569 static int my_check_for_conference(void *pvt)
02570 {
02571 struct dahdi_pvt *p = pvt;
02572 return check_for_conference(p);
02573 }
02574
02575 static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
02576 {
02577 struct dahdi_pvt *p = pvt;
02578 int da, db;
02579 int tchan;
02580 int tinthreeway;
02581
02582 da = analogsub_to_dahdisub(a);
02583 db = analogsub_to_dahdisub(b);
02584
02585 tchan = p->subs[da].chan;
02586 p->subs[da].chan = p->subs[db].chan;
02587 p->subs[db].chan = tchan;
02588
02589 tinthreeway = p->subs[da].inthreeway;
02590 p->subs[da].inthreeway = p->subs[db].inthreeway;
02591 p->subs[db].inthreeway = tinthreeway;
02592
02593 p->subs[da].owner = ast_a;
02594 p->subs[db].owner = ast_b;
02595
02596 if (ast_a)
02597 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02598 if (ast_b)
02599 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02600
02601 wakeup_sub(p, a);
02602 wakeup_sub(p, b);
02603
02604 return;
02605 }
02606
02607 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02608
02609 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02610 {
02611 struct dahdi_pvt *p = pvt;
02612 int dsub = analogsub_to_dahdisub(sub);
02613
02614 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02615 }
02616
02617 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02618 static int dahdi_setlaw(int dfd, int law)
02619 {
02620 int res;
02621 res = ioctl(dfd, DAHDI_SETLAW, &law);
02622 if (res)
02623 return res;
02624 return 0;
02625 }
02626 #endif
02627
02628 #if defined(HAVE_PRI)
02629 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, enum sig_pri_law law, char *exten, const struct ast_channel *requestor)
02630 {
02631 struct dahdi_pvt *p = pvt;
02632 int audio;
02633 int newlaw = -1;
02634
02635 switch (p->sig) {
02636 case SIG_PRI_LIB_HANDLE_CASES:
02637 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02638
02639 break;
02640 }
02641
02642 default:
02643
02644 audio = 1;
02645 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02646 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02647 p->channel, audio, strerror(errno));
02648 }
02649 break;
02650 }
02651
02652 if (law != SIG_PRI_DEFLAW) {
02653 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02654 }
02655
02656 ast_copy_string(p->exten, exten, sizeof(p->exten));
02657
02658 switch (law) {
02659 case SIG_PRI_DEFLAW:
02660 newlaw = 0;
02661 break;
02662 case SIG_PRI_ALAW:
02663 newlaw = DAHDI_LAW_ALAW;
02664 break;
02665 case SIG_PRI_ULAW:
02666 newlaw = DAHDI_LAW_MULAW;
02667 break;
02668 }
02669 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02670 }
02671 #endif
02672
02673 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02674
02675 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685 static void my_pri_ss7_open_media(void *p)
02686 {
02687 struct dahdi_pvt *pvt = p;
02688 int res;
02689 int dfd;
02690 int set_val;
02691
02692 dfd = pvt->subs[SUB_REAL].dfd;
02693
02694
02695 set_val = 1;
02696 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02697 if (res < 0) {
02698 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02699 pvt->channel, strerror(errno));
02700 }
02701
02702
02703 res = dahdi_setlaw(dfd, pvt->law);
02704 if (res < 0) {
02705 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02706 }
02707
02708
02709 if (pvt->digital) {
02710 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02711 } else {
02712 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02713 pvt->law);
02714 }
02715 if (res < 0) {
02716 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02717 }
02718
02719 if (pvt->dsp_features && pvt->dsp) {
02720 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02721 pvt->dsp_features = 0;
02722 }
02723 }
02724 #endif
02725
02726 #if defined(HAVE_PRI)
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739 static void my_pri_dial_digits(void *p, const char *dial_string)
02740 {
02741 struct dahdi_dialoperation zo = {
02742 .op = DAHDI_DIAL_OP_APPEND,
02743 };
02744 struct dahdi_pvt *pvt = p;
02745 int res;
02746
02747 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02748 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02749 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02750 if (res) {
02751 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02752 pvt->channel, dial_string, strerror(errno));
02753 } else {
02754 pvt->dialing = 1;
02755 }
02756 }
02757 #endif
02758
02759 static int unalloc_sub(struct dahdi_pvt *p, int x);
02760
02761 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02762 {
02763 struct dahdi_pvt *p = pvt;
02764
02765 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02766 }
02767
02768 static int alloc_sub(struct dahdi_pvt *p, int x);
02769
02770 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02771 {
02772 struct dahdi_pvt *p = pvt;
02773
02774 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02775 }
02776
02777 static int has_voicemail(struct dahdi_pvt *p);
02778
02779 static int my_has_voicemail(void *pvt)
02780 {
02781 struct dahdi_pvt *p = pvt;
02782
02783 return has_voicemail(p);
02784 }
02785
02786 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02787 {
02788 struct dahdi_pvt *p = pvt;
02789 int index;
02790
02791 index = analogsub_to_dahdisub(sub);
02792
02793 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02794 }
02795
02796 static enum analog_event dahdievent_to_analogevent(int event)
02797 {
02798 enum analog_event res;
02799
02800 switch (event) {
02801 case DAHDI_EVENT_ONHOOK:
02802 res = ANALOG_EVENT_ONHOOK;
02803 break;
02804 case DAHDI_EVENT_RINGOFFHOOK:
02805 res = ANALOG_EVENT_RINGOFFHOOK;
02806 break;
02807 case DAHDI_EVENT_WINKFLASH:
02808 res = ANALOG_EVENT_WINKFLASH;
02809 break;
02810 case DAHDI_EVENT_ALARM:
02811 res = ANALOG_EVENT_ALARM;
02812 break;
02813 case DAHDI_EVENT_NOALARM:
02814 res = ANALOG_EVENT_NOALARM;
02815 break;
02816 case DAHDI_EVENT_DIALCOMPLETE:
02817 res = ANALOG_EVENT_DIALCOMPLETE;
02818 break;
02819 case DAHDI_EVENT_RINGERON:
02820 res = ANALOG_EVENT_RINGERON;
02821 break;
02822 case DAHDI_EVENT_RINGEROFF:
02823 res = ANALOG_EVENT_RINGEROFF;
02824 break;
02825 case DAHDI_EVENT_HOOKCOMPLETE:
02826 res = ANALOG_EVENT_HOOKCOMPLETE;
02827 break;
02828 case DAHDI_EVENT_PULSE_START:
02829 res = ANALOG_EVENT_PULSE_START;
02830 break;
02831 case DAHDI_EVENT_POLARITY:
02832 res = ANALOG_EVENT_POLARITY;
02833 break;
02834 case DAHDI_EVENT_RINGBEGIN:
02835 res = ANALOG_EVENT_RINGBEGIN;
02836 break;
02837 case DAHDI_EVENT_EC_DISABLED:
02838 res = ANALOG_EVENT_EC_DISABLED;
02839 break;
02840 case DAHDI_EVENT_REMOVED:
02841 res = ANALOG_EVENT_REMOVED;
02842 break;
02843 case DAHDI_EVENT_NEONMWI_ACTIVE:
02844 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02845 break;
02846 case DAHDI_EVENT_NEONMWI_INACTIVE:
02847 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02848 break;
02849 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02850 case DAHDI_EVENT_TX_CED_DETECTED:
02851 res = ANALOG_EVENT_TX_CED_DETECTED;
02852 break;
02853 case DAHDI_EVENT_RX_CED_DETECTED:
02854 res = ANALOG_EVENT_RX_CED_DETECTED;
02855 break;
02856 case DAHDI_EVENT_EC_NLP_DISABLED:
02857 res = ANALOG_EVENT_EC_NLP_DISABLED;
02858 break;
02859 case DAHDI_EVENT_EC_NLP_ENABLED:
02860 res = ANALOG_EVENT_EC_NLP_ENABLED;
02861 break;
02862 #endif
02863 case DAHDI_EVENT_PULSEDIGIT:
02864 res = ANALOG_EVENT_PULSEDIGIT;
02865 break;
02866 case DAHDI_EVENT_DTMFDOWN:
02867 res = ANALOG_EVENT_DTMFDOWN;
02868 break;
02869 case DAHDI_EVENT_DTMFUP:
02870 res = ANALOG_EVENT_DTMFUP;
02871 break;
02872 default:
02873 switch(event & 0xFFFF0000) {
02874 case DAHDI_EVENT_PULSEDIGIT:
02875 case DAHDI_EVENT_DTMFDOWN:
02876 case DAHDI_EVENT_DTMFUP:
02877
02878
02879
02880
02881 return event;
02882 }
02883
02884 res = ANALOG_EVENT_ERROR;
02885 break;
02886 }
02887
02888 return res;
02889 }
02890
02891 static inline int dahdi_wait_event(int fd);
02892
02893 static int my_wait_event(void *pvt)
02894 {
02895 struct dahdi_pvt *p = pvt;
02896
02897 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02898 }
02899
02900 static int my_get_event(void *pvt)
02901 {
02902 struct dahdi_pvt *p = pvt;
02903 int res;
02904
02905 if (p->fake_event) {
02906 res = p->fake_event;
02907 p->fake_event = 0;
02908 } else
02909 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02910
02911 return dahdievent_to_analogevent(res);
02912 }
02913
02914 static int my_is_off_hook(void *pvt)
02915 {
02916 struct dahdi_pvt *p = pvt;
02917 int res;
02918 struct dahdi_params par;
02919
02920 memset(&par, 0, sizeof(par));
02921
02922 if (p->subs[SUB_REAL].dfd > -1)
02923 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02924 else {
02925
02926 res = 0;
02927 par.rxisoffhook = 0;
02928 }
02929 if (res) {
02930 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02931 }
02932
02933 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02934
02935
02936
02937 return (par.rxbits > -1) || par.rxisoffhook;
02938 }
02939
02940 return par.rxisoffhook;
02941 }
02942
02943 static void dahdi_enable_ec(struct dahdi_pvt *p);
02944 static void dahdi_disable_ec(struct dahdi_pvt *p);
02945
02946 static int my_set_echocanceller(void *pvt, int enable)
02947 {
02948 struct dahdi_pvt *p = pvt;
02949
02950 if (enable)
02951 dahdi_enable_ec(p);
02952 else
02953 dahdi_disable_ec(p);
02954
02955 return 0;
02956 }
02957
02958 static int dahdi_ring_phone(struct dahdi_pvt *p);
02959
02960 static int my_ring(void *pvt)
02961 {
02962 struct dahdi_pvt *p = pvt;
02963
02964 return dahdi_ring_phone(p);
02965 }
02966
02967 static int my_flash(void *pvt)
02968 {
02969 struct dahdi_pvt *p = pvt;
02970 int func = DAHDI_FLASH;
02971 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02972 }
02973
02974 static inline int dahdi_set_hook(int fd, int hs);
02975
02976 static int my_off_hook(void *pvt)
02977 {
02978 struct dahdi_pvt *p = pvt;
02979 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02980 }
02981
02982 static void my_set_needringing(void *pvt, int value)
02983 {
02984 struct dahdi_pvt *p = pvt;
02985 p->subs[SUB_REAL].needringing = value;
02986 }
02987
02988 static void my_set_polarity(void *pvt, int value)
02989 {
02990 struct dahdi_pvt *p = pvt;
02991
02992 if (p->channel == CHAN_PSEUDO) {
02993 return;
02994 }
02995 p->polarity = value;
02996 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02997 }
02998
02999 static void my_start_polarityswitch(void *pvt)
03000 {
03001 struct dahdi_pvt *p = pvt;
03002
03003 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03004 my_set_polarity(pvt, 0);
03005 }
03006 }
03007
03008 static void my_answer_polarityswitch(void *pvt)
03009 {
03010 struct dahdi_pvt *p = pvt;
03011
03012 if (!p->answeronpolarityswitch) {
03013 return;
03014 }
03015
03016 my_set_polarity(pvt, 1);
03017 }
03018
03019 static void my_hangup_polarityswitch(void *pvt)
03020 {
03021 struct dahdi_pvt *p = pvt;
03022
03023 if (!p->hanguponpolarityswitch) {
03024 return;
03025 }
03026
03027 if (p->answeronpolarityswitch) {
03028 my_set_polarity(pvt, 0);
03029 } else {
03030 my_set_polarity(pvt, 1);
03031 }
03032 }
03033
03034 static int my_start(void *pvt)
03035 {
03036 struct dahdi_pvt *p = pvt;
03037 int x = DAHDI_START;
03038
03039 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03040 }
03041
03042 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03043 {
03044 int index = analogsub_to_dahdisub(sub);
03045 int res;
03046 struct dahdi_pvt *p = pvt;
03047 struct dahdi_dialoperation ddop;
03048
03049 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03050 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03051 return -1;
03052 }
03053
03054 if (sub != ANALOG_SUB_REAL) {
03055 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
03056 dop->dialstr, p->channel, sub);
03057 return -1;
03058 }
03059
03060 ddop.op = DAHDI_DIAL_OP_REPLACE;
03061 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03062
03063 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03064
03065 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03066 if (res == -1) {
03067 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03068 }
03069
03070 return res;
03071 }
03072
03073 static void dahdi_train_ec(struct dahdi_pvt *p);
03074
03075 static int my_train_echocanceller(void *pvt)
03076 {
03077 struct dahdi_pvt *p = pvt;
03078
03079 dahdi_train_ec(p);
03080
03081 return 0;
03082 }
03083
03084 static int my_is_dialing(void *pvt, enum analog_sub sub)
03085 {
03086 struct dahdi_pvt *p = pvt;
03087 int index;
03088 int x;
03089
03090 index = analogsub_to_dahdisub(sub);
03091
03092 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03093 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03094 return -1;
03095 }
03096
03097 return x;
03098 }
03099
03100 static int my_on_hook(void *pvt)
03101 {
03102 struct dahdi_pvt *p = pvt;
03103 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03104 }
03105
03106 #if defined(HAVE_PRI)
03107 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03108 {
03109 struct dahdi_pvt *old_chan = chan_old;
03110 struct dahdi_pvt *new_chan = chan_new;
03111
03112 new_chan->owner = old_chan->owner;
03113 old_chan->owner = NULL;
03114 if (new_chan->owner) {
03115 new_chan->owner->tech_pvt = new_chan;
03116 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03117 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03118 old_chan->subs[SUB_REAL].owner = NULL;
03119 }
03120
03121 new_chan->dsp = old_chan->dsp;
03122 new_chan->dsp_features = old_chan->dsp_features;
03123 old_chan->dsp = NULL;
03124 old_chan->dsp_features = 0;
03125
03126
03127 new_chan->dialing = old_chan->dialing;
03128 new_chan->digital = old_chan->digital;
03129 new_chan->outgoing = old_chan->outgoing;
03130 old_chan->dialing = 0;
03131 old_chan->digital = 0;
03132 old_chan->outgoing = 0;
03133
03134
03135 new_chan->law = old_chan->law;
03136 strcpy(new_chan->dialstring, old_chan->dialstring);
03137 }
03138 #endif
03139
03140 #if defined(HAVE_PRI)
03141 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03142 {
03143 switch (tone) {
03144 case SIG_PRI_TONE_RINGTONE:
03145 return DAHDI_TONE_RINGTONE;
03146 case SIG_PRI_TONE_STUTTER:
03147 return DAHDI_TONE_STUTTER;
03148 case SIG_PRI_TONE_CONGESTION:
03149 return DAHDI_TONE_CONGESTION;
03150 case SIG_PRI_TONE_DIALTONE:
03151 return DAHDI_TONE_DIALTONE;
03152 case SIG_PRI_TONE_DIALRECALL:
03153 return DAHDI_TONE_DIALRECALL;
03154 case SIG_PRI_TONE_INFO:
03155 return DAHDI_TONE_INFO;
03156 case SIG_PRI_TONE_BUSY:
03157 return DAHDI_TONE_BUSY;
03158 default:
03159 return -1;
03160 }
03161 }
03162 #endif
03163
03164 #if defined(HAVE_PRI)
03165 static int pri_destroy_dchan(struct sig_pri_span *pri);
03166
03167 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03168 {
03169 int x;
03170
03171 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03172 switch (x) {
03173 case DAHDI_EVENT_NONE:
03174 break;
03175 case DAHDI_EVENT_ALARM:
03176 case DAHDI_EVENT_NOALARM:
03177 if (sig_pri_is_alarm_ignored(pri)) {
03178 break;
03179 }
03180
03181 default:
03182 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03183 event2str(x), x, pri->span);
03184 break;
03185 }
03186
03187 switch (x) {
03188 case DAHDI_EVENT_ALARM:
03189 pri_event_alarm(pri, index, 0);
03190 break;
03191 case DAHDI_EVENT_NOALARM:
03192 pri_event_noalarm(pri, index, 0);
03193 break;
03194 case DAHDI_EVENT_REMOVED:
03195 pri_destroy_dchan(pri);
03196 break;
03197 default:
03198 break;
03199 }
03200 }
03201 #endif
03202
03203 #if defined(HAVE_PRI)
03204 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03205 {
03206 struct dahdi_pvt *p = pvt;
03207
03208 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03209 }
03210 #endif
03211
03212 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03224 {
03225 struct dahdi_pvt *p = pvt;
03226
03227 ast_copy_string(p->cid_num,
03228 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03229 sizeof(p->cid_num));
03230 ast_copy_string(p->cid_name,
03231 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03232 sizeof(p->cid_name));
03233 ast_copy_string(p->cid_subaddr,
03234 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03235 sizeof(p->cid_subaddr));
03236 p->cid_ton = caller->id.number.plan;
03237 p->callingpres = ast_party_id_presentation(&caller->id);
03238 if (caller->id.tag) {
03239 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03240 }
03241 ast_copy_string(p->cid_ani,
03242 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03243 sizeof(p->cid_ani));
03244 p->cid_ani2 = caller->ani2;
03245 }
03246 #endif
03247
03248 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259 static void my_set_dnid(void *pvt, const char *dnid)
03260 {
03261 struct dahdi_pvt *p = pvt;
03262
03263 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03264 }
03265 #endif
03266
03267 #if defined(HAVE_PRI)
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278 static void my_set_rdnis(void *pvt, const char *rdnis)
03279 {
03280 struct dahdi_pvt *p = pvt;
03281
03282 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03283 }
03284 #endif
03285
03286 #if defined(HAVE_PRI)
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03312 {
03313 char *dial;
03314 struct dahdi_pvt *pvt;
03315 AST_DECLARE_APP_ARGS(args,
03316 AST_APP_ARG(tech);
03317 AST_APP_ARG(group);
03318
03319
03320
03321 );
03322
03323 pvt = priv;
03324 dial = ast_strdupa(pvt->dialstring);
03325 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03326 if (!args.tech) {
03327 ast_copy_string(buf, pvt->dialstring, buf_size);
03328 return;
03329 }
03330 if (!args.group) {
03331
03332 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03333 return;
03334 }
03335 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03336
03337
03338 ast_copy_string(buf, pvt->dialstring, buf_size);
03339 return;
03340 }
03341
03342 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03343 }
03344 #endif
03345
03346 #if defined(HAVE_PRI)
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03359 {
03360 unsigned idx;
03361 unsigned num_b_chans;
03362 unsigned in_use;
03363 unsigned in_alarm;
03364 enum ast_device_state new_state;
03365
03366
03367 num_b_chans = 0;
03368 in_use = 0;
03369 in_alarm = 1;
03370 for (idx = pri->numchans; idx--;) {
03371 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03372
03373 ++num_b_chans;
03374 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03375 ++in_use;
03376 }
03377 if (!pri->pvts[idx]->inalarm) {
03378
03379 in_alarm = 0;
03380 }
03381 }
03382 }
03383
03384
03385 if (in_alarm) {
03386 new_state = AST_DEVICE_UNAVAILABLE;
03387 } else {
03388 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03389 }
03390 if (pri->congestion_devstate != new_state) {
03391 pri->congestion_devstate = new_state;
03392 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03393 }
03394 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03395
03396 if (in_alarm) {
03397 new_state = AST_DEVICE_UNAVAILABLE;
03398 } else if (!in_use) {
03399 new_state = AST_DEVICE_NOT_INUSE;
03400 } else if (!pri->user_busy_threshold) {
03401 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03402 } else {
03403 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03404 : AST_DEVICE_BUSY;
03405 }
03406 if (pri->threshold_devstate != new_state) {
03407 pri->threshold_devstate = new_state;
03408 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03409 }
03410 #endif
03411 }
03412 #endif
03413
03414 #if defined(HAVE_PRI)
03415
03416
03417
03418
03419
03420
03421
03422 static void my_module_ref(void)
03423 {
03424 ast_module_ref(ast_module_info->self);
03425 }
03426 #endif
03427
03428 #if defined(HAVE_PRI)
03429
03430
03431
03432
03433
03434
03435
03436 static void my_module_unref(void)
03437 {
03438 ast_module_unref(ast_module_info->self);
03439 }
03440 #endif
03441
03442 #if defined(HAVE_PRI)
03443 #if defined(HAVE_PRI_CALL_WAITING)
03444 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03445 #endif
03446 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03447
03448 static struct sig_pri_callback dahdi_pri_callbacks =
03449 {
03450 .handle_dchan_exception = my_handle_dchan_exception,
03451 .play_tone = my_pri_play_tone,
03452 .set_echocanceller = my_set_echocanceller,
03453 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03454 .lock_private = my_lock_private,
03455 .unlock_private = my_unlock_private,
03456 .new_ast_channel = my_new_pri_ast_channel,
03457 .fixup_chans = my_pri_fixup_chans,
03458 .set_alarm = my_set_alarm,
03459 .set_dialing = my_set_dialing,
03460 .set_outgoing = my_set_outgoing,
03461 .set_digital = my_set_digital,
03462 .set_callerid = my_set_callerid,
03463 .set_dnid = my_set_dnid,
03464 .set_rdnis = my_set_rdnis,
03465 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03466 #if defined(HAVE_PRI_CALL_WAITING)
03467 .init_config = my_pri_init_config,
03468 #endif
03469 .get_orig_dialstring = my_get_orig_dialstring,
03470 .make_cc_dialstring = my_pri_make_cc_dialstring,
03471 .update_span_devstate = dahdi_pri_update_span_devstate,
03472 .module_ref = my_module_ref,
03473 .module_unref = my_module_unref,
03474 .dial_digits = my_pri_dial_digits,
03475 .open_media = my_pri_ss7_open_media,
03476 .ami_channel_event = my_ami_channel_event,
03477 };
03478 #endif
03479
03480 #if defined(HAVE_SS7)
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03492 {
03493 int event;
03494
03495 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03496 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03497 linkset->span, which);
03498 return;
03499 }
03500 switch (event) {
03501 case DAHDI_EVENT_NONE:
03502 break;
03503 case DAHDI_EVENT_ALARM:
03504 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03505 event2str(event), event, linkset->span, which);
03506 sig_ss7_link_alarm(linkset, which);
03507 break;
03508 case DAHDI_EVENT_NOALARM:
03509 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03510 event2str(event), event, linkset->span, which);
03511 sig_ss7_link_noalarm(linkset, which);
03512 break;
03513 default:
03514 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03515 event2str(event), event, linkset->span, which);
03516 break;
03517 }
03518 }
03519 #endif
03520
03521 #if defined(HAVE_SS7)
03522 static void my_ss7_set_loopback(void *pvt, int enable)
03523 {
03524 struct dahdi_pvt *p = pvt;
03525
03526 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03527 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03528 strerror(errno));
03529 }
03530 }
03531 #endif
03532
03533 #if defined(HAVE_SS7)
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548 static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor)
03549 {
03550 struct dahdi_pvt *p = pvt;
03551 int audio;
03552 int newlaw;
03553
03554
03555 audio = 1;
03556 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03557 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03558 p->channel, audio, strerror(errno));
03559
03560 if (law != SIG_SS7_DEFLAW) {
03561 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03562 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03563 }
03564
03565 ast_copy_string(p->exten, exten, sizeof(p->exten));
03566
03567 newlaw = -1;
03568 switch (law) {
03569 case SIG_SS7_DEFLAW:
03570 newlaw = 0;
03571 break;
03572 case SIG_SS7_ALAW:
03573 newlaw = DAHDI_LAW_ALAW;
03574 break;
03575 case SIG_SS7_ULAW:
03576 newlaw = DAHDI_LAW_MULAW;
03577 break;
03578 }
03579 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03580 }
03581 #endif
03582
03583 #if defined(HAVE_SS7)
03584 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03585 {
03586 switch (tone) {
03587 case SIG_SS7_TONE_RINGTONE:
03588 return DAHDI_TONE_RINGTONE;
03589 case SIG_SS7_TONE_STUTTER:
03590 return DAHDI_TONE_STUTTER;
03591 case SIG_SS7_TONE_CONGESTION:
03592 return DAHDI_TONE_CONGESTION;
03593 case SIG_SS7_TONE_DIALTONE:
03594 return DAHDI_TONE_DIALTONE;
03595 case SIG_SS7_TONE_DIALRECALL:
03596 return DAHDI_TONE_DIALRECALL;
03597 case SIG_SS7_TONE_INFO:
03598 return DAHDI_TONE_INFO;
03599 case SIG_SS7_TONE_BUSY:
03600 return DAHDI_TONE_BUSY;
03601 default:
03602 return -1;
03603 }
03604 }
03605 #endif
03606
03607 #if defined(HAVE_SS7)
03608 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03609 {
03610 struct dahdi_pvt *p = pvt;
03611
03612 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03613 }
03614 #endif
03615
03616 #if defined(HAVE_SS7)
03617 static struct sig_ss7_callback dahdi_ss7_callbacks =
03618 {
03619 .lock_private = my_lock_private,
03620 .unlock_private = my_unlock_private,
03621
03622 .set_echocanceller = my_set_echocanceller,
03623 .set_loopback = my_ss7_set_loopback,
03624
03625 .new_ast_channel = my_new_ss7_ast_channel,
03626 .play_tone = my_ss7_play_tone,
03627
03628 .handle_link_exception = my_handle_link_exception,
03629 .set_alarm = my_set_alarm,
03630 .set_dialing = my_set_dialing,
03631 .set_outgoing = my_set_outgoing,
03632 .set_digital = my_set_digital,
03633 .set_inservice = my_set_inservice,
03634 .set_locallyblocked = my_set_locallyblocked,
03635 .set_remotelyblocked = my_set_remotelyblocked,
03636 .set_callerid = my_set_callerid,
03637 .set_dnid = my_set_dnid,
03638 .open_media = my_pri_ss7_open_media,
03639 };
03640 #endif
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660 static void notify_message(char *mailbox_full, int thereornot)
03661 {
03662 char s[sizeof(mwimonitornotify) + 80];
03663 struct ast_event *event;
03664 char *mailbox, *context;
03665
03666
03667 context = mailbox = ast_strdupa(mailbox_full);
03668 strsep(&context, "@");
03669 if (ast_strlen_zero(context))
03670 context = "default";
03671
03672 if (!(event = ast_event_new(AST_EVENT_MWI,
03673 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03674 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03675 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03676 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03677 AST_EVENT_IE_END))) {
03678 return;
03679 }
03680
03681 ast_event_queue_and_cache(event);
03682
03683 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03684 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03685 ast_safe_system(s);
03686 }
03687 }
03688
03689 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03690 {
03691 struct dahdi_pvt *p = pvt;
03692
03693 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03694 return;
03695
03696 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03697 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03698 notify_message(p->mailbox, 1);
03699 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03700 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03701 notify_message(p->mailbox, 0);
03702 }
03703
03704
03705 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03706 ast_hangup(chan);
03707 return;
03708 }
03709 }
03710
03711 static int my_have_progressdetect(void *pvt)
03712 {
03713 struct dahdi_pvt *p = pvt;
03714
03715 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03716 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03717 return 1;
03718 } else {
03719
03720 return 0;
03721 }
03722 }
03723
03724 static struct analog_callback dahdi_analog_callbacks =
03725 {
03726 .play_tone = my_play_tone,
03727 .get_event = my_get_event,
03728 .wait_event = my_wait_event,
03729 .is_off_hook = my_is_off_hook,
03730 .set_echocanceller = my_set_echocanceller,
03731 .ring = my_ring,
03732 .flash = my_flash,
03733 .off_hook = my_off_hook,
03734 .dial_digits = my_dial_digits,
03735 .train_echocanceller = my_train_echocanceller,
03736 .on_hook = my_on_hook,
03737 .is_dialing = my_is_dialing,
03738 .allocate_sub = my_allocate_sub,
03739 .unallocate_sub = my_unallocate_sub,
03740 .swap_subs = my_swap_subchannels,
03741 .has_voicemail = my_has_voicemail,
03742 .check_for_conference = my_check_for_conference,
03743 .conf_add = my_conf_add,
03744 .conf_del = my_conf_del,
03745 .complete_conference_update = my_complete_conference_update,
03746 .start = my_start,
03747 .all_subchannels_hungup = my_all_subchannels_hungup,
03748 .lock_private = my_lock_private,
03749 .unlock_private = my_unlock_private,
03750 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03751 .handle_dtmf = my_handle_dtmf,
03752 .wink = my_wink,
03753 .new_ast_channel = my_new_analog_ast_channel,
03754 .dsp_set_digitmode = my_dsp_set_digitmode,
03755 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03756 .send_callerid = my_send_callerid,
03757 .callwait = my_callwait,
03758 .stop_callwait = my_stop_callwait,
03759 .get_callerid = my_get_callerid,
03760 .start_cid_detect = my_start_cid_detect,
03761 .stop_cid_detect = my_stop_cid_detect,
03762 .handle_notify_message = my_handle_notify_message,
03763 .increase_ss_count = my_increase_ss_count,
03764 .decrease_ss_count = my_decrease_ss_count,
03765 .distinctive_ring = my_distinctive_ring,
03766 .set_linear_mode = my_set_linear_mode,
03767 .set_inthreeway = my_set_inthreeway,
03768 .get_and_handle_alarms = my_get_and_handle_alarms,
03769 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03770 .get_sub_fd = my_get_sub_fd,
03771 .set_cadence = my_set_cadence,
03772 .set_alarm = my_set_alarm,
03773 .set_dialing = my_set_dialing,
03774 .set_outgoing = my_set_outgoing,
03775 .set_ringtimeout = my_set_ringtimeout,
03776 .set_waitingfordt = my_set_waitingfordt,
03777 .check_waitingfordt = my_check_waitingfordt,
03778 .set_confirmanswer = my_set_confirmanswer,
03779 .check_confirmanswer = my_check_confirmanswer,
03780 .set_callwaiting = my_set_callwaiting,
03781 .cancel_cidspill = my_cancel_cidspill,
03782 .confmute = my_confmute,
03783 .set_pulsedial = my_set_pulsedial,
03784 .set_new_owner = my_set_new_owner,
03785 .get_orig_dialstring = my_get_orig_dialstring,
03786 .set_needringing = my_set_needringing,
03787 .set_polarity = my_set_polarity,
03788 .start_polarityswitch = my_start_polarityswitch,
03789 .answer_polarityswitch = my_answer_polarityswitch,
03790 .hangup_polarityswitch = my_hangup_polarityswitch,
03791 .have_progressdetect = my_have_progressdetect,
03792 };
03793
03794
03795 static struct dahdi_pvt *round_robin[32];
03796
03797 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03798 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03799 {
03800 int res;
03801 if (p->subs[SUB_REAL].owner == ast)
03802 res = 0;
03803 else if (p->subs[SUB_CALLWAIT].owner == ast)
03804 res = 1;
03805 else if (p->subs[SUB_THREEWAY].owner == ast)
03806 res = 2;
03807 else {
03808 res = -1;
03809 if (!nullok)
03810 ast_log(LOG_WARNING,
03811 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03812 ast ? ast->name : "", p->channel, fname, line);
03813 }
03814 return res;
03815 }
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03833 {
03834 for (;;) {
03835 if (!pvt->subs[sub_idx].owner) {
03836
03837 break;
03838 }
03839 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03840
03841 break;
03842 }
03843
03844 DEADLOCK_AVOIDANCE(&pvt->lock);
03845 }
03846 }
03847
03848 static void wakeup_sub(struct dahdi_pvt *p, int a)
03849 {
03850 dahdi_lock_sub_owner(p, a);
03851 if (p->subs[a].owner) {
03852 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03853 ast_channel_unlock(p->subs[a].owner);
03854 }
03855 }
03856
03857 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03858 {
03859 for (;;) {
03860 if (p->owner) {
03861 if (ast_channel_trylock(p->owner)) {
03862 DEADLOCK_AVOIDANCE(&p->lock);
03863 } else {
03864 ast_queue_frame(p->owner, f);
03865 ast_channel_unlock(p->owner);
03866 break;
03867 }
03868 } else
03869 break;
03870 }
03871 }
03872
03873 static void handle_clear_alarms(struct dahdi_pvt *p)
03874 {
03875 #if defined(HAVE_PRI)
03876 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03877 return;
03878 }
03879 #endif
03880
03881 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03882 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03883 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03884 }
03885 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03886 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03887 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03888 }
03889 }
03890
03891 #ifdef HAVE_OPENR2
03892
03893 static int dahdi_r2_answer(struct dahdi_pvt *p)
03894 {
03895 int res = 0;
03896
03897
03898
03899 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03900 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03901 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03902 if (!double_answer) {
03903
03904
03905 res = openr2_chan_answer_call(p->r2chan);
03906 } else if (wants_double_answer) {
03907 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03908 } else {
03909 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03910 }
03911 #else
03912 res = openr2_chan_answer_call(p->r2chan);
03913 #endif
03914 return res;
03915 }
03916
03917
03918
03919
03920 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03921 {
03922 openr2_calling_party_category_t cat;
03923 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03924 struct dahdi_pvt *p = c->tech_pvt;
03925 if (ast_strlen_zero(catstr)) {
03926 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03927 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03928 return p->mfcr2_category;
03929 }
03930 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03931 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03932 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03933 return p->mfcr2_category;
03934 }
03935 ast_debug(1, "Using category %s\n", catstr);
03936 return cat;
03937 }
03938
03939 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03940 {
03941 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03942 ast_mutex_lock(&p->lock);
03943 if (p->mfcr2call) {
03944 ast_mutex_unlock(&p->lock);
03945
03946
03947
03948
03949
03950 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03951 return;
03952 }
03953 p->mfcr2call = 1;
03954
03955 p->cid_name[0] = '\0';
03956 p->cid_num[0] = '\0';
03957 p->cid_subaddr[0] = '\0';
03958 p->rdnis[0] = '\0';
03959 p->exten[0] = '\0';
03960 p->mfcr2_ani_index = '\0';
03961 p->mfcr2_dnis_index = '\0';
03962 p->mfcr2_dnis_matched = 0;
03963 p->mfcr2_answer_pending = 0;
03964 p->mfcr2_call_accepted = 0;
03965 ast_mutex_unlock(&p->lock);
03966 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03967 }
03968
03969 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03970 {
03971 int res;
03972 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03973 ast_mutex_lock(&p->lock);
03974 p->inalarm = alarm ? 1 : 0;
03975 if (p->inalarm) {
03976 res = get_alarms(p);
03977 handle_alarms(p, res);
03978 } else {
03979 handle_clear_alarms(p);
03980 }
03981 ast_mutex_unlock(&p->lock);
03982 }
03983
03984 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03985 {
03986 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03987 }
03988
03989 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03990 {
03991 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03992 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03993 if (p->owner) {
03994 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03995 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03996 }
03997 ast_mutex_lock(&p->lock);
03998 p->mfcr2call = 0;
03999 ast_mutex_unlock(&p->lock);
04000 }
04001
04002 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
04003 {
04004 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
04005 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
04006 p->channel, openr2_proto_get_disconnect_string(cause));
04007
04008 openr2_chan_set_idle(p->r2chan);
04009 ast_mutex_lock(&p->lock);
04010 p->mfcr2call = 0;
04011 ast_mutex_unlock(&p->lock);
04012 }
04013 }
04014
04015 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
04016 {
04017 struct dahdi_pvt *p;
04018 struct ast_channel *c;
04019 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04020 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04021 openr2_proto_get_category_string(category));
04022 p = openr2_chan_get_client_data(r2chan);
04023
04024 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04025 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04026 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04027 return;
04028 }
04029 ast_mutex_lock(&p->lock);
04030 p->mfcr2_recvd_category = category;
04031
04032 if (!p->use_callerid) {
04033 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04034 p->cid_num[0] = 0;
04035 p->cid_name[0] = 0;
04036 }
04037
04038 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04039 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04040 p->exten[0] = 's';
04041 p->exten[1] = 0;
04042 }
04043 ast_mutex_unlock(&p->lock);
04044 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04045 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04046 p->channel, p->exten, p->context);
04047 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04048 return;
04049 }
04050 if (!p->mfcr2_accept_on_offer) {
04051
04052 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04053 if (c) {
04054
04055
04056
04057 return;
04058 }
04059 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04060 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04061 } else if (p->mfcr2_charge_calls) {
04062 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04063 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04064 } else {
04065 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04066 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04067 }
04068 }
04069
04070 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04071 {
04072 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04073 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04074 ast_mutex_lock(&p->lock);
04075 p->mfcr2call = 0;
04076 ast_mutex_unlock(&p->lock);
04077 }
04078
04079 static void dahdi_enable_ec(struct dahdi_pvt *p);
04080 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04081 {
04082 struct dahdi_pvt *p = NULL;
04083 struct ast_channel *c = NULL;
04084 p = openr2_chan_get_client_data(r2chan);
04085 dahdi_enable_ec(p);
04086 p->mfcr2_call_accepted = 1;
04087
04088 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04089 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04090
04091
04092
04093
04094 if (!p->mfcr2_accept_on_offer) {
04095 openr2_chan_disable_read(r2chan);
04096 if (p->mfcr2_answer_pending) {
04097 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04098 dahdi_r2_answer(p);
04099 }
04100 return;
04101 }
04102 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04103 if (c) {
04104
04105
04106 openr2_chan_disable_read(r2chan);
04107 return;
04108 }
04109 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04110
04111 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04112 return;
04113 }
04114
04115 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04116 p->subs[SUB_REAL].needringing = 1;
04117 p->dialing = 0;
04118
04119 openr2_chan_disable_read(r2chan);
04120 }
04121
04122 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04123 {
04124 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04125 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04126 p->subs[SUB_REAL].needanswer = 1;
04127 }
04128
04129 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04130 {
04131
04132 }
04133
04134 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04135 {
04136 switch (cause) {
04137 case OR2_CAUSE_BUSY_NUMBER:
04138 return AST_CAUSE_BUSY;
04139 case OR2_CAUSE_NETWORK_CONGESTION:
04140 return AST_CAUSE_CONGESTION;
04141 case OR2_CAUSE_OUT_OF_ORDER:
04142 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04143 case OR2_CAUSE_UNALLOCATED_NUMBER:
04144 return AST_CAUSE_UNREGISTERED;
04145 case OR2_CAUSE_NO_ANSWER:
04146 return AST_CAUSE_NO_ANSWER;
04147 case OR2_CAUSE_NORMAL_CLEARING:
04148 return AST_CAUSE_NORMAL_CLEARING;
04149 case OR2_CAUSE_UNSPECIFIED:
04150 default:
04151 return AST_CAUSE_NOTDEFINED;
04152 }
04153 }
04154
04155 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04156 {
04157 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04158 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04159 ast_mutex_lock(&p->lock);
04160 if (!p->owner) {
04161 ast_mutex_unlock(&p->lock);
04162
04163 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04164 return;
04165 }
04166
04167
04168 if (p->owner->_state == AST_STATE_UP) {
04169 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04170 ast_mutex_unlock(&p->lock);
04171 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04172
04173 switch (cause) {
04174 case OR2_CAUSE_BUSY_NUMBER:
04175 p->subs[SUB_REAL].needbusy = 1;
04176 break;
04177 case OR2_CAUSE_NETWORK_CONGESTION:
04178 case OR2_CAUSE_OUT_OF_ORDER:
04179 case OR2_CAUSE_UNALLOCATED_NUMBER:
04180 case OR2_CAUSE_NO_ANSWER:
04181 case OR2_CAUSE_UNSPECIFIED:
04182 case OR2_CAUSE_NORMAL_CLEARING:
04183 p->subs[SUB_REAL].needcongestion = 1;
04184 break;
04185 default:
04186 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04187 }
04188 ast_mutex_unlock(&p->lock);
04189 } else {
04190 ast_mutex_unlock(&p->lock);
04191
04192
04193 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04194 }
04195 }
04196
04197 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04198 {
04199 switch (level) {
04200 case OR2_LOG_NOTICE:
04201 ast_verbose("%s", logmessage);
04202 break;
04203 case OR2_LOG_WARNING:
04204 ast_log(LOG_WARNING, "%s", logmessage);
04205 break;
04206 case OR2_LOG_ERROR:
04207 ast_log(LOG_ERROR, "%s", logmessage);
04208 break;
04209 case OR2_LOG_STACK_TRACE:
04210 case OR2_LOG_MF_TRACE:
04211 case OR2_LOG_CAS_TRACE:
04212 case OR2_LOG_DEBUG:
04213 case OR2_LOG_EX_DEBUG:
04214 ast_log(LOG_DEBUG, "%s", logmessage);
04215 break;
04216 default:
04217 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04218 ast_log(LOG_DEBUG, "%s", logmessage);
04219 break;
04220 }
04221 }
04222
04223 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04224 {
04225 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04226 ast_mutex_lock(&p->lock);
04227 p->remotelyblocked = 1;
04228 ast_mutex_unlock(&p->lock);
04229 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04230 }
04231
04232 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04233 {
04234 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04235 ast_mutex_lock(&p->lock);
04236 p->remotelyblocked = 0;
04237 ast_mutex_unlock(&p->lock);
04238 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04239 }
04240
04241 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04242 __attribute__((format (printf, 3, 0)));
04243 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04244 {
04245 #define CONTEXT_TAG "Context - "
04246 char logmsg[256];
04247 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04248 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04249 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04250 dahdi_r2_write_log(level, completemsg);
04251 #undef CONTEXT_TAG
04252 }
04253
04254 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04255 __attribute__((format (printf, 3, 0)));
04256 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04257 {
04258 #define CHAN_TAG "Chan "
04259 char logmsg[256];
04260 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04261 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04262 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04263 dahdi_r2_write_log(level, completemsg);
04264 }
04265
04266 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04267 {
04268 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04269
04270 if (p->immediate) {
04271 return 0;
04272 }
04273 p->exten[p->mfcr2_dnis_index] = digit;
04274 p->rdnis[p->mfcr2_dnis_index] = digit;
04275 p->mfcr2_dnis_index++;
04276 p->exten[p->mfcr2_dnis_index] = 0;
04277 p->rdnis[p->mfcr2_dnis_index] = 0;
04278
04279 if ((p->mfcr2_dnis_matched ||
04280 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04281 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04282 return 0;
04283 }
04284
04285 return 1;
04286 }
04287
04288 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04289 {
04290 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04291 p->cid_num[p->mfcr2_ani_index] = digit;
04292 p->cid_name[p->mfcr2_ani_index] = digit;
04293 p->mfcr2_ani_index++;
04294 p->cid_num[p->mfcr2_ani_index] = 0;
04295 p->cid_name[p->mfcr2_ani_index] = 0;
04296 }
04297
04298 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04299 {
04300 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04301 }
04302
04303 static openr2_event_interface_t dahdi_r2_event_iface = {
04304 .on_call_init = dahdi_r2_on_call_init,
04305 .on_call_offered = dahdi_r2_on_call_offered,
04306 .on_call_accepted = dahdi_r2_on_call_accepted,
04307 .on_call_answered = dahdi_r2_on_call_answered,
04308 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04309 .on_call_end = dahdi_r2_on_call_end,
04310 .on_call_read = dahdi_r2_on_call_read,
04311 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04312 .on_os_error = dahdi_r2_on_os_error,
04313 .on_protocol_error = dahdi_r2_on_protocol_error,
04314 .on_line_blocked = dahdi_r2_on_line_blocked,
04315 .on_line_idle = dahdi_r2_on_line_idle,
04316
04317 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04318 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04319 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04320
04321 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04322 };
04323
04324 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04325 {
04326 return AST_ALAW(sample);
04327 }
04328
04329 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04330 {
04331 return AST_LIN2A(sample);
04332 }
04333
04334 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04335 dahdi_r2_alaw_to_linear,
04336 dahdi_r2_linear_to_alaw
04337 };
04338
04339 #endif
04340
04341 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04342 {
04343 int tchan;
04344 int tinthreeway;
04345 struct ast_channel *towner;
04346
04347 ast_debug(1, "Swapping %d and %d\n", a, b);
04348
04349 tchan = p->subs[a].chan;
04350 towner = p->subs[a].owner;
04351 tinthreeway = p->subs[a].inthreeway;
04352
04353 p->subs[a].chan = p->subs[b].chan;
04354 p->subs[a].owner = p->subs[b].owner;
04355 p->subs[a].inthreeway = p->subs[b].inthreeway;
04356
04357 p->subs[b].chan = tchan;
04358 p->subs[b].owner = towner;
04359 p->subs[b].inthreeway = tinthreeway;
04360
04361 if (p->subs[a].owner)
04362 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04363 if (p->subs[b].owner)
04364 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04365 wakeup_sub(p, a);
04366 wakeup_sub(p, b);
04367 }
04368
04369 static int dahdi_open(char *fn)
04370 {
04371 int fd;
04372 int isnum;
04373 int chan = 0;
04374 int bs;
04375 int x;
04376 isnum = 1;
04377 for (x = 0; x < strlen(fn); x++) {
04378 if (!isdigit(fn[x])) {
04379 isnum = 0;
04380 break;
04381 }
04382 }
04383 if (isnum) {
04384 chan = atoi(fn);
04385 if (chan < 1) {
04386 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04387 return -1;
04388 }
04389 fn = "/dev/dahdi/channel";
04390 }
04391 fd = open(fn, O_RDWR | O_NONBLOCK);
04392 if (fd < 0) {
04393 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04394 return -1;
04395 }
04396 if (chan) {
04397 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04398 x = errno;
04399 close(fd);
04400 errno = x;
04401 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04402 return -1;
04403 }
04404 }
04405 bs = READ_SIZE;
04406 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04407 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04408 x = errno;
04409 close(fd);
04410 errno = x;
04411 return -1;
04412 }
04413 return fd;
04414 }
04415
04416 static void dahdi_close(int fd)
04417 {
04418 if (fd > 0)
04419 close(fd);
04420 }
04421
04422 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04423 {
04424 dahdi_close(chan_pvt->subs[sub_num].dfd);
04425 chan_pvt->subs[sub_num].dfd = -1;
04426 }
04427
04428 #if defined(HAVE_PRI)
04429 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04430 {
04431 dahdi_close(pri->pri.fds[fd_num]);
04432 pri->pri.fds[fd_num] = -1;
04433 }
04434 #endif
04435
04436 #if defined(HAVE_SS7)
04437 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04438 {
04439 dahdi_close(ss7->ss7.fds[fd_num]);
04440 ss7->ss7.fds[fd_num] = -1;
04441 }
04442 #endif
04443
04444 static int dahdi_setlinear(int dfd, int linear)
04445 {
04446 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04447 }
04448
04449
04450 static int alloc_sub(struct dahdi_pvt *p, int x)
04451 {
04452 struct dahdi_bufferinfo bi;
04453 int res;
04454 if (p->subs[x].dfd >= 0) {
04455 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04456 return -1;
04457 }
04458
04459 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04460 if (p->subs[x].dfd <= -1) {
04461 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04462 return -1;
04463 }
04464
04465 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04466 if (!res) {
04467 bi.txbufpolicy = p->buf_policy;
04468 bi.rxbufpolicy = p->buf_policy;
04469 bi.numbufs = p->buf_no;
04470 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04471 if (res < 0) {
04472 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04473 }
04474 } else
04475 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04476
04477 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04478 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04479 dahdi_close_sub(p, x);
04480 p->subs[x].dfd = -1;
04481 return -1;
04482 }
04483 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04484 return 0;
04485 }
04486
04487 static int unalloc_sub(struct dahdi_pvt *p, int x)
04488 {
04489 if (!x) {
04490 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04491 return -1;
04492 }
04493 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04494 dahdi_close_sub(p, x);
04495 p->subs[x].linear = 0;
04496 p->subs[x].chan = 0;
04497 p->subs[x].owner = NULL;
04498 p->subs[x].inthreeway = 0;
04499 p->polarity = POLARITY_IDLE;
04500 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04501 return 0;
04502 }
04503
04504 static int digit_to_dtmfindex(char digit)
04505 {
04506 if (isdigit(digit))
04507 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04508 else if (digit >= 'A' && digit <= 'D')
04509 return DAHDI_TONE_DTMF_A + (digit - 'A');
04510 else if (digit >= 'a' && digit <= 'd')
04511 return DAHDI_TONE_DTMF_A + (digit - 'a');
04512 else if (digit == '*')
04513 return DAHDI_TONE_DTMF_s;
04514 else if (digit == '#')
04515 return DAHDI_TONE_DTMF_p;
04516 else
04517 return -1;
04518 }
04519
04520 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04521 {
04522 struct dahdi_pvt *pvt;
04523 int idx;
04524 int dtmf = -1;
04525 int res;
04526
04527 pvt = chan->tech_pvt;
04528
04529 ast_mutex_lock(&pvt->lock);
04530
04531 idx = dahdi_get_index(chan, pvt, 0);
04532
04533 if ((idx != SUB_REAL) || !pvt->owner)
04534 goto out;
04535
04536 #ifdef HAVE_PRI
04537 switch (pvt->sig) {
04538 case SIG_PRI_LIB_HANDLE_CASES:
04539 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04540 if (!res)
04541 goto out;
04542 break;
04543 default:
04544 break;
04545 }
04546 #endif
04547 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04548 goto out;
04549
04550 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04551 struct dahdi_dialoperation zo = {
04552 .op = DAHDI_DIAL_OP_APPEND,
04553 };
04554
04555 zo.dialstr[0] = 'T';
04556 zo.dialstr[1] = digit;
04557 zo.dialstr[2] = '\0';
04558 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04559 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04560 chan->name, digit, strerror(errno));
04561 else
04562 pvt->dialing = 1;
04563 } else {
04564 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04565 chan->name, digit);
04566 pvt->dialing = 1;
04567 pvt->begindigit = digit;
04568 }
04569
04570 out:
04571 ast_mutex_unlock(&pvt->lock);
04572
04573 return 0;
04574 }
04575
04576 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04577 {
04578 struct dahdi_pvt *pvt;
04579 int res = 0;
04580 int idx;
04581 int x;
04582
04583 pvt = chan->tech_pvt;
04584
04585 ast_mutex_lock(&pvt->lock);
04586
04587 idx = dahdi_get_index(chan, pvt, 0);
04588
04589 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04590 goto out;
04591
04592 #ifdef HAVE_PRI
04593
04594 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04595 goto out;
04596 }
04597 #endif
04598
04599 if (pvt->begindigit) {
04600 x = -1;
04601 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04602 chan->name, digit);
04603 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04604 pvt->dialing = 0;
04605 pvt->begindigit = 0;
04606 }
04607
04608 out:
04609 ast_mutex_unlock(&pvt->lock);
04610
04611 return res;
04612 }
04613
04614 static const char * const events[] = {
04615 "No event",
04616 "On hook",
04617 "Ring/Answered",
04618 "Wink/Flash",
04619 "Alarm",
04620 "No more alarm",
04621 "HDLC Abort",
04622 "HDLC Overrun",
04623 "HDLC Bad FCS",
04624 "Dial Complete",
04625 "Ringer On",
04626 "Ringer Off",
04627 "Hook Transition Complete",
04628 "Bits Changed",
04629 "Pulse Start",
04630 "Timer Expired",
04631 "Timer Ping",
04632 "Polarity Reversal",
04633 "Ring Begin",
04634 };
04635
04636 static struct {
04637 int alarm;
04638 char *name;
04639 } alarms[] = {
04640 { DAHDI_ALARM_RED, "Red Alarm" },
04641 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04642 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04643 { DAHDI_ALARM_RECOVER, "Recovering" },
04644 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04645 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04646 { DAHDI_ALARM_NONE, "None" },
04647 };
04648
04649 static char *alarm2str(int alm)
04650 {
04651 int x;
04652 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04653 if (alarms[x].alarm & alm)
04654 return alarms[x].name;
04655 }
04656 return alm ? "Unknown Alarm" : "No Alarm";
04657 }
04658
04659 static const char *event2str(int event)
04660 {
04661 static char buf[256];
04662 if ((event < (ARRAY_LEN(events))) && (event > -1))
04663 return events[event];
04664 sprintf(buf, "Event %d", event);
04665 return buf;
04666 }
04667
04668 static char *dahdi_sig2str(int sig)
04669 {
04670 static char buf[256];
04671 switch (sig) {
04672 case SIG_EM:
04673 return "E & M Immediate";
04674 case SIG_EMWINK:
04675 return "E & M Wink";
04676 case SIG_EM_E1:
04677 return "E & M E1";
04678 case SIG_FEATD:
04679 return "Feature Group D (DTMF)";
04680 case SIG_FEATDMF:
04681 return "Feature Group D (MF)";
04682 case SIG_FEATDMF_TA:
04683 return "Feature Groud D (MF) Tandem Access";
04684 case SIG_FEATB:
04685 return "Feature Group B (MF)";
04686 case SIG_E911:
04687 return "E911 (MF)";
04688 case SIG_FGC_CAMA:
04689 return "FGC/CAMA (Dialpulse)";
04690 case SIG_FGC_CAMAMF:
04691 return "FGC/CAMA (MF)";
04692 case SIG_FXSLS:
04693 return "FXS Loopstart";
04694 case SIG_FXSGS:
04695 return "FXS Groundstart";
04696 case SIG_FXSKS:
04697 return "FXS Kewlstart";
04698 case SIG_FXOLS:
04699 return "FXO Loopstart";
04700 case SIG_FXOGS:
04701 return "FXO Groundstart";
04702 case SIG_FXOKS:
04703 return "FXO Kewlstart";
04704 case SIG_PRI:
04705 return "ISDN PRI";
04706 case SIG_BRI:
04707 return "ISDN BRI Point to Point";
04708 case SIG_BRI_PTMP:
04709 return "ISDN BRI Point to MultiPoint";
04710 case SIG_SS7:
04711 return "SS7";
04712 case SIG_MFCR2:
04713 return "MFC/R2";
04714 case SIG_SF:
04715 return "SF (Tone) Immediate";
04716 case SIG_SFWINK:
04717 return "SF (Tone) Wink";
04718 case SIG_SF_FEATD:
04719 return "SF (Tone) with Feature Group D (DTMF)";
04720 case SIG_SF_FEATDMF:
04721 return "SF (Tone) with Feature Group D (MF)";
04722 case SIG_SF_FEATB:
04723 return "SF (Tone) with Feature Group B (MF)";
04724 case 0:
04725 return "Pseudo";
04726 default:
04727 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04728 return buf;
04729 }
04730 }
04731
04732 #define sig2str dahdi_sig2str
04733
04734 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04735 {
04736
04737
04738 struct dahdi_confinfo zi;
04739
04740 memset(&zi, 0, sizeof(zi));
04741 zi.chan = 0;
04742
04743 if (slavechannel > 0) {
04744
04745 zi.confmode = DAHDI_CONF_DIGITALMON;
04746 zi.confno = slavechannel;
04747 } else {
04748 if (!idx) {
04749
04750 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04751 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04752 } else
04753 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04754 zi.confno = p->confno;
04755 }
04756 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04757 return 0;
04758 if (c->dfd < 0)
04759 return 0;
04760 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04761 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04762 return -1;
04763 }
04764 if (slavechannel < 1) {
04765 p->confno = zi.confno;
04766 }
04767 c->curconf = zi;
04768 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04769 return 0;
04770 }
04771
04772 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04773 {
04774
04775 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04776 return 1;
04777
04778 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04779 return 1;
04780 return 0;
04781 }
04782
04783 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04784 {
04785 struct dahdi_confinfo zi;
04786 if (
04787 (c->dfd < 0) ||
04788
04789 !isourconf(p, c)
04790
04791 ) return 0;
04792 memset(&zi, 0, sizeof(zi));
04793 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04794 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04795 return -1;
04796 }
04797 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04798 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04799 return 0;
04800 }
04801
04802 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04803 {
04804 int x;
04805 int useslavenative;
04806 struct dahdi_pvt *slave = NULL;
04807
04808 useslavenative = 1;
04809
04810 for (x = 0; x < 3; x++) {
04811
04812
04813 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04814 useslavenative = 0;
04815 }
04816
04817
04818 if (useslavenative) {
04819 for (x = 0; x < MAX_SLAVES; x++) {
04820 if (p->slaves[x]) {
04821 if (slave) {
04822
04823
04824 slave = NULL;
04825 useslavenative = 0;
04826 break;
04827 } else {
04828
04829 slave = p->slaves[x];
04830 }
04831 }
04832 }
04833 }
04834
04835 if (!slave)
04836 useslavenative = 0;
04837 else if (slave->law != p->law) {
04838 useslavenative = 0;
04839 slave = NULL;
04840 }
04841 if (out)
04842 *out = slave;
04843 return useslavenative;
04844 }
04845
04846 static int reset_conf(struct dahdi_pvt *p)
04847 {
04848 p->confno = -1;
04849 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04850 if (p->subs[SUB_REAL].dfd > -1) {
04851 struct dahdi_confinfo zi;
04852
04853 memset(&zi, 0, sizeof(zi));
04854 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04855 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04856 }
04857 return 0;
04858 }
04859
04860 static int update_conf(struct dahdi_pvt *p)
04861 {
04862 int needconf = 0;
04863 int x;
04864 int useslavenative;
04865 struct dahdi_pvt *slave = NULL;
04866
04867 useslavenative = isslavenative(p, &slave);
04868
04869 for (x = 0; x < 3; x++) {
04870
04871 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04872 conf_add(p, &p->subs[x], x, 0);
04873 needconf++;
04874 } else {
04875 conf_del(p, &p->subs[x], x);
04876 }
04877 }
04878
04879
04880 for (x = 0; x < MAX_SLAVES; x++) {
04881 if (p->slaves[x]) {
04882 if (useslavenative)
04883 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04884 else {
04885 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04886 needconf++;
04887 }
04888 }
04889 }
04890
04891 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04892 if (useslavenative)
04893 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04894 else {
04895 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04896 needconf++;
04897 }
04898 }
04899
04900 if (p->master) {
04901 if (isslavenative(p->master, NULL)) {
04902 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04903 } else {
04904 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04905 }
04906 }
04907 if (!needconf) {
04908
04909
04910 p->confno = -1;
04911 }
04912 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04913 return 0;
04914 }
04915
04916 static void dahdi_enable_ec(struct dahdi_pvt *p)
04917 {
04918 int res;
04919 if (!p)
04920 return;
04921 if (p->echocanon) {
04922 ast_debug(1, "Echo cancellation already on\n");
04923 return;
04924 }
04925 if (p->digital) {
04926 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04927 return;
04928 }
04929 if (p->echocancel.head.tap_length) {
04930 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04931 switch (p->sig) {
04932 #if defined(HAVE_PRI)
04933 case SIG_PRI_LIB_HANDLE_CASES:
04934 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04935
04936
04937
04938
04939 return;
04940 }
04941
04942 #endif
04943 #if defined(HAVE_SS7)
04944 case SIG_SS7:
04945 #endif
04946 {
04947 int x = 1;
04948
04949 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04950 if (res)
04951 ast_log(LOG_WARNING,
04952 "Unable to enable audio mode on channel %d (%s)\n",
04953 p->channel, strerror(errno));
04954 }
04955 break;
04956 default:
04957 break;
04958 }
04959 #endif
04960 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04961 if (res) {
04962 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04963 } else {
04964 p->echocanon = 1;
04965 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04966 }
04967 } else
04968 ast_debug(1, "No echo cancellation requested\n");
04969 }
04970
04971 static void dahdi_train_ec(struct dahdi_pvt *p)
04972 {
04973 int x;
04974 int res;
04975
04976 if (p && p->echocanon && p->echotraining) {
04977 x = p->echotraining;
04978 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04979 if (res)
04980 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04981 else
04982 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04983 } else {
04984 ast_debug(1, "No echo training requested\n");
04985 }
04986 }
04987
04988 static void dahdi_disable_ec(struct dahdi_pvt *p)
04989 {
04990 int res;
04991
04992 if (p->echocanon) {
04993 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04994
04995 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04996
04997 if (res)
04998 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04999 else
05000 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
05001 }
05002
05003 p->echocanon = 0;
05004 }
05005
05006
05007 static int drc_sample(int sample, float drc)
05008 {
05009 float neg;
05010 float shallow, steep;
05011 float max = SHRT_MAX;
05012
05013 neg = (sample < 0 ? -1 : 1);
05014 steep = drc*sample;
05015 shallow = neg*(max-max/drc)+(float)sample/drc;
05016 if (abs(steep) < abs(shallow)) {
05017 sample = steep;
05018 }
05019 else {
05020 sample = shallow;
05021 }
05022
05023 return sample;
05024 }
05025
05026
05027 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05028 {
05029 int j;
05030 int k;
05031
05032 float linear_gain = pow(10.0, gain / 20.0);
05033
05034 switch (law) {
05035 case DAHDI_LAW_ALAW:
05036 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05037 if (gain || drc) {
05038 k = AST_ALAW(j);
05039 if (drc) {
05040 k = drc_sample(k, drc);
05041 }
05042 k = (float)k * linear_gain;
05043 if (k > 32767) {
05044 k = 32767;
05045 } else if (k < -32768) {
05046 k = -32768;
05047 }
05048 g->txgain[j] = AST_LIN2A(k);
05049 } else {
05050 g->txgain[j] = j;
05051 }
05052 }
05053 break;
05054 case DAHDI_LAW_MULAW:
05055 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05056 if (gain || drc) {
05057 k = AST_MULAW(j);
05058 if (drc) {
05059 k = drc_sample(k, drc);
05060 }
05061 k = (float)k * linear_gain;
05062 if (k > 32767) {
05063 k = 32767;
05064 } else if (k < -32768) {
05065 k = -32768;
05066 }
05067 g->txgain[j] = AST_LIN2MU(k);
05068
05069 } else {
05070 g->txgain[j] = j;
05071 }
05072 }
05073 break;
05074 }
05075 }
05076
05077 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05078 {
05079 int j;
05080 int k;
05081 float linear_gain = pow(10.0, gain / 20.0);
05082
05083 switch (law) {
05084 case DAHDI_LAW_ALAW:
05085 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05086 if (gain || drc) {
05087 k = AST_ALAW(j);
05088 if (drc) {
05089 k = drc_sample(k, drc);
05090 }
05091 k = (float)k * linear_gain;
05092 if (k > 32767) {
05093 k = 32767;
05094 } else if (k < -32768) {
05095 k = -32768;
05096 }
05097 g->rxgain[j] = AST_LIN2A(k);
05098 } else {
05099 g->rxgain[j] = j;
05100 }
05101 }
05102 break;
05103 case DAHDI_LAW_MULAW:
05104 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05105 if (gain || drc) {
05106 k = AST_MULAW(j);
05107 if (drc) {
05108 k = drc_sample(k, drc);
05109 }
05110 k = (float)k * linear_gain;
05111 if (k > 32767) {
05112 k = 32767;
05113 } else if (k < -32768) {
05114 k = -32768;
05115 }
05116 g->rxgain[j] = AST_LIN2MU(k);
05117 } else {
05118 g->rxgain[j] = j;
05119 }
05120 }
05121 break;
05122 }
05123 }
05124
05125 static int set_actual_txgain(int fd, float gain, float drc, int law)
05126 {
05127 struct dahdi_gains g;
05128 int res;
05129
05130 memset(&g, 0, sizeof(g));
05131 res = ioctl(fd, DAHDI_GETGAINS, &g);
05132 if (res) {
05133 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05134 return res;
05135 }
05136
05137 fill_txgain(&g, gain, drc, law);
05138
05139 return ioctl(fd, DAHDI_SETGAINS, &g);
05140 }
05141
05142 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05143 {
05144 struct dahdi_gains g;
05145 int res;
05146
05147 memset(&g, 0, sizeof(g));
05148 res = ioctl(fd, DAHDI_GETGAINS, &g);
05149 if (res) {
05150 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05151 return res;
05152 }
05153
05154 fill_rxgain(&g, gain, drc, law);
05155
05156 return ioctl(fd, DAHDI_SETGAINS, &g);
05157 }
05158
05159 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05160 {
05161 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05162 }
05163
05164 static int bump_gains(struct dahdi_pvt *p)
05165 {
05166 int res;
05167
05168
05169 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05170 if (res) {
05171 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05172 return -1;
05173 }
05174
05175 return 0;
05176 }
05177
05178 static int restore_gains(struct dahdi_pvt *p)
05179 {
05180 int res;
05181
05182 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05183 if (res) {
05184 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05185 return -1;
05186 }
05187
05188 return 0;
05189 }
05190
05191 static inline int dahdi_set_hook(int fd, int hs)
05192 {
05193 int x, res;
05194
05195 x = hs;
05196 res = ioctl(fd, DAHDI_HOOK, &x);
05197
05198 if (res < 0) {
05199 if (errno == EINPROGRESS)
05200 return 0;
05201 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05202
05203 }
05204
05205 return res;
05206 }
05207
05208 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05209 {
05210 int x, res;
05211
05212 x = muted;
05213 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05214 switch (p->sig) {
05215 #if defined(HAVE_PRI)
05216 case SIG_PRI_LIB_HANDLE_CASES:
05217 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05218
05219 break;
05220 }
05221
05222 #endif
05223 #if defined(HAVE_SS7)
05224 case SIG_SS7:
05225 #endif
05226 {
05227 int y = 1;
05228
05229 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05230 if (res)
05231 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05232 p->channel, strerror(errno));
05233 }
05234 break;
05235 default:
05236 break;
05237 }
05238 #endif
05239 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05240 if (res < 0)
05241 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05242 return res;
05243 }
05244
05245 static int save_conference(struct dahdi_pvt *p)
05246 {
05247 struct dahdi_confinfo c;
05248 int res;
05249 if (p->saveconf.confmode) {
05250 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05251 return -1;
05252 }
05253 p->saveconf.chan = 0;
05254 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05255 if (res) {
05256 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05257 p->saveconf.confmode = 0;
05258 return -1;
05259 }
05260 memset(&c, 0, sizeof(c));
05261 c.confmode = DAHDI_CONF_NORMAL;
05262 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05263 if (res) {
05264 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05265 return -1;
05266 }
05267 ast_debug(1, "Disabled conferencing\n");
05268 return 0;
05269 }
05270
05271 static int restore_conference(struct dahdi_pvt *p)
05272 {
05273 int res;
05274 if (p->saveconf.confmode) {
05275 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05276 p->saveconf.confmode = 0;
05277 if (res) {
05278 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05279 return -1;
05280 }
05281 ast_debug(1, "Restored conferencing\n");
05282 }
05283 return 0;
05284 }
05285
05286 static int send_cwcidspill(struct dahdi_pvt *p)
05287 {
05288 p->callwaitcas = 0;
05289 p->cidcwexpire = 0;
05290 p->cid_suppress_expire = 0;
05291 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05292 return -1;
05293 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05294
05295 p->cidlen += READ_SIZE * 4;
05296 p->cidpos = 0;
05297 send_callerid(p);
05298 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05299 return 0;
05300 }
05301
05302 static int has_voicemail(struct dahdi_pvt *p)
05303 {
05304 int new_msgs;
05305 struct ast_event *event;
05306 char *mailbox, *context;
05307
05308 mailbox = context = ast_strdupa(p->mailbox);
05309 strsep(&context, "@");
05310 if (ast_strlen_zero(context))
05311 context = "default";
05312
05313 event = ast_event_get_cached(AST_EVENT_MWI,
05314 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05315 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05316 AST_EVENT_IE_END);
05317
05318 if (event) {
05319 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05320 ast_event_destroy(event);
05321 } else
05322 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05323
05324 return new_msgs;
05325 }
05326
05327
05328
05329 static int send_callerid(struct dahdi_pvt *p)
05330 {
05331
05332 int res;
05333
05334 if (p->subs[SUB_REAL].linear) {
05335 p->subs[SUB_REAL].linear = 0;
05336 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05337 }
05338 while (p->cidpos < p->cidlen) {
05339 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05340 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05341 if (res < 0) {
05342 if (errno == EAGAIN)
05343 return 0;
05344 else {
05345 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05346 return -1;
05347 }
05348 }
05349 if (!res)
05350 return 0;
05351 p->cidpos += res;
05352 }
05353 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05354 ast_free(p->cidspill);
05355 p->cidspill = NULL;
05356 if (p->callwaitcas) {
05357
05358 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05359 p->cid_suppress_expire = p->cidcwexpire;
05360 } else
05361 restore_conference(p);
05362 return 0;
05363 }
05364
05365 static int dahdi_callwait(struct ast_channel *ast)
05366 {
05367 struct dahdi_pvt *p = ast->tech_pvt;
05368 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05369 if (p->cidspill) {
05370 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05371 ast_free(p->cidspill);
05372 }
05373
05374
05375
05376
05377
05378 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05379 return -1;
05380 save_conference(p);
05381
05382 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05383 if (!p->callwaitrings && p->callwaitingcallerid) {
05384 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05385 p->callwaitcas = 1;
05386 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05387 } else {
05388 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05389 p->callwaitcas = 0;
05390 p->cidlen = 2400 + READ_SIZE * 4;
05391 }
05392 p->cidpos = 0;
05393 send_callerid(p);
05394
05395 return 0;
05396 }
05397
05398 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05399 {
05400 struct dahdi_pvt *p = ast->tech_pvt;
05401 int x, res, mysig;
05402 char dest[256];
05403
05404 ast_mutex_lock(&p->lock);
05405 ast_copy_string(dest, rdest, sizeof(dest));
05406 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05407 if ((ast->_state == AST_STATE_BUSY)) {
05408 p->subs[SUB_REAL].needbusy = 1;
05409 ast_mutex_unlock(&p->lock);
05410 return 0;
05411 }
05412 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05413 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05414 ast_mutex_unlock(&p->lock);
05415 return -1;
05416 }
05417 p->waitingfordt.tv_sec = 0;
05418 p->dialednone = 0;
05419 if ((p->radio || (p->oprmode < 0)))
05420 {
05421
05422 ast_setstate(ast, AST_STATE_UP);
05423 ast_mutex_unlock(&p->lock);
05424 return 0;
05425 }
05426 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05427 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05428 if (res)
05429 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05430 p->outgoing = 1;
05431
05432 if (IS_DIGITAL(ast->transfercapability)){
05433 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05434 } else {
05435 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05436 }
05437
05438 #ifdef HAVE_PRI
05439 if (dahdi_sig_pri_lib_handles(p->sig)) {
05440 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05441 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05442 ast_mutex_unlock(&p->lock);
05443 return res;
05444 }
05445 #endif
05446
05447 #if defined(HAVE_SS7)
05448 if (p->sig == SIG_SS7) {
05449 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05450 ast_mutex_unlock(&p->lock);
05451 return res;
05452 }
05453 #endif
05454
05455
05456 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05457 p->callwaitrings = 0;
05458 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05459 ast_mutex_unlock(&p->lock);
05460 return res;
05461 }
05462
05463 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05464 switch (mysig) {
05465 case 0:
05466
05467 ast_setstate(ast, AST_STATE_UP);
05468 break;
05469 case SIG_MFCR2:
05470 break;
05471 default:
05472 ast_debug(1, "not yet implemented\n");
05473 ast_mutex_unlock(&p->lock);
05474 return -1;
05475 }
05476
05477 #ifdef HAVE_OPENR2
05478 if (p->mfcr2) {
05479 openr2_calling_party_category_t chancat;
05480 int callres = 0;
05481 char *c, *l;
05482
05483
05484 p->dialdest[0] = '\0';
05485
05486 c = strchr(dest, '/');
05487 if (c) {
05488 c++;
05489 } else {
05490 c = "";
05491 }
05492 if (!p->hidecallerid) {
05493 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05494 } else {
05495 l = NULL;
05496 }
05497 if (strlen(c) < p->stripmsd) {
05498 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05499 ast_mutex_unlock(&p->lock);
05500 return -1;
05501 }
05502 p->dialing = 1;
05503 chancat = dahdi_r2_get_channel_category(ast);
05504 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05505 if (-1 == callres) {
05506 ast_mutex_unlock(&p->lock);
05507 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05508 return -1;
05509 }
05510 p->mfcr2_call_accepted = 0;
05511 p->mfcr2_progress = 0;
05512 ast_setstate(ast, AST_STATE_DIALING);
05513 }
05514 #endif
05515 ast_mutex_unlock(&p->lock);
05516 return 0;
05517 }
05518
05519
05520
05521
05522
05523
05524
05525
05526
05527
05528
05529
05530
05531
05532
05533
05534 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05535 {
05536 struct dahdi_pvt *cur;
05537
05538 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05539
05540
05541 for (cur = iflist; cur; cur = cur->next) {
05542 if (pvt->channel < cur->channel) {
05543
05544 pvt->prev = cur->prev;
05545 pvt->next = cur;
05546 if (cur->prev) {
05547
05548 cur->prev->next = pvt;
05549 } else {
05550
05551 iflist = pvt;
05552 }
05553 cur->prev = pvt;
05554 return;
05555 }
05556 }
05557
05558
05559 pvt->prev = ifend;
05560 pvt->next = NULL;
05561 if (ifend) {
05562 ifend->next = pvt;
05563 }
05564 ifend = pvt;
05565 if (!iflist) {
05566
05567 iflist = pvt;
05568 }
05569 }
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583
05584 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05585 {
05586
05587 if (pvt->prev) {
05588 pvt->prev->next = pvt->next;
05589 } else if (iflist == pvt) {
05590
05591 iflist = pvt->next;
05592 }
05593
05594
05595 if (pvt->next) {
05596 pvt->next->prev = pvt->prev;
05597 } else if (ifend == pvt) {
05598
05599 ifend = pvt->prev;
05600 }
05601
05602
05603 pvt->which_iflist = DAHDI_IFLIST_NONE;
05604 pvt->prev = NULL;
05605 pvt->next = NULL;
05606 }
05607
05608 #if defined(HAVE_PRI)
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618
05619
05620
05621
05622
05623
05624
05625 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05626 {
05627 struct dahdi_pvt *cur;
05628
05629 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05630
05631
05632 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05633 if (pvt->channel < cur->channel) {
05634
05635 pvt->prev = cur->prev;
05636 pvt->next = cur;
05637 if (cur->prev) {
05638
05639 cur->prev->next = pvt;
05640 } else {
05641
05642 pri->no_b_chan_iflist = pvt;
05643 }
05644 cur->prev = pvt;
05645 return;
05646 }
05647 }
05648
05649
05650 pvt->prev = pri->no_b_chan_end;
05651 pvt->next = NULL;
05652 if (pri->no_b_chan_end) {
05653 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05654 }
05655 pri->no_b_chan_end = pvt;
05656 if (!pri->no_b_chan_iflist) {
05657
05658 pri->no_b_chan_iflist = pvt;
05659 }
05660 }
05661 #endif
05662
05663 #if defined(HAVE_PRI)
05664
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05679 {
05680
05681 if (pvt->prev) {
05682 pvt->prev->next = pvt->next;
05683 } else if (pri->no_b_chan_iflist == pvt) {
05684
05685 pri->no_b_chan_iflist = pvt->next;
05686 }
05687
05688
05689 if (pvt->next) {
05690 pvt->next->prev = pvt->prev;
05691 } else if (pri->no_b_chan_end == pvt) {
05692
05693 pri->no_b_chan_end = pvt->prev;
05694 }
05695
05696
05697 pvt->which_iflist = DAHDI_IFLIST_NONE;
05698 pvt->prev = NULL;
05699 pvt->next = NULL;
05700 }
05701 #endif
05702
05703 #if defined(HAVE_PRI)
05704
05705
05706
05707
05708
05709
05710
05711
05712
05713 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05714 {
05715 unsigned idx;
05716 struct sig_pri_span *pri;
05717
05718 pri = pvt->pri;
05719 if (!pri) {
05720
05721 return;
05722 }
05723 ast_mutex_lock(&pri->lock);
05724 for (idx = 0; idx < pri->numchans; ++idx) {
05725 if (pri->pvts[idx] == pvt->sig_pvt) {
05726 pri->pvts[idx] = NULL;
05727 ast_mutex_unlock(&pri->lock);
05728 return;
05729 }
05730 }
05731 ast_mutex_unlock(&pri->lock);
05732 }
05733 #endif
05734
05735 #if defined(HAVE_SS7)
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05746 {
05747 unsigned idx;
05748 struct sig_ss7_linkset *ss7;
05749
05750 ss7 = pvt->ss7;
05751 if (!ss7) {
05752
05753 return;
05754 }
05755 ast_mutex_lock(&ss7->lock);
05756 for (idx = 0; idx < ss7->numchans; ++idx) {
05757 if (ss7->pvts[idx] == pvt->sig_pvt) {
05758 ss7->pvts[idx] = NULL;
05759 ast_mutex_unlock(&ss7->lock);
05760 return;
05761 }
05762 }
05763 ast_mutex_unlock(&ss7->lock);
05764 }
05765 #endif
05766
05767 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05768 {
05769 if (cur->next && cur->next->span == cur->span) {
05770 return cur->next;
05771 } else if (cur->prev && cur->prev->span == cur->span) {
05772 return cur->prev;
05773 }
05774
05775 return NULL;
05776 }
05777
05778 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05779 {
05780 struct dahdi_pvt *p = pvt;
05781
05782 if (p->manages_span_alarms) {
05783 struct dahdi_pvt *next = find_next_iface_in_span(p);
05784 if (next) {
05785 next->manages_span_alarms = 1;
05786 }
05787 }
05788
05789
05790 #if defined(HAVE_PRI)
05791 dahdi_unlink_pri_pvt(p);
05792 #endif
05793 #if defined(HAVE_SS7)
05794 dahdi_unlink_ss7_pvt(p);
05795 #endif
05796 switch (pvt->which_iflist) {
05797 case DAHDI_IFLIST_NONE:
05798 break;
05799 case DAHDI_IFLIST_MAIN:
05800 dahdi_iflist_extract(p);
05801 break;
05802 #if defined(HAVE_PRI)
05803 case DAHDI_IFLIST_NO_B_CHAN:
05804 if (p->pri) {
05805 dahdi_nobch_extract(p->pri, p);
05806 }
05807 break;
05808 #endif
05809 }
05810
05811 if (p->sig_pvt) {
05812 if (analog_lib_handles(p->sig, 0, 0)) {
05813 analog_delete(p->sig_pvt);
05814 }
05815 switch (p->sig) {
05816 #if defined(HAVE_PRI)
05817 case SIG_PRI_LIB_HANDLE_CASES:
05818 sig_pri_chan_delete(p->sig_pvt);
05819 break;
05820 #endif
05821 #if defined(HAVE_SS7)
05822 case SIG_SS7:
05823 sig_ss7_chan_delete(p->sig_pvt);
05824 break;
05825 #endif
05826 default:
05827 break;
05828 }
05829 }
05830 ast_free(p->cidspill);
05831 if (p->use_smdi)
05832 ast_smdi_interface_unref(p->smdi_iface);
05833 if (p->mwi_event_sub)
05834 ast_event_unsubscribe(p->mwi_event_sub);
05835 if (p->vars) {
05836 ast_variables_destroy(p->vars);
05837 }
05838 if (p->cc_params) {
05839 ast_cc_config_params_destroy(p->cc_params);
05840 }
05841 ast_mutex_destroy(&p->lock);
05842 dahdi_close_sub(p, SUB_REAL);
05843 if (p->owner)
05844 p->owner->tech_pvt = NULL;
05845 ast_free(p);
05846 }
05847
05848 static void destroy_channel(struct dahdi_pvt *cur, int now)
05849 {
05850 int i;
05851
05852 if (!now) {
05853
05854 if (cur->owner) {
05855 return;
05856 }
05857 for (i = 0; i < 3; i++) {
05858 if (cur->subs[i].owner) {
05859 return;
05860 }
05861 }
05862 }
05863 destroy_dahdi_pvt(cur);
05864 }
05865
05866 static void destroy_all_channels(void)
05867 {
05868 int chan;
05869 #if defined(HAVE_PRI)
05870 unsigned span;
05871 struct sig_pri_span *pri;
05872 #endif
05873 struct dahdi_pvt *p;
05874
05875 while (num_restart_pending) {
05876 usleep(1);
05877 }
05878
05879 ast_mutex_lock(&iflock);
05880
05881 while (iflist) {
05882 p = iflist;
05883
05884 chan = p->channel;
05885 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05886 {
05887 char db_chan_name[20];
05888 char db_answer[5];
05889 char state;
05890 int why = -1;
05891
05892 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05893 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05894 sscanf(db_answer, "%1c:%30d", &state, &why);
05895 }
05896 if (!why) {
05897
05898 ast_db_del(db_chan_name, SRVST_DBKEY);
05899 }
05900 }
05901 #endif
05902
05903 destroy_dahdi_pvt(p);
05904 ast_verb(3, "Unregistered channel %d\n", chan);
05905 }
05906 ifcount = 0;
05907 ast_mutex_unlock(&iflock);
05908
05909 #if defined(HAVE_PRI)
05910
05911 for (span = 0; span < NUM_SPANS; ++span) {
05912 if (!pris[span].dchannels[0]) {
05913 break;
05914 }
05915 pri = &pris[span].pri;
05916 ast_mutex_lock(&pri->lock);
05917 while (pri->no_b_chan_iflist) {
05918 p = pri->no_b_chan_iflist;
05919
05920
05921 destroy_dahdi_pvt(p);
05922 }
05923 ast_mutex_unlock(&pri->lock);
05924 }
05925 #endif
05926 }
05927
05928 #if defined(HAVE_PRI)
05929 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05930
05931 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05932 {
05933
05934 struct dahdi_pvt *p;
05935
05936 if (ast_strlen_zero(digits)) {
05937 ast_debug(1, "No digit string sent to application!\n");
05938 return -1;
05939 }
05940
05941 p = (struct dahdi_pvt *)chan->tech_pvt;
05942
05943 if (!p) {
05944 ast_debug(1, "Unable to find technology private\n");
05945 return -1;
05946 }
05947
05948 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05949
05950 return 0;
05951 }
05952 #endif
05953
05954 #if defined(HAVE_PRI)
05955 #if defined(HAVE_PRI_PROG_W_CAUSE)
05956 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05957
05958 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05959 {
05960
05961 struct dahdi_pvt *pvt;
05962 char *parse;
05963 int res;
05964 AST_DECLARE_APP_ARGS(args,
05965 AST_APP_ARG(destination);
05966 AST_APP_ARG(original);
05967 AST_APP_ARG(reason);
05968 );
05969
05970 if (ast_strlen_zero(data)) {
05971 ast_log(LOG_DEBUG, "No data sent to application!\n");
05972 return -1;
05973 }
05974 if (chan->tech != &dahdi_tech) {
05975 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05976 return -1;
05977 }
05978 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05979 if (!pvt) {
05980 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05981 return -1;
05982 }
05983 switch (pvt->sig) {
05984 case SIG_PRI_LIB_HANDLE_CASES:
05985 break;
05986 default:
05987 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05988 chan->name);
05989 return -1;
05990 }
05991
05992 parse = ast_strdupa(data);
05993 AST_STANDARD_APP_ARGS(args, parse);
05994
05995 if (ast_strlen_zero(args.destination)) {
05996 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05997 return -1;
05998 }
05999
06000 if (ast_strlen_zero(args.original)) {
06001 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
06002 args.original = NULL;
06003 }
06004
06005 if (ast_strlen_zero(args.reason)) {
06006 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
06007 args.reason = NULL;
06008 }
06009
06010 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
06011 args.destination, args.original, args.reason);
06012 if (!res) {
06013
06014
06015
06016
06017 ast_safe_sleep(chan, 5000);
06018 }
06019
06020 return -1;
06021 }
06022 #endif
06023 #endif
06024
06025 #if defined(HAVE_OPENR2)
06026 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06027
06028 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06029 {
06030
06031 openr2_call_mode_t accept_mode;
06032 int res, timeout, maxloops;
06033 struct ast_frame *f;
06034 struct dahdi_pvt *p;
06035 char *parse;
06036 AST_DECLARE_APP_ARGS(args,
06037 AST_APP_ARG(charge);
06038 );
06039
06040 if (ast_strlen_zero(data)) {
06041 ast_log(LOG_DEBUG, "No data sent to application!\n");
06042 return -1;
06043 }
06044
06045 if (chan->tech != &dahdi_tech) {
06046 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06047 return -1;
06048 }
06049
06050 p = (struct dahdi_pvt *)chan->tech_pvt;
06051 if (!p) {
06052 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06053 return -1;
06054 }
06055
06056 parse = ast_strdupa(data);
06057 AST_STANDARD_APP_ARGS(args, parse);
06058
06059 if (ast_strlen_zero(args.charge)) {
06060 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06061 return -1;
06062 }
06063
06064 ast_mutex_lock(&p->lock);
06065 if (!p->mfcr2 || !p->mfcr2call) {
06066 ast_mutex_unlock(&p->lock);
06067 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06068 return -1;
06069 }
06070
06071 if (p->mfcr2_call_accepted) {
06072 ast_mutex_unlock(&p->lock);
06073 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06074 return 0;
06075 }
06076 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06077 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06078 ast_mutex_unlock(&p->lock);
06079 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06080 return -1;
06081 }
06082 ast_mutex_unlock(&p->lock);
06083
06084 res = 0;
06085 timeout = 100;
06086 maxloops = 50;
06087
06088 while (maxloops > 0) {
06089 maxloops--;
06090 if (ast_check_hangup(chan)) {
06091 break;
06092 }
06093 res = ast_waitfor(chan, timeout);
06094 if (res < 0) {
06095 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06096 res = -1;
06097 break;
06098 }
06099 if (res == 0) {
06100 continue;
06101 }
06102 res = 0;
06103 f = ast_read(chan);
06104 if (!f) {
06105 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06106 res = -1;
06107 break;
06108 }
06109 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06110 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06111 ast_frfree(f);
06112 res = -1;
06113 break;
06114 }
06115 ast_frfree(f);
06116 ast_mutex_lock(&p->lock);
06117 if (p->mfcr2_call_accepted) {
06118 ast_mutex_unlock(&p->lock);
06119 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06120 break;
06121 }
06122 ast_mutex_unlock(&p->lock);
06123 }
06124 if (res == -1) {
06125 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06126 }
06127 return res;
06128 }
06129
06130 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06131 {
06132 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06133 switch (cause) {
06134 case AST_CAUSE_USER_BUSY:
06135 case AST_CAUSE_CALL_REJECTED:
06136 case AST_CAUSE_INTERWORKING:
06137 r2cause = OR2_CAUSE_BUSY_NUMBER;
06138 break;
06139
06140 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06141 case AST_CAUSE_SWITCH_CONGESTION:
06142 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06143 break;
06144
06145 case AST_CAUSE_UNALLOCATED:
06146 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06147 break;
06148
06149 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06150 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06151 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06152 break;
06153
06154 case AST_CAUSE_NO_ANSWER:
06155 case AST_CAUSE_NO_USER_RESPONSE:
06156 r2cause = OR2_CAUSE_NO_ANSWER;
06157 break;
06158
06159 default:
06160 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06161 break;
06162 }
06163 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06164 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06165 return r2cause;
06166 }
06167 #endif
06168
06169 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06170 {
06171 if (p->bufferoverrideinuse) {
06172
06173 struct dahdi_bufferinfo bi = {
06174 .txbufpolicy = p->buf_policy,
06175 .rxbufpolicy = p->buf_policy,
06176 .bufsize = p->bufsize,
06177 .numbufs = p->buf_no
06178 };
06179 int bpres;
06180
06181 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06182 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06183 }
06184 p->bufferoverrideinuse = 0;
06185 return bpres;
06186 }
06187
06188 return -1;
06189 }
06190
06191 static int dahdi_hangup(struct ast_channel *ast)
06192 {
06193 int res = 0;
06194 int idx,x;
06195 int law;
06196
06197 struct dahdi_pvt *p = ast->tech_pvt;
06198 struct dahdi_params par;
06199
06200 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06201 if (!ast->tech_pvt) {
06202 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06203 return 0;
06204 }
06205
06206 ast_mutex_lock(&p->lock);
06207 p->exten[0] = '\0';
06208 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06209 dahdi_confmute(p, 0);
06210 restore_gains(p);
06211 p->ignoredtmf = 0;
06212 p->waitingfordt.tv_sec = 0;
06213
06214 res = analog_hangup(p->sig_pvt, ast);
06215 revert_fax_buffers(p, ast);
06216
06217 goto hangup_out;
06218 } else {
06219 p->cid_num[0] = '\0';
06220 p->cid_name[0] = '\0';
06221 p->cid_subaddr[0] = '\0';
06222 }
06223
06224 #if defined(HAVE_PRI)
06225 if (dahdi_sig_pri_lib_handles(p->sig)) {
06226 x = 1;
06227 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06228
06229 dahdi_confmute(p, 0);
06230 p->muting = 0;
06231 restore_gains(p);
06232 if (p->dsp) {
06233 ast_dsp_free(p->dsp);
06234 p->dsp = NULL;
06235 }
06236 p->ignoredtmf = 0;
06237
06238
06239 p->subs[SUB_REAL].owner = NULL;
06240 p->subs[SUB_REAL].needbusy = 0;
06241 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06242
06243 p->owner = NULL;
06244 p->cid_tag[0] = '\0';
06245 p->ringt = 0;
06246 p->distinctivering = 0;
06247 p->confirmanswer = 0;
06248 p->outgoing = 0;
06249 p->digital = 0;
06250 p->faxhandled = 0;
06251 p->pulsedial = 0;
06252
06253 revert_fax_buffers(p, ast);
06254
06255 p->law = p->law_default;
06256 law = p->law_default;
06257 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06258 if (res < 0) {
06259 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06260 p->channel, strerror(errno));
06261 }
06262
06263 sig_pri_hangup(p->sig_pvt, ast);
06264
06265 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06266 dahdi_disable_ec(p);
06267
06268 x = 0;
06269 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06270 p->didtdd = 0;
06271
06272 p->rdnis[0] = '\0';
06273 update_conf(p);
06274 reset_conf(p);
06275
06276
06277 x = 0;
06278 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06279
06280 if (num_restart_pending == 0) {
06281 restart_monitor();
06282 }
06283 goto hangup_out;
06284 }
06285 #endif
06286
06287 #if defined(HAVE_SS7)
06288 if (p->sig == SIG_SS7) {
06289 x = 1;
06290 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06291
06292 dahdi_confmute(p, 0);
06293 p->muting = 0;
06294 restore_gains(p);
06295 if (p->dsp) {
06296 ast_dsp_free(p->dsp);
06297 p->dsp = NULL;
06298 }
06299 p->ignoredtmf = 0;
06300
06301
06302 p->subs[SUB_REAL].owner = NULL;
06303 p->subs[SUB_REAL].needbusy = 0;
06304 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06305
06306 p->owner = NULL;
06307 p->ringt = 0;
06308 p->distinctivering = 0;
06309 p->confirmanswer = 0;
06310 p->outgoing = 0;
06311 p->digital = 0;
06312 p->faxhandled = 0;
06313 p->pulsedial = 0;
06314
06315 revert_fax_buffers(p, ast);
06316
06317 p->law = p->law_default;
06318 law = p->law_default;
06319 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06320 if (res < 0) {
06321 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06322 p->channel, strerror(errno));
06323 }
06324
06325 sig_ss7_hangup(p->sig_pvt, ast);
06326
06327 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06328 dahdi_disable_ec(p);
06329
06330 x = 0;
06331 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06332 p->didtdd = 0;
06333
06334 update_conf(p);
06335 reset_conf(p);
06336
06337
06338 x = 0;
06339 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06340
06341 if (num_restart_pending == 0) {
06342 restart_monitor();
06343 }
06344 goto hangup_out;
06345 }
06346 #endif
06347
06348 idx = dahdi_get_index(ast, p, 1);
06349
06350 dahdi_confmute(p, 0);
06351 p->muting = 0;
06352 restore_gains(p);
06353 if (p->origcid_num) {
06354 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06355 ast_free(p->origcid_num);
06356 p->origcid_num = NULL;
06357 }
06358 if (p->origcid_name) {
06359 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06360 ast_free(p->origcid_name);
06361 p->origcid_name = NULL;
06362 }
06363 if (p->dsp)
06364 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06365
06366 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06367 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06368 p->ignoredtmf = 0;
06369
06370 if (idx > -1) {
06371
06372 p->subs[idx].owner = NULL;
06373 p->subs[idx].needanswer = 0;
06374 p->subs[idx].needflash = 0;
06375 p->subs[idx].needringing = 0;
06376 p->subs[idx].needbusy = 0;
06377 p->subs[idx].needcongestion = 0;
06378 p->subs[idx].linear = 0;
06379 p->polarity = POLARITY_IDLE;
06380 dahdi_setlinear(p->subs[idx].dfd, 0);
06381 if (idx == SUB_REAL) {
06382 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06383 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06384 if (p->subs[SUB_CALLWAIT].inthreeway) {
06385
06386 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06387
06388 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06389 unalloc_sub(p, SUB_CALLWAIT);
06390 p->owner = NULL;
06391 } else {
06392
06393 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06394 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06395 unalloc_sub(p, SUB_THREEWAY);
06396 if (p->subs[SUB_REAL].inthreeway) {
06397
06398
06399 ast_debug(1, "Call was complete, setting owner to former third call\n");
06400 p->owner = p->subs[SUB_REAL].owner;
06401 } else {
06402
06403 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06404 p->owner = NULL;
06405 }
06406 p->subs[SUB_REAL].inthreeway = 0;
06407 }
06408 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06409
06410 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06411 unalloc_sub(p, SUB_CALLWAIT);
06412 p->owner = p->subs[SUB_REAL].owner;
06413 if (p->owner->_state != AST_STATE_UP)
06414 p->subs[SUB_REAL].needanswer = 1;
06415 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06416 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06417 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06418 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06419 unalloc_sub(p, SUB_THREEWAY);
06420 if (p->subs[SUB_REAL].inthreeway) {
06421
06422
06423 ast_debug(1, "Call was complete, setting owner to former third call\n");
06424 p->owner = p->subs[SUB_REAL].owner;
06425 } else {
06426
06427 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06428 p->owner = NULL;
06429 }
06430 p->subs[SUB_REAL].inthreeway = 0;
06431 }
06432 } else if (idx == SUB_CALLWAIT) {
06433
06434 if (p->subs[SUB_CALLWAIT].inthreeway) {
06435
06436
06437 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06438 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06439 S_OR(p->mohsuggest, NULL),
06440 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06441 }
06442 p->subs[SUB_THREEWAY].inthreeway = 0;
06443
06444 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06445 unalloc_sub(p, SUB_THREEWAY);
06446 } else
06447 unalloc_sub(p, SUB_CALLWAIT);
06448 } else if (idx == SUB_THREEWAY) {
06449 if (p->subs[SUB_CALLWAIT].inthreeway) {
06450
06451
06452 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06453 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06454 S_OR(p->mohsuggest, NULL),
06455 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06456 }
06457 p->subs[SUB_CALLWAIT].inthreeway = 0;
06458 }
06459 p->subs[SUB_REAL].inthreeway = 0;
06460
06461
06462 unalloc_sub(p, SUB_THREEWAY);
06463 } else {
06464
06465 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06466 }
06467 }
06468
06469 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06470 p->owner = NULL;
06471 p->ringt = 0;
06472 p->distinctivering = 0;
06473 p->confirmanswer = 0;
06474 p->outgoing = 0;
06475 p->digital = 0;
06476 p->faxhandled = 0;
06477 p->pulsedial = 0;
06478 if (p->dsp) {
06479 ast_dsp_free(p->dsp);
06480 p->dsp = NULL;
06481 }
06482
06483 revert_fax_buffers(p, ast);
06484
06485 p->law = p->law_default;
06486 law = p->law_default;
06487 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06488 if (res < 0)
06489 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06490
06491 #ifdef HAVE_OPENR2
06492 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06493 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06494
06495 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06496 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06497 } else {
06498 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06499 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06500 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06501 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06502 dahdi_r2_disconnect_call(p, r2cause);
06503 }
06504 } else if (p->mfcr2call) {
06505 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06506
06507
06508
06509
06510 p->mfcr2call = 0;
06511 }
06512 #endif
06513 switch (p->sig) {
06514 case SIG_SS7:
06515 case SIG_MFCR2:
06516 case SIG_PRI_LIB_HANDLE_CASES:
06517 case 0:
06518 break;
06519 default:
06520 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06521 break;
06522 }
06523 if (res < 0) {
06524 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06525 }
06526 switch (p->sig) {
06527 case SIG_FXOGS:
06528 case SIG_FXOLS:
06529 case SIG_FXOKS:
06530 memset(&par, 0, sizeof(par));
06531 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06532 if (!res) {
06533 struct analog_pvt *analog_p = p->sig_pvt;
06534 #if 0
06535 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06536 #endif
06537
06538 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06539 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06540 else
06541 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06542 analog_p->fxsoffhookstate = par.rxisoffhook;
06543 }
06544 break;
06545 case SIG_FXSGS:
06546 case SIG_FXSLS:
06547 case SIG_FXSKS:
06548
06549
06550 if (ast->_state != AST_STATE_RESERVED) {
06551 time(&p->guardtime);
06552 p->guardtime += 2;
06553 }
06554 break;
06555 default:
06556 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06557 break;
06558 }
06559 if (p->sig)
06560 dahdi_disable_ec(p);
06561 x = 0;
06562 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06563 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06564 p->didtdd = 0;
06565 p->callwaitcas = 0;
06566 p->callwaiting = p->permcallwaiting;
06567 p->hidecallerid = p->permhidecallerid;
06568 p->waitingfordt.tv_sec = 0;
06569 p->dialing = 0;
06570 p->rdnis[0] = '\0';
06571 update_conf(p);
06572 reset_conf(p);
06573
06574 switch (p->sig) {
06575 case SIG_PRI_LIB_HANDLE_CASES:
06576 case SIG_SS7:
06577 x = 0;
06578 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06579 break;
06580 default:
06581 break;
06582 }
06583 if (num_restart_pending == 0)
06584 restart_monitor();
06585 }
06586
06587 p->callwaitingrepeat = 0;
06588 p->cidcwexpire = 0;
06589 p->cid_suppress_expire = 0;
06590 p->oprmode = 0;
06591 hangup_out:
06592 ast->tech_pvt = NULL;
06593 ast_free(p->cidspill);
06594 p->cidspill = NULL;
06595
06596 ast_mutex_unlock(&p->lock);
06597 ast_verb(3, "Hungup '%s'\n", ast->name);
06598
06599 ast_mutex_lock(&iflock);
06600 if (p->restartpending) {
06601 num_restart_pending--;
06602 }
06603
06604 if (p->destroy) {
06605 destroy_channel(p, 0);
06606 }
06607 ast_mutex_unlock(&iflock);
06608
06609 ast_module_unref(ast_module_info->self);
06610 return 0;
06611 }
06612
06613 static int dahdi_answer(struct ast_channel *ast)
06614 {
06615 struct dahdi_pvt *p = ast->tech_pvt;
06616 int res = 0;
06617 int idx;
06618 ast_setstate(ast, AST_STATE_UP);
06619 ast_mutex_lock(&p->lock);
06620 idx = dahdi_get_index(ast, p, 0);
06621 if (idx < 0)
06622 idx = SUB_REAL;
06623
06624 if ((p->radio || (p->oprmode < 0))) {
06625 ast_mutex_unlock(&p->lock);
06626 return 0;
06627 }
06628
06629 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06630 res = analog_answer(p->sig_pvt, ast);
06631 ast_mutex_unlock(&p->lock);
06632 return res;
06633 }
06634
06635 switch (p->sig) {
06636 #if defined(HAVE_PRI)
06637 case SIG_PRI_LIB_HANDLE_CASES:
06638 res = sig_pri_answer(p->sig_pvt, ast);
06639 break;
06640 #endif
06641 #if defined(HAVE_SS7)
06642 case SIG_SS7:
06643 res = sig_ss7_answer(p->sig_pvt, ast);
06644 break;
06645 #endif
06646 #ifdef HAVE_OPENR2
06647 case SIG_MFCR2:
06648 if (!p->mfcr2_call_accepted) {
06649
06650
06651 p->mfcr2_answer_pending = 1;
06652 if (p->mfcr2_charge_calls) {
06653 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06654 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06655 } else {
06656 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06657 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06658 }
06659 } else {
06660 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06661 dahdi_r2_answer(p);
06662 }
06663 break;
06664 #endif
06665 case 0:
06666 ast_mutex_unlock(&p->lock);
06667 return 0;
06668 default:
06669 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06670 res = -1;
06671 break;
06672 }
06673 ast_mutex_unlock(&p->lock);
06674 return res;
06675 }
06676
06677 static void disable_dtmf_detect(struct dahdi_pvt *p)
06678 {
06679 int val = 0;
06680
06681 p->ignoredtmf = 1;
06682
06683 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06684
06685 if (!p->hardwaredtmf && p->dsp) {
06686 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06687 ast_dsp_set_features(p->dsp, p->dsp_features);
06688 }
06689 }
06690
06691 static void enable_dtmf_detect(struct dahdi_pvt *p)
06692 {
06693 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06694
06695 if (p->channel == CHAN_PSEUDO)
06696 return;
06697
06698 p->ignoredtmf = 0;
06699
06700 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06701
06702 if (!p->hardwaredtmf && p->dsp) {
06703 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06704 ast_dsp_set_features(p->dsp, p->dsp_features);
06705 }
06706 }
06707
06708 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06709 {
06710 char *cp;
06711 struct dahdi_pvt *p = chan->tech_pvt;
06712
06713
06714 if (!p || !data || (*datalen < 1)) {
06715 errno = EINVAL;
06716 return -1;
06717 }
06718
06719 switch (option) {
06720 case AST_OPTION_DIGIT_DETECT:
06721 cp = (char *) data;
06722 *cp = p->ignoredtmf ? 0 : 1;
06723 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06724 break;
06725 case AST_OPTION_FAX_DETECT:
06726 cp = (char *) data;
06727 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06728 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06729 break;
06730 case AST_OPTION_CC_AGENT_TYPE:
06731 #if defined(HAVE_PRI)
06732 #if defined(HAVE_PRI_CCSS)
06733 if (dahdi_sig_pri_lib_handles(p->sig)) {
06734 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06735 break;
06736 }
06737 #endif
06738 #endif
06739 return -1;
06740 default:
06741 return -1;
06742 }
06743
06744 errno = 0;
06745
06746 return 0;
06747 }
06748
06749 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06750 {
06751 char *cp;
06752 signed char *scp;
06753 int x;
06754 int idx;
06755 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06756 struct oprmode *oprmode;
06757
06758
06759
06760 if (!p || !data || (datalen < 1)) {
06761 errno = EINVAL;
06762 return -1;
06763 }
06764
06765 switch (option) {
06766 case AST_OPTION_TXGAIN:
06767 scp = (signed char *) data;
06768 idx = dahdi_get_index(chan, p, 0);
06769 if (idx < 0) {
06770 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06771 return -1;
06772 }
06773 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06774 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06775 case AST_OPTION_RXGAIN:
06776 scp = (signed char *) data;
06777 idx = dahdi_get_index(chan, p, 0);
06778 if (idx < 0) {
06779 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06780 return -1;
06781 }
06782 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06783 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06784 case AST_OPTION_TONE_VERIFY:
06785 if (!p->dsp)
06786 break;
06787 cp = (char *) data;
06788 switch (*cp) {
06789 case 1:
06790 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06791 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06792 break;
06793 case 2:
06794 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06795 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06796 break;
06797 default:
06798 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06799 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06800 break;
06801 }
06802 break;
06803 case AST_OPTION_TDD:
06804
06805 cp = (char *) data;
06806 p->mate = 0;
06807 if (!*cp) {
06808 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06809 if (p->tdd)
06810 tdd_free(p->tdd);
06811 p->tdd = 0;
06812 break;
06813 }
06814 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06815 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06816 dahdi_disable_ec(p);
06817
06818 if (!p->didtdd) {
06819 unsigned char mybuf[41000];
06820 unsigned char *buf;
06821 int size, res, fd, len;
06822 struct pollfd fds[1];
06823
06824 buf = mybuf;
06825 memset(buf, 0x7f, sizeof(mybuf));
06826 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06827 len = 40000;
06828 idx = dahdi_get_index(chan, p, 0);
06829 if (idx < 0) {
06830 ast_log(LOG_WARNING, "No index in TDD?\n");
06831 return -1;
06832 }
06833 fd = p->subs[idx].dfd;
06834 while (len) {
06835 if (ast_check_hangup(chan))
06836 return -1;
06837 size = len;
06838 if (size > READ_SIZE)
06839 size = READ_SIZE;
06840 fds[0].fd = fd;
06841 fds[0].events = POLLPRI | POLLOUT;
06842 fds[0].revents = 0;
06843 res = poll(fds, 1, -1);
06844 if (!res) {
06845 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06846 continue;
06847 }
06848
06849 if (fds[0].revents & POLLPRI)
06850 return -1;
06851 if (!(fds[0].revents & POLLOUT)) {
06852 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06853 continue;
06854 }
06855 res = write(fd, buf, size);
06856 if (res != size) {
06857 if (res == -1) return -1;
06858 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06859 break;
06860 }
06861 len -= size;
06862 buf += size;
06863 }
06864 p->didtdd = 1;
06865 }
06866 if (*cp == 2) {
06867 if (p->tdd)
06868 tdd_free(p->tdd);
06869 p->tdd = 0;
06870 p->mate = 1;
06871 break;
06872 }
06873 if (!p->tdd) {
06874 p->tdd = tdd_new();
06875 }
06876 break;
06877 case AST_OPTION_RELAXDTMF:
06878 if (!p->dsp)
06879 break;
06880 cp = (char *) data;
06881 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06882 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06883 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06884 break;
06885 case AST_OPTION_AUDIO_MODE:
06886 #if defined(HAVE_PRI)
06887 if (dahdi_sig_pri_lib_handles(p->sig)
06888 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06889
06890 break;
06891 }
06892 #endif
06893
06894 cp = (char *) data;
06895 if (!*cp) {
06896 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06897 x = 0;
06898 dahdi_disable_ec(p);
06899 } else {
06900 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06901 x = 1;
06902 }
06903 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06904 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06905 break;
06906 case AST_OPTION_OPRMODE:
06907 oprmode = (struct oprmode *) data;
06908
06909 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06910 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06911 chan->tech->type, oprmode->peer->tech->type);
06912 errno = EINVAL;
06913 return -1;
06914 }
06915 pp = oprmode->peer->tech_pvt;
06916 p->oprmode = pp->oprmode = 0;
06917
06918 p->oprpeer = pp;
06919 pp->oprpeer = p;
06920
06921 if (oprmode->mode)
06922 {
06923 pp->oprmode = oprmode->mode;
06924 p->oprmode = -oprmode->mode;
06925 }
06926 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06927 oprmode->mode, chan->name,oprmode->peer->name);
06928 break;
06929 case AST_OPTION_ECHOCAN:
06930 cp = (char *) data;
06931 if (*cp) {
06932 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06933 dahdi_enable_ec(p);
06934 } else {
06935 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06936 dahdi_disable_ec(p);
06937 }
06938 break;
06939 case AST_OPTION_DIGIT_DETECT:
06940 cp = (char *) data;
06941 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06942 if (*cp) {
06943 enable_dtmf_detect(p);
06944 } else {
06945 disable_dtmf_detect(p);
06946 }
06947 break;
06948 case AST_OPTION_FAX_DETECT:
06949 cp = (char *) data;
06950 if (p->dsp) {
06951 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06952 if (*cp) {
06953 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06954 } else {
06955 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06956 }
06957 ast_dsp_set_features(p->dsp, p->dsp_features);
06958 }
06959 break;
06960 default:
06961 return -1;
06962 }
06963 errno = 0;
06964
06965 return 0;
06966 }
06967
06968 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06969 {
06970 struct dahdi_pvt *p = chan->tech_pvt;
06971 int res = 0;
06972
06973 if (!p) {
06974
06975 *buf = '\0';
06976 return -1;
06977 }
06978
06979 if (!strcasecmp(data, "rxgain")) {
06980 ast_mutex_lock(&p->lock);
06981 snprintf(buf, len, "%f", p->rxgain);
06982 ast_mutex_unlock(&p->lock);
06983 } else if (!strcasecmp(data, "txgain")) {
06984 ast_mutex_lock(&p->lock);
06985 snprintf(buf, len, "%f", p->txgain);
06986 ast_mutex_unlock(&p->lock);
06987 } else if (!strcasecmp(data, "dahdi_channel")) {
06988 ast_mutex_lock(&p->lock);
06989 snprintf(buf, len, "%d", p->channel);
06990 ast_mutex_unlock(&p->lock);
06991 } else if (!strcasecmp(data, "dahdi_span")) {
06992 ast_mutex_lock(&p->lock);
06993 snprintf(buf, len, "%d", p->span);
06994 ast_mutex_unlock(&p->lock);
06995 } else if (!strcasecmp(data, "dahdi_type")) {
06996 ast_mutex_lock(&p->lock);
06997 switch (p->sig) {
06998 #if defined(HAVE_OPENR2)
06999 case SIG_MFCR2:
07000 ast_copy_string(buf, "mfc/r2", len);
07001 break;
07002 #endif
07003 #if defined(HAVE_PRI)
07004 case SIG_PRI_LIB_HANDLE_CASES:
07005 ast_copy_string(buf, "pri", len);
07006 break;
07007 #endif
07008 case 0:
07009 ast_copy_string(buf, "pseudo", len);
07010 break;
07011 #if defined(HAVE_SS7)
07012 case SIG_SS7:
07013 ast_copy_string(buf, "ss7", len);
07014 break;
07015 #endif
07016 default:
07017
07018 ast_copy_string(buf, "analog", len);
07019 break;
07020 }
07021 ast_mutex_unlock(&p->lock);
07022 #if defined(HAVE_PRI)
07023 #if defined(HAVE_PRI_REVERSE_CHARGE)
07024 } else if (!strcasecmp(data, "reversecharge")) {
07025 ast_mutex_lock(&p->lock);
07026 switch (p->sig) {
07027 case SIG_PRI_LIB_HANDLE_CASES:
07028 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07029 break;
07030 default:
07031 *buf = '\0';
07032 res = -1;
07033 break;
07034 }
07035 ast_mutex_unlock(&p->lock);
07036 #endif
07037 #if defined(HAVE_PRI_SETUP_KEYPAD)
07038 } else if (!strcasecmp(data, "keypad_digits")) {
07039 ast_mutex_lock(&p->lock);
07040 switch (p->sig) {
07041 case SIG_PRI_LIB_HANDLE_CASES:
07042 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07043 len);
07044 break;
07045 default:
07046 *buf = '\0';
07047 res = -1;
07048 break;
07049 }
07050 ast_mutex_unlock(&p->lock);
07051 #endif
07052 } else if (!strcasecmp(data, "no_media_path")) {
07053 ast_mutex_lock(&p->lock);
07054 switch (p->sig) {
07055 case SIG_PRI_LIB_HANDLE_CASES:
07056
07057
07058
07059
07060 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07061 break;
07062 default:
07063 *buf = '\0';
07064 res = -1;
07065 break;
07066 }
07067 ast_mutex_unlock(&p->lock);
07068 #endif
07069 } else {
07070 *buf = '\0';
07071 res = -1;
07072 }
07073
07074 return res;
07075 }
07076
07077
07078 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07079 {
07080 int res;
07081 char policy_str[21] = "";
07082
07083 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07084 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07085 return 1;
07086 }
07087 if (*num_buffers < 0) {
07088 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07089 return -1;
07090 }
07091 if (!strcasecmp(policy_str, "full")) {
07092 *policy = DAHDI_POLICY_WHEN_FULL;
07093 } else if (!strcasecmp(policy_str, "immediate")) {
07094 *policy = DAHDI_POLICY_IMMEDIATE;
07095 #if defined(HAVE_DAHDI_HALF_FULL)
07096 } else if (!strcasecmp(policy_str, "half")) {
07097 *policy = DAHDI_POLICY_HALF_FULL;
07098 #endif
07099 } else {
07100 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07101 return -1;
07102 }
07103
07104 return 0;
07105 }
07106
07107 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07108 {
07109 struct dahdi_pvt *p = chan->tech_pvt;
07110 int res = 0;
07111
07112 if (!p) {
07113
07114 return -1;
07115 }
07116
07117 if (!strcasecmp(data, "buffers")) {
07118 int num_bufs, policy;
07119
07120 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07121 struct dahdi_bufferinfo bi = {
07122 .txbufpolicy = policy,
07123 .rxbufpolicy = policy,
07124 .bufsize = p->bufsize,
07125 .numbufs = num_bufs,
07126 };
07127 int bpres;
07128
07129 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07130 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07131 } else {
07132 p->bufferoverrideinuse = 1;
07133 }
07134 } else {
07135 res = -1;
07136 }
07137 } else if (!strcasecmp(data, "echocan_mode")) {
07138 if (!strcasecmp(value, "on")) {
07139 ast_mutex_lock(&p->lock);
07140 dahdi_enable_ec(p);
07141 ast_mutex_unlock(&p->lock);
07142 } else if (!strcasecmp(value, "off")) {
07143 ast_mutex_lock(&p->lock);
07144 dahdi_disable_ec(p);
07145 ast_mutex_unlock(&p->lock);
07146 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07147 } else if (!strcasecmp(value, "fax")) {
07148 int blah = 1;
07149
07150 ast_mutex_lock(&p->lock);
07151 if (!p->echocanon) {
07152 dahdi_enable_ec(p);
07153 }
07154 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07155 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07156 }
07157 ast_mutex_unlock(&p->lock);
07158 } else if (!strcasecmp(value, "voice")) {
07159 int blah = 0;
07160
07161 ast_mutex_lock(&p->lock);
07162 if (!p->echocanon) {
07163 dahdi_enable_ec(p);
07164 }
07165 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07166 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07167 }
07168 ast_mutex_unlock(&p->lock);
07169 #endif
07170 } else {
07171 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07172 res = -1;
07173 }
07174 } else {
07175 res = -1;
07176 }
07177
07178 return res;
07179 }
07180
07181 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07182 {
07183
07184 int x;
07185 int hasslaves;
07186 if (!master)
07187 return;
07188 if (needlock) {
07189 ast_mutex_lock(&master->lock);
07190 if (slave) {
07191 while (ast_mutex_trylock(&slave->lock)) {
07192 DEADLOCK_AVOIDANCE(&master->lock);
07193 }
07194 }
07195 }
07196 hasslaves = 0;
07197 for (x = 0; x < MAX_SLAVES; x++) {
07198 if (master->slaves[x]) {
07199 if (!slave || (master->slaves[x] == slave)) {
07200
07201 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07202 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07203 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07204 master->slaves[x]->master = NULL;
07205 master->slaves[x] = NULL;
07206 } else
07207 hasslaves = 1;
07208 }
07209 if (!hasslaves)
07210 master->inconference = 0;
07211 }
07212 if (!slave) {
07213 if (master->master) {
07214
07215 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07216 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07217 hasslaves = 0;
07218 for (x = 0; x < MAX_SLAVES; x++) {
07219 if (master->master->slaves[x] == master)
07220 master->master->slaves[x] = NULL;
07221 else if (master->master->slaves[x])
07222 hasslaves = 1;
07223 }
07224 if (!hasslaves)
07225 master->master->inconference = 0;
07226 }
07227 master->master = NULL;
07228 }
07229 update_conf(master);
07230 if (needlock) {
07231 if (slave)
07232 ast_mutex_unlock(&slave->lock);
07233 ast_mutex_unlock(&master->lock);
07234 }
07235 }
07236
07237 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07238 int x;
07239 if (!slave || !master) {
07240 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07241 return;
07242 }
07243 for (x = 0; x < MAX_SLAVES; x++) {
07244 if (!master->slaves[x]) {
07245 master->slaves[x] = slave;
07246 break;
07247 }
07248 }
07249 if (x >= MAX_SLAVES) {
07250 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07251 master->slaves[MAX_SLAVES - 1] = slave;
07252 }
07253 if (slave->master)
07254 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07255 slave->master = master;
07256
07257 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07258 }
07259
07260 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)
07261 {
07262 struct ast_channel *who;
07263 struct dahdi_pvt *p0, *p1, *op0, *op1;
07264 struct dahdi_pvt *master = NULL, *slave = NULL;
07265 struct ast_frame *f;
07266 int inconf = 0;
07267 int nothingok = 1;
07268 int ofd0, ofd1;
07269 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07270 int os0 = -1, os1 = -1;
07271 int priority = 0;
07272 struct ast_channel *oc0, *oc1;
07273 enum ast_bridge_result res;
07274 struct timeval start = ast_tvnow();
07275 #ifdef PRI_2BCT
07276 int triedtopribridge = 0;
07277 q931_call *q931c0;
07278 q931_call *q931c1;
07279 #endif
07280
07281
07282
07283
07284
07285
07286 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07287 return AST_BRIDGE_FAILED_NOWARN;
07288
07289 ast_channel_lock(c0);
07290 while (ast_channel_trylock(c1)) {
07291 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07292 }
07293
07294 p0 = c0->tech_pvt;
07295 p1 = c1->tech_pvt;
07296
07297 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07298 ast_channel_unlock(c0);
07299 ast_channel_unlock(c1);
07300 return AST_BRIDGE_FAILED_NOWARN;
07301 }
07302
07303 oi0 = dahdi_get_index(c0, p0, 0);
07304 oi1 = dahdi_get_index(c1, p1, 0);
07305 if ((oi0 < 0) || (oi1 < 0)) {
07306 ast_channel_unlock(c0);
07307 ast_channel_unlock(c1);
07308 return AST_BRIDGE_FAILED;
07309 }
07310
07311 op0 = p0 = c0->tech_pvt;
07312 op1 = p1 = c1->tech_pvt;
07313 ofd0 = c0->fds[0];
07314 ofd1 = c1->fds[0];
07315 oc0 = p0->owner;
07316 oc1 = p1->owner;
07317
07318 if (ast_mutex_trylock(&p0->lock)) {
07319
07320 ast_channel_unlock(c0);
07321 ast_channel_unlock(c1);
07322 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07323 return AST_BRIDGE_RETRY;
07324 }
07325 if (ast_mutex_trylock(&p1->lock)) {
07326
07327 ast_mutex_unlock(&p0->lock);
07328 ast_channel_unlock(c0);
07329 ast_channel_unlock(c1);
07330 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07331 return AST_BRIDGE_RETRY;
07332 }
07333
07334 if ((p0->callwaiting && p0->callwaitingcallerid)
07335 || (p1->callwaiting && p1->callwaitingcallerid)) {
07336
07337
07338
07339
07340
07341
07342
07343
07344
07345 ast_mutex_unlock(&p0->lock);
07346 ast_mutex_unlock(&p1->lock);
07347 ast_channel_unlock(c0);
07348 ast_channel_unlock(c1);
07349 return AST_BRIDGE_FAILED_NOWARN;
07350 }
07351
07352 #if defined(HAVE_PRI)
07353 if ((dahdi_sig_pri_lib_handles(p0->sig)
07354 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07355 || (dahdi_sig_pri_lib_handles(p1->sig)
07356 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07357
07358
07359
07360
07361 ast_mutex_unlock(&p0->lock);
07362 ast_mutex_unlock(&p1->lock);
07363 ast_channel_unlock(c0);
07364 ast_channel_unlock(c1);
07365 return AST_BRIDGE_FAILED_NOWARN;
07366 }
07367 #endif
07368
07369 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07370 if (p0->owner && p1->owner) {
07371
07372 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07373 master = p0;
07374 slave = p1;
07375 inconf = 1;
07376 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07377 master = p1;
07378 slave = p0;
07379 inconf = 1;
07380 } else {
07381 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07382 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07383 p0->channel,
07384 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07385 p0->subs[SUB_REAL].inthreeway, p0->channel,
07386 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07387 p1->subs[SUB_REAL].inthreeway);
07388 }
07389 nothingok = 0;
07390 }
07391 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07392 if (p1->subs[SUB_THREEWAY].inthreeway) {
07393 master = p1;
07394 slave = p0;
07395 nothingok = 0;
07396 }
07397 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07398 if (p0->subs[SUB_THREEWAY].inthreeway) {
07399 master = p0;
07400 slave = p1;
07401 nothingok = 0;
07402 }
07403 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07404
07405
07406 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07407 master = p1;
07408 slave = p0;
07409 nothingok = 0;
07410 }
07411 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07412
07413 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07414 master = p0;
07415 slave = p1;
07416 nothingok = 0;
07417 }
07418 }
07419 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07420 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07421 if (master && slave) {
07422
07423
07424
07425 if ((oi1 == SUB_THREEWAY) &&
07426 p1->subs[SUB_THREEWAY].inthreeway &&
07427 p1->subs[SUB_REAL].owner &&
07428 p1->subs[SUB_REAL].inthreeway &&
07429 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07430 ast_debug(1,
07431 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07432 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07433 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07434 os1 = p1->subs[SUB_REAL].owner->_state;
07435 } else {
07436 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07437 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07438 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07439 }
07440 if ((oi0 == SUB_THREEWAY) &&
07441 p0->subs[SUB_THREEWAY].inthreeway &&
07442 p0->subs[SUB_REAL].owner &&
07443 p0->subs[SUB_REAL].inthreeway &&
07444 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07445 ast_debug(1,
07446 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07447 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07448 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07449 os0 = p0->subs[SUB_REAL].owner->_state;
07450 } else {
07451 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07452 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07453 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07454 }
07455 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07456 if (!p0->echocanbridged || !p1->echocanbridged) {
07457
07458 dahdi_disable_ec(p0);
07459 dahdi_disable_ec(p1);
07460 }
07461 }
07462 dahdi_link(slave, master);
07463 master->inconference = inconf;
07464 } else if (!nothingok)
07465 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07466
07467 update_conf(p0);
07468 update_conf(p1);
07469 t0 = p0->subs[SUB_REAL].inthreeway;
07470 t1 = p1->subs[SUB_REAL].inthreeway;
07471
07472 ast_mutex_unlock(&p0->lock);
07473 ast_mutex_unlock(&p1->lock);
07474
07475 ast_channel_unlock(c0);
07476 ast_channel_unlock(c1);
07477
07478
07479 if ((!master || !slave) && !nothingok) {
07480 dahdi_enable_ec(p0);
07481 dahdi_enable_ec(p1);
07482 return AST_BRIDGE_FAILED;
07483 }
07484
07485 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07486
07487 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07488 disable_dtmf_detect(op0);
07489
07490 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07491 disable_dtmf_detect(op1);
07492
07493 for (;;) {
07494 struct ast_channel *c0_priority[2] = {c0, c1};
07495 struct ast_channel *c1_priority[2] = {c1, c0};
07496 int ms;
07497
07498
07499
07500
07501 ast_channel_lock(c0);
07502 while (ast_channel_trylock(c1)) {
07503 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07504 }
07505
07506 p0 = c0->tech_pvt;
07507 p1 = c1->tech_pvt;
07508
07509 if (op0 == p0)
07510 i0 = dahdi_get_index(c0, p0, 1);
07511 if (op1 == p1)
07512 i1 = dahdi_get_index(c1, p1, 1);
07513
07514 ast_channel_unlock(c0);
07515 ast_channel_unlock(c1);
07516 ms = ast_remaining_ms(start, timeoutms);
07517 if (!ms ||
07518 (op0 != p0) ||
07519 (op1 != p1) ||
07520 (ofd0 != c0->fds[0]) ||
07521 (ofd1 != c1->fds[0]) ||
07522 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07523 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07524 (oc0 != p0->owner) ||
07525 (oc1 != p1->owner) ||
07526 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07527 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07528 (oi0 != i0) ||
07529 (oi1 != i1)) {
07530 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07531 op0->channel, oi0, op1->channel, oi1);
07532 res = AST_BRIDGE_RETRY;
07533 goto return_from_bridge;
07534 }
07535
07536 #ifdef PRI_2BCT
07537 if (!triedtopribridge) {
07538 triedtopribridge = 1;
07539 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07540 ast_mutex_lock(&p0->pri->lock);
07541 switch (p0->sig) {
07542 case SIG_PRI_LIB_HANDLE_CASES:
07543 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07544 break;
07545 default:
07546 q931c0 = NULL;
07547 break;
07548 }
07549 switch (p1->sig) {
07550 case SIG_PRI_LIB_HANDLE_CASES:
07551 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07552 break;
07553 default:
07554 q931c1 = NULL;
07555 break;
07556 }
07557 if (q931c0 && q931c1) {
07558 pri_channel_bridge(q931c0, q931c1);
07559 }
07560 ast_mutex_unlock(&p0->pri->lock);
07561 }
07562 }
07563 #endif
07564
07565 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07566 if (!who) {
07567 ast_debug(1, "Ooh, empty read...\n");
07568 continue;
07569 }
07570 f = ast_read(who);
07571 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07572 *fo = f;
07573 *rc = who;
07574 res = AST_BRIDGE_COMPLETE;
07575 goto return_from_bridge;
07576 }
07577 if (f->frametype == AST_FRAME_DTMF) {
07578 if ((who == c0) && p0->pulsedial) {
07579 ast_write(c1, f);
07580 } else if ((who == c1) && p1->pulsedial) {
07581 ast_write(c0, f);
07582 } else {
07583 *fo = f;
07584 *rc = who;
07585 res = AST_BRIDGE_COMPLETE;
07586 goto return_from_bridge;
07587 }
07588 }
07589 ast_frfree(f);
07590
07591
07592 priority = !priority;
07593 }
07594
07595 return_from_bridge:
07596 if (op0 == p0)
07597 dahdi_enable_ec(p0);
07598
07599 if (op1 == p1)
07600 dahdi_enable_ec(p1);
07601
07602 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07603 enable_dtmf_detect(op0);
07604
07605 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07606 enable_dtmf_detect(op1);
07607
07608 dahdi_unlink(slave, master, 1);
07609
07610 return res;
07611 }
07612
07613 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07614 {
07615 struct dahdi_pvt *p = newchan->tech_pvt;
07616 int x;
07617
07618 ast_mutex_lock(&p->lock);
07619
07620 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07621 if (p->owner == oldchan) {
07622 p->owner = newchan;
07623 }
07624 for (x = 0; x < 3; x++) {
07625 if (p->subs[x].owner == oldchan) {
07626 if (!x) {
07627 dahdi_unlink(NULL, p, 0);
07628 }
07629 p->subs[x].owner = newchan;
07630 }
07631 }
07632 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07633 analog_fixup(oldchan, newchan, p->sig_pvt);
07634 #if defined(HAVE_PRI)
07635 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07636 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07637 #endif
07638 #if defined(HAVE_SS7)
07639 } else if (p->sig == SIG_SS7) {
07640 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07641 #endif
07642 }
07643 update_conf(p);
07644
07645 ast_mutex_unlock(&p->lock);
07646
07647 if (newchan->_state == AST_STATE_RINGING) {
07648 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07649 }
07650 return 0;
07651 }
07652
07653 static int dahdi_ring_phone(struct dahdi_pvt *p)
07654 {
07655 int x;
07656 int res;
07657
07658 x = 0;
07659 x = DAHDI_ONHOOK;
07660 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07661 do {
07662 x = DAHDI_RING;
07663 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07664 if (res) {
07665 switch (errno) {
07666 case EBUSY:
07667 case EINTR:
07668
07669 usleep(10000);
07670 continue;
07671 case EINPROGRESS:
07672 res = 0;
07673 break;
07674 default:
07675 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07676 res = 0;
07677 }
07678 }
07679 } while (res);
07680 return res;
07681 }
07682
07683 static void *analog_ss_thread(void *data);
07684
07685 static int attempt_transfer(struct dahdi_pvt *p)
07686 {
07687
07688
07689
07690 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07691
07692
07693 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07694 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07695 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07696 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07697 }
07698 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07699 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07700 }
07701 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07702 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07703 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07704 return -1;
07705 }
07706
07707 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07708 unalloc_sub(p, SUB_THREEWAY);
07709 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07710 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07711 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07712 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07713 }
07714 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07715 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07716 }
07717 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07718 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07719 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07720 return -1;
07721 }
07722
07723 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07724 ast_channel_unlock(p->subs[SUB_REAL].owner);
07725 unalloc_sub(p, SUB_THREEWAY);
07726
07727 return 1;
07728 } else {
07729 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07730 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07731 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07732 return -1;
07733 }
07734 return 0;
07735 }
07736
07737 static int check_for_conference(struct dahdi_pvt *p)
07738 {
07739 struct dahdi_confinfo ci;
07740
07741 if (p->master || (p->confno > -1))
07742 return 0;
07743 memset(&ci, 0, sizeof(ci));
07744 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07745 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07746 return 0;
07747 }
07748
07749
07750
07751 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07752 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07753 return 1;
07754 }
07755 return 0;
07756 }
07757
07758
07759
07760
07761
07762
07763 static int get_alarms(struct dahdi_pvt *p)
07764 {
07765 int res;
07766 struct dahdi_spaninfo zi;
07767 struct dahdi_params params;
07768
07769 memset(&zi, 0, sizeof(zi));
07770 zi.spanno = p->span;
07771
07772 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07773 if (zi.alarms != DAHDI_ALARM_NONE)
07774 return zi.alarms;
07775 } else {
07776 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07777 return 0;
07778 }
07779
07780
07781 memset(¶ms, 0, sizeof(params));
07782 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07783 return params.chan_alarms;
07784
07785 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07786
07787 return DAHDI_ALARM_NONE;
07788 }
07789
07790 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07791 {
07792 struct dahdi_pvt *p = ast->tech_pvt;
07793 struct ast_frame *f = *dest;
07794
07795 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07796 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07797 (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
07798
07799 if (p->confirmanswer) {
07800 if (f->frametype == AST_FRAME_DTMF_END) {
07801 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07802
07803
07804 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07805 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07806
07807 p->confirmanswer = 0;
07808 } else {
07809 p->subs[idx].f.frametype = AST_FRAME_NULL;
07810 p->subs[idx].f.subclass.integer = 0;
07811 }
07812 *dest = &p->subs[idx].f;
07813 } else if (p->callwaitcas) {
07814 if (f->frametype == AST_FRAME_DTMF_END) {
07815 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07816 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07817 ast_free(p->cidspill);
07818 p->cidspill = NULL;
07819 send_cwcidspill(p);
07820 }
07821 p->callwaitcas = 0;
07822 }
07823 p->subs[idx].f.frametype = AST_FRAME_NULL;
07824 p->subs[idx].f.subclass.integer = 0;
07825 *dest = &p->subs[idx].f;
07826 } else if (f->subclass.integer == 'f') {
07827 if (f->frametype == AST_FRAME_DTMF_END) {
07828
07829 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07830
07831 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07832 struct dahdi_bufferinfo bi = {
07833 .txbufpolicy = p->faxbuf_policy,
07834 .bufsize = p->bufsize,
07835 .numbufs = p->faxbuf_no
07836 };
07837 int res;
07838
07839 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07840 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07841 } else {
07842 p->bufferoverrideinuse = 1;
07843 }
07844 }
07845 p->faxhandled = 1;
07846 if (p->dsp) {
07847 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07848 ast_dsp_set_features(p->dsp, p->dsp_features);
07849 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07850 }
07851 if (strcmp(ast->exten, "fax")) {
07852 const char *target_context = S_OR(ast->macrocontext, ast->context);
07853
07854
07855
07856
07857
07858 ast_mutex_unlock(&p->lock);
07859 ast_channel_unlock(ast);
07860 if (ast_exists_extension(ast, target_context, "fax", 1,
07861 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07862 ast_channel_lock(ast);
07863 ast_mutex_lock(&p->lock);
07864 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07865
07866 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07867 if (ast_async_goto(ast, target_context, "fax", 1))
07868 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07869 } else {
07870 ast_channel_lock(ast);
07871 ast_mutex_lock(&p->lock);
07872 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07873 }
07874 } else {
07875 ast_debug(1, "Already in a fax extension, not redirecting\n");
07876 }
07877 } else {
07878 ast_debug(1, "Fax already handled\n");
07879 }
07880 dahdi_confmute(p, 0);
07881 }
07882 p->subs[idx].f.frametype = AST_FRAME_NULL;
07883 p->subs[idx].f.subclass.integer = 0;
07884 *dest = &p->subs[idx].f;
07885 }
07886 }
07887
07888 static void handle_alarms(struct dahdi_pvt *p, int alms)
07889 {
07890 const char *alarm_str;
07891
07892 #if defined(HAVE_PRI)
07893 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07894 return;
07895 }
07896 #endif
07897
07898 alarm_str = alarm2str(alms);
07899 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07900 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07901 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07902 "Alarm: %s\r\n"
07903 "Channel: %d\r\n",
07904 alarm_str, p->channel);
07905 }
07906
07907 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07908 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07909 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07910 "Alarm: %s\r\n"
07911 "Span: %d\r\n",
07912 alarm_str, p->span);
07913 }
07914 }
07915
07916 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07917 {
07918 int res, x;
07919 int idx, mysig;
07920 char *c;
07921 struct dahdi_pvt *p = ast->tech_pvt;
07922 pthread_t threadid;
07923 struct ast_channel *chan;
07924 struct ast_frame *f;
07925
07926 idx = dahdi_get_index(ast, p, 0);
07927 if (idx < 0) {
07928 return &ast_null_frame;
07929 }
07930 mysig = p->sig;
07931 if (p->outsigmod > -1)
07932 mysig = p->outsigmod;
07933 p->subs[idx].f.frametype = AST_FRAME_NULL;
07934 p->subs[idx].f.subclass.integer = 0;
07935 p->subs[idx].f.datalen = 0;
07936 p->subs[idx].f.samples = 0;
07937 p->subs[idx].f.mallocd = 0;
07938 p->subs[idx].f.offset = 0;
07939 p->subs[idx].f.src = "dahdi_handle_event";
07940 p->subs[idx].f.data.ptr = NULL;
07941 f = &p->subs[idx].f;
07942
07943 if (p->fake_event) {
07944 res = p->fake_event;
07945 p->fake_event = 0;
07946 } else
07947 res = dahdi_get_event(p->subs[idx].dfd);
07948
07949 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07950
07951 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07952 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07953 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07954 #if defined(HAVE_PRI)
07955 if (dahdi_sig_pri_lib_handles(p->sig)
07956 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07957 && p->pri
07958 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07959
07960 } else
07961 #endif
07962 {
07963
07964 dahdi_confmute(p, 0);
07965 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07966 p->subs[idx].f.subclass.integer = res & 0xff;
07967 dahdi_handle_dtmf(ast, idx, &f);
07968 }
07969 return f;
07970 }
07971
07972 if (res & DAHDI_EVENT_DTMFDOWN) {
07973 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07974 #if defined(HAVE_PRI)
07975 if (dahdi_sig_pri_lib_handles(p->sig)
07976 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07977 && p->pri
07978 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07979
07980 } else
07981 #endif
07982 {
07983
07984 dahdi_confmute(p, 1);
07985 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07986 p->subs[idx].f.subclass.integer = res & 0xff;
07987 dahdi_handle_dtmf(ast, idx, &f);
07988 }
07989 return &p->subs[idx].f;
07990 }
07991
07992 switch (res) {
07993 case DAHDI_EVENT_EC_DISABLED:
07994 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07995 p->echocanon = 0;
07996 break;
07997 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07998 case DAHDI_EVENT_TX_CED_DETECTED:
07999 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
08000 break;
08001 case DAHDI_EVENT_RX_CED_DETECTED:
08002 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
08003 break;
08004 case DAHDI_EVENT_EC_NLP_DISABLED:
08005 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
08006 break;
08007 case DAHDI_EVENT_EC_NLP_ENABLED:
08008 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
08009 break;
08010 #endif
08011 case DAHDI_EVENT_BITSCHANGED:
08012 #ifdef HAVE_OPENR2
08013 if (p->sig != SIG_MFCR2) {
08014 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08015 } else {
08016 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
08017 openr2_chan_handle_cas(p->r2chan);
08018 }
08019 #else
08020 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08021 #endif
08022 break;
08023 case DAHDI_EVENT_PULSE_START:
08024
08025 if (!ast->pbx)
08026 tone_zone_play_tone(p->subs[idx].dfd, -1);
08027 break;
08028 case DAHDI_EVENT_DIALCOMPLETE:
08029
08030 #if defined(HAVE_PRI)
08031 if (dahdi_sig_pri_lib_handles(p->sig)) {
08032 if (p->inalarm) {
08033 break;
08034 }
08035 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08036 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08037 strerror(errno));
08038 return NULL;
08039 }
08040 if (x) {
08041
08042 break;
08043 }
08044
08045
08046
08047
08048 sig_pri_dial_complete(p->sig_pvt, ast);
08049 break;
08050 }
08051 #endif
08052 #ifdef HAVE_OPENR2
08053 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08054
08055
08056 break;
08057 }
08058 #endif
08059 if (p->inalarm) break;
08060 if ((p->radio || (p->oprmode < 0))) break;
08061 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08062 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08063 return NULL;
08064 }
08065 if (!x) {
08066 dahdi_enable_ec(p);
08067 if (p->echobreak) {
08068 dahdi_train_ec(p);
08069 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08070 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08071 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08072 p->echobreak = 0;
08073 } else {
08074 p->dialing = 0;
08075 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08076
08077 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08078 ast_setstate(ast, AST_STATE_UP);
08079 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08080 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08081 break;
08082 } else {
08083
08084 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08085 }
08086 }
08087 if (ast->_state == AST_STATE_DIALING) {
08088 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08089 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08090 } else if (p->confirmanswer || (!p->dialednone
08091 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08092 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08093 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08094 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08095 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08096 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08097 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08098 || (mysig == SIG_SF_FEATB)))) {
08099 ast_setstate(ast, AST_STATE_RINGING);
08100 } else if (!p->answeronpolarityswitch) {
08101 ast_setstate(ast, AST_STATE_UP);
08102 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08103 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08104
08105 p->polarity = POLARITY_REV;
08106 } else {
08107
08108 p->polarity = POLARITY_IDLE;
08109 }
08110 }
08111 }
08112 }
08113 break;
08114 case DAHDI_EVENT_ALARM:
08115 switch (p->sig) {
08116 #if defined(HAVE_PRI)
08117 case SIG_PRI_LIB_HANDLE_CASES:
08118 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08119 break;
08120 #endif
08121 #if defined(HAVE_SS7)
08122 case SIG_SS7:
08123 sig_ss7_set_alarm(p->sig_pvt, 1);
08124 break;
08125 #endif
08126 default:
08127 p->inalarm = 1;
08128 break;
08129 }
08130 res = get_alarms(p);
08131 handle_alarms(p, res);
08132 #ifdef HAVE_PRI
08133 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08134
08135 } else {
08136 break;
08137 }
08138 #endif
08139 #if defined(HAVE_SS7)
08140 if (p->sig == SIG_SS7)
08141 break;
08142 #endif
08143 #ifdef HAVE_OPENR2
08144 if (p->sig == SIG_MFCR2)
08145 break;
08146 #endif
08147 case DAHDI_EVENT_ONHOOK:
08148 if (p->radio) {
08149 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08150 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08151 break;
08152 }
08153 if (p->oprmode < 0)
08154 {
08155 if (p->oprmode != -1) break;
08156 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08157 {
08158
08159 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08160 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08161 save_conference(p->oprpeer);
08162 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08163 }
08164 break;
08165 }
08166 switch (p->sig) {
08167 case SIG_FXOLS:
08168 case SIG_FXOGS:
08169 case SIG_FXOKS:
08170
08171 if (idx == SUB_REAL) {
08172
08173 if (p->subs[SUB_CALLWAIT].owner) {
08174
08175 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08176 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08177 unalloc_sub(p, SUB_CALLWAIT);
08178 #if 0
08179 p->subs[idx].needanswer = 0;
08180 p->subs[idx].needringing = 0;
08181 #endif
08182 p->callwaitingrepeat = 0;
08183 p->cidcwexpire = 0;
08184 p->cid_suppress_expire = 0;
08185 p->owner = NULL;
08186
08187 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08188 p->dialing = 1;
08189 dahdi_ring_phone(p);
08190 } else if (p->subs[SUB_THREEWAY].owner) {
08191 unsigned int mssinceflash;
08192
08193
08194 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08195
08196 DLA_UNLOCK(&p->lock);
08197 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08198
08199
08200
08201 DLA_LOCK(&p->lock);
08202 if (p->owner != ast) {
08203 ast_log(LOG_WARNING, "This isn't good...\n");
08204 return NULL;
08205 }
08206 }
08207 if (!p->subs[SUB_THREEWAY].owner) {
08208 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08209 return NULL;
08210 }
08211 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08212 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
08213 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08214
08215
08216 if (p->subs[SUB_THREEWAY].owner)
08217 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08218 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08219 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08220 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08221 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08222 if (p->transfer) {
08223
08224 p->subs[SUB_REAL].inthreeway = 0;
08225 p->subs[SUB_THREEWAY].inthreeway = 0;
08226
08227 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08228 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08229
08230 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08231 p->owner = NULL;
08232
08233 dahdi_ring_phone(p);
08234 } else {
08235 if ((res = attempt_transfer(p)) < 0) {
08236 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08237 if (p->subs[SUB_THREEWAY].owner)
08238 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08239 } else if (res) {
08240
08241 if (p->subs[SUB_THREEWAY].owner)
08242 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08243 break;
08244 }
08245 }
08246 } else {
08247 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08248 if (p->subs[SUB_THREEWAY].owner)
08249 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08250 }
08251 } else {
08252 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08253
08254 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08255 p->owner = NULL;
08256
08257 dahdi_ring_phone(p);
08258 }
08259 }
08260 } else {
08261 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08262 }
08263
08264 default:
08265 dahdi_disable_ec(p);
08266 return NULL;
08267 }
08268 break;
08269 case DAHDI_EVENT_RINGOFFHOOK:
08270 if (p->inalarm) break;
08271 if (p->oprmode < 0)
08272 {
08273 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08274 {
08275
08276 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08277 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08278 restore_conference(p->oprpeer);
08279 }
08280 break;
08281 }
08282 if (p->radio)
08283 {
08284 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08285 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08286 break;
08287 }
08288
08289
08290 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08291 c = strchr(p->dialdest, '/');
08292 if (c)
08293 c++;
08294 else
08295 c = p->dialdest;
08296 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08297 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08298 if (strlen(p->dop.dialstr) > 4) {
08299 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08300 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08301 p->echorest[sizeof(p->echorest) - 1] = '\0';
08302 p->echobreak = 1;
08303 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08304 } else
08305 p->echobreak = 0;
08306 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08307 int saveerr = errno;
08308
08309 x = DAHDI_ONHOOK;
08310 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08311 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08312 return NULL;
08313 }
08314 p->dialing = 1;
08315 return &p->subs[idx].f;
08316 }
08317 switch (p->sig) {
08318 case SIG_FXOLS:
08319 case SIG_FXOGS:
08320 case SIG_FXOKS:
08321 switch (ast->_state) {
08322 case AST_STATE_RINGING:
08323 dahdi_enable_ec(p);
08324 dahdi_train_ec(p);
08325 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08326 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08327
08328 p->subs[SUB_REAL].needringing = 0;
08329 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08330 ast_debug(1, "channel %d answered\n", p->channel);
08331
08332
08333 ast_free(p->cidspill);
08334 p->cidspill = NULL;
08335 restore_conference(p);
08336
08337 p->dialing = 0;
08338 p->callwaitcas = 0;
08339 if (p->confirmanswer) {
08340
08341 p->subs[idx].f.frametype = AST_FRAME_NULL;
08342 p->subs[idx].f.subclass.integer = 0;
08343 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08344
08345 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08346 if (res < 0) {
08347 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08348 p->dop.dialstr[0] = '\0';
08349 return NULL;
08350 } else {
08351 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08352 p->subs[idx].f.frametype = AST_FRAME_NULL;
08353 p->subs[idx].f.subclass.integer = 0;
08354 p->dialing = 1;
08355 }
08356 p->dop.dialstr[0] = '\0';
08357 ast_setstate(ast, AST_STATE_DIALING);
08358 } else
08359 ast_setstate(ast, AST_STATE_UP);
08360 return &p->subs[idx].f;
08361 case AST_STATE_DOWN:
08362 ast_setstate(ast, AST_STATE_RING);
08363 ast->rings = 1;
08364 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08365 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08366 ast_debug(1, "channel %d picked up\n", p->channel);
08367 return &p->subs[idx].f;
08368 case AST_STATE_UP:
08369
08370 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08371
08372 if (ast_bridged_channel(p->owner))
08373 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08374 p->subs[idx].needunhold = 1;
08375 break;
08376 case AST_STATE_RESERVED:
08377
08378 if (has_voicemail(p))
08379 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08380 else
08381 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08382 break;
08383 default:
08384 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast->_state);
08385 }
08386 break;
08387 case SIG_FXSLS:
08388 case SIG_FXSGS:
08389 case SIG_FXSKS:
08390 if (ast->_state == AST_STATE_RING) {
08391 p->ringt = p->ringt_base;
08392 }
08393
08394
08395
08396 ast_debug(1, "Setting IDLE polarity due "
08397 "to ring. Old polarity was %d\n",
08398 p->polarity);
08399 p->polarity = POLARITY_IDLE;
08400
08401
08402 case SIG_EM:
08403 case SIG_EM_E1:
08404 case SIG_EMWINK:
08405 case SIG_FEATD:
08406 case SIG_FEATDMF:
08407 case SIG_FEATDMF_TA:
08408 case SIG_E911:
08409 case SIG_FGC_CAMA:
08410 case SIG_FGC_CAMAMF:
08411 case SIG_FEATB:
08412 case SIG_SF:
08413 case SIG_SFWINK:
08414 case SIG_SF_FEATD:
08415 case SIG_SF_FEATDMF:
08416 case SIG_SF_FEATB:
08417 if (ast->_state == AST_STATE_PRERING)
08418 ast_setstate(ast, AST_STATE_RING);
08419 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08420 ast_debug(1, "Ring detected\n");
08421 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08422 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08423 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08424 ast_debug(1, "Line answered\n");
08425 if (p->confirmanswer) {
08426 p->subs[idx].f.frametype = AST_FRAME_NULL;
08427 p->subs[idx].f.subclass.integer = 0;
08428 } else {
08429 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08430 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08431 ast_setstate(ast, AST_STATE_UP);
08432 }
08433 } else if (ast->_state != AST_STATE_RING)
08434 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast->_state, p->channel);
08435 break;
08436 default:
08437 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08438 }
08439 break;
08440 case DAHDI_EVENT_RINGBEGIN:
08441 switch (p->sig) {
08442 case SIG_FXSLS:
08443 case SIG_FXSGS:
08444 case SIG_FXSKS:
08445 if (ast->_state == AST_STATE_RING) {
08446 p->ringt = p->ringt_base;
08447 }
08448 break;
08449 }
08450 break;
08451 case DAHDI_EVENT_RINGERON:
08452 break;
08453 case DAHDI_EVENT_NOALARM:
08454 switch (p->sig) {
08455 #if defined(HAVE_PRI)
08456 case SIG_PRI_LIB_HANDLE_CASES:
08457 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08458 break;
08459 #endif
08460 #if defined(HAVE_SS7)
08461 case SIG_SS7:
08462 sig_ss7_set_alarm(p->sig_pvt, 0);
08463 break;
08464 #endif
08465 default:
08466 p->inalarm = 0;
08467 break;
08468 }
08469 handle_clear_alarms(p);
08470 break;
08471 case DAHDI_EVENT_WINKFLASH:
08472 if (p->inalarm) break;
08473 if (p->radio) break;
08474 if (p->oprmode < 0) break;
08475 if (p->oprmode > 1)
08476 {
08477 struct dahdi_params par;
08478
08479 memset(&par, 0, sizeof(par));
08480 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08481 {
08482 if (!par.rxisoffhook)
08483 {
08484
08485 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08486 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08487 save_conference(p);
08488 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08489 }
08490 }
08491 break;
08492 }
08493
08494 p->flashtime = ast_tvnow();
08495 switch (mysig) {
08496 case SIG_FXOLS:
08497 case SIG_FXOGS:
08498 case SIG_FXOKS:
08499 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08500 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08501
08502
08503 ast_free(p->cidspill);
08504 p->cidspill = NULL;
08505 restore_conference(p);
08506 p->callwaitcas = 0;
08507
08508 if (idx != SUB_REAL) {
08509 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08510 goto winkflashdone;
08511 }
08512
08513 if (p->subs[SUB_CALLWAIT].owner) {
08514
08515 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08516 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08517 p->owner = p->subs[SUB_REAL].owner;
08518 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08519 if (p->owner->_state == AST_STATE_RINGING) {
08520 ast_setstate(p->owner, AST_STATE_UP);
08521 p->subs[SUB_REAL].needanswer = 1;
08522 }
08523 p->callwaitingrepeat = 0;
08524 p->cidcwexpire = 0;
08525 p->cid_suppress_expire = 0;
08526
08527 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08528 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08529 S_OR(p->mohsuggest, NULL),
08530 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08531 }
08532 p->subs[SUB_CALLWAIT].needhold = 1;
08533 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08534 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08535 S_OR(p->mohsuggest, NULL),
08536 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08537 }
08538 p->subs[SUB_REAL].needunhold = 1;
08539 } else if (!p->subs[SUB_THREEWAY].owner) {
08540 if (!p->threewaycalling) {
08541
08542 p->subs[SUB_REAL].needflash = 1;
08543 goto winkflashdone;
08544 } else if (!check_for_conference(p)) {
08545 char cid_num[256];
08546 char cid_name[256];
08547
08548 cid_num[0] = 0;
08549 cid_name[0] = 0;
08550 if (p->dahditrcallerid && p->owner) {
08551 if (p->owner->caller.id.number.valid
08552 && p->owner->caller.id.number.str) {
08553 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08554 sizeof(cid_num));
08555 }
08556 if (p->owner->caller.id.name.valid
08557 && p->owner->caller.id.name.str) {
08558 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08559 sizeof(cid_name));
08560 }
08561 }
08562
08563
08564 if (!((ast->pbx) ||
08565 (ast->_state == AST_STATE_UP) ||
08566 (ast->_state == AST_STATE_RING))) {
08567 ast_debug(1, "Flash when call not up or ringing\n");
08568 goto winkflashdone;
08569 }
08570 if (alloc_sub(p, SUB_THREEWAY)) {
08571 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08572 goto winkflashdone;
08573 }
08574
08575
08576
08577
08578
08579
08580
08581 ast_mutex_unlock(&p->lock);
08582 ast_channel_unlock(ast);
08583 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08584 ast_channel_lock(ast);
08585 ast_mutex_lock(&p->lock);
08586 if (p->dahditrcallerid) {
08587 if (!p->origcid_num)
08588 p->origcid_num = ast_strdup(p->cid_num);
08589 if (!p->origcid_name)
08590 p->origcid_name = ast_strdup(p->cid_name);
08591 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08592 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08593 }
08594
08595 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08596
08597 dahdi_disable_ec(p);
08598 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08599 if (res)
08600 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08601 p->owner = chan;
08602 if (!chan) {
08603 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08604 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08605 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08606 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08607 dahdi_enable_ec(p);
08608 ast_hangup(chan);
08609 } else {
08610 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08611
08612
08613 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08614 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08615 S_OR(p->mohsuggest, NULL),
08616 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08617 }
08618 p->subs[SUB_THREEWAY].needhold = 1;
08619 }
08620 }
08621 } else {
08622
08623 if (p->subs[SUB_THREEWAY].inthreeway) {
08624
08625 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08626
08627 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08628
08629 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08630 p->owner = p->subs[SUB_REAL].owner;
08631 }
08632
08633 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08634 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08635 p->subs[SUB_REAL].inthreeway = 0;
08636 p->subs[SUB_THREEWAY].inthreeway = 0;
08637 } else {
08638
08639 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08640 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08641 int otherindex = SUB_THREEWAY;
08642
08643 ast_verb(3, "Building conference call with %s and %s\n",
08644 p->subs[SUB_THREEWAY].owner->name,
08645 p->subs[SUB_REAL].owner->name);
08646
08647 p->subs[SUB_THREEWAY].inthreeway = 1;
08648 p->subs[SUB_REAL].inthreeway = 1;
08649 if (ast->_state == AST_STATE_UP) {
08650 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08651 otherindex = SUB_REAL;
08652 }
08653 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08654 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08655 p->subs[otherindex].needunhold = 1;
08656 p->owner = p->subs[SUB_REAL].owner;
08657 } else {
08658 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08659 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08660 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08661 p->owner = p->subs[SUB_REAL].owner;
08662 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08663 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08664 p->subs[SUB_REAL].needunhold = 1;
08665 dahdi_enable_ec(p);
08666 }
08667 }
08668 }
08669 winkflashdone:
08670 update_conf(p);
08671 break;
08672 case SIG_EM:
08673 case SIG_EM_E1:
08674 case SIG_FEATD:
08675 case SIG_SF:
08676 case SIG_SFWINK:
08677 case SIG_SF_FEATD:
08678 case SIG_FXSLS:
08679 case SIG_FXSGS:
08680 if (p->dialing)
08681 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08682 else
08683 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast->_state, p->channel);
08684 break;
08685 case SIG_FEATDMF_TA:
08686 switch (p->whichwink) {
08687 case 0:
08688 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08689 S_COR(p->owner->caller.ani.number.valid,
08690 p->owner->caller.ani.number.str, ""));
08691 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08692 p->owner->caller.ani2,
08693 S_COR(p->owner->caller.ani.number.valid,
08694 p->owner->caller.ani.number.str, ""));
08695 break;
08696 case 1:
08697 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08698 break;
08699 case 2:
08700 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08701 return NULL;
08702 }
08703 p->whichwink++;
08704
08705 case SIG_FEATDMF:
08706 case SIG_E911:
08707 case SIG_FGC_CAMAMF:
08708 case SIG_FGC_CAMA:
08709 case SIG_FEATB:
08710 case SIG_SF_FEATDMF:
08711 case SIG_SF_FEATB:
08712 case SIG_EMWINK:
08713
08714 if (!ast_strlen_zero(p->dop.dialstr)) {
08715 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08716 if (res < 0) {
08717 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08718 p->dop.dialstr[0] = '\0';
08719 return NULL;
08720 } else
08721 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08722 }
08723 p->dop.dialstr[0] = '\0';
08724 break;
08725 default:
08726 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08727 }
08728 break;
08729 case DAHDI_EVENT_HOOKCOMPLETE:
08730 if (p->inalarm) break;
08731 if ((p->radio || (p->oprmode < 0))) break;
08732 if (p->waitingfordt.tv_sec) break;
08733 switch (mysig) {
08734 case SIG_FXSLS:
08735 case SIG_FXSGS:
08736 case SIG_FXSKS:
08737 case SIG_EM:
08738 case SIG_EM_E1:
08739 case SIG_EMWINK:
08740 case SIG_FEATD:
08741 case SIG_SF:
08742 case SIG_SFWINK:
08743 case SIG_SF_FEATD:
08744 if (!ast_strlen_zero(p->dop.dialstr)) {
08745 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08746 if (res < 0) {
08747 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08748 p->dop.dialstr[0] = '\0';
08749 return NULL;
08750 } else
08751 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08752 }
08753 p->dop.dialstr[0] = '\0';
08754 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08755 break;
08756 case SIG_FEATDMF:
08757 case SIG_FEATDMF_TA:
08758 case SIG_E911:
08759 case SIG_FGC_CAMA:
08760 case SIG_FGC_CAMAMF:
08761 case SIG_FEATB:
08762 case SIG_SF_FEATDMF:
08763 case SIG_SF_FEATB:
08764 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08765 break;
08766 default:
08767 break;
08768 }
08769 break;
08770 case DAHDI_EVENT_POLARITY:
08771
08772
08773
08774
08775
08776
08777 if (p->polarity == POLARITY_IDLE) {
08778 p->polarity = POLARITY_REV;
08779 if (p->answeronpolarityswitch &&
08780 ((ast->_state == AST_STATE_DIALING) ||
08781 (ast->_state == AST_STATE_RINGING))) {
08782 ast_debug(1, "Answering on polarity switch!\n");
08783 ast_setstate(p->owner, AST_STATE_UP);
08784 if (p->hanguponpolarityswitch) {
08785 p->polaritydelaytv = ast_tvnow();
08786 }
08787 } else
08788 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast->_state);
08789 }
08790
08791
08792 if (p->hanguponpolarityswitch &&
08793 (p->polarityonanswerdelay > 0) &&
08794 (p->polarity == POLARITY_REV) &&
08795 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08796
08797 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08798
08799 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08800 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08801 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08802 p->polarity = POLARITY_IDLE;
08803 } else
08804 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %u\n", p->channel, ast->_state);
08805
08806 } else {
08807 p->polarity = POLARITY_IDLE;
08808 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast->_state);
08809 }
08810
08811 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08812 break;
08813 default:
08814 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08815 }
08816 return &p->subs[idx].f;
08817 }
08818
08819 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08820 {
08821 int res;
08822 int idx;
08823 struct ast_frame *f;
08824 int usedindex = -1;
08825 struct dahdi_pvt *p = ast->tech_pvt;
08826
08827 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08828 idx = SUB_REAL;
08829 }
08830
08831 p->subs[idx].f.frametype = AST_FRAME_NULL;
08832 p->subs[idx].f.datalen = 0;
08833 p->subs[idx].f.samples = 0;
08834 p->subs[idx].f.mallocd = 0;
08835 p->subs[idx].f.offset = 0;
08836 p->subs[idx].f.subclass.integer = 0;
08837 p->subs[idx].f.delivery = ast_tv(0,0);
08838 p->subs[idx].f.src = "dahdi_exception";
08839 p->subs[idx].f.data.ptr = NULL;
08840
08841
08842 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08843
08844
08845
08846
08847
08848 if (p->fake_event) {
08849 res = p->fake_event;
08850 p->fake_event = 0;
08851 } else
08852 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08853
08854 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08855 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08856 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08857 p->owner = p->subs[SUB_REAL].owner;
08858 if (p->owner && ast_bridged_channel(p->owner))
08859 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08860 p->subs[SUB_REAL].needunhold = 1;
08861 }
08862 switch (res) {
08863 case DAHDI_EVENT_ONHOOK:
08864 dahdi_disable_ec(p);
08865 if (p->owner) {
08866 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08867 dahdi_ring_phone(p);
08868 p->callwaitingrepeat = 0;
08869 p->cidcwexpire = 0;
08870 p->cid_suppress_expire = 0;
08871 } else
08872 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08873 update_conf(p);
08874 break;
08875 case DAHDI_EVENT_RINGOFFHOOK:
08876 dahdi_enable_ec(p);
08877 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08878 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08879 p->subs[SUB_REAL].needanswer = 1;
08880 p->dialing = 0;
08881 }
08882 break;
08883 case DAHDI_EVENT_HOOKCOMPLETE:
08884 case DAHDI_EVENT_RINGERON:
08885 case DAHDI_EVENT_RINGEROFF:
08886
08887 break;
08888 case DAHDI_EVENT_WINKFLASH:
08889 p->flashtime = ast_tvnow();
08890 if (p->owner) {
08891 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08892 if (p->owner->_state != AST_STATE_UP) {
08893
08894 usedindex = dahdi_get_index(p->owner, p, 0);
08895 if (usedindex > -1) {
08896 p->subs[usedindex].needanswer = 1;
08897 }
08898 ast_setstate(p->owner, AST_STATE_UP);
08899 }
08900 p->callwaitingrepeat = 0;
08901 p->cidcwexpire = 0;
08902 p->cid_suppress_expire = 0;
08903 if (ast_bridged_channel(p->owner))
08904 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08905 p->subs[SUB_REAL].needunhold = 1;
08906 } else
08907 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08908 update_conf(p);
08909 break;
08910 default:
08911 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08912 }
08913 f = &p->subs[idx].f;
08914 return f;
08915 }
08916 if (!(p->radio || (p->oprmode < 0)))
08917 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08918
08919 if (ast != p->owner) {
08920 if (p->owner) {
08921 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08922 }
08923 f = &p->subs[idx].f;
08924 return f;
08925 }
08926
08927 f = dahdi_handle_event(ast);
08928 if (!f) {
08929 const char *name = ast_strdupa(ast->name);
08930
08931
08932 ast_mutex_unlock(&p->lock);
08933 ast_channel_unlock(ast);
08934 ast_set_hangupsource(ast, name, 0);
08935 ast_channel_lock(ast);
08936 ast_mutex_lock(&p->lock);
08937 }
08938 return f;
08939 }
08940
08941 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08942 {
08943 struct dahdi_pvt *p = ast->tech_pvt;
08944 struct ast_frame *f;
08945 ast_mutex_lock(&p->lock);
08946 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08947 struct analog_pvt *analog_p = p->sig_pvt;
08948 f = analog_exception(analog_p, ast);
08949 } else {
08950 f = __dahdi_exception(ast);
08951 }
08952 ast_mutex_unlock(&p->lock);
08953 return f;
08954 }
08955
08956 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08957 {
08958 struct dahdi_pvt *p;
08959 int res;
08960 int idx;
08961 void *readbuf;
08962 struct ast_frame *f;
08963
08964
08965
08966
08967
08968
08969 p = ast->tech_pvt;
08970 while (ast_mutex_trylock(&p->lock)) {
08971 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08972
08973
08974
08975
08976
08977
08978
08979
08980
08981
08982
08983
08984 if (ast->tech_pvt != p) {
08985
08986 return &ast_null_frame;
08987 }
08988 }
08989
08990 idx = dahdi_get_index(ast, p, 0);
08991
08992
08993 if (idx < 0) {
08994 ast_log(LOG_WARNING, "We don't exist?\n");
08995 ast_mutex_unlock(&p->lock);
08996 return NULL;
08997 }
08998
08999 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
09000 ast_mutex_unlock(&p->lock);
09001 return NULL;
09002 }
09003
09004 p->subs[idx].f.frametype = AST_FRAME_NULL;
09005 p->subs[idx].f.datalen = 0;
09006 p->subs[idx].f.samples = 0;
09007 p->subs[idx].f.mallocd = 0;
09008 p->subs[idx].f.offset = 0;
09009 p->subs[idx].f.subclass.integer = 0;
09010 p->subs[idx].f.delivery = ast_tv(0,0);
09011 p->subs[idx].f.src = "dahdi_read";
09012 p->subs[idx].f.data.ptr = NULL;
09013
09014
09015 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
09016 {
09017 struct dahdi_params ps;
09018
09019 memset(&ps, 0, sizeof(ps));
09020 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09021 ast_mutex_unlock(&p->lock);
09022 return NULL;
09023 }
09024 p->firstradio = 1;
09025 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09026 if (ps.rxisoffhook)
09027 {
09028 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09029 }
09030 else
09031 {
09032 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09033 }
09034 ast_mutex_unlock(&p->lock);
09035 return &p->subs[idx].f;
09036 }
09037 if (p->ringt > 0) {
09038 if (!(--p->ringt)) {
09039 ast_mutex_unlock(&p->lock);
09040 return NULL;
09041 }
09042 }
09043
09044 #ifdef HAVE_OPENR2
09045 if (p->mfcr2) {
09046 openr2_chan_process_event(p->r2chan);
09047 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09048 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09049
09050
09051 if (p->mfcr2_call_accepted &&
09052 !p->mfcr2_progress &&
09053 ast->_state == AST_STATE_RINGING) {
09054 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09055 ast_queue_frame(p->owner, &f);
09056 p->mfcr2_progress = 1;
09057 }
09058 }
09059 }
09060 #endif
09061
09062 if (p->subs[idx].needringing) {
09063
09064 p->subs[idx].needringing = 0;
09065 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09066 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09067 ast_setstate(ast, AST_STATE_RINGING);
09068 ast_mutex_unlock(&p->lock);
09069 return &p->subs[idx].f;
09070 }
09071
09072 if (p->subs[idx].needbusy) {
09073
09074 p->subs[idx].needbusy = 0;
09075 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09076 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09077 ast_mutex_unlock(&p->lock);
09078 return &p->subs[idx].f;
09079 }
09080
09081 if (p->subs[idx].needcongestion) {
09082
09083 p->subs[idx].needcongestion = 0;
09084 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09085 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09086 ast_mutex_unlock(&p->lock);
09087 return &p->subs[idx].f;
09088 }
09089
09090 if (p->subs[idx].needanswer) {
09091
09092 p->subs[idx].needanswer = 0;
09093 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09094 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09095 ast_mutex_unlock(&p->lock);
09096 return &p->subs[idx].f;
09097 }
09098 #ifdef HAVE_OPENR2
09099 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09100
09101
09102
09103
09104 ast_mutex_unlock(&p->lock);
09105 return &ast_null_frame;
09106 }
09107 #endif
09108
09109 if (p->subs[idx].needflash) {
09110
09111 p->subs[idx].needflash = 0;
09112 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09113 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09114 ast_mutex_unlock(&p->lock);
09115 return &p->subs[idx].f;
09116 }
09117
09118 if (p->subs[idx].needhold) {
09119
09120 p->subs[idx].needhold = 0;
09121 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09122 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09123 ast_mutex_unlock(&p->lock);
09124 ast_debug(1, "Sending hold on '%s'\n", ast->name);
09125 return &p->subs[idx].f;
09126 }
09127
09128 if (p->subs[idx].needunhold) {
09129
09130 p->subs[idx].needunhold = 0;
09131 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09132 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09133 ast_mutex_unlock(&p->lock);
09134 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09135 return &p->subs[idx].f;
09136 }
09137
09138
09139
09140
09141
09142 if (p->fake_event && p->owner == ast) {
09143 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09144 struct analog_pvt *analog_p = p->sig_pvt;
09145
09146 f = analog_exception(analog_p, ast);
09147 } else {
09148 f = __dahdi_exception(ast);
09149 }
09150 ast_mutex_unlock(&p->lock);
09151 return f;
09152 }
09153
09154 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09155 if (!p->subs[idx].linear) {
09156 p->subs[idx].linear = 1;
09157 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09158 if (res)
09159 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09160 }
09161 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09162 (ast->rawreadformat == AST_FORMAT_ALAW)) {
09163 if (p->subs[idx].linear) {
09164 p->subs[idx].linear = 0;
09165 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09166 if (res)
09167 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09168 }
09169 } else {
09170 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09171 ast_mutex_unlock(&p->lock);
09172 return NULL;
09173 }
09174 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09175 CHECK_BLOCKING(ast);
09176 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09177 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09178
09179 if (res < 0) {
09180 f = NULL;
09181 if (res == -1) {
09182 if (errno == EAGAIN) {
09183
09184 ast_mutex_unlock(&p->lock);
09185 return &p->subs[idx].f;
09186 } else if (errno == ELAST) {
09187 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09188 struct analog_pvt *analog_p = p->sig_pvt;
09189 f = analog_exception(analog_p, ast);
09190 } else {
09191 f = __dahdi_exception(ast);
09192 }
09193 } else
09194 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09195 }
09196 ast_mutex_unlock(&p->lock);
09197 return f;
09198 }
09199 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09200 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09201 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09202 struct analog_pvt *analog_p = p->sig_pvt;
09203 f = analog_exception(analog_p, ast);
09204 } else {
09205 f = __dahdi_exception(ast);
09206 }
09207 ast_mutex_unlock(&p->lock);
09208 return f;
09209 }
09210 if (p->tdd) {
09211 int c;
09212
09213 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09214 if (c < 0) {
09215 ast_debug(1,"tdd_feed failed\n");
09216 ast_mutex_unlock(&p->lock);
09217 return NULL;
09218 }
09219 if (c) {
09220 p->subs[idx].f.subclass.integer = 0;
09221 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09222 p->subs[idx].f.mallocd = 0;
09223 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09224 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09225 p->subs[idx].f.datalen = 1;
09226 *((char *) p->subs[idx].f.data.ptr) = c;
09227 ast_mutex_unlock(&p->lock);
09228 return &p->subs[idx].f;
09229 }
09230 }
09231 if (idx == SUB_REAL) {
09232
09233 if (p->cidcwexpire) {
09234 if (!--p->cidcwexpire) {
09235
09236 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09237 restore_conference(p);
09238 }
09239 }
09240 if (p->cid_suppress_expire) {
09241 --p->cid_suppress_expire;
09242 }
09243 if (p->callwaitingrepeat) {
09244 if (!--p->callwaitingrepeat) {
09245
09246 ++p->callwaitrings;
09247 dahdi_callwait(ast);
09248 }
09249 }
09250 }
09251 if (p->subs[idx].linear) {
09252 p->subs[idx].f.datalen = READ_SIZE * 2;
09253 } else
09254 p->subs[idx].f.datalen = READ_SIZE;
09255
09256
09257 if ((p->owner == ast) && p->cidspill) {
09258 send_callerid(p);
09259 }
09260
09261 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09262 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09263 p->subs[idx].f.samples = READ_SIZE;
09264 p->subs[idx].f.mallocd = 0;
09265 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09266 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09267 #if 0
09268 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09269 #endif
09270 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio ||
09271 (idx && (ast->_state != AST_STATE_UP)) ||
09272 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09273 ) {
09274
09275
09276 p->subs[idx].f.frametype = AST_FRAME_NULL;
09277 p->subs[idx].f.subclass.integer = 0;
09278 p->subs[idx].f.samples = 0;
09279 p->subs[idx].f.mallocd = 0;
09280 p->subs[idx].f.offset = 0;
09281 p->subs[idx].f.data.ptr = NULL;
09282 p->subs[idx].f.datalen= 0;
09283 }
09284 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09285
09286 int mute;
09287
09288 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09289
09290
09291 mute = ast_dsp_was_muted(p->dsp);
09292 if (p->muting != mute) {
09293 p->muting = mute;
09294 dahdi_confmute(p, mute);
09295 }
09296
09297 if (f) {
09298 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09299 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09300
09301
09302 ast_frfree(f);
09303 f = NULL;
09304 }
09305 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09306 || f->frametype == AST_FRAME_DTMF_END) {
09307 #ifdef HAVE_PRI
09308 if (dahdi_sig_pri_lib_handles(p->sig)
09309 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09310 && p->pri
09311 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09312 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09313
09314 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09315 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09316 (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
09317
09318 f->frametype = AST_FRAME_NULL;
09319 f->subclass.integer = 0;
09320 }
09321 #endif
09322
09323 p->pulsedial = 0;
09324 } else if (p->waitingfordt.tv_sec) {
09325 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09326 p->waitingfordt.tv_sec = 0;
09327 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09328 ast_frfree(f);
09329 f = NULL;
09330 } else if (f->frametype == AST_FRAME_VOICE) {
09331 f->frametype = AST_FRAME_NULL;
09332 f->subclass.integer = 0;
09333 if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
09334 p->waitingfordt.tv_sec = 0;
09335 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09336 ast_dsp_set_features(p->dsp, p->dsp_features);
09337 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09338 if (!ast_strlen_zero(p->dop.dialstr)) {
09339 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09340 if (res < 0) {
09341 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09342 p->dop.dialstr[0] = '\0';
09343 ast_mutex_unlock(&p->lock);
09344 ast_frfree(f);
09345 return NULL;
09346 } else {
09347 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09348 p->dialing = 1;
09349 p->dop.dialstr[0] = '\0';
09350 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09351 ast_setstate(ast, AST_STATE_DIALING);
09352 }
09353 }
09354 }
09355 }
09356 }
09357 }
09358 } else
09359 f = &p->subs[idx].f;
09360
09361 if (f) {
09362 switch (f->frametype) {
09363 case AST_FRAME_DTMF_BEGIN:
09364 case AST_FRAME_DTMF_END:
09365 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09366 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09367 } else {
09368 dahdi_handle_dtmf(ast, idx, &f);
09369 }
09370 break;
09371 case AST_FRAME_VOICE:
09372 if (p->cidspill || p->cid_suppress_expire) {
09373
09374 p->subs[idx].f.frametype = AST_FRAME_NULL;
09375 p->subs[idx].f.subclass.integer = 0;
09376 p->subs[idx].f.samples = 0;
09377 p->subs[idx].f.mallocd = 0;
09378 p->subs[idx].f.offset = 0;
09379 p->subs[idx].f.data.ptr = NULL;
09380 p->subs[idx].f.datalen= 0;
09381 }
09382 break;
09383 default:
09384 break;
09385 }
09386 }
09387
09388 ast_mutex_unlock(&p->lock);
09389 return f;
09390 }
09391
09392 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09393 {
09394 int sent=0;
09395 int size;
09396 int res;
09397 int fd;
09398 fd = p->subs[idx].dfd;
09399 while (len) {
09400 size = len;
09401 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09402 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09403 res = write(fd, buf, size);
09404 if (res != size) {
09405 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09406 return sent;
09407 }
09408 len -= size;
09409 buf += size;
09410 }
09411 return sent;
09412 }
09413
09414 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09415 {
09416 struct dahdi_pvt *p = ast->tech_pvt;
09417 int res;
09418 int idx;
09419 idx = dahdi_get_index(ast, p, 0);
09420 if (idx < 0) {
09421 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09422 return -1;
09423 }
09424
09425
09426 if (frame->frametype != AST_FRAME_VOICE) {
09427 if (frame->frametype != AST_FRAME_IMAGE)
09428 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
09429 return 0;
09430 }
09431 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09432 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09433 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09434 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09435 return -1;
09436 }
09437 if (p->dialing) {
09438 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09439 return 0;
09440 }
09441 if (!p->owner) {
09442 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09443 return 0;
09444 }
09445 if (p->cidspill) {
09446 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09447 ast->name);
09448 return 0;
09449 }
09450
09451 if (!frame->data.ptr || !frame->datalen)
09452 return 0;
09453
09454 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09455 if (!p->subs[idx].linear) {
09456 p->subs[idx].linear = 1;
09457 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09458 if (res)
09459 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09460 }
09461 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09462 } else {
09463
09464 if (p->subs[idx].linear) {
09465 p->subs[idx].linear = 0;
09466 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09467 if (res)
09468 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09469 }
09470 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09471 }
09472 if (res < 0) {
09473 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09474 return -1;
09475 }
09476 return 0;
09477 }
09478
09479 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09480 {
09481 struct dahdi_pvt *p = chan->tech_pvt;
09482 int res=-1;
09483 int idx;
09484 int func = DAHDI_FLASH;
09485
09486 ast_mutex_lock(&p->lock);
09487 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09488 switch (p->sig) {
09489 #if defined(HAVE_PRI)
09490 case SIG_PRI_LIB_HANDLE_CASES:
09491 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09492 ast_mutex_unlock(&p->lock);
09493 return res;
09494 #endif
09495 #if defined(HAVE_SS7)
09496 case SIG_SS7:
09497 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09498 ast_mutex_unlock(&p->lock);
09499 return res;
09500 #endif
09501 default:
09502 break;
09503 }
09504 #ifdef HAVE_OPENR2
09505 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09506 ast_mutex_unlock(&p->lock);
09507
09508
09509 return 0;
09510 }
09511 #endif
09512 idx = dahdi_get_index(chan, p, 0);
09513 if (idx == SUB_REAL) {
09514 switch (condition) {
09515 case AST_CONTROL_BUSY:
09516 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09517 break;
09518 case AST_CONTROL_RINGING:
09519 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09520
09521 if (chan->_state != AST_STATE_UP) {
09522 if ((chan->_state != AST_STATE_RING) ||
09523 ((p->sig != SIG_FXSKS) &&
09524 (p->sig != SIG_FXSLS) &&
09525 (p->sig != SIG_FXSGS)))
09526 ast_setstate(chan, AST_STATE_RINGING);
09527 }
09528 break;
09529 case AST_CONTROL_INCOMPLETE:
09530 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09531
09532 res = 0;
09533 break;
09534 case AST_CONTROL_PROCEEDING:
09535 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09536
09537 res = 0;
09538 break;
09539 case AST_CONTROL_PROGRESS:
09540 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09541
09542 res = 0;
09543 break;
09544 case AST_CONTROL_CONGESTION:
09545
09546 switch (chan->hangupcause) {
09547 case AST_CAUSE_USER_BUSY:
09548 case AST_CAUSE_NORMAL_CLEARING:
09549 case 0:
09550
09551 chan->hangupcause = AST_CAUSE_CONGESTION;
09552 break;
09553 default:
09554 break;
09555 }
09556 break;
09557 case AST_CONTROL_HOLD:
09558 ast_moh_start(chan, data, p->mohinterpret);
09559 break;
09560 case AST_CONTROL_UNHOLD:
09561 ast_moh_stop(chan);
09562 break;
09563 case AST_CONTROL_RADIO_KEY:
09564 if (p->radio)
09565 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09566 res = 0;
09567 break;
09568 case AST_CONTROL_RADIO_UNKEY:
09569 if (p->radio)
09570 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09571 res = 0;
09572 break;
09573 case AST_CONTROL_FLASH:
09574
09575 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09576
09577 p->dop.dialstr[0] = '\0';
09578 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09579 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09580 chan->name, strerror(errno));
09581 } else
09582 res = 0;
09583 } else
09584 res = 0;
09585 break;
09586 case AST_CONTROL_SRCUPDATE:
09587 res = 0;
09588 break;
09589 case -1:
09590 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09591 break;
09592 }
09593 } else {
09594 res = 0;
09595 }
09596 ast_mutex_unlock(&p->lock);
09597 return res;
09598 }
09599
09600 #if defined(HAVE_PRI)
09601 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09602 #else
09603 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09604 #endif
09605 {
09606 struct ast_str *chan_name;
09607 int x, y;
09608
09609
09610 if (!(chan_name = ast_str_create(32))) {
09611 return NULL;
09612 }
09613 if (i->channel == CHAN_PSEUDO) {
09614 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09615 #if defined(HAVE_PRI)
09616 } else if (i->pri) {
09617 ast_mutex_lock(&i->pri->lock);
09618 y = ++i->pri->new_chan_seq;
09619 if (is_outgoing) {
09620 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
09621 address[0] = '\0';
09622 } else if (ast_strlen_zero(i->cid_subaddr)) {
09623
09624 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
09625 } else {
09626
09627 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09628 i->cid_subaddr, (unsigned)y);
09629 }
09630 ast_mutex_unlock(&i->pri->lock);
09631 #endif
09632 } else {
09633 y = 1;
09634 do {
09635 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09636 for (x = 0; x < 3; ++x) {
09637 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09638 i->subs[x].owner->name + 6)) {
09639 break;
09640 }
09641 }
09642 ++y;
09643 } while (x < 3);
09644 }
09645 return chan_name;
09646 }
09647
09648 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09649 {
09650 struct ast_channel *tmp;
09651 format_t deflaw;
09652 int x;
09653 int features;
09654 struct ast_str *chan_name;
09655 struct ast_variable *v;
09656 char *dashptr;
09657 char device_name[AST_CHANNEL_NAME];
09658
09659 if (i->subs[idx].owner) {
09660 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09661 return NULL;
09662 }
09663
09664 #if defined(HAVE_PRI)
09665
09666
09667
09668
09669 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09670 #else
09671 chan_name = create_channel_name(i);
09672 #endif
09673 if (!chan_name) {
09674 return NULL;
09675 }
09676
09677 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
09678 ast_free(chan_name);
09679 if (!tmp)
09680 return NULL;
09681 tmp->tech = &dahdi_tech;
09682 #if defined(HAVE_PRI)
09683 if (i->pri) {
09684 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09685 }
09686 #endif
09687 ast_channel_cc_params_init(tmp, i->cc_params);
09688 if (law) {
09689 i->law = law;
09690 if (law == DAHDI_LAW_ALAW) {
09691 deflaw = AST_FORMAT_ALAW;
09692 } else {
09693 deflaw = AST_FORMAT_ULAW;
09694 }
09695 } else {
09696 switch (i->sig) {
09697 case SIG_PRI_LIB_HANDLE_CASES:
09698
09699 i->law = (i->law_default == DAHDI_LAW_ALAW)
09700 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09701 break;
09702 default:
09703 i->law = i->law_default;
09704 break;
09705 }
09706 if (i->law_default == DAHDI_LAW_ALAW) {
09707 deflaw = AST_FORMAT_ALAW;
09708 } else {
09709 deflaw = AST_FORMAT_ULAW;
09710 }
09711 }
09712 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09713 tmp->nativeformats = deflaw;
09714
09715 tmp->rawreadformat = deflaw;
09716 tmp->readformat = deflaw;
09717 tmp->rawwriteformat = deflaw;
09718 tmp->writeformat = deflaw;
09719 i->subs[idx].linear = 0;
09720 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09721 features = 0;
09722 if (idx == SUB_REAL) {
09723 if (i->busydetect && CANBUSYDETECT(i))
09724 features |= DSP_FEATURE_BUSY_DETECT;
09725 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09726 features |= DSP_FEATURE_CALL_PROGRESS;
09727 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09728 features |= DSP_FEATURE_WAITDIALTONE;
09729 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09730 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09731 features |= DSP_FEATURE_FAX_DETECT;
09732 }
09733 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09734 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09735 i->hardwaredtmf = 0;
09736 features |= DSP_FEATURE_DIGIT_DETECT;
09737 } else if (NEED_MFDETECT(i)) {
09738 i->hardwaredtmf = 1;
09739 features |= DSP_FEATURE_DIGIT_DETECT;
09740 }
09741 }
09742 if (features) {
09743 if (i->dsp) {
09744 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09745 } else {
09746 if (i->channel != CHAN_PSEUDO)
09747 i->dsp = ast_dsp_new();
09748 else
09749 i->dsp = NULL;
09750 if (i->dsp) {
09751 i->dsp_features = features;
09752 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09753
09754 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09755
09756
09757 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09758 features = 0;
09759 }
09760 #endif
09761 ast_dsp_set_features(i->dsp, features);
09762 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09763 if (!ast_strlen_zero(progzone))
09764 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09765 if (i->busydetect && CANBUSYDETECT(i)) {
09766 if(i->silencethreshold > 0)
09767 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09768 ast_dsp_set_busy_count(i->dsp, i->busycount);
09769 if(i->busytonelength > 0)
09770 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09771 if((i->busytonelength == i->busyquietlength) && i->busycompare)
09772 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09773 }
09774 }
09775 }
09776 }
09777
09778 if (state == AST_STATE_RING)
09779 tmp->rings = 1;
09780 tmp->tech_pvt = i;
09781 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09782
09783 tmp->callgroup = i->callgroup;
09784 tmp->pickupgroup = i->pickupgroup;
09785 }
09786 if (!ast_strlen_zero(i->parkinglot))
09787 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09788 if (!ast_strlen_zero(i->language))
09789 ast_string_field_set(tmp, language, i->language);
09790 if (!i->owner)
09791 i->owner = tmp;
09792 if (!ast_strlen_zero(i->accountcode))
09793 ast_string_field_set(tmp, accountcode, i->accountcode);
09794 if (i->amaflags)
09795 tmp->amaflags = i->amaflags;
09796 i->subs[idx].owner = tmp;
09797 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09798 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09799 ast_string_field_set(tmp, call_forward, i->call_forward);
09800 }
09801
09802 if (!i->adsi)
09803 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09804 if (!ast_strlen_zero(i->exten))
09805 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09806 if (!ast_strlen_zero(i->rdnis)) {
09807 tmp->redirecting.from.number.valid = 1;
09808 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09809 }
09810 if (!ast_strlen_zero(i->dnid)) {
09811 tmp->dialed.number.str = ast_strdup(i->dnid);
09812 }
09813
09814
09815
09816 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09817 if (!ast_strlen_zero(i->cid_ani)) {
09818 tmp->caller.ani.number.valid = 1;
09819 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09820 } else if (!ast_strlen_zero(i->cid_num)) {
09821 tmp->caller.ani.number.valid = 1;
09822 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09823 }
09824 #else
09825 if (!ast_strlen_zero(i->cid_num)) {
09826 tmp->caller.ani.number.valid = 1;
09827 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09828 }
09829 #endif
09830 tmp->caller.id.name.presentation = i->callingpres;
09831 tmp->caller.id.number.presentation = i->callingpres;
09832 tmp->caller.id.number.plan = i->cid_ton;
09833 tmp->caller.ani2 = i->cid_ani2;
09834 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09835
09836 i->fake_event = 0;
09837
09838 dahdi_confmute(i, 0);
09839 i->muting = 0;
09840
09841 ast_jb_configure(tmp, &global_jbconf);
09842
09843
09844 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09845 dashptr = strrchr(device_name, '-');
09846 if (dashptr) {
09847 *dashptr = '\0';
09848 }
09849 tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09850 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09851
09852 for (v = i->vars ; v ; v = v->next)
09853 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09854
09855 ast_module_ref(ast_module_info->self);
09856
09857 dahdi_ami_channel_event(i, tmp);
09858 if (startpbx) {
09859 #ifdef HAVE_OPENR2
09860 if (i->mfcr2call) {
09861 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09862 }
09863 #endif
09864 if (ast_pbx_start(tmp)) {
09865 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09866 ast_hangup(tmp);
09867 return NULL;
09868 }
09869 }
09870 return tmp;
09871 }
09872
09873
09874 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09875 {
09876 char c;
09877
09878 *str = 0;
09879 for (;;)
09880 {
09881
09882 c = ast_waitfordigit(chan, ms);
09883
09884 if (c < 1)
09885 return c;
09886 *str++ = c;
09887 *str = 0;
09888 if (strchr(term, c))
09889 return 1;
09890 }
09891 }
09892
09893 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09894 {
09895 int j;
09896 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09897 for (;;)
09898 {
09899
09900 j = DAHDI_IOMUX_SIGEVENT;
09901
09902 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09903
09904 if (j & DAHDI_IOMUX_SIGEVENT) break;
09905 }
09906
09907 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09908 return 0;
09909 }
09910
09911
09912
09913
09914
09915
09916
09917
09918
09919
09920 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09921 {
09922 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09923 return analog_dnd(dahdichan->sig_pvt, flag);
09924 }
09925
09926 if (flag == -1) {
09927 return dahdichan->dnd;
09928 }
09929
09930
09931 dahdichan->dnd = flag;
09932 ast_verb(3, "%s DND on channel %d\n",
09933 flag? "Enabled" : "Disabled",
09934 dahdichan->channel);
09935 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09936 "Channel: DAHDI/%d\r\n"
09937 "Status: %s\r\n", dahdichan->channel,
09938 flag? "enabled" : "disabled");
09939
09940 return 0;
09941 }
09942
09943 static int canmatch_featurecode(const char *exten)
09944 {
09945 int extlen = strlen(exten);
09946 const char *pickup_ext;
09947 if (!extlen) {
09948 return 1;
09949 }
09950 pickup_ext = ast_pickup_ext();
09951 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09952 return 1;
09953 }
09954
09955 if (exten[0] == '*' && extlen < 3) {
09956 if (extlen == 1) {
09957 return 1;
09958 }
09959
09960 switch (exten[1]) {
09961 case '6':
09962 case '7':
09963 case '8':
09964 return 1;
09965 }
09966 }
09967 return 0;
09968 }
09969
09970 static void *analog_ss_thread(void *data)
09971 {
09972 struct ast_channel *chan = data;
09973 struct dahdi_pvt *p = chan->tech_pvt;
09974 char exten[AST_MAX_EXTENSION] = "";
09975 char exten2[AST_MAX_EXTENSION] = "";
09976 unsigned char buf[256];
09977 char dtmfcid[300];
09978 char dtmfbuf[300];
09979 struct callerid_state *cs = NULL;
09980 char *name = NULL, *number = NULL;
09981 int distMatches;
09982 int curRingData[3];
09983 int receivedRingT;
09984 int counter1;
09985 int counter;
09986 int samples = 0;
09987 struct ast_smdi_md_message *smdi_msg = NULL;
09988 int flags = 0;
09989 int i;
09990 int timeout;
09991 int getforward = 0;
09992 char *s1, *s2;
09993 int len = 0;
09994 int res;
09995 int idx;
09996
09997 ast_mutex_lock(&ss_thread_lock);
09998 ss_thread_count++;
09999 ast_mutex_unlock(&ss_thread_lock);
10000
10001
10002
10003 if (!p) {
10004 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
10005 ast_hangup(chan);
10006 goto quit;
10007 }
10008 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
10009 idx = dahdi_get_index(chan, p, 1);
10010 if (idx < 0) {
10011 ast_log(LOG_WARNING, "Huh?\n");
10012 ast_hangup(chan);
10013 goto quit;
10014 }
10015 if (p->dsp)
10016 ast_dsp_digitreset(p->dsp);
10017 switch (p->sig) {
10018 case SIG_FEATD:
10019 case SIG_FEATDMF:
10020 case SIG_FEATDMF_TA:
10021 case SIG_E911:
10022 case SIG_FGC_CAMAMF:
10023 case SIG_FEATB:
10024 case SIG_EMWINK:
10025 case SIG_SF_FEATD:
10026 case SIG_SF_FEATDMF:
10027 case SIG_SF_FEATB:
10028 case SIG_SFWINK:
10029 if (dahdi_wink(p, idx))
10030 goto quit;
10031
10032 case SIG_EM:
10033 case SIG_EM_E1:
10034 case SIG_SF:
10035 case SIG_FGC_CAMA:
10036 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10037 if (p->dsp)
10038 ast_dsp_digitreset(p->dsp);
10039
10040 if (p->dsp) {
10041 if (NEED_MFDETECT(p))
10042 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10043 else
10044 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10045 }
10046 memset(dtmfbuf, 0, sizeof(dtmfbuf));
10047
10048 if (!p->immediate)
10049
10050 res = ast_waitfordigit(chan, 5000);
10051 else
10052 res = 0;
10053 if (res > 0) {
10054
10055 dtmfbuf[0] = res;
10056 switch (p->sig) {
10057 case SIG_FEATD:
10058 case SIG_SF_FEATD:
10059 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10060 if (res > 0)
10061 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10062 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10063 break;
10064 case SIG_FEATDMF_TA:
10065 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10066 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10067 if (dahdi_wink(p, idx)) goto quit;
10068 dtmfbuf[0] = 0;
10069
10070 res = ast_waitfordigit(chan, 5000);
10071 if (res <= 0) break;
10072 dtmfbuf[0] = res;
10073
10074 case SIG_FEATDMF:
10075 case SIG_E911:
10076 case SIG_FGC_CAMAMF:
10077 case SIG_SF_FEATDMF:
10078 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10079
10080 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10081 {
10082 if (dahdi_wink(p, idx)) goto quit;
10083 dtmfbuf[0] = 0;
10084
10085 res = ast_waitfordigit(chan, 5000);
10086 if (res <= 0) break;
10087 dtmfbuf[0] = res;
10088 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10089 }
10090 if (res > 0) {
10091
10092 if (p->sig == SIG_E911)
10093 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10094 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10095 }
10096 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10097 break;
10098 case SIG_FEATB:
10099 case SIG_SF_FEATB:
10100 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10101 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10102 break;
10103 case SIG_EMWINK:
10104
10105
10106
10107
10108 if (res == '*') {
10109 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10110 if (res > 0)
10111 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10112 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10113 break;
10114 }
10115 default:
10116
10117 len = 1;
10118 dtmfbuf[len] = '\0';
10119 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10120 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10121 timeout = matchdigittimeout;
10122 } else {
10123 timeout = gendigittimeout;
10124 }
10125 res = ast_waitfordigit(chan, timeout);
10126 if (res < 0) {
10127 ast_debug(1, "waitfordigit returned < 0...\n");
10128 ast_hangup(chan);
10129 goto quit;
10130 } else if (res) {
10131 dtmfbuf[len++] = res;
10132 dtmfbuf[len] = '\0';
10133 } else {
10134 break;
10135 }
10136 }
10137 break;
10138 }
10139 }
10140 if (res == -1) {
10141 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10142 ast_hangup(chan);
10143 goto quit;
10144 } else if (res < 0) {
10145 ast_debug(1, "Got hung up before digits finished\n");
10146 ast_hangup(chan);
10147 goto quit;
10148 }
10149
10150 if (p->sig == SIG_FGC_CAMA) {
10151 char anibuf[100];
10152
10153 if (ast_safe_sleep(chan,1000) == -1) {
10154 ast_hangup(chan);
10155 goto quit;
10156 }
10157 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10158 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10159 res = my_getsigstr(chan, anibuf, "#", 10000);
10160 if ((res > 0) && (strlen(anibuf) > 2)) {
10161 if (anibuf[strlen(anibuf) - 1] == '#')
10162 anibuf[strlen(anibuf) - 1] = 0;
10163 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10164 }
10165 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10166 }
10167
10168 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10169 if (ast_strlen_zero(exten))
10170 ast_copy_string(exten, "s", sizeof(exten));
10171 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10172
10173 if (exten[0] == '*') {
10174 char *stringp=NULL;
10175 ast_copy_string(exten2, exten, sizeof(exten2));
10176
10177 stringp=exten2 +1;
10178 s1 = strsep(&stringp, "*");
10179 s2 = strsep(&stringp, "*");
10180 if (s2) {
10181 if (!ast_strlen_zero(p->cid_num))
10182 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10183 else
10184 ast_set_callerid(chan, s1, NULL, s1);
10185 ast_copy_string(exten, s2, sizeof(exten));
10186 } else
10187 ast_copy_string(exten, s1, sizeof(exten));
10188 } else if (p->sig == SIG_FEATD)
10189 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10190 }
10191 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10192 if (exten[0] == '*') {
10193 char *stringp=NULL;
10194 ast_copy_string(exten2, exten, sizeof(exten2));
10195
10196 stringp=exten2 +1;
10197 s1 = strsep(&stringp, "#");
10198 s2 = strsep(&stringp, "#");
10199 if (s2) {
10200 if (!ast_strlen_zero(p->cid_num))
10201 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10202 else
10203 if (*(s1 + 2))
10204 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10205 ast_copy_string(exten, s2 + 1, sizeof(exten));
10206 } else
10207 ast_copy_string(exten, s1 + 2, sizeof(exten));
10208 } else
10209 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10210 }
10211 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10212 if (exten[0] == '*') {
10213 char *stringp=NULL;
10214 ast_copy_string(exten2, exten, sizeof(exten2));
10215
10216 stringp=exten2 +1;
10217 s1 = strsep(&stringp, "#");
10218 s2 = strsep(&stringp, "#");
10219 if (s2 && (*(s2 + 1) == '0')) {
10220 if (*(s2 + 2))
10221 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10222 }
10223 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10224 else ast_copy_string(exten, "911", sizeof(exten));
10225 } else
10226 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10227 }
10228 if (p->sig == SIG_FEATB) {
10229 if (exten[0] == '*') {
10230 char *stringp=NULL;
10231 ast_copy_string(exten2, exten, sizeof(exten2));
10232
10233 stringp=exten2 +1;
10234 s1 = strsep(&stringp, "#");
10235 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10236 } else
10237 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10238 }
10239 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10240 dahdi_wink(p, idx);
10241
10242
10243
10244 if (ast_safe_sleep(chan, 100)) {
10245 ast_hangup(chan);
10246 goto quit;
10247 }
10248 }
10249 dahdi_enable_ec(p);
10250 if (NEED_MFDETECT(p)) {
10251 if (p->dsp) {
10252 if (!p->hardwaredtmf)
10253 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10254 else {
10255 ast_dsp_free(p->dsp);
10256 p->dsp = NULL;
10257 }
10258 }
10259 }
10260
10261 if (ast_exists_extension(chan, chan->context, exten, 1,
10262 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10263 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10264 if (p->dsp) ast_dsp_digitreset(p->dsp);
10265 res = ast_pbx_run(chan);
10266 if (res) {
10267 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10268 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10269 }
10270 goto quit;
10271 } else {
10272 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10273 sleep(2);
10274 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10275 if (res < 0)
10276 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10277 else
10278 sleep(1);
10279 res = ast_streamfile(chan, "ss-noservice", chan->language);
10280 if (res >= 0)
10281 ast_waitstream(chan, "");
10282 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10283 ast_hangup(chan);
10284 goto quit;
10285 }
10286 break;
10287 case SIG_FXOLS:
10288 case SIG_FXOGS:
10289 case SIG_FXOKS:
10290
10291 timeout = firstdigittimeout;
10292
10293
10294 if (p->subs[SUB_THREEWAY].owner)
10295 timeout = 999999;
10296 while (len < AST_MAX_EXTENSION-1) {
10297
10298
10299 if (p->immediate)
10300 res = 's';
10301 else
10302 res = ast_waitfordigit(chan, timeout);
10303 timeout = 0;
10304 if (res < 0) {
10305 ast_debug(1, "waitfordigit returned < 0...\n");
10306 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10307 ast_hangup(chan);
10308 goto quit;
10309 } else if (res) {
10310 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10311 exten[len++]=res;
10312 exten[len] = '\0';
10313 }
10314 if (!ast_ignore_pattern(chan->context, exten))
10315 tone_zone_play_tone(p->subs[idx].dfd, -1);
10316 else
10317 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10318 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10319 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10320 if (getforward) {
10321
10322 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10323 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10324 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10325 if (res)
10326 break;
10327 usleep(500000);
10328 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10329 sleep(1);
10330 memset(exten, 0, sizeof(exten));
10331 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10332 len = 0;
10333 getforward = 0;
10334 } else {
10335 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10336 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10337 if (!ast_strlen_zero(p->cid_num)) {
10338 if (!p->hidecallerid)
10339 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10340 else
10341 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10342 }
10343 if (!ast_strlen_zero(p->cid_name)) {
10344 if (!p->hidecallerid)
10345 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10346 }
10347 ast_setstate(chan, AST_STATE_RING);
10348 dahdi_enable_ec(p);
10349 res = ast_pbx_run(chan);
10350 if (res) {
10351 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10352 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10353 }
10354 goto quit;
10355 }
10356 } else {
10357
10358
10359 timeout = matchdigittimeout;
10360 }
10361 } else if (res == 0) {
10362 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10363 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10364 dahdi_wait_event(p->subs[idx].dfd);
10365 ast_hangup(chan);
10366 goto quit;
10367 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10368 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10369
10370 p->callwaiting = 0;
10371 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10372 if (res) {
10373 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10374 chan->name, strerror(errno));
10375 }
10376 len = 0;
10377 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10378 memset(exten, 0, sizeof(exten));
10379 timeout = firstdigittimeout;
10380
10381 } else if (!strcmp(exten,ast_pickup_ext())) {
10382
10383
10384
10385
10386 if (idx == SUB_REAL) {
10387
10388 if (p->subs[SUB_THREEWAY].owner) {
10389
10390
10391 alloc_sub(p, SUB_CALLWAIT);
10392 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10393 unalloc_sub(p, SUB_THREEWAY);
10394 }
10395 dahdi_enable_ec(p);
10396 if (ast_pickup_call(chan)) {
10397 ast_debug(1, "No call pickup possible...\n");
10398 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10399 dahdi_wait_event(p->subs[idx].dfd);
10400 }
10401 ast_hangup(chan);
10402 goto quit;
10403 } else {
10404 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10405 ast_hangup(chan);
10406 goto quit;
10407 }
10408
10409 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10410 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10411
10412 p->hidecallerid = 1;
10413 ast_party_number_free(&chan->caller.id.number);
10414 ast_party_number_init(&chan->caller.id.number);
10415 ast_party_name_free(&chan->caller.id.name);
10416 ast_party_name_init(&chan->caller.id.name);
10417 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10418 if (res) {
10419 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10420 chan->name, strerror(errno));
10421 }
10422 len = 0;
10423 memset(exten, 0, sizeof(exten));
10424 timeout = firstdigittimeout;
10425 } else if (p->callreturn && !strcmp(exten, "*69")) {
10426 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10427 break;
10428 } else if (!strcmp(exten, "*78")) {
10429 dahdi_dnd(p, 1);
10430
10431 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10432 getforward = 0;
10433 memset(exten, 0, sizeof(exten));
10434 len = 0;
10435 } else if (!strcmp(exten, "*79")) {
10436 dahdi_dnd(p, 0);
10437
10438 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10439 getforward = 0;
10440 memset(exten, 0, sizeof(exten));
10441 len = 0;
10442 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10443 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10444 getforward = 1;
10445 memset(exten, 0, sizeof(exten));
10446 len = 0;
10447 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10448 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10449 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10450 memset(p->call_forward, 0, sizeof(p->call_forward));
10451 getforward = 0;
10452 memset(exten, 0, sizeof(exten));
10453 len = 0;
10454 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10455 p->subs[SUB_THREEWAY].owner &&
10456 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10457
10458
10459 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10460 chan, exten, chan->context, 0, NULL);
10461 ast_verb(3, "Parking call to '%s'\n", chan->name);
10462 break;
10463 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10464 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10465
10466 p->hidecallerid = 0;
10467 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10468 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10469 if (res) {
10470 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10471 chan->name, strerror(errno));
10472 }
10473 len = 0;
10474 memset(exten, 0, sizeof(exten));
10475 timeout = firstdigittimeout;
10476 } else if (!strcmp(exten, "*0")) {
10477 struct ast_channel *nbridge =
10478 p->subs[SUB_THREEWAY].owner;
10479 struct dahdi_pvt *pbridge = NULL;
10480
10481 if (nbridge && ast_bridged_channel(nbridge))
10482 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10483 if (nbridge && pbridge &&
10484 (nbridge->tech == &dahdi_tech) &&
10485 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10486 ISTRUNK(pbridge)) {
10487 int func = DAHDI_FLASH;
10488
10489 p->dop.dialstr[0] = '\0';
10490
10491 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10492 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10493 nbridge->name, strerror(errno));
10494 }
10495 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10496 unalloc_sub(p, SUB_THREEWAY);
10497 p->owner = p->subs[SUB_REAL].owner;
10498 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10499 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10500 ast_hangup(chan);
10501 goto quit;
10502 } else {
10503 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10504 dahdi_wait_event(p->subs[idx].dfd);
10505 tone_zone_play_tone(p->subs[idx].dfd, -1);
10506 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10507 unalloc_sub(p, SUB_THREEWAY);
10508 p->owner = p->subs[SUB_REAL].owner;
10509 ast_hangup(chan);
10510 goto quit;
10511 }
10512 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10513 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10514 && !canmatch_featurecode(exten)) {
10515 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10516 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10517 chan->context);
10518 break;
10519 }
10520 if (!timeout)
10521 timeout = gendigittimeout;
10522 if (len && !ast_ignore_pattern(chan->context, exten))
10523 tone_zone_play_tone(p->subs[idx].dfd, -1);
10524 }
10525 break;
10526 case SIG_FXSLS:
10527 case SIG_FXSGS:
10528 case SIG_FXSKS:
10529
10530 if (p->use_smdi && p->smdi_iface) {
10531 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10532
10533 if (smdi_msg != NULL) {
10534 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10535
10536 if (smdi_msg->type == 'B')
10537 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10538 else if (smdi_msg->type == 'N')
10539 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10540
10541 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10542 } else {
10543 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10544 }
10545 }
10546
10547 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10548 number = smdi_msg->calling_st;
10549
10550
10551
10552
10553 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10554 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10555
10556 if (p->cid_signalling == CID_SIG_DTMF) {
10557 int k = 0;
10558 int off_ms;
10559 struct timeval start = ast_tvnow();
10560 int ms;
10561 cs = NULL;
10562 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10563 dahdi_setlinear(p->subs[idx].dfd, 0);
10564
10565
10566
10567
10568
10569
10570 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10571 off_ms = 4000;
10572 for (;;) {
10573 struct ast_frame *f;
10574
10575 ms = ast_remaining_ms(start, off_ms);
10576 res = ast_waitfor(chan, ms);
10577 if (res <= 0) {
10578
10579
10580
10581
10582
10583 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10584 "Exiting simple switch\n");
10585 ast_hangup(chan);
10586 goto quit;
10587 }
10588 f = ast_read(chan);
10589 if (!f)
10590 break;
10591 if (f->frametype == AST_FRAME_DTMF) {
10592 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10593 dtmfbuf[k++] = f->subclass.integer;
10594 }
10595 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10596 start = ast_tvnow();
10597 }
10598 ast_frfree(f);
10599 if (chan->_state == AST_STATE_RING ||
10600 chan->_state == AST_STATE_RINGING)
10601 break;
10602 }
10603 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10604 dtmfbuf[k] = '\0';
10605 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10606
10607 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10608 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10609 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10610
10611 if (!ast_strlen_zero(dtmfcid))
10612 number = dtmfcid;
10613 else
10614 number = NULL;
10615
10616 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10617 cs = callerid_new(p->cid_signalling);
10618 if (cs) {
10619 int off_ms;
10620 struct timeval start;
10621 int ms;
10622 samples = 0;
10623 #if 1
10624 bump_gains(p);
10625 #endif
10626
10627 dahdi_setlinear(p->subs[idx].dfd, 0);
10628
10629
10630 for (;;) {
10631 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10632 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10633 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10634 callerid_free(cs);
10635 ast_hangup(chan);
10636 goto quit;
10637 }
10638 if (i & DAHDI_IOMUX_SIGEVENT) {
10639 res = dahdi_get_event(p->subs[idx].dfd);
10640 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10641 if (res == DAHDI_EVENT_NOALARM) {
10642 p->inalarm = 0;
10643 }
10644
10645 if (p->cid_signalling == CID_SIG_V23_JP) {
10646 if (res == DAHDI_EVENT_RINGBEGIN) {
10647 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10648 usleep(1);
10649 }
10650 } else {
10651 res = 0;
10652 break;
10653 }
10654 } else if (i & DAHDI_IOMUX_READ) {
10655 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10656 if (res < 0) {
10657 if (errno != ELAST) {
10658 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10659 callerid_free(cs);
10660 ast_hangup(chan);
10661 goto quit;
10662 }
10663 break;
10664 }
10665 samples += res;
10666
10667 if (p->cid_signalling == CID_SIG_V23_JP) {
10668 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10669 } else {
10670 res = callerid_feed(cs, buf, res, AST_LAW(p));
10671 }
10672 if (res < 0) {
10673
10674
10675
10676
10677 ast_log(LOG_WARNING,
10678 "Failed to decode CallerID on channel '%s'\n",
10679 chan->name);
10680 break;
10681 } else if (res)
10682 break;
10683 else if (samples > (8000 * 10))
10684 break;
10685 }
10686 }
10687 if (res == 1) {
10688 callerid_get(cs, &name, &number, &flags);
10689 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10690 }
10691
10692 if (p->cid_signalling == CID_SIG_V23_JP) {
10693 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10694 usleep(1);
10695 }
10696
10697
10698 start = ast_tvnow();
10699 off_ms = 4000;
10700 for (;;) {
10701 struct ast_frame *f;
10702
10703 ms = ast_remaining_ms(start, off_ms);
10704 res = ast_waitfor(chan, ms);
10705 if (res <= 0) {
10706 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10707 "Exiting simple switch\n");
10708 ast_hangup(chan);
10709 goto quit;
10710 }
10711 if (!(f = ast_read(chan))) {
10712 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10713 ast_hangup(chan);
10714 goto quit;
10715 }
10716 ast_frfree(f);
10717 if (chan->_state == AST_STATE_RING ||
10718 chan->_state == AST_STATE_RINGING)
10719 break;
10720 }
10721
10722
10723
10724 if (p->usedistinctiveringdetection) {
10725 len = 0;
10726 distMatches = 0;
10727
10728 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10729 curRingData[receivedRingT] = 0;
10730 receivedRingT = 0;
10731 counter = 0;
10732 counter1 = 0;
10733
10734 if (strcmp(p->context,p->defcontext) != 0) {
10735 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10736 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10737 }
10738
10739 for (;;) {
10740 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10741 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10742 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10743 callerid_free(cs);
10744 ast_hangup(chan);
10745 goto quit;
10746 }
10747 if (i & DAHDI_IOMUX_SIGEVENT) {
10748 res = dahdi_get_event(p->subs[idx].dfd);
10749 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10750 if (res == DAHDI_EVENT_NOALARM) {
10751 p->inalarm = 0;
10752 }
10753 res = 0;
10754
10755
10756 curRingData[receivedRingT] = p->ringt;
10757
10758 if (p->ringt < p->ringt_base/2)
10759 break;
10760
10761
10762 if (++receivedRingT == ARRAY_LEN(curRingData))
10763 break;
10764 } else if (i & DAHDI_IOMUX_READ) {
10765 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10766 if (res < 0) {
10767 if (errno != ELAST) {
10768 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10769 callerid_free(cs);
10770 ast_hangup(chan);
10771 goto quit;
10772 }
10773 break;
10774 }
10775 if (p->ringt > 0) {
10776 if (!(--p->ringt)) {
10777 res = -1;
10778 break;
10779 }
10780 }
10781 }
10782 }
10783
10784 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10785 for (counter = 0; counter < 3; counter++) {
10786
10787
10788 distMatches = 0;
10789 for (counter1 = 0; counter1 < 3; counter1++) {
10790 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10791 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10792 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10793 curRingData[counter1]);
10794 distMatches++;
10795 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10796 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10797 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10798 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10799 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10800 distMatches++;
10801 }
10802 }
10803
10804 if (distMatches == 3) {
10805
10806 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10807 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10808 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10809 break;
10810 }
10811 }
10812 }
10813
10814 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10815 #if 1
10816 restore_gains(p);
10817 #endif
10818 } else
10819 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10820 } else {
10821 ast_log(LOG_WARNING, "Channel %s in prering "
10822 "state, but I have nothing to do. "
10823 "Terminating simple switch, should be "
10824 "restarted by the actual ring.\n",
10825 chan->name);
10826 ast_hangup(chan);
10827 goto quit;
10828 }
10829 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10830 if (p->cid_signalling == CID_SIG_DTMF) {
10831 int k = 0;
10832 int off_ms;
10833 struct timeval start;
10834 int ms;
10835 cs = NULL;
10836 dahdi_setlinear(p->subs[idx].dfd, 0);
10837 off_ms = 2000;
10838 start = ast_tvnow();
10839 for (;;) {
10840 struct ast_frame *f;
10841
10842 ms = ast_remaining_ms(start, off_ms);
10843 res = ast_waitfor(chan, ms);
10844 if (res <= 0) {
10845 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10846 "Exiting simple switch\n");
10847 ast_hangup(chan);
10848 goto quit;
10849 }
10850 f = ast_read(chan);
10851 if (!f) {
10852
10853 ast_hangup(chan);
10854 goto quit;
10855 }
10856 if (f->frametype == AST_FRAME_DTMF) {
10857 dtmfbuf[k++] = f->subclass.integer;
10858 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10859 start = ast_tvnow();
10860 }
10861 ast_frfree(f);
10862
10863 if (p->ringt_base == p->ringt)
10864 break;
10865 }
10866 dtmfbuf[k] = '\0';
10867 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10868
10869 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10870 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10871 dtmfcid, flags);
10872
10873 if (!ast_strlen_zero(dtmfcid))
10874 number = dtmfcid;
10875 else
10876 number = NULL;
10877
10878 } else {
10879
10880 cs = callerid_new(p->cid_signalling);
10881 if (cs) {
10882 #if 1
10883 bump_gains(p);
10884 #endif
10885 samples = 0;
10886 len = 0;
10887 distMatches = 0;
10888
10889 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10890 curRingData[receivedRingT] = 0;
10891 receivedRingT = 0;
10892 counter = 0;
10893 counter1 = 0;
10894
10895 if (strcmp(p->context,p->defcontext) != 0) {
10896 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10897 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10898 }
10899
10900
10901 dahdi_setlinear(p->subs[idx].dfd, 0);
10902 for (;;) {
10903 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10904 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10905 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10906 callerid_free(cs);
10907 ast_hangup(chan);
10908 goto quit;
10909 }
10910 if (i & DAHDI_IOMUX_SIGEVENT) {
10911 res = dahdi_get_event(p->subs[idx].dfd);
10912 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10913 if (res == DAHDI_EVENT_NOALARM) {
10914 p->inalarm = 0;
10915 }
10916
10917 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10918 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10919 p->polarity = POLARITY_IDLE;
10920 callerid_free(cs);
10921 ast_hangup(chan);
10922 goto quit;
10923 }
10924 res = 0;
10925
10926
10927 curRingData[receivedRingT] = p->ringt;
10928
10929 if (p->ringt < p->ringt_base/2)
10930 break;
10931
10932
10933 if (++receivedRingT == ARRAY_LEN(curRingData))
10934 break;
10935 } else if (i & DAHDI_IOMUX_READ) {
10936 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10937 if (res < 0) {
10938 if (errno != ELAST) {
10939 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10940 callerid_free(cs);
10941 ast_hangup(chan);
10942 goto quit;
10943 }
10944 break;
10945 }
10946 if (p->ringt > 0) {
10947 if (!(--p->ringt)) {
10948 res = -1;
10949 break;
10950 }
10951 }
10952 samples += res;
10953 res = callerid_feed(cs, buf, res, AST_LAW(p));
10954 if (res < 0) {
10955
10956
10957
10958
10959 ast_log(LOG_WARNING,
10960 "Failed to decode CallerID on channel '%s'\n",
10961 chan->name);
10962 break;
10963 } else if (res)
10964 break;
10965 else if (samples > (8000 * 10))
10966 break;
10967 }
10968 }
10969 if (res == 1) {
10970 callerid_get(cs, &name, &number, &flags);
10971 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10972 }
10973 if (distinctiveringaftercid == 1) {
10974
10975 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10976 curRingData[receivedRingT] = 0;
10977 }
10978 receivedRingT = 0;
10979 ast_verb(3, "Detecting post-CID distinctive ring\n");
10980 for (;;) {
10981 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10982 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10983 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10984 callerid_free(cs);
10985 ast_hangup(chan);
10986 goto quit;
10987 }
10988 if (i & DAHDI_IOMUX_SIGEVENT) {
10989 res = dahdi_get_event(p->subs[idx].dfd);
10990 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10991 if (res == DAHDI_EVENT_NOALARM) {
10992 p->inalarm = 0;
10993 }
10994 res = 0;
10995
10996
10997 curRingData[receivedRingT] = p->ringt;
10998
10999 if (p->ringt < p->ringt_base/2)
11000 break;
11001
11002
11003 if (++receivedRingT == ARRAY_LEN(curRingData))
11004 break;
11005 } else if (i & DAHDI_IOMUX_READ) {
11006 res = read(p->subs[idx].dfd, buf, sizeof(buf));
11007 if (res < 0) {
11008 if (errno != ELAST) {
11009 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11010 callerid_free(cs);
11011 ast_hangup(chan);
11012 goto quit;
11013 }
11014 break;
11015 }
11016 if (p->ringt > 0) {
11017 if (!(--p->ringt)) {
11018 res = -1;
11019 break;
11020 }
11021 }
11022 }
11023 }
11024 }
11025 if (p->usedistinctiveringdetection) {
11026
11027 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11028
11029 for (counter = 0; counter < 3; counter++) {
11030
11031
11032
11033 ast_verb(3, "Checking %d,%d,%d\n",
11034 p->drings.ringnum[counter].ring[0],
11035 p->drings.ringnum[counter].ring[1],
11036 p->drings.ringnum[counter].ring[2]);
11037 distMatches = 0;
11038 for (counter1 = 0; counter1 < 3; counter1++) {
11039 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11040 if (p->drings.ringnum[counter].ring[counter1] == -1) {
11041 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11042 curRingData[counter1]);
11043 distMatches++;
11044 }
11045 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11046 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11047 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11048 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11049 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11050 distMatches++;
11051 }
11052 }
11053 if (distMatches == 3) {
11054
11055 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11056 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11057 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11058 break;
11059 }
11060 }
11061 }
11062
11063 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11064 #if 1
11065 restore_gains(p);
11066 #endif
11067 if (res < 0) {
11068 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11069 }
11070 } else
11071 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11072 }
11073 } else
11074 cs = NULL;
11075
11076 if (number)
11077 ast_shrink_phone_number(number);
11078 ast_set_callerid(chan, number, name, number);
11079
11080 if (smdi_msg)
11081 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11082
11083 if (cs)
11084 callerid_free(cs);
11085
11086 my_handle_notify_message(chan, p, flags, -1);
11087
11088 ast_setstate(chan, AST_STATE_RING);
11089 chan->rings = 1;
11090 p->ringt = p->ringt_base;
11091 res = ast_pbx_run(chan);
11092 if (res) {
11093 ast_hangup(chan);
11094 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11095 }
11096 goto quit;
11097 default:
11098 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11099 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11100 if (res < 0)
11101 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11102 }
11103 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11104 if (res < 0)
11105 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11106 ast_hangup(chan);
11107 quit:
11108 ast_mutex_lock(&ss_thread_lock);
11109 ss_thread_count--;
11110 ast_cond_signal(&ss_thread_complete);
11111 ast_mutex_unlock(&ss_thread_lock);
11112 return NULL;
11113 }
11114
11115 struct mwi_thread_data {
11116 struct dahdi_pvt *pvt;
11117 unsigned char buf[READ_SIZE];
11118 size_t len;
11119 };
11120
11121 static int calc_energy(const unsigned char *buf, int len, format_t law)
11122 {
11123 int x;
11124 int sum = 0;
11125
11126 if (!len)
11127 return 0;
11128
11129 for (x = 0; x < len; x++)
11130 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11131
11132 return sum / len;
11133 }
11134
11135 static void *mwi_thread(void *data)
11136 {
11137 struct mwi_thread_data *mtd = data;
11138 struct callerid_state *cs;
11139 pthread_t threadid;
11140 int samples = 0;
11141 char *name, *number;
11142 int flags;
11143 int i, res;
11144 unsigned int spill_done = 0;
11145 int spill_result = -1;
11146
11147 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11148 goto quit_no_clean;
11149 }
11150
11151 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11152
11153 bump_gains(mtd->pvt);
11154
11155 for (;;) {
11156 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11157 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11158 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11159 goto quit;
11160 }
11161
11162 if (i & DAHDI_IOMUX_SIGEVENT) {
11163 struct ast_channel *chan;
11164
11165
11166
11167
11168 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11169
11170 switch (res) {
11171 case DAHDI_EVENT_NEONMWI_ACTIVE:
11172 case DAHDI_EVENT_NEONMWI_INACTIVE:
11173 case DAHDI_EVENT_NONE:
11174 case DAHDI_EVENT_BITSCHANGED:
11175 break;
11176 case DAHDI_EVENT_NOALARM:
11177 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11178 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11179
11180 analog_p->inalarm = 0;
11181 }
11182 mtd->pvt->inalarm = 0;
11183 handle_clear_alarms(mtd->pvt);
11184 break;
11185 case DAHDI_EVENT_ALARM:
11186 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11187 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11188
11189 analog_p->inalarm = 1;
11190 }
11191 mtd->pvt->inalarm = 1;
11192 res = get_alarms(mtd->pvt);
11193 handle_alarms(mtd->pvt, res);
11194 break;
11195 default:
11196 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11197 callerid_free(cs);
11198
11199 restore_gains(mtd->pvt);
11200 mtd->pvt->ringt = mtd->pvt->ringt_base;
11201
11202 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11203 int result;
11204
11205 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11206 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11207 } else {
11208 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11209 }
11210 if (result) {
11211 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11212 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11213 if (res < 0)
11214 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11215 ast_hangup(chan);
11216 }
11217 } else {
11218 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11219 }
11220 goto quit_no_clean;
11221 }
11222 } else if (i & DAHDI_IOMUX_READ) {
11223 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11224 if (errno != ELAST) {
11225 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11226 goto quit;
11227 }
11228 break;
11229 }
11230 samples += res;
11231 if (!spill_done) {
11232 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11233
11234
11235
11236
11237 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11238 break;
11239 } else if (spill_result) {
11240 spill_done = 1;
11241 }
11242 } else {
11243
11244
11245
11246 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11247 break;
11248 }
11249 if (samples > (8000 * 4))
11250 break;
11251 }
11252 }
11253
11254 if (spill_result == 1) {
11255 callerid_get(cs, &name, &number, &flags);
11256 if (flags & CID_MSGWAITING) {
11257 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11258 notify_message(mtd->pvt->mailbox, 1);
11259 } else if (flags & CID_NOMSGWAITING) {
11260 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11261 notify_message(mtd->pvt->mailbox, 0);
11262 } else {
11263 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11264 }
11265 }
11266
11267
11268 quit:
11269 callerid_free(cs);
11270
11271 restore_gains(mtd->pvt);
11272
11273 quit_no_clean:
11274 mtd->pvt->mwimonitoractive = 0;
11275 ast_free(mtd);
11276
11277 return NULL;
11278 }
11279
11280
11281
11282
11283
11284
11285
11286
11287 static int mwi_send_init(struct dahdi_pvt * pvt)
11288 {
11289 int x;
11290
11291 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11292
11293 if (pvt->mwisend_rpas) {
11294 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11295 pvt->mwisendactive = 1;
11296 } else if (pvt->mwisend_fsk) {
11297 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11298 pvt->mwisendactive = 1;
11299 } else {
11300 pvt->mwisendactive = 0;
11301 return 0;
11302 }
11303 #else
11304 if (mwisend_rpas) {
11305 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11306 } else {
11307 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11308 }
11309 pvt->mwisendactive = 1;
11310 #endif
11311
11312 if (pvt->cidspill) {
11313 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11314 ast_free(pvt->cidspill);
11315 pvt->cidspill = NULL;
11316 pvt->cidpos = 0;
11317 pvt->cidlen = 0;
11318 }
11319 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11320 if (!pvt->cidspill) {
11321 pvt->mwisendactive = 0;
11322 return -1;
11323 }
11324 x = DAHDI_FLUSH_BOTH;
11325 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11326 x = 3000;
11327 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11328 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11329 if (pvt->mwisend_fsk) {
11330 #endif
11331 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11332 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11333 pvt->cidpos = 0;
11334 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11335 }
11336 #endif
11337 return 0;
11338 }
11339
11340 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11341 {
11342 struct timeval now;
11343 int res;
11344
11345
11346
11347
11348 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11349 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11350 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11351
11352 switch ( pvt->mwisend_data.mwisend_current) {
11353 case MWI_SEND_SA:
11354
11355 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11356 if (res) {
11357 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11358 goto quit;
11359 }
11360 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11361 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11362 break;
11363 case MWI_SEND_SA_WAIT:
11364 break;
11365 case MWI_SEND_PAUSE:
11366 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11367 if (pvt->mwisend_fsk) {
11368 #endif
11369 gettimeofday(&now, NULL);
11370 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11371 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11372 }
11373 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11374 } else {
11375 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11376 }
11377 #endif
11378 break;
11379 case MWI_SEND_SPILL:
11380
11381 if(0 < num_read) {
11382 if (num_read > pvt->cidlen - pvt->cidpos)
11383 num_read = pvt->cidlen - pvt->cidpos;
11384 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11385 if (res > 0) {
11386 pvt->cidpos += res;
11387 if (pvt->cidpos >= pvt->cidlen) {
11388 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11389 }
11390 } else {
11391 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11392 goto quit;
11393 }
11394 }
11395 break;
11396 case MWI_SEND_CLEANUP:
11397
11398 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11399 break;
11400 default:
11401
11402 goto quit;
11403 }
11404 }
11405
11406 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11407 if (pvt->cidspill) {
11408 ast_free(pvt->cidspill);
11409 pvt->cidspill = NULL;
11410 pvt->cidpos = 0;
11411 pvt->cidlen = 0;
11412 }
11413 pvt->mwisendactive = 0;
11414 }
11415 return 0;
11416 quit:
11417 if (pvt->cidspill) {
11418 ast_free(pvt->cidspill);
11419 pvt->cidspill = NULL;
11420 pvt->cidpos = 0;
11421 pvt->cidlen = 0;
11422 }
11423 pvt->mwisendactive = 0;
11424 return -1;
11425 }
11426
11427 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11428 {
11429 int handled = 0;
11430
11431 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11432 switch (event) {
11433 case DAHDI_EVENT_RINGEROFF:
11434 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11435 handled = 1;
11436
11437 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11438 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11439 ast_free(pvt->cidspill);
11440 pvt->cidspill = NULL;
11441 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11442 pvt->mwisendactive = 0;
11443 } else {
11444 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11445 gettimeofday(&pvt->mwisend_data.pause, NULL);
11446 }
11447 }
11448 break;
11449
11450 case DAHDI_EVENT_RINGOFFHOOK:
11451 if (pvt->cidspill) {
11452 ast_free(pvt->cidspill);
11453 pvt->cidspill = NULL;
11454 pvt->cidpos = 0;
11455 pvt->cidlen = 0;
11456 }
11457 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11458 pvt->mwisendactive = 0;
11459 break;
11460 case DAHDI_EVENT_RINGERON:
11461 case DAHDI_EVENT_HOOKCOMPLETE:
11462 break;
11463 default:
11464 break;
11465 }
11466 }
11467 return handled;
11468 }
11469
11470
11471 static int dahdi_destroy_channel_bynum(int channel)
11472 {
11473 struct dahdi_pvt *cur;
11474
11475 ast_mutex_lock(&iflock);
11476 for (cur = iflist; cur; cur = cur->next) {
11477 if (cur->channel == channel) {
11478 int x = DAHDI_FLASH;
11479
11480
11481 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11482
11483 destroy_channel(cur, 1);
11484 ast_mutex_unlock(&iflock);
11485 ast_module_unref(ast_module_info->self);
11486 return RESULT_SUCCESS;
11487 }
11488 }
11489 ast_mutex_unlock(&iflock);
11490 return RESULT_FAILURE;
11491 }
11492
11493 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11494 {
11495 int res;
11496 pthread_t threadid;
11497 struct ast_channel *chan;
11498
11499
11500
11501 switch (event) {
11502 case DAHDI_EVENT_NONE:
11503 case DAHDI_EVENT_BITSCHANGED:
11504 break;
11505 case DAHDI_EVENT_WINKFLASH:
11506 case DAHDI_EVENT_RINGOFFHOOK:
11507 if (i->inalarm) break;
11508 if (i->radio) break;
11509
11510 switch (i->sig) {
11511 case SIG_FXOLS:
11512 case SIG_FXOGS:
11513 case SIG_FXOKS:
11514 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11515 if (res && (errno == EBUSY))
11516 break;
11517
11518
11519 ast_free(i->cidspill);
11520 i->cidspill = NULL;
11521 restore_conference(i);
11522
11523 if (i->immediate) {
11524 dahdi_enable_ec(i);
11525
11526 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11527 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11528 if (!chan) {
11529 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11530 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11531 if (res < 0)
11532 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11533 }
11534 } else {
11535
11536 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11537 if (chan) {
11538 if (has_voicemail(i))
11539 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11540 else
11541 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11542 if (res < 0)
11543 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11544 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11545 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11546 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11547 if (res < 0)
11548 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11549 ast_hangup(chan);
11550 }
11551 } else
11552 ast_log(LOG_WARNING, "Unable to create channel\n");
11553 }
11554 break;
11555 case SIG_FXSLS:
11556 case SIG_FXSGS:
11557 case SIG_FXSKS:
11558 i->ringt = i->ringt_base;
11559
11560 case SIG_EMWINK:
11561 case SIG_FEATD:
11562 case SIG_FEATDMF:
11563 case SIG_FEATDMF_TA:
11564 case SIG_E911:
11565 case SIG_FGC_CAMA:
11566 case SIG_FGC_CAMAMF:
11567 case SIG_FEATB:
11568 case SIG_EM:
11569 case SIG_EM_E1:
11570 case SIG_SFWINK:
11571 case SIG_SF_FEATD:
11572 case SIG_SF_FEATDMF:
11573 case SIG_SF_FEATB:
11574 case SIG_SF:
11575
11576 if (i->cid_start == CID_START_POLARITY_IN) {
11577 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11578 } else {
11579 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11580 }
11581
11582 if (!chan) {
11583 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11584 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11585 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11586 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11587 if (res < 0) {
11588 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11589 }
11590 ast_hangup(chan);
11591 }
11592 break;
11593 default:
11594 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11595 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11596 if (res < 0)
11597 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11598 return NULL;
11599 }
11600 break;
11601 case DAHDI_EVENT_NOALARM:
11602 switch (i->sig) {
11603 #if defined(HAVE_PRI)
11604 case SIG_PRI_LIB_HANDLE_CASES:
11605 ast_mutex_lock(&i->lock);
11606 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11607 ast_mutex_unlock(&i->lock);
11608 break;
11609 #endif
11610 #if defined(HAVE_SS7)
11611 case SIG_SS7:
11612 sig_ss7_set_alarm(i->sig_pvt, 0);
11613 break;
11614 #endif
11615 default:
11616 i->inalarm = 0;
11617 break;
11618 }
11619 handle_clear_alarms(i);
11620 break;
11621 case DAHDI_EVENT_ALARM:
11622 switch (i->sig) {
11623 #if defined(HAVE_PRI)
11624 case SIG_PRI_LIB_HANDLE_CASES:
11625 ast_mutex_lock(&i->lock);
11626 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11627 ast_mutex_unlock(&i->lock);
11628 break;
11629 #endif
11630 #if defined(HAVE_SS7)
11631 case SIG_SS7:
11632 sig_ss7_set_alarm(i->sig_pvt, 1);
11633 break;
11634 #endif
11635 default:
11636 i->inalarm = 1;
11637 break;
11638 }
11639 res = get_alarms(i);
11640 handle_alarms(i, res);
11641
11642 case DAHDI_EVENT_ONHOOK:
11643 if (i->radio)
11644 break;
11645
11646 switch (i->sig) {
11647 case SIG_FXOLS:
11648 case SIG_FXOGS:
11649 case SIG_FEATD:
11650 case SIG_FEATDMF:
11651 case SIG_FEATDMF_TA:
11652 case SIG_E911:
11653 case SIG_FGC_CAMA:
11654 case SIG_FGC_CAMAMF:
11655 case SIG_FEATB:
11656 case SIG_EM:
11657 case SIG_EM_E1:
11658 case SIG_EMWINK:
11659 case SIG_SF_FEATD:
11660 case SIG_SF_FEATDMF:
11661 case SIG_SF_FEATB:
11662 case SIG_SF:
11663 case SIG_SFWINK:
11664 case SIG_FXSLS:
11665 case SIG_FXSGS:
11666 case SIG_FXSKS:
11667 case SIG_FXOKS:
11668 dahdi_disable_ec(i);
11669
11670 #ifdef ZHONE_HACK
11671 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11672 usleep(1);
11673 #endif
11674 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11675 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11676 break;
11677 case SIG_SS7:
11678 case SIG_PRI_LIB_HANDLE_CASES:
11679 dahdi_disable_ec(i);
11680 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11681 break;
11682 default:
11683 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11684 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11685 return NULL;
11686 }
11687 break;
11688 case DAHDI_EVENT_POLARITY:
11689 switch (i->sig) {
11690 case SIG_FXSLS:
11691 case SIG_FXSKS:
11692 case SIG_FXSGS:
11693
11694
11695
11696
11697 if (i->hanguponpolarityswitch)
11698 i->polarity = POLARITY_REV;
11699 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11700 i->polarity = POLARITY_REV;
11701 ast_verb(2, "Starting post polarity "
11702 "CID detection on channel %d\n",
11703 i->channel);
11704 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11705 if (!chan) {
11706 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11707 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11708 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11709 ast_hangup(chan);
11710 }
11711 }
11712 break;
11713 default:
11714 ast_log(LOG_WARNING, "handle_init_event detected "
11715 "polarity reversal on non-FXO (SIG_FXS) "
11716 "interface %d\n", i->channel);
11717 }
11718 break;
11719 case DAHDI_EVENT_REMOVED:
11720 ast_log(LOG_NOTICE,
11721 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11722 i->channel);
11723 return i;
11724 case DAHDI_EVENT_NEONMWI_ACTIVE:
11725 if (i->mwimonitor_neon) {
11726 notify_message(i->mailbox, 1);
11727 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11728 }
11729 break;
11730 case DAHDI_EVENT_NEONMWI_INACTIVE:
11731 if (i->mwimonitor_neon) {
11732 notify_message(i->mailbox, 0);
11733 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11734 }
11735 break;
11736 }
11737 return NULL;
11738 }
11739
11740 static void monitor_pfds_clean(void *arg) {
11741 struct pollfd **pfds = arg;
11742 ast_free(*pfds);
11743 }
11744
11745 static void *do_monitor(void *data)
11746 {
11747 int count, res, res2, spoint, pollres=0;
11748 struct dahdi_pvt *i;
11749 struct dahdi_pvt *last = NULL;
11750 struct dahdi_pvt *doomed;
11751 time_t thispass = 0, lastpass = 0;
11752 int found;
11753 char buf[1024];
11754 struct pollfd *pfds=NULL;
11755 int lastalloc = -1;
11756
11757
11758
11759 #if 0
11760 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11761 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11762 return NULL;
11763 }
11764 ast_debug(1, "Monitor starting...\n");
11765 #endif
11766 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11767
11768 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11769 for (;;) {
11770
11771 ast_mutex_lock(&iflock);
11772 if (!pfds || (lastalloc != ifcount)) {
11773 if (pfds) {
11774 ast_free(pfds);
11775 pfds = NULL;
11776 }
11777 if (ifcount) {
11778 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11779 ast_mutex_unlock(&iflock);
11780 return NULL;
11781 }
11782 }
11783 lastalloc = ifcount;
11784 }
11785
11786
11787 count = 0;
11788 for (i = iflist; i; i = i->next) {
11789 ast_mutex_lock(&i->lock);
11790 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11791 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11792 struct analog_pvt *p = i->sig_pvt;
11793
11794 if (!p) {
11795 ast_log(LOG_ERROR, "No sig_pvt?\n");
11796 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11797
11798 pfds[count].fd = i->subs[SUB_REAL].dfd;
11799 pfds[count].events = POLLPRI;
11800 pfds[count].revents = 0;
11801
11802 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11803 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11804 pfds[count].events |= POLLIN;
11805 }
11806 count++;
11807 }
11808 } else {
11809 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11810
11811 pfds[count].fd = i->subs[SUB_REAL].dfd;
11812 pfds[count].events = POLLPRI;
11813 pfds[count].revents = 0;
11814
11815
11816 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11817 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11818 pfds[count].events |= POLLIN;
11819 }
11820 count++;
11821 }
11822 }
11823 }
11824 ast_mutex_unlock(&i->lock);
11825 }
11826
11827 ast_mutex_unlock(&iflock);
11828
11829 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11830 pthread_testcancel();
11831
11832 res = poll(pfds, count, 1000);
11833 pthread_testcancel();
11834 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11835
11836
11837 if (res < 0) {
11838 if ((errno != EAGAIN) && (errno != EINTR))
11839 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11840 continue;
11841 }
11842
11843
11844 ast_mutex_lock(&iflock);
11845 found = 0;
11846 spoint = 0;
11847 lastpass = thispass;
11848 thispass = time(NULL);
11849 doomed = NULL;
11850 for (i = iflist;; i = i->next) {
11851 if (doomed) {
11852 int res;
11853 res = dahdi_destroy_channel_bynum(doomed->channel);
11854 if (res != RESULT_SUCCESS) {
11855 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11856 }
11857 doomed = NULL;
11858 }
11859 if (!i) {
11860 break;
11861 }
11862
11863 if (thispass != lastpass) {
11864 if (!found && ((i == last) || ((i == iflist) && !last))) {
11865 last = i;
11866 if (last) {
11867 struct analog_pvt *analog_p = last->sig_pvt;
11868
11869 if (analog_p
11870 && !last->mwisendactive
11871 && (last->sig & __DAHDI_SIG_FXO)
11872 && !analog_p->fxsoffhookstate
11873 && !last->owner
11874 && !ast_strlen_zero(last->mailbox)
11875 && (thispass - analog_p->onhooktime > 3)) {
11876 res = has_voicemail(last);
11877 if (analog_p->msgstate != res) {
11878
11879 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11880 if (res2) {
11881
11882 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11883 }
11884
11885 if (mwi_send_init(last)) {
11886 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11887 }
11888 analog_p->msgstate = res;
11889 found ++;
11890 }
11891 }
11892 last = last->next;
11893 }
11894 }
11895 }
11896 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11897 if (i->radio && !i->owner)
11898 {
11899 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11900 if (res)
11901 {
11902 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11903
11904 ast_mutex_unlock(&iflock);
11905 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11906 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11907 else
11908 doomed = handle_init_event(i, res);
11909 ast_mutex_lock(&iflock);
11910 }
11911 continue;
11912 }
11913 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11914 if (pollres & POLLIN) {
11915 if (i->owner || i->subs[SUB_REAL].owner) {
11916 #ifdef HAVE_PRI
11917 if (!i->pri)
11918 #endif
11919 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11920 continue;
11921 }
11922 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11923 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11924 continue;
11925 }
11926 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11927 if (res > 0) {
11928 if (i->mwimonitor_fsk) {
11929 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11930 pthread_attr_t attr;
11931 pthread_t threadid;
11932 struct mwi_thread_data *mtd;
11933
11934 pthread_attr_init(&attr);
11935 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11936
11937 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11938 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11939 mtd->pvt = i;
11940 memcpy(mtd->buf, buf, res);
11941 mtd->len = res;
11942 i->mwimonitoractive = 1;
11943 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11944 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11945 i->mwimonitoractive = 0;
11946 ast_free(mtd);
11947 }
11948 }
11949 }
11950
11951 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11952 int energy;
11953 struct timeval now;
11954
11955
11956
11957 if (1 == i->dtmfcid_holdoff_state) {
11958 gettimeofday(&i->dtmfcid_delay, NULL);
11959 i->dtmfcid_holdoff_state = 2;
11960 } else if (2 == i->dtmfcid_holdoff_state) {
11961 gettimeofday(&now, NULL);
11962 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11963 i->dtmfcid_holdoff_state = 0;
11964 }
11965 } else {
11966 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11967 if (!i->mwisendactive && energy > dtmfcid_level) {
11968 pthread_t threadid;
11969 struct ast_channel *chan;
11970 ast_mutex_unlock(&iflock);
11971 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11972
11973 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11974 i->dtmfcid_holdoff_state = 1;
11975 } else {
11976 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11977 if (!chan) {
11978 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11979 } else {
11980 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11981 if (res) {
11982 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11983 ast_hangup(chan);
11984 } else {
11985 i->dtmfcid_holdoff_state = 1;
11986 }
11987 }
11988 }
11989 ast_mutex_lock(&iflock);
11990 }
11991 }
11992 }
11993 if (i->mwisendactive) {
11994 mwi_send_process_buffer(i, res);
11995 }
11996 } else {
11997 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11998 }
11999 }
12000 if (pollres & POLLPRI) {
12001 if (i->owner || i->subs[SUB_REAL].owner) {
12002 #ifdef HAVE_PRI
12003 if (!i->pri)
12004 #endif
12005 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12006 continue;
12007 }
12008 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12009 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12010
12011 ast_mutex_unlock(&iflock);
12012 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12013 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12014 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12015 else
12016 doomed = handle_init_event(i, res);
12017 }
12018 ast_mutex_lock(&iflock);
12019 }
12020 }
12021 }
12022 ast_mutex_unlock(&iflock);
12023 }
12024
12025 pthread_cleanup_pop(1);
12026 return NULL;
12027
12028 }
12029
12030 static int restart_monitor(void)
12031 {
12032
12033 if (monitor_thread == AST_PTHREADT_STOP)
12034 return 0;
12035 ast_mutex_lock(&monlock);
12036 if (monitor_thread == pthread_self()) {
12037 ast_mutex_unlock(&monlock);
12038 ast_log(LOG_WARNING, "Cannot kill myself\n");
12039 return -1;
12040 }
12041 if (monitor_thread != AST_PTHREADT_NULL) {
12042
12043 pthread_kill(monitor_thread, SIGURG);
12044 } else {
12045
12046 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12047 ast_mutex_unlock(&monlock);
12048 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12049 return -1;
12050 }
12051 }
12052 ast_mutex_unlock(&monlock);
12053 return 0;
12054 }
12055
12056 #if defined(HAVE_PRI)
12057 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12058 {
12059 int x;
12060 int trunkgroup;
12061
12062 trunkgroup = pris[*span].mastertrunkgroup;
12063 if (trunkgroup) {
12064
12065 for (x = 0; x < NUM_SPANS; x++) {
12066 if (pris[x].pri.trunkgroup == trunkgroup) {
12067 *span = x;
12068 return 0;
12069 }
12070 }
12071 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12072 *span = -1;
12073 } else {
12074 if (pris[*span].pri.trunkgroup) {
12075 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup);
12076 *span = -1;
12077 } else if (pris[*span].mastertrunkgroup) {
12078 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12079 *span = -1;
12080 } else {
12081 if (si->totalchans == 31) {
12082
12083 pris[*span].dchannels[0] = 16 + offset;
12084 } else if (si->totalchans == 24) {
12085
12086 pris[*span].dchannels[0] = 24 + offset;
12087 } else if (si->totalchans == 3) {
12088
12089 pris[*span].dchannels[0] = 3 + offset;
12090 } else {
12091 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);
12092 *span = -1;
12093 return 0;
12094 }
12095 pris[*span].pri.span = *span + 1;
12096 }
12097 }
12098 return 0;
12099 }
12100 #endif
12101
12102 #if defined(HAVE_PRI)
12103 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12104 {
12105 struct dahdi_spaninfo si;
12106 struct dahdi_params p;
12107 int fd;
12108 int span;
12109 int ospan=0;
12110 int x,y;
12111 for (x = 0; x < NUM_SPANS; x++) {
12112 if (pris[x].pri.trunkgroup == trunkgroup) {
12113 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12114 return -1;
12115 }
12116 }
12117 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12118 if (!channels[y])
12119 break;
12120 memset(&si, 0, sizeof(si));
12121 memset(&p, 0, sizeof(p));
12122 fd = open("/dev/dahdi/channel", O_RDWR);
12123 if (fd < 0) {
12124 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12125 return -1;
12126 }
12127 x = channels[y];
12128 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12129 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12130 close(fd);
12131 return -1;
12132 }
12133 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12134 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12135 return -1;
12136 }
12137 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12138 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12139 close(fd);
12140 return -1;
12141 }
12142 span = p.spanno - 1;
12143 if (pris[span].pri.trunkgroup) {
12144 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12145 close(fd);
12146 return -1;
12147 }
12148 if (pris[span].pri.pvts[0]) {
12149 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12150 close(fd);
12151 return -1;
12152 }
12153 if (!y) {
12154 pris[span].pri.trunkgroup = trunkgroup;
12155 ospan = span;
12156 }
12157 pris[ospan].dchannels[y] = channels[y];
12158 pris[span].pri.span = span + 1;
12159 close(fd);
12160 }
12161 return 0;
12162 }
12163 #endif
12164
12165 #if defined(HAVE_PRI)
12166 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12167 {
12168 if (pris[span].mastertrunkgroup) {
12169 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);
12170 return -1;
12171 }
12172 pris[span].mastertrunkgroup = trunkgroup;
12173 pris[span].prilogicalspan = logicalspan;
12174 return 0;
12175 }
12176 #endif
12177
12178 #if defined(HAVE_SS7)
12179 static unsigned int parse_pointcode(const char *pcstring)
12180 {
12181 unsigned int code1, code2, code3;
12182 int numvals;
12183
12184 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12185 if (numvals == 1)
12186 return code1;
12187 if (numvals == 3)
12188 return (code1 << 16) | (code2 << 8) | code3;
12189
12190 return 0;
12191 }
12192 #endif
12193
12194 #if defined(HAVE_SS7)
12195 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12196 {
12197 if ((linkset < 0) || (linkset >= NUM_SPANS))
12198 return NULL;
12199 else
12200 return &linksets[linkset - 1];
12201 }
12202 #endif
12203
12204 #ifdef HAVE_OPENR2
12205 static void dahdi_r2_destroy_links(void)
12206 {
12207 int i = 0;
12208 if (!r2links) {
12209 return;
12210 }
12211 for (; i < r2links_count; i++) {
12212 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12213 pthread_cancel(r2links[i]->r2master);
12214 pthread_join(r2links[i]->r2master, NULL);
12215 openr2_context_delete(r2links[i]->protocol_context);
12216 }
12217 ast_free(r2links[i]);
12218 }
12219 ast_free(r2links);
12220 r2links = NULL;
12221 r2links_count = 0;
12222 }
12223
12224
12225 #define R2_LINK_CAPACITY 30
12226 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12227 {
12228 struct dahdi_mfcr2 *new_r2link = NULL;
12229 struct dahdi_mfcr2 **new_r2links = NULL;
12230
12231
12232
12233
12234
12235 if (!r2links_count ||
12236 memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12237 (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12238 new_r2link = ast_calloc(1, sizeof(**r2links));
12239 if (!new_r2link) {
12240 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12241 return NULL;
12242 }
12243 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12244 if (!new_r2links) {
12245 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12246 ast_free(new_r2link);
12247 return NULL;
12248 }
12249 r2links = new_r2links;
12250 new_r2link->r2master = AST_PTHREADT_NULL;
12251 r2links[r2links_count] = new_r2link;
12252 r2links_count++;
12253 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12254 }
12255 return r2links[r2links_count - 1];
12256 }
12257
12258 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12259 {
12260 char tmplogdir[] = "/tmp";
12261 char logdir[OR2_MAX_PATH];
12262 int threshold = 0;
12263 int snres = 0;
12264 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12265 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12266 conf->mfcr2.max_dnis);
12267 if (!r2_link->protocol_context) {
12268 return -1;
12269 }
12270 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12271 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12272 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12273 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12274 #endif
12275 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12276 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12277 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12278 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12279 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12280 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12281 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12282 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12283 }
12284 } else {
12285 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12286 if (snres >= sizeof(logdir)) {
12287 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12288 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12289 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12290 }
12291 } else {
12292 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12293 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12294 }
12295 }
12296 }
12297 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12298 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12299 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12300 }
12301 }
12302
12303 memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12304 return 0;
12305 }
12306 #endif
12307
12308
12309
12310
12311
12312
12313 static int sigtype_to_signalling(int sigtype)
12314 {
12315 return sigtype;
12316 }
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12331 {
12332 struct stat stbuf;
12333 int num;
12334
12335 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12336 if (stat(path, &stbuf) < 0) {
12337 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12338 return -errno;
12339 }
12340 if (!S_ISCHR(stbuf.st_mode)) {
12341 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12342 return -EINVAL;
12343 }
12344 num = minor(stbuf.st_rdev);
12345 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12346 return num;
12347
12348 }
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12365 {
12366
12367 struct dahdi_pvt *tmp;
12368 char fn[80];
12369 struct dahdi_bufferinfo bi;
12370
12371 int res;
12372 #if defined(HAVE_PRI)
12373 int span = 0;
12374 #endif
12375 int here = 0;
12376 int x;
12377 struct analog_pvt *analog_p = NULL;
12378 struct dahdi_params p;
12379 #if defined(HAVE_PRI)
12380 struct dahdi_spaninfo si;
12381 struct sig_pri_chan *pri_chan = NULL;
12382 #endif
12383 #if defined(HAVE_SS7)
12384 struct sig_ss7_chan *ss7_chan = NULL;
12385 #endif
12386
12387
12388 for (tmp = iflist; tmp; tmp = tmp->next) {
12389 if (!tmp->destroy) {
12390 if (tmp->channel == channel) {
12391
12392 here = 1;
12393 break;
12394 }
12395 if (tmp->channel > channel) {
12396
12397 tmp = NULL;
12398 break;
12399 }
12400 }
12401 }
12402
12403 if (!here && reloading != 1) {
12404 tmp = ast_calloc(1, sizeof(*tmp));
12405 if (!tmp) {
12406 return NULL;
12407 }
12408 tmp->cc_params = ast_cc_config_params_init();
12409 if (!tmp->cc_params) {
12410 ast_free(tmp);
12411 return NULL;
12412 }
12413 ast_mutex_init(&tmp->lock);
12414 ifcount++;
12415 for (x = 0; x < 3; x++)
12416 tmp->subs[x].dfd = -1;
12417 tmp->channel = channel;
12418 tmp->priindication_oob = conf->chan.priindication_oob;
12419 }
12420
12421 if (tmp) {
12422 int chan_sig = conf->chan.sig;
12423
12424
12425 if (reloading && tmp->vars) {
12426 ast_variables_destroy(tmp->vars);
12427 tmp->vars = NULL;
12428 }
12429
12430
12431 if (!here) {
12432
12433 if ((channel != CHAN_PSEUDO)) {
12434 int count = 0;
12435
12436 snprintf(fn, sizeof(fn), "%d", channel);
12437
12438 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12439 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12440 usleep(1);
12441 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12442 count++;
12443 }
12444
12445 if (tmp->subs[SUB_REAL].dfd < 0) {
12446 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);
12447 destroy_dahdi_pvt(tmp);
12448 return NULL;
12449 }
12450 memset(&p, 0, sizeof(p));
12451 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12452 if (res < 0) {
12453 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12454 destroy_dahdi_pvt(tmp);
12455 return NULL;
12456 }
12457 if (conf->is_sig_auto)
12458 chan_sig = sigtype_to_signalling(p.sigtype);
12459 if (p.sigtype != (chan_sig & 0x3ffff)) {
12460 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
12461 destroy_dahdi_pvt(tmp);
12462 return NULL;
12463 }
12464 tmp->law_default = p.curlaw;
12465 tmp->law = p.curlaw;
12466 tmp->span = p.spanno;
12467 #if defined(HAVE_PRI)
12468 span = p.spanno - 1;
12469 #endif
12470 } else {
12471 chan_sig = 0;
12472 }
12473 tmp->sig = chan_sig;
12474 tmp->outsigmod = conf->chan.outsigmod;
12475
12476 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12477 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12478 if (!analog_p) {
12479 destroy_dahdi_pvt(tmp);
12480 return NULL;
12481 }
12482 tmp->sig_pvt = analog_p;
12483 }
12484 #if defined(HAVE_SS7)
12485 if (chan_sig == SIG_SS7) {
12486 struct dahdi_ss7 *ss7;
12487 int clear = 0;
12488
12489 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12490 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12491 destroy_dahdi_pvt(tmp);
12492 return NULL;
12493 }
12494
12495 ss7 = ss7_resolve_linkset(cur_linkset);
12496 if (!ss7) {
12497 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12498 destroy_dahdi_pvt(tmp);
12499 return NULL;
12500 }
12501 ss7->ss7.span = cur_linkset;
12502 if (cur_cicbeginswith < 0) {
12503 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12504 destroy_dahdi_pvt(tmp);
12505 return NULL;
12506 }
12507 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12508 if (!ss7_chan) {
12509 destroy_dahdi_pvt(tmp);
12510 return NULL;
12511 }
12512 tmp->sig_pvt = ss7_chan;
12513 tmp->ss7 = &ss7->ss7;
12514
12515 ss7_chan->channel = tmp->channel;
12516 ss7_chan->cic = cur_cicbeginswith++;
12517
12518
12519 ss7_chan->dpc = cur_defaultdpc;
12520
12521 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12522
12523 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12524 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12525 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12526 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12527
12528 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12529 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12530 }
12531 #endif
12532 #ifdef HAVE_OPENR2
12533 if (chan_sig == SIG_MFCR2) {
12534 struct dahdi_mfcr2 *r2_link;
12535 r2_link = dahdi_r2_get_link(conf);
12536 if (!r2_link) {
12537 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12538 destroy_dahdi_pvt(tmp);
12539 return NULL;
12540 }
12541 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12542 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12543 destroy_dahdi_pvt(tmp);
12544 return NULL;
12545 }
12546 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12547 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12548 destroy_dahdi_pvt(tmp);
12549 return NULL;
12550 }
12551 r2_link->pvts[r2_link->numchans++] = tmp;
12552 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12553 tmp->subs[SUB_REAL].dfd,
12554 NULL, NULL);
12555 if (!tmp->r2chan) {
12556 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12557 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12558 destroy_dahdi_pvt(tmp);
12559 return NULL;
12560 }
12561 tmp->mfcr2 = r2_link;
12562 if (conf->mfcr2.call_files) {
12563 openr2_chan_enable_call_files(tmp->r2chan);
12564 }
12565 openr2_chan_set_client_data(tmp->r2chan, tmp);
12566
12567 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12568 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12569 tmp->mfcr2_category = conf->mfcr2.category;
12570 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12571 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12572 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12573 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12574 tmp->mfcr2call = 0;
12575 tmp->mfcr2_dnis_index = 0;
12576 tmp->mfcr2_ani_index = 0;
12577 }
12578 #endif
12579 #ifdef HAVE_PRI
12580 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12581 int offset;
12582 int matchesdchan;
12583 int x,y;
12584 int myswitchtype = 0;
12585
12586 offset = 0;
12587 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12588 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12589 destroy_dahdi_pvt(tmp);
12590 return NULL;
12591 }
12592 if (span >= NUM_SPANS) {
12593 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12594 destroy_dahdi_pvt(tmp);
12595 return NULL;
12596 } else {
12597 si.spanno = 0;
12598 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12599 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12600 destroy_dahdi_pvt(tmp);
12601 return NULL;
12602 }
12603
12604 tmp->logicalspan = pris[span].prilogicalspan;
12605 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12606 if (span < 0) {
12607 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12608 destroy_dahdi_pvt(tmp);
12609 return NULL;
12610 }
12611 myswitchtype = conf->pri.pri.switchtype;
12612
12613 matchesdchan=0;
12614 for (x = 0; x < NUM_SPANS; x++) {
12615 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12616 if (pris[x].dchannels[y] == tmp->channel) {
12617 matchesdchan = 1;
12618 break;
12619 }
12620 }
12621 }
12622 if (!matchesdchan) {
12623 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12624 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12625 destroy_dahdi_pvt(tmp);
12626 return NULL;
12627 }
12628 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12629 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12630 destroy_dahdi_pvt(tmp);
12631 return NULL;
12632 }
12633 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12634 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
12635 destroy_dahdi_pvt(tmp);
12636 return NULL;
12637 }
12638 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12639 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12640 destroy_dahdi_pvt(tmp);
12641 return NULL;
12642 }
12643 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12644 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12645 destroy_dahdi_pvt(tmp);
12646 return NULL;
12647 }
12648 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12649 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12650 destroy_dahdi_pvt(tmp);
12651 return NULL;
12652 }
12653 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12654 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12655 destroy_dahdi_pvt(tmp);
12656 return NULL;
12657 }
12658 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12659 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12660 pris[span].pri.trunkgroup);
12661 destroy_dahdi_pvt(tmp);
12662 return NULL;
12663 }
12664
12665 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12666 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12667 if (!pri_chan) {
12668 destroy_dahdi_pvt(tmp);
12669 return NULL;
12670 }
12671 tmp->sig_pvt = pri_chan;
12672 tmp->pri = &pris[span].pri;
12673
12674 tmp->priexclusive = conf->chan.priexclusive;
12675
12676 if (!tmp->pri->cc_params) {
12677 tmp->pri->cc_params = ast_cc_config_params_init();
12678 if (!tmp->pri->cc_params) {
12679 destroy_dahdi_pvt(tmp);
12680 return NULL;
12681 }
12682 }
12683 ast_cc_copy_config_params(tmp->pri->cc_params,
12684 conf->chan.cc_params);
12685
12686 pris[span].pri.sig = chan_sig;
12687 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12688 pris[span].pri.switchtype = myswitchtype;
12689 pris[span].pri.nsf = conf->pri.pri.nsf;
12690 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12691 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12692 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12693 pris[span].pri.minunused = conf->pri.pri.minunused;
12694 pris[span].pri.minidle = conf->pri.pri.minidle;
12695 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12696 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12697 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12698 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12699 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12700 #endif
12701 #ifdef HAVE_PRI_INBANDDISCONNECT
12702 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12703 #endif
12704 #if defined(HAVE_PRI_CALL_HOLD)
12705 pris[span].pri.hold_disconnect_transfer =
12706 conf->pri.pri.hold_disconnect_transfer;
12707 #endif
12708 #if defined(HAVE_PRI_CCSS)
12709 pris[span].pri.cc_ptmp_recall_mode =
12710 conf->pri.pri.cc_ptmp_recall_mode;
12711 pris[span].pri.cc_qsig_signaling_link_req =
12712 conf->pri.pri.cc_qsig_signaling_link_req;
12713 pris[span].pri.cc_qsig_signaling_link_rsp =
12714 conf->pri.pri.cc_qsig_signaling_link_rsp;
12715 #endif
12716 #if defined(HAVE_PRI_CALL_WAITING)
12717 pris[span].pri.max_call_waiting_calls =
12718 conf->pri.pri.max_call_waiting_calls;
12719 pris[span].pri.allow_call_waiting_calls =
12720 conf->pri.pri.allow_call_waiting_calls;
12721 #endif
12722 pris[span].pri.transfer = conf->chan.transfer;
12723 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12724 #if defined(HAVE_PRI_L2_PERSISTENCE)
12725 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12726 #endif
12727 #if defined(HAVE_PRI_AOC_EVENTS)
12728 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12729 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12730 #endif
12731 if (chan_sig == SIG_BRI_PTMP) {
12732 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12733 } else {
12734
12735 pris[span].pri.layer1_ignored = 0;
12736 }
12737 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12738 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12739 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12740 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12741 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12742 #if defined(HAVE_PRI_MWI)
12743 ast_copy_string(pris[span].pri.mwi_mailboxes,
12744 conf->pri.pri.mwi_mailboxes,
12745 sizeof(pris[span].pri.mwi_mailboxes));
12746 #endif
12747 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12748 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12749 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12750 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12751 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12752 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12753 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12754 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12755
12756 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12757 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12758 }
12759
12760 #if defined(HAVE_PRI_CALL_WAITING)
12761
12762 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12763 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12764 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12765 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12766 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12767 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12768 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12769 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12770 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12771 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12772 #endif
12773 } else {
12774 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12775 destroy_dahdi_pvt(tmp);
12776 return NULL;
12777 }
12778 }
12779 }
12780 #endif
12781 } else {
12782
12783 ast_log(LOG_WARNING, "Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->sig));
12784 chan_sig = tmp->sig;
12785 if (tmp->subs[SUB_REAL].dfd > -1) {
12786 memset(&p, 0, sizeof(p));
12787 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12788 }
12789 }
12790
12791 switch (chan_sig) {
12792 case SIG_FXSKS:
12793 case SIG_FXSLS:
12794 case SIG_EM:
12795 case SIG_EM_E1:
12796 case SIG_EMWINK:
12797 case SIG_FEATD:
12798 case SIG_FEATDMF:
12799 case SIG_FEATDMF_TA:
12800 case SIG_FEATB:
12801 case SIG_E911:
12802 case SIG_SF:
12803 case SIG_SFWINK:
12804 case SIG_FGC_CAMA:
12805 case SIG_FGC_CAMAMF:
12806 case SIG_SF_FEATD:
12807 case SIG_SF_FEATDMF:
12808 case SIG_SF_FEATB:
12809 p.starttime = 250;
12810 break;
12811 }
12812
12813 if (tmp->radio) {
12814
12815 p.channo = channel;
12816 p.rxwinktime = 1;
12817 p.rxflashtime = 1;
12818 p.starttime = 1;
12819 p.debouncetime = 5;
12820 } else {
12821 p.channo = channel;
12822
12823 if (conf->timing.prewinktime >= 0)
12824 p.prewinktime = conf->timing.prewinktime;
12825 if (conf->timing.preflashtime >= 0)
12826 p.preflashtime = conf->timing.preflashtime;
12827 if (conf->timing.winktime >= 0)
12828 p.winktime = conf->timing.winktime;
12829 if (conf->timing.flashtime >= 0)
12830 p.flashtime = conf->timing.flashtime;
12831 if (conf->timing.starttime >= 0)
12832 p.starttime = conf->timing.starttime;
12833 if (conf->timing.rxwinktime >= 0)
12834 p.rxwinktime = conf->timing.rxwinktime;
12835 if (conf->timing.rxflashtime >= 0)
12836 p.rxflashtime = conf->timing.rxflashtime;
12837 if (conf->timing.debouncetime >= 0)
12838 p.debouncetime = conf->timing.debouncetime;
12839 }
12840
12841
12842 if (tmp->subs[SUB_REAL].dfd >= 0)
12843 {
12844 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12845 if (res < 0) {
12846 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12847 destroy_dahdi_pvt(tmp);
12848 return NULL;
12849 }
12850 }
12851 #if 1
12852 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12853 memset(&bi, 0, sizeof(bi));
12854 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12855 if (!res) {
12856 bi.txbufpolicy = conf->chan.buf_policy;
12857 bi.rxbufpolicy = conf->chan.buf_policy;
12858 bi.numbufs = conf->chan.buf_no;
12859 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12860 if (res < 0) {
12861 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12862 }
12863 } else {
12864 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12865 }
12866 tmp->buf_policy = conf->chan.buf_policy;
12867 tmp->buf_no = conf->chan.buf_no;
12868 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12869 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12870 tmp->faxbuf_no = conf->chan.faxbuf_no;
12871
12872
12873
12874
12875 tmp->bufsize = bi.bufsize;
12876 }
12877 #endif
12878 tmp->immediate = conf->chan.immediate;
12879 tmp->transfertobusy = conf->chan.transfertobusy;
12880 if (chan_sig & __DAHDI_SIG_FXS) {
12881 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12882 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12883 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12884 }
12885 tmp->ringt_base = ringt_base;
12886 tmp->firstradio = 0;
12887 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12888 tmp->permcallwaiting = conf->chan.callwaiting;
12889 else
12890 tmp->permcallwaiting = 0;
12891
12892 tmp->destroy = 0;
12893 tmp->drings = conf->chan.drings;
12894
12895
12896 if (tmp->drings.ringnum[0].range == 0)
12897 tmp->drings.ringnum[0].range = 10;
12898 if (tmp->drings.ringnum[1].range == 0)
12899 tmp->drings.ringnum[1].range = 10;
12900 if (tmp->drings.ringnum[2].range == 0)
12901 tmp->drings.ringnum[2].range = 10;
12902
12903 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12904 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12905 tmp->threewaycalling = conf->chan.threewaycalling;
12906 tmp->adsi = conf->chan.adsi;
12907 tmp->use_smdi = conf->chan.use_smdi;
12908 tmp->permhidecallerid = conf->chan.hidecallerid;
12909 tmp->hidecalleridname = conf->chan.hidecalleridname;
12910 tmp->callreturn = conf->chan.callreturn;
12911 tmp->echocancel = conf->chan.echocancel;
12912 tmp->echotraining = conf->chan.echotraining;
12913 tmp->pulse = conf->chan.pulse;
12914 if (tmp->echocancel.head.tap_length) {
12915 tmp->echocanbridged = conf->chan.echocanbridged;
12916 } else {
12917 if (conf->chan.echocanbridged)
12918 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12919 tmp->echocanbridged = 0;
12920 }
12921 tmp->busydetect = conf->chan.busydetect;
12922 tmp->busycount = conf->chan.busycount;
12923 tmp->busycompare = conf->chan.busycompare;
12924 tmp->busytonelength = conf->chan.busytonelength;
12925 tmp->busyquietlength = conf->chan.busyquietlength;
12926 tmp->busyfuzziness = conf->chan.busyfuzziness;
12927 tmp->silencethreshold = conf->chan.silencethreshold;
12928 tmp->callprogress = conf->chan.callprogress;
12929 tmp->waitfordialtone = conf->chan.waitfordialtone;
12930 tmp->cancallforward = conf->chan.cancallforward;
12931 tmp->dtmfrelax = conf->chan.dtmfrelax;
12932 tmp->callwaiting = tmp->permcallwaiting;
12933 tmp->hidecallerid = tmp->permhidecallerid;
12934 tmp->channel = channel;
12935 tmp->stripmsd = conf->chan.stripmsd;
12936 tmp->use_callerid = conf->chan.use_callerid;
12937 tmp->cid_signalling = conf->chan.cid_signalling;
12938 tmp->cid_start = conf->chan.cid_start;
12939 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12940 tmp->restrictcid = conf->chan.restrictcid;
12941 tmp->use_callingpres = conf->chan.use_callingpres;
12942 if (tmp->usedistinctiveringdetection) {
12943 if (!tmp->use_callerid) {
12944 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12945 tmp->use_callerid = 1;
12946 }
12947 }
12948
12949 if (tmp->cid_signalling == CID_SIG_SMDI) {
12950 if (!tmp->use_smdi) {
12951 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12952 tmp->use_smdi = 1;
12953 }
12954 }
12955 if (tmp->use_smdi) {
12956 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12957 if (!(tmp->smdi_iface)) {
12958 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12959 tmp->use_smdi = 0;
12960 }
12961 }
12962
12963 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12964 tmp->amaflags = conf->chan.amaflags;
12965 if (!here) {
12966 tmp->confno = -1;
12967 tmp->propconfno = -1;
12968 }
12969 tmp->canpark = conf->chan.canpark;
12970 tmp->transfer = conf->chan.transfer;
12971 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12972 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12973 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12974 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12975 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12976 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12977 tmp->cid_ton = 0;
12978 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12979 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12980 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12981 } else {
12982 tmp->cid_num[0] = '\0';
12983 tmp->cid_name[0] = '\0';
12984 }
12985 #if defined(HAVE_PRI)
12986 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12987 tmp->cid_tag[0] = '\0';
12988 } else
12989 #endif
12990 {
12991 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12992 }
12993 tmp->cid_subaddr[0] = '\0';
12994 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12995 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12996 char *mailbox, *context;
12997 mailbox = context = ast_strdupa(tmp->mailbox);
12998 strsep(&context, "@");
12999 if (ast_strlen_zero(context))
13000 context = "default";
13001 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
13002 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
13003 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
13004 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
13005 AST_EVENT_IE_END);
13006 }
13007 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13008 tmp->mwisend_setting = conf->chan.mwisend_setting;
13009 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13010 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13011 #endif
13012
13013 tmp->group = conf->chan.group;
13014 tmp->callgroup = conf->chan.callgroup;
13015 tmp->pickupgroup= conf->chan.pickupgroup;
13016 if (conf->chan.vars) {
13017 struct ast_variable *v, *tmpvar;
13018 for (v = conf->chan.vars ; v ; v = v->next) {
13019 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13020 tmpvar->next = tmp->vars;
13021 tmp->vars = tmpvar;
13022 }
13023 }
13024 }
13025 tmp->cid_rxgain = conf->chan.cid_rxgain;
13026 tmp->rxgain = conf->chan.rxgain;
13027 tmp->txgain = conf->chan.txgain;
13028 tmp->txdrc = conf->chan.txdrc;
13029 tmp->rxdrc = conf->chan.rxdrc;
13030 tmp->tonezone = conf->chan.tonezone;
13031 if (tmp->subs[SUB_REAL].dfd > -1) {
13032 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13033 if (tmp->dsp)
13034 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13035 update_conf(tmp);
13036 if (!here) {
13037 switch (chan_sig) {
13038 case SIG_PRI_LIB_HANDLE_CASES:
13039 case SIG_SS7:
13040 case SIG_MFCR2:
13041 break;
13042 default:
13043
13044 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13045 break;
13046 }
13047 }
13048 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13049 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13050
13051 switch (tmp->sig) {
13052 #ifdef HAVE_PRI
13053 case SIG_PRI_LIB_HANDLE_CASES:
13054 sig_pri_set_alarm(tmp->sig_pvt, 1);
13055 break;
13056 #endif
13057 #if defined(HAVE_SS7)
13058 case SIG_SS7:
13059 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13060 break;
13061 #endif
13062 default:
13063
13064 analog_p = tmp->sig_pvt;
13065 if (analog_p) {
13066 analog_p->inalarm = 1;
13067 }
13068 tmp->inalarm = 1;
13069 break;
13070 }
13071 handle_alarms(tmp, res);
13072 }
13073 }
13074
13075 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13076 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13077 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13078 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13079 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13080
13081 if (!here) {
13082 tmp->locallyblocked = 0;
13083 tmp->remotelyblocked = 0;
13084 switch (tmp->sig) {
13085 #if defined(HAVE_PRI)
13086 case SIG_PRI_LIB_HANDLE_CASES:
13087 tmp->inservice = 1;
13088 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13089 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13090 if (chan_sig == SIG_PRI) {
13091 char db_chan_name[20];
13092 char db_answer[5];
13093
13094
13095
13096
13097
13098 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13099 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13100 unsigned *why;
13101
13102 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13103 if (tmp->pri->enable_service_message_support) {
13104 char state;
13105
13106 sscanf(db_answer, "%1c:%30u", &state, why);
13107
13108
13109 *why &= (SRVST_NEAREND | SRVST_FAREND);
13110 }
13111 if (!*why) {
13112 ast_db_del(db_chan_name, SRVST_DBKEY);
13113 }
13114 }
13115 }
13116 #endif
13117 break;
13118 #endif
13119 #if defined(HAVE_SS7)
13120 case SIG_SS7:
13121 tmp->inservice = 0;
13122 break;
13123 #endif
13124 default:
13125
13126 tmp->inservice = 1;
13127 break;
13128 }
13129 }
13130
13131 switch (tmp->sig) {
13132 #if defined(HAVE_PRI)
13133 case SIG_PRI_LIB_HANDLE_CASES:
13134 if (pri_chan) {
13135 pri_chan->channel = tmp->channel;
13136 pri_chan->hidecallerid = tmp->hidecallerid;
13137 pri_chan->hidecalleridname = tmp->hidecalleridname;
13138 pri_chan->immediate = tmp->immediate;
13139 pri_chan->inalarm = tmp->inalarm;
13140 pri_chan->priexclusive = tmp->priexclusive;
13141 pri_chan->priindication_oob = tmp->priindication_oob;
13142 pri_chan->use_callerid = tmp->use_callerid;
13143 pri_chan->use_callingpres = tmp->use_callingpres;
13144 ast_copy_string(pri_chan->context, tmp->context,
13145 sizeof(pri_chan->context));
13146 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13147 sizeof(pri_chan->mohinterpret));
13148 pri_chan->stripmsd = tmp->stripmsd;
13149 }
13150 break;
13151 #endif
13152 #if defined(HAVE_SS7)
13153 case SIG_SS7:
13154 if (ss7_chan) {
13155 ss7_chan->inalarm = tmp->inalarm;
13156
13157 ss7_chan->stripmsd = tmp->stripmsd;
13158 ss7_chan->hidecallerid = tmp->hidecallerid;
13159 ss7_chan->use_callerid = tmp->use_callerid;
13160 ss7_chan->use_callingpres = tmp->use_callingpres;
13161 ss7_chan->immediate = tmp->immediate;
13162 ss7_chan->locallyblocked = tmp->locallyblocked;
13163 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13164 ast_copy_string(ss7_chan->context, tmp->context,
13165 sizeof(ss7_chan->context));
13166 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13167 sizeof(ss7_chan->mohinterpret));
13168 }
13169 break;
13170 #endif
13171 default:
13172
13173 analog_p = tmp->sig_pvt;
13174 if (analog_p) {
13175 analog_p->channel = tmp->channel;
13176 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13177 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13178 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13179 analog_p->permcallwaiting = conf->chan.callwaiting;
13180 analog_p->callreturn = conf->chan.callreturn;
13181 analog_p->cancallforward = conf->chan.cancallforward;
13182 analog_p->canpark = conf->chan.canpark;
13183 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13184 analog_p->immediate = conf->chan.immediate;
13185 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13186 analog_p->pulse = conf->chan.pulse;
13187 analog_p->threewaycalling = conf->chan.threewaycalling;
13188 analog_p->transfer = conf->chan.transfer;
13189 analog_p->transfertobusy = conf->chan.transfertobusy;
13190 analog_p->use_callerid = tmp->use_callerid;
13191 analog_p->use_smdi = tmp->use_smdi;
13192 analog_p->smdi_iface = tmp->smdi_iface;
13193 analog_p->outsigmod = ANALOG_SIG_NONE;
13194 analog_p->echotraining = conf->chan.echotraining;
13195 analog_p->cid_signalling = conf->chan.cid_signalling;
13196 analog_p->stripmsd = conf->chan.stripmsd;
13197 switch (conf->chan.cid_start) {
13198 case CID_START_POLARITY:
13199 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13200 break;
13201 case CID_START_POLARITY_IN:
13202 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13203 break;
13204 case CID_START_DTMF_NOALERT:
13205 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13206 break;
13207 default:
13208 analog_p->cid_start = ANALOG_CID_START_RING;
13209 break;
13210 }
13211 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13212 analog_p->ringt = conf->chan.ringt;
13213 analog_p->ringt_base = ringt_base;
13214 analog_p->onhooktime = time(NULL);
13215 if (chan_sig & __DAHDI_SIG_FXO) {
13216 memset(&p, 0, sizeof(p));
13217 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13218 if (!res) {
13219 analog_p->fxsoffhookstate = p.rxisoffhook;
13220 }
13221 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13222 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13223 #endif
13224 }
13225 analog_p->msgstate = -1;
13226
13227 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13228 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13229 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13230
13231 analog_config_complete(analog_p);
13232 }
13233 break;
13234 }
13235 #if defined(HAVE_PRI)
13236 if (tmp->channel == CHAN_PSEUDO) {
13237
13238
13239
13240
13241 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13242 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13243 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13244 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13245 }
13246 #endif
13247 }
13248 if (tmp && !here) {
13249
13250 dahdi_iflist_insert(tmp);
13251 }
13252 return tmp;
13253 }
13254
13255 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13256 {
13257 #if defined(HAVE_PRI)
13258 if (0 < span) {
13259
13260 if (!p->pri || p->pri->span != span) {
13261 return 0;
13262 }
13263 if (!groupmatch && channelmatch == -1) {
13264
13265 *groupmatched = 1;
13266 return 1;
13267 }
13268 }
13269 #endif
13270
13271 if (groupmatch) {
13272 if ((p->group & groupmatch) != groupmatch)
13273
13274 return 0;
13275 *groupmatched = 1;
13276 }
13277
13278 if (channelmatch != -1) {
13279 if (p->channel != channelmatch)
13280
13281 return 0;
13282 *channelmatched = 1;
13283 }
13284
13285 return 1;
13286 }
13287
13288 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13289 {
13290 struct dahdi_pvt *p = *pvt;
13291
13292 if (p->inalarm)
13293 return 0;
13294
13295 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13296 return analog_available(p->sig_pvt);
13297
13298 switch (p->sig) {
13299 #if defined(HAVE_PRI)
13300 case SIG_PRI_LIB_HANDLE_CASES:
13301 {
13302 struct sig_pri_chan *pvt_chan;
13303 int res;
13304
13305 pvt_chan = p->sig_pvt;
13306 res = sig_pri_available(&pvt_chan, is_specific_channel);
13307 *pvt = pvt_chan->chan_pvt;
13308 return res;
13309 }
13310 #endif
13311 #if defined(HAVE_SS7)
13312 case SIG_SS7:
13313 return sig_ss7_available(p->sig_pvt);
13314 #endif
13315 default:
13316 break;
13317 }
13318
13319 if (p->locallyblocked || p->remotelyblocked) {
13320 return 0;
13321 }
13322
13323
13324 if (!p->owner) {
13325 #ifdef HAVE_OPENR2
13326
13327 if (p->mfcr2) {
13328 if (p->mfcr2call) {
13329 return 0;
13330 } else {
13331 return 1;
13332 }
13333 }
13334 #endif
13335 return 1;
13336 }
13337
13338 return 0;
13339 }
13340
13341 #if defined(HAVE_PRI)
13342 #if defined(HAVE_PRI_CALL_WAITING)
13343
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353
13354
13355 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13356 {
13357 struct dahdi_pvt *pvt = priv;
13358
13359 pvt->stripmsd = pri->ch_cfg.stripmsd;
13360 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13361 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13362 pvt->immediate = pri->ch_cfg.immediate;
13363 pvt->priexclusive = pri->ch_cfg.priexclusive;
13364 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13365 pvt->use_callerid = pri->ch_cfg.use_callerid;
13366 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13367 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13368 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13369 }
13370 #endif
13371 #endif
13372
13373 #if defined(HAVE_PRI)
13374
13375
13376
13377
13378
13379
13380
13381
13382
13383
13384
13385
13386 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13387 {
13388 int pvt_idx;
13389 int res;
13390 unsigned idx;
13391 struct dahdi_pvt *pvt;
13392 struct sig_pri_chan *chan;
13393 struct dahdi_bufferinfo bi;
13394
13395 static int nobch_channel = CHAN_PSEUDO;
13396
13397
13398 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13399 if (!pri->pvts[pvt_idx]) {
13400 break;
13401 }
13402 }
13403 if (pri->numchans == pvt_idx) {
13404 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13405 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13406 return -1;
13407 }
13408
13409
13410 pri->pvts[pvt_idx] = NULL;
13411 ++pri->numchans;
13412 }
13413
13414 pvt = ast_calloc(1, sizeof(*pvt));
13415 if (!pvt) {
13416 return -1;
13417 }
13418 pvt->cc_params = ast_cc_config_params_init();
13419 if (!pvt->cc_params) {
13420 ast_free(pvt);
13421 return -1;
13422 }
13423 ast_mutex_init(&pvt->lock);
13424 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13425 pvt->subs[idx].dfd = -1;
13426 }
13427 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13428 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13429 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13430 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13431
13432 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13433 if (!chan) {
13434 destroy_dahdi_pvt(pvt);
13435 return -1;
13436 }
13437 chan->no_b_channel = 1;
13438
13439
13440
13441
13442
13443
13444 pvt->law_default = DAHDI_LAW_ALAW;
13445
13446 pvt->sig = pri->sig;
13447 pvt->outsigmod = -1;
13448 pvt->pri = pri;
13449 pvt->sig_pvt = chan;
13450 pri->pvts[pvt_idx] = chan;
13451
13452 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13453 if (pvt->subs[SUB_REAL].dfd < 0) {
13454 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13455 strerror(errno));
13456 destroy_dahdi_pvt(pvt);
13457 return -1;
13458 }
13459 memset(&bi, 0, sizeof(bi));
13460 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13461 if (!res) {
13462 pvt->bufsize = bi.bufsize;
13463 bi.txbufpolicy = pvt->buf_policy;
13464 bi.rxbufpolicy = pvt->buf_policy;
13465 bi.numbufs = pvt->buf_no;
13466 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13467 if (res < 0) {
13468 ast_log(LOG_WARNING,
13469 "Unable to set buffer policy on no B channel interface: %s\n",
13470 strerror(errno));
13471 }
13472 } else
13473 ast_log(LOG_WARNING,
13474 "Unable to check buffer policy on no B channel interface: %s\n",
13475 strerror(errno));
13476
13477 --nobch_channel;
13478 if (CHAN_PSEUDO < nobch_channel) {
13479 nobch_channel = CHAN_PSEUDO - 1;
13480 }
13481 pvt->channel = nobch_channel;
13482 pvt->span = pri->span;
13483 chan->channel = pvt->channel;
13484
13485 dahdi_nobch_insert(pri, pvt);
13486
13487 return pvt_idx;
13488 }
13489 #endif
13490
13491
13492
13493
13494
13495
13496 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13497 {
13498 struct dahdi_pvt *p;
13499 struct dahdi_bufferinfo bi;
13500 int res;
13501
13502 p = ast_malloc(sizeof(*p));
13503 if (!p) {
13504 return NULL;
13505 }
13506 *p = *src;
13507
13508
13509 p->cc_params = ast_cc_config_params_init();
13510 if (!p->cc_params) {
13511 ast_free(p);
13512 return NULL;
13513 }
13514 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13515
13516 p->which_iflist = DAHDI_IFLIST_NONE;
13517 p->next = NULL;
13518 p->prev = NULL;
13519 ast_mutex_init(&p->lock);
13520 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13521 if (p->subs[SUB_REAL].dfd < 0) {
13522 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13523 destroy_dahdi_pvt(p);
13524 return NULL;
13525 }
13526 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13527 if (!res) {
13528 bi.txbufpolicy = src->buf_policy;
13529 bi.rxbufpolicy = src->buf_policy;
13530 bi.numbufs = src->buf_no;
13531 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13532 if (res < 0) {
13533 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13534 }
13535 } else
13536 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13537 p->destroy = 1;
13538 dahdi_iflist_insert(p);
13539 return p;
13540 }
13541
13542 struct dahdi_starting_point {
13543
13544 ast_group_t groupmatch;
13545
13546 int channelmatch;
13547
13548 int rr_starting_point;
13549
13550 int span;
13551
13552 int cadance;
13553
13554 char opt;
13555
13556 char backwards;
13557
13558 char roundrobin;
13559 };
13560 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13561 {
13562 char *dest;
13563 char *s;
13564 int x;
13565 int res = 0;
13566 struct dahdi_pvt *p;
13567 char *subdir = NULL;
13568 AST_DECLARE_APP_ARGS(args,
13569 AST_APP_ARG(group);
13570
13571
13572 AST_APP_ARG(other);
13573 );
13574
13575
13576
13577
13578
13579
13580
13581
13582
13583
13584
13585
13586
13587
13588
13589
13590
13591
13592
13593
13594
13595
13596
13597
13598 if (data) {
13599 dest = ast_strdupa(data);
13600 } else {
13601 ast_log(LOG_WARNING, "Channel requested with no data\n");
13602 return NULL;
13603 }
13604 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13605 if (!args.argc || ast_strlen_zero(args.group)) {
13606 ast_log(LOG_WARNING, "No channel/group specified\n");
13607 return NULL;
13608 }
13609
13610
13611 memset(param, 0, sizeof(*param));
13612 param->channelmatch = -1;
13613
13614 if (strchr(args.group, '!') != NULL) {
13615 char *prev = args.group;
13616 while ((s = strchr(prev, '!')) != NULL) {
13617 *s++ = '/';
13618 prev = s;
13619 }
13620 *(prev - 1) = '\0';
13621 subdir = args.group;
13622 args.group = prev;
13623 } else if (args.group[0] == 'i') {
13624
13625 res = sscanf(args.group + 1, "%30d", &x);
13626 if (res < 1) {
13627 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13628 return NULL;
13629 }
13630 param->span = x;
13631
13632
13633 s = strchr(args.group, '-');
13634 if (!s) {
13635
13636 return iflist;
13637 }
13638 args.group = s + 1;
13639 res = 0;
13640 }
13641 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13642
13643 s = args.group + 1;
13644 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13645 if (res < 1) {
13646 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13647 return NULL;
13648 }
13649 param->groupmatch = ((ast_group_t) 1 << x);
13650
13651 if (toupper(args.group[0]) == 'G') {
13652 if (args.group[0] == 'G') {
13653 param->backwards = 1;
13654 p = ifend;
13655 } else
13656 p = iflist;
13657 } else {
13658 if (ARRAY_LEN(round_robin) <= x) {
13659 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13660 x, data);
13661 return NULL;
13662 }
13663 if (args.group[0] == 'R') {
13664 param->backwards = 1;
13665 p = round_robin[x] ? round_robin[x]->prev : ifend;
13666 if (!p)
13667 p = ifend;
13668 } else {
13669 p = round_robin[x] ? round_robin[x]->next : iflist;
13670 if (!p)
13671 p = iflist;
13672 }
13673 param->roundrobin = 1;
13674 param->rr_starting_point = x;
13675 }
13676 } else {
13677 s = args.group;
13678 if (!strcasecmp(s, "pseudo")) {
13679
13680 x = CHAN_PSEUDO;
13681 param->channelmatch = x;
13682 } else {
13683 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13684 if (res < 1) {
13685 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13686 return NULL;
13687 } else {
13688 param->channelmatch = x;
13689 }
13690 }
13691 if (subdir) {
13692 char path[PATH_MAX];
13693 struct stat stbuf;
13694
13695 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13696 subdir, param->channelmatch);
13697 if (stat(path, &stbuf) < 0) {
13698 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13699 path, strerror(errno));
13700 return NULL;
13701 }
13702 if (!S_ISCHR(stbuf.st_mode)) {
13703 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13704 path);
13705 return NULL;
13706 }
13707 param->channelmatch = minor(stbuf.st_rdev);
13708 }
13709
13710 p = iflist;
13711 }
13712
13713 if (param->opt == 'r' && res < 3) {
13714 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13715 param->opt = '\0';
13716 }
13717
13718 return p;
13719 }
13720
13721 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13722 {
13723 int callwait = 0;
13724 struct dahdi_pvt *p;
13725 struct ast_channel *tmp = NULL;
13726 struct dahdi_pvt *exitpvt;
13727 int channelmatched = 0;
13728 int groupmatched = 0;
13729 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13730 int transcapdigital = 0;
13731 #endif
13732 struct dahdi_starting_point start;
13733
13734 ast_mutex_lock(&iflock);
13735 p = determine_starting_point(data, &start);
13736 if (!p) {
13737
13738 ast_mutex_unlock(&iflock);
13739 return NULL;
13740 }
13741
13742
13743 exitpvt = p;
13744 while (p && !tmp) {
13745 if (start.roundrobin)
13746 round_robin[start.rr_starting_point] = p;
13747
13748 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13749 && available(&p, channelmatched)) {
13750 ast_debug(1, "Using channel %d\n", p->channel);
13751
13752 callwait = (p->owner != NULL);
13753 #ifdef HAVE_OPENR2
13754 if (p->mfcr2) {
13755 ast_mutex_lock(&p->lock);
13756 if (p->mfcr2call) {
13757 ast_mutex_unlock(&p->lock);
13758 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13759 goto next;
13760 }
13761 p->mfcr2call = 1;
13762 ast_mutex_unlock(&p->lock);
13763 }
13764 #endif
13765 if (p->channel == CHAN_PSEUDO) {
13766 p = duplicate_pseudo(p);
13767 if (!p) {
13768 break;
13769 }
13770 }
13771
13772 p->distinctivering = 0;
13773
13774 switch (start.opt) {
13775 case '\0':
13776
13777 break;
13778 case 'c':
13779
13780 p->confirmanswer = 1;
13781 break;
13782 case 'r':
13783
13784 p->distinctivering = start.cadance;
13785 break;
13786 case 'd':
13787 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13788
13789 transcapdigital = AST_TRANS_CAP_DIGITAL;
13790 #endif
13791 break;
13792 default:
13793 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13794 break;
13795 }
13796
13797 p->outgoing = 1;
13798 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13799 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13800 #ifdef HAVE_PRI
13801 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13802
13803
13804
13805
13806
13807 ast_mutex_lock(&p->lock);
13808 ast_mutex_unlock(&p->lock);
13809
13810 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13811 sizeof(p->dnid));
13812 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13813 #endif
13814 #if defined(HAVE_SS7)
13815 } else if (p->sig == SIG_SS7) {
13816 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13817 #endif
13818 } else {
13819 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13820 }
13821 if (!tmp) {
13822 p->outgoing = 0;
13823 #if defined(HAVE_PRI)
13824 switch (p->sig) {
13825 case SIG_PRI_LIB_HANDLE_CASES:
13826 #if defined(HAVE_PRI_CALL_WAITING)
13827 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13828 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13829 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13830 }
13831 #endif
13832
13833
13834
13835
13836 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13837 break;
13838 default:
13839 break;
13840 }
13841 #endif
13842 } else {
13843 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13844 }
13845 break;
13846 }
13847 #ifdef HAVE_OPENR2
13848 next:
13849 #endif
13850 if (start.backwards) {
13851 p = p->prev;
13852 if (!p)
13853 p = ifend;
13854 } else {
13855 p = p->next;
13856 if (!p)
13857 p = iflist;
13858 }
13859
13860 if (p == exitpvt)
13861 break;
13862 }
13863 ast_mutex_unlock(&iflock);
13864 restart_monitor();
13865 if (cause && !tmp) {
13866 if (callwait || channelmatched) {
13867 *cause = AST_CAUSE_BUSY;
13868 } else if (groupmatched) {
13869 *cause = AST_CAUSE_CONGESTION;
13870 } else {
13871
13872
13873
13874
13875 }
13876 }
13877
13878 return tmp;
13879 }
13880
13881
13882
13883
13884
13885
13886
13887
13888
13889
13890
13891 static int dahdi_devicestate(void *data)
13892 {
13893 #if defined(HAVE_PRI)
13894 char *device;
13895 unsigned span;
13896 int res;
13897
13898 device = data;
13899
13900 if (*device != 'I') {
13901
13902 return AST_DEVICE_UNKNOWN;
13903 }
13904 res = sscanf(device, "I%30u", &span);
13905 if (res != 1 || !span || NUM_SPANS < span) {
13906
13907 return AST_DEVICE_UNKNOWN;
13908 }
13909 device = strchr(device, '/');
13910 if (!device) {
13911
13912 return AST_DEVICE_UNKNOWN;
13913 }
13914
13915
13916
13917
13918
13919 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13920 ++device;
13921 if (!strcmp(device, "congestion"))
13922 #endif
13923 {
13924 return pris[span - 1].pri.congestion_devstate;
13925 }
13926 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13927 else if (!strcmp(device, "threshold")) {
13928 return pris[span - 1].pri.threshold_devstate;
13929 }
13930 return AST_DEVICE_UNKNOWN;
13931 #endif
13932 #else
13933 return AST_DEVICE_UNKNOWN;
13934 #endif
13935 }
13936
13937
13938
13939
13940
13941
13942
13943
13944
13945
13946
13947
13948
13949
13950
13951
13952
13953 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13954 {
13955 struct dahdi_pvt *p;
13956 struct dahdi_pvt *exitpvt;
13957 struct dahdi_starting_point start;
13958 int groupmatched = 0;
13959 int channelmatched = 0;
13960
13961 ast_mutex_lock(&iflock);
13962 p = determine_starting_point(dest, &start);
13963 if (!p) {
13964 ast_mutex_unlock(&iflock);
13965 return -1;
13966 }
13967 exitpvt = p;
13968 for (;;) {
13969 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13970
13971 struct ast_str *device_name;
13972 char *dash;
13973 const char *monitor_type;
13974 char dialstring[AST_CHANNEL_NAME];
13975 char full_device_name[AST_CHANNEL_NAME];
13976
13977 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13978 case AST_CC_MONITOR_NEVER:
13979 break;
13980 case AST_CC_MONITOR_NATIVE:
13981 case AST_CC_MONITOR_ALWAYS:
13982 case AST_CC_MONITOR_GENERIC:
13983 #if defined(HAVE_PRI)
13984 if (dahdi_sig_pri_lib_handles(p->sig)) {
13985
13986
13987
13988
13989 snprintf(full_device_name, sizeof(full_device_name),
13990 "DAHDI/I%d/congestion", p->pri->span);
13991 } else
13992 #endif
13993 {
13994 #if defined(HAVE_PRI)
13995 device_name = create_channel_name(p, 1, "");
13996 #else
13997 device_name = create_channel_name(p);
13998 #endif
13999 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14000 device_name ? ast_str_buffer(device_name) : "");
14001 ast_free(device_name);
14002
14003
14004
14005
14006
14007 dash = strrchr(full_device_name, '-');
14008 if (dash) {
14009 *dash = '\0';
14010 }
14011 }
14012 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14013
14014
14015
14016
14017
14018
14019
14020 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14021 callback(inbound,
14022 #if defined(HAVE_PRI)
14023 p->pri ? p->pri->cc_params : p->cc_params,
14024 #else
14025 p->cc_params,
14026 #endif
14027 monitor_type, full_device_name, dialstring, NULL);
14028 break;
14029 }
14030 }
14031 p = start.backwards ? p->prev : p->next;
14032 if (!p) {
14033 p = start.backwards ? ifend : iflist;
14034 }
14035 if (p == exitpvt) {
14036 break;
14037 }
14038 }
14039 ast_mutex_unlock(&iflock);
14040 return 0;
14041 }
14042
14043 #if defined(HAVE_SS7)
14044 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14045 {
14046 int i;
14047
14048 if (ss7) {
14049 for (i = 0; i < NUM_SPANS; i++) {
14050 if (linksets[i].ss7.ss7 == ss7) {
14051 ast_verbose("[%d] %s", i + 1, s);
14052 return;
14053 }
14054 }
14055 }
14056 ast_verbose("%s", s);
14057 }
14058 #endif
14059
14060 #if defined(HAVE_SS7)
14061 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14062 {
14063 int i;
14064
14065 if (ss7) {
14066 for (i = 0; i < NUM_SPANS; i++) {
14067 if (linksets[i].ss7.ss7 == ss7) {
14068 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14069 return;
14070 }
14071 }
14072 }
14073 ast_log(LOG_ERROR, "%s", s);
14074 }
14075 #endif
14076
14077 #if defined(HAVE_OPENR2)
14078 static void *mfcr2_monitor(void *data)
14079 {
14080 struct dahdi_mfcr2 *mfcr2 = data;
14081
14082
14083
14084
14085
14086 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14087 int res = 0;
14088 int i = 0;
14089 int oldstate = 0;
14090 int quit_loop = 0;
14091 int maxsleep = 20;
14092 int was_idle = 0;
14093 int pollsize = 0;
14094
14095
14096 for (i = 0; i < mfcr2->numchans; i++) {
14097 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14098 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14099 }
14100 while (1) {
14101
14102
14103 pollsize = 0;
14104 for (i = 0; i < mfcr2->numchans; i++) {
14105 pollers[i].revents = 0;
14106 pollers[i].events = 0;
14107 if (mfcr2->pvts[i]->owner) {
14108 continue;
14109 }
14110 if (!mfcr2->pvts[i]->r2chan) {
14111 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14112 quit_loop = 1;
14113 break;
14114 }
14115 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14116 pollers[i].events = POLLIN | POLLPRI;
14117 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14118 pollsize++;
14119 }
14120 if (quit_loop) {
14121 break;
14122 }
14123 if (pollsize == 0) {
14124 if (!was_idle) {
14125 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14126 was_idle = 1;
14127 }
14128 poll(NULL, 0, maxsleep);
14129 continue;
14130 }
14131 was_idle = 0;
14132
14133
14134 pthread_testcancel();
14135 res = poll(pollers, mfcr2->numchans, maxsleep);
14136 pthread_testcancel();
14137 if ((res < 0) && (errno != EINTR)) {
14138 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14139 break;
14140 }
14141
14142 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14143 for (i = 0; i < mfcr2->numchans; i++) {
14144 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14145 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14146 }
14147 }
14148 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14149 }
14150 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14151 return 0;
14152 }
14153 #endif
14154
14155 #if defined(HAVE_PRI)
14156 static void dahdi_pri_message(struct pri *pri, char *s)
14157 {
14158 int x;
14159 int y;
14160 int dchan = -1;
14161 int span = -1;
14162 int dchancount = 0;
14163
14164 if (pri) {
14165 for (x = 0; x < NUM_SPANS; x++) {
14166 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14167 if (pris[x].pri.dchans[y]) {
14168 dchancount++;
14169 }
14170
14171 if (pris[x].pri.dchans[y] == pri) {
14172 dchan = y;
14173 }
14174 }
14175 if (dchan >= 0) {
14176 span = x;
14177 break;
14178 }
14179 dchancount = 0;
14180 }
14181 if (-1 < span) {
14182 if (1 < dchancount) {
14183 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14184 } else {
14185 ast_verbose("PRI Span: %d %s", span + 1, s);
14186 }
14187 } else {
14188 ast_verbose("PRI Span: ? %s", s);
14189 }
14190 } else {
14191 ast_verbose("PRI Span: ? %s", s);
14192 }
14193
14194 ast_mutex_lock(&pridebugfdlock);
14195
14196 if (pridebugfd >= 0) {
14197 if (write(pridebugfd, s, strlen(s)) < 0) {
14198 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14199 }
14200 }
14201
14202 ast_mutex_unlock(&pridebugfdlock);
14203 }
14204 #endif
14205
14206 #if defined(HAVE_PRI)
14207 static void dahdi_pri_error(struct pri *pri, char *s)
14208 {
14209 int x;
14210 int y;
14211 int dchan = -1;
14212 int span = -1;
14213 int dchancount = 0;
14214
14215 if (pri) {
14216 for (x = 0; x < NUM_SPANS; x++) {
14217 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14218 if (pris[x].pri.dchans[y]) {
14219 dchancount++;
14220 }
14221
14222 if (pris[x].pri.dchans[y] == pri) {
14223 dchan = y;
14224 }
14225 }
14226 if (dchan >= 0) {
14227 span = x;
14228 break;
14229 }
14230 dchancount = 0;
14231 }
14232 if (-1 < span) {
14233 if (1 < dchancount) {
14234 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14235 } else {
14236 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14237 }
14238 } else {
14239 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14240 }
14241 } else {
14242 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14243 }
14244
14245 ast_mutex_lock(&pridebugfdlock);
14246
14247 if (pridebugfd >= 0) {
14248 if (write(pridebugfd, s, strlen(s)) < 0) {
14249 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14250 }
14251 }
14252
14253 ast_mutex_unlock(&pridebugfdlock);
14254 }
14255 #endif
14256
14257 #if defined(HAVE_PRI)
14258 static int prepare_pri(struct dahdi_pri *pri)
14259 {
14260 int i, res, x;
14261 struct dahdi_params p;
14262 struct dahdi_bufferinfo bi;
14263 struct dahdi_spaninfo si;
14264
14265 pri->pri.calls = &dahdi_pri_callbacks;
14266
14267 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14268 if (!pri->dchannels[i])
14269 break;
14270 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14271 x = pri->dchannels[i];
14272 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14273 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14274 return -1;
14275 }
14276 memset(&p, 0, sizeof(p));
14277 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14278 if (res) {
14279 dahdi_close_pri_fd(pri, i);
14280 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14281 return -1;
14282 }
14283 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14284 dahdi_close_pri_fd(pri, i);
14285 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14286 return -1;
14287 }
14288 memset(&si, 0, sizeof(si));
14289 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14290 if (res) {
14291 dahdi_close_pri_fd(pri, i);
14292 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14293 }
14294 if (!si.alarms) {
14295 pri_event_noalarm(&pri->pri, i, 1);
14296 } else {
14297 pri_event_alarm(&pri->pri, i, 1);
14298 }
14299 memset(&bi, 0, sizeof(bi));
14300 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14301 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14302 bi.numbufs = 32;
14303 bi.bufsize = 1024;
14304 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14305 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14306 dahdi_close_pri_fd(pri, i);
14307 return -1;
14308 }
14309 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14310 }
14311 return 0;
14312 }
14313 #endif
14314
14315 #if defined(HAVE_PRI)
14316 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14317 {
14318 int which, span;
14319 char *ret = NULL;
14320
14321 if (pos != rpos)
14322 return ret;
14323
14324 for (which = span = 0; span < NUM_SPANS; span++) {
14325 if (pris[span].pri.pri && ++which > state) {
14326 if (ast_asprintf(&ret, "%d", span + 1) < 0) {
14327 ret = NULL;
14328 }
14329 break;
14330 }
14331 }
14332 return ret;
14333 }
14334 #endif
14335
14336 #if defined(HAVE_PRI)
14337 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14338 {
14339 return complete_span_helper(line,word,pos,state,3);
14340 }
14341 #endif
14342
14343 #if defined(HAVE_PRI)
14344 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14345 {
14346 int myfd;
14347 switch (cmd) {
14348 case CLI_INIT:
14349 e->command = "pri set debug file";
14350 e->usage = "Usage: pri set debug file [output-file]\n"
14351 " Sends PRI debug output to the specified output file\n";
14352 return NULL;
14353 case CLI_GENERATE:
14354 return NULL;
14355 }
14356 if (a->argc < 5)
14357 return CLI_SHOWUSAGE;
14358
14359 if (ast_strlen_zero(a->argv[4]))
14360 return CLI_SHOWUSAGE;
14361
14362 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14363 if (myfd < 0) {
14364 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14365 return CLI_SUCCESS;
14366 }
14367
14368 ast_mutex_lock(&pridebugfdlock);
14369
14370 if (pridebugfd >= 0)
14371 close(pridebugfd);
14372
14373 pridebugfd = myfd;
14374 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14375 ast_mutex_unlock(&pridebugfdlock);
14376 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14377 return CLI_SUCCESS;
14378 }
14379 #endif
14380
14381 #if defined(HAVE_PRI)
14382 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14383 {
14384 int span;
14385 int x;
14386 int level = 0;
14387 switch (cmd) {
14388 case CLI_INIT:
14389 e->command = "pri set debug {on|off|0|1|2} span";
14390 e->usage =
14391 "Usage: pri set debug {<level>|on|off} span <span>\n"
14392 " Enables debugging on a given PRI span\n";
14393 return NULL;
14394 case CLI_GENERATE:
14395 return complete_span_4(a->line, a->word, a->pos, a->n);
14396 }
14397 if (a->argc < 6) {
14398 return CLI_SHOWUSAGE;
14399 }
14400
14401 if (!strcasecmp(a->argv[3], "on")) {
14402 level = 1;
14403 } else if (!strcasecmp(a->argv[3], "off")) {
14404 level = 0;
14405 } else {
14406 level = atoi(a->argv[3]);
14407 }
14408 span = atoi(a->argv[5]);
14409 if ((span < 1) || (span > NUM_SPANS)) {
14410 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14411 return CLI_SUCCESS;
14412 }
14413 if (!pris[span-1].pri.pri) {
14414 ast_cli(a->fd, "No PRI running on span %d\n", span);
14415 return CLI_SUCCESS;
14416 }
14417
14418
14419 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14420 if (pris[span - 1].pri.dchans[x]) {
14421 switch (level) {
14422 case 0:
14423 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14424 break;
14425 case 1:
14426 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14427 break;
14428 default:
14429 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14430 break;
14431 }
14432 }
14433 }
14434 if (level == 0) {
14435
14436 ast_mutex_lock(&pridebugfdlock);
14437 if (0 <= pridebugfd) {
14438 close(pridebugfd);
14439 pridebugfd = -1;
14440 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14441 pridebugfilename);
14442 }
14443 ast_mutex_unlock(&pridebugfdlock);
14444 }
14445 pris[span - 1].pri.debug = (level) ? 1 : 0;
14446 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14447 return CLI_SUCCESS;
14448 }
14449 #endif
14450
14451 #if defined(HAVE_PRI)
14452 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14453 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14454 {
14455 unsigned *why;
14456 int channel;
14457 int trunkgroup;
14458 int x, y, fd = a->fd;
14459 int interfaceid = 0;
14460 char db_chan_name[20], db_answer[5];
14461 struct dahdi_pvt *tmp;
14462 struct dahdi_pri *pri;
14463
14464 if (a->argc < 5 || a->argc > 6)
14465 return CLI_SHOWUSAGE;
14466 if (strchr(a->argv[4], ':')) {
14467 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14468 return CLI_SHOWUSAGE;
14469 if ((trunkgroup < 1) || (channel < 1))
14470 return CLI_SHOWUSAGE;
14471 pri = NULL;
14472 for (x=0;x<NUM_SPANS;x++) {
14473 if (pris[x].pri.trunkgroup == trunkgroup) {
14474 pri = pris + x;
14475 break;
14476 }
14477 }
14478 if (!pri) {
14479 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14480 return CLI_FAILURE;
14481 }
14482 } else
14483 channel = atoi(a->argv[4]);
14484
14485 if (a->argc == 6)
14486 interfaceid = atoi(a->argv[5]);
14487
14488
14489 for (x = 0; x < NUM_SPANS; x++) {
14490 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14491 if (pris[x].dchannels[y] == channel) {
14492 pri = pris + x;
14493 if (pri->pri.enable_service_message_support) {
14494 ast_mutex_lock(&pri->pri.lock);
14495 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14496 ast_mutex_unlock(&pri->pri.lock);
14497 } else {
14498 ast_cli(fd,
14499 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14500 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14501 }
14502 return CLI_SUCCESS;
14503 }
14504 }
14505 }
14506
14507
14508 ast_mutex_lock(&iflock);
14509 for (tmp = iflist; tmp; tmp = tmp->next) {
14510 if (tmp->pri && tmp->channel == channel) {
14511 ast_mutex_unlock(&iflock);
14512 ast_mutex_lock(&tmp->pri->lock);
14513 if (!tmp->pri->enable_service_message_support) {
14514 ast_mutex_unlock(&tmp->pri->lock);
14515 ast_cli(fd,
14516 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14517 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14518 return CLI_SUCCESS;
14519 }
14520 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14521 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14522 switch(changestatus) {
14523 case 0:
14524
14525 ast_db_del(db_chan_name, SRVST_DBKEY);
14526 *why &= ~SRVST_NEAREND;
14527 if (*why) {
14528 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14529 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14530 } else {
14531 dahdi_pri_update_span_devstate(tmp->pri);
14532 }
14533 break;
14534
14535 case 2:
14536
14537 ast_db_del(db_chan_name, SRVST_DBKEY);
14538 *why |= SRVST_NEAREND;
14539 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14540 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14541 dahdi_pri_update_span_devstate(tmp->pri);
14542 break;
14543
14544
14545 default:
14546 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14547 break;
14548 }
14549 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14550 ast_mutex_unlock(&tmp->pri->lock);
14551 return CLI_SUCCESS;
14552 }
14553 }
14554 ast_mutex_unlock(&iflock);
14555
14556 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14557 return CLI_FAILURE;
14558 }
14559
14560 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14561 {
14562 switch (cmd) {
14563 case CLI_INIT:
14564 e->command = "pri service enable channel";
14565 e->usage =
14566 "Usage: pri service enable channel <channel> [<interface id>]\n"
14567 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14568 " to restore a channel to service, with optional interface id\n"
14569 " as agreed upon with remote switch operator\n";
14570 return NULL;
14571 case CLI_GENERATE:
14572 return NULL;
14573 }
14574 return handle_pri_service_generic(e, cmd, a, 0);
14575 }
14576
14577 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14578 {
14579 switch (cmd) {
14580 case CLI_INIT:
14581 e->command = "pri service disable channel";
14582 e->usage =
14583 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14584 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14585 " to remove a channel from service, with optional interface id\n"
14586 " as agreed upon with remote switch operator\n";
14587 return NULL;
14588 case CLI_GENERATE:
14589 return NULL;
14590 }
14591 return handle_pri_service_generic(e, cmd, a, 2);
14592 }
14593 #endif
14594 #endif
14595
14596 #if defined(HAVE_PRI)
14597 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14598 {
14599 int span;
14600
14601 switch (cmd) {
14602 case CLI_INIT:
14603 e->command = "pri show channels";
14604 e->usage =
14605 "Usage: pri show channels\n"
14606 " Displays PRI channel information such as the current mapping\n"
14607 " of DAHDI B channels to Asterisk channel names and which calls\n"
14608 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14609 " are not associated with any B channel.\n";
14610 return NULL;
14611 case CLI_GENERATE:
14612 return NULL;
14613 }
14614
14615 if (a->argc != 3)
14616 return CLI_SHOWUSAGE;
14617
14618 sig_pri_cli_show_channels_header(a->fd);
14619 for (span = 0; span < NUM_SPANS; ++span) {
14620 if (pris[span].pri.pri) {
14621 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14622 }
14623 }
14624 return CLI_SUCCESS;
14625 }
14626 #endif
14627
14628 #if defined(HAVE_PRI)
14629 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14630 {
14631 int span;
14632
14633 switch (cmd) {
14634 case CLI_INIT:
14635 e->command = "pri show spans";
14636 e->usage =
14637 "Usage: pri show spans\n"
14638 " Displays PRI span information\n";
14639 return NULL;
14640 case CLI_GENERATE:
14641 return NULL;
14642 }
14643
14644 if (a->argc != 3)
14645 return CLI_SHOWUSAGE;
14646
14647 for (span = 0; span < NUM_SPANS; span++) {
14648 if (pris[span].pri.pri) {
14649 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14650 }
14651 }
14652 return CLI_SUCCESS;
14653 }
14654 #endif
14655
14656 #if defined(HAVE_PRI)
14657 #define container_of(ptr, type, member) \
14658 ((type *)((char *)(ptr) - offsetof(type, member)))
14659
14660
14661
14662
14663
14664
14665
14666
14667
14668
14669
14670
14671
14672 static int pri_destroy_dchan(struct sig_pri_span *pri)
14673 {
14674 int i;
14675 struct dahdi_pri* dahdi_pri;
14676
14677 if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14678 return 0;
14679 }
14680 pthread_cancel(pri->master);
14681 pthread_join(pri->master, NULL);
14682
14683
14684 dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14685 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14686 ast_debug(4, "closing pri_fd %d\n", i);
14687 dahdi_close_pri_fd(dahdi_pri, i);
14688 }
14689 pri->pri = NULL;
14690 ast_debug(1, "PRI span %d destroyed\n", pri->span);
14691 return 1;
14692 }
14693
14694 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14695 struct ast_cli_args *a)
14696 {
14697 int span;
14698 int i;
14699 int res;
14700
14701 switch (cmd) {
14702 case CLI_INIT:
14703 e->command = "pri destroy span";
14704 e->usage =
14705 "Usage: pri destroy span <span>\n"
14706 " Destorys D-channel of span and its B-channels.\n"
14707 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14708 return NULL;
14709 case CLI_GENERATE:
14710 return complete_span_4(a->line, a->word, a->pos, a->n);
14711 }
14712
14713 if (a->argc < 4) {
14714 return CLI_SHOWUSAGE;
14715 }
14716 res = sscanf(a->argv[3], "%30d", &span);
14717 if ((res != 1) || span < 1 || span > NUM_SPANS) {
14718 ast_cli(a->fd,
14719 "Invalid span '%s'. Should be a number from %d to %d\n",
14720 a->argv[3], 1, NUM_SPANS);
14721 return CLI_SUCCESS;
14722 }
14723 if (!pris[span - 1].pri.pri) {
14724 ast_cli(a->fd, "No PRI running on span %d\n", span);
14725 return CLI_SUCCESS;
14726 }
14727
14728 for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14729 int channel;
14730 struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14731
14732 if (!pvt) {
14733 continue;
14734 }
14735 channel = pvt->channel;
14736 ast_debug(2, "About to destroy B-channel %d.\n", channel);
14737 dahdi_destroy_channel_bynum(channel);
14738 }
14739 ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14740 pri_destroy_dchan(&pris[span - 1].pri);
14741
14742 return CLI_SUCCESS;
14743 }
14744
14745 #endif
14746
14747 #if defined(HAVE_PRI)
14748 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14749 {
14750 int span;
14751
14752 switch (cmd) {
14753 case CLI_INIT:
14754 e->command = "pri show span";
14755 e->usage =
14756 "Usage: pri show span <span>\n"
14757 " Displays PRI Information on a given PRI span\n";
14758 return NULL;
14759 case CLI_GENERATE:
14760 return complete_span_4(a->line, a->word, a->pos, a->n);
14761 }
14762
14763 if (a->argc < 4)
14764 return CLI_SHOWUSAGE;
14765 span = atoi(a->argv[3]);
14766 if ((span < 1) || (span > NUM_SPANS)) {
14767 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14768 return CLI_SUCCESS;
14769 }
14770 if (!pris[span-1].pri.pri) {
14771 ast_cli(a->fd, "No PRI running on span %d\n", span);
14772 return CLI_SUCCESS;
14773 }
14774
14775 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14776
14777 return CLI_SUCCESS;
14778 }
14779 #endif
14780
14781 #if defined(HAVE_PRI)
14782 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14783 {
14784 int x;
14785 int span;
14786 int count=0;
14787 int debug;
14788
14789 switch (cmd) {
14790 case CLI_INIT:
14791 e->command = "pri show debug";
14792 e->usage =
14793 "Usage: pri show debug\n"
14794 " Show the debug state of pri spans\n";
14795 return NULL;
14796 case CLI_GENERATE:
14797 return NULL;
14798 }
14799
14800 for (span = 0; span < NUM_SPANS; span++) {
14801 if (pris[span].pri.pri) {
14802 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14803 if (pris[span].pri.dchans[x]) {
14804 debug = pri_get_debug(pris[span].pri.dchans[x]);
14805 ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
14806 count++;
14807 }
14808 }
14809 }
14810
14811 }
14812 ast_mutex_lock(&pridebugfdlock);
14813 if (pridebugfd >= 0)
14814 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14815 ast_mutex_unlock(&pridebugfdlock);
14816
14817 if (!count)
14818 ast_cli(a->fd, "No PRI running\n");
14819 return CLI_SUCCESS;
14820 }
14821 #endif
14822
14823 #if defined(HAVE_PRI)
14824 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14825 {
14826 switch (cmd) {
14827 case CLI_INIT:
14828 e->command = "pri show version";
14829 e->usage =
14830 "Usage: pri show version\n"
14831 "Show libpri version information\n";
14832 return NULL;
14833 case CLI_GENERATE:
14834 return NULL;
14835 }
14836
14837 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14838
14839 return CLI_SUCCESS;
14840 }
14841 #endif
14842
14843 #if defined(HAVE_PRI)
14844 static struct ast_cli_entry dahdi_pri_cli[] = {
14845 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14846 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14847 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14848 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14849 #endif
14850 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14851 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14852 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14853 AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
14854 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14855 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14856 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14857 };
14858 #endif
14859
14860 #ifdef HAVE_OPENR2
14861
14862 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14863 {
14864 switch (cmd) {
14865 case CLI_INIT:
14866 e->command = "mfcr2 show version";
14867 e->usage =
14868 "Usage: mfcr2 show version\n"
14869 " Shows the version of the OpenR2 library being used.\n";
14870 return NULL;
14871 case CLI_GENERATE:
14872 return NULL;
14873 }
14874 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14875 return CLI_SUCCESS;
14876 }
14877
14878 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14879 {
14880 #define FORMAT "%4s %40s\n"
14881 int i = 0;
14882 int numvariants = 0;
14883 const openr2_variant_entry_t *variants;
14884 switch (cmd) {
14885 case CLI_INIT:
14886 e->command = "mfcr2 show variants";
14887 e->usage =
14888 "Usage: mfcr2 show variants\n"
14889 " Shows the list of MFC/R2 variants supported.\n";
14890 return NULL;
14891 case CLI_GENERATE:
14892 return NULL;
14893 }
14894 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14895 ast_cli(a->fd, "Failed to get list of variants.\n");
14896 return CLI_FAILURE;
14897 }
14898 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14899 for (i = 0; i < numvariants; i++) {
14900 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14901 }
14902 return CLI_SUCCESS;
14903 #undef FORMAT
14904 }
14905
14906 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14907 {
14908 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14909 int filtertype = 0;
14910 int targetnum = 0;
14911 char channo[5];
14912 char anino[5];
14913 char dnisno[5];
14914 struct dahdi_pvt *p;
14915 openr2_context_t *r2context;
14916 openr2_variant_t r2variant;
14917 switch (cmd) {
14918 case CLI_INIT:
14919 e->command = "mfcr2 show channels [group|context]";
14920 e->usage =
14921 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14922 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14923 return NULL;
14924 case CLI_GENERATE:
14925 return NULL;
14926 }
14927 if (!((a->argc == 3) || (a->argc == 5))) {
14928 return CLI_SHOWUSAGE;
14929 }
14930 if (a->argc == 5) {
14931 if (!strcasecmp(a->argv[3], "group")) {
14932 targetnum = atoi(a->argv[4]);
14933 if ((targetnum < 0) || (targetnum > 63))
14934 return CLI_SHOWUSAGE;
14935 targetnum = 1 << targetnum;
14936 filtertype = 1;
14937 } else if (!strcasecmp(a->argv[3], "context")) {
14938 filtertype = 2;
14939 } else {
14940 return CLI_SHOWUSAGE;
14941 }
14942 }
14943 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14944 ast_mutex_lock(&iflock);
14945 for (p = iflist; p; p = p->next) {
14946 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14947 continue;
14948 }
14949 if (filtertype) {
14950 switch(filtertype) {
14951 case 1:
14952 if (p->group != targetnum) {
14953 continue;
14954 }
14955 break;
14956 case 2:
14957 if (strcasecmp(p->context, a->argv[4])) {
14958 continue;
14959 }
14960 break;
14961 default:
14962 ;
14963 }
14964 }
14965 r2context = openr2_chan_get_context(p->r2chan);
14966 r2variant = openr2_context_get_variant(r2context);
14967 snprintf(channo, sizeof(channo), "%d", p->channel);
14968 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14969 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14970 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14971 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14972 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14973 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14974 }
14975 ast_mutex_unlock(&iflock);
14976 return CLI_SUCCESS;
14977 #undef FORMAT
14978 }
14979
14980 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14981 {
14982 struct dahdi_pvt *p = NULL;
14983 int channo = 0;
14984 char *toklevel = NULL;
14985 char *saveptr = NULL;
14986 char *logval = NULL;
14987 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14988 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14989 switch (cmd) {
14990 case CLI_INIT:
14991 e->command = "mfcr2 set debug";
14992 e->usage =
14993 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14994 " Set a new logging level for the specified channel.\n"
14995 " If no channel is specified the logging level will be applied to all channels.\n";
14996 return NULL;
14997 case CLI_GENERATE:
14998 return NULL;
14999 }
15000 if (a->argc < 4) {
15001 return CLI_SHOWUSAGE;
15002 }
15003 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15004 logval = ast_strdupa(a->argv[3]);
15005 toklevel = strtok_r(logval, ",", &saveptr);
15006 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15007 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15008 return CLI_FAILURE;
15009 } else if (OR2_LOG_NOTHING == tmplevel) {
15010 loglevel = tmplevel;
15011 } else {
15012 loglevel |= tmplevel;
15013 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15014 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15015 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15016 continue;
15017 }
15018 loglevel |= tmplevel;
15019 }
15020 }
15021 ast_mutex_lock(&iflock);
15022 for (p = iflist; p; p = p->next) {
15023 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15024 continue;
15025 }
15026 if ((channo != -1) && (p->channel != channo )) {
15027 continue;
15028 }
15029 openr2_chan_set_log_level(p->r2chan, loglevel);
15030 if (channo != -1) {
15031 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15032 break;
15033 }
15034 }
15035 if ((channo != -1) && !p) {
15036 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15037 }
15038 if (channo == -1) {
15039 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15040 }
15041 ast_mutex_unlock(&iflock);
15042 return CLI_SUCCESS;
15043 }
15044
15045 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15046 {
15047 struct dahdi_pvt *p = NULL;
15048 int channo = 0;
15049 switch (cmd) {
15050 case CLI_INIT:
15051 e->command = "mfcr2 call files [on|off]";
15052 e->usage =
15053 "Usage: mfcr2 call files [on|off] <channel>\n"
15054 " Enable call files creation on the specified channel.\n"
15055 " If no channel is specified call files creation policy will be applied to all channels.\n";
15056 return NULL;
15057 case CLI_GENERATE:
15058 return NULL;
15059 }
15060 if (a->argc < 4) {
15061 return CLI_SHOWUSAGE;
15062 }
15063 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15064 ast_mutex_lock(&iflock);
15065 for (p = iflist; p; p = p->next) {
15066 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15067 continue;
15068 }
15069 if ((channo != -1) && (p->channel != channo )) {
15070 continue;
15071 }
15072 if (ast_true(a->argv[3])) {
15073 openr2_chan_enable_call_files(p->r2chan);
15074 } else {
15075 openr2_chan_disable_call_files(p->r2chan);
15076 }
15077 if (channo != -1) {
15078 if (ast_true(a->argv[3])) {
15079 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15080 } else {
15081 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15082 }
15083 break;
15084 }
15085 }
15086 if ((channo != -1) && !p) {
15087 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15088 }
15089 if (channo == -1) {
15090 if (ast_true(a->argv[3])) {
15091 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15092 } else {
15093 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15094 }
15095 }
15096 ast_mutex_unlock(&iflock);
15097 return CLI_SUCCESS;
15098 }
15099
15100 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15101 {
15102 struct dahdi_pvt *p = NULL;
15103 int channo = 0;
15104 switch (cmd) {
15105 case CLI_INIT:
15106 e->command = "mfcr2 set idle";
15107 e->usage =
15108 "Usage: mfcr2 set idle <channel>\n"
15109 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15110 " Force the given channel into IDLE state.\n"
15111 " If no channel is specified, all channels will be set to IDLE.\n";
15112 return NULL;
15113 case CLI_GENERATE:
15114 return NULL;
15115 }
15116 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15117 ast_mutex_lock(&iflock);
15118 for (p = iflist; p; p = p->next) {
15119 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15120 continue;
15121 }
15122 if ((channo != -1) && (p->channel != channo )) {
15123 continue;
15124 }
15125 openr2_chan_set_idle(p->r2chan);
15126 ast_mutex_lock(&p->lock);
15127 p->locallyblocked = 0;
15128 p->mfcr2call = 0;
15129 ast_mutex_unlock(&p->lock);
15130 if (channo != -1) {
15131 break;
15132 }
15133 }
15134 if ((channo != -1) && !p) {
15135 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15136 }
15137 ast_mutex_unlock(&iflock);
15138 return CLI_SUCCESS;
15139 }
15140
15141 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15142 {
15143 struct dahdi_pvt *p = NULL;
15144 int channo = 0;
15145 switch (cmd) {
15146 case CLI_INIT:
15147 e->command = "mfcr2 set blocked";
15148 e->usage =
15149 "Usage: mfcr2 set blocked <channel>\n"
15150 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15151 " Force the given channel into BLOCKED state.\n"
15152 " If no channel is specified, all channels will be set to BLOCKED.\n";
15153 return NULL;
15154 case CLI_GENERATE:
15155 return NULL;
15156 }
15157 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15158 ast_mutex_lock(&iflock);
15159 for (p = iflist; p; p = p->next) {
15160 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15161 continue;
15162 }
15163 if ((channo != -1) && (p->channel != channo )) {
15164 continue;
15165 }
15166 openr2_chan_set_blocked(p->r2chan);
15167 ast_mutex_lock(&p->lock);
15168 p->locallyblocked = 1;
15169 ast_mutex_unlock(&p->lock);
15170 if (channo != -1) {
15171 break;
15172 }
15173 }
15174 if ((channo != -1) && !p) {
15175 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15176 }
15177 ast_mutex_unlock(&iflock);
15178 return CLI_SUCCESS;
15179 }
15180
15181 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15182 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15183 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15184 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15185 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15186 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15187 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15188 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15189 };
15190
15191 #endif
15192
15193 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15194 {
15195 int channel;
15196 int ret;
15197 switch (cmd) {
15198 case CLI_INIT:
15199 e->command = "dahdi destroy channel";
15200 e->usage =
15201 "Usage: dahdi destroy channel <chan num>\n"
15202 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15203 return NULL;
15204 case CLI_GENERATE:
15205 return NULL;
15206 }
15207 if (a->argc != 4)
15208 return CLI_SHOWUSAGE;
15209
15210 channel = atoi(a->argv[3]);
15211 ret = dahdi_destroy_channel_bynum(channel);
15212 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15213 }
15214
15215 static void dahdi_softhangup_all(void)
15216 {
15217 struct dahdi_pvt *p;
15218 retry:
15219 ast_mutex_lock(&iflock);
15220 for (p = iflist; p; p = p->next) {
15221 ast_mutex_lock(&p->lock);
15222 if (p->owner && !p->restartpending) {
15223 if (ast_channel_trylock(p->owner)) {
15224 if (option_debug > 2)
15225 ast_verbose("Avoiding deadlock\n");
15226
15227 ast_mutex_unlock(&p->lock);
15228 ast_mutex_unlock(&iflock);
15229 goto retry;
15230 }
15231 if (option_debug > 2)
15232 ast_verbose("Softhanging up on %s\n", p->owner->name);
15233 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15234 p->restartpending = 1;
15235 num_restart_pending++;
15236 ast_channel_unlock(p->owner);
15237 }
15238 ast_mutex_unlock(&p->lock);
15239 }
15240 ast_mutex_unlock(&iflock);
15241 }
15242
15243 static int setup_dahdi(int reload);
15244 static int dahdi_restart(void)
15245 {
15246 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15247 int i, j;
15248 #endif
15249 int cancel_code;
15250 struct dahdi_pvt *p;
15251
15252 ast_mutex_lock(&restart_lock);
15253 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15254 dahdi_softhangup_all();
15255 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15256 #ifdef HAVE_OPENR2
15257 dahdi_r2_destroy_links();
15258 #endif
15259
15260 #if defined(HAVE_PRI)
15261 for (i = 0; i < NUM_SPANS; i++) {
15262 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15263 cancel_code = pthread_cancel(pris[i].pri.master);
15264 pthread_kill(pris[i].pri.master, SIGURG);
15265 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].pri.master, cancel_code);
15266 pthread_join(pris[i].pri.master, NULL);
15267 ast_debug(4, "Joined thread of span %d\n", i);
15268 }
15269 }
15270 #endif
15271
15272 #if defined(HAVE_SS7)
15273 for (i = 0; i < NUM_SPANS; i++) {
15274 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15275 cancel_code = pthread_cancel(linksets[i].ss7.master);
15276 pthread_kill(linksets[i].ss7.master, SIGURG);
15277 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].ss7.master, cancel_code);
15278 pthread_join(linksets[i].ss7.master, NULL);
15279 ast_debug(4, "Joined thread of span %d\n", i);
15280 }
15281 }
15282 #endif
15283
15284 ast_mutex_lock(&monlock);
15285 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15286 cancel_code = pthread_cancel(monitor_thread);
15287 pthread_kill(monitor_thread, SIGURG);
15288 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15289 pthread_join(monitor_thread, NULL);
15290 ast_debug(4, "Joined monitor thread\n");
15291 }
15292 monitor_thread = AST_PTHREADT_NULL;
15293
15294 ast_mutex_lock(&ss_thread_lock);
15295 while (ss_thread_count > 0) {
15296 int x = DAHDI_FLASH;
15297 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15298
15299 ast_mutex_lock(&iflock);
15300 for (p = iflist; p; p = p->next) {
15301 if (p->owner) {
15302
15303 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15304 }
15305 }
15306 ast_mutex_unlock(&iflock);
15307 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15308 }
15309
15310
15311 dahdi_softhangup_all();
15312 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15313 destroy_all_channels();
15314 memset(round_robin, 0, sizeof(round_robin));
15315 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15316
15317 ast_mutex_unlock(&monlock);
15318
15319 #ifdef HAVE_PRI
15320 for (i = 0; i < NUM_SPANS; i++) {
15321 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15322 dahdi_close_pri_fd(&(pris[i]), j);
15323 }
15324
15325 memset(pris, 0, sizeof(pris));
15326 for (i = 0; i < NUM_SPANS; i++) {
15327 sig_pri_init_pri(&pris[i].pri);
15328 }
15329 pri_set_error(dahdi_pri_error);
15330 pri_set_message(dahdi_pri_message);
15331 #endif
15332 #if defined(HAVE_SS7)
15333 for (i = 0; i < NUM_SPANS; i++) {
15334 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15335 dahdi_close_ss7_fd(&(linksets[i]), j);
15336 }
15337
15338 memset(linksets, 0, sizeof(linksets));
15339 for (i = 0; i < NUM_SPANS; i++) {
15340 sig_ss7_init_linkset(&linksets[i].ss7);
15341 }
15342 ss7_set_error(dahdi_ss7_error);
15343 ss7_set_message(dahdi_ss7_message);
15344 #endif
15345
15346 if (setup_dahdi(2) != 0) {
15347 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15348 ast_mutex_unlock(&ss_thread_lock);
15349 return 1;
15350 }
15351 ast_mutex_unlock(&ss_thread_lock);
15352 ast_mutex_unlock(&restart_lock);
15353 return 0;
15354 }
15355
15356 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15357 {
15358 switch (cmd) {
15359 case CLI_INIT:
15360 e->command = "dahdi restart";
15361 e->usage =
15362 "Usage: dahdi restart\n"
15363 " Restarts the DAHDI channels: destroys them all and then\n"
15364 " re-reads them from chan_dahdi.conf.\n"
15365 " Note that this will STOP any running CALL on DAHDI channels.\n"
15366 "";
15367 return NULL;
15368 case CLI_GENERATE:
15369 return NULL;
15370 }
15371 if (a->argc != 2)
15372 return CLI_SHOWUSAGE;
15373
15374 if (dahdi_restart() != 0)
15375 return CLI_FAILURE;
15376 return CLI_SUCCESS;
15377 }
15378
15379 static int action_dahdirestart(struct mansession *s, const struct message *m)
15380 {
15381 if (dahdi_restart() != 0) {
15382 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15383 return 1;
15384 }
15385 astman_send_ack(s, m, "DAHDIRestart: Success");
15386 return 0;
15387 }
15388
15389 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15390 {
15391 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15392 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15393 ast_group_t targetnum = 0;
15394 int filtertype = 0;
15395 struct dahdi_pvt *tmp = NULL;
15396 char tmps[20] = "";
15397 char statestr[20] = "";
15398 char blockstr[20] = "";
15399
15400 switch (cmd) {
15401 case CLI_INIT:
15402 e->command = "dahdi show channels [group|context]";
15403 e->usage =
15404 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15405 " Shows a list of available channels with optional filtering\n"
15406 " <group> must be a number between 0 and 63\n";
15407 return NULL;
15408 case CLI_GENERATE:
15409 return NULL;
15410 }
15411
15412
15413
15414 if (!((a->argc == 3) || (a->argc == 5)))
15415 return CLI_SHOWUSAGE;
15416
15417 if (a->argc == 5) {
15418 if (!strcasecmp(a->argv[3], "group")) {
15419 targetnum = atoi(a->argv[4]);
15420 if (63 < targetnum) {
15421 return CLI_SHOWUSAGE;
15422 }
15423 targetnum = ((ast_group_t) 1) << targetnum;
15424 filtertype = 1;
15425 } else if (!strcasecmp(a->argv[3], "context")) {
15426 filtertype = 2;
15427 }
15428 }
15429
15430 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15431 ast_mutex_lock(&iflock);
15432 for (tmp = iflist; tmp; tmp = tmp->next) {
15433 if (filtertype) {
15434 switch(filtertype) {
15435 case 1:
15436 if (!(tmp->group & targetnum)) {
15437 continue;
15438 }
15439 break;
15440 case 2:
15441 if (strcasecmp(tmp->context, a->argv[4])) {
15442 continue;
15443 }
15444 break;
15445 default:
15446 break;
15447 }
15448 }
15449 if (tmp->channel > 0) {
15450 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15451 } else
15452 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15453
15454 if (tmp->locallyblocked)
15455 blockstr[0] = 'L';
15456 else
15457 blockstr[0] = ' ';
15458
15459 if (tmp->remotelyblocked)
15460 blockstr[1] = 'R';
15461 else
15462 blockstr[1] = ' ';
15463
15464 blockstr[2] = '\0';
15465
15466 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15467
15468 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15469 }
15470 ast_mutex_unlock(&iflock);
15471 return CLI_SUCCESS;
15472 #undef FORMAT
15473 #undef FORMAT2
15474 }
15475
15476 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15477 {
15478 int channel;
15479 struct dahdi_pvt *tmp = NULL;
15480 struct dahdi_confinfo ci;
15481 struct dahdi_params ps;
15482 int x;
15483
15484 switch (cmd) {
15485 case CLI_INIT:
15486 e->command = "dahdi show channel";
15487 e->usage =
15488 "Usage: dahdi show channel <chan num>\n"
15489 " Detailed information about a given channel\n";
15490 return NULL;
15491 case CLI_GENERATE:
15492 return NULL;
15493 }
15494
15495 if (a->argc != 4)
15496 return CLI_SHOWUSAGE;
15497
15498 channel = atoi(a->argv[3]);
15499
15500 ast_mutex_lock(&iflock);
15501 for (tmp = iflist; tmp; tmp = tmp->next) {
15502 if (tmp->channel == channel) {
15503 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15504 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15505 ast_cli(a->fd, "Span: %d\n", tmp->span);
15506 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15507 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15508 ast_cli(a->fd, "Context: %s\n", tmp->context);
15509 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15510 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15511 #if defined(HAVE_PRI)
15512 #if defined(HAVE_PRI_SUBADDR)
15513 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15514 #endif
15515 #endif
15516 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15517 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15518 if (tmp->vars) {
15519 struct ast_variable *v;
15520 ast_cli(a->fd, "Variables:\n");
15521 for (v = tmp->vars ; v ; v = v->next)
15522 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15523 }
15524 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15525 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15526 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15527 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15528 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15529 ast_cli(a->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)" : "");
15530 ast_cli(a->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)" : "");
15531 ast_cli(a->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)" : "");
15532 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15533 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15534 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15535 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15536 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15537 if (tmp->busydetect) {
15538 #if defined(BUSYDETECT_TONEONLY)
15539 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15540 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15541 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15542 #endif
15543 #ifdef BUSYDETECT_DEBUG
15544 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15545 #endif
15546 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15547 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15548 }
15549 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15550 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15551 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15552 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15553 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15554 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15555 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15556 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15557 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15558 ast_cli(a->fd, "Echo Cancellation:\n");
15559
15560 if (tmp->echocancel.head.tap_length) {
15561 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
15562 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15563 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15564 }
15565 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15566 } else {
15567 ast_cli(a->fd, "\tnone\n");
15568 }
15569 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15570 if (tmp->master)
15571 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15572 for (x = 0; x < MAX_SLAVES; x++) {
15573 if (tmp->slaves[x])
15574 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15575 }
15576 #ifdef HAVE_OPENR2
15577 if (tmp->mfcr2) {
15578 char calldir[OR2_MAX_PATH];
15579 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15580 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15581 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15582 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15583 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15584 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15585 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15586 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15587 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15588 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15589 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15590 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15591 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15592 #endif
15593 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15594 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15595 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15596 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15597 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15598 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15599 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15600 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15601 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15602 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15603 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15604 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15605 }
15606 #endif
15607 #if defined(HAVE_SS7)
15608 if (tmp->ss7) {
15609 struct sig_ss7_chan *chan = tmp->sig_pvt;
15610
15611 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15612 }
15613 #endif
15614 #ifdef HAVE_PRI
15615 if (tmp->pri) {
15616 struct sig_pri_chan *chan = tmp->sig_pvt;
15617
15618 ast_cli(a->fd, "PRI Flags: ");
15619 if (chan->resetting != SIG_PRI_RESET_IDLE) {
15620 ast_cli(a->fd, "Resetting=%u ", chan->resetting);
15621 }
15622 if (chan->call)
15623 ast_cli(a->fd, "Call ");
15624 if (chan->allocated) {
15625 ast_cli(a->fd, "Allocated ");
15626 }
15627 ast_cli(a->fd, "\n");
15628 if (tmp->logicalspan)
15629 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15630 else
15631 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15632 }
15633 #endif
15634 memset(&ci, 0, sizeof(ci));
15635 ps.channo = tmp->channel;
15636 if (tmp->subs[SUB_REAL].dfd > -1) {
15637 memset(&ci, 0, sizeof(ci));
15638 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15639 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
15640 }
15641 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15642 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15643 }
15644 memset(&ps, 0, sizeof(ps));
15645 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15646 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15647 } else {
15648 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15649 }
15650 }
15651 if (ISTRUNK(tmp)) {
15652 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
15653 if (!ast_strlen_zero(progzone))
15654 ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15655 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
15656 if(tmp->busydetect) {
15657 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15658 if(tmp->busytonelength > 0) {
15659 ast_cli(a->fd, "Busy Pattern:\n");
15660 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15661 if (tmp->busyquietlength > 0)
15662 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15663 else
15664 ast_cli(a->fd, " -- Detect Tone Only\n");
15665 if(tmp->busyfuzziness > 0)
15666 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15667 }
15668 }
15669 }
15670 ast_mutex_unlock(&iflock);
15671 return CLI_SUCCESS;
15672 }
15673 }
15674 ast_mutex_unlock(&iflock);
15675
15676 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15677 return CLI_FAILURE;
15678 }
15679
15680 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15681 {
15682 int i, j;
15683 switch (cmd) {
15684 case CLI_INIT:
15685 e->command = "dahdi show cadences";
15686 e->usage =
15687 "Usage: dahdi show cadences\n"
15688 " Shows all cadences currently defined\n";
15689 return NULL;
15690 case CLI_GENERATE:
15691 return NULL;
15692 }
15693 for (i = 0; i < num_cadence; i++) {
15694 char output[1024];
15695 char tmp[16], tmp2[64];
15696 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15697 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15698
15699 for (j = 0; j < 16; j++) {
15700 if (cadences[i].ringcadence[j] == 0)
15701 break;
15702 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15703 if (cidrings[i] * 2 - 1 == j)
15704 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15705 else
15706 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15707 if (j != 0)
15708 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15709 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15710 }
15711 ast_cli(a->fd,"%s\n",output);
15712 }
15713 return CLI_SUCCESS;
15714 }
15715
15716
15717 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15718 {
15719 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15720 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15721 int span;
15722 int res;
15723 char alarmstr[50];
15724
15725 int ctl;
15726 struct dahdi_spaninfo s;
15727
15728 switch (cmd) {
15729 case CLI_INIT:
15730 e->command = "dahdi show status";
15731 e->usage =
15732 "Usage: dahdi show status\n"
15733 " Shows a list of DAHDI cards with status\n";
15734 return NULL;
15735 case CLI_GENERATE:
15736 return NULL;
15737 }
15738 ctl = open("/dev/dahdi/ctl", O_RDWR);
15739 if (ctl < 0) {
15740 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15741 return CLI_FAILURE;
15742 }
15743 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15744
15745 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15746 s.spanno = span;
15747 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15748 if (res) {
15749 continue;
15750 }
15751 alarmstr[0] = '\0';
15752 if (s.alarms > 0) {
15753 if (s.alarms & DAHDI_ALARM_BLUE)
15754 strcat(alarmstr, "BLU/");
15755 if (s.alarms & DAHDI_ALARM_YELLOW)
15756 strcat(alarmstr, "YEL/");
15757 if (s.alarms & DAHDI_ALARM_RED)
15758 strcat(alarmstr, "RED/");
15759 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15760 strcat(alarmstr, "LB/");
15761 if (s.alarms & DAHDI_ALARM_RECOVER)
15762 strcat(alarmstr, "REC/");
15763 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15764 strcat(alarmstr, "NOP/");
15765 if (!strlen(alarmstr))
15766 strcat(alarmstr, "UUU/");
15767 if (strlen(alarmstr)) {
15768
15769 alarmstr[strlen(alarmstr) - 1] = '\0';
15770 }
15771 } else {
15772 if (s.numchans)
15773 strcpy(alarmstr, "OK");
15774 else
15775 strcpy(alarmstr, "UNCONFIGURED");
15776 }
15777
15778 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15779 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15780 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15781 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15782 "CAS",
15783 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15784 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15785 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15786 "Unk",
15787 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15788 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15789 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15790 lbostr[s.lbo]
15791 );
15792 }
15793 close(ctl);
15794
15795 return CLI_SUCCESS;
15796 #undef FORMAT
15797 #undef FORMAT2
15798 }
15799
15800 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15801 {
15802 int pseudo_fd = -1;
15803 struct dahdi_versioninfo vi;
15804
15805 switch (cmd) {
15806 case CLI_INIT:
15807 e->command = "dahdi show version";
15808 e->usage =
15809 "Usage: dahdi show version\n"
15810 " Shows the DAHDI version in use\n";
15811 return NULL;
15812 case CLI_GENERATE:
15813 return NULL;
15814 }
15815 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15816 ast_cli(a->fd, "Failed to open control file to get version.\n");
15817 return CLI_SUCCESS;
15818 }
15819
15820 strcpy(vi.version, "Unknown");
15821 strcpy(vi.echo_canceller, "Unknown");
15822
15823 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15824 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15825 else
15826 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15827
15828 close(pseudo_fd);
15829
15830 return CLI_SUCCESS;
15831 }
15832
15833 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15834 {
15835 int channel;
15836 int gain;
15837 int tx;
15838 struct dahdi_hwgain hwgain;
15839 struct dahdi_pvt *tmp = NULL;
15840
15841 switch (cmd) {
15842 case CLI_INIT:
15843 e->command = "dahdi set hwgain {rx|tx}";
15844 e->usage =
15845 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15846 " Sets the hardware gain on a given channel. Changes take effect\n"
15847 " immediately whether the channel is in use or not.\n"
15848 "\n"
15849 " <rx|tx> which direction do you want to change (relative to our module)\n"
15850 " <chan num> is the channel number relative to the device\n"
15851 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15852 "\n"
15853 " Please note:\n"
15854 " * This is currently the only way to set hwgain by the channel driver.\n"
15855 " * hwgain is only supportable by hardware with analog ports because\n"
15856 " hwgain works on the analog side of an analog-digital conversion.\n";
15857 return NULL;
15858 case CLI_GENERATE:
15859 return NULL;
15860 }
15861
15862 if (a->argc != 6)
15863 return CLI_SHOWUSAGE;
15864
15865 if (!strcasecmp("rx", a->argv[3]))
15866 tx = 0;
15867 else if (!strcasecmp("tx", a->argv[3]))
15868 tx = 1;
15869 else
15870 return CLI_SHOWUSAGE;
15871
15872 channel = atoi(a->argv[4]);
15873 gain = atof(a->argv[5])*10.0;
15874
15875 ast_mutex_lock(&iflock);
15876
15877 for (tmp = iflist; tmp; tmp = tmp->next) {
15878
15879 if (tmp->channel != channel)
15880 continue;
15881
15882 if (tmp->subs[SUB_REAL].dfd == -1)
15883 break;
15884
15885 hwgain.newgain = gain;
15886 hwgain.tx = tx;
15887 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15888 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15889 ast_mutex_unlock(&iflock);
15890 return CLI_FAILURE;
15891 }
15892 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15893 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15894 break;
15895 }
15896
15897 ast_mutex_unlock(&iflock);
15898
15899 if (tmp)
15900 return CLI_SUCCESS;
15901
15902 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15903 return CLI_FAILURE;
15904
15905 }
15906
15907 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15908 {
15909 int channel;
15910 float gain;
15911 int tx;
15912 int res;
15913 struct dahdi_pvt *tmp = NULL;
15914
15915 switch (cmd) {
15916 case CLI_INIT:
15917 e->command = "dahdi set swgain {rx|tx}";
15918 e->usage =
15919 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15920 " Sets the software gain on a given channel and overrides the\n"
15921 " value provided at module loadtime. Changes take effect\n"
15922 " immediately whether the channel is in use or not.\n"
15923 "\n"
15924 " <rx|tx> which direction do you want to change (relative to our module)\n"
15925 " <chan num> is the channel number relative to the device\n"
15926 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15927 return NULL;
15928 case CLI_GENERATE:
15929 return NULL;
15930 }
15931
15932 if (a->argc != 6)
15933 return CLI_SHOWUSAGE;
15934
15935 if (!strcasecmp("rx", a->argv[3]))
15936 tx = 0;
15937 else if (!strcasecmp("tx", a->argv[3]))
15938 tx = 1;
15939 else
15940 return CLI_SHOWUSAGE;
15941
15942 channel = atoi(a->argv[4]);
15943 gain = atof(a->argv[5]);
15944
15945 ast_mutex_lock(&iflock);
15946 for (tmp = iflist; tmp; tmp = tmp->next) {
15947
15948 if (tmp->channel != channel)
15949 continue;
15950
15951 if (tmp->subs[SUB_REAL].dfd == -1)
15952 break;
15953
15954 if (tx)
15955 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15956 else
15957 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15958
15959 if (res) {
15960 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15961 ast_mutex_unlock(&iflock);
15962 return CLI_FAILURE;
15963 }
15964
15965 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15966 tx ? "tx" : "rx", gain, channel);
15967
15968 if (tx) {
15969 tmp->txgain = gain;
15970 } else {
15971 tmp->rxgain = gain;
15972 }
15973 break;
15974 }
15975 ast_mutex_unlock(&iflock);
15976
15977 if (tmp)
15978 return CLI_SUCCESS;
15979
15980 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15981 return CLI_FAILURE;
15982
15983 }
15984
15985 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15986 {
15987 int channel;
15988 int on;
15989 struct dahdi_pvt *dahdi_chan = NULL;
15990
15991 switch (cmd) {
15992 case CLI_INIT:
15993 e->command = "dahdi set dnd";
15994 e->usage =
15995 "Usage: dahdi set dnd <chan#> <on|off>\n"
15996 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15997 " Changes take effect immediately.\n"
15998 " <chan num> is the channel number\n"
15999 " <on|off> Enable or disable DND mode?\n"
16000 ;
16001 return NULL;
16002 case CLI_GENERATE:
16003 return NULL;
16004 }
16005
16006 if (a->argc != 5)
16007 return CLI_SHOWUSAGE;
16008
16009 if ((channel = atoi(a->argv[3])) <= 0) {
16010 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16011 return CLI_SHOWUSAGE;
16012 }
16013
16014 if (ast_true(a->argv[4]))
16015 on = 1;
16016 else if (ast_false(a->argv[4]))
16017 on = 0;
16018 else {
16019 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16020 return CLI_SHOWUSAGE;
16021 }
16022
16023 ast_mutex_lock(&iflock);
16024 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16025 if (dahdi_chan->channel != channel)
16026 continue;
16027
16028
16029 dahdi_dnd(dahdi_chan, on);
16030 break;
16031 }
16032 ast_mutex_unlock(&iflock);
16033
16034 if (!dahdi_chan) {
16035 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16036 return CLI_FAILURE;
16037 }
16038
16039 return CLI_SUCCESS;
16040 }
16041
16042 static struct ast_cli_entry dahdi_cli[] = {
16043 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16044 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16045 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16046 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16047 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16048 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16049 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16050 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16051 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16052 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16053 };
16054
16055 #define TRANSFER 0
16056 #define HANGUP 1
16057
16058 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16059 {
16060 if (p) {
16061 switch (mode) {
16062 case TRANSFER:
16063 p->fake_event = DAHDI_EVENT_WINKFLASH;
16064 break;
16065 case HANGUP:
16066 p->fake_event = DAHDI_EVENT_ONHOOK;
16067 break;
16068 default:
16069 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16070 }
16071 }
16072 return 0;
16073 }
16074 static struct dahdi_pvt *find_channel(int channel)
16075 {
16076 struct dahdi_pvt *p;
16077
16078 ast_mutex_lock(&iflock);
16079 for (p = iflist; p; p = p->next) {
16080 if (p->channel == channel) {
16081 break;
16082 }
16083 }
16084 ast_mutex_unlock(&iflock);
16085 return p;
16086 }
16087
16088
16089
16090
16091
16092
16093
16094
16095
16096
16097 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16098 {
16099 int chan_num;
16100
16101 if (sscanf(channel, "%30d", &chan_num) != 1) {
16102
16103 return NULL;
16104 }
16105
16106 return find_channel(chan_num);
16107 }
16108
16109 static int action_dahdidndon(struct mansession *s, const struct message *m)
16110 {
16111 struct dahdi_pvt *p;
16112 const char *channel = astman_get_header(m, "DAHDIChannel");
16113
16114 if (ast_strlen_zero(channel)) {
16115 astman_send_error(s, m, "No channel specified");
16116 return 0;
16117 }
16118 p = find_channel_from_str(channel);
16119 if (!p) {
16120 astman_send_error(s, m, "No such channel");
16121 return 0;
16122 }
16123 dahdi_dnd(p, 1);
16124 astman_send_ack(s, m, "DND Enabled");
16125 return 0;
16126 }
16127
16128 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16129 {
16130 struct dahdi_pvt *p;
16131 const char *channel = astman_get_header(m, "DAHDIChannel");
16132
16133 if (ast_strlen_zero(channel)) {
16134 astman_send_error(s, m, "No channel specified");
16135 return 0;
16136 }
16137 p = find_channel_from_str(channel);
16138 if (!p) {
16139 astman_send_error(s, m, "No such channel");
16140 return 0;
16141 }
16142 dahdi_dnd(p, 0);
16143 astman_send_ack(s, m, "DND Disabled");
16144 return 0;
16145 }
16146
16147 static int action_transfer(struct mansession *s, const struct message *m)
16148 {
16149 struct dahdi_pvt *p;
16150 const char *channel = astman_get_header(m, "DAHDIChannel");
16151
16152 if (ast_strlen_zero(channel)) {
16153 astman_send_error(s, m, "No channel specified");
16154 return 0;
16155 }
16156 p = find_channel_from_str(channel);
16157 if (!p) {
16158 astman_send_error(s, m, "No such channel");
16159 return 0;
16160 }
16161 if (!analog_lib_handles(p->sig, 0, 0)) {
16162 astman_send_error(s, m, "Channel signaling is not analog");
16163 return 0;
16164 }
16165 dahdi_fake_event(p,TRANSFER);
16166 astman_send_ack(s, m, "DAHDITransfer");
16167 return 0;
16168 }
16169
16170 static int action_transferhangup(struct mansession *s, const struct message *m)
16171 {
16172 struct dahdi_pvt *p;
16173 const char *channel = astman_get_header(m, "DAHDIChannel");
16174
16175 if (ast_strlen_zero(channel)) {
16176 astman_send_error(s, m, "No channel specified");
16177 return 0;
16178 }
16179 p = find_channel_from_str(channel);
16180 if (!p) {
16181 astman_send_error(s, m, "No such channel");
16182 return 0;
16183 }
16184 if (!analog_lib_handles(p->sig, 0, 0)) {
16185 astman_send_error(s, m, "Channel signaling is not analog");
16186 return 0;
16187 }
16188 dahdi_fake_event(p,HANGUP);
16189 astman_send_ack(s, m, "DAHDIHangup");
16190 return 0;
16191 }
16192
16193 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16194 {
16195 struct dahdi_pvt *p;
16196 const char *channel = astman_get_header(m, "DAHDIChannel");
16197 const char *number = astman_get_header(m, "Number");
16198 int i;
16199
16200 if (ast_strlen_zero(channel)) {
16201 astman_send_error(s, m, "No channel specified");
16202 return 0;
16203 }
16204 if (ast_strlen_zero(number)) {
16205 astman_send_error(s, m, "No number specified");
16206 return 0;
16207 }
16208 p = find_channel_from_str(channel);
16209 if (!p) {
16210 astman_send_error(s, m, "No such channel");
16211 return 0;
16212 }
16213 if (!p->owner) {
16214 astman_send_error(s, m, "Channel does not have it's owner");
16215 return 0;
16216 }
16217 for (i = 0; i < strlen(number); i++) {
16218 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16219 dahdi_queue_frame(p, &f);
16220 }
16221 astman_send_ack(s, m, "DAHDIDialOffhook");
16222 return 0;
16223 }
16224
16225 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16226 {
16227 struct dahdi_pvt *tmp = NULL;
16228 const char *id = astman_get_header(m, "ActionID");
16229 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16230 char idText[256] = "";
16231 int channels = 0;
16232 int dahdichanquery;
16233
16234 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16235
16236 dahdichanquery = -1;
16237 }
16238
16239 astman_send_ack(s, m, "DAHDI channel status will follow");
16240 if (!ast_strlen_zero(id))
16241 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16242
16243 ast_mutex_lock(&iflock);
16244
16245 for (tmp = iflist; tmp; tmp = tmp->next) {
16246 if (tmp->channel > 0) {
16247 int alm;
16248
16249
16250 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16251 continue;
16252
16253 alm = get_alarms(tmp);
16254 channels++;
16255 if (tmp->owner) {
16256
16257 astman_append(s,
16258 "Event: DAHDIShowChannels\r\n"
16259 "DAHDIChannel: %d\r\n"
16260 "Channel: %s\r\n"
16261 "Uniqueid: %s\r\n"
16262 "AccountCode: %s\r\n"
16263 "Signalling: %s\r\n"
16264 "SignallingCode: %d\r\n"
16265 "Context: %s\r\n"
16266 "DND: %s\r\n"
16267 "Alarm: %s\r\n"
16268 "%s"
16269 "\r\n",
16270 tmp->channel,
16271 tmp->owner->name,
16272 tmp->owner->uniqueid,
16273 tmp->owner->accountcode,
16274 sig2str(tmp->sig),
16275 tmp->sig,
16276 tmp->context,
16277 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16278 alarm2str(alm), idText);
16279 } else {
16280 astman_append(s,
16281 "Event: DAHDIShowChannels\r\n"
16282 "DAHDIChannel: %d\r\n"
16283 "Signalling: %s\r\n"
16284 "SignallingCode: %d\r\n"
16285 "Context: %s\r\n"
16286 "DND: %s\r\n"
16287 "Alarm: %s\r\n"
16288 "%s"
16289 "\r\n",
16290 tmp->channel, sig2str(tmp->sig), tmp->sig,
16291 tmp->context,
16292 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16293 alarm2str(alm), idText);
16294 }
16295 }
16296 }
16297
16298 ast_mutex_unlock(&iflock);
16299
16300 astman_append(s,
16301 "Event: DAHDIShowChannelsComplete\r\n"
16302 "%s"
16303 "Items: %d\r\n"
16304 "\r\n",
16305 idText,
16306 channels);
16307 return 0;
16308 }
16309
16310 #if defined(HAVE_SS7)
16311 static int linkset_addsigchan(int sigchan)
16312 {
16313 struct dahdi_ss7 *link;
16314 int res;
16315 int curfd;
16316 struct dahdi_params params;
16317 struct dahdi_bufferinfo bi;
16318 struct dahdi_spaninfo si;
16319
16320 if (sigchan < 0) {
16321 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16322 return -1;
16323 }
16324 if (cur_ss7type < 0) {
16325 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16326 return -1;
16327 }
16328 if (cur_pointcode < 0) {
16329 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16330 return -1;
16331 }
16332 if (cur_adjpointcode < 0) {
16333 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16334 return -1;
16335 }
16336 if (cur_defaultdpc < 0) {
16337 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16338 return -1;
16339 }
16340 if (cur_networkindicator < 0) {
16341 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16342 return -1;
16343 }
16344 link = ss7_resolve_linkset(cur_linkset);
16345 if (!link) {
16346 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16347 return -1;
16348 }
16349 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16350 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16351 return -1;
16352 }
16353
16354 curfd = link->ss7.numsigchans;
16355
16356
16357 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16358 if (link->ss7.fds[curfd] < 0) {
16359 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16360 strerror(errno));
16361 return -1;
16362 }
16363 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16364 dahdi_close_ss7_fd(link, curfd);
16365 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16366 strerror(errno));
16367 return -1;
16368 }
16369
16370
16371 memset(¶ms, 0, sizeof(params));
16372 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16373 if (res) {
16374 dahdi_close_ss7_fd(link, curfd);
16375 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16376 strerror(errno));
16377 return -1;
16378 }
16379 if (params.sigtype != DAHDI_SIG_HDLCFCS
16380 && params.sigtype != DAHDI_SIG_HARDHDLC
16381 && params.sigtype != DAHDI_SIG_MTP2) {
16382 dahdi_close_ss7_fd(link, curfd);
16383 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16384 return -1;
16385 }
16386
16387
16388 memset(&bi, 0, sizeof(bi));
16389 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16390 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16391 bi.numbufs = 32;
16392 bi.bufsize = 512;
16393 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16394 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16395 sigchan, strerror(errno));
16396 dahdi_close_ss7_fd(link, curfd);
16397 return -1;
16398 }
16399
16400
16401 memset(&si, 0, sizeof(si));
16402 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16403 if (res) {
16404 dahdi_close_ss7_fd(link, curfd);
16405 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16406 strerror(errno));
16407 }
16408
16409 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16410 (params.sigtype == DAHDI_SIG_MTP2)
16411 ? SS7_TRANSPORT_DAHDIMTP2
16412 : SS7_TRANSPORT_DAHDIDCHAN,
16413 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16414 if (res) {
16415 dahdi_close_ss7_fd(link, curfd);
16416 return -1;
16417 }
16418
16419 ++link->ss7.numsigchans;
16420
16421 return 0;
16422 }
16423 #endif
16424
16425 #if defined(HAVE_SS7)
16426 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16427 {
16428 int span;
16429 switch (cmd) {
16430 case CLI_INIT:
16431 e->command = "ss7 set debug {on|off} linkset";
16432 e->usage =
16433 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16434 " Enables debugging on a given SS7 linkset\n";
16435 return NULL;
16436 case CLI_GENERATE:
16437 return NULL;
16438 }
16439 if (a->argc < 6)
16440 return CLI_SHOWUSAGE;
16441 span = atoi(a->argv[5]);
16442 if ((span < 1) || (span > NUM_SPANS)) {
16443 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16444 return CLI_SUCCESS;
16445 }
16446 if (!linksets[span-1].ss7.ss7) {
16447 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16448 } else {
16449 if (!strcasecmp(a->argv[3], "on")) {
16450 linksets[span - 1].ss7.debug = 1;
16451 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16452 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16453 } else {
16454 linksets[span - 1].ss7.debug = 0;
16455 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16456 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16457 }
16458 }
16459
16460 return CLI_SUCCESS;
16461 }
16462 #endif
16463
16464 #if defined(HAVE_SS7)
16465 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16466 {
16467 int linkset, cic;
16468 int blocked = -1, i;
16469 switch (cmd) {
16470 case CLI_INIT:
16471 e->command = "ss7 block cic";
16472 e->usage =
16473 "Usage: ss7 block cic <linkset> <CIC>\n"
16474 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16475 return NULL;
16476 case CLI_GENERATE:
16477 return NULL;
16478 }
16479 if (a->argc == 5)
16480 linkset = atoi(a->argv[3]);
16481 else
16482 return CLI_SHOWUSAGE;
16483
16484 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16485 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16486 return CLI_SUCCESS;
16487 }
16488
16489 if (!linksets[linkset-1].ss7.ss7) {
16490 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16491 return CLI_SUCCESS;
16492 }
16493
16494 cic = atoi(a->argv[4]);
16495
16496 if (cic < 1) {
16497 ast_cli(a->fd, "Invalid CIC specified!\n");
16498 return CLI_SUCCESS;
16499 }
16500
16501 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16502 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16503 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16504 if (!blocked) {
16505 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16506 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16507 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16508 }
16509 }
16510 }
16511
16512 if (blocked < 0) {
16513 ast_cli(a->fd, "Invalid CIC specified!\n");
16514 return CLI_SUCCESS;
16515 }
16516
16517 if (!blocked)
16518 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16519 else
16520 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16521
16522
16523 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16524
16525 return CLI_SUCCESS;
16526 }
16527 #endif
16528
16529 #if defined(HAVE_SS7)
16530 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16531 {
16532 int linkset;
16533 int i;
16534 switch (cmd) {
16535 case CLI_INIT:
16536 e->command = "ss7 block linkset";
16537 e->usage =
16538 "Usage: ss7 block linkset <linkset number>\n"
16539 " Sends a remote blocking request for all CICs on the given linkset\n";
16540 return NULL;
16541 case CLI_GENERATE:
16542 return NULL;
16543 }
16544 if (a->argc == 4)
16545 linkset = atoi(a->argv[3]);
16546 else
16547 return CLI_SHOWUSAGE;
16548
16549 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16550 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16551 return CLI_SUCCESS;
16552 }
16553
16554 if (!linksets[linkset-1].ss7.ss7) {
16555 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16556 return CLI_SUCCESS;
16557 }
16558
16559 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16560 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16561 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16562 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16563 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16564 }
16565
16566
16567 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16568
16569 return CLI_SUCCESS;
16570 }
16571 #endif
16572
16573 #if defined(HAVE_SS7)
16574 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16575 {
16576 int linkset, cic;
16577 int i, blocked = -1;
16578 switch (cmd) {
16579 case CLI_INIT:
16580 e->command = "ss7 unblock cic";
16581 e->usage =
16582 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16583 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16584 return NULL;
16585 case CLI_GENERATE:
16586 return NULL;
16587 }
16588
16589 if (a->argc == 5)
16590 linkset = atoi(a->argv[3]);
16591 else
16592 return CLI_SHOWUSAGE;
16593
16594 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16595 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16596 return CLI_SUCCESS;
16597 }
16598
16599 if (!linksets[linkset-1].ss7.ss7) {
16600 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16601 return CLI_SUCCESS;
16602 }
16603
16604 cic = atoi(a->argv[4]);
16605
16606 if (cic < 1) {
16607 ast_cli(a->fd, "Invalid CIC specified!\n");
16608 return CLI_SUCCESS;
16609 }
16610
16611 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16612 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16613 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16614 if (blocked) {
16615 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16616 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16617 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16618 }
16619 }
16620 }
16621
16622 if (blocked > 0)
16623 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16624
16625
16626 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16627
16628 return CLI_SUCCESS;
16629 }
16630 #endif
16631
16632 #if defined(HAVE_SS7)
16633 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16634 {
16635 int linkset;
16636 int i;
16637 switch (cmd) {
16638 case CLI_INIT:
16639 e->command = "ss7 unblock linkset";
16640 e->usage =
16641 "Usage: ss7 unblock linkset <linkset number>\n"
16642 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16643 return NULL;
16644 case CLI_GENERATE:
16645 return NULL;
16646 }
16647
16648 if (a->argc == 4)
16649 linkset = atoi(a->argv[3]);
16650 else
16651 return CLI_SHOWUSAGE;
16652
16653 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16654 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16655 return CLI_SUCCESS;
16656 }
16657
16658 if (!linksets[linkset-1].ss7.ss7) {
16659 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16660 return CLI_SUCCESS;
16661 }
16662
16663 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16664 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16665 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16666 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16667 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16668 }
16669
16670
16671 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16672
16673 return CLI_SUCCESS;
16674 }
16675 #endif
16676
16677 #if defined(HAVE_SS7)
16678 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16679 {
16680 int linkset;
16681 struct sig_ss7_linkset *ss7;
16682 switch (cmd) {
16683 case CLI_INIT:
16684 e->command = "ss7 show linkset";
16685 e->usage =
16686 "Usage: ss7 show linkset <span>\n"
16687 " Shows the status of an SS7 linkset.\n";
16688 return NULL;
16689 case CLI_GENERATE:
16690 return NULL;
16691 }
16692
16693 if (a->argc < 4)
16694 return CLI_SHOWUSAGE;
16695 linkset = atoi(a->argv[3]);
16696 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16697 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16698 return CLI_SUCCESS;
16699 }
16700 ss7 = &linksets[linkset - 1].ss7;
16701 if (!ss7->ss7) {
16702 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16703 return CLI_SUCCESS;
16704 }
16705
16706 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16707
16708 return CLI_SUCCESS;
16709 }
16710 #endif
16711
16712 #if defined(HAVE_SS7)
16713 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16714 {
16715 int linkset;
16716
16717 switch (cmd) {
16718 case CLI_INIT:
16719 e->command = "ss7 show channels";
16720 e->usage =
16721 "Usage: ss7 show channels\n"
16722 " Displays SS7 channel information at a glance.\n";
16723 return NULL;
16724 case CLI_GENERATE:
16725 return NULL;
16726 }
16727
16728 if (a->argc != 3)
16729 return CLI_SHOWUSAGE;
16730
16731 sig_ss7_cli_show_channels_header(a->fd);
16732 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16733 if (linksets[linkset].ss7.ss7) {
16734 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16735 }
16736 }
16737 return CLI_SUCCESS;
16738 }
16739 #endif
16740
16741 #if defined(HAVE_SS7)
16742 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16743 {
16744 switch (cmd) {
16745 case CLI_INIT:
16746 e->command = "ss7 show version";
16747 e->usage =
16748 "Usage: ss7 show version\n"
16749 " Show the libss7 version\n";
16750 return NULL;
16751 case CLI_GENERATE:
16752 return NULL;
16753 }
16754
16755 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16756
16757 return CLI_SUCCESS;
16758 }
16759 #endif
16760
16761 #if defined(HAVE_SS7)
16762 static struct ast_cli_entry dahdi_ss7_cli[] = {
16763 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16764 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16765 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16766 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16767 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16768 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16769 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16770 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16771 };
16772 #endif
16773
16774 #if defined(HAVE_PRI)
16775 #if defined(HAVE_PRI_CCSS)
16776
16777
16778
16779
16780
16781
16782
16783
16784
16785
16786
16787
16788
16789
16790
16791
16792
16793 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16794 {
16795 struct dahdi_pvt *pvt;
16796 struct sig_pri_chan *pvt_chan;
16797 int res;
16798
16799 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16800
16801 pvt = chan->tech_pvt;
16802 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16803 pvt_chan = pvt->sig_pvt;
16804 } else {
16805 pvt_chan = NULL;
16806 }
16807 if (!pvt_chan) {
16808 return -1;
16809 }
16810
16811 ast_module_ref(ast_module_info->self);
16812
16813 res = sig_pri_cc_agent_init(agent, pvt_chan);
16814 if (res) {
16815 ast_module_unref(ast_module_info->self);
16816 }
16817 return res;
16818 }
16819 #endif
16820 #endif
16821
16822 #if defined(HAVE_PRI)
16823 #if defined(HAVE_PRI_CCSS)
16824
16825
16826
16827
16828
16829
16830
16831
16832
16833
16834
16835
16836
16837 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16838 {
16839 sig_pri_cc_agent_destructor(agent);
16840
16841 ast_module_unref(ast_module_info->self);
16842 }
16843 #endif
16844 #endif
16845
16846 #if defined(HAVE_PRI)
16847 #if defined(HAVE_PRI_CCSS)
16848 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16849 .type = dahdi_pri_cc_type,
16850 .init = dahdi_pri_cc_agent_init,
16851 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16852 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16853 .respond = sig_pri_cc_agent_req_rsp,
16854 .status_request = sig_pri_cc_agent_status_req,
16855 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16856 .party_b_free = sig_pri_cc_agent_party_b_free,
16857 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16858 .callee_available = sig_pri_cc_agent_callee_available,
16859 .destructor = dahdi_pri_cc_agent_destructor,
16860 };
16861 #endif
16862 #endif
16863
16864 #if defined(HAVE_PRI)
16865 #if defined(HAVE_PRI_CCSS)
16866 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16867 .type = dahdi_pri_cc_type,
16868 .request_cc = sig_pri_cc_monitor_req_cc,
16869 .suspend = sig_pri_cc_monitor_suspend,
16870 .unsuspend = sig_pri_cc_monitor_unsuspend,
16871 .status_response = sig_pri_cc_monitor_status_rsp,
16872 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16873 .destructor = sig_pri_cc_monitor_destructor,
16874 };
16875 #endif
16876 #endif
16877
16878 static int __unload_module(void)
16879 {
16880 struct dahdi_pvt *p;
16881 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16882 int i, j;
16883 #endif
16884
16885 #ifdef HAVE_PRI
16886 for (i = 0; i < NUM_SPANS; i++) {
16887 if (pris[i].pri.master != AST_PTHREADT_NULL) {
16888 pthread_cancel(pris[i].pri.master);
16889 pthread_kill(pris[i].pri.master, SIGURG);
16890 }
16891 }
16892 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16893 ast_unregister_application(dahdi_send_keypad_facility_app);
16894 #ifdef HAVE_PRI_PROG_W_CAUSE
16895 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16896 #endif
16897 #endif
16898 #if defined(HAVE_SS7)
16899 for (i = 0; i < NUM_SPANS; i++) {
16900 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16901 pthread_cancel(linksets[i].ss7.master);
16902 pthread_kill(linksets[i].ss7.master, SIGURG);
16903 }
16904 }
16905 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16906 #endif
16907 #if defined(HAVE_OPENR2)
16908 dahdi_r2_destroy_links();
16909 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16910 ast_unregister_application(dahdi_accept_r2_call_app);
16911 #endif
16912
16913 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16914 ast_manager_unregister("DAHDIDialOffhook");
16915 ast_manager_unregister("DAHDIHangup");
16916 ast_manager_unregister("DAHDITransfer");
16917 ast_manager_unregister("DAHDIDNDoff");
16918 ast_manager_unregister("DAHDIDNDon");
16919 ast_manager_unregister("DAHDIShowChannels");
16920 ast_manager_unregister("DAHDIRestart");
16921 ast_data_unregister(NULL);
16922 ast_channel_unregister(&dahdi_tech);
16923
16924
16925 ast_mutex_lock(&iflock);
16926 for (p = iflist; p; p = p->next) {
16927 if (p->owner)
16928 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16929 }
16930 ast_mutex_unlock(&iflock);
16931
16932 ast_mutex_lock(&monlock);
16933 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16934 pthread_cancel(monitor_thread);
16935 pthread_kill(monitor_thread, SIGURG);
16936 pthread_join(monitor_thread, NULL);
16937 }
16938 monitor_thread = AST_PTHREADT_STOP;
16939 ast_mutex_unlock(&monlock);
16940
16941 destroy_all_channels();
16942
16943 #if defined(HAVE_PRI)
16944 for (i = 0; i < NUM_SPANS; i++) {
16945 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16946 pthread_join(pris[i].pri.master, NULL);
16947 }
16948 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16949 dahdi_close_pri_fd(&(pris[i]), j);
16950 }
16951 sig_pri_stop_pri(&pris[i].pri);
16952 }
16953 #if defined(HAVE_PRI_CCSS)
16954 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16955 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16956 #endif
16957 sig_pri_unload();
16958 #endif
16959
16960 #if defined(HAVE_SS7)
16961 for (i = 0; i < NUM_SPANS; i++) {
16962 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16963 pthread_join(linksets[i].ss7.master, NULL);
16964 }
16965 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16966 dahdi_close_ss7_fd(&(linksets[i]), j);
16967 }
16968 }
16969 #endif
16970 ast_cond_destroy(&ss_thread_complete);
16971 return 0;
16972 }
16973
16974 static int unload_module(void)
16975 {
16976 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16977 int y;
16978 #endif
16979 #ifdef HAVE_PRI
16980 for (y = 0; y < NUM_SPANS; y++)
16981 ast_mutex_destroy(&pris[y].pri.lock);
16982 #endif
16983 #if defined(HAVE_SS7)
16984 for (y = 0; y < NUM_SPANS; y++)
16985 ast_mutex_destroy(&linksets[y].ss7.lock);
16986 #endif
16987 return __unload_module();
16988 }
16989
16990 static void string_replace(char *str, int char1, int char2)
16991 {
16992 for (; *str; str++) {
16993 if (*str == char1) {
16994 *str = char2;
16995 }
16996 }
16997 }
16998
16999 static char *parse_spanchan(char *chanstr, char **subdir)
17000 {
17001 char *p;
17002
17003 if ((p = strrchr(chanstr, '!')) == NULL) {
17004 *subdir = NULL;
17005 return chanstr;
17006 }
17007 *p++ = '\0';
17008 string_replace(chanstr, '!', '/');
17009 *subdir = chanstr;
17010 return p;
17011 }
17012
17013 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
17014 {
17015 char *c, *chan;
17016 char *subdir;
17017 int x, start, finish;
17018 struct dahdi_pvt *tmp;
17019
17020 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17021 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17022 return -1;
17023 }
17024
17025 c = ast_strdupa(value);
17026 c = parse_spanchan(c, &subdir);
17027
17028 while ((chan = strsep(&c, ","))) {
17029 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17030
17031 } else if (sscanf(chan, "%30d", &start)) {
17032
17033 finish = start;
17034 } else if (!strcasecmp(chan, "pseudo")) {
17035 finish = start = CHAN_PSEUDO;
17036 if (found_pseudo)
17037 *found_pseudo = 1;
17038 } else {
17039 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17040 return -1;
17041 }
17042 if (finish < start) {
17043 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17044 x = finish;
17045 finish = start;
17046 start = x;
17047 }
17048
17049 for (x = start; x <= finish; x++) {
17050 char fn[PATH_MAX];
17051 int real_channel = x;
17052
17053 if (!ast_strlen_zero(subdir)) {
17054 real_channel = device2chan(subdir, x, fn, sizeof(fn));
17055 if (real_channel < 0) {
17056 if (conf->ignore_failed_channels) {
17057 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17058 subdir, x, real_channel);
17059 continue;
17060 } else {
17061 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17062 subdir, x, real_channel);
17063 return -1;
17064 }
17065 }
17066 }
17067 tmp = mkintf(real_channel, conf, reload);
17068
17069 if (tmp) {
17070 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17071 } else {
17072 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17073 (reload == 1) ? "reconfigure" : "register", value);
17074 return -1;
17075 }
17076 }
17077 }
17078
17079 return 0;
17080 }
17081
17082
17083
17084 #define MAX_CHANLIST_LEN 80
17085
17086 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17087 {
17088 char *parse = ast_strdupa(data);
17089 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17090 unsigned int param_count;
17091 unsigned int x;
17092
17093 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17094 return;
17095
17096 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17097
17098
17099
17100 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17101
17102 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17103 confp->chan.echocancel.head.tap_length = x;
17104 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17105 confp->chan.echocancel.head.tap_length = 128;
17106
17107
17108
17109 for (x = 1; x < param_count; x++) {
17110 struct {
17111 char *name;
17112 char *value;
17113 } param;
17114
17115 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
17116 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
17117 continue;
17118 }
17119
17120 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17121 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
17122 continue;
17123 }
17124
17125 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17126
17127 if (param.value) {
17128 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17129 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
17130 continue;
17131 }
17132 }
17133 confp->chan.echocancel.head.param_count++;
17134 }
17135 }
17136
17137
17138 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
17139
17140 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
17141
17142 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17143 {
17144 struct dahdi_pvt *tmp;
17145 int y;
17146 int found_pseudo = 0;
17147 struct ast_variable *dahdichan = NULL;
17148
17149 for (; v; v = v->next) {
17150 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17151 continue;
17152
17153
17154 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17155 if (options & PROC_DAHDI_OPT_NOCHAN) {
17156 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17157 continue;
17158 }
17159 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17160 if (confp->ignore_failed_channels) {
17161 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17162 continue;
17163 } else {
17164 return -1;
17165 }
17166 }
17167 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17168 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17169 confp->ignore_failed_channels = ast_true(v->value);
17170 } else if (!strcasecmp(v->name, "buffers")) {
17171 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17172 ast_log(LOG_WARNING, "Using default buffer policy.\n");
17173 confp->chan.buf_no = numbufs;
17174 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17175 }
17176 } else if (!strcasecmp(v->name, "faxbuffers")) {
17177 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17178 confp->chan.usefaxbuffers = 1;
17179 }
17180 } else if (!strcasecmp(v->name, "dahdichan")) {
17181
17182 dahdichan = v;
17183 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17184 usedistinctiveringdetection = ast_true(v->value);
17185 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17186 distinctiveringaftercid = ast_true(v->value);
17187 } else if (!strcasecmp(v->name, "dring1context")) {
17188 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17189 } else if (!strcasecmp(v->name, "dring2context")) {
17190 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17191 } else if (!strcasecmp(v->name, "dring3context")) {
17192 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17193 } else if (!strcasecmp(v->name, "dring1range")) {
17194 confp->chan.drings.ringnum[0].range = atoi(v->value);
17195 } else if (!strcasecmp(v->name, "dring2range")) {
17196 confp->chan.drings.ringnum[1].range = atoi(v->value);
17197 } else if (!strcasecmp(v->name, "dring3range")) {
17198 confp->chan.drings.ringnum[2].range = atoi(v->value);
17199 } else if (!strcasecmp(v->name, "dring1")) {
17200 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
17201 } else if (!strcasecmp(v->name, "dring2")) {
17202 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
17203 } else if (!strcasecmp(v->name, "dring3")) {
17204 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
17205 } else if (!strcasecmp(v->name, "usecallerid")) {
17206 confp->chan.use_callerid = ast_true(v->value);
17207 } else if (!strcasecmp(v->name, "cidsignalling")) {
17208 if (!strcasecmp(v->value, "bell"))
17209 confp->chan.cid_signalling = CID_SIG_BELL;
17210 else if (!strcasecmp(v->value, "v23"))
17211 confp->chan.cid_signalling = CID_SIG_V23;
17212 else if (!strcasecmp(v->value, "dtmf"))
17213 confp->chan.cid_signalling = CID_SIG_DTMF;
17214 else if (!strcasecmp(v->value, "smdi"))
17215 confp->chan.cid_signalling = CID_SIG_SMDI;
17216 else if (!strcasecmp(v->value, "v23_jp"))
17217 confp->chan.cid_signalling = CID_SIG_V23_JP;
17218 else if (ast_true(v->value))
17219 confp->chan.cid_signalling = CID_SIG_BELL;
17220 } else if (!strcasecmp(v->name, "cidstart")) {
17221 if (!strcasecmp(v->value, "ring"))
17222 confp->chan.cid_start = CID_START_RING;
17223 else if (!strcasecmp(v->value, "polarity_in"))
17224 confp->chan.cid_start = CID_START_POLARITY_IN;
17225 else if (!strcasecmp(v->value, "polarity"))
17226 confp->chan.cid_start = CID_START_POLARITY;
17227 else if (!strcasecmp(v->value, "dtmf"))
17228 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17229 else if (ast_true(v->value))
17230 confp->chan.cid_start = CID_START_RING;
17231 } else if (!strcasecmp(v->name, "threewaycalling")) {
17232 confp->chan.threewaycalling = ast_true(v->value);
17233 } else if (!strcasecmp(v->name, "cancallforward")) {
17234 confp->chan.cancallforward = ast_true(v->value);
17235 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17236 if (ast_true(v->value))
17237 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17238 else
17239 confp->chan.dtmfrelax = 0;
17240 } else if (!strcasecmp(v->name, "mailbox")) {
17241 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17242 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17243 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17244 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17245 }
17246 } else if (!strcasecmp(v->name, "adsi")) {
17247 confp->chan.adsi = ast_true(v->value);
17248 } else if (!strcasecmp(v->name, "usesmdi")) {
17249 confp->chan.use_smdi = ast_true(v->value);
17250 } else if (!strcasecmp(v->name, "smdiport")) {
17251 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17252 } else if (!strcasecmp(v->name, "transfer")) {
17253 confp->chan.transfer = ast_true(v->value);
17254 } else if (!strcasecmp(v->name, "canpark")) {
17255 confp->chan.canpark = ast_true(v->value);
17256 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17257 confp->chan.echocanbridged = ast_true(v->value);
17258 } else if (!strcasecmp(v->name, "busydetect")) {
17259 confp->chan.busydetect = ast_true(v->value);
17260 } else if (!strcasecmp(v->name, "busycount")) {
17261 confp->chan.busycount = atoi(v->value);
17262 } else if (!strcasecmp(v->name, "silencethreshold")) {
17263 confp->chan.silencethreshold = atoi(v->value);
17264 } else if (!strcasecmp(v->name, "busycompare")) {
17265 confp->chan.busycompare = ast_true(v->value);
17266 } else if (!strcasecmp(v->name, "busypattern")) {
17267 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
17268 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17269 }
17270 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
17271 if (count == 1)
17272 confp->chan.busyquietlength = 0;
17273 else if (count < 1)
17274 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
17275 } else if (!strcasecmp(v->name, "busyfuzziness")) {
17276 confp->chan.busyfuzziness = atoi(v->value);
17277 } else if (!strcasecmp(v->name, "callprogress")) {
17278 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17279 if (ast_true(v->value))
17280 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17281 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17282 confp->chan.waitfordialtone = atoi(v->value);
17283 } else if (!strcasecmp(v->name, "faxdetect")) {
17284 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17285 if (!strcasecmp(v->value, "incoming")) {
17286 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17287 } else if (!strcasecmp(v->value, "outgoing")) {
17288 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17289 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17290 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17291 } else if (!strcasecmp(v->name, "echocancel")) {
17292 process_echocancel(confp, v->value, v->lineno);
17293 } else if (!strcasecmp(v->name, "echotraining")) {
17294 if (sscanf(v->value, "%30d", &y) == 1) {
17295 if ((y < 10) || (y > 4000)) {
17296 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17297 } else {
17298 confp->chan.echotraining = y;
17299 }
17300 } else if (ast_true(v->value)) {
17301 confp->chan.echotraining = 400;
17302 } else
17303 confp->chan.echotraining = 0;
17304 } else if (!strcasecmp(v->name, "hidecallerid")) {
17305 confp->chan.hidecallerid = ast_true(v->value);
17306 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17307 confp->chan.hidecalleridname = ast_true(v->value);
17308 } else if (!strcasecmp(v->name, "pulsedial")) {
17309 confp->chan.pulse = ast_true(v->value);
17310 } else if (!strcasecmp(v->name, "callreturn")) {
17311 confp->chan.callreturn = ast_true(v->value);
17312 } else if (!strcasecmp(v->name, "callwaiting")) {
17313 confp->chan.callwaiting = ast_true(v->value);
17314 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17315 confp->chan.callwaitingcallerid = ast_true(v->value);
17316 } else if (!strcasecmp(v->name, "context")) {
17317 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17318 } else if (!strcasecmp(v->name, "language")) {
17319 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17320 } else if (!strcasecmp(v->name, "progzone")) {
17321 ast_copy_string(progzone, v->value, sizeof(progzone));
17322 } else if (!strcasecmp(v->name, "mohinterpret")
17323 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17324 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17325 } else if (!strcasecmp(v->name, "mohsuggest")) {
17326 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17327 } else if (!strcasecmp(v->name, "parkinglot")) {
17328 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17329 } else if (!strcasecmp(v->name, "stripmsd")) {
17330 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17331 confp->chan.stripmsd = atoi(v->value);
17332 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17333 numbufs = atoi(v->value);
17334 } else if (!strcasecmp(v->name, "group")) {
17335 confp->chan.group = ast_get_group(v->value);
17336 } else if (!strcasecmp(v->name, "callgroup")) {
17337 if (!strcasecmp(v->value, "none"))
17338 confp->chan.callgroup = 0;
17339 else
17340 confp->chan.callgroup = ast_get_group(v->value);
17341 } else if (!strcasecmp(v->name, "pickupgroup")) {
17342 if (!strcasecmp(v->value, "none"))
17343 confp->chan.pickupgroup = 0;
17344 else
17345 confp->chan.pickupgroup = ast_get_group(v->value);
17346 } else if (!strcasecmp(v->name, "setvar")) {
17347 char *varname = ast_strdupa(v->value), *varval = NULL;
17348 struct ast_variable *tmpvar;
17349 if (varname && (varval = strchr(varname, '='))) {
17350 *varval++ = '\0';
17351 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17352 tmpvar->next = confp->chan.vars;
17353 confp->chan.vars = tmpvar;
17354 }
17355 }
17356 } else if (!strcasecmp(v->name, "immediate")) {
17357 confp->chan.immediate = ast_true(v->value);
17358 } else if (!strcasecmp(v->name, "transfertobusy")) {
17359 confp->chan.transfertobusy = ast_true(v->value);
17360 } else if (!strcasecmp(v->name, "mwimonitor")) {
17361 confp->chan.mwimonitor_neon = 0;
17362 confp->chan.mwimonitor_fsk = 0;
17363 confp->chan.mwimonitor_rpas = 0;
17364 if (strcasestr(v->value, "fsk")) {
17365 confp->chan.mwimonitor_fsk = 1;
17366 }
17367 if (strcasestr(v->value, "rpas")) {
17368 confp->chan.mwimonitor_rpas = 1;
17369 }
17370 if (strcasestr(v->value, "neon")) {
17371 confp->chan.mwimonitor_neon = 1;
17372 }
17373
17374 if (ast_true(v->value)) {
17375 confp->chan.mwimonitor_fsk = 1;
17376 }
17377 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17378 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17379 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17380 }
17381 } else if (!strcasecmp(v->name, "rxgain")) {
17382 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17383 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17384 }
17385 } else if (!strcasecmp(v->name, "txgain")) {
17386 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17387 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17388 }
17389 } else if (!strcasecmp(v->name, "txdrc")) {
17390 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17391 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17392 }
17393 } else if (!strcasecmp(v->name, "rxdrc")) {
17394 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17395 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17396 }
17397 } else if (!strcasecmp(v->name, "tonezone")) {
17398 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17399 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17400 }
17401 } else if (!strcasecmp(v->name, "callerid")) {
17402 if (!strcasecmp(v->value, "asreceived")) {
17403 confp->chan.cid_num[0] = '\0';
17404 confp->chan.cid_name[0] = '\0';
17405 } else {
17406 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17407 }
17408 } else if (!strcasecmp(v->name, "fullname")) {
17409 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17410 } else if (!strcasecmp(v->name, "cid_number")) {
17411 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17412 } else if (!strcasecmp(v->name, "cid_tag")) {
17413 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17414 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17415 confp->chan.dahditrcallerid = ast_true(v->value);
17416 } else if (!strcasecmp(v->name, "restrictcid")) {
17417 confp->chan.restrictcid = ast_true(v->value);
17418 } else if (!strcasecmp(v->name, "usecallingpres")) {
17419 confp->chan.use_callingpres = ast_true(v->value);
17420 } else if (!strcasecmp(v->name, "accountcode")) {
17421 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17422 } else if (!strcasecmp(v->name, "amaflags")) {
17423 y = ast_cdr_amaflags2int(v->value);
17424 if (y < 0)
17425 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17426 else
17427 confp->chan.amaflags = y;
17428 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17429 confp->chan.polarityonanswerdelay = atoi(v->value);
17430 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17431 confp->chan.answeronpolarityswitch = ast_true(v->value);
17432 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17433 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17434 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17435 confp->chan.sendcalleridafter = atoi(v->value);
17436 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17437 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17438 } else if (ast_cc_is_config_param(v->name)) {
17439 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17440 } else if (!strcasecmp(v->name, "mwisendtype")) {
17441 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17442 if (!strcasecmp(v->value, "rpas")) {
17443 mwisend_rpas = 1;
17444 } else {
17445 mwisend_rpas = 0;
17446 }
17447 #else
17448
17449 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17450 if (strcasestr(v->value, "nofsk")) {
17451 confp->chan.mwisend_fsk = 0;
17452 } else {
17453 confp->chan.mwisend_fsk = 1;
17454 }
17455 if (strcasestr(v->value, "rpas")) {
17456 confp->chan.mwisend_rpas = 1;
17457 } else {
17458 confp->chan.mwisend_rpas = 0;
17459 }
17460 if (strcasestr(v->value, "lrev")) {
17461 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17462 }
17463 if (strcasestr(v->value, "hvdc")) {
17464 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17465 }
17466 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17467 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17468 }
17469 #endif
17470 } else if (reload != 1) {
17471 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17472 int orig_radio = confp->chan.radio;
17473 int orig_outsigmod = confp->chan.outsigmod;
17474 int orig_auto = confp->is_sig_auto;
17475
17476 confp->chan.radio = 0;
17477 confp->chan.outsigmod = -1;
17478 confp->is_sig_auto = 0;
17479 if (!strcasecmp(v->value, "em")) {
17480 confp->chan.sig = SIG_EM;
17481 } else if (!strcasecmp(v->value, "em_e1")) {
17482 confp->chan.sig = SIG_EM_E1;
17483 } else if (!strcasecmp(v->value, "em_w")) {
17484 confp->chan.sig = SIG_EMWINK;
17485 } else if (!strcasecmp(v->value, "fxs_ls")) {
17486 confp->chan.sig = SIG_FXSLS;
17487 } else if (!strcasecmp(v->value, "fxs_gs")) {
17488 confp->chan.sig = SIG_FXSGS;
17489 } else if (!strcasecmp(v->value, "fxs_ks")) {
17490 confp->chan.sig = SIG_FXSKS;
17491 } else if (!strcasecmp(v->value, "fxo_ls")) {
17492 confp->chan.sig = SIG_FXOLS;
17493 } else if (!strcasecmp(v->value, "fxo_gs")) {
17494 confp->chan.sig = SIG_FXOGS;
17495 } else if (!strcasecmp(v->value, "fxo_ks")) {
17496 confp->chan.sig = SIG_FXOKS;
17497 } else if (!strcasecmp(v->value, "fxs_rx")) {
17498 confp->chan.sig = SIG_FXSKS;
17499 confp->chan.radio = 1;
17500 } else if (!strcasecmp(v->value, "fxo_rx")) {
17501 confp->chan.sig = SIG_FXOLS;
17502 confp->chan.radio = 1;
17503 } else if (!strcasecmp(v->value, "fxs_tx")) {
17504 confp->chan.sig = SIG_FXSLS;
17505 confp->chan.radio = 1;
17506 } else if (!strcasecmp(v->value, "fxo_tx")) {
17507 confp->chan.sig = SIG_FXOGS;
17508 confp->chan.radio = 1;
17509 } else if (!strcasecmp(v->value, "em_rx")) {
17510 confp->chan.sig = SIG_EM;
17511 confp->chan.radio = 1;
17512 } else if (!strcasecmp(v->value, "em_tx")) {
17513 confp->chan.sig = SIG_EM;
17514 confp->chan.radio = 1;
17515 } else if (!strcasecmp(v->value, "em_rxtx")) {
17516 confp->chan.sig = SIG_EM;
17517 confp->chan.radio = 2;
17518 } else if (!strcasecmp(v->value, "em_txrx")) {
17519 confp->chan.sig = SIG_EM;
17520 confp->chan.radio = 2;
17521 } else if (!strcasecmp(v->value, "sf")) {
17522 confp->chan.sig = SIG_SF;
17523 } else if (!strcasecmp(v->value, "sf_w")) {
17524 confp->chan.sig = SIG_SFWINK;
17525 } else if (!strcasecmp(v->value, "sf_featd")) {
17526 confp->chan.sig = SIG_FEATD;
17527 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17528 confp->chan.sig = SIG_FEATDMF;
17529 } else if (!strcasecmp(v->value, "sf_featb")) {
17530 confp->chan.sig = SIG_SF_FEATB;
17531 } else if (!strcasecmp(v->value, "sf")) {
17532 confp->chan.sig = SIG_SF;
17533 } else if (!strcasecmp(v->value, "sf_rx")) {
17534 confp->chan.sig = SIG_SF;
17535 confp->chan.radio = 1;
17536 } else if (!strcasecmp(v->value, "sf_tx")) {
17537 confp->chan.sig = SIG_SF;
17538 confp->chan.radio = 1;
17539 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17540 confp->chan.sig = SIG_SF;
17541 confp->chan.radio = 2;
17542 } else if (!strcasecmp(v->value, "sf_txrx")) {
17543 confp->chan.sig = SIG_SF;
17544 confp->chan.radio = 2;
17545 } else if (!strcasecmp(v->value, "featd")) {
17546 confp->chan.sig = SIG_FEATD;
17547 } else if (!strcasecmp(v->value, "featdmf")) {
17548 confp->chan.sig = SIG_FEATDMF;
17549 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17550 confp->chan.sig = SIG_FEATDMF_TA;
17551 } else if (!strcasecmp(v->value, "e911")) {
17552 confp->chan.sig = SIG_E911;
17553 } else if (!strcasecmp(v->value, "fgccama")) {
17554 confp->chan.sig = SIG_FGC_CAMA;
17555 } else if (!strcasecmp(v->value, "fgccamamf")) {
17556 confp->chan.sig = SIG_FGC_CAMAMF;
17557 } else if (!strcasecmp(v->value, "featb")) {
17558 confp->chan.sig = SIG_FEATB;
17559 #ifdef HAVE_PRI
17560 } else if (!strcasecmp(v->value, "pri_net")) {
17561 confp->chan.sig = SIG_PRI;
17562 confp->pri.pri.nodetype = PRI_NETWORK;
17563 } else if (!strcasecmp(v->value, "pri_cpe")) {
17564 confp->chan.sig = SIG_PRI;
17565 confp->pri.pri.nodetype = PRI_CPE;
17566 } else if (!strcasecmp(v->value, "bri_cpe")) {
17567 confp->chan.sig = SIG_BRI;
17568 confp->pri.pri.nodetype = PRI_CPE;
17569 } else if (!strcasecmp(v->value, "bri_net")) {
17570 confp->chan.sig = SIG_BRI;
17571 confp->pri.pri.nodetype = PRI_NETWORK;
17572 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17573 confp->chan.sig = SIG_BRI_PTMP;
17574 confp->pri.pri.nodetype = PRI_CPE;
17575 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17576 #if defined(HAVE_PRI_CALL_HOLD)
17577 confp->chan.sig = SIG_BRI_PTMP;
17578 confp->pri.pri.nodetype = PRI_NETWORK;
17579 #else
17580 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17581 #endif
17582 #endif
17583 #if defined(HAVE_SS7)
17584 } else if (!strcasecmp(v->value, "ss7")) {
17585 confp->chan.sig = SIG_SS7;
17586 #endif
17587 #ifdef HAVE_OPENR2
17588 } else if (!strcasecmp(v->value, "mfcr2")) {
17589 confp->chan.sig = SIG_MFCR2;
17590 #endif
17591 } else if (!strcasecmp(v->value, "auto")) {
17592 confp->is_sig_auto = 1;
17593 } else {
17594 confp->chan.outsigmod = orig_outsigmod;
17595 confp->chan.radio = orig_radio;
17596 confp->is_sig_auto = orig_auto;
17597 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17598 }
17599 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17600 if (!strcasecmp(v->value, "em")) {
17601 confp->chan.outsigmod = SIG_EM;
17602 } else if (!strcasecmp(v->value, "em_e1")) {
17603 confp->chan.outsigmod = SIG_EM_E1;
17604 } else if (!strcasecmp(v->value, "em_w")) {
17605 confp->chan.outsigmod = SIG_EMWINK;
17606 } else if (!strcasecmp(v->value, "sf")) {
17607 confp->chan.outsigmod = SIG_SF;
17608 } else if (!strcasecmp(v->value, "sf_w")) {
17609 confp->chan.outsigmod = SIG_SFWINK;
17610 } else if (!strcasecmp(v->value, "sf_featd")) {
17611 confp->chan.outsigmod = SIG_FEATD;
17612 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17613 confp->chan.outsigmod = SIG_FEATDMF;
17614 } else if (!strcasecmp(v->value, "sf_featb")) {
17615 confp->chan.outsigmod = SIG_SF_FEATB;
17616 } else if (!strcasecmp(v->value, "sf")) {
17617 confp->chan.outsigmod = SIG_SF;
17618 } else if (!strcasecmp(v->value, "featd")) {
17619 confp->chan.outsigmod = SIG_FEATD;
17620 } else if (!strcasecmp(v->value, "featdmf")) {
17621 confp->chan.outsigmod = SIG_FEATDMF;
17622 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17623 confp->chan.outsigmod = SIG_FEATDMF_TA;
17624 } else if (!strcasecmp(v->value, "e911")) {
17625 confp->chan.outsigmod = SIG_E911;
17626 } else if (!strcasecmp(v->value, "fgccama")) {
17627 confp->chan.outsigmod = SIG_FGC_CAMA;
17628 } else if (!strcasecmp(v->value, "fgccamamf")) {
17629 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17630 } else if (!strcasecmp(v->value, "featb")) {
17631 confp->chan.outsigmod = SIG_FEATB;
17632 } else {
17633 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17634 }
17635 #ifdef HAVE_PRI
17636 } else if (!strcasecmp(v->name, "pridialplan")) {
17637 if (!strcasecmp(v->value, "national")) {
17638 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17639 } else if (!strcasecmp(v->value, "unknown")) {
17640 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17641 } else if (!strcasecmp(v->value, "private")) {
17642 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17643 } else if (!strcasecmp(v->value, "international")) {
17644 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17645 } else if (!strcasecmp(v->value, "local")) {
17646 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17647 } else if (!strcasecmp(v->value, "dynamic")) {
17648 confp->pri.pri.dialplan = -1;
17649 } else if (!strcasecmp(v->value, "redundant")) {
17650 confp->pri.pri.dialplan = -2;
17651 } else {
17652 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17653 }
17654 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17655 if (!strcasecmp(v->value, "national")) {
17656 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17657 } else if (!strcasecmp(v->value, "unknown")) {
17658 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17659 } else if (!strcasecmp(v->value, "private")) {
17660 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17661 } else if (!strcasecmp(v->value, "international")) {
17662 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17663 } else if (!strcasecmp(v->value, "local")) {
17664 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17665 } else if (!strcasecmp(v->value, "dynamic")) {
17666 confp->pri.pri.localdialplan = -1;
17667 } else if (!strcasecmp(v->value, "redundant")) {
17668 confp->pri.pri.localdialplan = -2;
17669 } else {
17670 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17671 }
17672 } else if (!strcasecmp(v->name, "switchtype")) {
17673 if (!strcasecmp(v->value, "national"))
17674 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17675 else if (!strcasecmp(v->value, "ni1"))
17676 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17677 else if (!strcasecmp(v->value, "dms100"))
17678 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17679 else if (!strcasecmp(v->value, "4ess"))
17680 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17681 else if (!strcasecmp(v->value, "5ess"))
17682 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17683 else if (!strcasecmp(v->value, "euroisdn"))
17684 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17685 else if (!strcasecmp(v->value, "qsig"))
17686 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17687 else {
17688 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17689 return -1;
17690 }
17691 } else if (!strcasecmp(v->name, "msn")) {
17692 ast_copy_string(confp->pri.pri.msn_list, v->value,
17693 sizeof(confp->pri.pri.msn_list));
17694 } else if (!strcasecmp(v->name, "nsf")) {
17695 if (!strcasecmp(v->value, "sdn"))
17696 confp->pri.pri.nsf = PRI_NSF_SDN;
17697 else if (!strcasecmp(v->value, "megacom"))
17698 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17699 else if (!strcasecmp(v->value, "tollfreemegacom"))
17700 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17701 else if (!strcasecmp(v->value, "accunet"))
17702 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17703 else if (!strcasecmp(v->value, "none"))
17704 confp->pri.pri.nsf = PRI_NSF_NONE;
17705 else {
17706 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17707 confp->pri.pri.nsf = PRI_NSF_NONE;
17708 }
17709 } else if (!strcasecmp(v->name, "priindication")) {
17710 if (!strcasecmp(v->value, "outofband"))
17711 confp->chan.priindication_oob = 1;
17712 else if (!strcasecmp(v->value, "inband"))
17713 confp->chan.priindication_oob = 0;
17714 else
17715 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17716 v->value, v->lineno);
17717 } else if (!strcasecmp(v->name, "priexclusive")) {
17718 confp->chan.priexclusive = ast_true(v->value);
17719 } else if (!strcasecmp(v->name, "internationalprefix")) {
17720 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17721 } else if (!strcasecmp(v->name, "nationalprefix")) {
17722 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17723 } else if (!strcasecmp(v->name, "localprefix")) {
17724 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17725 } else if (!strcasecmp(v->name, "privateprefix")) {
17726 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17727 } else if (!strcasecmp(v->name, "unknownprefix")) {
17728 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17729 } else if (!strcasecmp(v->name, "resetinterval")) {
17730 if (!strcasecmp(v->value, "never"))
17731 confp->pri.pri.resetinterval = -1;
17732 else if (atoi(v->value) >= 60)
17733 confp->pri.pri.resetinterval = atoi(v->value);
17734 else
17735 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17736 v->value, v->lineno);
17737 } else if (!strcasecmp(v->name, "minunused")) {
17738 confp->pri.pri.minunused = atoi(v->value);
17739 } else if (!strcasecmp(v->name, "minidle")) {
17740 confp->pri.pri.minidle = atoi(v->value);
17741 } else if (!strcasecmp(v->name, "idleext")) {
17742 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17743 } else if (!strcasecmp(v->name, "idledial")) {
17744 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17745 } else if (!strcasecmp(v->name, "overlapdial")) {
17746 if (ast_true(v->value)) {
17747 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17748 } else if (!strcasecmp(v->value, "incoming")) {
17749 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17750 } else if (!strcasecmp(v->value, "outgoing")) {
17751 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17752 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17753 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17754 } else {
17755 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17756 }
17757 #ifdef HAVE_PRI_PROG_W_CAUSE
17758 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17759 if (!strcasecmp(v->value, "logical")) {
17760 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17761 } else if (!strcasecmp(v->value, "physical")) {
17762 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17763 } else {
17764 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17765 }
17766 #endif
17767 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17768 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17769 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17770 } else if (!strcasecmp(v->name, "service_message_support")) {
17771
17772 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17773 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17774 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17775 confp->pri.pri.enable_service_message_support = 1;
17776 } else {
17777 confp->pri.pri.enable_service_message_support = 0;
17778 }
17779 #endif
17780 #ifdef HAVE_PRI_INBANDDISCONNECT
17781 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17782 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17783 #endif
17784 } else if (!strcasecmp(v->name, "pritimer")) {
17785 #ifdef PRI_GETSET_TIMERS
17786 char tmp[20];
17787 char *timerc;
17788 char *c;
17789 int timer;
17790 int timeridx;
17791
17792 ast_copy_string(tmp, v->value, sizeof(tmp));
17793 c = tmp;
17794 timerc = strsep(&c, ",");
17795 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17796 timeridx = pri_timer2idx(timerc);
17797 timer = atoi(c);
17798 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17799 ast_log(LOG_WARNING,
17800 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17801 v->lineno);
17802 } else if (!timer) {
17803 ast_log(LOG_WARNING,
17804 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17805 c, timerc, v->lineno);
17806 } else {
17807 confp->pri.pri.pritimers[timeridx] = timer;
17808 }
17809 } else {
17810 ast_log(LOG_WARNING,
17811 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17812 v->value, v->lineno);
17813 }
17814 #endif
17815 } else if (!strcasecmp(v->name, "facilityenable")) {
17816 confp->pri.pri.facilityenable = ast_true(v->value);
17817 #if defined(HAVE_PRI_AOC_EVENTS)
17818 } else if (!strcasecmp(v->name, "aoc_enable")) {
17819 confp->pri.pri.aoc_passthrough_flag = 0;
17820 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17821 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17822 }
17823 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17824 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17825 }
17826 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17827 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17828 }
17829 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17830 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17831 #endif
17832 #if defined(HAVE_PRI_CALL_HOLD)
17833 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17834 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17835 #endif
17836 #if defined(HAVE_PRI_CCSS)
17837 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17838 if (!strcasecmp(v->value, "global")) {
17839 confp->pri.pri.cc_ptmp_recall_mode = 0;
17840 } else if (!strcasecmp(v->value, "specific")) {
17841 confp->pri.pri.cc_ptmp_recall_mode = 1;
17842 } else {
17843 confp->pri.pri.cc_ptmp_recall_mode = 1;
17844 }
17845 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17846 if (!strcasecmp(v->value, "release")) {
17847 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17848 } else if (!strcasecmp(v->value, "retain")) {
17849 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17850 } else if (!strcasecmp(v->value, "do_not_care")) {
17851 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17852 } else {
17853 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17854 }
17855 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17856 if (!strcasecmp(v->value, "release")) {
17857 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17858 } else if (!strcasecmp(v->value, "retain")) {
17859 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17860 } else {
17861 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17862 }
17863 #endif
17864 #if defined(HAVE_PRI_CALL_WAITING)
17865 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17866 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17867 if (confp->pri.pri.max_call_waiting_calls < 0) {
17868
17869 confp->pri.pri.max_call_waiting_calls = 0;
17870 }
17871 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17872 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17873 #endif
17874 #if defined(HAVE_PRI_MWI)
17875 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17876 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17877 sizeof(confp->pri.pri.mwi_mailboxes));
17878 #endif
17879 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17880 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17881 } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
17882 confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
17883 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
17884 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
17885 } else if (!strcasecmp(v->name, "layer1_presence")) {
17886 if (!strcasecmp(v->value, "required")) {
17887 confp->pri.pri.layer1_ignored = 0;
17888 } else if (!strcasecmp(v->value, "ignore")) {
17889 confp->pri.pri.layer1_ignored = 1;
17890 } else {
17891
17892 confp->pri.pri.layer1_ignored = 0;
17893 }
17894 #if defined(HAVE_PRI_L2_PERSISTENCE)
17895 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17896 if (!strcasecmp(v->value, "keep_up")) {
17897 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17898 } else if (!strcasecmp(v->value, "leave_down")) {
17899 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17900 } else {
17901 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17902 }
17903 #endif
17904 #endif
17905 #if defined(HAVE_SS7)
17906 } else if (!strcasecmp(v->name, "ss7type")) {
17907 if (!strcasecmp(v->value, "itu")) {
17908 cur_ss7type = SS7_ITU;
17909 } else if (!strcasecmp(v->value, "ansi")) {
17910 cur_ss7type = SS7_ANSI;
17911 } else
17912 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17913 } else if (!strcasecmp(v->name, "linkset")) {
17914 cur_linkset = atoi(v->value);
17915 } else if (!strcasecmp(v->name, "pointcode")) {
17916 cur_pointcode = parse_pointcode(v->value);
17917 } else if (!strcasecmp(v->name, "adjpointcode")) {
17918 cur_adjpointcode = parse_pointcode(v->value);
17919 } else if (!strcasecmp(v->name, "defaultdpc")) {
17920 cur_defaultdpc = parse_pointcode(v->value);
17921 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17922 cur_cicbeginswith = atoi(v->value);
17923 } else if (!strcasecmp(v->name, "networkindicator")) {
17924 if (!strcasecmp(v->value, "national"))
17925 cur_networkindicator = SS7_NI_NAT;
17926 else if (!strcasecmp(v->value, "national_spare"))
17927 cur_networkindicator = SS7_NI_NAT_SPARE;
17928 else if (!strcasecmp(v->value, "international"))
17929 cur_networkindicator = SS7_NI_INT;
17930 else if (!strcasecmp(v->value, "international_spare"))
17931 cur_networkindicator = SS7_NI_INT_SPARE;
17932 else
17933 cur_networkindicator = -1;
17934 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17935 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17936 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17937 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17938 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17939 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17940 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17941 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17942 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17943 if (!strcasecmp(v->value, "national")) {
17944 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17945 } else if (!strcasecmp(v->value, "international")) {
17946 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17947 } else if (!strcasecmp(v->value, "subscriber")) {
17948 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17949 } else if (!strcasecmp(v->value, "unknown")) {
17950 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17951 } else if (!strcasecmp(v->value, "dynamic")) {
17952 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17953 } else {
17954 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17955 }
17956 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17957 if (!strcasecmp(v->value, "national")) {
17958 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17959 } else if (!strcasecmp(v->value, "international")) {
17960 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17961 } else if (!strcasecmp(v->value, "subscriber")) {
17962 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17963 } else if (!strcasecmp(v->value, "unknown")) {
17964 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17965 } else if (!strcasecmp(v->value, "dynamic")) {
17966 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17967 } else {
17968 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17969 }
17970 } else if (!strcasecmp(v->name, "sigchan")) {
17971 int sigchan, res;
17972 sigchan = atoi(v->value);
17973 res = linkset_addsigchan(sigchan);
17974 if (res < 0)
17975 return -1;
17976
17977 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17978 struct dahdi_ss7 *link;
17979 link = ss7_resolve_linkset(cur_linkset);
17980 if (!link) {
17981 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17982 return -1;
17983 }
17984 if (ast_true(v->value))
17985 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17986 #endif
17987 #ifdef HAVE_OPENR2
17988 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17989 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17990 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", confp->mfcr2.r2proto_file);
17991 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17992 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17993 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17994 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17995 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17996 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17997 confp->mfcr2.variant = OR2_VAR_ITU;
17998 }
17999 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
18000 confp->mfcr2.mfback_timeout = atoi(v->value);
18001 if (!confp->mfcr2.mfback_timeout) {
18002 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
18003 confp->mfcr2.mfback_timeout = -1;
18004 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
18005 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
18006 }
18007 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
18008 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
18009 if (confp->mfcr2.metering_pulse_timeout > 500) {
18010 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
18011 }
18012 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
18013 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
18014 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
18015 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
18016 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
18017 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
18018 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
18019 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
18020 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
18021 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
18022 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
18023 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
18024 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
18025 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
18026 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
18027 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
18028 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
18029 #endif
18030 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
18031 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
18032 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
18033 confp->mfcr2.max_ani = atoi(v->value);
18034 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
18035 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
18036 }
18037 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
18038 confp->mfcr2.max_dnis = atoi(v->value);
18039 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
18040 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
18041 }
18042 } else if (!strcasecmp(v->name, "mfcr2_category")) {
18043 confp->mfcr2.category = openr2_proto_get_category(v->value);
18044 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
18045 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
18046 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
18047 v->value, v->lineno);
18048 }
18049 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
18050 openr2_log_level_t tmplevel;
18051 char *clevel;
18052 char *logval = ast_strdupa(v->value);
18053 while (logval) {
18054 clevel = strsep(&logval,",");
18055 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
18056 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
18057 continue;
18058 }
18059 confp->mfcr2.loglevel |= tmplevel;
18060 }
18061 #endif
18062 } else if (!strcasecmp(v->name, "cadence")) {
18063
18064 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18065 int i;
18066 struct dahdi_ring_cadence new_cadence;
18067 int cid_location = -1;
18068 int firstcadencepos = 0;
18069 char original_args[80];
18070 int cadence_is_ok = 1;
18071
18072 ast_copy_string(original_args, v->value, sizeof(original_args));
18073
18074 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]);
18075
18076
18077 if (element_count % 2 == 1) {
18078 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18079 cadence_is_ok = 0;
18080 }
18081
18082
18083 for (i = 0; i < element_count; i++) {
18084 if (c[i] == 0) {
18085 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18086 cadence_is_ok = 0;
18087 break;
18088 } else if (c[i] < 0) {
18089 if (i % 2 == 1) {
18090
18091 if (cid_location == -1) {
18092 cid_location = i;
18093 c[i] *= -1;
18094 } else {
18095 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18096 cadence_is_ok = 0;
18097 break;
18098 }
18099 } else {
18100 if (firstcadencepos == 0) {
18101 firstcadencepos = i;
18102
18103 } else {
18104 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18105 cadence_is_ok = 0;
18106 break;
18107 }
18108 }
18109 }
18110 }
18111
18112
18113 for (i = 0; i < 16; i++) {
18114 new_cadence.ringcadence[i] = c[i];
18115 }
18116
18117 if (cadence_is_ok) {
18118
18119 if (element_count < 2) {
18120 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18121 } else {
18122 if (cid_location == -1) {
18123
18124 cid_location = 1;
18125 } else {
18126
18127 cid_location = (cid_location + 1) / 2;
18128 }
18129
18130 if (!user_has_defined_cadences++)
18131
18132 num_cadence = 0;
18133 if ((num_cadence+1) >= NUM_CADENCE_MAX)
18134 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18135 else {
18136 cadences[num_cadence] = new_cadence;
18137 cidrings[num_cadence++] = cid_location;
18138 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18139 }
18140 }
18141 }
18142 } else if (!strcasecmp(v->name, "ringtimeout")) {
18143 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18144 } else if (!strcasecmp(v->name, "prewink")) {
18145 confp->timing.prewinktime = atoi(v->value);
18146 } else if (!strcasecmp(v->name, "preflash")) {
18147 confp->timing.preflashtime = atoi(v->value);
18148 } else if (!strcasecmp(v->name, "wink")) {
18149 confp->timing.winktime = atoi(v->value);
18150 } else if (!strcasecmp(v->name, "flash")) {
18151 confp->timing.flashtime = atoi(v->value);
18152 } else if (!strcasecmp(v->name, "start")) {
18153 confp->timing.starttime = atoi(v->value);
18154 } else if (!strcasecmp(v->name, "rxwink")) {
18155 confp->timing.rxwinktime = atoi(v->value);
18156 } else if (!strcasecmp(v->name, "rxflash")) {
18157 confp->timing.rxflashtime = atoi(v->value);
18158 } else if (!strcasecmp(v->name, "debounce")) {
18159 confp->timing.debouncetime = atoi(v->value);
18160 } else if (!strcasecmp(v->name, "toneduration")) {
18161 int toneduration;
18162 int ctlfd;
18163 int res;
18164 struct dahdi_dialparams dps;
18165
18166 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18167 if (ctlfd == -1) {
18168 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18169 return -1;
18170 }
18171
18172 toneduration = atoi(v->value);
18173 if (toneduration > -1) {
18174 memset(&dps, 0, sizeof(dps));
18175
18176 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18177 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18178 if (res < 0) {
18179 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18180 close(ctlfd);
18181 return -1;
18182 }
18183 }
18184 close(ctlfd);
18185 } else if (!strcasecmp(v->name, "defaultcic")) {
18186 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18187 } else if (!strcasecmp(v->name, "defaultozz")) {
18188 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18189 } else if (!strcasecmp(v->name, "mwilevel")) {
18190 mwilevel = atoi(v->value);
18191 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18192 dtmfcid_level = atoi(v->value);
18193 } else if (!strcasecmp(v->name, "reportalarms")) {
18194 if (!strcasecmp(v->value, "all"))
18195 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18196 if (!strcasecmp(v->value, "none"))
18197 report_alarms = 0;
18198 else if (!strcasecmp(v->value, "channels"))
18199 report_alarms = REPORT_CHANNEL_ALARMS;
18200 else if (!strcasecmp(v->value, "spans"))
18201 report_alarms = REPORT_SPAN_ALARMS;
18202 }
18203 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18204 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18205 }
18206
18207
18208 if (confp->chan.vars) {
18209 ast_variables_destroy(confp->chan.vars);
18210 confp->chan.vars = NULL;
18211 }
18212
18213 if (dahdichan) {
18214
18215 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18216 &found_pseudo)) {
18217 if (confp->ignore_failed_channels) {
18218 ast_log(LOG_WARNING,
18219 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18220 dahdichan->value);
18221 } else {
18222 return -1;
18223 }
18224 }
18225 }
18226
18227
18228 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18229 if (!tmp->destroy && tmp->span != y) {
18230 tmp->manages_span_alarms = 1;
18231 y = tmp->span;
18232 } else {
18233 tmp->manages_span_alarms = 0;
18234 }
18235 }
18236
18237
18238
18239 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18240
18241
18242
18243
18244 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18245
18246 if (conf.chan.cc_params) {
18247 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18248 } else {
18249 tmp = NULL;
18250 }
18251 if (tmp) {
18252 ast_verb(3, "Automatically generated pseudo channel\n");
18253 } else {
18254 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18255 }
18256 ast_cc_config_params_destroy(conf.chan.cc_params);
18257 }
18258 return 0;
18259 }
18260
18261
18262
18263
18264
18265
18266
18267
18268
18269
18270
18271 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18272 {
18273 struct ast_cc_config_params *cc_params;
18274
18275 cc_params = dest->chan.cc_params;
18276 *dest = *src;
18277 dest->chan.cc_params = cc_params;
18278 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18279 }
18280
18281
18282
18283
18284
18285
18286
18287
18288
18289
18290
18291
18292
18293 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18294 {
18295 struct ast_config *cfg;
18296 struct ast_config *ucfg;
18297 struct ast_variable *v;
18298 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18299 const char *chans;
18300 const char *cat;
18301 int res;
18302
18303 #ifdef HAVE_PRI
18304 char *c;
18305 int spanno;
18306 int i;
18307 int logicalspan;
18308 int trunkgroup;
18309 int dchannels[SIG_PRI_NUM_DCHANS];
18310 #endif
18311 int have_cfg_now;
18312 static int had_cfg_before = 1;
18313
18314 cfg = ast_config_load(config, config_flags);
18315 have_cfg_now = !!cfg;
18316 if (!cfg) {
18317
18318 if (had_cfg_before) {
18319 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18320 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18321 }
18322 cfg = ast_config_new();
18323 if (!cfg) {
18324 return 0;
18325 }
18326 ucfg = ast_config_load("users.conf", config_flags);
18327 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18328 ast_config_destroy(cfg);
18329 return 0;
18330 }
18331 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18332 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18333 ast_config_destroy(cfg);
18334 return 0;
18335 }
18336 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18337 ucfg = ast_config_load("users.conf", config_flags);
18338 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18339 return 0;
18340 }
18341 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18342 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18343 return 0;
18344 }
18345 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18346 cfg = ast_config_load(config, config_flags);
18347 have_cfg_now = !!cfg;
18348 if (!cfg) {
18349 if (had_cfg_before) {
18350
18351 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18352 ast_config_destroy(ucfg);
18353 return 0;
18354 }
18355 cfg = ast_config_new();
18356 if (!cfg) {
18357 ast_config_destroy(ucfg);
18358 return 0;
18359 }
18360 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18361 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18362 ast_config_destroy(ucfg);
18363 return 0;
18364 }
18365 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18366 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18367 return 0;
18368 } else {
18369 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18370 ucfg = ast_config_load("users.conf", config_flags);
18371 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18372 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18373 ast_config_destroy(cfg);
18374 return 0;
18375 }
18376 }
18377 had_cfg_before = have_cfg_now;
18378
18379
18380 ast_mutex_lock(&iflock);
18381 #ifdef HAVE_PRI
18382 if (reload != 1) {
18383
18384 v = ast_variable_browse(cfg, "trunkgroups");
18385 while (v) {
18386 if (!strcasecmp(v->name, "trunkgroup")) {
18387 trunkgroup = atoi(v->value);
18388 if (trunkgroup > 0) {
18389 if ((c = strchr(v->value, ','))) {
18390 i = 0;
18391 memset(dchannels, 0, sizeof(dchannels));
18392 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18393 dchannels[i] = atoi(c + 1);
18394 if (dchannels[i] < 0) {
18395 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);
18396 } else
18397 i++;
18398 c = strchr(c + 1, ',');
18399 }
18400 if (i) {
18401 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18402 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);
18403 } else
18404 ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
18405 } else
18406 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18407 } else
18408 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18409 } else
18410 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18411 } else if (!strcasecmp(v->name, "spanmap")) {
18412 spanno = atoi(v->value);
18413 if (spanno > 0) {
18414 if ((c = strchr(v->value, ','))) {
18415 trunkgroup = atoi(c + 1);
18416 if (trunkgroup > 0) {
18417 if ((c = strchr(c + 1, ',')))
18418 logicalspan = atoi(c + 1);
18419 else
18420 logicalspan = 0;
18421 if (logicalspan >= 0) {
18422 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18423 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18424 } else
18425 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18426 } else
18427 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);
18428 } else
18429 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18430 } else
18431 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18432 } else
18433 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18434 } else {
18435 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18436 }
18437 v = v->next;
18438 }
18439 }
18440 #endif
18441
18442
18443 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18444
18445 mwimonitornotify[0] = '\0';
18446
18447 v = ast_variable_browse(cfg, "channels");
18448 if ((res = process_dahdi(base_conf,
18449 "" ,
18450 v, reload, 0))) {
18451 ast_mutex_unlock(&iflock);
18452 ast_config_destroy(cfg);
18453 if (ucfg) {
18454 ast_config_destroy(ucfg);
18455 }
18456 return res;
18457 }
18458
18459
18460 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18461
18462
18463
18464 if (!strcasecmp(cat, "general") ||
18465 !strcasecmp(cat, "trunkgroups") ||
18466 !strcasecmp(cat, "globals") ||
18467 !strcasecmp(cat, "channels")) {
18468 continue;
18469 }
18470
18471 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18472 if (ast_strlen_zero(chans)) {
18473
18474 continue;
18475 }
18476
18477
18478 deep_copy_dahdi_chan_conf(conf, base_conf);
18479
18480 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18481 ast_mutex_unlock(&iflock);
18482 ast_config_destroy(cfg);
18483 if (ucfg) {
18484 ast_config_destroy(ucfg);
18485 }
18486 return res;
18487 }
18488 }
18489
18490 ast_config_destroy(cfg);
18491
18492 if (ucfg) {
18493
18494 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18495 process_dahdi(base_conf,
18496 "" ,
18497 ast_variable_browse(ucfg, "general"), 1, 0);
18498
18499 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18500 if (!strcasecmp(cat, "general")) {
18501 continue;
18502 }
18503
18504 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18505 if (ast_strlen_zero(chans)) {
18506
18507 continue;
18508 }
18509
18510
18511 deep_copy_dahdi_chan_conf(conf, base_conf);
18512
18513 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18514 ast_config_destroy(ucfg);
18515 ast_mutex_unlock(&iflock);
18516 return res;
18517 }
18518 }
18519 ast_config_destroy(ucfg);
18520 }
18521 ast_mutex_unlock(&iflock);
18522
18523 #ifdef HAVE_PRI
18524 if (reload != 1) {
18525 int x;
18526 for (x = 0; x < NUM_SPANS; x++) {
18527 if (pris[x].pri.pvts[0]) {
18528 prepare_pri(pris + x);
18529 if (sig_pri_start_pri(&pris[x].pri)) {
18530 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18531 return -1;
18532 } else
18533 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18534 }
18535 }
18536 }
18537 #endif
18538 #if defined(HAVE_SS7)
18539 if (reload != 1) {
18540 int x;
18541 for (x = 0; x < NUM_SPANS; x++) {
18542 if (linksets[x].ss7.ss7) {
18543 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18544 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18545 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18546 return -1;
18547 } else
18548 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18549 }
18550 }
18551 }
18552 #endif
18553 #ifdef HAVE_OPENR2
18554 if (reload != 1) {
18555 int x;
18556 for (x = 0; x < r2links_count; x++) {
18557 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18558 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18559 return -1;
18560 } else {
18561 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18562 }
18563 }
18564 }
18565 #endif
18566
18567 restart_monitor();
18568 return 0;
18569 }
18570
18571
18572
18573
18574
18575
18576
18577
18578
18579
18580 static int setup_dahdi(int reload)
18581 {
18582 int res;
18583 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18584 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18585 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18586
18587 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18588 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18589 } else {
18590 res = -1;
18591 }
18592 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18593 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18594 ast_cc_config_params_destroy(conf.chan.cc_params);
18595
18596 return res;
18597 }
18598
18599
18600
18601
18602
18603
18604
18605
18606 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18607 struct ast_data *data_root)
18608 {
18609 int ctl, res, span;
18610 struct ast_data *data_span, *data_alarms;
18611 struct dahdi_spaninfo s;
18612
18613 ctl = open("/dev/dahdi/ctl", O_RDWR);
18614 if (ctl < 0) {
18615 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18616 return -1;
18617 }
18618 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18619 s.spanno = span;
18620 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18621 if (res) {
18622 continue;
18623 }
18624
18625 data_span = ast_data_add_node(data_root, "span");
18626 if (!data_span) {
18627 continue;
18628 }
18629 ast_data_add_str(data_span, "description", s.desc);
18630
18631
18632 data_alarms = ast_data_add_node(data_span, "alarms");
18633 if (!data_alarms) {
18634 continue;
18635 }
18636
18637 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18638 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18639 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18640 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18641 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18642 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18643
18644 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18645 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18646 ast_data_add_int(data_span, "crc4", s.crc4count);
18647 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18648 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18649 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18650 "CAS");
18651 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18652 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18653 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18654 "Unknown");
18655 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18656 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18657 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18658 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18659
18660
18661 if (!ast_data_search_match(search, data_span)) {
18662 ast_data_remove_node(data_root, data_span);
18663 }
18664 }
18665 close(ctl);
18666
18667 return 0;
18668 }
18669
18670
18671
18672
18673
18674
18675
18676
18677 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18678 struct ast_data *data_root)
18679 {
18680 struct dahdi_pvt *tmp;
18681 struct ast_data *data_channel;
18682
18683 ast_mutex_lock(&iflock);
18684 for (tmp = iflist; tmp; tmp = tmp->next) {
18685 data_channel = ast_data_add_node(data_root, "channel");
18686 if (!data_channel) {
18687 continue;
18688 }
18689
18690 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18691
18692
18693 if (!ast_data_search_match(search, data_channel)) {
18694 ast_data_remove_node(data_root, data_channel);
18695 }
18696 }
18697 ast_mutex_unlock(&iflock);
18698
18699 return 0;
18700 }
18701
18702
18703
18704
18705
18706
18707
18708
18709 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18710 struct ast_data *data_root)
18711 {
18712 int pseudo_fd = -1;
18713 struct dahdi_versioninfo vi = {
18714 .version = "Unknown",
18715 .echo_canceller = "Unknown"
18716 };
18717
18718 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18719 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18720 return -1;
18721 }
18722
18723 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18724 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18725 }
18726
18727 close(pseudo_fd);
18728
18729 ast_data_add_str(data_root, "value", vi.version);
18730 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18731
18732 return 0;
18733 }
18734
18735 static const struct ast_data_handler dahdi_status_data_provider = {
18736 .version = AST_DATA_HANDLER_VERSION,
18737 .get = dahdi_status_data_provider_get
18738 };
18739
18740 static const struct ast_data_handler dahdi_channels_data_provider = {
18741 .version = AST_DATA_HANDLER_VERSION,
18742 .get = dahdi_channels_data_provider_get
18743 };
18744
18745 static const struct ast_data_handler dahdi_version_data_provider = {
18746 .version = AST_DATA_HANDLER_VERSION,
18747 .get = dahdi_version_data_provider_get
18748 };
18749
18750 static const struct ast_data_entry dahdi_data_providers[] = {
18751 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18752 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18753 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18754 };
18755
18756 static int load_module(void)
18757 {
18758 int res;
18759 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18760 int y;
18761 #endif
18762
18763 #ifdef HAVE_PRI
18764 memset(pris, 0, sizeof(pris));
18765 for (y = 0; y < NUM_SPANS; y++) {
18766 sig_pri_init_pri(&pris[y].pri);
18767 }
18768 pri_set_error(dahdi_pri_error);
18769 pri_set_message(dahdi_pri_message);
18770 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18771 #ifdef HAVE_PRI_PROG_W_CAUSE
18772 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18773 #endif
18774 #if defined(HAVE_PRI_CCSS)
18775 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18776 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18777 __unload_module();
18778 return AST_MODULE_LOAD_FAILURE;
18779 }
18780 #endif
18781 if (sig_pri_load(
18782 #if defined(HAVE_PRI_CCSS)
18783 dahdi_pri_cc_type
18784 #else
18785 NULL
18786 #endif
18787 )) {
18788 __unload_module();
18789 return AST_MODULE_LOAD_FAILURE;
18790 }
18791 #endif
18792 #if defined(HAVE_SS7)
18793 memset(linksets, 0, sizeof(linksets));
18794 for (y = 0; y < NUM_SPANS; y++) {
18795 sig_ss7_init_linkset(&linksets[y].ss7);
18796 }
18797 ss7_set_error(dahdi_ss7_error);
18798 ss7_set_message(dahdi_ss7_message);
18799 #endif
18800 res = setup_dahdi(0);
18801
18802 if (res)
18803 return AST_MODULE_LOAD_DECLINE;
18804 if (ast_channel_register(&dahdi_tech)) {
18805 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18806 __unload_module();
18807 return AST_MODULE_LOAD_FAILURE;
18808 }
18809 #ifdef HAVE_PRI
18810 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18811 #endif
18812 #if defined(HAVE_SS7)
18813 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18814 #endif
18815 #ifdef HAVE_OPENR2
18816 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18817 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18818 #endif
18819
18820 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18821
18822 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18823 memset(round_robin, 0, sizeof(round_robin));
18824 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18825 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18826 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18827 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18828 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18829 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18830 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18831
18832 ast_cond_init(&ss_thread_complete, NULL);
18833
18834 return res;
18835 }
18836
18837 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18838 {
18839 #define END_SILENCE_LEN 400
18840 #define HEADER_MS 50
18841 #define TRAILER_MS 5
18842 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18843 #define ASCII_BYTES_PER_CHAR 80
18844
18845 unsigned char *buf,*mybuf;
18846 struct dahdi_pvt *p = c->tech_pvt;
18847 struct pollfd fds[1];
18848 int size,res,fd,len,x;
18849 int bytes=0;
18850
18851 float cr = 1.0;
18852 float ci = 0.0;
18853 float scont = 0.0;
18854 int idx;
18855
18856 idx = dahdi_get_index(c, p, 0);
18857 if (idx < 0) {
18858 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18859 return -1;
18860 }
18861 if (!text[0]) return(0);
18862 if ((!p->tdd) && (!p->mate)) return(0);
18863 if (p->mate)
18864 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18865 else
18866 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18867 if (!buf)
18868 return -1;
18869 mybuf = buf;
18870 if (p->mate) {
18871 int codec = AST_LAW(p);
18872 for (x = 0; x < HEADER_MS; x++) {
18873 PUT_CLID_MARKMS;
18874 }
18875
18876 for (x = 0; text[x]; x++) {
18877 PUT_CLID(text[x]);
18878 }
18879 for (x = 0; x < TRAILER_MS; x++) {
18880 PUT_CLID_MARKMS;
18881 }
18882 len = bytes;
18883 buf = mybuf;
18884 } else {
18885 len = tdd_generate(p->tdd, buf, text);
18886 if (len < 1) {
18887 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18888 ast_free(mybuf);
18889 return -1;
18890 }
18891 }
18892 memset(buf + len, 0x7f, END_SILENCE_LEN);
18893 len += END_SILENCE_LEN;
18894 fd = p->subs[idx].dfd;
18895 while (len) {
18896 if (ast_check_hangup(c)) {
18897 ast_free(mybuf);
18898 return -1;
18899 }
18900 size = len;
18901 if (size > READ_SIZE)
18902 size = READ_SIZE;
18903 fds[0].fd = fd;
18904 fds[0].events = POLLOUT | POLLPRI;
18905 fds[0].revents = 0;
18906 res = poll(fds, 1, -1);
18907 if (!res) {
18908 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18909 continue;
18910 }
18911
18912 if (fds[0].revents & POLLPRI) {
18913 ast_free(mybuf);
18914 return -1;
18915 }
18916 if (!(fds[0].revents & POLLOUT)) {
18917 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18918 continue;
18919 }
18920 res = write(fd, buf, size);
18921 if (res != size) {
18922 if (res == -1) {
18923 ast_free(mybuf);
18924 return -1;
18925 }
18926 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18927 break;
18928 }
18929 len -= size;
18930 buf += size;
18931 }
18932 ast_free(mybuf);
18933 return(0);
18934 }
18935
18936
18937 static int reload(void)
18938 {
18939 int res = 0;
18940
18941 res = setup_dahdi(1);
18942 if (res) {
18943 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18944 return -1;
18945 }
18946 return 0;
18947 }
18948
18949
18950
18951
18952
18953 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18954 .load = load_module,
18955 .unload = unload_module,
18956 .reload = reload,
18957 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18958 .nonoptreq = "res_smdi",
18959 );