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 busy_tonelength;
01137
01138
01139
01140
01141 int busy_quietlength;
01142
01143
01144
01145
01146 int callprogress;
01147
01148
01149
01150
01151 int waitfordialtone;
01152 struct timeval waitingfordt;
01153 struct timeval flashtime;
01154
01155 struct ast_dsp *dsp;
01156
01157 struct dahdi_dialoperation dop;
01158 int whichwink;
01159
01160 char finaldial[64];
01161 char accountcode[AST_MAX_ACCOUNT_CODE];
01162 int amaflags;
01163 struct tdd_state *tdd;
01164
01165 char call_forward[AST_MAX_EXTENSION];
01166
01167
01168
01169
01170 char mailbox[AST_MAX_EXTENSION];
01171
01172 struct ast_event_sub *mwi_event_sub;
01173
01174 char dialdest[256];
01175 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01176 struct dahdi_vmwi_info mwisend_setting;
01177 unsigned int mwisend_fsk: 1;
01178 unsigned int mwisend_rpas:1;
01179 #endif
01180 int distinctivering;
01181 int dtmfrelax;
01182
01183 int fake_event;
01184
01185
01186
01187
01188 int polarityonanswerdelay;
01189
01190 struct timeval polaritydelaytv;
01191
01192
01193
01194
01195 int sendcalleridafter;
01196
01197 int polarity;
01198
01199 int dsp_features;
01200 #if defined(HAVE_SS7)
01201
01202 struct sig_ss7_linkset *ss7;
01203 #endif
01204 #ifdef HAVE_OPENR2
01205 struct dahdi_mfcr2 *mfcr2;
01206 openr2_chan_t *r2chan;
01207 openr2_calling_party_category_t mfcr2_recvd_category;
01208 openr2_calling_party_category_t mfcr2_category;
01209 int mfcr2_dnis_index;
01210 int mfcr2_ani_index;
01211 int mfcr2call:1;
01212 int mfcr2_answer_pending:1;
01213 int mfcr2_charge_calls:1;
01214 int mfcr2_allow_collect_calls:1;
01215 int mfcr2_forced_release:1;
01216 int mfcr2_dnis_matched:1;
01217 int mfcr2_call_accepted:1;
01218 int mfcr2_progress:1;
01219 int mfcr2_accept_on_offer:1;
01220 #endif
01221
01222 char begindigit;
01223
01224 int muting;
01225 void *sig_pvt;
01226 struct ast_cc_config_params *cc_params;
01227
01228
01229
01230
01231
01232
01233 char dialstring[AST_CHANNEL_NAME];
01234 };
01235
01236 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01237 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01238 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01239 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01240 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01241 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01242 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01243 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01244 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01245 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01246 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01247 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01248 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01249 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01250 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01251 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01252 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01253 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01254 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01255 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01256 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01257 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01287 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01288 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01289 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01291 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01292 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01293 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01294 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01295 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01296 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01297 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01298 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01299 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01300 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01301 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01302 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01303 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01304
01305 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01306
01307 static struct dahdi_pvt *iflist = NULL;
01308 static struct dahdi_pvt *ifend = NULL;
01309
01310 #if defined(HAVE_PRI)
01311 static struct dahdi_parms_pseudo {
01312 int buf_no;
01313 int buf_policy;
01314 int faxbuf_no;
01315 int faxbuf_policy;
01316 } dahdi_pseudo_parms;
01317 #endif
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329 struct dahdi_chan_conf {
01330 struct dahdi_pvt chan;
01331 #ifdef HAVE_PRI
01332 struct dahdi_pri pri;
01333 #endif
01334
01335 #if defined(HAVE_SS7)
01336 struct dahdi_ss7 ss7;
01337 #endif
01338
01339 #ifdef HAVE_OPENR2
01340 struct dahdi_mfcr2_conf mfcr2;
01341 #endif
01342 struct dahdi_params timing;
01343 int is_sig_auto;
01344
01345 int ignore_failed_channels;
01346
01347
01348
01349
01350
01351 char smdi_port[SMDI_MAX_FILENAME_LEN];
01352 };
01353
01354
01355 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01356 {
01357
01358
01359
01360 struct dahdi_chan_conf conf = {
01361 #ifdef HAVE_PRI
01362 .pri.pri = {
01363 .nsf = PRI_NSF_NONE,
01364 .switchtype = PRI_SWITCH_NI2,
01365 .dialplan = PRI_UNKNOWN + 1,
01366 .localdialplan = PRI_NATIONAL_ISDN + 1,
01367 .nodetype = PRI_CPE,
01368 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01369 .inband_on_setup_ack = 1,
01370 .inband_on_proceeding = 1,
01371
01372 #if defined(HAVE_PRI_CCSS)
01373 .cc_ptmp_recall_mode = 1,
01374 .cc_qsig_signaling_link_req = 1,
01375 .cc_qsig_signaling_link_rsp = 1,
01376 #endif
01377
01378 .minunused = 2,
01379 .idleext = "",
01380 .idledial = "",
01381 .internationalprefix = "",
01382 .nationalprefix = "",
01383 .localprefix = "",
01384 .privateprefix = "",
01385 .unknownprefix = "",
01386 .resetinterval = -1,
01387 },
01388 #endif
01389 #if defined(HAVE_SS7)
01390 .ss7.ss7 = {
01391 .called_nai = SS7_NAI_NATIONAL,
01392 .calling_nai = SS7_NAI_NATIONAL,
01393 .internationalprefix = "",
01394 .nationalprefix = "",
01395 .subscriberprefix = "",
01396 .unknownprefix = ""
01397 },
01398 #endif
01399 #ifdef HAVE_OPENR2
01400 .mfcr2 = {
01401 .variant = OR2_VAR_ITU,
01402 .mfback_timeout = -1,
01403 .metering_pulse_timeout = -1,
01404 .max_ani = 10,
01405 .max_dnis = 4,
01406 .get_ani_first = -1,
01407 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01408 .skip_category_request = -1,
01409 #endif
01410 .call_files = 0,
01411 .allow_collect_calls = 0,
01412 .charge_calls = 1,
01413 .accept_on_offer = 1,
01414 .forced_release = 0,
01415 .double_answer = 0,
01416 .immediate_accept = -1,
01417 .logdir = "",
01418 .r2proto_file = "",
01419 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01420 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01421 },
01422 #endif
01423 .chan = {
01424 .context = "default",
01425 .cid_num = "",
01426 .cid_name = "",
01427 .cid_tag = "",
01428 .mohinterpret = "default",
01429 .mohsuggest = "",
01430 .parkinglot = "",
01431 .transfertobusy = 1,
01432
01433 .cid_signalling = CID_SIG_BELL,
01434 .cid_start = CID_START_RING,
01435 .dahditrcallerid = 0,
01436 .use_callerid = 1,
01437 .sig = -1,
01438 .outsigmod = -1,
01439
01440 .cid_rxgain = +5.0,
01441
01442 .tonezone = -1,
01443
01444 .echocancel.head.tap_length = 1,
01445
01446 .busycount = 3,
01447
01448 .accountcode = "",
01449
01450 .mailbox = "",
01451
01452 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01453 .mwisend_fsk = 1,
01454 #endif
01455 .polarityonanswerdelay = 600,
01456
01457 .sendcalleridafter = DEFAULT_CIDRINGS,
01458
01459 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01460 .buf_no = numbufs,
01461 .usefaxbuffers = 0,
01462 .cc_params = ast_cc_config_params_init(),
01463 },
01464 .timing = {
01465 .prewinktime = -1,
01466 .preflashtime = -1,
01467 .winktime = -1,
01468 .flashtime = -1,
01469 .starttime = -1,
01470 .rxwinktime = -1,
01471 .rxflashtime = -1,
01472 .debouncetime = -1
01473 },
01474 .is_sig_auto = 1,
01475 .smdi_port = "/dev/ttyS0",
01476 };
01477
01478 return conf;
01479 }
01480
01481
01482 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01483 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01484 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01485 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01486 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01487 static int dahdi_hangup(struct ast_channel *ast);
01488 static int dahdi_answer(struct ast_channel *ast);
01489 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01490 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01491 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01492 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01493 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01494 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01495 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01496 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01497 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01498 static int dahdi_devicestate(void *data);
01499 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01500
01501 static const struct ast_channel_tech dahdi_tech = {
01502 .type = "DAHDI",
01503 .description = tdesc,
01504 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01505 .requester = dahdi_request,
01506 .send_digit_begin = dahdi_digit_begin,
01507 .send_digit_end = dahdi_digit_end,
01508 .send_text = dahdi_sendtext,
01509 .call = dahdi_call,
01510 .hangup = dahdi_hangup,
01511 .answer = dahdi_answer,
01512 .read = dahdi_read,
01513 .write = dahdi_write,
01514 .bridge = dahdi_bridge,
01515 .exception = dahdi_exception,
01516 .indicate = dahdi_indicate,
01517 .fixup = dahdi_fixup,
01518 .setoption = dahdi_setoption,
01519 .queryoption = dahdi_queryoption,
01520 .func_channel_read = dahdi_func_read,
01521 .func_channel_write = dahdi_func_write,
01522 .devicestate = dahdi_devicestate,
01523 .cc_callback = dahdi_cc_callback,
01524 };
01525
01526 #define GET_CHANNEL(p) ((p)->channel)
01527
01528 #define SIG_PRI_LIB_HANDLE_CASES \
01529 SIG_PRI: \
01530 case SIG_BRI: \
01531 case SIG_BRI_PTMP
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542 static inline int dahdi_sig_pri_lib_handles(int signaling)
01543 {
01544 int handles;
01545
01546 switch (signaling) {
01547 case SIG_PRI_LIB_HANDLE_CASES:
01548 handles = 1;
01549 break;
01550 default:
01551 handles = 0;
01552 break;
01553 }
01554
01555 return handles;
01556 }
01557
01558 static int analog_lib_handles(int signalling, int radio, int oprmode)
01559 {
01560 switch (signalling) {
01561 case SIG_FXOLS:
01562 case SIG_FXOGS:
01563 case SIG_FXOKS:
01564 case SIG_FXSLS:
01565 case SIG_FXSGS:
01566 case SIG_FXSKS:
01567 case SIG_EMWINK:
01568 case SIG_EM:
01569 case SIG_EM_E1:
01570 case SIG_FEATD:
01571 case SIG_FEATDMF:
01572 case SIG_E911:
01573 case SIG_FGC_CAMA:
01574 case SIG_FGC_CAMAMF:
01575 case SIG_FEATB:
01576 case SIG_SFWINK:
01577 case SIG_SF:
01578 case SIG_SF_FEATD:
01579 case SIG_SF_FEATDMF:
01580 case SIG_FEATDMF_TA:
01581 case SIG_SF_FEATB:
01582 break;
01583 default:
01584
01585 return 0;
01586 }
01587
01588 if (radio) {
01589 return 0;
01590 }
01591
01592 if (oprmode) {
01593 return 0;
01594 }
01595
01596 return 1;
01597 }
01598
01599 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01600 {
01601 switch (sig) {
01602 case SIG_FXOLS:
01603 return ANALOG_SIG_FXOLS;
01604 case SIG_FXOGS:
01605 return ANALOG_SIG_FXOGS;
01606 case SIG_FXOKS:
01607 return ANALOG_SIG_FXOKS;
01608 case SIG_FXSLS:
01609 return ANALOG_SIG_FXSLS;
01610 case SIG_FXSGS:
01611 return ANALOG_SIG_FXSGS;
01612 case SIG_FXSKS:
01613 return ANALOG_SIG_FXSKS;
01614 case SIG_EMWINK:
01615 return ANALOG_SIG_EMWINK;
01616 case SIG_EM:
01617 return ANALOG_SIG_EM;
01618 case SIG_EM_E1:
01619 return ANALOG_SIG_EM_E1;
01620 case SIG_FEATD:
01621 return ANALOG_SIG_FEATD;
01622 case SIG_FEATDMF:
01623 return ANALOG_SIG_FEATDMF;
01624 case SIG_E911:
01625 return SIG_E911;
01626 case SIG_FGC_CAMA:
01627 return ANALOG_SIG_FGC_CAMA;
01628 case SIG_FGC_CAMAMF:
01629 return ANALOG_SIG_FGC_CAMAMF;
01630 case SIG_FEATB:
01631 return ANALOG_SIG_FEATB;
01632 case SIG_SFWINK:
01633 return ANALOG_SIG_SFWINK;
01634 case SIG_SF:
01635 return ANALOG_SIG_SF;
01636 case SIG_SF_FEATD:
01637 return ANALOG_SIG_SF_FEATD;
01638 case SIG_SF_FEATDMF:
01639 return ANALOG_SIG_SF_FEATDMF;
01640 case SIG_FEATDMF_TA:
01641 return ANALOG_SIG_FEATDMF_TA;
01642 case SIG_SF_FEATB:
01643 return ANALOG_SIG_FEATB;
01644 default:
01645 return -1;
01646 }
01647 }
01648
01649
01650 static int analog_tone_to_dahditone(enum analog_tone tone)
01651 {
01652 switch (tone) {
01653 case ANALOG_TONE_RINGTONE:
01654 return DAHDI_TONE_RINGTONE;
01655 case ANALOG_TONE_STUTTER:
01656 return DAHDI_TONE_STUTTER;
01657 case ANALOG_TONE_CONGESTION:
01658 return DAHDI_TONE_CONGESTION;
01659 case ANALOG_TONE_DIALTONE:
01660 return DAHDI_TONE_DIALTONE;
01661 case ANALOG_TONE_DIALRECALL:
01662 return DAHDI_TONE_DIALRECALL;
01663 case ANALOG_TONE_INFO:
01664 return DAHDI_TONE_INFO;
01665 default:
01666 return -1;
01667 }
01668 }
01669
01670 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01671 {
01672 int index;
01673
01674 switch (analogsub) {
01675 case ANALOG_SUB_REAL:
01676 index = SUB_REAL;
01677 break;
01678 case ANALOG_SUB_CALLWAIT:
01679 index = SUB_CALLWAIT;
01680 break;
01681 case ANALOG_SUB_THREEWAY:
01682 index = SUB_THREEWAY;
01683 break;
01684 default:
01685 ast_log(LOG_ERROR, "Unidentified sub!\n");
01686 index = SUB_REAL;
01687 }
01688
01689 return index;
01690 }
01691
01692 static enum analog_event dahdievent_to_analogevent(int event);
01693 static int bump_gains(struct dahdi_pvt *p);
01694 static int dahdi_setlinear(int dfd, int linear);
01695
01696 static int my_start_cid_detect(void *pvt, int cid_signalling)
01697 {
01698 struct dahdi_pvt *p = pvt;
01699 int index = SUB_REAL;
01700 p->cs = callerid_new(cid_signalling);
01701 if (!p->cs) {
01702 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01703 return -1;
01704 }
01705 bump_gains(p);
01706 dahdi_setlinear(p->subs[index].dfd, 0);
01707
01708 return 0;
01709 }
01710
01711 static int my_stop_cid_detect(void *pvt)
01712 {
01713 struct dahdi_pvt *p = pvt;
01714 int index = SUB_REAL;
01715 if (p->cs)
01716 callerid_free(p->cs);
01717 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01718 return 0;
01719 }
01720
01721 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01722 {
01723 struct dahdi_pvt *p = pvt;
01724 struct analog_pvt *analog_p = p->sig_pvt;
01725 struct pollfd poller;
01726 char *name, *num;
01727 int index = SUB_REAL;
01728 int res;
01729 unsigned char buf[256];
01730 int flags;
01731
01732 poller.fd = p->subs[SUB_REAL].dfd;
01733 poller.events = POLLPRI | POLLIN;
01734 poller.revents = 0;
01735
01736 res = poll(&poller, 1, timeout);
01737
01738 if (poller.revents & POLLPRI) {
01739 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01740 return 1;
01741 }
01742
01743 if (poller.revents & POLLIN) {
01744
01745
01746
01747
01748
01749 res = read(p->subs[index].dfd, buf, sizeof(buf));
01750 if (res < 0) {
01751 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01752 return -1;
01753 }
01754
01755 if (analog_p->ringt > 0) {
01756 if (!(--analog_p->ringt)) {
01757
01758 return -1;
01759 }
01760 }
01761
01762 if (p->cid_signalling == CID_SIG_V23_JP) {
01763 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01764 } else {
01765 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01766 }
01767 if (res < 0) {
01768
01769
01770
01771
01772 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01773 return -1;
01774 }
01775
01776 if (res == 1) {
01777 callerid_get(p->cs, &name, &num, &flags);
01778 if (name)
01779 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01780 if (num)
01781 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01782
01783 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01784 return 0;
01785 }
01786 }
01787
01788 *ev = ANALOG_EVENT_NONE;
01789 return 2;
01790 }
01791
01792 static const char *event2str(int event);
01793 static int restore_gains(struct dahdi_pvt *p);
01794
01795 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01796 {
01797 unsigned char buf[256];
01798 int distMatches;
01799 int curRingData[RING_PATTERNS];
01800 int receivedRingT;
01801 int counter1;
01802 int counter;
01803 int i;
01804 int res;
01805 int checkaftercid = 0;
01806
01807 struct dahdi_pvt *p = pvt;
01808 struct analog_pvt *analog_p = p->sig_pvt;
01809
01810 if (ringdata == NULL) {
01811 ringdata = curRingData;
01812 } else {
01813 checkaftercid = 1;
01814 }
01815
01816
01817
01818 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01819
01820 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01821 ringdata[receivedRingT] = 0;
01822 receivedRingT = 0;
01823 if (checkaftercid && distinctiveringaftercid)
01824 ast_verb(3, "Detecting post-CID distinctive ring\n");
01825
01826 else if (strcmp(p->context,p->defcontext) != 0) {
01827 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01828 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01829 }
01830
01831 for (;;) {
01832 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01833 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01834 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01835 ast_hangup(chan);
01836 return 1;
01837 }
01838 if (i & DAHDI_IOMUX_SIGEVENT) {
01839 res = dahdi_get_event(p->subs[idx].dfd);
01840 if (res == DAHDI_EVENT_NOALARM) {
01841 p->inalarm = 0;
01842 analog_p->inalarm = 0;
01843 }
01844 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01845 res = 0;
01846
01847
01848 ringdata[receivedRingT] = analog_p->ringt;
01849
01850 if (analog_p->ringt < analog_p->ringt_base/2)
01851 break;
01852
01853
01854 if (++receivedRingT == RING_PATTERNS)
01855 break;
01856 } else if (i & DAHDI_IOMUX_READ) {
01857 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01858 if (res < 0) {
01859 if (errno != ELAST) {
01860 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01861 ast_hangup(chan);
01862 return 1;
01863 }
01864 break;
01865 }
01866 if (analog_p->ringt > 0) {
01867 if (!(--analog_p->ringt)) {
01868 res = -1;
01869 break;
01870 }
01871 }
01872 }
01873 }
01874 }
01875 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01876
01877 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01878 for (counter = 0; counter < 3; counter++) {
01879
01880 distMatches = 0;
01881
01882 ast_verb(3, "Checking %d,%d,%d\n",
01883 p->drings.ringnum[counter].ring[0],
01884 p->drings.ringnum[counter].ring[1],
01885 p->drings.ringnum[counter].ring[2]);
01886 for (counter1 = 0; counter1 < 3; counter1++) {
01887 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01888 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01889 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01890 ringdata[counter1]);
01891 distMatches++;
01892 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01893 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01894 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01895 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01896 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01897 distMatches++;
01898 }
01899 }
01900
01901 if (distMatches == 3) {
01902
01903 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01904 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01905 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01906 break;
01907 }
01908 }
01909 }
01910
01911 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01912 restore_gains(p);
01913
01914 return 0;
01915 }
01916
01917 static int my_stop_callwait(void *pvt)
01918 {
01919 struct dahdi_pvt *p = pvt;
01920 p->callwaitingrepeat = 0;
01921 p->cidcwexpire = 0;
01922 p->cid_suppress_expire = 0;
01923
01924 return 0;
01925 }
01926
01927 static int send_callerid(struct dahdi_pvt *p);
01928 static int save_conference(struct dahdi_pvt *p);
01929 static int restore_conference(struct dahdi_pvt *p);
01930
01931 static int my_callwait(void *pvt)
01932 {
01933 struct dahdi_pvt *p = pvt;
01934 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01935 if (p->cidspill) {
01936 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01937 ast_free(p->cidspill);
01938 }
01939
01940
01941
01942
01943
01944 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01945 return -1;
01946 save_conference(p);
01947
01948 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01949 if (!p->callwaitrings && p->callwaitingcallerid) {
01950 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01951 p->callwaitcas = 1;
01952 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01953 } else {
01954 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01955 p->callwaitcas = 0;
01956 p->cidlen = 2400 + READ_SIZE * 4;
01957 }
01958 p->cidpos = 0;
01959 send_callerid(p);
01960
01961 return 0;
01962 }
01963
01964 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01965 {
01966 struct dahdi_pvt *p = pvt;
01967
01968 ast_debug(2, "Starting cid spill\n");
01969
01970 if (p->cidspill) {
01971 ast_log(LOG_WARNING, "cidspill already exists??\n");
01972 ast_free(p->cidspill);
01973 }
01974
01975 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01976 if (cwcid == 0) {
01977 p->cidlen = ast_callerid_generate(p->cidspill,
01978 caller->id.name.str,
01979 caller->id.number.str,
01980 AST_LAW(p));
01981 } else {
01982 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01983 caller->id.name.str, caller->id.number.str);
01984 p->callwaitcas = 0;
01985 p->cidcwexpire = 0;
01986 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01987 caller->id.name.str,
01988 caller->id.number.str,
01989 AST_LAW(p));
01990 p->cidlen += READ_SIZE * 4;
01991 }
01992 p->cidpos = 0;
01993 p->cid_suppress_expire = 0;
01994 send_callerid(p);
01995 }
01996 return 0;
01997 }
01998
01999 static int my_dsp_reset_and_flush_digits(void *pvt)
02000 {
02001 struct dahdi_pvt *p = pvt;
02002 if (p->dsp)
02003 ast_dsp_digitreset(p->dsp);
02004
02005 return 0;
02006 }
02007
02008 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02009 {
02010 struct dahdi_pvt *p = pvt;
02011
02012 if (p->channel == CHAN_PSEUDO)
02013 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02014
02015 if (mode == ANALOG_DIGITMODE_DTMF) {
02016
02017 if (p->hardwaredtmf) {
02018 if (p->dsp) {
02019 ast_dsp_free(p->dsp);
02020 p->dsp = NULL;
02021 }
02022 return 0;
02023 }
02024
02025 if (!p->dsp) {
02026 p->dsp = ast_dsp_new();
02027 if (!p->dsp) {
02028 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02029 return -1;
02030 }
02031 }
02032
02033 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02034 } else if (mode == ANALOG_DIGITMODE_MF) {
02035 if (!p->dsp) {
02036 p->dsp = ast_dsp_new();
02037 if (!p->dsp) {
02038 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02039 return -1;
02040 }
02041 }
02042 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02043 }
02044 return 0;
02045 }
02046
02047 static int dahdi_wink(struct dahdi_pvt *p, int index);
02048
02049 static int my_wink(void *pvt, enum analog_sub sub)
02050 {
02051 struct dahdi_pvt *p = pvt;
02052 int index = analogsub_to_dahdisub(sub);
02053 if (index != SUB_REAL) {
02054 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02055 }
02056 return dahdi_wink(p, index);
02057 }
02058
02059 static void wakeup_sub(struct dahdi_pvt *p, int a);
02060
02061 static int reset_conf(struct dahdi_pvt *p);
02062
02063 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02064
02065 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02066 {
02067 struct ast_frame *f = *dest;
02068 struct dahdi_pvt *p = pvt;
02069 int idx = analogsub_to_dahdisub(analog_index);
02070
02071 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02072 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02073 (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
02074
02075 if (f->subclass.integer == 'f') {
02076 if (f->frametype == AST_FRAME_DTMF_END) {
02077
02078 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02079
02080 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02081 struct dahdi_bufferinfo bi = {
02082 .txbufpolicy = p->faxbuf_policy,
02083 .bufsize = p->bufsize,
02084 .numbufs = p->faxbuf_no
02085 };
02086 int res;
02087
02088 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02089 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02090 } else {
02091 p->bufferoverrideinuse = 1;
02092 }
02093 }
02094 p->faxhandled = 1;
02095 if (p->dsp) {
02096 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02097 ast_dsp_set_features(p->dsp, p->dsp_features);
02098 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02099 }
02100 if (strcmp(ast->exten, "fax")) {
02101 const char *target_context = S_OR(ast->macrocontext, ast->context);
02102
02103
02104
02105
02106
02107 ast_mutex_unlock(&p->lock);
02108 ast_channel_unlock(ast);
02109 if (ast_exists_extension(ast, target_context, "fax", 1,
02110 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02111 ast_channel_lock(ast);
02112 ast_mutex_lock(&p->lock);
02113 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02114
02115 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02116 if (ast_async_goto(ast, target_context, "fax", 1))
02117 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02118 } else {
02119 ast_channel_lock(ast);
02120 ast_mutex_lock(&p->lock);
02121 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02122 }
02123 } else {
02124 ast_debug(1, "Already in a fax extension, not redirecting\n");
02125 }
02126 } else {
02127 ast_debug(1, "Fax already handled\n");
02128 }
02129 dahdi_confmute(p, 0);
02130 }
02131 p->subs[idx].f.frametype = AST_FRAME_NULL;
02132 p->subs[idx].f.subclass.integer = 0;
02133 *dest = &p->subs[idx].f;
02134 }
02135 }
02136
02137 static void my_lock_private(void *pvt)
02138 {
02139 struct dahdi_pvt *p = pvt;
02140 ast_mutex_lock(&p->lock);
02141 }
02142
02143 static void my_unlock_private(void *pvt)
02144 {
02145 struct dahdi_pvt *p = pvt;
02146 ast_mutex_unlock(&p->lock);
02147 }
02148
02149 static void my_deadlock_avoidance_private(void *pvt)
02150 {
02151 struct dahdi_pvt *p = pvt;
02152
02153 DEADLOCK_AVOIDANCE(&p->lock);
02154 }
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02167 {
02168 char ch_name[20];
02169
02170 if (p->channel < CHAN_PSEUDO) {
02171
02172 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02173 } else if (p->channel == CHAN_PSEUDO) {
02174
02175 strcpy(ch_name, "pseudo");
02176 } else {
02177
02178 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02179 }
02180 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02181 "Channel: %s\r\n"
02182 "Uniqueid: %s\r\n"
02183 "DAHDISpan: %d\r\n"
02184 "DAHDIChannel: %s\r\n",
02185 chan->name,
02186 chan->uniqueid,
02187 p->span,
02188 ch_name);
02189 }
02190
02191 #ifdef HAVE_PRI
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02203 {
02204 struct dahdi_pvt *p = pvt;
02205
02206 dahdi_ami_channel_event(p, chan);
02207 }
02208 #endif
02209
02210
02211
02212
02213 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02214 {
02215 struct dahdi_pvt *p = pvt;
02216 int oldval;
02217 int idx = analogsub_to_dahdisub(sub);
02218
02219 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02220 oldval = p->subs[idx].linear;
02221 p->subs[idx].linear = linear_mode ? 1 : 0;
02222 return oldval;
02223 }
02224
02225 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02226 {
02227 struct dahdi_pvt *p = pvt;
02228 int idx = analogsub_to_dahdisub(sub);
02229
02230 p->subs[idx].inthreeway = inthreeway;
02231 }
02232
02233 static int get_alarms(struct dahdi_pvt *p);
02234 static void handle_alarms(struct dahdi_pvt *p, int alms);
02235 static void my_get_and_handle_alarms(void *pvt)
02236 {
02237 int res;
02238 struct dahdi_pvt *p = pvt;
02239
02240 res = get_alarms(p);
02241 handle_alarms(p, res);
02242 }
02243
02244 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02245 {
02246 struct ast_channel *bridged = ast_bridged_channel(chan);
02247
02248 if (bridged && bridged->tech == &dahdi_tech) {
02249 struct dahdi_pvt *p = bridged->tech_pvt;
02250
02251 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02252 return p->sig_pvt;
02253 }
02254 }
02255 return NULL;
02256 }
02257
02258 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02259 {
02260 struct dahdi_pvt *p = pvt;
02261 int dahdi_sub = analogsub_to_dahdisub(sub);
02262 return p->subs[dahdi_sub].dfd;
02263 }
02264
02265 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02266 {
02267 struct dahdi_pvt *p = pvt;
02268
02269
02270 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02271 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02272 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02273 *cid_rings = cidrings[p->distinctivering - 1];
02274 } else {
02275 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02276 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02277 *cid_rings = p->sendcalleridafter;
02278 }
02279 }
02280
02281 static void my_set_alarm(void *pvt, int in_alarm)
02282 {
02283 struct dahdi_pvt *p = pvt;
02284
02285 p->inalarm = in_alarm;
02286 }
02287
02288 static void my_set_dialing(void *pvt, int is_dialing)
02289 {
02290 struct dahdi_pvt *p = pvt;
02291
02292 p->dialing = is_dialing;
02293 }
02294
02295 static void my_set_outgoing(void *pvt, int is_outgoing)
02296 {
02297 struct dahdi_pvt *p = pvt;
02298
02299 p->outgoing = is_outgoing;
02300 }
02301
02302 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02303 static void my_set_digital(void *pvt, int is_digital)
02304 {
02305 struct dahdi_pvt *p = pvt;
02306
02307 p->digital = is_digital;
02308 }
02309 #endif
02310
02311 #if defined(HAVE_SS7)
02312 static void my_set_inservice(void *pvt, int is_inservice)
02313 {
02314 struct dahdi_pvt *p = pvt;
02315
02316 p->inservice = is_inservice;
02317 }
02318 #endif
02319
02320 #if defined(HAVE_SS7)
02321 static void my_set_locallyblocked(void *pvt, int is_blocked)
02322 {
02323 struct dahdi_pvt *p = pvt;
02324
02325 p->locallyblocked = is_blocked;
02326 }
02327 #endif
02328
02329 #if defined(HAVE_SS7)
02330 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02331 {
02332 struct dahdi_pvt *p = pvt;
02333
02334 p->remotelyblocked = is_blocked;
02335 }
02336 #endif
02337
02338 static void my_set_ringtimeout(void *pvt, int ringt)
02339 {
02340 struct dahdi_pvt *p = pvt;
02341 p->ringt = ringt;
02342 }
02343
02344 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02345 {
02346 struct dahdi_pvt *p = pvt;
02347
02348 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02349 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02350 gettimeofday(&p->waitingfordt, NULL);
02351 ast_setstate(ast, AST_STATE_OFFHOOK);
02352 }
02353 }
02354
02355 static int my_check_waitingfordt(void *pvt)
02356 {
02357 struct dahdi_pvt *p = pvt;
02358
02359 if (p->waitingfordt.tv_sec) {
02360 return 1;
02361 }
02362
02363 return 0;
02364 }
02365
02366 static void my_set_confirmanswer(void *pvt, int flag)
02367 {
02368 struct dahdi_pvt *p = pvt;
02369 p->confirmanswer = flag;
02370 }
02371
02372 static int my_check_confirmanswer(void *pvt)
02373 {
02374 struct dahdi_pvt *p = pvt;
02375 if (p->confirmanswer) {
02376 return 1;
02377 }
02378
02379 return 0;
02380 }
02381
02382 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02383 {
02384 struct dahdi_pvt *p = pvt;
02385
02386 p->callwaiting = callwaiting_enable;
02387 }
02388
02389 static void my_cancel_cidspill(void *pvt)
02390 {
02391 struct dahdi_pvt *p = pvt;
02392
02393 ast_free(p->cidspill);
02394 p->cidspill = NULL;
02395 restore_conference(p);
02396 }
02397
02398 static int my_confmute(void *pvt, int mute)
02399 {
02400 struct dahdi_pvt *p = pvt;
02401 return dahdi_confmute(p, mute);
02402 }
02403
02404 static void my_set_pulsedial(void *pvt, int flag)
02405 {
02406 struct dahdi_pvt *p = pvt;
02407 p->pulsedial = flag;
02408 }
02409
02410 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02411 {
02412 struct dahdi_pvt *p = pvt;
02413
02414 p->owner = new_owner;
02415 }
02416
02417 static const char *my_get_orig_dialstring(void *pvt)
02418 {
02419 struct dahdi_pvt *p = pvt;
02420
02421 return p->dialstring;
02422 }
02423
02424 static void my_increase_ss_count(void)
02425 {
02426 ast_mutex_lock(&ss_thread_lock);
02427 ss_thread_count++;
02428 ast_mutex_unlock(&ss_thread_lock);
02429 }
02430
02431 static void my_decrease_ss_count(void)
02432 {
02433 ast_mutex_lock(&ss_thread_lock);
02434 ss_thread_count--;
02435 ast_cond_signal(&ss_thread_complete);
02436 ast_mutex_unlock(&ss_thread_lock);
02437 }
02438
02439 static void my_all_subchannels_hungup(void *pvt)
02440 {
02441 struct dahdi_pvt *p = pvt;
02442 int res, law;
02443
02444 p->faxhandled = 0;
02445 p->didtdd = 0;
02446
02447 if (p->dsp) {
02448 ast_dsp_free(p->dsp);
02449 p->dsp = NULL;
02450 }
02451
02452 p->law = p->law_default;
02453 law = p->law_default;
02454 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02455 if (res < 0)
02456 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02457
02458 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02459
02460 #if 1
02461 {
02462 int i;
02463 p->owner = NULL;
02464
02465 for (i = 0; i < 3; i++) {
02466 p->subs[i].owner = NULL;
02467 }
02468 }
02469 #endif
02470
02471 reset_conf(p);
02472 if (num_restart_pending == 0) {
02473 restart_monitor();
02474 }
02475 }
02476
02477 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02478
02479 static int my_conf_del(void *pvt, enum analog_sub sub)
02480 {
02481 struct dahdi_pvt *p = pvt;
02482 int x = analogsub_to_dahdisub(sub);
02483
02484 return conf_del(p, &p->subs[x], x);
02485 }
02486
02487 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02488
02489 static int my_conf_add(void *pvt, enum analog_sub sub)
02490 {
02491 struct dahdi_pvt *p = pvt;
02492 int x = analogsub_to_dahdisub(sub);
02493
02494 return conf_add(p, &p->subs[x], x, 0);
02495 }
02496
02497 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02498
02499 static int my_complete_conference_update(void *pvt, int needconference)
02500 {
02501 struct dahdi_pvt *p = pvt;
02502 int needconf = needconference;
02503 int x;
02504 int useslavenative;
02505 struct dahdi_pvt *slave = NULL;
02506
02507 useslavenative = isslavenative(p, &slave);
02508
02509
02510
02511 for (x = 0; x < MAX_SLAVES; x++) {
02512 if (p->slaves[x]) {
02513 if (useslavenative)
02514 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02515 else {
02516 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02517 needconf++;
02518 }
02519 }
02520 }
02521
02522 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02523 if (useslavenative)
02524 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02525 else {
02526 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02527 needconf++;
02528 }
02529 }
02530
02531 if (p->master) {
02532 if (isslavenative(p->master, NULL)) {
02533 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02534 } else {
02535 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02536 }
02537 }
02538 if (!needconf) {
02539
02540
02541 p->confno = -1;
02542 }
02543
02544 return 0;
02545 }
02546
02547 static int check_for_conference(struct dahdi_pvt *p);
02548
02549 static int my_check_for_conference(void *pvt)
02550 {
02551 struct dahdi_pvt *p = pvt;
02552 return check_for_conference(p);
02553 }
02554
02555 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)
02556 {
02557 struct dahdi_pvt *p = pvt;
02558 int da, db;
02559 int tchan;
02560 int tinthreeway;
02561
02562 da = analogsub_to_dahdisub(a);
02563 db = analogsub_to_dahdisub(b);
02564
02565 tchan = p->subs[da].chan;
02566 p->subs[da].chan = p->subs[db].chan;
02567 p->subs[db].chan = tchan;
02568
02569 tinthreeway = p->subs[da].inthreeway;
02570 p->subs[da].inthreeway = p->subs[db].inthreeway;
02571 p->subs[db].inthreeway = tinthreeway;
02572
02573 p->subs[da].owner = ast_a;
02574 p->subs[db].owner = ast_b;
02575
02576 if (ast_a)
02577 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02578 if (ast_b)
02579 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02580
02581 wakeup_sub(p, a);
02582 wakeup_sub(p, b);
02583
02584 return;
02585 }
02586
02587 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02588
02589 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02590 {
02591 struct dahdi_pvt *p = pvt;
02592 int dsub = analogsub_to_dahdisub(sub);
02593
02594 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02595 }
02596
02597 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02598 static int dahdi_setlaw(int dfd, int law)
02599 {
02600 int res;
02601 res = ioctl(dfd, DAHDI_SETLAW, &law);
02602 if (res)
02603 return res;
02604 return 0;
02605 }
02606 #endif
02607
02608 #if defined(HAVE_PRI)
02609 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)
02610 {
02611 struct dahdi_pvt *p = pvt;
02612 int audio;
02613 int newlaw = -1;
02614
02615 switch (p->sig) {
02616 case SIG_PRI_LIB_HANDLE_CASES:
02617 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02618
02619 break;
02620 }
02621
02622 default:
02623
02624 audio = 1;
02625 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02626 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02627 p->channel, audio, strerror(errno));
02628 }
02629 break;
02630 }
02631
02632 if (law != SIG_PRI_DEFLAW) {
02633 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02634 }
02635
02636 ast_copy_string(p->exten, exten, sizeof(p->exten));
02637
02638 switch (law) {
02639 case SIG_PRI_DEFLAW:
02640 newlaw = 0;
02641 break;
02642 case SIG_PRI_ALAW:
02643 newlaw = DAHDI_LAW_ALAW;
02644 break;
02645 case SIG_PRI_ULAW:
02646 newlaw = DAHDI_LAW_MULAW;
02647 break;
02648 }
02649 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02650 }
02651 #endif
02652
02653 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02654
02655 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665 static void my_pri_ss7_open_media(void *p)
02666 {
02667 struct dahdi_pvt *pvt = p;
02668 int res;
02669 int dfd;
02670 int set_val;
02671
02672 dfd = pvt->subs[SUB_REAL].dfd;
02673
02674
02675 set_val = 1;
02676 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02677 if (res < 0) {
02678 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02679 pvt->channel, strerror(errno));
02680 }
02681
02682
02683 res = dahdi_setlaw(dfd, pvt->law);
02684 if (res < 0) {
02685 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02686 }
02687
02688
02689 if (pvt->digital) {
02690 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02691 } else {
02692 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02693 pvt->law);
02694 }
02695 if (res < 0) {
02696 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02697 }
02698
02699 if (pvt->dsp_features && pvt->dsp) {
02700 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02701 pvt->dsp_features = 0;
02702 }
02703 }
02704 #endif
02705
02706 #if defined(HAVE_PRI)
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719 static void my_pri_dial_digits(void *p, const char *dial_string)
02720 {
02721 struct dahdi_dialoperation zo = {
02722 .op = DAHDI_DIAL_OP_APPEND,
02723 };
02724 struct dahdi_pvt *pvt = p;
02725 int res;
02726
02727 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02728 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02729 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02730 if (res) {
02731 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02732 pvt->channel, dial_string, strerror(errno));
02733 } else {
02734 pvt->dialing = 1;
02735 }
02736 }
02737 #endif
02738
02739 static int unalloc_sub(struct dahdi_pvt *p, int x);
02740
02741 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02742 {
02743 struct dahdi_pvt *p = pvt;
02744
02745 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02746 }
02747
02748 static int alloc_sub(struct dahdi_pvt *p, int x);
02749
02750 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02751 {
02752 struct dahdi_pvt *p = pvt;
02753
02754 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02755 }
02756
02757 static int has_voicemail(struct dahdi_pvt *p);
02758
02759 static int my_has_voicemail(void *pvt)
02760 {
02761 struct dahdi_pvt *p = pvt;
02762
02763 return has_voicemail(p);
02764 }
02765
02766 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02767 {
02768 struct dahdi_pvt *p = pvt;
02769 int index;
02770
02771 index = analogsub_to_dahdisub(sub);
02772
02773 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02774 }
02775
02776 static enum analog_event dahdievent_to_analogevent(int event)
02777 {
02778 enum analog_event res;
02779
02780 switch (event) {
02781 case DAHDI_EVENT_ONHOOK:
02782 res = ANALOG_EVENT_ONHOOK;
02783 break;
02784 case DAHDI_EVENT_RINGOFFHOOK:
02785 res = ANALOG_EVENT_RINGOFFHOOK;
02786 break;
02787 case DAHDI_EVENT_WINKFLASH:
02788 res = ANALOG_EVENT_WINKFLASH;
02789 break;
02790 case DAHDI_EVENT_ALARM:
02791 res = ANALOG_EVENT_ALARM;
02792 break;
02793 case DAHDI_EVENT_NOALARM:
02794 res = ANALOG_EVENT_NOALARM;
02795 break;
02796 case DAHDI_EVENT_DIALCOMPLETE:
02797 res = ANALOG_EVENT_DIALCOMPLETE;
02798 break;
02799 case DAHDI_EVENT_RINGERON:
02800 res = ANALOG_EVENT_RINGERON;
02801 break;
02802 case DAHDI_EVENT_RINGEROFF:
02803 res = ANALOG_EVENT_RINGEROFF;
02804 break;
02805 case DAHDI_EVENT_HOOKCOMPLETE:
02806 res = ANALOG_EVENT_HOOKCOMPLETE;
02807 break;
02808 case DAHDI_EVENT_PULSE_START:
02809 res = ANALOG_EVENT_PULSE_START;
02810 break;
02811 case DAHDI_EVENT_POLARITY:
02812 res = ANALOG_EVENT_POLARITY;
02813 break;
02814 case DAHDI_EVENT_RINGBEGIN:
02815 res = ANALOG_EVENT_RINGBEGIN;
02816 break;
02817 case DAHDI_EVENT_EC_DISABLED:
02818 res = ANALOG_EVENT_EC_DISABLED;
02819 break;
02820 case DAHDI_EVENT_REMOVED:
02821 res = ANALOG_EVENT_REMOVED;
02822 break;
02823 case DAHDI_EVENT_NEONMWI_ACTIVE:
02824 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02825 break;
02826 case DAHDI_EVENT_NEONMWI_INACTIVE:
02827 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02828 break;
02829 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02830 case DAHDI_EVENT_TX_CED_DETECTED:
02831 res = ANALOG_EVENT_TX_CED_DETECTED;
02832 break;
02833 case DAHDI_EVENT_RX_CED_DETECTED:
02834 res = ANALOG_EVENT_RX_CED_DETECTED;
02835 break;
02836 case DAHDI_EVENT_EC_NLP_DISABLED:
02837 res = ANALOG_EVENT_EC_NLP_DISABLED;
02838 break;
02839 case DAHDI_EVENT_EC_NLP_ENABLED:
02840 res = ANALOG_EVENT_EC_NLP_ENABLED;
02841 break;
02842 #endif
02843 case DAHDI_EVENT_PULSEDIGIT:
02844 res = ANALOG_EVENT_PULSEDIGIT;
02845 break;
02846 case DAHDI_EVENT_DTMFDOWN:
02847 res = ANALOG_EVENT_DTMFDOWN;
02848 break;
02849 case DAHDI_EVENT_DTMFUP:
02850 res = ANALOG_EVENT_DTMFUP;
02851 break;
02852 default:
02853 switch(event & 0xFFFF0000) {
02854 case DAHDI_EVENT_PULSEDIGIT:
02855 case DAHDI_EVENT_DTMFDOWN:
02856 case DAHDI_EVENT_DTMFUP:
02857
02858
02859
02860
02861 return event;
02862 }
02863
02864 res = ANALOG_EVENT_ERROR;
02865 break;
02866 }
02867
02868 return res;
02869 }
02870
02871 static inline int dahdi_wait_event(int fd);
02872
02873 static int my_wait_event(void *pvt)
02874 {
02875 struct dahdi_pvt *p = pvt;
02876
02877 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02878 }
02879
02880 static int my_get_event(void *pvt)
02881 {
02882 struct dahdi_pvt *p = pvt;
02883 int res;
02884
02885 if (p->fake_event) {
02886 res = p->fake_event;
02887 p->fake_event = 0;
02888 } else
02889 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02890
02891 return dahdievent_to_analogevent(res);
02892 }
02893
02894 static int my_is_off_hook(void *pvt)
02895 {
02896 struct dahdi_pvt *p = pvt;
02897 int res;
02898 struct dahdi_params par;
02899
02900 memset(&par, 0, sizeof(par));
02901
02902 if (p->subs[SUB_REAL].dfd > -1)
02903 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02904 else {
02905
02906 res = 0;
02907 par.rxisoffhook = 0;
02908 }
02909 if (res) {
02910 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02911 }
02912
02913 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02914
02915
02916
02917 return (par.rxbits > -1) || par.rxisoffhook;
02918 }
02919
02920 return par.rxisoffhook;
02921 }
02922
02923 static void dahdi_enable_ec(struct dahdi_pvt *p);
02924 static void dahdi_disable_ec(struct dahdi_pvt *p);
02925
02926 static int my_set_echocanceller(void *pvt, int enable)
02927 {
02928 struct dahdi_pvt *p = pvt;
02929
02930 if (enable)
02931 dahdi_enable_ec(p);
02932 else
02933 dahdi_disable_ec(p);
02934
02935 return 0;
02936 }
02937
02938 static int dahdi_ring_phone(struct dahdi_pvt *p);
02939
02940 static int my_ring(void *pvt)
02941 {
02942 struct dahdi_pvt *p = pvt;
02943
02944 return dahdi_ring_phone(p);
02945 }
02946
02947 static int my_flash(void *pvt)
02948 {
02949 struct dahdi_pvt *p = pvt;
02950 int func = DAHDI_FLASH;
02951 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02952 }
02953
02954 static inline int dahdi_set_hook(int fd, int hs);
02955
02956 static int my_off_hook(void *pvt)
02957 {
02958 struct dahdi_pvt *p = pvt;
02959 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02960 }
02961
02962 static void my_set_needringing(void *pvt, int value)
02963 {
02964 struct dahdi_pvt *p = pvt;
02965 p->subs[SUB_REAL].needringing = value;
02966 }
02967
02968 static void my_set_polarity(void *pvt, int value)
02969 {
02970 struct dahdi_pvt *p = pvt;
02971
02972 if (p->channel == CHAN_PSEUDO) {
02973 return;
02974 }
02975 p->polarity = value;
02976 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02977 }
02978
02979 static void my_start_polarityswitch(void *pvt)
02980 {
02981 struct dahdi_pvt *p = pvt;
02982
02983 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02984 my_set_polarity(pvt, 0);
02985 }
02986 }
02987
02988 static void my_answer_polarityswitch(void *pvt)
02989 {
02990 struct dahdi_pvt *p = pvt;
02991
02992 if (!p->answeronpolarityswitch) {
02993 return;
02994 }
02995
02996 my_set_polarity(pvt, 1);
02997 }
02998
02999 static void my_hangup_polarityswitch(void *pvt)
03000 {
03001 struct dahdi_pvt *p = pvt;
03002
03003 if (!p->hanguponpolarityswitch) {
03004 return;
03005 }
03006
03007 if (p->answeronpolarityswitch) {
03008 my_set_polarity(pvt, 0);
03009 } else {
03010 my_set_polarity(pvt, 1);
03011 }
03012 }
03013
03014 static int my_start(void *pvt)
03015 {
03016 struct dahdi_pvt *p = pvt;
03017 int x = DAHDI_START;
03018
03019 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03020 }
03021
03022 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03023 {
03024 int index = analogsub_to_dahdisub(sub);
03025 int res;
03026 struct dahdi_pvt *p = pvt;
03027 struct dahdi_dialoperation ddop;
03028
03029 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03030 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03031 return -1;
03032 }
03033
03034 if (sub != ANALOG_SUB_REAL) {
03035 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
03036 dop->dialstr, p->channel, sub);
03037 return -1;
03038 }
03039
03040 ddop.op = DAHDI_DIAL_OP_REPLACE;
03041 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03042
03043 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03044
03045 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03046 if (res == -1) {
03047 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03048 }
03049
03050 return res;
03051 }
03052
03053 static void dahdi_train_ec(struct dahdi_pvt *p);
03054
03055 static int my_train_echocanceller(void *pvt)
03056 {
03057 struct dahdi_pvt *p = pvt;
03058
03059 dahdi_train_ec(p);
03060
03061 return 0;
03062 }
03063
03064 static int my_is_dialing(void *pvt, enum analog_sub sub)
03065 {
03066 struct dahdi_pvt *p = pvt;
03067 int index;
03068 int x;
03069
03070 index = analogsub_to_dahdisub(sub);
03071
03072 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03073 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03074 return -1;
03075 }
03076
03077 return x;
03078 }
03079
03080 static int my_on_hook(void *pvt)
03081 {
03082 struct dahdi_pvt *p = pvt;
03083 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03084 }
03085
03086 #if defined(HAVE_PRI)
03087 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03088 {
03089 struct dahdi_pvt *old_chan = chan_old;
03090 struct dahdi_pvt *new_chan = chan_new;
03091
03092 new_chan->owner = old_chan->owner;
03093 old_chan->owner = NULL;
03094 if (new_chan->owner) {
03095 new_chan->owner->tech_pvt = new_chan;
03096 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03097 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03098 old_chan->subs[SUB_REAL].owner = NULL;
03099 }
03100
03101 new_chan->dsp = old_chan->dsp;
03102 new_chan->dsp_features = old_chan->dsp_features;
03103 old_chan->dsp = NULL;
03104 old_chan->dsp_features = 0;
03105
03106
03107 new_chan->dialing = old_chan->dialing;
03108 new_chan->digital = old_chan->digital;
03109 new_chan->outgoing = old_chan->outgoing;
03110 old_chan->dialing = 0;
03111 old_chan->digital = 0;
03112 old_chan->outgoing = 0;
03113
03114
03115 new_chan->law = old_chan->law;
03116 strcpy(new_chan->dialstring, old_chan->dialstring);
03117 }
03118 #endif
03119
03120 #if defined(HAVE_PRI)
03121 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03122 {
03123 switch (tone) {
03124 case SIG_PRI_TONE_RINGTONE:
03125 return DAHDI_TONE_RINGTONE;
03126 case SIG_PRI_TONE_STUTTER:
03127 return DAHDI_TONE_STUTTER;
03128 case SIG_PRI_TONE_CONGESTION:
03129 return DAHDI_TONE_CONGESTION;
03130 case SIG_PRI_TONE_DIALTONE:
03131 return DAHDI_TONE_DIALTONE;
03132 case SIG_PRI_TONE_DIALRECALL:
03133 return DAHDI_TONE_DIALRECALL;
03134 case SIG_PRI_TONE_INFO:
03135 return DAHDI_TONE_INFO;
03136 case SIG_PRI_TONE_BUSY:
03137 return DAHDI_TONE_BUSY;
03138 default:
03139 return -1;
03140 }
03141 }
03142 #endif
03143
03144 #if defined(HAVE_PRI)
03145 static int pri_destroy_dchan(struct sig_pri_span *pri);
03146
03147 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03148 {
03149 int x;
03150
03151 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03152 switch (x) {
03153 case DAHDI_EVENT_NONE:
03154 break;
03155 case DAHDI_EVENT_ALARM:
03156 case DAHDI_EVENT_NOALARM:
03157 if (sig_pri_is_alarm_ignored(pri)) {
03158 break;
03159 }
03160
03161 default:
03162 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03163 event2str(x), x, pri->span);
03164 break;
03165 }
03166
03167 switch (x) {
03168 case DAHDI_EVENT_ALARM:
03169 pri_event_alarm(pri, index, 0);
03170 break;
03171 case DAHDI_EVENT_NOALARM:
03172 pri_event_noalarm(pri, index, 0);
03173 break;
03174 case DAHDI_EVENT_REMOVED:
03175 pri_destroy_dchan(pri);
03176 break;
03177 default:
03178 break;
03179 }
03180 }
03181 #endif
03182
03183 #if defined(HAVE_PRI)
03184 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03185 {
03186 struct dahdi_pvt *p = pvt;
03187
03188 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03189 }
03190 #endif
03191
03192 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03204 {
03205 struct dahdi_pvt *p = pvt;
03206
03207 ast_copy_string(p->cid_num,
03208 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03209 sizeof(p->cid_num));
03210 ast_copy_string(p->cid_name,
03211 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03212 sizeof(p->cid_name));
03213 ast_copy_string(p->cid_subaddr,
03214 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03215 sizeof(p->cid_subaddr));
03216 p->cid_ton = caller->id.number.plan;
03217 p->callingpres = ast_party_id_presentation(&caller->id);
03218 if (caller->id.tag) {
03219 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03220 }
03221 ast_copy_string(p->cid_ani,
03222 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03223 sizeof(p->cid_ani));
03224 p->cid_ani2 = caller->ani2;
03225 }
03226 #endif
03227
03228 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239 static void my_set_dnid(void *pvt, const char *dnid)
03240 {
03241 struct dahdi_pvt *p = pvt;
03242
03243 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03244 }
03245 #endif
03246
03247 #if defined(HAVE_PRI)
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258 static void my_set_rdnis(void *pvt, const char *rdnis)
03259 {
03260 struct dahdi_pvt *p = pvt;
03261
03262 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03263 }
03264 #endif
03265
03266 #if defined(HAVE_PRI)
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03292 {
03293 char *dial;
03294 struct dahdi_pvt *pvt;
03295 AST_DECLARE_APP_ARGS(args,
03296 AST_APP_ARG(tech);
03297 AST_APP_ARG(group);
03298
03299
03300
03301 );
03302
03303 pvt = priv;
03304 dial = ast_strdupa(pvt->dialstring);
03305 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03306 if (!args.tech) {
03307 ast_copy_string(buf, pvt->dialstring, buf_size);
03308 return;
03309 }
03310 if (!args.group) {
03311
03312 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03313 return;
03314 }
03315 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03316
03317
03318 ast_copy_string(buf, pvt->dialstring, buf_size);
03319 return;
03320 }
03321
03322 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03323 }
03324 #endif
03325
03326 #if defined(HAVE_PRI)
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03339 {
03340 unsigned idx;
03341 unsigned num_b_chans;
03342 unsigned in_use;
03343 unsigned in_alarm;
03344 enum ast_device_state new_state;
03345
03346
03347 num_b_chans = 0;
03348 in_use = 0;
03349 in_alarm = 1;
03350 for (idx = pri->numchans; idx--;) {
03351 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03352
03353 ++num_b_chans;
03354 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03355 ++in_use;
03356 }
03357 if (!pri->pvts[idx]->inalarm) {
03358
03359 in_alarm = 0;
03360 }
03361 }
03362 }
03363
03364
03365 if (in_alarm) {
03366 new_state = AST_DEVICE_UNAVAILABLE;
03367 } else {
03368 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03369 }
03370 if (pri->congestion_devstate != new_state) {
03371 pri->congestion_devstate = new_state;
03372 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03373 }
03374 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03375
03376 if (in_alarm) {
03377 new_state = AST_DEVICE_UNAVAILABLE;
03378 } else if (!in_use) {
03379 new_state = AST_DEVICE_NOT_INUSE;
03380 } else if (!pri->user_busy_threshold) {
03381 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03382 } else {
03383 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03384 : AST_DEVICE_BUSY;
03385 }
03386 if (pri->threshold_devstate != new_state) {
03387 pri->threshold_devstate = new_state;
03388 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03389 }
03390 #endif
03391 }
03392 #endif
03393
03394 #if defined(HAVE_PRI)
03395
03396
03397
03398
03399
03400
03401
03402 static void my_module_ref(void)
03403 {
03404 ast_module_ref(ast_module_info->self);
03405 }
03406 #endif
03407
03408 #if defined(HAVE_PRI)
03409
03410
03411
03412
03413
03414
03415
03416 static void my_module_unref(void)
03417 {
03418 ast_module_unref(ast_module_info->self);
03419 }
03420 #endif
03421
03422 #if defined(HAVE_PRI)
03423 #if defined(HAVE_PRI_CALL_WAITING)
03424 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03425 #endif
03426 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03427
03428 static struct sig_pri_callback dahdi_pri_callbacks =
03429 {
03430 .handle_dchan_exception = my_handle_dchan_exception,
03431 .play_tone = my_pri_play_tone,
03432 .set_echocanceller = my_set_echocanceller,
03433 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03434 .lock_private = my_lock_private,
03435 .unlock_private = my_unlock_private,
03436 .new_ast_channel = my_new_pri_ast_channel,
03437 .fixup_chans = my_pri_fixup_chans,
03438 .set_alarm = my_set_alarm,
03439 .set_dialing = my_set_dialing,
03440 .set_outgoing = my_set_outgoing,
03441 .set_digital = my_set_digital,
03442 .set_callerid = my_set_callerid,
03443 .set_dnid = my_set_dnid,
03444 .set_rdnis = my_set_rdnis,
03445 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03446 #if defined(HAVE_PRI_CALL_WAITING)
03447 .init_config = my_pri_init_config,
03448 #endif
03449 .get_orig_dialstring = my_get_orig_dialstring,
03450 .make_cc_dialstring = my_pri_make_cc_dialstring,
03451 .update_span_devstate = dahdi_pri_update_span_devstate,
03452 .module_ref = my_module_ref,
03453 .module_unref = my_module_unref,
03454 .dial_digits = my_pri_dial_digits,
03455 .open_media = my_pri_ss7_open_media,
03456 .ami_channel_event = my_ami_channel_event,
03457 };
03458 #endif
03459
03460 #if defined(HAVE_SS7)
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03472 {
03473 int event;
03474
03475 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03476 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03477 linkset->span, which);
03478 return;
03479 }
03480 switch (event) {
03481 case DAHDI_EVENT_NONE:
03482 break;
03483 case DAHDI_EVENT_ALARM:
03484 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03485 event2str(event), event, linkset->span, which);
03486 sig_ss7_link_alarm(linkset, which);
03487 break;
03488 case DAHDI_EVENT_NOALARM:
03489 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03490 event2str(event), event, linkset->span, which);
03491 sig_ss7_link_noalarm(linkset, which);
03492 break;
03493 default:
03494 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03495 event2str(event), event, linkset->span, which);
03496 break;
03497 }
03498 }
03499 #endif
03500
03501 #if defined(HAVE_SS7)
03502 static void my_ss7_set_loopback(void *pvt, int enable)
03503 {
03504 struct dahdi_pvt *p = pvt;
03505
03506 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03507 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03508 strerror(errno));
03509 }
03510 }
03511 #endif
03512
03513 #if defined(HAVE_SS7)
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526
03527
03528 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)
03529 {
03530 struct dahdi_pvt *p = pvt;
03531 int audio;
03532 int newlaw;
03533
03534
03535 audio = 1;
03536 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03537 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03538 p->channel, audio, strerror(errno));
03539
03540 if (law != SIG_SS7_DEFLAW) {
03541 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03542 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03543 }
03544
03545 ast_copy_string(p->exten, exten, sizeof(p->exten));
03546
03547 newlaw = -1;
03548 switch (law) {
03549 case SIG_SS7_DEFLAW:
03550 newlaw = 0;
03551 break;
03552 case SIG_SS7_ALAW:
03553 newlaw = DAHDI_LAW_ALAW;
03554 break;
03555 case SIG_SS7_ULAW:
03556 newlaw = DAHDI_LAW_MULAW;
03557 break;
03558 }
03559 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03560 }
03561 #endif
03562
03563 #if defined(HAVE_SS7)
03564 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03565 {
03566 switch (tone) {
03567 case SIG_SS7_TONE_RINGTONE:
03568 return DAHDI_TONE_RINGTONE;
03569 case SIG_SS7_TONE_STUTTER:
03570 return DAHDI_TONE_STUTTER;
03571 case SIG_SS7_TONE_CONGESTION:
03572 return DAHDI_TONE_CONGESTION;
03573 case SIG_SS7_TONE_DIALTONE:
03574 return DAHDI_TONE_DIALTONE;
03575 case SIG_SS7_TONE_DIALRECALL:
03576 return DAHDI_TONE_DIALRECALL;
03577 case SIG_SS7_TONE_INFO:
03578 return DAHDI_TONE_INFO;
03579 case SIG_SS7_TONE_BUSY:
03580 return DAHDI_TONE_BUSY;
03581 default:
03582 return -1;
03583 }
03584 }
03585 #endif
03586
03587 #if defined(HAVE_SS7)
03588 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03589 {
03590 struct dahdi_pvt *p = pvt;
03591
03592 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03593 }
03594 #endif
03595
03596 #if defined(HAVE_SS7)
03597 static struct sig_ss7_callback dahdi_ss7_callbacks =
03598 {
03599 .lock_private = my_lock_private,
03600 .unlock_private = my_unlock_private,
03601
03602 .set_echocanceller = my_set_echocanceller,
03603 .set_loopback = my_ss7_set_loopback,
03604
03605 .new_ast_channel = my_new_ss7_ast_channel,
03606 .play_tone = my_ss7_play_tone,
03607
03608 .handle_link_exception = my_handle_link_exception,
03609 .set_alarm = my_set_alarm,
03610 .set_dialing = my_set_dialing,
03611 .set_outgoing = my_set_outgoing,
03612 .set_digital = my_set_digital,
03613 .set_inservice = my_set_inservice,
03614 .set_locallyblocked = my_set_locallyblocked,
03615 .set_remotelyblocked = my_set_remotelyblocked,
03616 .set_callerid = my_set_callerid,
03617 .set_dnid = my_set_dnid,
03618 .open_media = my_pri_ss7_open_media,
03619 };
03620 #endif
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640 static void notify_message(char *mailbox_full, int thereornot)
03641 {
03642 char s[sizeof(mwimonitornotify) + 80];
03643 struct ast_event *event;
03644 char *mailbox, *context;
03645
03646
03647 context = mailbox = ast_strdupa(mailbox_full);
03648 strsep(&context, "@");
03649 if (ast_strlen_zero(context))
03650 context = "default";
03651
03652 if (!(event = ast_event_new(AST_EVENT_MWI,
03653 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03654 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03655 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03656 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03657 AST_EVENT_IE_END))) {
03658 return;
03659 }
03660
03661 ast_event_queue_and_cache(event);
03662
03663 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03664 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03665 ast_safe_system(s);
03666 }
03667 }
03668
03669 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03670 {
03671 struct dahdi_pvt *p = pvt;
03672
03673 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03674 return;
03675
03676 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03677 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03678 notify_message(p->mailbox, 1);
03679 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03680 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03681 notify_message(p->mailbox, 0);
03682 }
03683
03684
03685 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03686 ast_hangup(chan);
03687 return;
03688 }
03689 }
03690
03691 static int my_have_progressdetect(void *pvt)
03692 {
03693 struct dahdi_pvt *p = pvt;
03694
03695 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03696 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03697 return 1;
03698 } else {
03699
03700 return 0;
03701 }
03702 }
03703
03704 static struct analog_callback dahdi_analog_callbacks =
03705 {
03706 .play_tone = my_play_tone,
03707 .get_event = my_get_event,
03708 .wait_event = my_wait_event,
03709 .is_off_hook = my_is_off_hook,
03710 .set_echocanceller = my_set_echocanceller,
03711 .ring = my_ring,
03712 .flash = my_flash,
03713 .off_hook = my_off_hook,
03714 .dial_digits = my_dial_digits,
03715 .train_echocanceller = my_train_echocanceller,
03716 .on_hook = my_on_hook,
03717 .is_dialing = my_is_dialing,
03718 .allocate_sub = my_allocate_sub,
03719 .unallocate_sub = my_unallocate_sub,
03720 .swap_subs = my_swap_subchannels,
03721 .has_voicemail = my_has_voicemail,
03722 .check_for_conference = my_check_for_conference,
03723 .conf_add = my_conf_add,
03724 .conf_del = my_conf_del,
03725 .complete_conference_update = my_complete_conference_update,
03726 .start = my_start,
03727 .all_subchannels_hungup = my_all_subchannels_hungup,
03728 .lock_private = my_lock_private,
03729 .unlock_private = my_unlock_private,
03730 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03731 .handle_dtmf = my_handle_dtmf,
03732 .wink = my_wink,
03733 .new_ast_channel = my_new_analog_ast_channel,
03734 .dsp_set_digitmode = my_dsp_set_digitmode,
03735 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03736 .send_callerid = my_send_callerid,
03737 .callwait = my_callwait,
03738 .stop_callwait = my_stop_callwait,
03739 .get_callerid = my_get_callerid,
03740 .start_cid_detect = my_start_cid_detect,
03741 .stop_cid_detect = my_stop_cid_detect,
03742 .handle_notify_message = my_handle_notify_message,
03743 .increase_ss_count = my_increase_ss_count,
03744 .decrease_ss_count = my_decrease_ss_count,
03745 .distinctive_ring = my_distinctive_ring,
03746 .set_linear_mode = my_set_linear_mode,
03747 .set_inthreeway = my_set_inthreeway,
03748 .get_and_handle_alarms = my_get_and_handle_alarms,
03749 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03750 .get_sub_fd = my_get_sub_fd,
03751 .set_cadence = my_set_cadence,
03752 .set_alarm = my_set_alarm,
03753 .set_dialing = my_set_dialing,
03754 .set_outgoing = my_set_outgoing,
03755 .set_ringtimeout = my_set_ringtimeout,
03756 .set_waitingfordt = my_set_waitingfordt,
03757 .check_waitingfordt = my_check_waitingfordt,
03758 .set_confirmanswer = my_set_confirmanswer,
03759 .check_confirmanswer = my_check_confirmanswer,
03760 .set_callwaiting = my_set_callwaiting,
03761 .cancel_cidspill = my_cancel_cidspill,
03762 .confmute = my_confmute,
03763 .set_pulsedial = my_set_pulsedial,
03764 .set_new_owner = my_set_new_owner,
03765 .get_orig_dialstring = my_get_orig_dialstring,
03766 .set_needringing = my_set_needringing,
03767 .set_polarity = my_set_polarity,
03768 .start_polarityswitch = my_start_polarityswitch,
03769 .answer_polarityswitch = my_answer_polarityswitch,
03770 .hangup_polarityswitch = my_hangup_polarityswitch,
03771 .have_progressdetect = my_have_progressdetect,
03772 };
03773
03774
03775 static struct dahdi_pvt *round_robin[32];
03776
03777 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03778 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03779 {
03780 int res;
03781 if (p->subs[SUB_REAL].owner == ast)
03782 res = 0;
03783 else if (p->subs[SUB_CALLWAIT].owner == ast)
03784 res = 1;
03785 else if (p->subs[SUB_THREEWAY].owner == ast)
03786 res = 2;
03787 else {
03788 res = -1;
03789 if (!nullok)
03790 ast_log(LOG_WARNING,
03791 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03792 ast ? ast->name : "", p->channel, fname, line);
03793 }
03794 return res;
03795 }
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807
03808
03809
03810
03811
03812 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03813 {
03814 for (;;) {
03815 if (!pvt->subs[sub_idx].owner) {
03816
03817 break;
03818 }
03819 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03820
03821 break;
03822 }
03823
03824 DEADLOCK_AVOIDANCE(&pvt->lock);
03825 }
03826 }
03827
03828 static void wakeup_sub(struct dahdi_pvt *p, int a)
03829 {
03830 dahdi_lock_sub_owner(p, a);
03831 if (p->subs[a].owner) {
03832 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03833 ast_channel_unlock(p->subs[a].owner);
03834 }
03835 }
03836
03837 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03838 {
03839 for (;;) {
03840 if (p->owner) {
03841 if (ast_channel_trylock(p->owner)) {
03842 DEADLOCK_AVOIDANCE(&p->lock);
03843 } else {
03844 ast_queue_frame(p->owner, f);
03845 ast_channel_unlock(p->owner);
03846 break;
03847 }
03848 } else
03849 break;
03850 }
03851 }
03852
03853 static void handle_clear_alarms(struct dahdi_pvt *p)
03854 {
03855 #if defined(HAVE_PRI)
03856 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03857 return;
03858 }
03859 #endif
03860
03861 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03862 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03863 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03864 }
03865 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03866 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03867 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03868 }
03869 }
03870
03871 #ifdef HAVE_OPENR2
03872
03873 static int dahdi_r2_answer(struct dahdi_pvt *p)
03874 {
03875 int res = 0;
03876
03877
03878
03879 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03880 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03881 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03882 if (!double_answer) {
03883
03884
03885 res = openr2_chan_answer_call(p->r2chan);
03886 } else if (wants_double_answer) {
03887 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03888 } else {
03889 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03890 }
03891 #else
03892 res = openr2_chan_answer_call(p->r2chan);
03893 #endif
03894 return res;
03895 }
03896
03897
03898
03899
03900 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03901 {
03902 openr2_calling_party_category_t cat;
03903 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03904 struct dahdi_pvt *p = c->tech_pvt;
03905 if (ast_strlen_zero(catstr)) {
03906 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03907 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03908 return p->mfcr2_category;
03909 }
03910 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03911 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03912 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03913 return p->mfcr2_category;
03914 }
03915 ast_debug(1, "Using category %s\n", catstr);
03916 return cat;
03917 }
03918
03919 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03920 {
03921 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03922 ast_mutex_lock(&p->lock);
03923 if (p->mfcr2call) {
03924 ast_mutex_unlock(&p->lock);
03925
03926
03927
03928
03929
03930 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03931 return;
03932 }
03933 p->mfcr2call = 1;
03934
03935 p->cid_name[0] = '\0';
03936 p->cid_num[0] = '\0';
03937 p->cid_subaddr[0] = '\0';
03938 p->rdnis[0] = '\0';
03939 p->exten[0] = '\0';
03940 p->mfcr2_ani_index = '\0';
03941 p->mfcr2_dnis_index = '\0';
03942 p->mfcr2_dnis_matched = 0;
03943 p->mfcr2_answer_pending = 0;
03944 p->mfcr2_call_accepted = 0;
03945 ast_mutex_unlock(&p->lock);
03946 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03947 }
03948
03949 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03950 {
03951 int res;
03952 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03953 ast_mutex_lock(&p->lock);
03954 p->inalarm = alarm ? 1 : 0;
03955 if (p->inalarm) {
03956 res = get_alarms(p);
03957 handle_alarms(p, res);
03958 } else {
03959 handle_clear_alarms(p);
03960 }
03961 ast_mutex_unlock(&p->lock);
03962 }
03963
03964 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03965 {
03966 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03967 }
03968
03969 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03970 {
03971 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03972 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03973 if (p->owner) {
03974 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03975 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03976 }
03977 ast_mutex_lock(&p->lock);
03978 p->mfcr2call = 0;
03979 ast_mutex_unlock(&p->lock);
03980 }
03981
03982 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03983 {
03984 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03985 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03986 p->channel, openr2_proto_get_disconnect_string(cause));
03987
03988 openr2_chan_set_idle(p->r2chan);
03989 ast_mutex_lock(&p->lock);
03990 p->mfcr2call = 0;
03991 ast_mutex_unlock(&p->lock);
03992 }
03993 }
03994
03995 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03996 {
03997 struct dahdi_pvt *p;
03998 struct ast_channel *c;
03999 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04000 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04001 openr2_proto_get_category_string(category));
04002 p = openr2_chan_get_client_data(r2chan);
04003
04004 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04005 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04006 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04007 return;
04008 }
04009 ast_mutex_lock(&p->lock);
04010 p->mfcr2_recvd_category = category;
04011
04012 if (!p->use_callerid) {
04013 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04014 p->cid_num[0] = 0;
04015 p->cid_name[0] = 0;
04016 }
04017
04018 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04019 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04020 p->exten[0] = 's';
04021 p->exten[1] = 0;
04022 }
04023 ast_mutex_unlock(&p->lock);
04024 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04025 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04026 p->channel, p->exten, p->context);
04027 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04028 return;
04029 }
04030 if (!p->mfcr2_accept_on_offer) {
04031
04032 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04033 if (c) {
04034
04035
04036
04037 return;
04038 }
04039 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04040 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04041 } else if (p->mfcr2_charge_calls) {
04042 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04043 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04044 } else {
04045 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04046 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04047 }
04048 }
04049
04050 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04051 {
04052 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04053 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04054 ast_mutex_lock(&p->lock);
04055 p->mfcr2call = 0;
04056 ast_mutex_unlock(&p->lock);
04057 }
04058
04059 static void dahdi_enable_ec(struct dahdi_pvt *p);
04060 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04061 {
04062 struct dahdi_pvt *p = NULL;
04063 struct ast_channel *c = NULL;
04064 p = openr2_chan_get_client_data(r2chan);
04065 dahdi_enable_ec(p);
04066 p->mfcr2_call_accepted = 1;
04067
04068 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04069 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04070
04071
04072
04073
04074 if (!p->mfcr2_accept_on_offer) {
04075 openr2_chan_disable_read(r2chan);
04076 if (p->mfcr2_answer_pending) {
04077 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04078 dahdi_r2_answer(p);
04079 }
04080 return;
04081 }
04082 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04083 if (c) {
04084
04085
04086 openr2_chan_disable_read(r2chan);
04087 return;
04088 }
04089 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04090
04091 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04092 return;
04093 }
04094
04095 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04096 p->subs[SUB_REAL].needringing = 1;
04097 p->dialing = 0;
04098
04099 openr2_chan_disable_read(r2chan);
04100 }
04101
04102 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04103 {
04104 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04105 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04106 p->subs[SUB_REAL].needanswer = 1;
04107 }
04108
04109 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04110 {
04111
04112 }
04113
04114 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04115 {
04116 switch (cause) {
04117 case OR2_CAUSE_BUSY_NUMBER:
04118 return AST_CAUSE_BUSY;
04119 case OR2_CAUSE_NETWORK_CONGESTION:
04120 return AST_CAUSE_CONGESTION;
04121 case OR2_CAUSE_OUT_OF_ORDER:
04122 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04123 case OR2_CAUSE_UNALLOCATED_NUMBER:
04124 return AST_CAUSE_UNREGISTERED;
04125 case OR2_CAUSE_NO_ANSWER:
04126 return AST_CAUSE_NO_ANSWER;
04127 case OR2_CAUSE_NORMAL_CLEARING:
04128 return AST_CAUSE_NORMAL_CLEARING;
04129 case OR2_CAUSE_UNSPECIFIED:
04130 default:
04131 return AST_CAUSE_NOTDEFINED;
04132 }
04133 }
04134
04135 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04136 {
04137 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04138 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04139 ast_mutex_lock(&p->lock);
04140 if (!p->owner) {
04141 ast_mutex_unlock(&p->lock);
04142
04143 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04144 return;
04145 }
04146
04147
04148 if (p->owner->_state == AST_STATE_UP) {
04149 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04150 ast_mutex_unlock(&p->lock);
04151 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04152
04153 switch (cause) {
04154 case OR2_CAUSE_BUSY_NUMBER:
04155 p->subs[SUB_REAL].needbusy = 1;
04156 break;
04157 case OR2_CAUSE_NETWORK_CONGESTION:
04158 case OR2_CAUSE_OUT_OF_ORDER:
04159 case OR2_CAUSE_UNALLOCATED_NUMBER:
04160 case OR2_CAUSE_NO_ANSWER:
04161 case OR2_CAUSE_UNSPECIFIED:
04162 case OR2_CAUSE_NORMAL_CLEARING:
04163 p->subs[SUB_REAL].needcongestion = 1;
04164 break;
04165 default:
04166 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04167 }
04168 ast_mutex_unlock(&p->lock);
04169 } else {
04170 ast_mutex_unlock(&p->lock);
04171
04172
04173 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04174 }
04175 }
04176
04177 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04178 {
04179 switch (level) {
04180 case OR2_LOG_NOTICE:
04181 ast_verbose("%s", logmessage);
04182 break;
04183 case OR2_LOG_WARNING:
04184 ast_log(LOG_WARNING, "%s", logmessage);
04185 break;
04186 case OR2_LOG_ERROR:
04187 ast_log(LOG_ERROR, "%s", logmessage);
04188 break;
04189 case OR2_LOG_STACK_TRACE:
04190 case OR2_LOG_MF_TRACE:
04191 case OR2_LOG_CAS_TRACE:
04192 case OR2_LOG_DEBUG:
04193 case OR2_LOG_EX_DEBUG:
04194 ast_log(LOG_DEBUG, "%s", logmessage);
04195 break;
04196 default:
04197 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04198 ast_log(LOG_DEBUG, "%s", logmessage);
04199 break;
04200 }
04201 }
04202
04203 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04204 {
04205 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04206 ast_mutex_lock(&p->lock);
04207 p->remotelyblocked = 1;
04208 ast_mutex_unlock(&p->lock);
04209 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04210 }
04211
04212 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04213 {
04214 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04215 ast_mutex_lock(&p->lock);
04216 p->remotelyblocked = 0;
04217 ast_mutex_unlock(&p->lock);
04218 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04219 }
04220
04221 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04222 __attribute__((format (printf, 3, 0)));
04223 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04224 {
04225 #define CONTEXT_TAG "Context - "
04226 char logmsg[256];
04227 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04228 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04229 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04230 dahdi_r2_write_log(level, completemsg);
04231 #undef CONTEXT_TAG
04232 }
04233
04234 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04235 __attribute__((format (printf, 3, 0)));
04236 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04237 {
04238 #define CHAN_TAG "Chan "
04239 char logmsg[256];
04240 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04241 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04242 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04243 dahdi_r2_write_log(level, completemsg);
04244 }
04245
04246 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04247 {
04248 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04249
04250 if (p->immediate) {
04251 return 0;
04252 }
04253 p->exten[p->mfcr2_dnis_index] = digit;
04254 p->rdnis[p->mfcr2_dnis_index] = digit;
04255 p->mfcr2_dnis_index++;
04256 p->exten[p->mfcr2_dnis_index] = 0;
04257 p->rdnis[p->mfcr2_dnis_index] = 0;
04258
04259 if ((p->mfcr2_dnis_matched ||
04260 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04261 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04262 return 0;
04263 }
04264
04265 return 1;
04266 }
04267
04268 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04269 {
04270 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04271 p->cid_num[p->mfcr2_ani_index] = digit;
04272 p->cid_name[p->mfcr2_ani_index] = digit;
04273 p->mfcr2_ani_index++;
04274 p->cid_num[p->mfcr2_ani_index] = 0;
04275 p->cid_name[p->mfcr2_ani_index] = 0;
04276 }
04277
04278 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04279 {
04280 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04281 }
04282
04283 static openr2_event_interface_t dahdi_r2_event_iface = {
04284 .on_call_init = dahdi_r2_on_call_init,
04285 .on_call_offered = dahdi_r2_on_call_offered,
04286 .on_call_accepted = dahdi_r2_on_call_accepted,
04287 .on_call_answered = dahdi_r2_on_call_answered,
04288 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04289 .on_call_end = dahdi_r2_on_call_end,
04290 .on_call_read = dahdi_r2_on_call_read,
04291 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04292 .on_os_error = dahdi_r2_on_os_error,
04293 .on_protocol_error = dahdi_r2_on_protocol_error,
04294 .on_line_blocked = dahdi_r2_on_line_blocked,
04295 .on_line_idle = dahdi_r2_on_line_idle,
04296
04297 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04298 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04299 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04300
04301 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04302 };
04303
04304 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04305 {
04306 return AST_ALAW(sample);
04307 }
04308
04309 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04310 {
04311 return AST_LIN2A(sample);
04312 }
04313
04314 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04315 dahdi_r2_alaw_to_linear,
04316 dahdi_r2_linear_to_alaw
04317 };
04318
04319 #endif
04320
04321 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04322 {
04323 int tchan;
04324 int tinthreeway;
04325 struct ast_channel *towner;
04326
04327 ast_debug(1, "Swapping %d and %d\n", a, b);
04328
04329 tchan = p->subs[a].chan;
04330 towner = p->subs[a].owner;
04331 tinthreeway = p->subs[a].inthreeway;
04332
04333 p->subs[a].chan = p->subs[b].chan;
04334 p->subs[a].owner = p->subs[b].owner;
04335 p->subs[a].inthreeway = p->subs[b].inthreeway;
04336
04337 p->subs[b].chan = tchan;
04338 p->subs[b].owner = towner;
04339 p->subs[b].inthreeway = tinthreeway;
04340
04341 if (p->subs[a].owner)
04342 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04343 if (p->subs[b].owner)
04344 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04345 wakeup_sub(p, a);
04346 wakeup_sub(p, b);
04347 }
04348
04349 static int dahdi_open(char *fn)
04350 {
04351 int fd;
04352 int isnum;
04353 int chan = 0;
04354 int bs;
04355 int x;
04356 isnum = 1;
04357 for (x = 0; x < strlen(fn); x++) {
04358 if (!isdigit(fn[x])) {
04359 isnum = 0;
04360 break;
04361 }
04362 }
04363 if (isnum) {
04364 chan = atoi(fn);
04365 if (chan < 1) {
04366 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04367 return -1;
04368 }
04369 fn = "/dev/dahdi/channel";
04370 }
04371 fd = open(fn, O_RDWR | O_NONBLOCK);
04372 if (fd < 0) {
04373 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04374 return -1;
04375 }
04376 if (chan) {
04377 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04378 x = errno;
04379 close(fd);
04380 errno = x;
04381 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04382 return -1;
04383 }
04384 }
04385 bs = READ_SIZE;
04386 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04387 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04388 x = errno;
04389 close(fd);
04390 errno = x;
04391 return -1;
04392 }
04393 return fd;
04394 }
04395
04396 static void dahdi_close(int fd)
04397 {
04398 if (fd > 0)
04399 close(fd);
04400 }
04401
04402 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04403 {
04404 dahdi_close(chan_pvt->subs[sub_num].dfd);
04405 chan_pvt->subs[sub_num].dfd = -1;
04406 }
04407
04408 #if defined(HAVE_PRI)
04409 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04410 {
04411 dahdi_close(pri->pri.fds[fd_num]);
04412 pri->pri.fds[fd_num] = -1;
04413 }
04414 #endif
04415
04416 #if defined(HAVE_SS7)
04417 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04418 {
04419 dahdi_close(ss7->ss7.fds[fd_num]);
04420 ss7->ss7.fds[fd_num] = -1;
04421 }
04422 #endif
04423
04424 static int dahdi_setlinear(int dfd, int linear)
04425 {
04426 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04427 }
04428
04429
04430 static int alloc_sub(struct dahdi_pvt *p, int x)
04431 {
04432 struct dahdi_bufferinfo bi;
04433 int res;
04434 if (p->subs[x].dfd >= 0) {
04435 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04436 return -1;
04437 }
04438
04439 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04440 if (p->subs[x].dfd <= -1) {
04441 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04442 return -1;
04443 }
04444
04445 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04446 if (!res) {
04447 bi.txbufpolicy = p->buf_policy;
04448 bi.rxbufpolicy = p->buf_policy;
04449 bi.numbufs = p->buf_no;
04450 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04451 if (res < 0) {
04452 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04453 }
04454 } else
04455 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04456
04457 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04458 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04459 dahdi_close_sub(p, x);
04460 p->subs[x].dfd = -1;
04461 return -1;
04462 }
04463 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04464 return 0;
04465 }
04466
04467 static int unalloc_sub(struct dahdi_pvt *p, int x)
04468 {
04469 if (!x) {
04470 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04471 return -1;
04472 }
04473 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04474 dahdi_close_sub(p, x);
04475 p->subs[x].linear = 0;
04476 p->subs[x].chan = 0;
04477 p->subs[x].owner = NULL;
04478 p->subs[x].inthreeway = 0;
04479 p->polarity = POLARITY_IDLE;
04480 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04481 return 0;
04482 }
04483
04484 static int digit_to_dtmfindex(char digit)
04485 {
04486 if (isdigit(digit))
04487 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04488 else if (digit >= 'A' && digit <= 'D')
04489 return DAHDI_TONE_DTMF_A + (digit - 'A');
04490 else if (digit >= 'a' && digit <= 'd')
04491 return DAHDI_TONE_DTMF_A + (digit - 'a');
04492 else if (digit == '*')
04493 return DAHDI_TONE_DTMF_s;
04494 else if (digit == '#')
04495 return DAHDI_TONE_DTMF_p;
04496 else
04497 return -1;
04498 }
04499
04500 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04501 {
04502 struct dahdi_pvt *pvt;
04503 int idx;
04504 int dtmf = -1;
04505 int res;
04506
04507 pvt = chan->tech_pvt;
04508
04509 ast_mutex_lock(&pvt->lock);
04510
04511 idx = dahdi_get_index(chan, pvt, 0);
04512
04513 if ((idx != SUB_REAL) || !pvt->owner)
04514 goto out;
04515
04516 #ifdef HAVE_PRI
04517 switch (pvt->sig) {
04518 case SIG_PRI_LIB_HANDLE_CASES:
04519 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04520 if (!res)
04521 goto out;
04522 break;
04523 default:
04524 break;
04525 }
04526 #endif
04527 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04528 goto out;
04529
04530 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04531 struct dahdi_dialoperation zo = {
04532 .op = DAHDI_DIAL_OP_APPEND,
04533 };
04534
04535 zo.dialstr[0] = 'T';
04536 zo.dialstr[1] = digit;
04537 zo.dialstr[2] = '\0';
04538 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04539 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04540 chan->name, digit, strerror(errno));
04541 else
04542 pvt->dialing = 1;
04543 } else {
04544 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04545 chan->name, digit);
04546 pvt->dialing = 1;
04547 pvt->begindigit = digit;
04548 }
04549
04550 out:
04551 ast_mutex_unlock(&pvt->lock);
04552
04553 return 0;
04554 }
04555
04556 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04557 {
04558 struct dahdi_pvt *pvt;
04559 int res = 0;
04560 int idx;
04561 int x;
04562
04563 pvt = chan->tech_pvt;
04564
04565 ast_mutex_lock(&pvt->lock);
04566
04567 idx = dahdi_get_index(chan, pvt, 0);
04568
04569 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04570 goto out;
04571
04572 #ifdef HAVE_PRI
04573
04574 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04575 goto out;
04576 }
04577 #endif
04578
04579 if (pvt->begindigit) {
04580 x = -1;
04581 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04582 chan->name, digit);
04583 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04584 pvt->dialing = 0;
04585 pvt->begindigit = 0;
04586 }
04587
04588 out:
04589 ast_mutex_unlock(&pvt->lock);
04590
04591 return res;
04592 }
04593
04594 static const char * const events[] = {
04595 "No event",
04596 "On hook",
04597 "Ring/Answered",
04598 "Wink/Flash",
04599 "Alarm",
04600 "No more alarm",
04601 "HDLC Abort",
04602 "HDLC Overrun",
04603 "HDLC Bad FCS",
04604 "Dial Complete",
04605 "Ringer On",
04606 "Ringer Off",
04607 "Hook Transition Complete",
04608 "Bits Changed",
04609 "Pulse Start",
04610 "Timer Expired",
04611 "Timer Ping",
04612 "Polarity Reversal",
04613 "Ring Begin",
04614 };
04615
04616 static struct {
04617 int alarm;
04618 char *name;
04619 } alarms[] = {
04620 { DAHDI_ALARM_RED, "Red Alarm" },
04621 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04622 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04623 { DAHDI_ALARM_RECOVER, "Recovering" },
04624 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04625 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04626 { DAHDI_ALARM_NONE, "None" },
04627 };
04628
04629 static char *alarm2str(int alm)
04630 {
04631 int x;
04632 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04633 if (alarms[x].alarm & alm)
04634 return alarms[x].name;
04635 }
04636 return alm ? "Unknown Alarm" : "No Alarm";
04637 }
04638
04639 static const char *event2str(int event)
04640 {
04641 static char buf[256];
04642 if ((event < (ARRAY_LEN(events))) && (event > -1))
04643 return events[event];
04644 sprintf(buf, "Event %d", event);
04645 return buf;
04646 }
04647
04648 static char *dahdi_sig2str(int sig)
04649 {
04650 static char buf[256];
04651 switch (sig) {
04652 case SIG_EM:
04653 return "E & M Immediate";
04654 case SIG_EMWINK:
04655 return "E & M Wink";
04656 case SIG_EM_E1:
04657 return "E & M E1";
04658 case SIG_FEATD:
04659 return "Feature Group D (DTMF)";
04660 case SIG_FEATDMF:
04661 return "Feature Group D (MF)";
04662 case SIG_FEATDMF_TA:
04663 return "Feature Groud D (MF) Tandem Access";
04664 case SIG_FEATB:
04665 return "Feature Group B (MF)";
04666 case SIG_E911:
04667 return "E911 (MF)";
04668 case SIG_FGC_CAMA:
04669 return "FGC/CAMA (Dialpulse)";
04670 case SIG_FGC_CAMAMF:
04671 return "FGC/CAMA (MF)";
04672 case SIG_FXSLS:
04673 return "FXS Loopstart";
04674 case SIG_FXSGS:
04675 return "FXS Groundstart";
04676 case SIG_FXSKS:
04677 return "FXS Kewlstart";
04678 case SIG_FXOLS:
04679 return "FXO Loopstart";
04680 case SIG_FXOGS:
04681 return "FXO Groundstart";
04682 case SIG_FXOKS:
04683 return "FXO Kewlstart";
04684 case SIG_PRI:
04685 return "ISDN PRI";
04686 case SIG_BRI:
04687 return "ISDN BRI Point to Point";
04688 case SIG_BRI_PTMP:
04689 return "ISDN BRI Point to MultiPoint";
04690 case SIG_SS7:
04691 return "SS7";
04692 case SIG_MFCR2:
04693 return "MFC/R2";
04694 case SIG_SF:
04695 return "SF (Tone) Immediate";
04696 case SIG_SFWINK:
04697 return "SF (Tone) Wink";
04698 case SIG_SF_FEATD:
04699 return "SF (Tone) with Feature Group D (DTMF)";
04700 case SIG_SF_FEATDMF:
04701 return "SF (Tone) with Feature Group D (MF)";
04702 case SIG_SF_FEATB:
04703 return "SF (Tone) with Feature Group B (MF)";
04704 case 0:
04705 return "Pseudo";
04706 default:
04707 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04708 return buf;
04709 }
04710 }
04711
04712 #define sig2str dahdi_sig2str
04713
04714 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04715 {
04716
04717
04718 struct dahdi_confinfo zi;
04719
04720 memset(&zi, 0, sizeof(zi));
04721 zi.chan = 0;
04722
04723 if (slavechannel > 0) {
04724
04725 zi.confmode = DAHDI_CONF_DIGITALMON;
04726 zi.confno = slavechannel;
04727 } else {
04728 if (!idx) {
04729
04730 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04731 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04732 } else
04733 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04734 zi.confno = p->confno;
04735 }
04736 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04737 return 0;
04738 if (c->dfd < 0)
04739 return 0;
04740 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04741 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04742 return -1;
04743 }
04744 if (slavechannel < 1) {
04745 p->confno = zi.confno;
04746 }
04747 c->curconf = zi;
04748 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04749 return 0;
04750 }
04751
04752 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04753 {
04754
04755 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04756 return 1;
04757
04758 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04759 return 1;
04760 return 0;
04761 }
04762
04763 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04764 {
04765 struct dahdi_confinfo zi;
04766 if (
04767 (c->dfd < 0) ||
04768
04769 !isourconf(p, c)
04770
04771 ) return 0;
04772 memset(&zi, 0, sizeof(zi));
04773 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04774 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04775 return -1;
04776 }
04777 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04778 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04779 return 0;
04780 }
04781
04782 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04783 {
04784 int x;
04785 int useslavenative;
04786 struct dahdi_pvt *slave = NULL;
04787
04788 useslavenative = 1;
04789
04790 for (x = 0; x < 3; x++) {
04791
04792
04793 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04794 useslavenative = 0;
04795 }
04796
04797
04798 if (useslavenative) {
04799 for (x = 0; x < MAX_SLAVES; x++) {
04800 if (p->slaves[x]) {
04801 if (slave) {
04802
04803
04804 slave = NULL;
04805 useslavenative = 0;
04806 break;
04807 } else {
04808
04809 slave = p->slaves[x];
04810 }
04811 }
04812 }
04813 }
04814
04815 if (!slave)
04816 useslavenative = 0;
04817 else if (slave->law != p->law) {
04818 useslavenative = 0;
04819 slave = NULL;
04820 }
04821 if (out)
04822 *out = slave;
04823 return useslavenative;
04824 }
04825
04826 static int reset_conf(struct dahdi_pvt *p)
04827 {
04828 p->confno = -1;
04829 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04830 if (p->subs[SUB_REAL].dfd > -1) {
04831 struct dahdi_confinfo zi;
04832
04833 memset(&zi, 0, sizeof(zi));
04834 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04835 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04836 }
04837 return 0;
04838 }
04839
04840 static int update_conf(struct dahdi_pvt *p)
04841 {
04842 int needconf = 0;
04843 int x;
04844 int useslavenative;
04845 struct dahdi_pvt *slave = NULL;
04846
04847 useslavenative = isslavenative(p, &slave);
04848
04849 for (x = 0; x < 3; x++) {
04850
04851 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04852 conf_add(p, &p->subs[x], x, 0);
04853 needconf++;
04854 } else {
04855 conf_del(p, &p->subs[x], x);
04856 }
04857 }
04858
04859
04860 for (x = 0; x < MAX_SLAVES; x++) {
04861 if (p->slaves[x]) {
04862 if (useslavenative)
04863 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04864 else {
04865 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04866 needconf++;
04867 }
04868 }
04869 }
04870
04871 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04872 if (useslavenative)
04873 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04874 else {
04875 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04876 needconf++;
04877 }
04878 }
04879
04880 if (p->master) {
04881 if (isslavenative(p->master, NULL)) {
04882 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04883 } else {
04884 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04885 }
04886 }
04887 if (!needconf) {
04888
04889
04890 p->confno = -1;
04891 }
04892 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04893 return 0;
04894 }
04895
04896 static void dahdi_enable_ec(struct dahdi_pvt *p)
04897 {
04898 int res;
04899 if (!p)
04900 return;
04901 if (p->echocanon) {
04902 ast_debug(1, "Echo cancellation already on\n");
04903 return;
04904 }
04905 if (p->digital) {
04906 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04907 return;
04908 }
04909 if (p->echocancel.head.tap_length) {
04910 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04911 switch (p->sig) {
04912 #if defined(HAVE_PRI)
04913 case SIG_PRI_LIB_HANDLE_CASES:
04914 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04915
04916
04917
04918
04919 return;
04920 }
04921
04922 #endif
04923 #if defined(HAVE_SS7)
04924 case SIG_SS7:
04925 #endif
04926 {
04927 int x = 1;
04928
04929 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04930 if (res)
04931 ast_log(LOG_WARNING,
04932 "Unable to enable audio mode on channel %d (%s)\n",
04933 p->channel, strerror(errno));
04934 }
04935 break;
04936 default:
04937 break;
04938 }
04939 #endif
04940 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04941 if (res) {
04942 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04943 } else {
04944 p->echocanon = 1;
04945 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04946 }
04947 } else
04948 ast_debug(1, "No echo cancellation requested\n");
04949 }
04950
04951 static void dahdi_train_ec(struct dahdi_pvt *p)
04952 {
04953 int x;
04954 int res;
04955
04956 if (p && p->echocanon && p->echotraining) {
04957 x = p->echotraining;
04958 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04959 if (res)
04960 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04961 else
04962 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04963 } else {
04964 ast_debug(1, "No echo training requested\n");
04965 }
04966 }
04967
04968 static void dahdi_disable_ec(struct dahdi_pvt *p)
04969 {
04970 int res;
04971
04972 if (p->echocanon) {
04973 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04974
04975 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04976
04977 if (res)
04978 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04979 else
04980 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04981 }
04982
04983 p->echocanon = 0;
04984 }
04985
04986
04987 static int drc_sample(int sample, float drc)
04988 {
04989 float neg;
04990 float shallow, steep;
04991 float max = SHRT_MAX;
04992
04993 neg = (sample < 0 ? -1 : 1);
04994 steep = drc*sample;
04995 shallow = neg*(max-max/drc)+(float)sample/drc;
04996 if (abs(steep) < abs(shallow)) {
04997 sample = steep;
04998 }
04999 else {
05000 sample = shallow;
05001 }
05002
05003 return sample;
05004 }
05005
05006
05007 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05008 {
05009 int j;
05010 int k;
05011
05012 float linear_gain = pow(10.0, gain / 20.0);
05013
05014 switch (law) {
05015 case DAHDI_LAW_ALAW:
05016 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05017 if (gain || drc) {
05018 k = AST_ALAW(j);
05019 if (drc) {
05020 k = drc_sample(k, drc);
05021 }
05022 k = (float)k * linear_gain;
05023 if (k > 32767) {
05024 k = 32767;
05025 } else if (k < -32768) {
05026 k = -32768;
05027 }
05028 g->txgain[j] = AST_LIN2A(k);
05029 } else {
05030 g->txgain[j] = j;
05031 }
05032 }
05033 break;
05034 case DAHDI_LAW_MULAW:
05035 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05036 if (gain || drc) {
05037 k = AST_MULAW(j);
05038 if (drc) {
05039 k = drc_sample(k, drc);
05040 }
05041 k = (float)k * linear_gain;
05042 if (k > 32767) {
05043 k = 32767;
05044 } else if (k < -32768) {
05045 k = -32768;
05046 }
05047 g->txgain[j] = AST_LIN2MU(k);
05048
05049 } else {
05050 g->txgain[j] = j;
05051 }
05052 }
05053 break;
05054 }
05055 }
05056
05057 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05058 {
05059 int j;
05060 int k;
05061 float linear_gain = pow(10.0, gain / 20.0);
05062
05063 switch (law) {
05064 case DAHDI_LAW_ALAW:
05065 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05066 if (gain || drc) {
05067 k = AST_ALAW(j);
05068 if (drc) {
05069 k = drc_sample(k, drc);
05070 }
05071 k = (float)k * linear_gain;
05072 if (k > 32767) {
05073 k = 32767;
05074 } else if (k < -32768) {
05075 k = -32768;
05076 }
05077 g->rxgain[j] = AST_LIN2A(k);
05078 } else {
05079 g->rxgain[j] = j;
05080 }
05081 }
05082 break;
05083 case DAHDI_LAW_MULAW:
05084 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05085 if (gain || drc) {
05086 k = AST_MULAW(j);
05087 if (drc) {
05088 k = drc_sample(k, drc);
05089 }
05090 k = (float)k * linear_gain;
05091 if (k > 32767) {
05092 k = 32767;
05093 } else if (k < -32768) {
05094 k = -32768;
05095 }
05096 g->rxgain[j] = AST_LIN2MU(k);
05097 } else {
05098 g->rxgain[j] = j;
05099 }
05100 }
05101 break;
05102 }
05103 }
05104
05105 static int set_actual_txgain(int fd, float gain, float drc, int law)
05106 {
05107 struct dahdi_gains g;
05108 int res;
05109
05110 memset(&g, 0, sizeof(g));
05111 res = ioctl(fd, DAHDI_GETGAINS, &g);
05112 if (res) {
05113 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05114 return res;
05115 }
05116
05117 fill_txgain(&g, gain, drc, law);
05118
05119 return ioctl(fd, DAHDI_SETGAINS, &g);
05120 }
05121
05122 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05123 {
05124 struct dahdi_gains g;
05125 int res;
05126
05127 memset(&g, 0, sizeof(g));
05128 res = ioctl(fd, DAHDI_GETGAINS, &g);
05129 if (res) {
05130 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05131 return res;
05132 }
05133
05134 fill_rxgain(&g, gain, drc, law);
05135
05136 return ioctl(fd, DAHDI_SETGAINS, &g);
05137 }
05138
05139 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05140 {
05141 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05142 }
05143
05144 static int bump_gains(struct dahdi_pvt *p)
05145 {
05146 int res;
05147
05148
05149 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05150 if (res) {
05151 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05152 return -1;
05153 }
05154
05155 return 0;
05156 }
05157
05158 static int restore_gains(struct dahdi_pvt *p)
05159 {
05160 int res;
05161
05162 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05163 if (res) {
05164 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05165 return -1;
05166 }
05167
05168 return 0;
05169 }
05170
05171 static inline int dahdi_set_hook(int fd, int hs)
05172 {
05173 int x, res;
05174
05175 x = hs;
05176 res = ioctl(fd, DAHDI_HOOK, &x);
05177
05178 if (res < 0) {
05179 if (errno == EINPROGRESS)
05180 return 0;
05181 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05182
05183 }
05184
05185 return res;
05186 }
05187
05188 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05189 {
05190 int x, res;
05191
05192 x = muted;
05193 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05194 switch (p->sig) {
05195 #if defined(HAVE_PRI)
05196 case SIG_PRI_LIB_HANDLE_CASES:
05197 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05198
05199 break;
05200 }
05201
05202 #endif
05203 #if defined(HAVE_SS7)
05204 case SIG_SS7:
05205 #endif
05206 {
05207 int y = 1;
05208
05209 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05210 if (res)
05211 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05212 p->channel, strerror(errno));
05213 }
05214 break;
05215 default:
05216 break;
05217 }
05218 #endif
05219 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05220 if (res < 0)
05221 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05222 return res;
05223 }
05224
05225 static int save_conference(struct dahdi_pvt *p)
05226 {
05227 struct dahdi_confinfo c;
05228 int res;
05229 if (p->saveconf.confmode) {
05230 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05231 return -1;
05232 }
05233 p->saveconf.chan = 0;
05234 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05235 if (res) {
05236 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05237 p->saveconf.confmode = 0;
05238 return -1;
05239 }
05240 memset(&c, 0, sizeof(c));
05241 c.confmode = DAHDI_CONF_NORMAL;
05242 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05243 if (res) {
05244 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05245 return -1;
05246 }
05247 ast_debug(1, "Disabled conferencing\n");
05248 return 0;
05249 }
05250
05251 static int restore_conference(struct dahdi_pvt *p)
05252 {
05253 int res;
05254 if (p->saveconf.confmode) {
05255 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05256 p->saveconf.confmode = 0;
05257 if (res) {
05258 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05259 return -1;
05260 }
05261 ast_debug(1, "Restored conferencing\n");
05262 }
05263 return 0;
05264 }
05265
05266 static int send_cwcidspill(struct dahdi_pvt *p)
05267 {
05268 p->callwaitcas = 0;
05269 p->cidcwexpire = 0;
05270 p->cid_suppress_expire = 0;
05271 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05272 return -1;
05273 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05274
05275 p->cidlen += READ_SIZE * 4;
05276 p->cidpos = 0;
05277 send_callerid(p);
05278 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05279 return 0;
05280 }
05281
05282 static int has_voicemail(struct dahdi_pvt *p)
05283 {
05284 int new_msgs;
05285 struct ast_event *event;
05286 char *mailbox, *context;
05287
05288 mailbox = context = ast_strdupa(p->mailbox);
05289 strsep(&context, "@");
05290 if (ast_strlen_zero(context))
05291 context = "default";
05292
05293 event = ast_event_get_cached(AST_EVENT_MWI,
05294 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05295 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05296 AST_EVENT_IE_END);
05297
05298 if (event) {
05299 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05300 ast_event_destroy(event);
05301 } else
05302 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05303
05304 return new_msgs;
05305 }
05306
05307
05308
05309 static int send_callerid(struct dahdi_pvt *p)
05310 {
05311
05312 int res;
05313
05314 if (p->subs[SUB_REAL].linear) {
05315 p->subs[SUB_REAL].linear = 0;
05316 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05317 }
05318 while (p->cidpos < p->cidlen) {
05319 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05320 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05321 if (res < 0) {
05322 if (errno == EAGAIN)
05323 return 0;
05324 else {
05325 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05326 return -1;
05327 }
05328 }
05329 if (!res)
05330 return 0;
05331 p->cidpos += res;
05332 }
05333 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05334 ast_free(p->cidspill);
05335 p->cidspill = NULL;
05336 if (p->callwaitcas) {
05337
05338 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05339 p->cid_suppress_expire = p->cidcwexpire;
05340 } else
05341 restore_conference(p);
05342 return 0;
05343 }
05344
05345 static int dahdi_callwait(struct ast_channel *ast)
05346 {
05347 struct dahdi_pvt *p = ast->tech_pvt;
05348 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05349 if (p->cidspill) {
05350 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05351 ast_free(p->cidspill);
05352 }
05353
05354
05355
05356
05357
05358 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05359 return -1;
05360 save_conference(p);
05361
05362 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05363 if (!p->callwaitrings && p->callwaitingcallerid) {
05364 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05365 p->callwaitcas = 1;
05366 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05367 } else {
05368 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05369 p->callwaitcas = 0;
05370 p->cidlen = 2400 + READ_SIZE * 4;
05371 }
05372 p->cidpos = 0;
05373 send_callerid(p);
05374
05375 return 0;
05376 }
05377
05378 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05379 {
05380 struct dahdi_pvt *p = ast->tech_pvt;
05381 int x, res, mysig;
05382 char dest[256];
05383
05384 ast_mutex_lock(&p->lock);
05385 ast_copy_string(dest, rdest, sizeof(dest));
05386 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05387 if ((ast->_state == AST_STATE_BUSY)) {
05388 p->subs[SUB_REAL].needbusy = 1;
05389 ast_mutex_unlock(&p->lock);
05390 return 0;
05391 }
05392 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05393 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05394 ast_mutex_unlock(&p->lock);
05395 return -1;
05396 }
05397 p->waitingfordt.tv_sec = 0;
05398 p->dialednone = 0;
05399 if ((p->radio || (p->oprmode < 0)))
05400 {
05401
05402 ast_setstate(ast, AST_STATE_UP);
05403 ast_mutex_unlock(&p->lock);
05404 return 0;
05405 }
05406 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05407 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05408 if (res)
05409 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05410 p->outgoing = 1;
05411
05412 if (IS_DIGITAL(ast->transfercapability)){
05413 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05414 } else {
05415 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05416 }
05417
05418 #ifdef HAVE_PRI
05419 if (dahdi_sig_pri_lib_handles(p->sig)) {
05420 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05421 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05422 ast_mutex_unlock(&p->lock);
05423 return res;
05424 }
05425 #endif
05426
05427 #if defined(HAVE_SS7)
05428 if (p->sig == SIG_SS7) {
05429 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05430 ast_mutex_unlock(&p->lock);
05431 return res;
05432 }
05433 #endif
05434
05435
05436 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05437 p->callwaitrings = 0;
05438 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05439 ast_mutex_unlock(&p->lock);
05440 return res;
05441 }
05442
05443 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05444 switch (mysig) {
05445 case 0:
05446
05447 ast_setstate(ast, AST_STATE_UP);
05448 break;
05449 case SIG_MFCR2:
05450 break;
05451 default:
05452 ast_debug(1, "not yet implemented\n");
05453 ast_mutex_unlock(&p->lock);
05454 return -1;
05455 }
05456
05457 #ifdef HAVE_OPENR2
05458 if (p->mfcr2) {
05459 openr2_calling_party_category_t chancat;
05460 int callres = 0;
05461 char *c, *l;
05462
05463
05464 p->dialdest[0] = '\0';
05465
05466 c = strchr(dest, '/');
05467 if (c) {
05468 c++;
05469 } else {
05470 c = "";
05471 }
05472 if (!p->hidecallerid) {
05473 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05474 } else {
05475 l = NULL;
05476 }
05477 if (strlen(c) < p->stripmsd) {
05478 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05479 ast_mutex_unlock(&p->lock);
05480 return -1;
05481 }
05482 p->dialing = 1;
05483 chancat = dahdi_r2_get_channel_category(ast);
05484 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05485 if (-1 == callres) {
05486 ast_mutex_unlock(&p->lock);
05487 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05488 return -1;
05489 }
05490 p->mfcr2_call_accepted = 0;
05491 p->mfcr2_progress = 0;
05492 ast_setstate(ast, AST_STATE_DIALING);
05493 }
05494 #endif
05495 ast_mutex_unlock(&p->lock);
05496 return 0;
05497 }
05498
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513
05514 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05515 {
05516 struct dahdi_pvt *cur;
05517
05518 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05519
05520
05521 for (cur = iflist; cur; cur = cur->next) {
05522 if (pvt->channel < cur->channel) {
05523
05524 pvt->prev = cur->prev;
05525 pvt->next = cur;
05526 if (cur->prev) {
05527
05528 cur->prev->next = pvt;
05529 } else {
05530
05531 iflist = pvt;
05532 }
05533 cur->prev = pvt;
05534 return;
05535 }
05536 }
05537
05538
05539 pvt->prev = ifend;
05540 pvt->next = NULL;
05541 if (ifend) {
05542 ifend->next = pvt;
05543 }
05544 ifend = pvt;
05545 if (!iflist) {
05546
05547 iflist = pvt;
05548 }
05549 }
05550
05551
05552
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563
05564 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05565 {
05566
05567 if (pvt->prev) {
05568 pvt->prev->next = pvt->next;
05569 } else if (iflist == pvt) {
05570
05571 iflist = pvt->next;
05572 }
05573
05574
05575 if (pvt->next) {
05576 pvt->next->prev = pvt->prev;
05577 } else if (ifend == pvt) {
05578
05579 ifend = pvt->prev;
05580 }
05581
05582
05583 pvt->which_iflist = DAHDI_IFLIST_NONE;
05584 pvt->prev = NULL;
05585 pvt->next = NULL;
05586 }
05587
05588 #if defined(HAVE_PRI)
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599
05600
05601
05602
05603
05604
05605 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05606 {
05607 struct dahdi_pvt *cur;
05608
05609 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05610
05611
05612 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05613 if (pvt->channel < cur->channel) {
05614
05615 pvt->prev = cur->prev;
05616 pvt->next = cur;
05617 if (cur->prev) {
05618
05619 cur->prev->next = pvt;
05620 } else {
05621
05622 pri->no_b_chan_iflist = pvt;
05623 }
05624 cur->prev = pvt;
05625 return;
05626 }
05627 }
05628
05629
05630 pvt->prev = pri->no_b_chan_end;
05631 pvt->next = NULL;
05632 if (pri->no_b_chan_end) {
05633 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05634 }
05635 pri->no_b_chan_end = pvt;
05636 if (!pri->no_b_chan_iflist) {
05637
05638 pri->no_b_chan_iflist = pvt;
05639 }
05640 }
05641 #endif
05642
05643 #if defined(HAVE_PRI)
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653
05654
05655
05656
05657
05658 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05659 {
05660
05661 if (pvt->prev) {
05662 pvt->prev->next = pvt->next;
05663 } else if (pri->no_b_chan_iflist == pvt) {
05664
05665 pri->no_b_chan_iflist = pvt->next;
05666 }
05667
05668
05669 if (pvt->next) {
05670 pvt->next->prev = pvt->prev;
05671 } else if (pri->no_b_chan_end == pvt) {
05672
05673 pri->no_b_chan_end = pvt->prev;
05674 }
05675
05676
05677 pvt->which_iflist = DAHDI_IFLIST_NONE;
05678 pvt->prev = NULL;
05679 pvt->next = NULL;
05680 }
05681 #endif
05682
05683 #if defined(HAVE_PRI)
05684
05685
05686
05687
05688
05689
05690
05691
05692
05693 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05694 {
05695 unsigned idx;
05696 struct sig_pri_span *pri;
05697
05698 pri = pvt->pri;
05699 if (!pri) {
05700
05701 return;
05702 }
05703 ast_mutex_lock(&pri->lock);
05704 for (idx = 0; idx < pri->numchans; ++idx) {
05705 if (pri->pvts[idx] == pvt->sig_pvt) {
05706 pri->pvts[idx] = NULL;
05707 ast_mutex_unlock(&pri->lock);
05708 return;
05709 }
05710 }
05711 ast_mutex_unlock(&pri->lock);
05712 }
05713 #endif
05714
05715 #if defined(HAVE_SS7)
05716
05717
05718
05719
05720
05721
05722
05723
05724
05725 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05726 {
05727 unsigned idx;
05728 struct sig_ss7_linkset *ss7;
05729
05730 ss7 = pvt->ss7;
05731 if (!ss7) {
05732
05733 return;
05734 }
05735 ast_mutex_lock(&ss7->lock);
05736 for (idx = 0; idx < ss7->numchans; ++idx) {
05737 if (ss7->pvts[idx] == pvt->sig_pvt) {
05738 ss7->pvts[idx] = NULL;
05739 ast_mutex_unlock(&ss7->lock);
05740 return;
05741 }
05742 }
05743 ast_mutex_unlock(&ss7->lock);
05744 }
05745 #endif
05746
05747 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05748 {
05749 if (cur->next && cur->next->span == cur->span) {
05750 return cur->next;
05751 } else if (cur->prev && cur->prev->span == cur->span) {
05752 return cur->prev;
05753 }
05754
05755 return NULL;
05756 }
05757
05758 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05759 {
05760 struct dahdi_pvt *p = pvt;
05761
05762 if (p->manages_span_alarms) {
05763 struct dahdi_pvt *next = find_next_iface_in_span(p);
05764 if (next) {
05765 next->manages_span_alarms = 1;
05766 }
05767 }
05768
05769
05770 #if defined(HAVE_PRI)
05771 dahdi_unlink_pri_pvt(p);
05772 #endif
05773 #if defined(HAVE_SS7)
05774 dahdi_unlink_ss7_pvt(p);
05775 #endif
05776 switch (pvt->which_iflist) {
05777 case DAHDI_IFLIST_NONE:
05778 break;
05779 case DAHDI_IFLIST_MAIN:
05780 dahdi_iflist_extract(p);
05781 break;
05782 #if defined(HAVE_PRI)
05783 case DAHDI_IFLIST_NO_B_CHAN:
05784 if (p->pri) {
05785 dahdi_nobch_extract(p->pri, p);
05786 }
05787 break;
05788 #endif
05789 }
05790
05791 if (p->sig_pvt) {
05792 if (analog_lib_handles(p->sig, 0, 0)) {
05793 analog_delete(p->sig_pvt);
05794 }
05795 switch (p->sig) {
05796 #if defined(HAVE_PRI)
05797 case SIG_PRI_LIB_HANDLE_CASES:
05798 sig_pri_chan_delete(p->sig_pvt);
05799 break;
05800 #endif
05801 #if defined(HAVE_SS7)
05802 case SIG_SS7:
05803 sig_ss7_chan_delete(p->sig_pvt);
05804 break;
05805 #endif
05806 default:
05807 break;
05808 }
05809 }
05810 ast_free(p->cidspill);
05811 if (p->use_smdi)
05812 ast_smdi_interface_unref(p->smdi_iface);
05813 if (p->mwi_event_sub)
05814 ast_event_unsubscribe(p->mwi_event_sub);
05815 if (p->vars) {
05816 ast_variables_destroy(p->vars);
05817 }
05818 if (p->cc_params) {
05819 ast_cc_config_params_destroy(p->cc_params);
05820 }
05821 ast_mutex_destroy(&p->lock);
05822 dahdi_close_sub(p, SUB_REAL);
05823 if (p->owner)
05824 p->owner->tech_pvt = NULL;
05825 ast_free(p);
05826 }
05827
05828 static void destroy_channel(struct dahdi_pvt *cur, int now)
05829 {
05830 int i;
05831
05832 if (!now) {
05833
05834 if (cur->owner) {
05835 return;
05836 }
05837 for (i = 0; i < 3; i++) {
05838 if (cur->subs[i].owner) {
05839 return;
05840 }
05841 }
05842 }
05843 destroy_dahdi_pvt(cur);
05844 }
05845
05846 static void destroy_all_channels(void)
05847 {
05848 int chan;
05849 #if defined(HAVE_PRI)
05850 unsigned span;
05851 struct sig_pri_span *pri;
05852 #endif
05853 struct dahdi_pvt *p;
05854
05855 while (num_restart_pending) {
05856 usleep(1);
05857 }
05858
05859 ast_mutex_lock(&iflock);
05860
05861 while (iflist) {
05862 p = iflist;
05863
05864 chan = p->channel;
05865 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05866 {
05867 char db_chan_name[20];
05868 char db_answer[5];
05869 char state;
05870 int why = -1;
05871
05872 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05873 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05874 sscanf(db_answer, "%1c:%30d", &state, &why);
05875 }
05876 if (!why) {
05877
05878 ast_db_del(db_chan_name, SRVST_DBKEY);
05879 }
05880 }
05881 #endif
05882
05883 destroy_dahdi_pvt(p);
05884 ast_verb(3, "Unregistered channel %d\n", chan);
05885 }
05886 ifcount = 0;
05887 ast_mutex_unlock(&iflock);
05888
05889 #if defined(HAVE_PRI)
05890
05891 for (span = 0; span < NUM_SPANS; ++span) {
05892 if (!pris[span].dchannels[0]) {
05893 break;
05894 }
05895 pri = &pris[span].pri;
05896 ast_mutex_lock(&pri->lock);
05897 while (pri->no_b_chan_iflist) {
05898 p = pri->no_b_chan_iflist;
05899
05900
05901 destroy_dahdi_pvt(p);
05902 }
05903 ast_mutex_unlock(&pri->lock);
05904 }
05905 #endif
05906 }
05907
05908 #if defined(HAVE_PRI)
05909 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05910
05911 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05912 {
05913
05914 struct dahdi_pvt *p;
05915
05916 if (ast_strlen_zero(digits)) {
05917 ast_debug(1, "No digit string sent to application!\n");
05918 return -1;
05919 }
05920
05921 p = (struct dahdi_pvt *)chan->tech_pvt;
05922
05923 if (!p) {
05924 ast_debug(1, "Unable to find technology private\n");
05925 return -1;
05926 }
05927
05928 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05929
05930 return 0;
05931 }
05932 #endif
05933
05934 #if defined(HAVE_PRI)
05935 #if defined(HAVE_PRI_PROG_W_CAUSE)
05936 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05937
05938 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05939 {
05940
05941 struct dahdi_pvt *pvt;
05942 char *parse;
05943 int res;
05944 AST_DECLARE_APP_ARGS(args,
05945 AST_APP_ARG(destination);
05946 AST_APP_ARG(original);
05947 AST_APP_ARG(reason);
05948 );
05949
05950 if (ast_strlen_zero(data)) {
05951 ast_log(LOG_DEBUG, "No data sent to application!\n");
05952 return -1;
05953 }
05954 if (chan->tech != &dahdi_tech) {
05955 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05956 return -1;
05957 }
05958 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05959 if (!pvt) {
05960 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05961 return -1;
05962 }
05963 switch (pvt->sig) {
05964 case SIG_PRI_LIB_HANDLE_CASES:
05965 break;
05966 default:
05967 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05968 chan->name);
05969 return -1;
05970 }
05971
05972 parse = ast_strdupa(data);
05973 AST_STANDARD_APP_ARGS(args, parse);
05974
05975 if (ast_strlen_zero(args.destination)) {
05976 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05977 return -1;
05978 }
05979
05980 if (ast_strlen_zero(args.original)) {
05981 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05982 args.original = NULL;
05983 }
05984
05985 if (ast_strlen_zero(args.reason)) {
05986 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05987 args.reason = NULL;
05988 }
05989
05990 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05991 args.destination, args.original, args.reason);
05992 if (!res) {
05993
05994
05995
05996
05997 ast_safe_sleep(chan, 5000);
05998 }
05999
06000 return -1;
06001 }
06002 #endif
06003 #endif
06004
06005 #if defined(HAVE_OPENR2)
06006 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06007
06008 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06009 {
06010
06011 openr2_call_mode_t accept_mode;
06012 int res, timeout, maxloops;
06013 struct ast_frame *f;
06014 struct dahdi_pvt *p;
06015 char *parse;
06016 AST_DECLARE_APP_ARGS(args,
06017 AST_APP_ARG(charge);
06018 );
06019
06020 if (ast_strlen_zero(data)) {
06021 ast_log(LOG_DEBUG, "No data sent to application!\n");
06022 return -1;
06023 }
06024
06025 if (chan->tech != &dahdi_tech) {
06026 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06027 return -1;
06028 }
06029
06030 p = (struct dahdi_pvt *)chan->tech_pvt;
06031 if (!p) {
06032 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06033 return -1;
06034 }
06035
06036 parse = ast_strdupa(data);
06037 AST_STANDARD_APP_ARGS(args, parse);
06038
06039 if (ast_strlen_zero(args.charge)) {
06040 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06041 return -1;
06042 }
06043
06044 ast_mutex_lock(&p->lock);
06045 if (!p->mfcr2 || !p->mfcr2call) {
06046 ast_mutex_unlock(&p->lock);
06047 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06048 return -1;
06049 }
06050
06051 if (p->mfcr2_call_accepted) {
06052 ast_mutex_unlock(&p->lock);
06053 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06054 return 0;
06055 }
06056 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06057 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06058 ast_mutex_unlock(&p->lock);
06059 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06060 return -1;
06061 }
06062 ast_mutex_unlock(&p->lock);
06063
06064 res = 0;
06065 timeout = 100;
06066 maxloops = 50;
06067
06068 while (maxloops > 0) {
06069 maxloops--;
06070 if (ast_check_hangup(chan)) {
06071 break;
06072 }
06073 res = ast_waitfor(chan, timeout);
06074 if (res < 0) {
06075 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06076 res = -1;
06077 break;
06078 }
06079 if (res == 0) {
06080 continue;
06081 }
06082 res = 0;
06083 f = ast_read(chan);
06084 if (!f) {
06085 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06086 res = -1;
06087 break;
06088 }
06089 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06090 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06091 ast_frfree(f);
06092 res = -1;
06093 break;
06094 }
06095 ast_frfree(f);
06096 ast_mutex_lock(&p->lock);
06097 if (p->mfcr2_call_accepted) {
06098 ast_mutex_unlock(&p->lock);
06099 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06100 break;
06101 }
06102 ast_mutex_unlock(&p->lock);
06103 }
06104 if (res == -1) {
06105 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06106 }
06107 return res;
06108 }
06109
06110 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06111 {
06112 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06113 switch (cause) {
06114 case AST_CAUSE_USER_BUSY:
06115 case AST_CAUSE_CALL_REJECTED:
06116 case AST_CAUSE_INTERWORKING:
06117 r2cause = OR2_CAUSE_BUSY_NUMBER;
06118 break;
06119
06120 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06121 case AST_CAUSE_SWITCH_CONGESTION:
06122 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06123 break;
06124
06125 case AST_CAUSE_UNALLOCATED:
06126 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06127 break;
06128
06129 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06130 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06131 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06132 break;
06133
06134 case AST_CAUSE_NO_ANSWER:
06135 case AST_CAUSE_NO_USER_RESPONSE:
06136 r2cause = OR2_CAUSE_NO_ANSWER;
06137 break;
06138
06139 default:
06140 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06141 break;
06142 }
06143 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06144 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06145 return r2cause;
06146 }
06147 #endif
06148
06149 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06150 {
06151 if (p->bufferoverrideinuse) {
06152
06153 struct dahdi_bufferinfo bi = {
06154 .txbufpolicy = p->buf_policy,
06155 .rxbufpolicy = p->buf_policy,
06156 .bufsize = p->bufsize,
06157 .numbufs = p->buf_no
06158 };
06159 int bpres;
06160
06161 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06162 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06163 }
06164 p->bufferoverrideinuse = 0;
06165 return bpres;
06166 }
06167
06168 return -1;
06169 }
06170
06171 static int dahdi_hangup(struct ast_channel *ast)
06172 {
06173 int res = 0;
06174 int idx,x;
06175 int law;
06176
06177 struct dahdi_pvt *p = ast->tech_pvt;
06178 struct dahdi_params par;
06179
06180 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06181 if (!ast->tech_pvt) {
06182 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06183 return 0;
06184 }
06185
06186 ast_mutex_lock(&p->lock);
06187 p->exten[0] = '\0';
06188 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06189 dahdi_confmute(p, 0);
06190 restore_gains(p);
06191 p->ignoredtmf = 0;
06192 p->waitingfordt.tv_sec = 0;
06193
06194 res = analog_hangup(p->sig_pvt, ast);
06195 revert_fax_buffers(p, ast);
06196
06197 goto hangup_out;
06198 } else {
06199 p->cid_num[0] = '\0';
06200 p->cid_name[0] = '\0';
06201 p->cid_subaddr[0] = '\0';
06202 }
06203
06204 #if defined(HAVE_PRI)
06205 if (dahdi_sig_pri_lib_handles(p->sig)) {
06206 x = 1;
06207 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06208
06209 dahdi_confmute(p, 0);
06210 p->muting = 0;
06211 restore_gains(p);
06212 if (p->dsp) {
06213 ast_dsp_free(p->dsp);
06214 p->dsp = NULL;
06215 }
06216 p->ignoredtmf = 0;
06217
06218
06219 p->subs[SUB_REAL].owner = NULL;
06220 p->subs[SUB_REAL].needbusy = 0;
06221 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06222
06223 p->owner = NULL;
06224 p->cid_tag[0] = '\0';
06225 p->ringt = 0;
06226 p->distinctivering = 0;
06227 p->confirmanswer = 0;
06228 p->outgoing = 0;
06229 p->digital = 0;
06230 p->faxhandled = 0;
06231 p->pulsedial = 0;
06232
06233 revert_fax_buffers(p, ast);
06234
06235 p->law = p->law_default;
06236 law = p->law_default;
06237 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06238 if (res < 0) {
06239 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06240 p->channel, strerror(errno));
06241 }
06242
06243 sig_pri_hangup(p->sig_pvt, ast);
06244
06245 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06246 dahdi_disable_ec(p);
06247
06248 x = 0;
06249 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06250 p->didtdd = 0;
06251
06252 p->rdnis[0] = '\0';
06253 update_conf(p);
06254 reset_conf(p);
06255
06256
06257 x = 0;
06258 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06259
06260 if (num_restart_pending == 0) {
06261 restart_monitor();
06262 }
06263 goto hangup_out;
06264 }
06265 #endif
06266
06267 #if defined(HAVE_SS7)
06268 if (p->sig == SIG_SS7) {
06269 x = 1;
06270 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06271
06272 dahdi_confmute(p, 0);
06273 p->muting = 0;
06274 restore_gains(p);
06275 if (p->dsp) {
06276 ast_dsp_free(p->dsp);
06277 p->dsp = NULL;
06278 }
06279 p->ignoredtmf = 0;
06280
06281
06282 p->subs[SUB_REAL].owner = NULL;
06283 p->subs[SUB_REAL].needbusy = 0;
06284 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06285
06286 p->owner = NULL;
06287 p->ringt = 0;
06288 p->distinctivering = 0;
06289 p->confirmanswer = 0;
06290 p->outgoing = 0;
06291 p->digital = 0;
06292 p->faxhandled = 0;
06293 p->pulsedial = 0;
06294
06295 revert_fax_buffers(p, ast);
06296
06297 p->law = p->law_default;
06298 law = p->law_default;
06299 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06300 if (res < 0) {
06301 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06302 p->channel, strerror(errno));
06303 }
06304
06305 sig_ss7_hangup(p->sig_pvt, ast);
06306
06307 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06308 dahdi_disable_ec(p);
06309
06310 x = 0;
06311 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06312 p->didtdd = 0;
06313
06314 update_conf(p);
06315 reset_conf(p);
06316
06317
06318 x = 0;
06319 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06320
06321 if (num_restart_pending == 0) {
06322 restart_monitor();
06323 }
06324 goto hangup_out;
06325 }
06326 #endif
06327
06328 idx = dahdi_get_index(ast, p, 1);
06329
06330 dahdi_confmute(p, 0);
06331 p->muting = 0;
06332 restore_gains(p);
06333 if (p->origcid_num) {
06334 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06335 ast_free(p->origcid_num);
06336 p->origcid_num = NULL;
06337 }
06338 if (p->origcid_name) {
06339 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06340 ast_free(p->origcid_name);
06341 p->origcid_name = NULL;
06342 }
06343 if (p->dsp)
06344 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06345
06346 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06347 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06348 p->ignoredtmf = 0;
06349
06350 if (idx > -1) {
06351
06352 p->subs[idx].owner = NULL;
06353 p->subs[idx].needanswer = 0;
06354 p->subs[idx].needflash = 0;
06355 p->subs[idx].needringing = 0;
06356 p->subs[idx].needbusy = 0;
06357 p->subs[idx].needcongestion = 0;
06358 p->subs[idx].linear = 0;
06359 p->polarity = POLARITY_IDLE;
06360 dahdi_setlinear(p->subs[idx].dfd, 0);
06361 if (idx == SUB_REAL) {
06362 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06363 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06364 if (p->subs[SUB_CALLWAIT].inthreeway) {
06365
06366 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06367
06368 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06369 unalloc_sub(p, SUB_CALLWAIT);
06370 p->owner = NULL;
06371 } else {
06372
06373 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06374 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06375 unalloc_sub(p, SUB_THREEWAY);
06376 if (p->subs[SUB_REAL].inthreeway) {
06377
06378
06379 ast_debug(1, "Call was complete, setting owner to former third call\n");
06380 p->owner = p->subs[SUB_REAL].owner;
06381 } else {
06382
06383 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06384 p->owner = NULL;
06385 }
06386 p->subs[SUB_REAL].inthreeway = 0;
06387 }
06388 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06389
06390 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06391 unalloc_sub(p, SUB_CALLWAIT);
06392 p->owner = p->subs[SUB_REAL].owner;
06393 if (p->owner->_state != AST_STATE_UP)
06394 p->subs[SUB_REAL].needanswer = 1;
06395 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06396 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06397 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06398 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06399 unalloc_sub(p, SUB_THREEWAY);
06400 if (p->subs[SUB_REAL].inthreeway) {
06401
06402
06403 ast_debug(1, "Call was complete, setting owner to former third call\n");
06404 p->owner = p->subs[SUB_REAL].owner;
06405 } else {
06406
06407 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06408 p->owner = NULL;
06409 }
06410 p->subs[SUB_REAL].inthreeway = 0;
06411 }
06412 } else if (idx == SUB_CALLWAIT) {
06413
06414 if (p->subs[SUB_CALLWAIT].inthreeway) {
06415
06416
06417 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06418 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06419 S_OR(p->mohsuggest, NULL),
06420 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06421 }
06422 p->subs[SUB_THREEWAY].inthreeway = 0;
06423
06424 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06425 unalloc_sub(p, SUB_THREEWAY);
06426 } else
06427 unalloc_sub(p, SUB_CALLWAIT);
06428 } else if (idx == SUB_THREEWAY) {
06429 if (p->subs[SUB_CALLWAIT].inthreeway) {
06430
06431
06432 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06433 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06434 S_OR(p->mohsuggest, NULL),
06435 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06436 }
06437 p->subs[SUB_CALLWAIT].inthreeway = 0;
06438 }
06439 p->subs[SUB_REAL].inthreeway = 0;
06440
06441
06442 unalloc_sub(p, SUB_THREEWAY);
06443 } else {
06444
06445 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06446 }
06447 }
06448
06449 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06450 p->owner = NULL;
06451 p->ringt = 0;
06452 p->distinctivering = 0;
06453 p->confirmanswer = 0;
06454 p->outgoing = 0;
06455 p->digital = 0;
06456 p->faxhandled = 0;
06457 p->pulsedial = 0;
06458 if (p->dsp) {
06459 ast_dsp_free(p->dsp);
06460 p->dsp = NULL;
06461 }
06462
06463 revert_fax_buffers(p, ast);
06464
06465 p->law = p->law_default;
06466 law = p->law_default;
06467 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06468 if (res < 0)
06469 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06470
06471 #ifdef HAVE_OPENR2
06472 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06473 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06474
06475 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06476 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06477 } else {
06478 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06479 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06480 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06481 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06482 dahdi_r2_disconnect_call(p, r2cause);
06483 }
06484 } else if (p->mfcr2call) {
06485 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06486
06487
06488
06489
06490 p->mfcr2call = 0;
06491 }
06492 #endif
06493 switch (p->sig) {
06494 case SIG_SS7:
06495 case SIG_MFCR2:
06496 case SIG_PRI_LIB_HANDLE_CASES:
06497 case 0:
06498 break;
06499 default:
06500 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06501 break;
06502 }
06503 if (res < 0) {
06504 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06505 }
06506 switch (p->sig) {
06507 case SIG_FXOGS:
06508 case SIG_FXOLS:
06509 case SIG_FXOKS:
06510 memset(&par, 0, sizeof(par));
06511 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06512 if (!res) {
06513 struct analog_pvt *analog_p = p->sig_pvt;
06514 #if 0
06515 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06516 #endif
06517
06518 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06519 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06520 else
06521 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06522 analog_p->fxsoffhookstate = par.rxisoffhook;
06523 }
06524 break;
06525 case SIG_FXSGS:
06526 case SIG_FXSLS:
06527 case SIG_FXSKS:
06528
06529
06530 if (ast->_state != AST_STATE_RESERVED) {
06531 time(&p->guardtime);
06532 p->guardtime += 2;
06533 }
06534 break;
06535 default:
06536 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06537 break;
06538 }
06539 if (p->sig)
06540 dahdi_disable_ec(p);
06541 x = 0;
06542 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06543 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06544 p->didtdd = 0;
06545 p->callwaitcas = 0;
06546 p->callwaiting = p->permcallwaiting;
06547 p->hidecallerid = p->permhidecallerid;
06548 p->waitingfordt.tv_sec = 0;
06549 p->dialing = 0;
06550 p->rdnis[0] = '\0';
06551 update_conf(p);
06552 reset_conf(p);
06553
06554 switch (p->sig) {
06555 case SIG_PRI_LIB_HANDLE_CASES:
06556 case SIG_SS7:
06557 x = 0;
06558 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06559 break;
06560 default:
06561 break;
06562 }
06563 if (num_restart_pending == 0)
06564 restart_monitor();
06565 }
06566
06567 p->callwaitingrepeat = 0;
06568 p->cidcwexpire = 0;
06569 p->cid_suppress_expire = 0;
06570 p->oprmode = 0;
06571 hangup_out:
06572 ast->tech_pvt = NULL;
06573 ast_free(p->cidspill);
06574 p->cidspill = NULL;
06575
06576 ast_mutex_unlock(&p->lock);
06577 ast_verb(3, "Hungup '%s'\n", ast->name);
06578
06579 ast_mutex_lock(&iflock);
06580 if (p->restartpending) {
06581 num_restart_pending--;
06582 }
06583
06584 if (p->destroy) {
06585 destroy_channel(p, 0);
06586 }
06587 ast_mutex_unlock(&iflock);
06588
06589 ast_module_unref(ast_module_info->self);
06590 return 0;
06591 }
06592
06593 static int dahdi_answer(struct ast_channel *ast)
06594 {
06595 struct dahdi_pvt *p = ast->tech_pvt;
06596 int res = 0;
06597 int idx;
06598 ast_setstate(ast, AST_STATE_UP);
06599 ast_mutex_lock(&p->lock);
06600 idx = dahdi_get_index(ast, p, 0);
06601 if (idx < 0)
06602 idx = SUB_REAL;
06603
06604 if ((p->radio || (p->oprmode < 0))) {
06605 ast_mutex_unlock(&p->lock);
06606 return 0;
06607 }
06608
06609 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06610 res = analog_answer(p->sig_pvt, ast);
06611 ast_mutex_unlock(&p->lock);
06612 return res;
06613 }
06614
06615 switch (p->sig) {
06616 #if defined(HAVE_PRI)
06617 case SIG_PRI_LIB_HANDLE_CASES:
06618 res = sig_pri_answer(p->sig_pvt, ast);
06619 break;
06620 #endif
06621 #if defined(HAVE_SS7)
06622 case SIG_SS7:
06623 res = sig_ss7_answer(p->sig_pvt, ast);
06624 break;
06625 #endif
06626 #ifdef HAVE_OPENR2
06627 case SIG_MFCR2:
06628 if (!p->mfcr2_call_accepted) {
06629
06630
06631 p->mfcr2_answer_pending = 1;
06632 if (p->mfcr2_charge_calls) {
06633 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06634 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06635 } else {
06636 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06637 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06638 }
06639 } else {
06640 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06641 dahdi_r2_answer(p);
06642 }
06643 break;
06644 #endif
06645 case 0:
06646 ast_mutex_unlock(&p->lock);
06647 return 0;
06648 default:
06649 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06650 res = -1;
06651 break;
06652 }
06653 ast_mutex_unlock(&p->lock);
06654 return res;
06655 }
06656
06657 static void disable_dtmf_detect(struct dahdi_pvt *p)
06658 {
06659 int val = 0;
06660
06661 p->ignoredtmf = 1;
06662
06663 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06664
06665 if (!p->hardwaredtmf && p->dsp) {
06666 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06667 ast_dsp_set_features(p->dsp, p->dsp_features);
06668 }
06669 }
06670
06671 static void enable_dtmf_detect(struct dahdi_pvt *p)
06672 {
06673 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06674
06675 if (p->channel == CHAN_PSEUDO)
06676 return;
06677
06678 p->ignoredtmf = 0;
06679
06680 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06681
06682 if (!p->hardwaredtmf && p->dsp) {
06683 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06684 ast_dsp_set_features(p->dsp, p->dsp_features);
06685 }
06686 }
06687
06688 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06689 {
06690 char *cp;
06691 struct dahdi_pvt *p = chan->tech_pvt;
06692
06693
06694 if (!p || !data || (*datalen < 1)) {
06695 errno = EINVAL;
06696 return -1;
06697 }
06698
06699 switch (option) {
06700 case AST_OPTION_DIGIT_DETECT:
06701 cp = (char *) data;
06702 *cp = p->ignoredtmf ? 0 : 1;
06703 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06704 break;
06705 case AST_OPTION_FAX_DETECT:
06706 cp = (char *) data;
06707 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06708 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06709 break;
06710 case AST_OPTION_CC_AGENT_TYPE:
06711 #if defined(HAVE_PRI)
06712 #if defined(HAVE_PRI_CCSS)
06713 if (dahdi_sig_pri_lib_handles(p->sig)) {
06714 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06715 break;
06716 }
06717 #endif
06718 #endif
06719 return -1;
06720 default:
06721 return -1;
06722 }
06723
06724 errno = 0;
06725
06726 return 0;
06727 }
06728
06729 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06730 {
06731 char *cp;
06732 signed char *scp;
06733 int x;
06734 int idx;
06735 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06736 struct oprmode *oprmode;
06737
06738
06739
06740 if (!p || !data || (datalen < 1)) {
06741 errno = EINVAL;
06742 return -1;
06743 }
06744
06745 switch (option) {
06746 case AST_OPTION_TXGAIN:
06747 scp = (signed char *) data;
06748 idx = dahdi_get_index(chan, p, 0);
06749 if (idx < 0) {
06750 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06751 return -1;
06752 }
06753 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06754 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06755 case AST_OPTION_RXGAIN:
06756 scp = (signed char *) data;
06757 idx = dahdi_get_index(chan, p, 0);
06758 if (idx < 0) {
06759 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06760 return -1;
06761 }
06762 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06763 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06764 case AST_OPTION_TONE_VERIFY:
06765 if (!p->dsp)
06766 break;
06767 cp = (char *) data;
06768 switch (*cp) {
06769 case 1:
06770 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06771 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06772 break;
06773 case 2:
06774 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06775 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06776 break;
06777 default:
06778 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06779 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06780 break;
06781 }
06782 break;
06783 case AST_OPTION_TDD:
06784
06785 cp = (char *) data;
06786 p->mate = 0;
06787 if (!*cp) {
06788 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06789 if (p->tdd)
06790 tdd_free(p->tdd);
06791 p->tdd = 0;
06792 break;
06793 }
06794 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06795 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06796 dahdi_disable_ec(p);
06797
06798 if (!p->didtdd) {
06799 unsigned char mybuf[41000];
06800 unsigned char *buf;
06801 int size, res, fd, len;
06802 struct pollfd fds[1];
06803
06804 buf = mybuf;
06805 memset(buf, 0x7f, sizeof(mybuf));
06806 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06807 len = 40000;
06808 idx = dahdi_get_index(chan, p, 0);
06809 if (idx < 0) {
06810 ast_log(LOG_WARNING, "No index in TDD?\n");
06811 return -1;
06812 }
06813 fd = p->subs[idx].dfd;
06814 while (len) {
06815 if (ast_check_hangup(chan))
06816 return -1;
06817 size = len;
06818 if (size > READ_SIZE)
06819 size = READ_SIZE;
06820 fds[0].fd = fd;
06821 fds[0].events = POLLPRI | POLLOUT;
06822 fds[0].revents = 0;
06823 res = poll(fds, 1, -1);
06824 if (!res) {
06825 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06826 continue;
06827 }
06828
06829 if (fds[0].revents & POLLPRI)
06830 return -1;
06831 if (!(fds[0].revents & POLLOUT)) {
06832 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06833 continue;
06834 }
06835 res = write(fd, buf, size);
06836 if (res != size) {
06837 if (res == -1) return -1;
06838 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06839 break;
06840 }
06841 len -= size;
06842 buf += size;
06843 }
06844 p->didtdd = 1;
06845 }
06846 if (*cp == 2) {
06847 if (p->tdd)
06848 tdd_free(p->tdd);
06849 p->tdd = 0;
06850 p->mate = 1;
06851 break;
06852 }
06853 if (!p->tdd) {
06854 p->tdd = tdd_new();
06855 }
06856 break;
06857 case AST_OPTION_RELAXDTMF:
06858 if (!p->dsp)
06859 break;
06860 cp = (char *) data;
06861 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06862 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06863 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06864 break;
06865 case AST_OPTION_AUDIO_MODE:
06866 #if defined(HAVE_PRI)
06867 if (dahdi_sig_pri_lib_handles(p->sig)
06868 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06869
06870 break;
06871 }
06872 #endif
06873
06874 cp = (char *) data;
06875 if (!*cp) {
06876 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06877 x = 0;
06878 dahdi_disable_ec(p);
06879 } else {
06880 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06881 x = 1;
06882 }
06883 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06884 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06885 break;
06886 case AST_OPTION_OPRMODE:
06887 oprmode = (struct oprmode *) data;
06888
06889 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06890 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06891 chan->tech->type, oprmode->peer->tech->type);
06892 errno = EINVAL;
06893 return -1;
06894 }
06895 pp = oprmode->peer->tech_pvt;
06896 p->oprmode = pp->oprmode = 0;
06897
06898 p->oprpeer = pp;
06899 pp->oprpeer = p;
06900
06901 if (oprmode->mode)
06902 {
06903 pp->oprmode = oprmode->mode;
06904 p->oprmode = -oprmode->mode;
06905 }
06906 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06907 oprmode->mode, chan->name,oprmode->peer->name);
06908 break;
06909 case AST_OPTION_ECHOCAN:
06910 cp = (char *) data;
06911 if (*cp) {
06912 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06913 dahdi_enable_ec(p);
06914 } else {
06915 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06916 dahdi_disable_ec(p);
06917 }
06918 break;
06919 case AST_OPTION_DIGIT_DETECT:
06920 cp = (char *) data;
06921 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06922 if (*cp) {
06923 enable_dtmf_detect(p);
06924 } else {
06925 disable_dtmf_detect(p);
06926 }
06927 break;
06928 case AST_OPTION_FAX_DETECT:
06929 cp = (char *) data;
06930 if (p->dsp) {
06931 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06932 if (*cp) {
06933 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06934 } else {
06935 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06936 }
06937 ast_dsp_set_features(p->dsp, p->dsp_features);
06938 }
06939 break;
06940 default:
06941 return -1;
06942 }
06943 errno = 0;
06944
06945 return 0;
06946 }
06947
06948 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06949 {
06950 struct dahdi_pvt *p = chan->tech_pvt;
06951 int res = 0;
06952
06953 if (!p) {
06954
06955 *buf = '\0';
06956 return -1;
06957 }
06958
06959 if (!strcasecmp(data, "rxgain")) {
06960 ast_mutex_lock(&p->lock);
06961 snprintf(buf, len, "%f", p->rxgain);
06962 ast_mutex_unlock(&p->lock);
06963 } else if (!strcasecmp(data, "txgain")) {
06964 ast_mutex_lock(&p->lock);
06965 snprintf(buf, len, "%f", p->txgain);
06966 ast_mutex_unlock(&p->lock);
06967 } else if (!strcasecmp(data, "dahdi_channel")) {
06968 ast_mutex_lock(&p->lock);
06969 snprintf(buf, len, "%d", p->channel);
06970 ast_mutex_unlock(&p->lock);
06971 } else if (!strcasecmp(data, "dahdi_span")) {
06972 ast_mutex_lock(&p->lock);
06973 snprintf(buf, len, "%d", p->span);
06974 ast_mutex_unlock(&p->lock);
06975 } else if (!strcasecmp(data, "dahdi_type")) {
06976 ast_mutex_lock(&p->lock);
06977 switch (p->sig) {
06978 #if defined(HAVE_OPENR2)
06979 case SIG_MFCR2:
06980 ast_copy_string(buf, "mfc/r2", len);
06981 break;
06982 #endif
06983 #if defined(HAVE_PRI)
06984 case SIG_PRI_LIB_HANDLE_CASES:
06985 ast_copy_string(buf, "pri", len);
06986 break;
06987 #endif
06988 case 0:
06989 ast_copy_string(buf, "pseudo", len);
06990 break;
06991 #if defined(HAVE_SS7)
06992 case SIG_SS7:
06993 ast_copy_string(buf, "ss7", len);
06994 break;
06995 #endif
06996 default:
06997
06998 ast_copy_string(buf, "analog", len);
06999 break;
07000 }
07001 ast_mutex_unlock(&p->lock);
07002 #if defined(HAVE_PRI)
07003 #if defined(HAVE_PRI_REVERSE_CHARGE)
07004 } else if (!strcasecmp(data, "reversecharge")) {
07005 ast_mutex_lock(&p->lock);
07006 switch (p->sig) {
07007 case SIG_PRI_LIB_HANDLE_CASES:
07008 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07009 break;
07010 default:
07011 *buf = '\0';
07012 res = -1;
07013 break;
07014 }
07015 ast_mutex_unlock(&p->lock);
07016 #endif
07017 #if defined(HAVE_PRI_SETUP_KEYPAD)
07018 } else if (!strcasecmp(data, "keypad_digits")) {
07019 ast_mutex_lock(&p->lock);
07020 switch (p->sig) {
07021 case SIG_PRI_LIB_HANDLE_CASES:
07022 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07023 len);
07024 break;
07025 default:
07026 *buf = '\0';
07027 res = -1;
07028 break;
07029 }
07030 ast_mutex_unlock(&p->lock);
07031 #endif
07032 } else if (!strcasecmp(data, "no_media_path")) {
07033 ast_mutex_lock(&p->lock);
07034 switch (p->sig) {
07035 case SIG_PRI_LIB_HANDLE_CASES:
07036
07037
07038
07039
07040 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07041 break;
07042 default:
07043 *buf = '\0';
07044 res = -1;
07045 break;
07046 }
07047 ast_mutex_unlock(&p->lock);
07048 #endif
07049 } else {
07050 *buf = '\0';
07051 res = -1;
07052 }
07053
07054 return res;
07055 }
07056
07057
07058 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07059 {
07060 int res;
07061 char policy_str[21] = "";
07062
07063 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07064 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07065 return 1;
07066 }
07067 if (*num_buffers < 0) {
07068 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07069 return -1;
07070 }
07071 if (!strcasecmp(policy_str, "full")) {
07072 *policy = DAHDI_POLICY_WHEN_FULL;
07073 } else if (!strcasecmp(policy_str, "immediate")) {
07074 *policy = DAHDI_POLICY_IMMEDIATE;
07075 #if defined(HAVE_DAHDI_HALF_FULL)
07076 } else if (!strcasecmp(policy_str, "half")) {
07077 *policy = DAHDI_POLICY_HALF_FULL;
07078 #endif
07079 } else {
07080 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07081 return -1;
07082 }
07083
07084 return 0;
07085 }
07086
07087 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07088 {
07089 struct dahdi_pvt *p = chan->tech_pvt;
07090 int res = 0;
07091
07092 if (!p) {
07093
07094 return -1;
07095 }
07096
07097 if (!strcasecmp(data, "buffers")) {
07098 int num_bufs, policy;
07099
07100 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07101 struct dahdi_bufferinfo bi = {
07102 .txbufpolicy = policy,
07103 .rxbufpolicy = policy,
07104 .bufsize = p->bufsize,
07105 .numbufs = num_bufs,
07106 };
07107 int bpres;
07108
07109 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07110 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07111 } else {
07112 p->bufferoverrideinuse = 1;
07113 }
07114 } else {
07115 res = -1;
07116 }
07117 } else if (!strcasecmp(data, "echocan_mode")) {
07118 if (!strcasecmp(value, "on")) {
07119 ast_mutex_lock(&p->lock);
07120 dahdi_enable_ec(p);
07121 ast_mutex_unlock(&p->lock);
07122 } else if (!strcasecmp(value, "off")) {
07123 ast_mutex_lock(&p->lock);
07124 dahdi_disable_ec(p);
07125 ast_mutex_unlock(&p->lock);
07126 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07127 } else if (!strcasecmp(value, "fax")) {
07128 int blah = 1;
07129
07130 ast_mutex_lock(&p->lock);
07131 if (!p->echocanon) {
07132 dahdi_enable_ec(p);
07133 }
07134 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07135 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07136 }
07137 ast_mutex_unlock(&p->lock);
07138 } else if (!strcasecmp(value, "voice")) {
07139 int blah = 0;
07140
07141 ast_mutex_lock(&p->lock);
07142 if (!p->echocanon) {
07143 dahdi_enable_ec(p);
07144 }
07145 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07146 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07147 }
07148 ast_mutex_unlock(&p->lock);
07149 #endif
07150 } else {
07151 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07152 res = -1;
07153 }
07154 } else {
07155 res = -1;
07156 }
07157
07158 return res;
07159 }
07160
07161 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07162 {
07163
07164 int x;
07165 int hasslaves;
07166 if (!master)
07167 return;
07168 if (needlock) {
07169 ast_mutex_lock(&master->lock);
07170 if (slave) {
07171 while (ast_mutex_trylock(&slave->lock)) {
07172 DEADLOCK_AVOIDANCE(&master->lock);
07173 }
07174 }
07175 }
07176 hasslaves = 0;
07177 for (x = 0; x < MAX_SLAVES; x++) {
07178 if (master->slaves[x]) {
07179 if (!slave || (master->slaves[x] == slave)) {
07180
07181 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07182 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07183 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07184 master->slaves[x]->master = NULL;
07185 master->slaves[x] = NULL;
07186 } else
07187 hasslaves = 1;
07188 }
07189 if (!hasslaves)
07190 master->inconference = 0;
07191 }
07192 if (!slave) {
07193 if (master->master) {
07194
07195 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07196 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07197 hasslaves = 0;
07198 for (x = 0; x < MAX_SLAVES; x++) {
07199 if (master->master->slaves[x] == master)
07200 master->master->slaves[x] = NULL;
07201 else if (master->master->slaves[x])
07202 hasslaves = 1;
07203 }
07204 if (!hasslaves)
07205 master->master->inconference = 0;
07206 }
07207 master->master = NULL;
07208 }
07209 update_conf(master);
07210 if (needlock) {
07211 if (slave)
07212 ast_mutex_unlock(&slave->lock);
07213 ast_mutex_unlock(&master->lock);
07214 }
07215 }
07216
07217 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07218 int x;
07219 if (!slave || !master) {
07220 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07221 return;
07222 }
07223 for (x = 0; x < MAX_SLAVES; x++) {
07224 if (!master->slaves[x]) {
07225 master->slaves[x] = slave;
07226 break;
07227 }
07228 }
07229 if (x >= MAX_SLAVES) {
07230 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07231 master->slaves[MAX_SLAVES - 1] = slave;
07232 }
07233 if (slave->master)
07234 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07235 slave->master = master;
07236
07237 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07238 }
07239
07240 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)
07241 {
07242 struct ast_channel *who;
07243 struct dahdi_pvt *p0, *p1, *op0, *op1;
07244 struct dahdi_pvt *master = NULL, *slave = NULL;
07245 struct ast_frame *f;
07246 int inconf = 0;
07247 int nothingok = 1;
07248 int ofd0, ofd1;
07249 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07250 int os0 = -1, os1 = -1;
07251 int priority = 0;
07252 struct ast_channel *oc0, *oc1;
07253 enum ast_bridge_result res;
07254 struct timeval start = ast_tvnow();
07255 #ifdef PRI_2BCT
07256 int triedtopribridge = 0;
07257 q931_call *q931c0;
07258 q931_call *q931c1;
07259 #endif
07260
07261
07262
07263
07264
07265
07266 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07267 return AST_BRIDGE_FAILED_NOWARN;
07268
07269 ast_channel_lock(c0);
07270 while (ast_channel_trylock(c1)) {
07271 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07272 }
07273
07274 p0 = c0->tech_pvt;
07275 p1 = c1->tech_pvt;
07276
07277 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07278 ast_channel_unlock(c0);
07279 ast_channel_unlock(c1);
07280 return AST_BRIDGE_FAILED_NOWARN;
07281 }
07282
07283 oi0 = dahdi_get_index(c0, p0, 0);
07284 oi1 = dahdi_get_index(c1, p1, 0);
07285 if ((oi0 < 0) || (oi1 < 0)) {
07286 ast_channel_unlock(c0);
07287 ast_channel_unlock(c1);
07288 return AST_BRIDGE_FAILED;
07289 }
07290
07291 op0 = p0 = c0->tech_pvt;
07292 op1 = p1 = c1->tech_pvt;
07293 ofd0 = c0->fds[0];
07294 ofd1 = c1->fds[0];
07295 oc0 = p0->owner;
07296 oc1 = p1->owner;
07297
07298 if (ast_mutex_trylock(&p0->lock)) {
07299
07300 ast_channel_unlock(c0);
07301 ast_channel_unlock(c1);
07302 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07303 return AST_BRIDGE_RETRY;
07304 }
07305 if (ast_mutex_trylock(&p1->lock)) {
07306
07307 ast_mutex_unlock(&p0->lock);
07308 ast_channel_unlock(c0);
07309 ast_channel_unlock(c1);
07310 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07311 return AST_BRIDGE_RETRY;
07312 }
07313
07314 if ((p0->callwaiting && p0->callwaitingcallerid)
07315 || (p1->callwaiting && p1->callwaitingcallerid)) {
07316
07317
07318
07319
07320
07321
07322
07323
07324
07325 ast_mutex_unlock(&p0->lock);
07326 ast_mutex_unlock(&p1->lock);
07327 ast_channel_unlock(c0);
07328 ast_channel_unlock(c1);
07329 return AST_BRIDGE_FAILED_NOWARN;
07330 }
07331
07332 #if defined(HAVE_PRI)
07333 if ((dahdi_sig_pri_lib_handles(p0->sig)
07334 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07335 || (dahdi_sig_pri_lib_handles(p1->sig)
07336 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07337
07338
07339
07340
07341 ast_mutex_unlock(&p0->lock);
07342 ast_mutex_unlock(&p1->lock);
07343 ast_channel_unlock(c0);
07344 ast_channel_unlock(c1);
07345 return AST_BRIDGE_FAILED_NOWARN;
07346 }
07347 #endif
07348
07349 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07350 if (p0->owner && p1->owner) {
07351
07352 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07353 master = p0;
07354 slave = p1;
07355 inconf = 1;
07356 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07357 master = p1;
07358 slave = p0;
07359 inconf = 1;
07360 } else {
07361 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07362 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07363 p0->channel,
07364 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07365 p0->subs[SUB_REAL].inthreeway, p0->channel,
07366 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07367 p1->subs[SUB_REAL].inthreeway);
07368 }
07369 nothingok = 0;
07370 }
07371 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07372 if (p1->subs[SUB_THREEWAY].inthreeway) {
07373 master = p1;
07374 slave = p0;
07375 nothingok = 0;
07376 }
07377 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07378 if (p0->subs[SUB_THREEWAY].inthreeway) {
07379 master = p0;
07380 slave = p1;
07381 nothingok = 0;
07382 }
07383 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07384
07385
07386 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07387 master = p1;
07388 slave = p0;
07389 nothingok = 0;
07390 }
07391 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07392
07393 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07394 master = p0;
07395 slave = p1;
07396 nothingok = 0;
07397 }
07398 }
07399 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07400 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07401 if (master && slave) {
07402
07403
07404
07405 if ((oi1 == SUB_THREEWAY) &&
07406 p1->subs[SUB_THREEWAY].inthreeway &&
07407 p1->subs[SUB_REAL].owner &&
07408 p1->subs[SUB_REAL].inthreeway &&
07409 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07410 ast_debug(1,
07411 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07412 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07413 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07414 os1 = p1->subs[SUB_REAL].owner->_state;
07415 } else {
07416 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07417 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07418 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07419 }
07420 if ((oi0 == SUB_THREEWAY) &&
07421 p0->subs[SUB_THREEWAY].inthreeway &&
07422 p0->subs[SUB_REAL].owner &&
07423 p0->subs[SUB_REAL].inthreeway &&
07424 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07425 ast_debug(1,
07426 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07427 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07428 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07429 os0 = p0->subs[SUB_REAL].owner->_state;
07430 } else {
07431 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07432 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07433 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07434 }
07435 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07436 if (!p0->echocanbridged || !p1->echocanbridged) {
07437
07438 dahdi_disable_ec(p0);
07439 dahdi_disable_ec(p1);
07440 }
07441 }
07442 dahdi_link(slave, master);
07443 master->inconference = inconf;
07444 } else if (!nothingok)
07445 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07446
07447 update_conf(p0);
07448 update_conf(p1);
07449 t0 = p0->subs[SUB_REAL].inthreeway;
07450 t1 = p1->subs[SUB_REAL].inthreeway;
07451
07452 ast_mutex_unlock(&p0->lock);
07453 ast_mutex_unlock(&p1->lock);
07454
07455 ast_channel_unlock(c0);
07456 ast_channel_unlock(c1);
07457
07458
07459 if ((!master || !slave) && !nothingok) {
07460 dahdi_enable_ec(p0);
07461 dahdi_enable_ec(p1);
07462 return AST_BRIDGE_FAILED;
07463 }
07464
07465 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07466
07467 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07468 disable_dtmf_detect(op0);
07469
07470 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07471 disable_dtmf_detect(op1);
07472
07473 for (;;) {
07474 struct ast_channel *c0_priority[2] = {c0, c1};
07475 struct ast_channel *c1_priority[2] = {c1, c0};
07476 int ms;
07477
07478
07479
07480
07481 ast_channel_lock(c0);
07482 while (ast_channel_trylock(c1)) {
07483 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07484 }
07485
07486 p0 = c0->tech_pvt;
07487 p1 = c1->tech_pvt;
07488
07489 if (op0 == p0)
07490 i0 = dahdi_get_index(c0, p0, 1);
07491 if (op1 == p1)
07492 i1 = dahdi_get_index(c1, p1, 1);
07493
07494 ast_channel_unlock(c0);
07495 ast_channel_unlock(c1);
07496 ms = ast_remaining_ms(start, timeoutms);
07497 if (!ms ||
07498 (op0 != p0) ||
07499 (op1 != p1) ||
07500 (ofd0 != c0->fds[0]) ||
07501 (ofd1 != c1->fds[0]) ||
07502 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07503 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07504 (oc0 != p0->owner) ||
07505 (oc1 != p1->owner) ||
07506 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07507 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07508 (oi0 != i0) ||
07509 (oi1 != i1)) {
07510 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07511 op0->channel, oi0, op1->channel, oi1);
07512 res = AST_BRIDGE_RETRY;
07513 goto return_from_bridge;
07514 }
07515
07516 #ifdef PRI_2BCT
07517 if (!triedtopribridge) {
07518 triedtopribridge = 1;
07519 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07520 ast_mutex_lock(&p0->pri->lock);
07521 switch (p0->sig) {
07522 case SIG_PRI_LIB_HANDLE_CASES:
07523 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07524 break;
07525 default:
07526 q931c0 = NULL;
07527 break;
07528 }
07529 switch (p1->sig) {
07530 case SIG_PRI_LIB_HANDLE_CASES:
07531 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07532 break;
07533 default:
07534 q931c1 = NULL;
07535 break;
07536 }
07537 if (q931c0 && q931c1) {
07538 pri_channel_bridge(q931c0, q931c1);
07539 }
07540 ast_mutex_unlock(&p0->pri->lock);
07541 }
07542 }
07543 #endif
07544
07545 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07546 if (!who) {
07547 ast_debug(1, "Ooh, empty read...\n");
07548 continue;
07549 }
07550 f = ast_read(who);
07551 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07552 *fo = f;
07553 *rc = who;
07554 res = AST_BRIDGE_COMPLETE;
07555 goto return_from_bridge;
07556 }
07557 if (f->frametype == AST_FRAME_DTMF) {
07558 if ((who == c0) && p0->pulsedial) {
07559 ast_write(c1, f);
07560 } else if ((who == c1) && p1->pulsedial) {
07561 ast_write(c0, f);
07562 } else {
07563 *fo = f;
07564 *rc = who;
07565 res = AST_BRIDGE_COMPLETE;
07566 goto return_from_bridge;
07567 }
07568 }
07569 ast_frfree(f);
07570
07571
07572 priority = !priority;
07573 }
07574
07575 return_from_bridge:
07576 if (op0 == p0)
07577 dahdi_enable_ec(p0);
07578
07579 if (op1 == p1)
07580 dahdi_enable_ec(p1);
07581
07582 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07583 enable_dtmf_detect(op0);
07584
07585 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07586 enable_dtmf_detect(op1);
07587
07588 dahdi_unlink(slave, master, 1);
07589
07590 return res;
07591 }
07592
07593 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07594 {
07595 struct dahdi_pvt *p = newchan->tech_pvt;
07596 int x;
07597
07598 ast_mutex_lock(&p->lock);
07599
07600 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07601 if (p->owner == oldchan) {
07602 p->owner = newchan;
07603 }
07604 for (x = 0; x < 3; x++) {
07605 if (p->subs[x].owner == oldchan) {
07606 if (!x) {
07607 dahdi_unlink(NULL, p, 0);
07608 }
07609 p->subs[x].owner = newchan;
07610 }
07611 }
07612 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07613 analog_fixup(oldchan, newchan, p->sig_pvt);
07614 #if defined(HAVE_PRI)
07615 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07616 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07617 #endif
07618 #if defined(HAVE_SS7)
07619 } else if (p->sig == SIG_SS7) {
07620 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07621 #endif
07622 }
07623 update_conf(p);
07624
07625 ast_mutex_unlock(&p->lock);
07626
07627 if (newchan->_state == AST_STATE_RINGING) {
07628 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07629 }
07630 return 0;
07631 }
07632
07633 static int dahdi_ring_phone(struct dahdi_pvt *p)
07634 {
07635 int x;
07636 int res;
07637
07638 x = 0;
07639 x = DAHDI_ONHOOK;
07640 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07641 do {
07642 x = DAHDI_RING;
07643 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07644 if (res) {
07645 switch (errno) {
07646 case EBUSY:
07647 case EINTR:
07648
07649 usleep(10000);
07650 continue;
07651 case EINPROGRESS:
07652 res = 0;
07653 break;
07654 default:
07655 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07656 res = 0;
07657 }
07658 }
07659 } while (res);
07660 return res;
07661 }
07662
07663 static void *analog_ss_thread(void *data);
07664
07665 static int attempt_transfer(struct dahdi_pvt *p)
07666 {
07667
07668
07669
07670 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07671
07672
07673 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07674 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07675 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07676 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07677 }
07678 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07679 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07680 }
07681 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07682 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07683 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07684 return -1;
07685 }
07686
07687 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07688 unalloc_sub(p, SUB_THREEWAY);
07689 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07690 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07691 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07692 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07693 }
07694 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07695 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07696 }
07697 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07698 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07699 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07700 return -1;
07701 }
07702
07703 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07704 ast_channel_unlock(p->subs[SUB_REAL].owner);
07705 unalloc_sub(p, SUB_THREEWAY);
07706
07707 return 1;
07708 } else {
07709 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07710 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07711 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07712 return -1;
07713 }
07714 return 0;
07715 }
07716
07717 static int check_for_conference(struct dahdi_pvt *p)
07718 {
07719 struct dahdi_confinfo ci;
07720
07721 if (p->master || (p->confno > -1))
07722 return 0;
07723 memset(&ci, 0, sizeof(ci));
07724 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07725 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07726 return 0;
07727 }
07728
07729
07730
07731 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07732 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07733 return 1;
07734 }
07735 return 0;
07736 }
07737
07738
07739
07740
07741
07742
07743 static int get_alarms(struct dahdi_pvt *p)
07744 {
07745 int res;
07746 struct dahdi_spaninfo zi;
07747 struct dahdi_params params;
07748
07749 memset(&zi, 0, sizeof(zi));
07750 zi.spanno = p->span;
07751
07752 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07753 if (zi.alarms != DAHDI_ALARM_NONE)
07754 return zi.alarms;
07755 } else {
07756 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07757 return 0;
07758 }
07759
07760
07761 memset(¶ms, 0, sizeof(params));
07762 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07763 return params.chan_alarms;
07764
07765 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07766
07767 return DAHDI_ALARM_NONE;
07768 }
07769
07770 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07771 {
07772 struct dahdi_pvt *p = ast->tech_pvt;
07773 struct ast_frame *f = *dest;
07774
07775 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07776 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07777 (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
07778
07779 if (p->confirmanswer) {
07780 if (f->frametype == AST_FRAME_DTMF_END) {
07781 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07782
07783
07784 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07785 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07786
07787 p->confirmanswer = 0;
07788 } else {
07789 p->subs[idx].f.frametype = AST_FRAME_NULL;
07790 p->subs[idx].f.subclass.integer = 0;
07791 }
07792 *dest = &p->subs[idx].f;
07793 } else if (p->callwaitcas) {
07794 if (f->frametype == AST_FRAME_DTMF_END) {
07795 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07796 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07797 ast_free(p->cidspill);
07798 p->cidspill = NULL;
07799 send_cwcidspill(p);
07800 }
07801 p->callwaitcas = 0;
07802 }
07803 p->subs[idx].f.frametype = AST_FRAME_NULL;
07804 p->subs[idx].f.subclass.integer = 0;
07805 *dest = &p->subs[idx].f;
07806 } else if (f->subclass.integer == 'f') {
07807 if (f->frametype == AST_FRAME_DTMF_END) {
07808
07809 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07810
07811 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07812 struct dahdi_bufferinfo bi = {
07813 .txbufpolicy = p->faxbuf_policy,
07814 .bufsize = p->bufsize,
07815 .numbufs = p->faxbuf_no
07816 };
07817 int res;
07818
07819 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07820 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07821 } else {
07822 p->bufferoverrideinuse = 1;
07823 }
07824 }
07825 p->faxhandled = 1;
07826 if (p->dsp) {
07827 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07828 ast_dsp_set_features(p->dsp, p->dsp_features);
07829 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07830 }
07831 if (strcmp(ast->exten, "fax")) {
07832 const char *target_context = S_OR(ast->macrocontext, ast->context);
07833
07834
07835
07836
07837
07838 ast_mutex_unlock(&p->lock);
07839 ast_channel_unlock(ast);
07840 if (ast_exists_extension(ast, target_context, "fax", 1,
07841 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07842 ast_channel_lock(ast);
07843 ast_mutex_lock(&p->lock);
07844 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07845
07846 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07847 if (ast_async_goto(ast, target_context, "fax", 1))
07848 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07849 } else {
07850 ast_channel_lock(ast);
07851 ast_mutex_lock(&p->lock);
07852 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07853 }
07854 } else {
07855 ast_debug(1, "Already in a fax extension, not redirecting\n");
07856 }
07857 } else {
07858 ast_debug(1, "Fax already handled\n");
07859 }
07860 dahdi_confmute(p, 0);
07861 }
07862 p->subs[idx].f.frametype = AST_FRAME_NULL;
07863 p->subs[idx].f.subclass.integer = 0;
07864 *dest = &p->subs[idx].f;
07865 }
07866 }
07867
07868 static void handle_alarms(struct dahdi_pvt *p, int alms)
07869 {
07870 const char *alarm_str;
07871
07872 #if defined(HAVE_PRI)
07873 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07874 return;
07875 }
07876 #endif
07877
07878 alarm_str = alarm2str(alms);
07879 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07880 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07881 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07882 "Alarm: %s\r\n"
07883 "Channel: %d\r\n",
07884 alarm_str, p->channel);
07885 }
07886
07887 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07888 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07889 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07890 "Alarm: %s\r\n"
07891 "Span: %d\r\n",
07892 alarm_str, p->span);
07893 }
07894 }
07895
07896 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07897 {
07898 int res, x;
07899 int idx, mysig;
07900 char *c;
07901 struct dahdi_pvt *p = ast->tech_pvt;
07902 pthread_t threadid;
07903 struct ast_channel *chan;
07904 struct ast_frame *f;
07905
07906 idx = dahdi_get_index(ast, p, 0);
07907 if (idx < 0) {
07908 return &ast_null_frame;
07909 }
07910 mysig = p->sig;
07911 if (p->outsigmod > -1)
07912 mysig = p->outsigmod;
07913 p->subs[idx].f.frametype = AST_FRAME_NULL;
07914 p->subs[idx].f.subclass.integer = 0;
07915 p->subs[idx].f.datalen = 0;
07916 p->subs[idx].f.samples = 0;
07917 p->subs[idx].f.mallocd = 0;
07918 p->subs[idx].f.offset = 0;
07919 p->subs[idx].f.src = "dahdi_handle_event";
07920 p->subs[idx].f.data.ptr = NULL;
07921 f = &p->subs[idx].f;
07922
07923 if (p->fake_event) {
07924 res = p->fake_event;
07925 p->fake_event = 0;
07926 } else
07927 res = dahdi_get_event(p->subs[idx].dfd);
07928
07929 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07930
07931 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07932 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07933 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07934 #if defined(HAVE_PRI)
07935 if (dahdi_sig_pri_lib_handles(p->sig)
07936 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07937 && p->pri
07938 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07939
07940 } else
07941 #endif
07942 {
07943
07944 dahdi_confmute(p, 0);
07945 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07946 p->subs[idx].f.subclass.integer = res & 0xff;
07947 dahdi_handle_dtmf(ast, idx, &f);
07948 }
07949 return f;
07950 }
07951
07952 if (res & DAHDI_EVENT_DTMFDOWN) {
07953 ast_debug(1, "DTMF Down '%c'\n", 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, 1);
07965 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07966 p->subs[idx].f.subclass.integer = res & 0xff;
07967 dahdi_handle_dtmf(ast, idx, &f);
07968 }
07969 return &p->subs[idx].f;
07970 }
07971
07972 switch (res) {
07973 case DAHDI_EVENT_EC_DISABLED:
07974 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07975 p->echocanon = 0;
07976 break;
07977 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07978 case DAHDI_EVENT_TX_CED_DETECTED:
07979 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07980 break;
07981 case DAHDI_EVENT_RX_CED_DETECTED:
07982 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07983 break;
07984 case DAHDI_EVENT_EC_NLP_DISABLED:
07985 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07986 break;
07987 case DAHDI_EVENT_EC_NLP_ENABLED:
07988 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07989 break;
07990 #endif
07991 case DAHDI_EVENT_BITSCHANGED:
07992 #ifdef HAVE_OPENR2
07993 if (p->sig != SIG_MFCR2) {
07994 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07995 } else {
07996 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07997 openr2_chan_handle_cas(p->r2chan);
07998 }
07999 #else
08000 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08001 #endif
08002 break;
08003 case DAHDI_EVENT_PULSE_START:
08004
08005 if (!ast->pbx)
08006 tone_zone_play_tone(p->subs[idx].dfd, -1);
08007 break;
08008 case DAHDI_EVENT_DIALCOMPLETE:
08009
08010 #if defined(HAVE_PRI)
08011 if (dahdi_sig_pri_lib_handles(p->sig)) {
08012 if (p->inalarm) {
08013 break;
08014 }
08015 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08016 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08017 strerror(errno));
08018 return NULL;
08019 }
08020 if (x) {
08021
08022 break;
08023 }
08024
08025
08026
08027
08028 sig_pri_dial_complete(p->sig_pvt, ast);
08029 break;
08030 }
08031 #endif
08032 #ifdef HAVE_OPENR2
08033 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08034
08035
08036 break;
08037 }
08038 #endif
08039 if (p->inalarm) break;
08040 if ((p->radio || (p->oprmode < 0))) break;
08041 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08042 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08043 return NULL;
08044 }
08045 if (!x) {
08046 dahdi_enable_ec(p);
08047 if (p->echobreak) {
08048 dahdi_train_ec(p);
08049 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08050 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08051 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08052 p->echobreak = 0;
08053 } else {
08054 p->dialing = 0;
08055 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08056
08057 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08058 ast_setstate(ast, AST_STATE_UP);
08059 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08060 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08061 break;
08062 } else {
08063
08064 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08065 }
08066 }
08067 if (ast->_state == AST_STATE_DIALING) {
08068 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08069 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08070 } else if (p->confirmanswer || (!p->dialednone
08071 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08072 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08073 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08074 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08075 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08076 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08077 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08078 || (mysig == SIG_SF_FEATB)))) {
08079 ast_setstate(ast, AST_STATE_RINGING);
08080 } else if (!p->answeronpolarityswitch) {
08081 ast_setstate(ast, AST_STATE_UP);
08082 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08083 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08084
08085 p->polarity = POLARITY_REV;
08086 } else {
08087
08088 p->polarity = POLARITY_IDLE;
08089 }
08090 }
08091 }
08092 }
08093 break;
08094 case DAHDI_EVENT_ALARM:
08095 switch (p->sig) {
08096 #if defined(HAVE_PRI)
08097 case SIG_PRI_LIB_HANDLE_CASES:
08098 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08099 break;
08100 #endif
08101 #if defined(HAVE_SS7)
08102 case SIG_SS7:
08103 sig_ss7_set_alarm(p->sig_pvt, 1);
08104 break;
08105 #endif
08106 default:
08107 p->inalarm = 1;
08108 break;
08109 }
08110 res = get_alarms(p);
08111 handle_alarms(p, res);
08112 #ifdef HAVE_PRI
08113 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08114
08115 } else {
08116 break;
08117 }
08118 #endif
08119 #if defined(HAVE_SS7)
08120 if (p->sig == SIG_SS7)
08121 break;
08122 #endif
08123 #ifdef HAVE_OPENR2
08124 if (p->sig == SIG_MFCR2)
08125 break;
08126 #endif
08127 case DAHDI_EVENT_ONHOOK:
08128 if (p->radio) {
08129 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08130 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08131 break;
08132 }
08133 if (p->oprmode < 0)
08134 {
08135 if (p->oprmode != -1) break;
08136 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08137 {
08138
08139 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08140 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08141 save_conference(p->oprpeer);
08142 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08143 }
08144 break;
08145 }
08146 switch (p->sig) {
08147 case SIG_FXOLS:
08148 case SIG_FXOGS:
08149 case SIG_FXOKS:
08150
08151 if (idx == SUB_REAL) {
08152
08153 if (p->subs[SUB_CALLWAIT].owner) {
08154
08155 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08156 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08157 unalloc_sub(p, SUB_CALLWAIT);
08158 #if 0
08159 p->subs[idx].needanswer = 0;
08160 p->subs[idx].needringing = 0;
08161 #endif
08162 p->callwaitingrepeat = 0;
08163 p->cidcwexpire = 0;
08164 p->cid_suppress_expire = 0;
08165 p->owner = NULL;
08166
08167 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08168 p->dialing = 1;
08169 dahdi_ring_phone(p);
08170 } else if (p->subs[SUB_THREEWAY].owner) {
08171 unsigned int mssinceflash;
08172
08173
08174 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08175
08176 DLA_UNLOCK(&p->lock);
08177 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08178
08179
08180
08181 DLA_LOCK(&p->lock);
08182 if (p->owner != ast) {
08183 ast_log(LOG_WARNING, "This isn't good...\n");
08184 return NULL;
08185 }
08186 }
08187 if (!p->subs[SUB_THREEWAY].owner) {
08188 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08189 return NULL;
08190 }
08191 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08192 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
08193 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08194
08195
08196 if (p->subs[SUB_THREEWAY].owner)
08197 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08198 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08199 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08200 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08201 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08202 if (p->transfer) {
08203
08204 p->subs[SUB_REAL].inthreeway = 0;
08205 p->subs[SUB_THREEWAY].inthreeway = 0;
08206
08207 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08208 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08209
08210 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08211 p->owner = NULL;
08212
08213 dahdi_ring_phone(p);
08214 } else {
08215 if ((res = attempt_transfer(p)) < 0) {
08216 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08217 if (p->subs[SUB_THREEWAY].owner)
08218 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08219 } else if (res) {
08220
08221 if (p->subs[SUB_THREEWAY].owner)
08222 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08223 break;
08224 }
08225 }
08226 } else {
08227 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08228 if (p->subs[SUB_THREEWAY].owner)
08229 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08230 }
08231 } else {
08232 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08233
08234 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08235 p->owner = NULL;
08236
08237 dahdi_ring_phone(p);
08238 }
08239 }
08240 } else {
08241 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08242 }
08243
08244 default:
08245 dahdi_disable_ec(p);
08246 return NULL;
08247 }
08248 break;
08249 case DAHDI_EVENT_RINGOFFHOOK:
08250 if (p->inalarm) break;
08251 if (p->oprmode < 0)
08252 {
08253 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08254 {
08255
08256 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08257 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08258 restore_conference(p->oprpeer);
08259 }
08260 break;
08261 }
08262 if (p->radio)
08263 {
08264 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08265 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08266 break;
08267 }
08268
08269
08270 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08271 c = strchr(p->dialdest, '/');
08272 if (c)
08273 c++;
08274 else
08275 c = p->dialdest;
08276 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08277 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08278 if (strlen(p->dop.dialstr) > 4) {
08279 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08280 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08281 p->echorest[sizeof(p->echorest) - 1] = '\0';
08282 p->echobreak = 1;
08283 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08284 } else
08285 p->echobreak = 0;
08286 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08287 int saveerr = errno;
08288
08289 x = DAHDI_ONHOOK;
08290 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08291 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08292 return NULL;
08293 }
08294 p->dialing = 1;
08295 return &p->subs[idx].f;
08296 }
08297 switch (p->sig) {
08298 case SIG_FXOLS:
08299 case SIG_FXOGS:
08300 case SIG_FXOKS:
08301 switch (ast->_state) {
08302 case AST_STATE_RINGING:
08303 dahdi_enable_ec(p);
08304 dahdi_train_ec(p);
08305 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08306 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08307
08308 p->subs[SUB_REAL].needringing = 0;
08309 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08310 ast_debug(1, "channel %d answered\n", p->channel);
08311
08312
08313 ast_free(p->cidspill);
08314 p->cidspill = NULL;
08315 restore_conference(p);
08316
08317 p->dialing = 0;
08318 p->callwaitcas = 0;
08319 if (p->confirmanswer) {
08320
08321 p->subs[idx].f.frametype = AST_FRAME_NULL;
08322 p->subs[idx].f.subclass.integer = 0;
08323 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08324
08325 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08326 if (res < 0) {
08327 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08328 p->dop.dialstr[0] = '\0';
08329 return NULL;
08330 } else {
08331 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08332 p->subs[idx].f.frametype = AST_FRAME_NULL;
08333 p->subs[idx].f.subclass.integer = 0;
08334 p->dialing = 1;
08335 }
08336 p->dop.dialstr[0] = '\0';
08337 ast_setstate(ast, AST_STATE_DIALING);
08338 } else
08339 ast_setstate(ast, AST_STATE_UP);
08340 return &p->subs[idx].f;
08341 case AST_STATE_DOWN:
08342 ast_setstate(ast, AST_STATE_RING);
08343 ast->rings = 1;
08344 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08345 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08346 ast_debug(1, "channel %d picked up\n", p->channel);
08347 return &p->subs[idx].f;
08348 case AST_STATE_UP:
08349
08350 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08351
08352 if (ast_bridged_channel(p->owner))
08353 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08354 p->subs[idx].needunhold = 1;
08355 break;
08356 case AST_STATE_RESERVED:
08357
08358 if (has_voicemail(p))
08359 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08360 else
08361 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08362 break;
08363 default:
08364 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast->_state);
08365 }
08366 break;
08367 case SIG_FXSLS:
08368 case SIG_FXSGS:
08369 case SIG_FXSKS:
08370 if (ast->_state == AST_STATE_RING) {
08371 p->ringt = p->ringt_base;
08372 }
08373
08374
08375
08376 ast_debug(1, "Setting IDLE polarity due "
08377 "to ring. Old polarity was %d\n",
08378 p->polarity);
08379 p->polarity = POLARITY_IDLE;
08380
08381
08382 case SIG_EM:
08383 case SIG_EM_E1:
08384 case SIG_EMWINK:
08385 case SIG_FEATD:
08386 case SIG_FEATDMF:
08387 case SIG_FEATDMF_TA:
08388 case SIG_E911:
08389 case SIG_FGC_CAMA:
08390 case SIG_FGC_CAMAMF:
08391 case SIG_FEATB:
08392 case SIG_SF:
08393 case SIG_SFWINK:
08394 case SIG_SF_FEATD:
08395 case SIG_SF_FEATDMF:
08396 case SIG_SF_FEATB:
08397 if (ast->_state == AST_STATE_PRERING)
08398 ast_setstate(ast, AST_STATE_RING);
08399 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08400 ast_debug(1, "Ring detected\n");
08401 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08402 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08403 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08404 ast_debug(1, "Line answered\n");
08405 if (p->confirmanswer) {
08406 p->subs[idx].f.frametype = AST_FRAME_NULL;
08407 p->subs[idx].f.subclass.integer = 0;
08408 } else {
08409 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08410 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08411 ast_setstate(ast, AST_STATE_UP);
08412 }
08413 } else if (ast->_state != AST_STATE_RING)
08414 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast->_state, p->channel);
08415 break;
08416 default:
08417 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08418 }
08419 break;
08420 case DAHDI_EVENT_RINGBEGIN:
08421 switch (p->sig) {
08422 case SIG_FXSLS:
08423 case SIG_FXSGS:
08424 case SIG_FXSKS:
08425 if (ast->_state == AST_STATE_RING) {
08426 p->ringt = p->ringt_base;
08427 }
08428 break;
08429 }
08430 break;
08431 case DAHDI_EVENT_RINGERON:
08432 break;
08433 case DAHDI_EVENT_NOALARM:
08434 switch (p->sig) {
08435 #if defined(HAVE_PRI)
08436 case SIG_PRI_LIB_HANDLE_CASES:
08437 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08438 break;
08439 #endif
08440 #if defined(HAVE_SS7)
08441 case SIG_SS7:
08442 sig_ss7_set_alarm(p->sig_pvt, 0);
08443 break;
08444 #endif
08445 default:
08446 p->inalarm = 0;
08447 break;
08448 }
08449 handle_clear_alarms(p);
08450 break;
08451 case DAHDI_EVENT_WINKFLASH:
08452 if (p->inalarm) break;
08453 if (p->radio) break;
08454 if (p->oprmode < 0) break;
08455 if (p->oprmode > 1)
08456 {
08457 struct dahdi_params par;
08458
08459 memset(&par, 0, sizeof(par));
08460 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08461 {
08462 if (!par.rxisoffhook)
08463 {
08464
08465 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08466 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08467 save_conference(p);
08468 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08469 }
08470 }
08471 break;
08472 }
08473
08474 p->flashtime = ast_tvnow();
08475 switch (mysig) {
08476 case SIG_FXOLS:
08477 case SIG_FXOGS:
08478 case SIG_FXOKS:
08479 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08480 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08481
08482
08483 ast_free(p->cidspill);
08484 p->cidspill = NULL;
08485 restore_conference(p);
08486 p->callwaitcas = 0;
08487
08488 if (idx != SUB_REAL) {
08489 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08490 goto winkflashdone;
08491 }
08492
08493 if (p->subs[SUB_CALLWAIT].owner) {
08494
08495 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08496 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08497 p->owner = p->subs[SUB_REAL].owner;
08498 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08499 if (p->owner->_state == AST_STATE_RINGING) {
08500 ast_setstate(p->owner, AST_STATE_UP);
08501 p->subs[SUB_REAL].needanswer = 1;
08502 }
08503 p->callwaitingrepeat = 0;
08504 p->cidcwexpire = 0;
08505 p->cid_suppress_expire = 0;
08506
08507 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08508 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08509 S_OR(p->mohsuggest, NULL),
08510 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08511 }
08512 p->subs[SUB_CALLWAIT].needhold = 1;
08513 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08514 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08515 S_OR(p->mohsuggest, NULL),
08516 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08517 }
08518 p->subs[SUB_REAL].needunhold = 1;
08519 } else if (!p->subs[SUB_THREEWAY].owner) {
08520 if (!p->threewaycalling) {
08521
08522 p->subs[SUB_REAL].needflash = 1;
08523 goto winkflashdone;
08524 } else if (!check_for_conference(p)) {
08525 char cid_num[256];
08526 char cid_name[256];
08527
08528 cid_num[0] = 0;
08529 cid_name[0] = 0;
08530 if (p->dahditrcallerid && p->owner) {
08531 if (p->owner->caller.id.number.valid
08532 && p->owner->caller.id.number.str) {
08533 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08534 sizeof(cid_num));
08535 }
08536 if (p->owner->caller.id.name.valid
08537 && p->owner->caller.id.name.str) {
08538 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08539 sizeof(cid_name));
08540 }
08541 }
08542
08543
08544 if (!((ast->pbx) ||
08545 (ast->_state == AST_STATE_UP) ||
08546 (ast->_state == AST_STATE_RING))) {
08547 ast_debug(1, "Flash when call not up or ringing\n");
08548 goto winkflashdone;
08549 }
08550 if (alloc_sub(p, SUB_THREEWAY)) {
08551 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08552 goto winkflashdone;
08553 }
08554
08555
08556
08557
08558
08559
08560
08561 ast_mutex_unlock(&p->lock);
08562 ast_channel_unlock(ast);
08563 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08564 ast_channel_lock(ast);
08565 ast_mutex_lock(&p->lock);
08566 if (p->dahditrcallerid) {
08567 if (!p->origcid_num)
08568 p->origcid_num = ast_strdup(p->cid_num);
08569 if (!p->origcid_name)
08570 p->origcid_name = ast_strdup(p->cid_name);
08571 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08572 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08573 }
08574
08575 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08576
08577 dahdi_disable_ec(p);
08578 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08579 if (res)
08580 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08581 p->owner = chan;
08582 if (!chan) {
08583 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08584 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08585 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08586 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08587 dahdi_enable_ec(p);
08588 ast_hangup(chan);
08589 } else {
08590 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08591
08592
08593 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08594 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08595 S_OR(p->mohsuggest, NULL),
08596 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08597 }
08598 p->subs[SUB_THREEWAY].needhold = 1;
08599 }
08600 }
08601 } else {
08602
08603 if (p->subs[SUB_THREEWAY].inthreeway) {
08604
08605 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08606
08607 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08608
08609 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08610 p->owner = p->subs[SUB_REAL].owner;
08611 }
08612
08613 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08614 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08615 p->subs[SUB_REAL].inthreeway = 0;
08616 p->subs[SUB_THREEWAY].inthreeway = 0;
08617 } else {
08618
08619 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08620 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08621 int otherindex = SUB_THREEWAY;
08622
08623 ast_verb(3, "Building conference call with %s and %s\n",
08624 p->subs[SUB_THREEWAY].owner->name,
08625 p->subs[SUB_REAL].owner->name);
08626
08627 p->subs[SUB_THREEWAY].inthreeway = 1;
08628 p->subs[SUB_REAL].inthreeway = 1;
08629 if (ast->_state == AST_STATE_UP) {
08630 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08631 otherindex = SUB_REAL;
08632 }
08633 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08634 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08635 p->subs[otherindex].needunhold = 1;
08636 p->owner = p->subs[SUB_REAL].owner;
08637 } else {
08638 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08639 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08640 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08641 p->owner = p->subs[SUB_REAL].owner;
08642 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08643 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08644 p->subs[SUB_REAL].needunhold = 1;
08645 dahdi_enable_ec(p);
08646 }
08647 }
08648 }
08649 winkflashdone:
08650 update_conf(p);
08651 break;
08652 case SIG_EM:
08653 case SIG_EM_E1:
08654 case SIG_FEATD:
08655 case SIG_SF:
08656 case SIG_SFWINK:
08657 case SIG_SF_FEATD:
08658 case SIG_FXSLS:
08659 case SIG_FXSGS:
08660 if (p->dialing)
08661 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08662 else
08663 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast->_state, p->channel);
08664 break;
08665 case SIG_FEATDMF_TA:
08666 switch (p->whichwink) {
08667 case 0:
08668 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08669 S_COR(p->owner->caller.ani.number.valid,
08670 p->owner->caller.ani.number.str, ""));
08671 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08672 p->owner->caller.ani2,
08673 S_COR(p->owner->caller.ani.number.valid,
08674 p->owner->caller.ani.number.str, ""));
08675 break;
08676 case 1:
08677 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08678 break;
08679 case 2:
08680 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08681 return NULL;
08682 }
08683 p->whichwink++;
08684
08685 case SIG_FEATDMF:
08686 case SIG_E911:
08687 case SIG_FGC_CAMAMF:
08688 case SIG_FGC_CAMA:
08689 case SIG_FEATB:
08690 case SIG_SF_FEATDMF:
08691 case SIG_SF_FEATB:
08692 case SIG_EMWINK:
08693
08694 if (!ast_strlen_zero(p->dop.dialstr)) {
08695 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08696 if (res < 0) {
08697 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08698 p->dop.dialstr[0] = '\0';
08699 return NULL;
08700 } else
08701 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08702 }
08703 p->dop.dialstr[0] = '\0';
08704 break;
08705 default:
08706 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08707 }
08708 break;
08709 case DAHDI_EVENT_HOOKCOMPLETE:
08710 if (p->inalarm) break;
08711 if ((p->radio || (p->oprmode < 0))) break;
08712 if (p->waitingfordt.tv_sec) break;
08713 switch (mysig) {
08714 case SIG_FXSLS:
08715 case SIG_FXSGS:
08716 case SIG_FXSKS:
08717 case SIG_EM:
08718 case SIG_EM_E1:
08719 case SIG_EMWINK:
08720 case SIG_FEATD:
08721 case SIG_SF:
08722 case SIG_SFWINK:
08723 case SIG_SF_FEATD:
08724 if (!ast_strlen_zero(p->dop.dialstr)) {
08725 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08726 if (res < 0) {
08727 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08728 p->dop.dialstr[0] = '\0';
08729 return NULL;
08730 } else
08731 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08732 }
08733 p->dop.dialstr[0] = '\0';
08734 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08735 break;
08736 case SIG_FEATDMF:
08737 case SIG_FEATDMF_TA:
08738 case SIG_E911:
08739 case SIG_FGC_CAMA:
08740 case SIG_FGC_CAMAMF:
08741 case SIG_FEATB:
08742 case SIG_SF_FEATDMF:
08743 case SIG_SF_FEATB:
08744 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08745 break;
08746 default:
08747 break;
08748 }
08749 break;
08750 case DAHDI_EVENT_POLARITY:
08751
08752
08753
08754
08755
08756
08757 if (p->polarity == POLARITY_IDLE) {
08758 p->polarity = POLARITY_REV;
08759 if (p->answeronpolarityswitch &&
08760 ((ast->_state == AST_STATE_DIALING) ||
08761 (ast->_state == AST_STATE_RINGING))) {
08762 ast_debug(1, "Answering on polarity switch!\n");
08763 ast_setstate(p->owner, AST_STATE_UP);
08764 if (p->hanguponpolarityswitch) {
08765 p->polaritydelaytv = ast_tvnow();
08766 }
08767 } else
08768 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast->_state);
08769 }
08770
08771
08772 if (p->hanguponpolarityswitch &&
08773 (p->polarityonanswerdelay > 0) &&
08774 (p->polarity == POLARITY_REV) &&
08775 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08776
08777 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) );
08778
08779 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08780 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08781 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08782 p->polarity = POLARITY_IDLE;
08783 } else
08784 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);
08785
08786 } else {
08787 p->polarity = POLARITY_IDLE;
08788 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast->_state);
08789 }
08790
08791 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) );
08792 break;
08793 default:
08794 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08795 }
08796 return &p->subs[idx].f;
08797 }
08798
08799 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08800 {
08801 int res;
08802 int idx;
08803 struct ast_frame *f;
08804 int usedindex = -1;
08805 struct dahdi_pvt *p = ast->tech_pvt;
08806
08807 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08808 idx = SUB_REAL;
08809 }
08810
08811 p->subs[idx].f.frametype = AST_FRAME_NULL;
08812 p->subs[idx].f.datalen = 0;
08813 p->subs[idx].f.samples = 0;
08814 p->subs[idx].f.mallocd = 0;
08815 p->subs[idx].f.offset = 0;
08816 p->subs[idx].f.subclass.integer = 0;
08817 p->subs[idx].f.delivery = ast_tv(0,0);
08818 p->subs[idx].f.src = "dahdi_exception";
08819 p->subs[idx].f.data.ptr = NULL;
08820
08821
08822 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08823
08824
08825
08826
08827
08828 if (p->fake_event) {
08829 res = p->fake_event;
08830 p->fake_event = 0;
08831 } else
08832 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08833
08834 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08835 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08836 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08837 p->owner = p->subs[SUB_REAL].owner;
08838 if (p->owner && ast_bridged_channel(p->owner))
08839 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08840 p->subs[SUB_REAL].needunhold = 1;
08841 }
08842 switch (res) {
08843 case DAHDI_EVENT_ONHOOK:
08844 dahdi_disable_ec(p);
08845 if (p->owner) {
08846 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08847 dahdi_ring_phone(p);
08848 p->callwaitingrepeat = 0;
08849 p->cidcwexpire = 0;
08850 p->cid_suppress_expire = 0;
08851 } else
08852 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08853 update_conf(p);
08854 break;
08855 case DAHDI_EVENT_RINGOFFHOOK:
08856 dahdi_enable_ec(p);
08857 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08858 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08859 p->subs[SUB_REAL].needanswer = 1;
08860 p->dialing = 0;
08861 }
08862 break;
08863 case DAHDI_EVENT_HOOKCOMPLETE:
08864 case DAHDI_EVENT_RINGERON:
08865 case DAHDI_EVENT_RINGEROFF:
08866
08867 break;
08868 case DAHDI_EVENT_WINKFLASH:
08869 p->flashtime = ast_tvnow();
08870 if (p->owner) {
08871 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08872 if (p->owner->_state != AST_STATE_UP) {
08873
08874 usedindex = dahdi_get_index(p->owner, p, 0);
08875 if (usedindex > -1) {
08876 p->subs[usedindex].needanswer = 1;
08877 }
08878 ast_setstate(p->owner, AST_STATE_UP);
08879 }
08880 p->callwaitingrepeat = 0;
08881 p->cidcwexpire = 0;
08882 p->cid_suppress_expire = 0;
08883 if (ast_bridged_channel(p->owner))
08884 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08885 p->subs[SUB_REAL].needunhold = 1;
08886 } else
08887 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08888 update_conf(p);
08889 break;
08890 default:
08891 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08892 }
08893 f = &p->subs[idx].f;
08894 return f;
08895 }
08896 if (!(p->radio || (p->oprmode < 0)))
08897 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08898
08899 if (ast != p->owner) {
08900 if (p->owner) {
08901 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08902 }
08903 f = &p->subs[idx].f;
08904 return f;
08905 }
08906
08907 f = dahdi_handle_event(ast);
08908 if (!f) {
08909 const char *name = ast_strdupa(ast->name);
08910
08911
08912 ast_mutex_unlock(&p->lock);
08913 ast_channel_unlock(ast);
08914 ast_set_hangupsource(ast, name, 0);
08915 ast_channel_lock(ast);
08916 ast_mutex_lock(&p->lock);
08917 }
08918 return f;
08919 }
08920
08921 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08922 {
08923 struct dahdi_pvt *p = ast->tech_pvt;
08924 struct ast_frame *f;
08925 ast_mutex_lock(&p->lock);
08926 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08927 struct analog_pvt *analog_p = p->sig_pvt;
08928 f = analog_exception(analog_p, ast);
08929 } else {
08930 f = __dahdi_exception(ast);
08931 }
08932 ast_mutex_unlock(&p->lock);
08933 return f;
08934 }
08935
08936 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08937 {
08938 struct dahdi_pvt *p;
08939 int res;
08940 int idx;
08941 void *readbuf;
08942 struct ast_frame *f;
08943
08944
08945
08946
08947
08948
08949 p = ast->tech_pvt;
08950 while (ast_mutex_trylock(&p->lock)) {
08951 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08952
08953
08954
08955
08956
08957
08958
08959
08960
08961
08962
08963
08964 if (ast->tech_pvt != p) {
08965
08966 return &ast_null_frame;
08967 }
08968 }
08969
08970 idx = dahdi_get_index(ast, p, 0);
08971
08972
08973 if (idx < 0) {
08974 ast_log(LOG_WARNING, "We don't exist?\n");
08975 ast_mutex_unlock(&p->lock);
08976 return NULL;
08977 }
08978
08979 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08980 ast_mutex_unlock(&p->lock);
08981 return NULL;
08982 }
08983
08984 p->subs[idx].f.frametype = AST_FRAME_NULL;
08985 p->subs[idx].f.datalen = 0;
08986 p->subs[idx].f.samples = 0;
08987 p->subs[idx].f.mallocd = 0;
08988 p->subs[idx].f.offset = 0;
08989 p->subs[idx].f.subclass.integer = 0;
08990 p->subs[idx].f.delivery = ast_tv(0,0);
08991 p->subs[idx].f.src = "dahdi_read";
08992 p->subs[idx].f.data.ptr = NULL;
08993
08994
08995 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08996 {
08997 struct dahdi_params ps;
08998
08999 memset(&ps, 0, sizeof(ps));
09000 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09001 ast_mutex_unlock(&p->lock);
09002 return NULL;
09003 }
09004 p->firstradio = 1;
09005 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09006 if (ps.rxisoffhook)
09007 {
09008 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09009 }
09010 else
09011 {
09012 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09013 }
09014 ast_mutex_unlock(&p->lock);
09015 return &p->subs[idx].f;
09016 }
09017 if (p->ringt > 0) {
09018 if (!(--p->ringt)) {
09019 ast_mutex_unlock(&p->lock);
09020 return NULL;
09021 }
09022 }
09023
09024 #ifdef HAVE_OPENR2
09025 if (p->mfcr2) {
09026 openr2_chan_process_event(p->r2chan);
09027 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09028 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09029
09030
09031 if (p->mfcr2_call_accepted &&
09032 !p->mfcr2_progress &&
09033 ast->_state == AST_STATE_RINGING) {
09034 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09035 ast_queue_frame(p->owner, &f);
09036 p->mfcr2_progress = 1;
09037 }
09038 }
09039 }
09040 #endif
09041
09042 if (p->subs[idx].needringing) {
09043
09044 p->subs[idx].needringing = 0;
09045 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09046 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09047 ast_setstate(ast, AST_STATE_RINGING);
09048 ast_mutex_unlock(&p->lock);
09049 return &p->subs[idx].f;
09050 }
09051
09052 if (p->subs[idx].needbusy) {
09053
09054 p->subs[idx].needbusy = 0;
09055 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09056 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09057 ast_mutex_unlock(&p->lock);
09058 return &p->subs[idx].f;
09059 }
09060
09061 if (p->subs[idx].needcongestion) {
09062
09063 p->subs[idx].needcongestion = 0;
09064 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09065 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09066 ast_mutex_unlock(&p->lock);
09067 return &p->subs[idx].f;
09068 }
09069
09070 if (p->subs[idx].needanswer) {
09071
09072 p->subs[idx].needanswer = 0;
09073 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09074 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09075 ast_mutex_unlock(&p->lock);
09076 return &p->subs[idx].f;
09077 }
09078 #ifdef HAVE_OPENR2
09079 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09080
09081
09082
09083
09084 ast_mutex_unlock(&p->lock);
09085 return &ast_null_frame;
09086 }
09087 #endif
09088
09089 if (p->subs[idx].needflash) {
09090
09091 p->subs[idx].needflash = 0;
09092 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09093 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09094 ast_mutex_unlock(&p->lock);
09095 return &p->subs[idx].f;
09096 }
09097
09098 if (p->subs[idx].needhold) {
09099
09100 p->subs[idx].needhold = 0;
09101 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09102 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09103 ast_mutex_unlock(&p->lock);
09104 ast_debug(1, "Sending hold on '%s'\n", ast->name);
09105 return &p->subs[idx].f;
09106 }
09107
09108 if (p->subs[idx].needunhold) {
09109
09110 p->subs[idx].needunhold = 0;
09111 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09112 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09113 ast_mutex_unlock(&p->lock);
09114 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09115 return &p->subs[idx].f;
09116 }
09117
09118
09119
09120
09121
09122 if (p->fake_event && p->owner == ast) {
09123 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09124 struct analog_pvt *analog_p = p->sig_pvt;
09125
09126 f = analog_exception(analog_p, ast);
09127 } else {
09128 f = __dahdi_exception(ast);
09129 }
09130 ast_mutex_unlock(&p->lock);
09131 return f;
09132 }
09133
09134 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09135 if (!p->subs[idx].linear) {
09136 p->subs[idx].linear = 1;
09137 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09138 if (res)
09139 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09140 }
09141 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09142 (ast->rawreadformat == AST_FORMAT_ALAW)) {
09143 if (p->subs[idx].linear) {
09144 p->subs[idx].linear = 0;
09145 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09146 if (res)
09147 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09148 }
09149 } else {
09150 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09151 ast_mutex_unlock(&p->lock);
09152 return NULL;
09153 }
09154 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09155 CHECK_BLOCKING(ast);
09156 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09157 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09158
09159 if (res < 0) {
09160 f = NULL;
09161 if (res == -1) {
09162 if (errno == EAGAIN) {
09163
09164 ast_mutex_unlock(&p->lock);
09165 return &p->subs[idx].f;
09166 } else if (errno == ELAST) {
09167 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09168 struct analog_pvt *analog_p = p->sig_pvt;
09169 f = analog_exception(analog_p, ast);
09170 } else {
09171 f = __dahdi_exception(ast);
09172 }
09173 } else
09174 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09175 }
09176 ast_mutex_unlock(&p->lock);
09177 return f;
09178 }
09179 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09180 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09181 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09182 struct analog_pvt *analog_p = p->sig_pvt;
09183 f = analog_exception(analog_p, ast);
09184 } else {
09185 f = __dahdi_exception(ast);
09186 }
09187 ast_mutex_unlock(&p->lock);
09188 return f;
09189 }
09190 if (p->tdd) {
09191 int c;
09192
09193 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09194 if (c < 0) {
09195 ast_debug(1,"tdd_feed failed\n");
09196 ast_mutex_unlock(&p->lock);
09197 return NULL;
09198 }
09199 if (c) {
09200 p->subs[idx].f.subclass.integer = 0;
09201 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09202 p->subs[idx].f.mallocd = 0;
09203 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09204 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09205 p->subs[idx].f.datalen = 1;
09206 *((char *) p->subs[idx].f.data.ptr) = c;
09207 ast_mutex_unlock(&p->lock);
09208 return &p->subs[idx].f;
09209 }
09210 }
09211 if (idx == SUB_REAL) {
09212
09213 if (p->cidcwexpire) {
09214 if (!--p->cidcwexpire) {
09215
09216 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09217 restore_conference(p);
09218 }
09219 }
09220 if (p->cid_suppress_expire) {
09221 --p->cid_suppress_expire;
09222 }
09223 if (p->callwaitingrepeat) {
09224 if (!--p->callwaitingrepeat) {
09225
09226 ++p->callwaitrings;
09227 dahdi_callwait(ast);
09228 }
09229 }
09230 }
09231 if (p->subs[idx].linear) {
09232 p->subs[idx].f.datalen = READ_SIZE * 2;
09233 } else
09234 p->subs[idx].f.datalen = READ_SIZE;
09235
09236
09237 if ((p->owner == ast) && p->cidspill) {
09238 send_callerid(p);
09239 }
09240
09241 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09242 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09243 p->subs[idx].f.samples = READ_SIZE;
09244 p->subs[idx].f.mallocd = 0;
09245 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09246 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09247 #if 0
09248 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09249 #endif
09250 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio ||
09251 (idx && (ast->_state != AST_STATE_UP)) ||
09252 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09253 ) {
09254
09255
09256 p->subs[idx].f.frametype = AST_FRAME_NULL;
09257 p->subs[idx].f.subclass.integer = 0;
09258 p->subs[idx].f.samples = 0;
09259 p->subs[idx].f.mallocd = 0;
09260 p->subs[idx].f.offset = 0;
09261 p->subs[idx].f.data.ptr = NULL;
09262 p->subs[idx].f.datalen= 0;
09263 }
09264 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09265
09266 int mute;
09267
09268 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09269
09270
09271 mute = ast_dsp_was_muted(p->dsp);
09272 if (p->muting != mute) {
09273 p->muting = mute;
09274 dahdi_confmute(p, mute);
09275 }
09276
09277 if (f) {
09278 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09279 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09280
09281
09282 ast_frfree(f);
09283 f = NULL;
09284 }
09285 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09286 || f->frametype == AST_FRAME_DTMF_END) {
09287 #ifdef HAVE_PRI
09288 if (dahdi_sig_pri_lib_handles(p->sig)
09289 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09290 && p->pri
09291 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09292 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09293
09294 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09295 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09296 (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
09297
09298 f->frametype = AST_FRAME_NULL;
09299 f->subclass.integer = 0;
09300 }
09301 #endif
09302
09303 p->pulsedial = 0;
09304 } else if (p->waitingfordt.tv_sec) {
09305 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09306 p->waitingfordt.tv_sec = 0;
09307 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09308 ast_frfree(f);
09309 f = NULL;
09310 } else if (f->frametype == AST_FRAME_VOICE) {
09311 f->frametype = AST_FRAME_NULL;
09312 f->subclass.integer = 0;
09313 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) {
09314 p->waitingfordt.tv_sec = 0;
09315 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09316 ast_dsp_set_features(p->dsp, p->dsp_features);
09317 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09318 if (!ast_strlen_zero(p->dop.dialstr)) {
09319 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09320 if (res < 0) {
09321 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09322 p->dop.dialstr[0] = '\0';
09323 ast_mutex_unlock(&p->lock);
09324 ast_frfree(f);
09325 return NULL;
09326 } else {
09327 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09328 p->dialing = 1;
09329 p->dop.dialstr[0] = '\0';
09330 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09331 ast_setstate(ast, AST_STATE_DIALING);
09332 }
09333 }
09334 }
09335 }
09336 }
09337 }
09338 } else
09339 f = &p->subs[idx].f;
09340
09341 if (f) {
09342 switch (f->frametype) {
09343 case AST_FRAME_DTMF_BEGIN:
09344 case AST_FRAME_DTMF_END:
09345 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09346 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09347 } else {
09348 dahdi_handle_dtmf(ast, idx, &f);
09349 }
09350 break;
09351 case AST_FRAME_VOICE:
09352 if (p->cidspill || p->cid_suppress_expire) {
09353
09354 p->subs[idx].f.frametype = AST_FRAME_NULL;
09355 p->subs[idx].f.subclass.integer = 0;
09356 p->subs[idx].f.samples = 0;
09357 p->subs[idx].f.mallocd = 0;
09358 p->subs[idx].f.offset = 0;
09359 p->subs[idx].f.data.ptr = NULL;
09360 p->subs[idx].f.datalen= 0;
09361 }
09362 break;
09363 default:
09364 break;
09365 }
09366 }
09367
09368 ast_mutex_unlock(&p->lock);
09369 return f;
09370 }
09371
09372 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09373 {
09374 int sent=0;
09375 int size;
09376 int res;
09377 int fd;
09378 fd = p->subs[idx].dfd;
09379 while (len) {
09380 size = len;
09381 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09382 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09383 res = write(fd, buf, size);
09384 if (res != size) {
09385 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09386 return sent;
09387 }
09388 len -= size;
09389 buf += size;
09390 }
09391 return sent;
09392 }
09393
09394 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09395 {
09396 struct dahdi_pvt *p = ast->tech_pvt;
09397 int res;
09398 int idx;
09399 idx = dahdi_get_index(ast, p, 0);
09400 if (idx < 0) {
09401 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09402 return -1;
09403 }
09404
09405
09406 if (frame->frametype != AST_FRAME_VOICE) {
09407 if (frame->frametype != AST_FRAME_IMAGE)
09408 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
09409 return 0;
09410 }
09411 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09412 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09413 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09414 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09415 return -1;
09416 }
09417 if (p->dialing) {
09418 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09419 return 0;
09420 }
09421 if (!p->owner) {
09422 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09423 return 0;
09424 }
09425 if (p->cidspill) {
09426 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09427 ast->name);
09428 return 0;
09429 }
09430
09431 if (!frame->data.ptr || !frame->datalen)
09432 return 0;
09433
09434 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09435 if (!p->subs[idx].linear) {
09436 p->subs[idx].linear = 1;
09437 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09438 if (res)
09439 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09440 }
09441 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09442 } else {
09443
09444 if (p->subs[idx].linear) {
09445 p->subs[idx].linear = 0;
09446 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09447 if (res)
09448 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09449 }
09450 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09451 }
09452 if (res < 0) {
09453 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09454 return -1;
09455 }
09456 return 0;
09457 }
09458
09459 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09460 {
09461 struct dahdi_pvt *p = chan->tech_pvt;
09462 int res=-1;
09463 int idx;
09464 int func = DAHDI_FLASH;
09465
09466 ast_mutex_lock(&p->lock);
09467 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09468 switch (p->sig) {
09469 #if defined(HAVE_PRI)
09470 case SIG_PRI_LIB_HANDLE_CASES:
09471 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09472 ast_mutex_unlock(&p->lock);
09473 return res;
09474 #endif
09475 #if defined(HAVE_SS7)
09476 case SIG_SS7:
09477 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09478 ast_mutex_unlock(&p->lock);
09479 return res;
09480 #endif
09481 default:
09482 break;
09483 }
09484 #ifdef HAVE_OPENR2
09485 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09486 ast_mutex_unlock(&p->lock);
09487
09488
09489 return 0;
09490 }
09491 #endif
09492 idx = dahdi_get_index(chan, p, 0);
09493 if (idx == SUB_REAL) {
09494 switch (condition) {
09495 case AST_CONTROL_BUSY:
09496 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09497 break;
09498 case AST_CONTROL_RINGING:
09499 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09500
09501 if (chan->_state != AST_STATE_UP) {
09502 if ((chan->_state != AST_STATE_RING) ||
09503 ((p->sig != SIG_FXSKS) &&
09504 (p->sig != SIG_FXSLS) &&
09505 (p->sig != SIG_FXSGS)))
09506 ast_setstate(chan, AST_STATE_RINGING);
09507 }
09508 break;
09509 case AST_CONTROL_INCOMPLETE:
09510 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09511
09512 res = 0;
09513 break;
09514 case AST_CONTROL_PROCEEDING:
09515 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09516
09517 res = 0;
09518 break;
09519 case AST_CONTROL_PROGRESS:
09520 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09521
09522 res = 0;
09523 break;
09524 case AST_CONTROL_CONGESTION:
09525
09526 switch (chan->hangupcause) {
09527 case AST_CAUSE_USER_BUSY:
09528 case AST_CAUSE_NORMAL_CLEARING:
09529 case 0:
09530
09531 chan->hangupcause = AST_CAUSE_CONGESTION;
09532 break;
09533 default:
09534 break;
09535 }
09536 break;
09537 case AST_CONTROL_HOLD:
09538 ast_moh_start(chan, data, p->mohinterpret);
09539 break;
09540 case AST_CONTROL_UNHOLD:
09541 ast_moh_stop(chan);
09542 break;
09543 case AST_CONTROL_RADIO_KEY:
09544 if (p->radio)
09545 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09546 res = 0;
09547 break;
09548 case AST_CONTROL_RADIO_UNKEY:
09549 if (p->radio)
09550 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09551 res = 0;
09552 break;
09553 case AST_CONTROL_FLASH:
09554
09555 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09556
09557 p->dop.dialstr[0] = '\0';
09558 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09559 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09560 chan->name, strerror(errno));
09561 } else
09562 res = 0;
09563 } else
09564 res = 0;
09565 break;
09566 case AST_CONTROL_SRCUPDATE:
09567 res = 0;
09568 break;
09569 case -1:
09570 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09571 break;
09572 }
09573 } else {
09574 res = 0;
09575 }
09576 ast_mutex_unlock(&p->lock);
09577 return res;
09578 }
09579
09580 #if defined(HAVE_PRI)
09581 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09582 #else
09583 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09584 #endif
09585 {
09586 struct ast_str *chan_name;
09587 int x, y;
09588
09589
09590 if (!(chan_name = ast_str_create(32))) {
09591 return NULL;
09592 }
09593 if (i->channel == CHAN_PSEUDO) {
09594 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09595 #if defined(HAVE_PRI)
09596 } else if (i->pri) {
09597 ast_mutex_lock(&i->pri->lock);
09598 y = ++i->pri->new_chan_seq;
09599 if (is_outgoing) {
09600 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
09601 address[0] = '\0';
09602 } else if (ast_strlen_zero(i->cid_subaddr)) {
09603
09604 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
09605 } else {
09606
09607 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09608 i->cid_subaddr, (unsigned)y);
09609 }
09610 ast_mutex_unlock(&i->pri->lock);
09611 #endif
09612 } else {
09613 y = 1;
09614 do {
09615 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09616 for (x = 0; x < 3; ++x) {
09617 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09618 i->subs[x].owner->name + 6)) {
09619 break;
09620 }
09621 }
09622 ++y;
09623 } while (x < 3);
09624 }
09625 return chan_name;
09626 }
09627
09628 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09629 {
09630 struct ast_channel *tmp;
09631 format_t deflaw;
09632 int x;
09633 int features;
09634 struct ast_str *chan_name;
09635 struct ast_variable *v;
09636 char *dashptr;
09637 char device_name[AST_CHANNEL_NAME];
09638
09639 if (i->subs[idx].owner) {
09640 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09641 return NULL;
09642 }
09643
09644 #if defined(HAVE_PRI)
09645
09646
09647
09648
09649 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09650 #else
09651 chan_name = create_channel_name(i);
09652 #endif
09653 if (!chan_name) {
09654 return NULL;
09655 }
09656
09657 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));
09658 ast_free(chan_name);
09659 if (!tmp)
09660 return NULL;
09661 tmp->tech = &dahdi_tech;
09662 #if defined(HAVE_PRI)
09663 if (i->pri) {
09664 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09665 }
09666 #endif
09667 ast_channel_cc_params_init(tmp, i->cc_params);
09668 if (law) {
09669 i->law = law;
09670 if (law == DAHDI_LAW_ALAW) {
09671 deflaw = AST_FORMAT_ALAW;
09672 } else {
09673 deflaw = AST_FORMAT_ULAW;
09674 }
09675 } else {
09676 switch (i->sig) {
09677 case SIG_PRI_LIB_HANDLE_CASES:
09678
09679 i->law = (i->law_default == DAHDI_LAW_ALAW)
09680 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09681 break;
09682 default:
09683 i->law = i->law_default;
09684 break;
09685 }
09686 if (i->law_default == DAHDI_LAW_ALAW) {
09687 deflaw = AST_FORMAT_ALAW;
09688 } else {
09689 deflaw = AST_FORMAT_ULAW;
09690 }
09691 }
09692 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09693 tmp->nativeformats = deflaw;
09694
09695 tmp->rawreadformat = deflaw;
09696 tmp->readformat = deflaw;
09697 tmp->rawwriteformat = deflaw;
09698 tmp->writeformat = deflaw;
09699 i->subs[idx].linear = 0;
09700 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09701 features = 0;
09702 if (idx == SUB_REAL) {
09703 if (i->busydetect && CANBUSYDETECT(i))
09704 features |= DSP_FEATURE_BUSY_DETECT;
09705 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09706 features |= DSP_FEATURE_CALL_PROGRESS;
09707 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09708 features |= DSP_FEATURE_WAITDIALTONE;
09709 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09710 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09711 features |= DSP_FEATURE_FAX_DETECT;
09712 }
09713 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09714 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09715 i->hardwaredtmf = 0;
09716 features |= DSP_FEATURE_DIGIT_DETECT;
09717 } else if (NEED_MFDETECT(i)) {
09718 i->hardwaredtmf = 1;
09719 features |= DSP_FEATURE_DIGIT_DETECT;
09720 }
09721 }
09722 if (features) {
09723 if (i->dsp) {
09724 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09725 } else {
09726 if (i->channel != CHAN_PSEUDO)
09727 i->dsp = ast_dsp_new();
09728 else
09729 i->dsp = NULL;
09730 if (i->dsp) {
09731 i->dsp_features = features;
09732 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09733
09734 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09735
09736
09737 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09738 features = 0;
09739 }
09740 #endif
09741 ast_dsp_set_features(i->dsp, features);
09742 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09743 if (!ast_strlen_zero(progzone))
09744 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09745 if (i->busydetect && CANBUSYDETECT(i)) {
09746 ast_dsp_set_busy_count(i->dsp, i->busycount);
09747 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09748 }
09749 }
09750 }
09751 }
09752
09753 if (state == AST_STATE_RING)
09754 tmp->rings = 1;
09755 tmp->tech_pvt = i;
09756 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09757
09758 tmp->callgroup = i->callgroup;
09759 tmp->pickupgroup = i->pickupgroup;
09760 }
09761 if (!ast_strlen_zero(i->parkinglot))
09762 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09763 if (!ast_strlen_zero(i->language))
09764 ast_string_field_set(tmp, language, i->language);
09765 if (!i->owner)
09766 i->owner = tmp;
09767 if (!ast_strlen_zero(i->accountcode))
09768 ast_string_field_set(tmp, accountcode, i->accountcode);
09769 if (i->amaflags)
09770 tmp->amaflags = i->amaflags;
09771 i->subs[idx].owner = tmp;
09772 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09773 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09774 ast_string_field_set(tmp, call_forward, i->call_forward);
09775 }
09776
09777 if (!i->adsi)
09778 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09779 if (!ast_strlen_zero(i->exten))
09780 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09781 if (!ast_strlen_zero(i->rdnis)) {
09782 tmp->redirecting.from.number.valid = 1;
09783 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09784 }
09785 if (!ast_strlen_zero(i->dnid)) {
09786 tmp->dialed.number.str = ast_strdup(i->dnid);
09787 }
09788
09789
09790
09791 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09792 if (!ast_strlen_zero(i->cid_ani)) {
09793 tmp->caller.ani.number.valid = 1;
09794 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09795 } else if (!ast_strlen_zero(i->cid_num)) {
09796 tmp->caller.ani.number.valid = 1;
09797 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09798 }
09799 #else
09800 if (!ast_strlen_zero(i->cid_num)) {
09801 tmp->caller.ani.number.valid = 1;
09802 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09803 }
09804 #endif
09805 tmp->caller.id.name.presentation = i->callingpres;
09806 tmp->caller.id.number.presentation = i->callingpres;
09807 tmp->caller.id.number.plan = i->cid_ton;
09808 tmp->caller.ani2 = i->cid_ani2;
09809 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09810
09811 i->fake_event = 0;
09812
09813 dahdi_confmute(i, 0);
09814 i->muting = 0;
09815
09816 ast_jb_configure(tmp, &global_jbconf);
09817
09818
09819 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09820 dashptr = strrchr(device_name, '-');
09821 if (dashptr) {
09822 *dashptr = '\0';
09823 }
09824 tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09825 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09826
09827 for (v = i->vars ; v ; v = v->next)
09828 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09829
09830 ast_module_ref(ast_module_info->self);
09831
09832 dahdi_ami_channel_event(i, tmp);
09833 if (startpbx) {
09834 #ifdef HAVE_OPENR2
09835 if (i->mfcr2call) {
09836 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09837 }
09838 #endif
09839 if (ast_pbx_start(tmp)) {
09840 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09841 ast_hangup(tmp);
09842 return NULL;
09843 }
09844 }
09845 return tmp;
09846 }
09847
09848
09849 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09850 {
09851 char c;
09852
09853 *str = 0;
09854 for (;;)
09855 {
09856
09857 c = ast_waitfordigit(chan, ms);
09858
09859 if (c < 1)
09860 return c;
09861 *str++ = c;
09862 *str = 0;
09863 if (strchr(term, c))
09864 return 1;
09865 }
09866 }
09867
09868 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09869 {
09870 int j;
09871 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09872 for (;;)
09873 {
09874
09875 j = DAHDI_IOMUX_SIGEVENT;
09876
09877 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09878
09879 if (j & DAHDI_IOMUX_SIGEVENT) break;
09880 }
09881
09882 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09883 return 0;
09884 }
09885
09886
09887
09888
09889
09890
09891
09892
09893
09894
09895 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09896 {
09897 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09898 return analog_dnd(dahdichan->sig_pvt, flag);
09899 }
09900
09901 if (flag == -1) {
09902 return dahdichan->dnd;
09903 }
09904
09905
09906 dahdichan->dnd = flag;
09907 ast_verb(3, "%s DND on channel %d\n",
09908 flag? "Enabled" : "Disabled",
09909 dahdichan->channel);
09910 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09911 "Channel: DAHDI/%d\r\n"
09912 "Status: %s\r\n", dahdichan->channel,
09913 flag? "enabled" : "disabled");
09914
09915 return 0;
09916 }
09917
09918 static int canmatch_featurecode(const char *exten)
09919 {
09920 int extlen = strlen(exten);
09921 const char *pickup_ext;
09922 if (!extlen) {
09923 return 1;
09924 }
09925 pickup_ext = ast_pickup_ext();
09926 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09927 return 1;
09928 }
09929
09930 if (exten[0] == '*' && extlen < 3) {
09931 if (extlen == 1) {
09932 return 1;
09933 }
09934
09935 switch (exten[1]) {
09936 case '6':
09937 case '7':
09938 case '8':
09939 return 1;
09940 }
09941 }
09942 return 0;
09943 }
09944
09945 static void *analog_ss_thread(void *data)
09946 {
09947 struct ast_channel *chan = data;
09948 struct dahdi_pvt *p = chan->tech_pvt;
09949 char exten[AST_MAX_EXTENSION] = "";
09950 char exten2[AST_MAX_EXTENSION] = "";
09951 unsigned char buf[256];
09952 char dtmfcid[300];
09953 char dtmfbuf[300];
09954 struct callerid_state *cs = NULL;
09955 char *name = NULL, *number = NULL;
09956 int distMatches;
09957 int curRingData[3];
09958 int receivedRingT;
09959 int counter1;
09960 int counter;
09961 int samples = 0;
09962 struct ast_smdi_md_message *smdi_msg = NULL;
09963 int flags = 0;
09964 int i;
09965 int timeout;
09966 int getforward = 0;
09967 char *s1, *s2;
09968 int len = 0;
09969 int res;
09970 int idx;
09971
09972 ast_mutex_lock(&ss_thread_lock);
09973 ss_thread_count++;
09974 ast_mutex_unlock(&ss_thread_lock);
09975
09976
09977
09978 if (!p) {
09979 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09980 ast_hangup(chan);
09981 goto quit;
09982 }
09983 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09984 idx = dahdi_get_index(chan, p, 1);
09985 if (idx < 0) {
09986 ast_log(LOG_WARNING, "Huh?\n");
09987 ast_hangup(chan);
09988 goto quit;
09989 }
09990 if (p->dsp)
09991 ast_dsp_digitreset(p->dsp);
09992 switch (p->sig) {
09993 case SIG_FEATD:
09994 case SIG_FEATDMF:
09995 case SIG_FEATDMF_TA:
09996 case SIG_E911:
09997 case SIG_FGC_CAMAMF:
09998 case SIG_FEATB:
09999 case SIG_EMWINK:
10000 case SIG_SF_FEATD:
10001 case SIG_SF_FEATDMF:
10002 case SIG_SF_FEATB:
10003 case SIG_SFWINK:
10004 if (dahdi_wink(p, idx))
10005 goto quit;
10006
10007 case SIG_EM:
10008 case SIG_EM_E1:
10009 case SIG_SF:
10010 case SIG_FGC_CAMA:
10011 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10012 if (p->dsp)
10013 ast_dsp_digitreset(p->dsp);
10014
10015 if (p->dsp) {
10016 if (NEED_MFDETECT(p))
10017 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10018 else
10019 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10020 }
10021 memset(dtmfbuf, 0, sizeof(dtmfbuf));
10022
10023 if (!p->immediate)
10024
10025 res = ast_waitfordigit(chan, 5000);
10026 else
10027 res = 0;
10028 if (res > 0) {
10029
10030 dtmfbuf[0] = res;
10031 switch (p->sig) {
10032 case SIG_FEATD:
10033 case SIG_SF_FEATD:
10034 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10035 if (res > 0)
10036 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10037 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10038 break;
10039 case SIG_FEATDMF_TA:
10040 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10041 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10042 if (dahdi_wink(p, idx)) goto quit;
10043 dtmfbuf[0] = 0;
10044
10045 res = ast_waitfordigit(chan, 5000);
10046 if (res <= 0) break;
10047 dtmfbuf[0] = res;
10048
10049 case SIG_FEATDMF:
10050 case SIG_E911:
10051 case SIG_FGC_CAMAMF:
10052 case SIG_SF_FEATDMF:
10053 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10054
10055 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10056 {
10057 if (dahdi_wink(p, idx)) goto quit;
10058 dtmfbuf[0] = 0;
10059
10060 res = ast_waitfordigit(chan, 5000);
10061 if (res <= 0) break;
10062 dtmfbuf[0] = res;
10063 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10064 }
10065 if (res > 0) {
10066
10067 if (p->sig == SIG_E911)
10068 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10069 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10070 }
10071 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10072 break;
10073 case SIG_FEATB:
10074 case SIG_SF_FEATB:
10075 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10076 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10077 break;
10078 case SIG_EMWINK:
10079
10080
10081
10082
10083 if (res == '*') {
10084 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10085 if (res > 0)
10086 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10087 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10088 break;
10089 }
10090 default:
10091
10092 len = 1;
10093 dtmfbuf[len] = '\0';
10094 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10095 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10096 timeout = matchdigittimeout;
10097 } else {
10098 timeout = gendigittimeout;
10099 }
10100 res = ast_waitfordigit(chan, timeout);
10101 if (res < 0) {
10102 ast_debug(1, "waitfordigit returned < 0...\n");
10103 ast_hangup(chan);
10104 goto quit;
10105 } else if (res) {
10106 dtmfbuf[len++] = res;
10107 dtmfbuf[len] = '\0';
10108 } else {
10109 break;
10110 }
10111 }
10112 break;
10113 }
10114 }
10115 if (res == -1) {
10116 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10117 ast_hangup(chan);
10118 goto quit;
10119 } else if (res < 0) {
10120 ast_debug(1, "Got hung up before digits finished\n");
10121 ast_hangup(chan);
10122 goto quit;
10123 }
10124
10125 if (p->sig == SIG_FGC_CAMA) {
10126 char anibuf[100];
10127
10128 if (ast_safe_sleep(chan,1000) == -1) {
10129 ast_hangup(chan);
10130 goto quit;
10131 }
10132 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10133 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10134 res = my_getsigstr(chan, anibuf, "#", 10000);
10135 if ((res > 0) && (strlen(anibuf) > 2)) {
10136 if (anibuf[strlen(anibuf) - 1] == '#')
10137 anibuf[strlen(anibuf) - 1] = 0;
10138 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10139 }
10140 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10141 }
10142
10143 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10144 if (ast_strlen_zero(exten))
10145 ast_copy_string(exten, "s", sizeof(exten));
10146 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10147
10148 if (exten[0] == '*') {
10149 char *stringp=NULL;
10150 ast_copy_string(exten2, exten, sizeof(exten2));
10151
10152 stringp=exten2 +1;
10153 s1 = strsep(&stringp, "*");
10154 s2 = strsep(&stringp, "*");
10155 if (s2) {
10156 if (!ast_strlen_zero(p->cid_num))
10157 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10158 else
10159 ast_set_callerid(chan, s1, NULL, s1);
10160 ast_copy_string(exten, s2, sizeof(exten));
10161 } else
10162 ast_copy_string(exten, s1, sizeof(exten));
10163 } else if (p->sig == SIG_FEATD)
10164 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10165 }
10166 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10167 if (exten[0] == '*') {
10168 char *stringp=NULL;
10169 ast_copy_string(exten2, exten, sizeof(exten2));
10170
10171 stringp=exten2 +1;
10172 s1 = strsep(&stringp, "#");
10173 s2 = strsep(&stringp, "#");
10174 if (s2) {
10175 if (!ast_strlen_zero(p->cid_num))
10176 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10177 else
10178 if (*(s1 + 2))
10179 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10180 ast_copy_string(exten, s2 + 1, sizeof(exten));
10181 } else
10182 ast_copy_string(exten, s1 + 2, sizeof(exten));
10183 } else
10184 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10185 }
10186 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10187 if (exten[0] == '*') {
10188 char *stringp=NULL;
10189 ast_copy_string(exten2, exten, sizeof(exten2));
10190
10191 stringp=exten2 +1;
10192 s1 = strsep(&stringp, "#");
10193 s2 = strsep(&stringp, "#");
10194 if (s2 && (*(s2 + 1) == '0')) {
10195 if (*(s2 + 2))
10196 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10197 }
10198 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10199 else ast_copy_string(exten, "911", sizeof(exten));
10200 } else
10201 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10202 }
10203 if (p->sig == SIG_FEATB) {
10204 if (exten[0] == '*') {
10205 char *stringp=NULL;
10206 ast_copy_string(exten2, exten, sizeof(exten2));
10207
10208 stringp=exten2 +1;
10209 s1 = strsep(&stringp, "#");
10210 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10211 } else
10212 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10213 }
10214 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10215 dahdi_wink(p, idx);
10216
10217
10218
10219 if (ast_safe_sleep(chan, 100)) {
10220 ast_hangup(chan);
10221 goto quit;
10222 }
10223 }
10224 dahdi_enable_ec(p);
10225 if (NEED_MFDETECT(p)) {
10226 if (p->dsp) {
10227 if (!p->hardwaredtmf)
10228 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10229 else {
10230 ast_dsp_free(p->dsp);
10231 p->dsp = NULL;
10232 }
10233 }
10234 }
10235
10236 if (ast_exists_extension(chan, chan->context, exten, 1,
10237 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10238 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10239 if (p->dsp) ast_dsp_digitreset(p->dsp);
10240 res = ast_pbx_run(chan);
10241 if (res) {
10242 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10243 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10244 }
10245 goto quit;
10246 } else {
10247 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10248 sleep(2);
10249 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10250 if (res < 0)
10251 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10252 else
10253 sleep(1);
10254 res = ast_streamfile(chan, "ss-noservice", chan->language);
10255 if (res >= 0)
10256 ast_waitstream(chan, "");
10257 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10258 ast_hangup(chan);
10259 goto quit;
10260 }
10261 break;
10262 case SIG_FXOLS:
10263 case SIG_FXOGS:
10264 case SIG_FXOKS:
10265
10266 timeout = firstdigittimeout;
10267
10268
10269 if (p->subs[SUB_THREEWAY].owner)
10270 timeout = 999999;
10271 while (len < AST_MAX_EXTENSION-1) {
10272
10273
10274 if (p->immediate)
10275 res = 's';
10276 else
10277 res = ast_waitfordigit(chan, timeout);
10278 timeout = 0;
10279 if (res < 0) {
10280 ast_debug(1, "waitfordigit returned < 0...\n");
10281 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10282 ast_hangup(chan);
10283 goto quit;
10284 } else if (res) {
10285 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10286 exten[len++]=res;
10287 exten[len] = '\0';
10288 }
10289 if (!ast_ignore_pattern(chan->context, exten))
10290 tone_zone_play_tone(p->subs[idx].dfd, -1);
10291 else
10292 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10293 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10294 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10295 if (getforward) {
10296
10297 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10298 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10299 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10300 if (res)
10301 break;
10302 usleep(500000);
10303 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10304 sleep(1);
10305 memset(exten, 0, sizeof(exten));
10306 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10307 len = 0;
10308 getforward = 0;
10309 } else {
10310 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10311 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10312 if (!ast_strlen_zero(p->cid_num)) {
10313 if (!p->hidecallerid)
10314 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10315 else
10316 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10317 }
10318 if (!ast_strlen_zero(p->cid_name)) {
10319 if (!p->hidecallerid)
10320 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10321 }
10322 ast_setstate(chan, AST_STATE_RING);
10323 dahdi_enable_ec(p);
10324 res = ast_pbx_run(chan);
10325 if (res) {
10326 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10327 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10328 }
10329 goto quit;
10330 }
10331 } else {
10332
10333
10334 timeout = matchdigittimeout;
10335 }
10336 } else if (res == 0) {
10337 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10338 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10339 dahdi_wait_event(p->subs[idx].dfd);
10340 ast_hangup(chan);
10341 goto quit;
10342 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10343 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10344
10345 p->callwaiting = 0;
10346 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10347 if (res) {
10348 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10349 chan->name, strerror(errno));
10350 }
10351 len = 0;
10352 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10353 memset(exten, 0, sizeof(exten));
10354 timeout = firstdigittimeout;
10355
10356 } else if (!strcmp(exten,ast_pickup_ext())) {
10357
10358
10359
10360
10361 if (idx == SUB_REAL) {
10362
10363 if (p->subs[SUB_THREEWAY].owner) {
10364
10365
10366 alloc_sub(p, SUB_CALLWAIT);
10367 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10368 unalloc_sub(p, SUB_THREEWAY);
10369 }
10370 dahdi_enable_ec(p);
10371 if (ast_pickup_call(chan)) {
10372 ast_debug(1, "No call pickup possible...\n");
10373 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10374 dahdi_wait_event(p->subs[idx].dfd);
10375 }
10376 ast_hangup(chan);
10377 goto quit;
10378 } else {
10379 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10380 ast_hangup(chan);
10381 goto quit;
10382 }
10383
10384 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10385 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10386
10387 p->hidecallerid = 1;
10388 ast_party_number_free(&chan->caller.id.number);
10389 ast_party_number_init(&chan->caller.id.number);
10390 ast_party_name_free(&chan->caller.id.name);
10391 ast_party_name_init(&chan->caller.id.name);
10392 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10393 if (res) {
10394 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10395 chan->name, strerror(errno));
10396 }
10397 len = 0;
10398 memset(exten, 0, sizeof(exten));
10399 timeout = firstdigittimeout;
10400 } else if (p->callreturn && !strcmp(exten, "*69")) {
10401 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10402 break;
10403 } else if (!strcmp(exten, "*78")) {
10404 dahdi_dnd(p, 1);
10405
10406 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10407 getforward = 0;
10408 memset(exten, 0, sizeof(exten));
10409 len = 0;
10410 } else if (!strcmp(exten, "*79")) {
10411 dahdi_dnd(p, 0);
10412
10413 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10414 getforward = 0;
10415 memset(exten, 0, sizeof(exten));
10416 len = 0;
10417 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10418 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10419 getforward = 1;
10420 memset(exten, 0, sizeof(exten));
10421 len = 0;
10422 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10423 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10424 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10425 memset(p->call_forward, 0, sizeof(p->call_forward));
10426 getforward = 0;
10427 memset(exten, 0, sizeof(exten));
10428 len = 0;
10429 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10430 p->subs[SUB_THREEWAY].owner &&
10431 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10432
10433
10434 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10435 chan, exten, chan->context, 0, NULL);
10436 ast_verb(3, "Parking call to '%s'\n", chan->name);
10437 break;
10438 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10439 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10440
10441 p->hidecallerid = 0;
10442 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10443 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10444 if (res) {
10445 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10446 chan->name, strerror(errno));
10447 }
10448 len = 0;
10449 memset(exten, 0, sizeof(exten));
10450 timeout = firstdigittimeout;
10451 } else if (!strcmp(exten, "*0")) {
10452 struct ast_channel *nbridge =
10453 p->subs[SUB_THREEWAY].owner;
10454 struct dahdi_pvt *pbridge = NULL;
10455
10456 if (nbridge && ast_bridged_channel(nbridge))
10457 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10458 if (nbridge && pbridge &&
10459 (nbridge->tech == &dahdi_tech) &&
10460 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10461 ISTRUNK(pbridge)) {
10462 int func = DAHDI_FLASH;
10463
10464 p->dop.dialstr[0] = '\0';
10465
10466 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10467 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10468 nbridge->name, strerror(errno));
10469 }
10470 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10471 unalloc_sub(p, SUB_THREEWAY);
10472 p->owner = p->subs[SUB_REAL].owner;
10473 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10474 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10475 ast_hangup(chan);
10476 goto quit;
10477 } else {
10478 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10479 dahdi_wait_event(p->subs[idx].dfd);
10480 tone_zone_play_tone(p->subs[idx].dfd, -1);
10481 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10482 unalloc_sub(p, SUB_THREEWAY);
10483 p->owner = p->subs[SUB_REAL].owner;
10484 ast_hangup(chan);
10485 goto quit;
10486 }
10487 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10488 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10489 && !canmatch_featurecode(exten)) {
10490 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10491 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10492 chan->context);
10493 break;
10494 }
10495 if (!timeout)
10496 timeout = gendigittimeout;
10497 if (len && !ast_ignore_pattern(chan->context, exten))
10498 tone_zone_play_tone(p->subs[idx].dfd, -1);
10499 }
10500 break;
10501 case SIG_FXSLS:
10502 case SIG_FXSGS:
10503 case SIG_FXSKS:
10504
10505 if (p->use_smdi && p->smdi_iface) {
10506 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10507
10508 if (smdi_msg != NULL) {
10509 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10510
10511 if (smdi_msg->type == 'B')
10512 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10513 else if (smdi_msg->type == 'N')
10514 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10515
10516 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10517 } else {
10518 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10519 }
10520 }
10521
10522 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10523 number = smdi_msg->calling_st;
10524
10525
10526
10527
10528 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10529 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10530
10531 if (p->cid_signalling == CID_SIG_DTMF) {
10532 int k = 0;
10533 int off_ms;
10534 struct timeval start = ast_tvnow();
10535 int ms;
10536 cs = NULL;
10537 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10538 dahdi_setlinear(p->subs[idx].dfd, 0);
10539
10540
10541
10542
10543
10544
10545 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10546 off_ms = 4000;
10547 for (;;) {
10548 struct ast_frame *f;
10549
10550 ms = ast_remaining_ms(start, off_ms);
10551 res = ast_waitfor(chan, ms);
10552 if (res <= 0) {
10553
10554
10555
10556
10557
10558 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10559 "Exiting simple switch\n");
10560 ast_hangup(chan);
10561 goto quit;
10562 }
10563 f = ast_read(chan);
10564 if (!f)
10565 break;
10566 if (f->frametype == AST_FRAME_DTMF) {
10567 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10568 dtmfbuf[k++] = f->subclass.integer;
10569 }
10570 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10571 start = ast_tvnow();
10572 }
10573 ast_frfree(f);
10574 if (chan->_state == AST_STATE_RING ||
10575 chan->_state == AST_STATE_RINGING)
10576 break;
10577 }
10578 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10579 dtmfbuf[k] = '\0';
10580 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10581
10582 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10583 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10584 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10585
10586 if (!ast_strlen_zero(dtmfcid))
10587 number = dtmfcid;
10588 else
10589 number = NULL;
10590
10591 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10592 cs = callerid_new(p->cid_signalling);
10593 if (cs) {
10594 int off_ms;
10595 struct timeval start;
10596 int ms;
10597 samples = 0;
10598 #if 1
10599 bump_gains(p);
10600 #endif
10601
10602 dahdi_setlinear(p->subs[idx].dfd, 0);
10603
10604
10605 for (;;) {
10606 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10607 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10608 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10609 callerid_free(cs);
10610 ast_hangup(chan);
10611 goto quit;
10612 }
10613 if (i & DAHDI_IOMUX_SIGEVENT) {
10614 res = dahdi_get_event(p->subs[idx].dfd);
10615 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10616 if (res == DAHDI_EVENT_NOALARM) {
10617 p->inalarm = 0;
10618 }
10619
10620 if (p->cid_signalling == CID_SIG_V23_JP) {
10621 if (res == DAHDI_EVENT_RINGBEGIN) {
10622 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10623 usleep(1);
10624 }
10625 } else {
10626 res = 0;
10627 break;
10628 }
10629 } else if (i & DAHDI_IOMUX_READ) {
10630 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10631 if (res < 0) {
10632 if (errno != ELAST) {
10633 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10634 callerid_free(cs);
10635 ast_hangup(chan);
10636 goto quit;
10637 }
10638 break;
10639 }
10640 samples += res;
10641
10642 if (p->cid_signalling == CID_SIG_V23_JP) {
10643 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10644 } else {
10645 res = callerid_feed(cs, buf, res, AST_LAW(p));
10646 }
10647 if (res < 0) {
10648
10649
10650
10651
10652 ast_log(LOG_WARNING,
10653 "Failed to decode CallerID on channel '%s'\n",
10654 chan->name);
10655 break;
10656 } else if (res)
10657 break;
10658 else if (samples > (8000 * 10))
10659 break;
10660 }
10661 }
10662 if (res == 1) {
10663 callerid_get(cs, &name, &number, &flags);
10664 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10665 }
10666
10667 if (p->cid_signalling == CID_SIG_V23_JP) {
10668 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10669 usleep(1);
10670 }
10671
10672
10673 start = ast_tvnow();
10674 off_ms = 4000;
10675 for (;;) {
10676 struct ast_frame *f;
10677
10678 ms = ast_remaining_ms(start, off_ms);
10679 res = ast_waitfor(chan, ms);
10680 if (res <= 0) {
10681 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10682 "Exiting simple switch\n");
10683 ast_hangup(chan);
10684 goto quit;
10685 }
10686 if (!(f = ast_read(chan))) {
10687 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10688 ast_hangup(chan);
10689 goto quit;
10690 }
10691 ast_frfree(f);
10692 if (chan->_state == AST_STATE_RING ||
10693 chan->_state == AST_STATE_RINGING)
10694 break;
10695 }
10696
10697
10698
10699 if (p->usedistinctiveringdetection) {
10700 len = 0;
10701 distMatches = 0;
10702
10703 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10704 curRingData[receivedRingT] = 0;
10705 receivedRingT = 0;
10706 counter = 0;
10707 counter1 = 0;
10708
10709 if (strcmp(p->context,p->defcontext) != 0) {
10710 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10711 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10712 }
10713
10714 for (;;) {
10715 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10716 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10717 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10718 callerid_free(cs);
10719 ast_hangup(chan);
10720 goto quit;
10721 }
10722 if (i & DAHDI_IOMUX_SIGEVENT) {
10723 res = dahdi_get_event(p->subs[idx].dfd);
10724 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10725 if (res == DAHDI_EVENT_NOALARM) {
10726 p->inalarm = 0;
10727 }
10728 res = 0;
10729
10730
10731 curRingData[receivedRingT] = p->ringt;
10732
10733 if (p->ringt < p->ringt_base/2)
10734 break;
10735
10736
10737 if (++receivedRingT == ARRAY_LEN(curRingData))
10738 break;
10739 } else if (i & DAHDI_IOMUX_READ) {
10740 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10741 if (res < 0) {
10742 if (errno != ELAST) {
10743 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10744 callerid_free(cs);
10745 ast_hangup(chan);
10746 goto quit;
10747 }
10748 break;
10749 }
10750 if (p->ringt > 0) {
10751 if (!(--p->ringt)) {
10752 res = -1;
10753 break;
10754 }
10755 }
10756 }
10757 }
10758
10759 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10760 for (counter = 0; counter < 3; counter++) {
10761
10762
10763 distMatches = 0;
10764 for (counter1 = 0; counter1 < 3; counter1++) {
10765 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10766 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10767 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10768 curRingData[counter1]);
10769 distMatches++;
10770 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10771 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10772 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10773 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10774 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10775 distMatches++;
10776 }
10777 }
10778
10779 if (distMatches == 3) {
10780
10781 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10782 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10783 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10784 break;
10785 }
10786 }
10787 }
10788
10789 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10790 #if 1
10791 restore_gains(p);
10792 #endif
10793 } else
10794 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10795 } else {
10796 ast_log(LOG_WARNING, "Channel %s in prering "
10797 "state, but I have nothing to do. "
10798 "Terminating simple switch, should be "
10799 "restarted by the actual ring.\n",
10800 chan->name);
10801 ast_hangup(chan);
10802 goto quit;
10803 }
10804 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10805 if (p->cid_signalling == CID_SIG_DTMF) {
10806 int k = 0;
10807 int off_ms;
10808 struct timeval start;
10809 int ms;
10810 cs = NULL;
10811 dahdi_setlinear(p->subs[idx].dfd, 0);
10812 off_ms = 2000;
10813 start = ast_tvnow();
10814 for (;;) {
10815 struct ast_frame *f;
10816
10817 ms = ast_remaining_ms(start, off_ms);
10818 res = ast_waitfor(chan, ms);
10819 if (res <= 0) {
10820 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10821 "Exiting simple switch\n");
10822 ast_hangup(chan);
10823 goto quit;
10824 }
10825 f = ast_read(chan);
10826 if (!f) {
10827
10828 ast_hangup(chan);
10829 goto quit;
10830 }
10831 if (f->frametype == AST_FRAME_DTMF) {
10832 dtmfbuf[k++] = f->subclass.integer;
10833 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10834 start = ast_tvnow();
10835 }
10836 ast_frfree(f);
10837
10838 if (p->ringt_base == p->ringt)
10839 break;
10840 }
10841 dtmfbuf[k] = '\0';
10842 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10843
10844 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10845 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10846 dtmfcid, flags);
10847
10848 if (!ast_strlen_zero(dtmfcid))
10849 number = dtmfcid;
10850 else
10851 number = NULL;
10852
10853 } else {
10854
10855 cs = callerid_new(p->cid_signalling);
10856 if (cs) {
10857 #if 1
10858 bump_gains(p);
10859 #endif
10860 samples = 0;
10861 len = 0;
10862 distMatches = 0;
10863
10864 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10865 curRingData[receivedRingT] = 0;
10866 receivedRingT = 0;
10867 counter = 0;
10868 counter1 = 0;
10869
10870 if (strcmp(p->context,p->defcontext) != 0) {
10871 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10872 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10873 }
10874
10875
10876 dahdi_setlinear(p->subs[idx].dfd, 0);
10877 for (;;) {
10878 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10879 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10880 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10881 callerid_free(cs);
10882 ast_hangup(chan);
10883 goto quit;
10884 }
10885 if (i & DAHDI_IOMUX_SIGEVENT) {
10886 res = dahdi_get_event(p->subs[idx].dfd);
10887 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10888 if (res == DAHDI_EVENT_NOALARM) {
10889 p->inalarm = 0;
10890 }
10891
10892 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10893 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10894 p->polarity = POLARITY_IDLE;
10895 callerid_free(cs);
10896 ast_hangup(chan);
10897 goto quit;
10898 }
10899 res = 0;
10900
10901
10902 curRingData[receivedRingT] = p->ringt;
10903
10904 if (p->ringt < p->ringt_base/2)
10905 break;
10906
10907
10908 if (++receivedRingT == ARRAY_LEN(curRingData))
10909 break;
10910 } else if (i & DAHDI_IOMUX_READ) {
10911 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10912 if (res < 0) {
10913 if (errno != ELAST) {
10914 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10915 callerid_free(cs);
10916 ast_hangup(chan);
10917 goto quit;
10918 }
10919 break;
10920 }
10921 if (p->ringt > 0) {
10922 if (!(--p->ringt)) {
10923 res = -1;
10924 break;
10925 }
10926 }
10927 samples += res;
10928 res = callerid_feed(cs, buf, res, AST_LAW(p));
10929 if (res < 0) {
10930
10931
10932
10933
10934 ast_log(LOG_WARNING,
10935 "Failed to decode CallerID on channel '%s'\n",
10936 chan->name);
10937 break;
10938 } else if (res)
10939 break;
10940 else if (samples > (8000 * 10))
10941 break;
10942 }
10943 }
10944 if (res == 1) {
10945 callerid_get(cs, &name, &number, &flags);
10946 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10947 }
10948 if (distinctiveringaftercid == 1) {
10949
10950 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10951 curRingData[receivedRingT] = 0;
10952 }
10953 receivedRingT = 0;
10954 ast_verb(3, "Detecting post-CID distinctive ring\n");
10955 for (;;) {
10956 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10957 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10958 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10959 callerid_free(cs);
10960 ast_hangup(chan);
10961 goto quit;
10962 }
10963 if (i & DAHDI_IOMUX_SIGEVENT) {
10964 res = dahdi_get_event(p->subs[idx].dfd);
10965 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10966 if (res == DAHDI_EVENT_NOALARM) {
10967 p->inalarm = 0;
10968 }
10969 res = 0;
10970
10971
10972 curRingData[receivedRingT] = p->ringt;
10973
10974 if (p->ringt < p->ringt_base/2)
10975 break;
10976
10977
10978 if (++receivedRingT == ARRAY_LEN(curRingData))
10979 break;
10980 } else if (i & DAHDI_IOMUX_READ) {
10981 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10982 if (res < 0) {
10983 if (errno != ELAST) {
10984 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10985 callerid_free(cs);
10986 ast_hangup(chan);
10987 goto quit;
10988 }
10989 break;
10990 }
10991 if (p->ringt > 0) {
10992 if (!(--p->ringt)) {
10993 res = -1;
10994 break;
10995 }
10996 }
10997 }
10998 }
10999 }
11000 if (p->usedistinctiveringdetection) {
11001
11002 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11003
11004 for (counter = 0; counter < 3; counter++) {
11005
11006
11007
11008 ast_verb(3, "Checking %d,%d,%d\n",
11009 p->drings.ringnum[counter].ring[0],
11010 p->drings.ringnum[counter].ring[1],
11011 p->drings.ringnum[counter].ring[2]);
11012 distMatches = 0;
11013 for (counter1 = 0; counter1 < 3; counter1++) {
11014 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11015 if (p->drings.ringnum[counter].ring[counter1] == -1) {
11016 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11017 curRingData[counter1]);
11018 distMatches++;
11019 }
11020 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11021 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11022 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11023 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11024 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11025 distMatches++;
11026 }
11027 }
11028 if (distMatches == 3) {
11029
11030 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11031 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11032 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11033 break;
11034 }
11035 }
11036 }
11037
11038 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11039 #if 1
11040 restore_gains(p);
11041 #endif
11042 if (res < 0) {
11043 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11044 }
11045 } else
11046 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11047 }
11048 } else
11049 cs = NULL;
11050
11051 if (number)
11052 ast_shrink_phone_number(number);
11053 ast_set_callerid(chan, number, name, number);
11054
11055 if (smdi_msg)
11056 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11057
11058 if (cs)
11059 callerid_free(cs);
11060
11061 my_handle_notify_message(chan, p, flags, -1);
11062
11063 ast_setstate(chan, AST_STATE_RING);
11064 chan->rings = 1;
11065 p->ringt = p->ringt_base;
11066 res = ast_pbx_run(chan);
11067 if (res) {
11068 ast_hangup(chan);
11069 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11070 }
11071 goto quit;
11072 default:
11073 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11074 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11075 if (res < 0)
11076 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11077 }
11078 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11079 if (res < 0)
11080 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11081 ast_hangup(chan);
11082 quit:
11083 ast_mutex_lock(&ss_thread_lock);
11084 ss_thread_count--;
11085 ast_cond_signal(&ss_thread_complete);
11086 ast_mutex_unlock(&ss_thread_lock);
11087 return NULL;
11088 }
11089
11090 struct mwi_thread_data {
11091 struct dahdi_pvt *pvt;
11092 unsigned char buf[READ_SIZE];
11093 size_t len;
11094 };
11095
11096 static int calc_energy(const unsigned char *buf, int len, format_t law)
11097 {
11098 int x;
11099 int sum = 0;
11100
11101 if (!len)
11102 return 0;
11103
11104 for (x = 0; x < len; x++)
11105 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11106
11107 return sum / len;
11108 }
11109
11110 static void *mwi_thread(void *data)
11111 {
11112 struct mwi_thread_data *mtd = data;
11113 struct callerid_state *cs;
11114 pthread_t threadid;
11115 int samples = 0;
11116 char *name, *number;
11117 int flags;
11118 int i, res;
11119 unsigned int spill_done = 0;
11120 int spill_result = -1;
11121
11122 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11123 goto quit_no_clean;
11124 }
11125
11126 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11127
11128 bump_gains(mtd->pvt);
11129
11130 for (;;) {
11131 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11132 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11133 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11134 goto quit;
11135 }
11136
11137 if (i & DAHDI_IOMUX_SIGEVENT) {
11138 struct ast_channel *chan;
11139
11140
11141
11142
11143 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11144
11145 switch (res) {
11146 case DAHDI_EVENT_NEONMWI_ACTIVE:
11147 case DAHDI_EVENT_NEONMWI_INACTIVE:
11148 case DAHDI_EVENT_NONE:
11149 case DAHDI_EVENT_BITSCHANGED:
11150 break;
11151 case DAHDI_EVENT_NOALARM:
11152 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11153 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11154
11155 analog_p->inalarm = 0;
11156 }
11157 mtd->pvt->inalarm = 0;
11158 handle_clear_alarms(mtd->pvt);
11159 break;
11160 case DAHDI_EVENT_ALARM:
11161 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11162 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11163
11164 analog_p->inalarm = 1;
11165 }
11166 mtd->pvt->inalarm = 1;
11167 res = get_alarms(mtd->pvt);
11168 handle_alarms(mtd->pvt, res);
11169 break;
11170 default:
11171 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11172 callerid_free(cs);
11173
11174 restore_gains(mtd->pvt);
11175 mtd->pvt->ringt = mtd->pvt->ringt_base;
11176
11177 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11178 int result;
11179
11180 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11181 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11182 } else {
11183 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11184 }
11185 if (result) {
11186 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11187 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11188 if (res < 0)
11189 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11190 ast_hangup(chan);
11191 }
11192 } else {
11193 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11194 }
11195 goto quit_no_clean;
11196 }
11197 } else if (i & DAHDI_IOMUX_READ) {
11198 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11199 if (errno != ELAST) {
11200 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11201 goto quit;
11202 }
11203 break;
11204 }
11205 samples += res;
11206 if (!spill_done) {
11207 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11208
11209
11210
11211
11212 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11213 break;
11214 } else if (spill_result) {
11215 spill_done = 1;
11216 }
11217 } else {
11218
11219
11220
11221 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11222 break;
11223 }
11224 if (samples > (8000 * 4))
11225 break;
11226 }
11227 }
11228
11229 if (spill_result == 1) {
11230 callerid_get(cs, &name, &number, &flags);
11231 if (flags & CID_MSGWAITING) {
11232 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11233 notify_message(mtd->pvt->mailbox, 1);
11234 } else if (flags & CID_NOMSGWAITING) {
11235 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11236 notify_message(mtd->pvt->mailbox, 0);
11237 } else {
11238 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11239 }
11240 }
11241
11242
11243 quit:
11244 callerid_free(cs);
11245
11246 restore_gains(mtd->pvt);
11247
11248 quit_no_clean:
11249 mtd->pvt->mwimonitoractive = 0;
11250 ast_free(mtd);
11251
11252 return NULL;
11253 }
11254
11255
11256
11257
11258
11259
11260
11261
11262 static int mwi_send_init(struct dahdi_pvt * pvt)
11263 {
11264 int x;
11265
11266 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11267
11268 if (pvt->mwisend_rpas) {
11269 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11270 pvt->mwisendactive = 1;
11271 } else if (pvt->mwisend_fsk) {
11272 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11273 pvt->mwisendactive = 1;
11274 } else {
11275 pvt->mwisendactive = 0;
11276 return 0;
11277 }
11278 #else
11279 if (mwisend_rpas) {
11280 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11281 } else {
11282 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11283 }
11284 pvt->mwisendactive = 1;
11285 #endif
11286
11287 if (pvt->cidspill) {
11288 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11289 ast_free(pvt->cidspill);
11290 pvt->cidspill = NULL;
11291 pvt->cidpos = 0;
11292 pvt->cidlen = 0;
11293 }
11294 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11295 if (!pvt->cidspill) {
11296 pvt->mwisendactive = 0;
11297 return -1;
11298 }
11299 x = DAHDI_FLUSH_BOTH;
11300 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11301 x = 3000;
11302 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11303 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11304 if (pvt->mwisend_fsk) {
11305 #endif
11306 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11307 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11308 pvt->cidpos = 0;
11309 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11310 }
11311 #endif
11312 return 0;
11313 }
11314
11315 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11316 {
11317 struct timeval now;
11318 int res;
11319
11320
11321
11322
11323 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11324 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11325 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11326
11327 switch ( pvt->mwisend_data.mwisend_current) {
11328 case MWI_SEND_SA:
11329
11330 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11331 if (res) {
11332 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11333 goto quit;
11334 }
11335 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11336 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11337 break;
11338 case MWI_SEND_SA_WAIT:
11339 break;
11340 case MWI_SEND_PAUSE:
11341 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11342 if (pvt->mwisend_fsk) {
11343 #endif
11344 gettimeofday(&now, NULL);
11345 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11346 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11347 }
11348 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11349 } else {
11350 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11351 }
11352 #endif
11353 break;
11354 case MWI_SEND_SPILL:
11355
11356 if(0 < num_read) {
11357 if (num_read > pvt->cidlen - pvt->cidpos)
11358 num_read = pvt->cidlen - pvt->cidpos;
11359 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11360 if (res > 0) {
11361 pvt->cidpos += res;
11362 if (pvt->cidpos >= pvt->cidlen) {
11363 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11364 }
11365 } else {
11366 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11367 goto quit;
11368 }
11369 }
11370 break;
11371 case MWI_SEND_CLEANUP:
11372
11373 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11374 break;
11375 default:
11376
11377 goto quit;
11378 }
11379 }
11380
11381 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11382 if (pvt->cidspill) {
11383 ast_free(pvt->cidspill);
11384 pvt->cidspill = NULL;
11385 pvt->cidpos = 0;
11386 pvt->cidlen = 0;
11387 }
11388 pvt->mwisendactive = 0;
11389 }
11390 return 0;
11391 quit:
11392 if (pvt->cidspill) {
11393 ast_free(pvt->cidspill);
11394 pvt->cidspill = NULL;
11395 pvt->cidpos = 0;
11396 pvt->cidlen = 0;
11397 }
11398 pvt->mwisendactive = 0;
11399 return -1;
11400 }
11401
11402 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11403 {
11404 int handled = 0;
11405
11406 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11407 switch (event) {
11408 case DAHDI_EVENT_RINGEROFF:
11409 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11410 handled = 1;
11411
11412 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11413 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11414 ast_free(pvt->cidspill);
11415 pvt->cidspill = NULL;
11416 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11417 pvt->mwisendactive = 0;
11418 } else {
11419 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11420 gettimeofday(&pvt->mwisend_data.pause, NULL);
11421 }
11422 }
11423 break;
11424
11425 case DAHDI_EVENT_RINGOFFHOOK:
11426 if (pvt->cidspill) {
11427 ast_free(pvt->cidspill);
11428 pvt->cidspill = NULL;
11429 pvt->cidpos = 0;
11430 pvt->cidlen = 0;
11431 }
11432 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11433 pvt->mwisendactive = 0;
11434 break;
11435 case DAHDI_EVENT_RINGERON:
11436 case DAHDI_EVENT_HOOKCOMPLETE:
11437 break;
11438 default:
11439 break;
11440 }
11441 }
11442 return handled;
11443 }
11444
11445
11446 static int dahdi_destroy_channel_bynum(int channel)
11447 {
11448 struct dahdi_pvt *cur;
11449
11450 ast_mutex_lock(&iflock);
11451 for (cur = iflist; cur; cur = cur->next) {
11452 if (cur->channel == channel) {
11453 int x = DAHDI_FLASH;
11454
11455
11456 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11457
11458 destroy_channel(cur, 1);
11459 ast_mutex_unlock(&iflock);
11460 ast_module_unref(ast_module_info->self);
11461 return RESULT_SUCCESS;
11462 }
11463 }
11464 ast_mutex_unlock(&iflock);
11465 return RESULT_FAILURE;
11466 }
11467
11468 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11469 {
11470 int res;
11471 pthread_t threadid;
11472 struct ast_channel *chan;
11473
11474
11475
11476 switch (event) {
11477 case DAHDI_EVENT_NONE:
11478 case DAHDI_EVENT_BITSCHANGED:
11479 break;
11480 case DAHDI_EVENT_WINKFLASH:
11481 case DAHDI_EVENT_RINGOFFHOOK:
11482 if (i->inalarm) break;
11483 if (i->radio) break;
11484
11485 switch (i->sig) {
11486 case SIG_FXOLS:
11487 case SIG_FXOGS:
11488 case SIG_FXOKS:
11489 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11490 if (res && (errno == EBUSY))
11491 break;
11492
11493
11494 ast_free(i->cidspill);
11495 i->cidspill = NULL;
11496 restore_conference(i);
11497
11498 if (i->immediate) {
11499 dahdi_enable_ec(i);
11500
11501 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11502 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11503 if (!chan) {
11504 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11505 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11506 if (res < 0)
11507 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11508 }
11509 } else {
11510
11511 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11512 if (chan) {
11513 if (has_voicemail(i))
11514 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11515 else
11516 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11517 if (res < 0)
11518 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11519 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11520 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11521 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11522 if (res < 0)
11523 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11524 ast_hangup(chan);
11525 }
11526 } else
11527 ast_log(LOG_WARNING, "Unable to create channel\n");
11528 }
11529 break;
11530 case SIG_FXSLS:
11531 case SIG_FXSGS:
11532 case SIG_FXSKS:
11533 i->ringt = i->ringt_base;
11534
11535 case SIG_EMWINK:
11536 case SIG_FEATD:
11537 case SIG_FEATDMF:
11538 case SIG_FEATDMF_TA:
11539 case SIG_E911:
11540 case SIG_FGC_CAMA:
11541 case SIG_FGC_CAMAMF:
11542 case SIG_FEATB:
11543 case SIG_EM:
11544 case SIG_EM_E1:
11545 case SIG_SFWINK:
11546 case SIG_SF_FEATD:
11547 case SIG_SF_FEATDMF:
11548 case SIG_SF_FEATB:
11549 case SIG_SF:
11550
11551 if (i->cid_start == CID_START_POLARITY_IN) {
11552 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11553 } else {
11554 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11555 }
11556
11557 if (!chan) {
11558 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11559 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11560 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11561 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11562 if (res < 0) {
11563 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11564 }
11565 ast_hangup(chan);
11566 }
11567 break;
11568 default:
11569 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11570 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11571 if (res < 0)
11572 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11573 return NULL;
11574 }
11575 break;
11576 case DAHDI_EVENT_NOALARM:
11577 switch (i->sig) {
11578 #if defined(HAVE_PRI)
11579 case SIG_PRI_LIB_HANDLE_CASES:
11580 ast_mutex_lock(&i->lock);
11581 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11582 ast_mutex_unlock(&i->lock);
11583 break;
11584 #endif
11585 #if defined(HAVE_SS7)
11586 case SIG_SS7:
11587 sig_ss7_set_alarm(i->sig_pvt, 0);
11588 break;
11589 #endif
11590 default:
11591 i->inalarm = 0;
11592 break;
11593 }
11594 handle_clear_alarms(i);
11595 break;
11596 case DAHDI_EVENT_ALARM:
11597 switch (i->sig) {
11598 #if defined(HAVE_PRI)
11599 case SIG_PRI_LIB_HANDLE_CASES:
11600 ast_mutex_lock(&i->lock);
11601 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11602 ast_mutex_unlock(&i->lock);
11603 break;
11604 #endif
11605 #if defined(HAVE_SS7)
11606 case SIG_SS7:
11607 sig_ss7_set_alarm(i->sig_pvt, 1);
11608 break;
11609 #endif
11610 default:
11611 i->inalarm = 1;
11612 break;
11613 }
11614 res = get_alarms(i);
11615 handle_alarms(i, res);
11616
11617 case DAHDI_EVENT_ONHOOK:
11618 if (i->radio)
11619 break;
11620
11621 switch (i->sig) {
11622 case SIG_FXOLS:
11623 case SIG_FXOGS:
11624 case SIG_FEATD:
11625 case SIG_FEATDMF:
11626 case SIG_FEATDMF_TA:
11627 case SIG_E911:
11628 case SIG_FGC_CAMA:
11629 case SIG_FGC_CAMAMF:
11630 case SIG_FEATB:
11631 case SIG_EM:
11632 case SIG_EM_E1:
11633 case SIG_EMWINK:
11634 case SIG_SF_FEATD:
11635 case SIG_SF_FEATDMF:
11636 case SIG_SF_FEATB:
11637 case SIG_SF:
11638 case SIG_SFWINK:
11639 case SIG_FXSLS:
11640 case SIG_FXSGS:
11641 case SIG_FXSKS:
11642 case SIG_FXOKS:
11643 dahdi_disable_ec(i);
11644
11645 #ifdef ZHONE_HACK
11646 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11647 usleep(1);
11648 #endif
11649 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11650 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11651 break;
11652 case SIG_SS7:
11653 case SIG_PRI_LIB_HANDLE_CASES:
11654 dahdi_disable_ec(i);
11655 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11656 break;
11657 default:
11658 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11659 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11660 return NULL;
11661 }
11662 break;
11663 case DAHDI_EVENT_POLARITY:
11664 switch (i->sig) {
11665 case SIG_FXSLS:
11666 case SIG_FXSKS:
11667 case SIG_FXSGS:
11668
11669
11670
11671
11672 if (i->hanguponpolarityswitch)
11673 i->polarity = POLARITY_REV;
11674 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11675 i->polarity = POLARITY_REV;
11676 ast_verb(2, "Starting post polarity "
11677 "CID detection on channel %d\n",
11678 i->channel);
11679 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11680 if (!chan) {
11681 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11682 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11683 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11684 ast_hangup(chan);
11685 }
11686 }
11687 break;
11688 default:
11689 ast_log(LOG_WARNING, "handle_init_event detected "
11690 "polarity reversal on non-FXO (SIG_FXS) "
11691 "interface %d\n", i->channel);
11692 }
11693 break;
11694 case DAHDI_EVENT_REMOVED:
11695 ast_log(LOG_NOTICE,
11696 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11697 i->channel);
11698 return i;
11699 case DAHDI_EVENT_NEONMWI_ACTIVE:
11700 if (i->mwimonitor_neon) {
11701 notify_message(i->mailbox, 1);
11702 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11703 }
11704 break;
11705 case DAHDI_EVENT_NEONMWI_INACTIVE:
11706 if (i->mwimonitor_neon) {
11707 notify_message(i->mailbox, 0);
11708 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11709 }
11710 break;
11711 }
11712 return NULL;
11713 }
11714
11715 static void monitor_pfds_clean(void *arg) {
11716 struct pollfd **pfds = arg;
11717 ast_free(*pfds);
11718 }
11719
11720 static void *do_monitor(void *data)
11721 {
11722 int count, res, res2, spoint, pollres=0;
11723 struct dahdi_pvt *i;
11724 struct dahdi_pvt *last = NULL;
11725 struct dahdi_pvt *doomed;
11726 time_t thispass = 0, lastpass = 0;
11727 int found;
11728 char buf[1024];
11729 struct pollfd *pfds=NULL;
11730 int lastalloc = -1;
11731
11732
11733
11734 #if 0
11735 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11736 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11737 return NULL;
11738 }
11739 ast_debug(1, "Monitor starting...\n");
11740 #endif
11741 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11742
11743 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11744 for (;;) {
11745
11746 ast_mutex_lock(&iflock);
11747 if (!pfds || (lastalloc != ifcount)) {
11748 if (pfds) {
11749 ast_free(pfds);
11750 pfds = NULL;
11751 }
11752 if (ifcount) {
11753 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11754 ast_mutex_unlock(&iflock);
11755 return NULL;
11756 }
11757 }
11758 lastalloc = ifcount;
11759 }
11760
11761
11762 count = 0;
11763 for (i = iflist; i; i = i->next) {
11764 ast_mutex_lock(&i->lock);
11765 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11766 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11767 struct analog_pvt *p = i->sig_pvt;
11768
11769 if (!p) {
11770 ast_log(LOG_ERROR, "No sig_pvt?\n");
11771 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11772
11773 pfds[count].fd = i->subs[SUB_REAL].dfd;
11774 pfds[count].events = POLLPRI;
11775 pfds[count].revents = 0;
11776
11777 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11778 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11779 pfds[count].events |= POLLIN;
11780 }
11781 count++;
11782 }
11783 } else {
11784 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11785
11786 pfds[count].fd = i->subs[SUB_REAL].dfd;
11787 pfds[count].events = POLLPRI;
11788 pfds[count].revents = 0;
11789
11790
11791 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11792 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11793 pfds[count].events |= POLLIN;
11794 }
11795 count++;
11796 }
11797 }
11798 }
11799 ast_mutex_unlock(&i->lock);
11800 }
11801
11802 ast_mutex_unlock(&iflock);
11803
11804 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11805 pthread_testcancel();
11806
11807 res = poll(pfds, count, 1000);
11808 pthread_testcancel();
11809 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11810
11811
11812 if (res < 0) {
11813 if ((errno != EAGAIN) && (errno != EINTR))
11814 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11815 continue;
11816 }
11817
11818
11819 ast_mutex_lock(&iflock);
11820 found = 0;
11821 spoint = 0;
11822 lastpass = thispass;
11823 thispass = time(NULL);
11824 doomed = NULL;
11825 for (i = iflist;; i = i->next) {
11826 if (doomed) {
11827 int res;
11828 res = dahdi_destroy_channel_bynum(doomed->channel);
11829 if (res != RESULT_SUCCESS) {
11830 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11831 }
11832 doomed = NULL;
11833 }
11834 if (!i) {
11835 break;
11836 }
11837
11838 if (thispass != lastpass) {
11839 if (!found && ((i == last) || ((i == iflist) && !last))) {
11840 last = i;
11841 if (last) {
11842 struct analog_pvt *analog_p = last->sig_pvt;
11843
11844 if (analog_p
11845 && !last->mwisendactive
11846 && (last->sig & __DAHDI_SIG_FXO)
11847 && !analog_p->fxsoffhookstate
11848 && !last->owner
11849 && !ast_strlen_zero(last->mailbox)
11850 && (thispass - analog_p->onhooktime > 3)) {
11851 res = has_voicemail(last);
11852 if (analog_p->msgstate != res) {
11853
11854 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11855 if (res2) {
11856
11857 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11858 }
11859
11860 if (mwi_send_init(last)) {
11861 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11862 }
11863 analog_p->msgstate = res;
11864 found ++;
11865 }
11866 }
11867 last = last->next;
11868 }
11869 }
11870 }
11871 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11872 if (i->radio && !i->owner)
11873 {
11874 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11875 if (res)
11876 {
11877 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11878
11879 ast_mutex_unlock(&iflock);
11880 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11881 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11882 else
11883 doomed = handle_init_event(i, res);
11884 ast_mutex_lock(&iflock);
11885 }
11886 continue;
11887 }
11888 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11889 if (pollres & POLLIN) {
11890 if (i->owner || i->subs[SUB_REAL].owner) {
11891 #ifdef HAVE_PRI
11892 if (!i->pri)
11893 #endif
11894 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11895 continue;
11896 }
11897 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11898 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11899 continue;
11900 }
11901 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11902 if (res > 0) {
11903 if (i->mwimonitor_fsk) {
11904 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11905 pthread_attr_t attr;
11906 pthread_t threadid;
11907 struct mwi_thread_data *mtd;
11908
11909 pthread_attr_init(&attr);
11910 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11911
11912 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11913 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11914 mtd->pvt = i;
11915 memcpy(mtd->buf, buf, res);
11916 mtd->len = res;
11917 i->mwimonitoractive = 1;
11918 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11919 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11920 i->mwimonitoractive = 0;
11921 ast_free(mtd);
11922 }
11923 }
11924 }
11925
11926 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11927 int energy;
11928 struct timeval now;
11929
11930
11931
11932 if (1 == i->dtmfcid_holdoff_state) {
11933 gettimeofday(&i->dtmfcid_delay, NULL);
11934 i->dtmfcid_holdoff_state = 2;
11935 } else if (2 == i->dtmfcid_holdoff_state) {
11936 gettimeofday(&now, NULL);
11937 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11938 i->dtmfcid_holdoff_state = 0;
11939 }
11940 } else {
11941 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11942 if (!i->mwisendactive && energy > dtmfcid_level) {
11943 pthread_t threadid;
11944 struct ast_channel *chan;
11945 ast_mutex_unlock(&iflock);
11946 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11947
11948 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11949 i->dtmfcid_holdoff_state = 1;
11950 } else {
11951 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11952 if (!chan) {
11953 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11954 } else {
11955 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11956 if (res) {
11957 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11958 ast_hangup(chan);
11959 } else {
11960 i->dtmfcid_holdoff_state = 1;
11961 }
11962 }
11963 }
11964 ast_mutex_lock(&iflock);
11965 }
11966 }
11967 }
11968 if (i->mwisendactive) {
11969 mwi_send_process_buffer(i, res);
11970 }
11971 } else {
11972 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11973 }
11974 }
11975 if (pollres & POLLPRI) {
11976 if (i->owner || i->subs[SUB_REAL].owner) {
11977 #ifdef HAVE_PRI
11978 if (!i->pri)
11979 #endif
11980 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11981 continue;
11982 }
11983 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11984 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11985
11986 ast_mutex_unlock(&iflock);
11987 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11988 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11989 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11990 else
11991 doomed = handle_init_event(i, res);
11992 }
11993 ast_mutex_lock(&iflock);
11994 }
11995 }
11996 }
11997 ast_mutex_unlock(&iflock);
11998 }
11999
12000 pthread_cleanup_pop(1);
12001 return NULL;
12002
12003 }
12004
12005 static int restart_monitor(void)
12006 {
12007
12008 if (monitor_thread == AST_PTHREADT_STOP)
12009 return 0;
12010 ast_mutex_lock(&monlock);
12011 if (monitor_thread == pthread_self()) {
12012 ast_mutex_unlock(&monlock);
12013 ast_log(LOG_WARNING, "Cannot kill myself\n");
12014 return -1;
12015 }
12016 if (monitor_thread != AST_PTHREADT_NULL) {
12017
12018 pthread_kill(monitor_thread, SIGURG);
12019 } else {
12020
12021 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12022 ast_mutex_unlock(&monlock);
12023 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12024 return -1;
12025 }
12026 }
12027 ast_mutex_unlock(&monlock);
12028 return 0;
12029 }
12030
12031 #if defined(HAVE_PRI)
12032 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12033 {
12034 int x;
12035 int trunkgroup;
12036
12037 trunkgroup = pris[*span].mastertrunkgroup;
12038 if (trunkgroup) {
12039
12040 for (x = 0; x < NUM_SPANS; x++) {
12041 if (pris[x].pri.trunkgroup == trunkgroup) {
12042 *span = x;
12043 return 0;
12044 }
12045 }
12046 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12047 *span = -1;
12048 } else {
12049 if (pris[*span].pri.trunkgroup) {
12050 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);
12051 *span = -1;
12052 } else if (pris[*span].mastertrunkgroup) {
12053 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12054 *span = -1;
12055 } else {
12056 if (si->totalchans == 31) {
12057
12058 pris[*span].dchannels[0] = 16 + offset;
12059 } else if (si->totalchans == 24) {
12060
12061 pris[*span].dchannels[0] = 24 + offset;
12062 } else if (si->totalchans == 3) {
12063
12064 pris[*span].dchannels[0] = 3 + offset;
12065 } else {
12066 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);
12067 *span = -1;
12068 return 0;
12069 }
12070 pris[*span].pri.span = *span + 1;
12071 }
12072 }
12073 return 0;
12074 }
12075 #endif
12076
12077 #if defined(HAVE_PRI)
12078 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12079 {
12080 struct dahdi_spaninfo si;
12081 struct dahdi_params p;
12082 int fd;
12083 int span;
12084 int ospan=0;
12085 int x,y;
12086 for (x = 0; x < NUM_SPANS; x++) {
12087 if (pris[x].pri.trunkgroup == trunkgroup) {
12088 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12089 return -1;
12090 }
12091 }
12092 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12093 if (!channels[y])
12094 break;
12095 memset(&si, 0, sizeof(si));
12096 memset(&p, 0, sizeof(p));
12097 fd = open("/dev/dahdi/channel", O_RDWR);
12098 if (fd < 0) {
12099 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12100 return -1;
12101 }
12102 x = channels[y];
12103 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12104 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12105 close(fd);
12106 return -1;
12107 }
12108 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12109 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12110 return -1;
12111 }
12112 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12113 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12114 close(fd);
12115 return -1;
12116 }
12117 span = p.spanno - 1;
12118 if (pris[span].pri.trunkgroup) {
12119 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12120 close(fd);
12121 return -1;
12122 }
12123 if (pris[span].pri.pvts[0]) {
12124 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12125 close(fd);
12126 return -1;
12127 }
12128 if (!y) {
12129 pris[span].pri.trunkgroup = trunkgroup;
12130 ospan = span;
12131 }
12132 pris[ospan].dchannels[y] = channels[y];
12133 pris[span].pri.span = span + 1;
12134 close(fd);
12135 }
12136 return 0;
12137 }
12138 #endif
12139
12140 #if defined(HAVE_PRI)
12141 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12142 {
12143 if (pris[span].mastertrunkgroup) {
12144 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);
12145 return -1;
12146 }
12147 pris[span].mastertrunkgroup = trunkgroup;
12148 pris[span].prilogicalspan = logicalspan;
12149 return 0;
12150 }
12151 #endif
12152
12153 #if defined(HAVE_SS7)
12154 static unsigned int parse_pointcode(const char *pcstring)
12155 {
12156 unsigned int code1, code2, code3;
12157 int numvals;
12158
12159 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12160 if (numvals == 1)
12161 return code1;
12162 if (numvals == 3)
12163 return (code1 << 16) | (code2 << 8) | code3;
12164
12165 return 0;
12166 }
12167 #endif
12168
12169 #if defined(HAVE_SS7)
12170 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12171 {
12172 if ((linkset < 0) || (linkset >= NUM_SPANS))
12173 return NULL;
12174 else
12175 return &linksets[linkset - 1];
12176 }
12177 #endif
12178
12179 #ifdef HAVE_OPENR2
12180 static void dahdi_r2_destroy_links(void)
12181 {
12182 int i = 0;
12183 if (!r2links) {
12184 return;
12185 }
12186 for (; i < r2links_count; i++) {
12187 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12188 pthread_cancel(r2links[i]->r2master);
12189 pthread_join(r2links[i]->r2master, NULL);
12190 openr2_context_delete(r2links[i]->protocol_context);
12191 }
12192 ast_free(r2links[i]);
12193 }
12194 ast_free(r2links);
12195 r2links = NULL;
12196 r2links_count = 0;
12197 }
12198
12199
12200 #define R2_LINK_CAPACITY 30
12201 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12202 {
12203 struct dahdi_mfcr2 *new_r2link = NULL;
12204 struct dahdi_mfcr2 **new_r2links = NULL;
12205
12206
12207
12208
12209
12210 if (!r2links_count ||
12211 memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12212 (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12213 new_r2link = ast_calloc(1, sizeof(**r2links));
12214 if (!new_r2link) {
12215 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12216 return NULL;
12217 }
12218 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12219 if (!new_r2links) {
12220 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12221 ast_free(new_r2link);
12222 return NULL;
12223 }
12224 r2links = new_r2links;
12225 new_r2link->r2master = AST_PTHREADT_NULL;
12226 r2links[r2links_count] = new_r2link;
12227 r2links_count++;
12228 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12229 }
12230 return r2links[r2links_count - 1];
12231 }
12232
12233 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12234 {
12235 char tmplogdir[] = "/tmp";
12236 char logdir[OR2_MAX_PATH];
12237 int threshold = 0;
12238 int snres = 0;
12239 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12240 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12241 conf->mfcr2.max_dnis);
12242 if (!r2_link->protocol_context) {
12243 return -1;
12244 }
12245 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12246 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12247 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12248 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12249 #endif
12250 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12251 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12252 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12253 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12254 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12255 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12256 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12257 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12258 }
12259 } else {
12260 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12261 if (snres >= sizeof(logdir)) {
12262 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12263 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12264 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12265 }
12266 } else {
12267 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12268 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12269 }
12270 }
12271 }
12272 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12273 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12274 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12275 }
12276 }
12277
12278 memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12279 return 0;
12280 }
12281 #endif
12282
12283
12284
12285
12286
12287
12288 static int sigtype_to_signalling(int sigtype)
12289 {
12290 return sigtype;
12291 }
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12306 {
12307 struct stat stbuf;
12308 int num;
12309
12310 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12311 if (stat(path, &stbuf) < 0) {
12312 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12313 return -errno;
12314 }
12315 if (!S_ISCHR(stbuf.st_mode)) {
12316 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12317 return -EINVAL;
12318 }
12319 num = minor(stbuf.st_rdev);
12320 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12321 return num;
12322
12323 }
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333
12334
12335
12336
12337
12338
12339 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12340 {
12341
12342 struct dahdi_pvt *tmp;
12343 char fn[80];
12344 struct dahdi_bufferinfo bi;
12345
12346 int res;
12347 #if defined(HAVE_PRI)
12348 int span = 0;
12349 #endif
12350 int here = 0;
12351 int x;
12352 struct analog_pvt *analog_p = NULL;
12353 struct dahdi_params p;
12354 #if defined(HAVE_PRI)
12355 struct dahdi_spaninfo si;
12356 struct sig_pri_chan *pri_chan = NULL;
12357 #endif
12358 #if defined(HAVE_SS7)
12359 struct sig_ss7_chan *ss7_chan = NULL;
12360 #endif
12361
12362
12363 for (tmp = iflist; tmp; tmp = tmp->next) {
12364 if (!tmp->destroy) {
12365 if (tmp->channel == channel) {
12366
12367 here = 1;
12368 break;
12369 }
12370 if (tmp->channel > channel) {
12371
12372 tmp = NULL;
12373 break;
12374 }
12375 }
12376 }
12377
12378 if (!here && reloading != 1) {
12379 tmp = ast_calloc(1, sizeof(*tmp));
12380 if (!tmp) {
12381 return NULL;
12382 }
12383 tmp->cc_params = ast_cc_config_params_init();
12384 if (!tmp->cc_params) {
12385 ast_free(tmp);
12386 return NULL;
12387 }
12388 ast_mutex_init(&tmp->lock);
12389 ifcount++;
12390 for (x = 0; x < 3; x++)
12391 tmp->subs[x].dfd = -1;
12392 tmp->channel = channel;
12393 tmp->priindication_oob = conf->chan.priindication_oob;
12394 }
12395
12396 if (tmp) {
12397 int chan_sig = conf->chan.sig;
12398
12399
12400 if (reloading && tmp->vars) {
12401 ast_variables_destroy(tmp->vars);
12402 tmp->vars = NULL;
12403 }
12404
12405
12406 if (!here) {
12407
12408 if ((channel != CHAN_PSEUDO)) {
12409 int count = 0;
12410
12411 snprintf(fn, sizeof(fn), "%d", channel);
12412
12413 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12414 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12415 usleep(1);
12416 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12417 count++;
12418 }
12419
12420 if (tmp->subs[SUB_REAL].dfd < 0) {
12421 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);
12422 destroy_dahdi_pvt(tmp);
12423 return NULL;
12424 }
12425 memset(&p, 0, sizeof(p));
12426 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12427 if (res < 0) {
12428 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12429 destroy_dahdi_pvt(tmp);
12430 return NULL;
12431 }
12432 if (conf->is_sig_auto)
12433 chan_sig = sigtype_to_signalling(p.sigtype);
12434 if (p.sigtype != (chan_sig & 0x3ffff)) {
12435 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));
12436 destroy_dahdi_pvt(tmp);
12437 return NULL;
12438 }
12439 tmp->law_default = p.curlaw;
12440 tmp->law = p.curlaw;
12441 tmp->span = p.spanno;
12442 #if defined(HAVE_PRI)
12443 span = p.spanno - 1;
12444 #endif
12445 } else {
12446 chan_sig = 0;
12447 }
12448 tmp->sig = chan_sig;
12449 tmp->outsigmod = conf->chan.outsigmod;
12450
12451 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12452 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12453 if (!analog_p) {
12454 destroy_dahdi_pvt(tmp);
12455 return NULL;
12456 }
12457 tmp->sig_pvt = analog_p;
12458 }
12459 #if defined(HAVE_SS7)
12460 if (chan_sig == SIG_SS7) {
12461 struct dahdi_ss7 *ss7;
12462 int clear = 0;
12463
12464 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12465 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12466 destroy_dahdi_pvt(tmp);
12467 return NULL;
12468 }
12469
12470 ss7 = ss7_resolve_linkset(cur_linkset);
12471 if (!ss7) {
12472 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12473 destroy_dahdi_pvt(tmp);
12474 return NULL;
12475 }
12476 ss7->ss7.span = cur_linkset;
12477 if (cur_cicbeginswith < 0) {
12478 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12479 destroy_dahdi_pvt(tmp);
12480 return NULL;
12481 }
12482 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12483 if (!ss7_chan) {
12484 destroy_dahdi_pvt(tmp);
12485 return NULL;
12486 }
12487 tmp->sig_pvt = ss7_chan;
12488 tmp->ss7 = &ss7->ss7;
12489
12490 ss7_chan->channel = tmp->channel;
12491 ss7_chan->cic = cur_cicbeginswith++;
12492
12493
12494 ss7_chan->dpc = cur_defaultdpc;
12495
12496 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12497
12498 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12499 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12500 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12501 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12502
12503 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12504 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12505 }
12506 #endif
12507 #ifdef HAVE_OPENR2
12508 if (chan_sig == SIG_MFCR2) {
12509 struct dahdi_mfcr2 *r2_link;
12510 r2_link = dahdi_r2_get_link(conf);
12511 if (!r2_link) {
12512 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12513 destroy_dahdi_pvt(tmp);
12514 return NULL;
12515 }
12516 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12517 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12518 destroy_dahdi_pvt(tmp);
12519 return NULL;
12520 }
12521 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12522 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12523 destroy_dahdi_pvt(tmp);
12524 return NULL;
12525 }
12526 r2_link->pvts[r2_link->numchans++] = tmp;
12527 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12528 tmp->subs[SUB_REAL].dfd,
12529 NULL, NULL);
12530 if (!tmp->r2chan) {
12531 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12532 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12533 destroy_dahdi_pvt(tmp);
12534 return NULL;
12535 }
12536 tmp->mfcr2 = r2_link;
12537 if (conf->mfcr2.call_files) {
12538 openr2_chan_enable_call_files(tmp->r2chan);
12539 }
12540 openr2_chan_set_client_data(tmp->r2chan, tmp);
12541
12542 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12543 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12544 tmp->mfcr2_category = conf->mfcr2.category;
12545 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12546 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12547 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12548 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12549 tmp->mfcr2call = 0;
12550 tmp->mfcr2_dnis_index = 0;
12551 tmp->mfcr2_ani_index = 0;
12552 }
12553 #endif
12554 #ifdef HAVE_PRI
12555 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12556 int offset;
12557 int matchesdchan;
12558 int x,y;
12559 int myswitchtype = 0;
12560
12561 offset = 0;
12562 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12563 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12564 destroy_dahdi_pvt(tmp);
12565 return NULL;
12566 }
12567 if (span >= NUM_SPANS) {
12568 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12569 destroy_dahdi_pvt(tmp);
12570 return NULL;
12571 } else {
12572 si.spanno = 0;
12573 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12574 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12575 destroy_dahdi_pvt(tmp);
12576 return NULL;
12577 }
12578
12579 tmp->logicalspan = pris[span].prilogicalspan;
12580 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12581 if (span < 0) {
12582 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12583 destroy_dahdi_pvt(tmp);
12584 return NULL;
12585 }
12586 myswitchtype = conf->pri.pri.switchtype;
12587
12588 matchesdchan=0;
12589 for (x = 0; x < NUM_SPANS; x++) {
12590 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12591 if (pris[x].dchannels[y] == tmp->channel) {
12592 matchesdchan = 1;
12593 break;
12594 }
12595 }
12596 }
12597 if (!matchesdchan) {
12598 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12599 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12600 destroy_dahdi_pvt(tmp);
12601 return NULL;
12602 }
12603 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12604 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12605 destroy_dahdi_pvt(tmp);
12606 return NULL;
12607 }
12608 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12609 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));
12610 destroy_dahdi_pvt(tmp);
12611 return NULL;
12612 }
12613 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12614 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12615 destroy_dahdi_pvt(tmp);
12616 return NULL;
12617 }
12618 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12619 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12620 destroy_dahdi_pvt(tmp);
12621 return NULL;
12622 }
12623 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12624 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12625 destroy_dahdi_pvt(tmp);
12626 return NULL;
12627 }
12628 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12629 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12630 destroy_dahdi_pvt(tmp);
12631 return NULL;
12632 }
12633 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12634 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12635 pris[span].pri.trunkgroup);
12636 destroy_dahdi_pvt(tmp);
12637 return NULL;
12638 }
12639
12640 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12641 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12642 if (!pri_chan) {
12643 destroy_dahdi_pvt(tmp);
12644 return NULL;
12645 }
12646 tmp->sig_pvt = pri_chan;
12647 tmp->pri = &pris[span].pri;
12648
12649 tmp->priexclusive = conf->chan.priexclusive;
12650
12651 if (!tmp->pri->cc_params) {
12652 tmp->pri->cc_params = ast_cc_config_params_init();
12653 if (!tmp->pri->cc_params) {
12654 destroy_dahdi_pvt(tmp);
12655 return NULL;
12656 }
12657 }
12658 ast_cc_copy_config_params(tmp->pri->cc_params,
12659 conf->chan.cc_params);
12660
12661 pris[span].pri.sig = chan_sig;
12662 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12663 pris[span].pri.switchtype = myswitchtype;
12664 pris[span].pri.nsf = conf->pri.pri.nsf;
12665 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12666 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12667 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12668 pris[span].pri.minunused = conf->pri.pri.minunused;
12669 pris[span].pri.minidle = conf->pri.pri.minidle;
12670 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12671 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12672 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12673 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12674 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12675 #endif
12676 #ifdef HAVE_PRI_INBANDDISCONNECT
12677 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12678 #endif
12679 #if defined(HAVE_PRI_CALL_HOLD)
12680 pris[span].pri.hold_disconnect_transfer =
12681 conf->pri.pri.hold_disconnect_transfer;
12682 #endif
12683 #if defined(HAVE_PRI_CCSS)
12684 pris[span].pri.cc_ptmp_recall_mode =
12685 conf->pri.pri.cc_ptmp_recall_mode;
12686 pris[span].pri.cc_qsig_signaling_link_req =
12687 conf->pri.pri.cc_qsig_signaling_link_req;
12688 pris[span].pri.cc_qsig_signaling_link_rsp =
12689 conf->pri.pri.cc_qsig_signaling_link_rsp;
12690 #endif
12691 #if defined(HAVE_PRI_CALL_WAITING)
12692 pris[span].pri.max_call_waiting_calls =
12693 conf->pri.pri.max_call_waiting_calls;
12694 pris[span].pri.allow_call_waiting_calls =
12695 conf->pri.pri.allow_call_waiting_calls;
12696 #endif
12697 pris[span].pri.transfer = conf->chan.transfer;
12698 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12699 #if defined(HAVE_PRI_L2_PERSISTENCE)
12700 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12701 #endif
12702 #if defined(HAVE_PRI_AOC_EVENTS)
12703 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12704 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12705 #endif
12706 if (chan_sig == SIG_BRI_PTMP) {
12707 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12708 } else {
12709
12710 pris[span].pri.layer1_ignored = 0;
12711 }
12712 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12713 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12714 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12715 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12716 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12717 #if defined(HAVE_PRI_MWI)
12718 ast_copy_string(pris[span].pri.mwi_mailboxes,
12719 conf->pri.pri.mwi_mailboxes,
12720 sizeof(pris[span].pri.mwi_mailboxes));
12721 #endif
12722 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12723 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12724 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12725 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12726 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12727 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12728 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12729 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12730
12731 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12732 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12733 }
12734
12735 #if defined(HAVE_PRI_CALL_WAITING)
12736
12737 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12738 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12739 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12740 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12741 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12742 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12743 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12744 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12745 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12746 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12747 #endif
12748 } else {
12749 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12750 destroy_dahdi_pvt(tmp);
12751 return NULL;
12752 }
12753 }
12754 }
12755 #endif
12756 } else {
12757
12758 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));
12759 chan_sig = tmp->sig;
12760 if (tmp->subs[SUB_REAL].dfd > -1) {
12761 memset(&p, 0, sizeof(p));
12762 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12763 }
12764 }
12765
12766 switch (chan_sig) {
12767 case SIG_FXSKS:
12768 case SIG_FXSLS:
12769 case SIG_EM:
12770 case SIG_EM_E1:
12771 case SIG_EMWINK:
12772 case SIG_FEATD:
12773 case SIG_FEATDMF:
12774 case SIG_FEATDMF_TA:
12775 case SIG_FEATB:
12776 case SIG_E911:
12777 case SIG_SF:
12778 case SIG_SFWINK:
12779 case SIG_FGC_CAMA:
12780 case SIG_FGC_CAMAMF:
12781 case SIG_SF_FEATD:
12782 case SIG_SF_FEATDMF:
12783 case SIG_SF_FEATB:
12784 p.starttime = 250;
12785 break;
12786 }
12787
12788 if (tmp->radio) {
12789
12790 p.channo = channel;
12791 p.rxwinktime = 1;
12792 p.rxflashtime = 1;
12793 p.starttime = 1;
12794 p.debouncetime = 5;
12795 } else {
12796 p.channo = channel;
12797
12798 if (conf->timing.prewinktime >= 0)
12799 p.prewinktime = conf->timing.prewinktime;
12800 if (conf->timing.preflashtime >= 0)
12801 p.preflashtime = conf->timing.preflashtime;
12802 if (conf->timing.winktime >= 0)
12803 p.winktime = conf->timing.winktime;
12804 if (conf->timing.flashtime >= 0)
12805 p.flashtime = conf->timing.flashtime;
12806 if (conf->timing.starttime >= 0)
12807 p.starttime = conf->timing.starttime;
12808 if (conf->timing.rxwinktime >= 0)
12809 p.rxwinktime = conf->timing.rxwinktime;
12810 if (conf->timing.rxflashtime >= 0)
12811 p.rxflashtime = conf->timing.rxflashtime;
12812 if (conf->timing.debouncetime >= 0)
12813 p.debouncetime = conf->timing.debouncetime;
12814 }
12815
12816
12817 if (tmp->subs[SUB_REAL].dfd >= 0)
12818 {
12819 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12820 if (res < 0) {
12821 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12822 destroy_dahdi_pvt(tmp);
12823 return NULL;
12824 }
12825 }
12826 #if 1
12827 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12828 memset(&bi, 0, sizeof(bi));
12829 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12830 if (!res) {
12831 bi.txbufpolicy = conf->chan.buf_policy;
12832 bi.rxbufpolicy = conf->chan.buf_policy;
12833 bi.numbufs = conf->chan.buf_no;
12834 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12835 if (res < 0) {
12836 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12837 }
12838 } else {
12839 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12840 }
12841 tmp->buf_policy = conf->chan.buf_policy;
12842 tmp->buf_no = conf->chan.buf_no;
12843 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12844 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12845 tmp->faxbuf_no = conf->chan.faxbuf_no;
12846
12847
12848
12849
12850 tmp->bufsize = bi.bufsize;
12851 }
12852 #endif
12853 tmp->immediate = conf->chan.immediate;
12854 tmp->transfertobusy = conf->chan.transfertobusy;
12855 if (chan_sig & __DAHDI_SIG_FXS) {
12856 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12857 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12858 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12859 }
12860 tmp->ringt_base = ringt_base;
12861 tmp->firstradio = 0;
12862 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12863 tmp->permcallwaiting = conf->chan.callwaiting;
12864 else
12865 tmp->permcallwaiting = 0;
12866
12867 tmp->destroy = 0;
12868 tmp->drings = conf->chan.drings;
12869
12870
12871 if (tmp->drings.ringnum[0].range == 0)
12872 tmp->drings.ringnum[0].range = 10;
12873 if (tmp->drings.ringnum[1].range == 0)
12874 tmp->drings.ringnum[1].range = 10;
12875 if (tmp->drings.ringnum[2].range == 0)
12876 tmp->drings.ringnum[2].range = 10;
12877
12878 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12879 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12880 tmp->threewaycalling = conf->chan.threewaycalling;
12881 tmp->adsi = conf->chan.adsi;
12882 tmp->use_smdi = conf->chan.use_smdi;
12883 tmp->permhidecallerid = conf->chan.hidecallerid;
12884 tmp->hidecalleridname = conf->chan.hidecalleridname;
12885 tmp->callreturn = conf->chan.callreturn;
12886 tmp->echocancel = conf->chan.echocancel;
12887 tmp->echotraining = conf->chan.echotraining;
12888 tmp->pulse = conf->chan.pulse;
12889 if (tmp->echocancel.head.tap_length) {
12890 tmp->echocanbridged = conf->chan.echocanbridged;
12891 } else {
12892 if (conf->chan.echocanbridged)
12893 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12894 tmp->echocanbridged = 0;
12895 }
12896 tmp->busydetect = conf->chan.busydetect;
12897 tmp->busycount = conf->chan.busycount;
12898 tmp->busy_tonelength = conf->chan.busy_tonelength;
12899 tmp->busy_quietlength = conf->chan.busy_quietlength;
12900 tmp->callprogress = conf->chan.callprogress;
12901 tmp->waitfordialtone = conf->chan.waitfordialtone;
12902 tmp->cancallforward = conf->chan.cancallforward;
12903 tmp->dtmfrelax = conf->chan.dtmfrelax;
12904 tmp->callwaiting = tmp->permcallwaiting;
12905 tmp->hidecallerid = tmp->permhidecallerid;
12906 tmp->channel = channel;
12907 tmp->stripmsd = conf->chan.stripmsd;
12908 tmp->use_callerid = conf->chan.use_callerid;
12909 tmp->cid_signalling = conf->chan.cid_signalling;
12910 tmp->cid_start = conf->chan.cid_start;
12911 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12912 tmp->restrictcid = conf->chan.restrictcid;
12913 tmp->use_callingpres = conf->chan.use_callingpres;
12914 if (tmp->usedistinctiveringdetection) {
12915 if (!tmp->use_callerid) {
12916 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12917 tmp->use_callerid = 1;
12918 }
12919 }
12920
12921 if (tmp->cid_signalling == CID_SIG_SMDI) {
12922 if (!tmp->use_smdi) {
12923 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12924 tmp->use_smdi = 1;
12925 }
12926 }
12927 if (tmp->use_smdi) {
12928 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12929 if (!(tmp->smdi_iface)) {
12930 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12931 tmp->use_smdi = 0;
12932 }
12933 }
12934
12935 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12936 tmp->amaflags = conf->chan.amaflags;
12937 if (!here) {
12938 tmp->confno = -1;
12939 tmp->propconfno = -1;
12940 }
12941 tmp->canpark = conf->chan.canpark;
12942 tmp->transfer = conf->chan.transfer;
12943 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12944 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12945 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12946 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12947 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12948 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12949 tmp->cid_ton = 0;
12950 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12951 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12952 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12953 } else {
12954 tmp->cid_num[0] = '\0';
12955 tmp->cid_name[0] = '\0';
12956 }
12957 #if defined(HAVE_PRI)
12958 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12959 tmp->cid_tag[0] = '\0';
12960 } else
12961 #endif
12962 {
12963 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12964 }
12965 tmp->cid_subaddr[0] = '\0';
12966 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12967 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12968 char *mailbox, *context;
12969 mailbox = context = ast_strdupa(tmp->mailbox);
12970 strsep(&context, "@");
12971 if (ast_strlen_zero(context))
12972 context = "default";
12973 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12974 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12975 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12976 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12977 AST_EVENT_IE_END);
12978 }
12979 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12980 tmp->mwisend_setting = conf->chan.mwisend_setting;
12981 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12982 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12983 #endif
12984
12985 tmp->group = conf->chan.group;
12986 tmp->callgroup = conf->chan.callgroup;
12987 tmp->pickupgroup= conf->chan.pickupgroup;
12988 if (conf->chan.vars) {
12989 struct ast_variable *v, *tmpvar;
12990 for (v = conf->chan.vars ; v ; v = v->next) {
12991 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12992 tmpvar->next = tmp->vars;
12993 tmp->vars = tmpvar;
12994 }
12995 }
12996 }
12997 tmp->cid_rxgain = conf->chan.cid_rxgain;
12998 tmp->rxgain = conf->chan.rxgain;
12999 tmp->txgain = conf->chan.txgain;
13000 tmp->txdrc = conf->chan.txdrc;
13001 tmp->rxdrc = conf->chan.rxdrc;
13002 tmp->tonezone = conf->chan.tonezone;
13003 if (tmp->subs[SUB_REAL].dfd > -1) {
13004 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13005 if (tmp->dsp)
13006 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13007 update_conf(tmp);
13008 if (!here) {
13009 switch (chan_sig) {
13010 case SIG_PRI_LIB_HANDLE_CASES:
13011 case SIG_SS7:
13012 case SIG_MFCR2:
13013 break;
13014 default:
13015
13016 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13017 break;
13018 }
13019 }
13020 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13021 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13022
13023 switch (tmp->sig) {
13024 #ifdef HAVE_PRI
13025 case SIG_PRI_LIB_HANDLE_CASES:
13026 sig_pri_set_alarm(tmp->sig_pvt, 1);
13027 break;
13028 #endif
13029 #if defined(HAVE_SS7)
13030 case SIG_SS7:
13031 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13032 break;
13033 #endif
13034 default:
13035
13036 analog_p = tmp->sig_pvt;
13037 if (analog_p) {
13038 analog_p->inalarm = 1;
13039 }
13040 tmp->inalarm = 1;
13041 break;
13042 }
13043 handle_alarms(tmp, res);
13044 }
13045 }
13046
13047 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13048 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13049 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13050 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13051 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13052
13053 if (!here) {
13054 tmp->locallyblocked = 0;
13055 tmp->remotelyblocked = 0;
13056 switch (tmp->sig) {
13057 #if defined(HAVE_PRI)
13058 case SIG_PRI_LIB_HANDLE_CASES:
13059 tmp->inservice = 1;
13060 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13061 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13062 if (chan_sig == SIG_PRI) {
13063 char db_chan_name[20];
13064 char db_answer[5];
13065
13066
13067
13068
13069
13070 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13071 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13072 unsigned *why;
13073
13074 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13075 if (tmp->pri->enable_service_message_support) {
13076 char state;
13077
13078 sscanf(db_answer, "%1c:%30u", &state, why);
13079
13080
13081 *why &= (SRVST_NEAREND | SRVST_FAREND);
13082 }
13083 if (!*why) {
13084 ast_db_del(db_chan_name, SRVST_DBKEY);
13085 }
13086 }
13087 }
13088 #endif
13089 break;
13090 #endif
13091 #if defined(HAVE_SS7)
13092 case SIG_SS7:
13093 tmp->inservice = 0;
13094 break;
13095 #endif
13096 default:
13097
13098 tmp->inservice = 1;
13099 break;
13100 }
13101 }
13102
13103 switch (tmp->sig) {
13104 #if defined(HAVE_PRI)
13105 case SIG_PRI_LIB_HANDLE_CASES:
13106 if (pri_chan) {
13107 pri_chan->channel = tmp->channel;
13108 pri_chan->hidecallerid = tmp->hidecallerid;
13109 pri_chan->hidecalleridname = tmp->hidecalleridname;
13110 pri_chan->immediate = tmp->immediate;
13111 pri_chan->inalarm = tmp->inalarm;
13112 pri_chan->priexclusive = tmp->priexclusive;
13113 pri_chan->priindication_oob = tmp->priindication_oob;
13114 pri_chan->use_callerid = tmp->use_callerid;
13115 pri_chan->use_callingpres = tmp->use_callingpres;
13116 ast_copy_string(pri_chan->context, tmp->context,
13117 sizeof(pri_chan->context));
13118 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13119 sizeof(pri_chan->mohinterpret));
13120 pri_chan->stripmsd = tmp->stripmsd;
13121 }
13122 break;
13123 #endif
13124 #if defined(HAVE_SS7)
13125 case SIG_SS7:
13126 if (ss7_chan) {
13127 ss7_chan->inalarm = tmp->inalarm;
13128
13129 ss7_chan->stripmsd = tmp->stripmsd;
13130 ss7_chan->hidecallerid = tmp->hidecallerid;
13131 ss7_chan->use_callerid = tmp->use_callerid;
13132 ss7_chan->use_callingpres = tmp->use_callingpres;
13133 ss7_chan->immediate = tmp->immediate;
13134 ss7_chan->locallyblocked = tmp->locallyblocked;
13135 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13136 ast_copy_string(ss7_chan->context, tmp->context,
13137 sizeof(ss7_chan->context));
13138 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13139 sizeof(ss7_chan->mohinterpret));
13140 }
13141 break;
13142 #endif
13143 default:
13144
13145 analog_p = tmp->sig_pvt;
13146 if (analog_p) {
13147 analog_p->channel = tmp->channel;
13148 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13149 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13150 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13151 analog_p->permcallwaiting = conf->chan.callwaiting;
13152 analog_p->callreturn = conf->chan.callreturn;
13153 analog_p->cancallforward = conf->chan.cancallforward;
13154 analog_p->canpark = conf->chan.canpark;
13155 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13156 analog_p->immediate = conf->chan.immediate;
13157 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13158 analog_p->pulse = conf->chan.pulse;
13159 analog_p->threewaycalling = conf->chan.threewaycalling;
13160 analog_p->transfer = conf->chan.transfer;
13161 analog_p->transfertobusy = conf->chan.transfertobusy;
13162 analog_p->use_callerid = tmp->use_callerid;
13163 analog_p->use_smdi = tmp->use_smdi;
13164 analog_p->smdi_iface = tmp->smdi_iface;
13165 analog_p->outsigmod = ANALOG_SIG_NONE;
13166 analog_p->echotraining = conf->chan.echotraining;
13167 analog_p->cid_signalling = conf->chan.cid_signalling;
13168 analog_p->stripmsd = conf->chan.stripmsd;
13169 switch (conf->chan.cid_start) {
13170 case CID_START_POLARITY:
13171 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13172 break;
13173 case CID_START_POLARITY_IN:
13174 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13175 break;
13176 case CID_START_DTMF_NOALERT:
13177 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13178 break;
13179 default:
13180 analog_p->cid_start = ANALOG_CID_START_RING;
13181 break;
13182 }
13183 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13184 analog_p->ringt = conf->chan.ringt;
13185 analog_p->ringt_base = ringt_base;
13186 analog_p->onhooktime = time(NULL);
13187 if (chan_sig & __DAHDI_SIG_FXO) {
13188 memset(&p, 0, sizeof(p));
13189 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13190 if (!res) {
13191 analog_p->fxsoffhookstate = p.rxisoffhook;
13192 }
13193 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13194 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13195 #endif
13196 }
13197 analog_p->msgstate = -1;
13198
13199 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13200 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13201 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13202
13203 analog_config_complete(analog_p);
13204 }
13205 break;
13206 }
13207 #if defined(HAVE_PRI)
13208 if (tmp->channel == CHAN_PSEUDO) {
13209
13210
13211
13212
13213 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13214 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13215 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13216 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13217 }
13218 #endif
13219 }
13220 if (tmp && !here) {
13221
13222 dahdi_iflist_insert(tmp);
13223 }
13224 return tmp;
13225 }
13226
13227 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13228 {
13229 #if defined(HAVE_PRI)
13230 if (0 < span) {
13231
13232 if (!p->pri || p->pri->span != span) {
13233 return 0;
13234 }
13235 if (!groupmatch && channelmatch == -1) {
13236
13237 *groupmatched = 1;
13238 return 1;
13239 }
13240 }
13241 #endif
13242
13243 if (groupmatch) {
13244 if ((p->group & groupmatch) != groupmatch)
13245
13246 return 0;
13247 *groupmatched = 1;
13248 }
13249
13250 if (channelmatch != -1) {
13251 if (p->channel != channelmatch)
13252
13253 return 0;
13254 *channelmatched = 1;
13255 }
13256
13257 return 1;
13258 }
13259
13260 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13261 {
13262 struct dahdi_pvt *p = *pvt;
13263
13264 if (p->inalarm)
13265 return 0;
13266
13267 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13268 return analog_available(p->sig_pvt);
13269
13270 switch (p->sig) {
13271 #if defined(HAVE_PRI)
13272 case SIG_PRI_LIB_HANDLE_CASES:
13273 {
13274 struct sig_pri_chan *pvt_chan;
13275 int res;
13276
13277 pvt_chan = p->sig_pvt;
13278 res = sig_pri_available(&pvt_chan, is_specific_channel);
13279 *pvt = pvt_chan->chan_pvt;
13280 return res;
13281 }
13282 #endif
13283 #if defined(HAVE_SS7)
13284 case SIG_SS7:
13285 return sig_ss7_available(p->sig_pvt);
13286 #endif
13287 default:
13288 break;
13289 }
13290
13291 if (p->locallyblocked || p->remotelyblocked) {
13292 return 0;
13293 }
13294
13295
13296 if (!p->owner) {
13297 #ifdef HAVE_OPENR2
13298
13299 if (p->mfcr2) {
13300 if (p->mfcr2call) {
13301 return 0;
13302 } else {
13303 return 1;
13304 }
13305 }
13306 #endif
13307 return 1;
13308 }
13309
13310 return 0;
13311 }
13312
13313 #if defined(HAVE_PRI)
13314 #if defined(HAVE_PRI_CALL_WAITING)
13315
13316
13317
13318
13319
13320
13321
13322
13323
13324
13325
13326
13327 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13328 {
13329 struct dahdi_pvt *pvt = priv;
13330
13331 pvt->stripmsd = pri->ch_cfg.stripmsd;
13332 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13333 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13334 pvt->immediate = pri->ch_cfg.immediate;
13335 pvt->priexclusive = pri->ch_cfg.priexclusive;
13336 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13337 pvt->use_callerid = pri->ch_cfg.use_callerid;
13338 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13339 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13340 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13341 }
13342 #endif
13343 #endif
13344
13345 #if defined(HAVE_PRI)
13346
13347
13348
13349
13350
13351
13352
13353
13354
13355
13356
13357
13358 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13359 {
13360 int pvt_idx;
13361 int res;
13362 unsigned idx;
13363 struct dahdi_pvt *pvt;
13364 struct sig_pri_chan *chan;
13365 struct dahdi_bufferinfo bi;
13366
13367 static int nobch_channel = CHAN_PSEUDO;
13368
13369
13370 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13371 if (!pri->pvts[pvt_idx]) {
13372 break;
13373 }
13374 }
13375 if (pri->numchans == pvt_idx) {
13376 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13377 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13378 return -1;
13379 }
13380
13381
13382 pri->pvts[pvt_idx] = NULL;
13383 ++pri->numchans;
13384 }
13385
13386 pvt = ast_calloc(1, sizeof(*pvt));
13387 if (!pvt) {
13388 return -1;
13389 }
13390 pvt->cc_params = ast_cc_config_params_init();
13391 if (!pvt->cc_params) {
13392 ast_free(pvt);
13393 return -1;
13394 }
13395 ast_mutex_init(&pvt->lock);
13396 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13397 pvt->subs[idx].dfd = -1;
13398 }
13399 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13400 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13401 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13402 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13403
13404 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13405 if (!chan) {
13406 destroy_dahdi_pvt(pvt);
13407 return -1;
13408 }
13409 chan->no_b_channel = 1;
13410
13411
13412
13413
13414
13415
13416 pvt->law_default = DAHDI_LAW_ALAW;
13417
13418 pvt->sig = pri->sig;
13419 pvt->outsigmod = -1;
13420 pvt->pri = pri;
13421 pvt->sig_pvt = chan;
13422 pri->pvts[pvt_idx] = chan;
13423
13424 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13425 if (pvt->subs[SUB_REAL].dfd < 0) {
13426 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13427 strerror(errno));
13428 destroy_dahdi_pvt(pvt);
13429 return -1;
13430 }
13431 memset(&bi, 0, sizeof(bi));
13432 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13433 if (!res) {
13434 pvt->bufsize = bi.bufsize;
13435 bi.txbufpolicy = pvt->buf_policy;
13436 bi.rxbufpolicy = pvt->buf_policy;
13437 bi.numbufs = pvt->buf_no;
13438 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13439 if (res < 0) {
13440 ast_log(LOG_WARNING,
13441 "Unable to set buffer policy on no B channel interface: %s\n",
13442 strerror(errno));
13443 }
13444 } else
13445 ast_log(LOG_WARNING,
13446 "Unable to check buffer policy on no B channel interface: %s\n",
13447 strerror(errno));
13448
13449 --nobch_channel;
13450 if (CHAN_PSEUDO < nobch_channel) {
13451 nobch_channel = CHAN_PSEUDO - 1;
13452 }
13453 pvt->channel = nobch_channel;
13454 pvt->span = pri->span;
13455 chan->channel = pvt->channel;
13456
13457 dahdi_nobch_insert(pri, pvt);
13458
13459 return pvt_idx;
13460 }
13461 #endif
13462
13463
13464
13465
13466
13467
13468 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13469 {
13470 struct dahdi_pvt *p;
13471 struct dahdi_bufferinfo bi;
13472 int res;
13473
13474 p = ast_malloc(sizeof(*p));
13475 if (!p) {
13476 return NULL;
13477 }
13478 *p = *src;
13479
13480
13481 p->cc_params = ast_cc_config_params_init();
13482 if (!p->cc_params) {
13483 ast_free(p);
13484 return NULL;
13485 }
13486 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13487
13488 p->which_iflist = DAHDI_IFLIST_NONE;
13489 p->next = NULL;
13490 p->prev = NULL;
13491 ast_mutex_init(&p->lock);
13492 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13493 if (p->subs[SUB_REAL].dfd < 0) {
13494 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13495 destroy_dahdi_pvt(p);
13496 return NULL;
13497 }
13498 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13499 if (!res) {
13500 bi.txbufpolicy = src->buf_policy;
13501 bi.rxbufpolicy = src->buf_policy;
13502 bi.numbufs = src->buf_no;
13503 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13504 if (res < 0) {
13505 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13506 }
13507 } else
13508 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13509 p->destroy = 1;
13510 dahdi_iflist_insert(p);
13511 return p;
13512 }
13513
13514 struct dahdi_starting_point {
13515
13516 ast_group_t groupmatch;
13517
13518 int channelmatch;
13519
13520 int rr_starting_point;
13521
13522 int span;
13523
13524 int cadance;
13525
13526 char opt;
13527
13528 char backwards;
13529
13530 char roundrobin;
13531 };
13532 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13533 {
13534 char *dest;
13535 char *s;
13536 int x;
13537 int res = 0;
13538 struct dahdi_pvt *p;
13539 char *subdir = NULL;
13540 AST_DECLARE_APP_ARGS(args,
13541 AST_APP_ARG(group);
13542
13543
13544 AST_APP_ARG(other);
13545 );
13546
13547
13548
13549
13550
13551
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561
13562
13563
13564
13565
13566
13567
13568
13569
13570 if (data) {
13571 dest = ast_strdupa(data);
13572 } else {
13573 ast_log(LOG_WARNING, "Channel requested with no data\n");
13574 return NULL;
13575 }
13576 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13577 if (!args.argc || ast_strlen_zero(args.group)) {
13578 ast_log(LOG_WARNING, "No channel/group specified\n");
13579 return NULL;
13580 }
13581
13582
13583 memset(param, 0, sizeof(*param));
13584 param->channelmatch = -1;
13585
13586 if (strchr(args.group, '!') != NULL) {
13587 char *prev = args.group;
13588 while ((s = strchr(prev, '!')) != NULL) {
13589 *s++ = '/';
13590 prev = s;
13591 }
13592 *(prev - 1) = '\0';
13593 subdir = args.group;
13594 args.group = prev;
13595 } else if (args.group[0] == 'i') {
13596
13597 res = sscanf(args.group + 1, "%30d", &x);
13598 if (res < 1) {
13599 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13600 return NULL;
13601 }
13602 param->span = x;
13603
13604
13605 s = strchr(args.group, '-');
13606 if (!s) {
13607
13608 return iflist;
13609 }
13610 args.group = s + 1;
13611 res = 0;
13612 }
13613 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13614
13615 s = args.group + 1;
13616 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13617 if (res < 1) {
13618 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13619 return NULL;
13620 }
13621 param->groupmatch = ((ast_group_t) 1 << x);
13622
13623 if (toupper(args.group[0]) == 'G') {
13624 if (args.group[0] == 'G') {
13625 param->backwards = 1;
13626 p = ifend;
13627 } else
13628 p = iflist;
13629 } else {
13630 if (ARRAY_LEN(round_robin) <= x) {
13631 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13632 x, data);
13633 return NULL;
13634 }
13635 if (args.group[0] == 'R') {
13636 param->backwards = 1;
13637 p = round_robin[x] ? round_robin[x]->prev : ifend;
13638 if (!p)
13639 p = ifend;
13640 } else {
13641 p = round_robin[x] ? round_robin[x]->next : iflist;
13642 if (!p)
13643 p = iflist;
13644 }
13645 param->roundrobin = 1;
13646 param->rr_starting_point = x;
13647 }
13648 } else {
13649 s = args.group;
13650 if (!strcasecmp(s, "pseudo")) {
13651
13652 x = CHAN_PSEUDO;
13653 param->channelmatch = x;
13654 } else {
13655 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13656 if (res < 1) {
13657 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13658 return NULL;
13659 } else {
13660 param->channelmatch = x;
13661 }
13662 }
13663 if (subdir) {
13664 char path[PATH_MAX];
13665 struct stat stbuf;
13666
13667 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13668 subdir, param->channelmatch);
13669 if (stat(path, &stbuf) < 0) {
13670 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13671 path, strerror(errno));
13672 return NULL;
13673 }
13674 if (!S_ISCHR(stbuf.st_mode)) {
13675 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13676 path);
13677 return NULL;
13678 }
13679 param->channelmatch = minor(stbuf.st_rdev);
13680 }
13681
13682 p = iflist;
13683 }
13684
13685 if (param->opt == 'r' && res < 3) {
13686 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13687 param->opt = '\0';
13688 }
13689
13690 return p;
13691 }
13692
13693 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13694 {
13695 int callwait = 0;
13696 struct dahdi_pvt *p;
13697 struct ast_channel *tmp = NULL;
13698 struct dahdi_pvt *exitpvt;
13699 int channelmatched = 0;
13700 int groupmatched = 0;
13701 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13702 int transcapdigital = 0;
13703 #endif
13704 struct dahdi_starting_point start;
13705
13706 ast_mutex_lock(&iflock);
13707 p = determine_starting_point(data, &start);
13708 if (!p) {
13709
13710 ast_mutex_unlock(&iflock);
13711 return NULL;
13712 }
13713
13714
13715 exitpvt = p;
13716 while (p && !tmp) {
13717 if (start.roundrobin)
13718 round_robin[start.rr_starting_point] = p;
13719
13720 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13721 && available(&p, channelmatched)) {
13722 ast_debug(1, "Using channel %d\n", p->channel);
13723
13724 callwait = (p->owner != NULL);
13725 #ifdef HAVE_OPENR2
13726 if (p->mfcr2) {
13727 ast_mutex_lock(&p->lock);
13728 if (p->mfcr2call) {
13729 ast_mutex_unlock(&p->lock);
13730 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13731 goto next;
13732 }
13733 p->mfcr2call = 1;
13734 ast_mutex_unlock(&p->lock);
13735 }
13736 #endif
13737 if (p->channel == CHAN_PSEUDO) {
13738 p = duplicate_pseudo(p);
13739 if (!p) {
13740 break;
13741 }
13742 }
13743
13744 p->distinctivering = 0;
13745
13746 switch (start.opt) {
13747 case '\0':
13748
13749 break;
13750 case 'c':
13751
13752 p->confirmanswer = 1;
13753 break;
13754 case 'r':
13755
13756 p->distinctivering = start.cadance;
13757 break;
13758 case 'd':
13759 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13760
13761 transcapdigital = AST_TRANS_CAP_DIGITAL;
13762 #endif
13763 break;
13764 default:
13765 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13766 break;
13767 }
13768
13769 p->outgoing = 1;
13770 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13771 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13772 #ifdef HAVE_PRI
13773 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13774
13775
13776
13777
13778
13779 ast_mutex_lock(&p->lock);
13780 ast_mutex_unlock(&p->lock);
13781
13782 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13783 sizeof(p->dnid));
13784 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13785 #endif
13786 #if defined(HAVE_SS7)
13787 } else if (p->sig == SIG_SS7) {
13788 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13789 #endif
13790 } else {
13791 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13792 }
13793 if (!tmp) {
13794 p->outgoing = 0;
13795 #if defined(HAVE_PRI)
13796 switch (p->sig) {
13797 case SIG_PRI_LIB_HANDLE_CASES:
13798 #if defined(HAVE_PRI_CALL_WAITING)
13799 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13800 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13801 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13802 }
13803 #endif
13804
13805
13806
13807
13808 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13809 break;
13810 default:
13811 break;
13812 }
13813 #endif
13814 } else {
13815 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13816 }
13817 break;
13818 }
13819 #ifdef HAVE_OPENR2
13820 next:
13821 #endif
13822 if (start.backwards) {
13823 p = p->prev;
13824 if (!p)
13825 p = ifend;
13826 } else {
13827 p = p->next;
13828 if (!p)
13829 p = iflist;
13830 }
13831
13832 if (p == exitpvt)
13833 break;
13834 }
13835 ast_mutex_unlock(&iflock);
13836 restart_monitor();
13837 if (cause && !tmp) {
13838 if (callwait || channelmatched) {
13839 *cause = AST_CAUSE_BUSY;
13840 } else if (groupmatched) {
13841 *cause = AST_CAUSE_CONGESTION;
13842 } else {
13843
13844
13845
13846
13847 }
13848 }
13849
13850 return tmp;
13851 }
13852
13853
13854
13855
13856
13857
13858
13859
13860
13861
13862
13863 static int dahdi_devicestate(void *data)
13864 {
13865 #if defined(HAVE_PRI)
13866 char *device;
13867 unsigned span;
13868 int res;
13869
13870 device = data;
13871
13872 if (*device != 'I') {
13873
13874 return AST_DEVICE_UNKNOWN;
13875 }
13876 res = sscanf(device, "I%30u", &span);
13877 if (res != 1 || !span || NUM_SPANS < span) {
13878
13879 return AST_DEVICE_UNKNOWN;
13880 }
13881 device = strchr(device, '/');
13882 if (!device) {
13883
13884 return AST_DEVICE_UNKNOWN;
13885 }
13886
13887
13888
13889
13890
13891 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13892 ++device;
13893 if (!strcmp(device, "congestion"))
13894 #endif
13895 {
13896 return pris[span - 1].pri.congestion_devstate;
13897 }
13898 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13899 else if (!strcmp(device, "threshold")) {
13900 return pris[span - 1].pri.threshold_devstate;
13901 }
13902 return AST_DEVICE_UNKNOWN;
13903 #endif
13904 #else
13905 return AST_DEVICE_UNKNOWN;
13906 #endif
13907 }
13908
13909
13910
13911
13912
13913
13914
13915
13916
13917
13918
13919
13920
13921
13922
13923
13924
13925 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13926 {
13927 struct dahdi_pvt *p;
13928 struct dahdi_pvt *exitpvt;
13929 struct dahdi_starting_point start;
13930 int groupmatched = 0;
13931 int channelmatched = 0;
13932
13933 ast_mutex_lock(&iflock);
13934 p = determine_starting_point(dest, &start);
13935 if (!p) {
13936 ast_mutex_unlock(&iflock);
13937 return -1;
13938 }
13939 exitpvt = p;
13940 for (;;) {
13941 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13942
13943 struct ast_str *device_name;
13944 char *dash;
13945 const char *monitor_type;
13946 char dialstring[AST_CHANNEL_NAME];
13947 char full_device_name[AST_CHANNEL_NAME];
13948
13949 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13950 case AST_CC_MONITOR_NEVER:
13951 break;
13952 case AST_CC_MONITOR_NATIVE:
13953 case AST_CC_MONITOR_ALWAYS:
13954 case AST_CC_MONITOR_GENERIC:
13955 #if defined(HAVE_PRI)
13956 if (dahdi_sig_pri_lib_handles(p->sig)) {
13957
13958
13959
13960
13961 snprintf(full_device_name, sizeof(full_device_name),
13962 "DAHDI/I%d/congestion", p->pri->span);
13963 } else
13964 #endif
13965 {
13966 #if defined(HAVE_PRI)
13967 device_name = create_channel_name(p, 1, "");
13968 #else
13969 device_name = create_channel_name(p);
13970 #endif
13971 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13972 device_name ? ast_str_buffer(device_name) : "");
13973 ast_free(device_name);
13974
13975
13976
13977
13978
13979 dash = strrchr(full_device_name, '-');
13980 if (dash) {
13981 *dash = '\0';
13982 }
13983 }
13984 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13985
13986
13987
13988
13989
13990
13991
13992 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13993 callback(inbound,
13994 #if defined(HAVE_PRI)
13995 p->pri ? p->pri->cc_params : p->cc_params,
13996 #else
13997 p->cc_params,
13998 #endif
13999 monitor_type, full_device_name, dialstring, NULL);
14000 break;
14001 }
14002 }
14003 p = start.backwards ? p->prev : p->next;
14004 if (!p) {
14005 p = start.backwards ? ifend : iflist;
14006 }
14007 if (p == exitpvt) {
14008 break;
14009 }
14010 }
14011 ast_mutex_unlock(&iflock);
14012 return 0;
14013 }
14014
14015 #if defined(HAVE_SS7)
14016 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14017 {
14018 int i;
14019
14020 if (ss7) {
14021 for (i = 0; i < NUM_SPANS; i++) {
14022 if (linksets[i].ss7.ss7 == ss7) {
14023 ast_verbose("[%d] %s", i + 1, s);
14024 return;
14025 }
14026 }
14027 }
14028 ast_verbose("%s", s);
14029 }
14030 #endif
14031
14032 #if defined(HAVE_SS7)
14033 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14034 {
14035 int i;
14036
14037 if (ss7) {
14038 for (i = 0; i < NUM_SPANS; i++) {
14039 if (linksets[i].ss7.ss7 == ss7) {
14040 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14041 return;
14042 }
14043 }
14044 }
14045 ast_log(LOG_ERROR, "%s", s);
14046 }
14047 #endif
14048
14049 #if defined(HAVE_OPENR2)
14050 static void *mfcr2_monitor(void *data)
14051 {
14052 struct dahdi_mfcr2 *mfcr2 = data;
14053
14054
14055
14056
14057
14058 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14059 int res = 0;
14060 int i = 0;
14061 int oldstate = 0;
14062 int quit_loop = 0;
14063 int maxsleep = 20;
14064 int was_idle = 0;
14065 int pollsize = 0;
14066
14067
14068 for (i = 0; i < mfcr2->numchans; i++) {
14069 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14070 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14071 }
14072 while (1) {
14073
14074
14075 pollsize = 0;
14076 for (i = 0; i < mfcr2->numchans; i++) {
14077 pollers[i].revents = 0;
14078 pollers[i].events = 0;
14079 if (mfcr2->pvts[i]->owner) {
14080 continue;
14081 }
14082 if (!mfcr2->pvts[i]->r2chan) {
14083 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14084 quit_loop = 1;
14085 break;
14086 }
14087 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14088 pollers[i].events = POLLIN | POLLPRI;
14089 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14090 pollsize++;
14091 }
14092 if (quit_loop) {
14093 break;
14094 }
14095 if (pollsize == 0) {
14096 if (!was_idle) {
14097 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14098 was_idle = 1;
14099 }
14100 poll(NULL, 0, maxsleep);
14101 continue;
14102 }
14103 was_idle = 0;
14104
14105
14106 pthread_testcancel();
14107 res = poll(pollers, mfcr2->numchans, maxsleep);
14108 pthread_testcancel();
14109 if ((res < 0) && (errno != EINTR)) {
14110 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14111 break;
14112 }
14113
14114 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14115 for (i = 0; i < mfcr2->numchans; i++) {
14116 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14117 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14118 }
14119 }
14120 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14121 }
14122 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14123 return 0;
14124 }
14125 #endif
14126
14127 #if defined(HAVE_PRI)
14128 static void dahdi_pri_message(struct pri *pri, char *s)
14129 {
14130 int x;
14131 int y;
14132 int dchan = -1;
14133 int span = -1;
14134 int dchancount = 0;
14135
14136 if (pri) {
14137 for (x = 0; x < NUM_SPANS; x++) {
14138 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14139 if (pris[x].pri.dchans[y]) {
14140 dchancount++;
14141 }
14142
14143 if (pris[x].pri.dchans[y] == pri) {
14144 dchan = y;
14145 }
14146 }
14147 if (dchan >= 0) {
14148 span = x;
14149 break;
14150 }
14151 dchancount = 0;
14152 }
14153 if (-1 < span) {
14154 if (1 < dchancount) {
14155 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14156 } else {
14157 ast_verbose("PRI Span: %d %s", span + 1, s);
14158 }
14159 } else {
14160 ast_verbose("PRI Span: ? %s", s);
14161 }
14162 } else {
14163 ast_verbose("PRI Span: ? %s", s);
14164 }
14165
14166 ast_mutex_lock(&pridebugfdlock);
14167
14168 if (pridebugfd >= 0) {
14169 if (write(pridebugfd, s, strlen(s)) < 0) {
14170 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14171 }
14172 }
14173
14174 ast_mutex_unlock(&pridebugfdlock);
14175 }
14176 #endif
14177
14178 #if defined(HAVE_PRI)
14179 static void dahdi_pri_error(struct pri *pri, char *s)
14180 {
14181 int x;
14182 int y;
14183 int dchan = -1;
14184 int span = -1;
14185 int dchancount = 0;
14186
14187 if (pri) {
14188 for (x = 0; x < NUM_SPANS; x++) {
14189 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14190 if (pris[x].pri.dchans[y]) {
14191 dchancount++;
14192 }
14193
14194 if (pris[x].pri.dchans[y] == pri) {
14195 dchan = y;
14196 }
14197 }
14198 if (dchan >= 0) {
14199 span = x;
14200 break;
14201 }
14202 dchancount = 0;
14203 }
14204 if (-1 < span) {
14205 if (1 < dchancount) {
14206 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14207 } else {
14208 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14209 }
14210 } else {
14211 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14212 }
14213 } else {
14214 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14215 }
14216
14217 ast_mutex_lock(&pridebugfdlock);
14218
14219 if (pridebugfd >= 0) {
14220 if (write(pridebugfd, s, strlen(s)) < 0) {
14221 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14222 }
14223 }
14224
14225 ast_mutex_unlock(&pridebugfdlock);
14226 }
14227 #endif
14228
14229 #if defined(HAVE_PRI)
14230 static int prepare_pri(struct dahdi_pri *pri)
14231 {
14232 int i, res, x;
14233 struct dahdi_params p;
14234 struct dahdi_bufferinfo bi;
14235 struct dahdi_spaninfo si;
14236
14237 pri->pri.calls = &dahdi_pri_callbacks;
14238
14239 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14240 if (!pri->dchannels[i])
14241 break;
14242 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14243 x = pri->dchannels[i];
14244 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14245 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14246 return -1;
14247 }
14248 memset(&p, 0, sizeof(p));
14249 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14250 if (res) {
14251 dahdi_close_pri_fd(pri, i);
14252 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14253 return -1;
14254 }
14255 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14256 dahdi_close_pri_fd(pri, i);
14257 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14258 return -1;
14259 }
14260 memset(&si, 0, sizeof(si));
14261 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14262 if (res) {
14263 dahdi_close_pri_fd(pri, i);
14264 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14265 }
14266 if (!si.alarms) {
14267 pri_event_noalarm(&pri->pri, i, 1);
14268 } else {
14269 pri_event_alarm(&pri->pri, i, 1);
14270 }
14271 memset(&bi, 0, sizeof(bi));
14272 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14273 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14274 bi.numbufs = 32;
14275 bi.bufsize = 1024;
14276 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14277 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14278 dahdi_close_pri_fd(pri, i);
14279 return -1;
14280 }
14281 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14282 }
14283 return 0;
14284 }
14285 #endif
14286
14287 #if defined(HAVE_PRI)
14288 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14289 {
14290 int which, span;
14291 char *ret = NULL;
14292
14293 if (pos != rpos)
14294 return ret;
14295
14296 for (which = span = 0; span < NUM_SPANS; span++) {
14297 if (pris[span].pri.pri && ++which > state) {
14298 if (ast_asprintf(&ret, "%d", span + 1) < 0) {
14299 ret = NULL;
14300 }
14301 break;
14302 }
14303 }
14304 return ret;
14305 }
14306 #endif
14307
14308 #if defined(HAVE_PRI)
14309 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14310 {
14311 return complete_span_helper(line,word,pos,state,3);
14312 }
14313 #endif
14314
14315 #if defined(HAVE_PRI)
14316 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14317 {
14318 int myfd;
14319 switch (cmd) {
14320 case CLI_INIT:
14321 e->command = "pri set debug file";
14322 e->usage = "Usage: pri set debug file [output-file]\n"
14323 " Sends PRI debug output to the specified output file\n";
14324 return NULL;
14325 case CLI_GENERATE:
14326 return NULL;
14327 }
14328 if (a->argc < 5)
14329 return CLI_SHOWUSAGE;
14330
14331 if (ast_strlen_zero(a->argv[4]))
14332 return CLI_SHOWUSAGE;
14333
14334 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14335 if (myfd < 0) {
14336 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14337 return CLI_SUCCESS;
14338 }
14339
14340 ast_mutex_lock(&pridebugfdlock);
14341
14342 if (pridebugfd >= 0)
14343 close(pridebugfd);
14344
14345 pridebugfd = myfd;
14346 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14347 ast_mutex_unlock(&pridebugfdlock);
14348 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14349 return CLI_SUCCESS;
14350 }
14351 #endif
14352
14353 #if defined(HAVE_PRI)
14354 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14355 {
14356 int span;
14357 int x;
14358 int level = 0;
14359 switch (cmd) {
14360 case CLI_INIT:
14361 e->command = "pri set debug {on|off|0|1|2} span";
14362 e->usage =
14363 "Usage: pri set debug {<level>|on|off} span <span>\n"
14364 " Enables debugging on a given PRI span\n";
14365 return NULL;
14366 case CLI_GENERATE:
14367 return complete_span_4(a->line, a->word, a->pos, a->n);
14368 }
14369 if (a->argc < 6) {
14370 return CLI_SHOWUSAGE;
14371 }
14372
14373 if (!strcasecmp(a->argv[3], "on")) {
14374 level = 1;
14375 } else if (!strcasecmp(a->argv[3], "off")) {
14376 level = 0;
14377 } else {
14378 level = atoi(a->argv[3]);
14379 }
14380 span = atoi(a->argv[5]);
14381 if ((span < 1) || (span > NUM_SPANS)) {
14382 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14383 return CLI_SUCCESS;
14384 }
14385 if (!pris[span-1].pri.pri) {
14386 ast_cli(a->fd, "No PRI running on span %d\n", span);
14387 return CLI_SUCCESS;
14388 }
14389
14390
14391 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14392 if (pris[span - 1].pri.dchans[x]) {
14393 switch (level) {
14394 case 0:
14395 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14396 break;
14397 case 1:
14398 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14399 break;
14400 default:
14401 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14402 break;
14403 }
14404 }
14405 }
14406 if (level == 0) {
14407
14408 ast_mutex_lock(&pridebugfdlock);
14409 if (0 <= pridebugfd) {
14410 close(pridebugfd);
14411 pridebugfd = -1;
14412 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14413 pridebugfilename);
14414 }
14415 ast_mutex_unlock(&pridebugfdlock);
14416 }
14417 pris[span - 1].pri.debug = (level) ? 1 : 0;
14418 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14419 return CLI_SUCCESS;
14420 }
14421 #endif
14422
14423 #if defined(HAVE_PRI)
14424 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14425 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14426 {
14427 unsigned *why;
14428 int channel;
14429 int trunkgroup;
14430 int x, y, fd = a->fd;
14431 int interfaceid = 0;
14432 char db_chan_name[20], db_answer[5];
14433 struct dahdi_pvt *tmp;
14434 struct dahdi_pri *pri;
14435
14436 if (a->argc < 5 || a->argc > 6)
14437 return CLI_SHOWUSAGE;
14438 if (strchr(a->argv[4], ':')) {
14439 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14440 return CLI_SHOWUSAGE;
14441 if ((trunkgroup < 1) || (channel < 1))
14442 return CLI_SHOWUSAGE;
14443 pri = NULL;
14444 for (x=0;x<NUM_SPANS;x++) {
14445 if (pris[x].pri.trunkgroup == trunkgroup) {
14446 pri = pris + x;
14447 break;
14448 }
14449 }
14450 if (!pri) {
14451 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14452 return CLI_FAILURE;
14453 }
14454 } else
14455 channel = atoi(a->argv[4]);
14456
14457 if (a->argc == 6)
14458 interfaceid = atoi(a->argv[5]);
14459
14460
14461 for (x = 0; x < NUM_SPANS; x++) {
14462 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14463 if (pris[x].dchannels[y] == channel) {
14464 pri = pris + x;
14465 if (pri->pri.enable_service_message_support) {
14466 ast_mutex_lock(&pri->pri.lock);
14467 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14468 ast_mutex_unlock(&pri->pri.lock);
14469 } else {
14470 ast_cli(fd,
14471 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14472 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14473 }
14474 return CLI_SUCCESS;
14475 }
14476 }
14477 }
14478
14479
14480 ast_mutex_lock(&iflock);
14481 for (tmp = iflist; tmp; tmp = tmp->next) {
14482 if (tmp->pri && tmp->channel == channel) {
14483 ast_mutex_unlock(&iflock);
14484 ast_mutex_lock(&tmp->pri->lock);
14485 if (!tmp->pri->enable_service_message_support) {
14486 ast_mutex_unlock(&tmp->pri->lock);
14487 ast_cli(fd,
14488 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14489 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14490 return CLI_SUCCESS;
14491 }
14492 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14493 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14494 switch(changestatus) {
14495 case 0:
14496
14497 ast_db_del(db_chan_name, SRVST_DBKEY);
14498 *why &= ~SRVST_NEAREND;
14499 if (*why) {
14500 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14501 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14502 } else {
14503 dahdi_pri_update_span_devstate(tmp->pri);
14504 }
14505 break;
14506
14507 case 2:
14508
14509 ast_db_del(db_chan_name, SRVST_DBKEY);
14510 *why |= SRVST_NEAREND;
14511 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14512 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14513 dahdi_pri_update_span_devstate(tmp->pri);
14514 break;
14515
14516
14517 default:
14518 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14519 break;
14520 }
14521 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14522 ast_mutex_unlock(&tmp->pri->lock);
14523 return CLI_SUCCESS;
14524 }
14525 }
14526 ast_mutex_unlock(&iflock);
14527
14528 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14529 return CLI_FAILURE;
14530 }
14531
14532 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14533 {
14534 switch (cmd) {
14535 case CLI_INIT:
14536 e->command = "pri service enable channel";
14537 e->usage =
14538 "Usage: pri service enable channel <channel> [<interface id>]\n"
14539 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14540 " to restore a channel to service, with optional interface id\n"
14541 " as agreed upon with remote switch operator\n";
14542 return NULL;
14543 case CLI_GENERATE:
14544 return NULL;
14545 }
14546 return handle_pri_service_generic(e, cmd, a, 0);
14547 }
14548
14549 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14550 {
14551 switch (cmd) {
14552 case CLI_INIT:
14553 e->command = "pri service disable channel";
14554 e->usage =
14555 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14556 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14557 " to remove a channel from service, with optional interface id\n"
14558 " as agreed upon with remote switch operator\n";
14559 return NULL;
14560 case CLI_GENERATE:
14561 return NULL;
14562 }
14563 return handle_pri_service_generic(e, cmd, a, 2);
14564 }
14565 #endif
14566 #endif
14567
14568 #if defined(HAVE_PRI)
14569 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14570 {
14571 int span;
14572
14573 switch (cmd) {
14574 case CLI_INIT:
14575 e->command = "pri show channels";
14576 e->usage =
14577 "Usage: pri show channels\n"
14578 " Displays PRI channel information such as the current mapping\n"
14579 " of DAHDI B channels to Asterisk channel names and which calls\n"
14580 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14581 " are not associated with any B channel.\n";
14582 return NULL;
14583 case CLI_GENERATE:
14584 return NULL;
14585 }
14586
14587 if (a->argc != 3)
14588 return CLI_SHOWUSAGE;
14589
14590 sig_pri_cli_show_channels_header(a->fd);
14591 for (span = 0; span < NUM_SPANS; ++span) {
14592 if (pris[span].pri.pri) {
14593 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14594 }
14595 }
14596 return CLI_SUCCESS;
14597 }
14598 #endif
14599
14600 #if defined(HAVE_PRI)
14601 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14602 {
14603 int span;
14604
14605 switch (cmd) {
14606 case CLI_INIT:
14607 e->command = "pri show spans";
14608 e->usage =
14609 "Usage: pri show spans\n"
14610 " Displays PRI span information\n";
14611 return NULL;
14612 case CLI_GENERATE:
14613 return NULL;
14614 }
14615
14616 if (a->argc != 3)
14617 return CLI_SHOWUSAGE;
14618
14619 for (span = 0; span < NUM_SPANS; span++) {
14620 if (pris[span].pri.pri) {
14621 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14622 }
14623 }
14624 return CLI_SUCCESS;
14625 }
14626 #endif
14627
14628 #if defined(HAVE_PRI)
14629 #define container_of(ptr, type, member) \
14630 ((type *)((char *)(ptr) - offsetof(type, member)))
14631
14632
14633
14634
14635
14636
14637
14638
14639
14640
14641
14642
14643
14644 static int pri_destroy_dchan(struct sig_pri_span *pri)
14645 {
14646 int i;
14647 struct dahdi_pri* dahdi_pri;
14648
14649 if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14650 return 0;
14651 }
14652 pthread_cancel(pri->master);
14653 pthread_join(pri->master, NULL);
14654
14655
14656 dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14657 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14658 ast_debug(4, "closing pri_fd %d\n", i);
14659 dahdi_close_pri_fd(dahdi_pri, i);
14660 }
14661 pri->pri = NULL;
14662 ast_debug(1, "PRI span %d destroyed\n", pri->span);
14663 return 1;
14664 }
14665
14666 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14667 struct ast_cli_args *a)
14668 {
14669 int span;
14670 int i;
14671 int res;
14672
14673 switch (cmd) {
14674 case CLI_INIT:
14675 e->command = "pri destroy span";
14676 e->usage =
14677 "Usage: pri destroy span <span>\n"
14678 " Destorys D-channel of span and its B-channels.\n"
14679 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14680 return NULL;
14681 case CLI_GENERATE:
14682 return complete_span_4(a->line, a->word, a->pos, a->n);
14683 }
14684
14685 if (a->argc < 4) {
14686 return CLI_SHOWUSAGE;
14687 }
14688 res = sscanf(a->argv[3], "%30d", &span);
14689 if ((res != 1) || span < 1 || span > NUM_SPANS) {
14690 ast_cli(a->fd,
14691 "Invalid span '%s'. Should be a number from %d to %d\n",
14692 a->argv[3], 1, NUM_SPANS);
14693 return CLI_SUCCESS;
14694 }
14695 if (!pris[span - 1].pri.pri) {
14696 ast_cli(a->fd, "No PRI running on span %d\n", span);
14697 return CLI_SUCCESS;
14698 }
14699
14700 for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14701 int channel;
14702 struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14703
14704 if (!pvt) {
14705 continue;
14706 }
14707 channel = pvt->channel;
14708 ast_debug(2, "About to destroy B-channel %d.\n", channel);
14709 dahdi_destroy_channel_bynum(channel);
14710 }
14711 ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14712 pri_destroy_dchan(&pris[span - 1].pri);
14713
14714 return CLI_SUCCESS;
14715 }
14716
14717 #endif
14718
14719 #if defined(HAVE_PRI)
14720 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14721 {
14722 int span;
14723
14724 switch (cmd) {
14725 case CLI_INIT:
14726 e->command = "pri show span";
14727 e->usage =
14728 "Usage: pri show span <span>\n"
14729 " Displays PRI Information on a given PRI span\n";
14730 return NULL;
14731 case CLI_GENERATE:
14732 return complete_span_4(a->line, a->word, a->pos, a->n);
14733 }
14734
14735 if (a->argc < 4)
14736 return CLI_SHOWUSAGE;
14737 span = atoi(a->argv[3]);
14738 if ((span < 1) || (span > NUM_SPANS)) {
14739 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14740 return CLI_SUCCESS;
14741 }
14742 if (!pris[span-1].pri.pri) {
14743 ast_cli(a->fd, "No PRI running on span %d\n", span);
14744 return CLI_SUCCESS;
14745 }
14746
14747 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14748
14749 return CLI_SUCCESS;
14750 }
14751 #endif
14752
14753 #if defined(HAVE_PRI)
14754 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14755 {
14756 int x;
14757 int span;
14758 int count=0;
14759 int debug;
14760
14761 switch (cmd) {
14762 case CLI_INIT:
14763 e->command = "pri show debug";
14764 e->usage =
14765 "Usage: pri show debug\n"
14766 " Show the debug state of pri spans\n";
14767 return NULL;
14768 case CLI_GENERATE:
14769 return NULL;
14770 }
14771
14772 for (span = 0; span < NUM_SPANS; span++) {
14773 if (pris[span].pri.pri) {
14774 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14775 if (pris[span].pri.dchans[x]) {
14776 debug = pri_get_debug(pris[span].pri.dchans[x]);
14777 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" );
14778 count++;
14779 }
14780 }
14781 }
14782
14783 }
14784 ast_mutex_lock(&pridebugfdlock);
14785 if (pridebugfd >= 0)
14786 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14787 ast_mutex_unlock(&pridebugfdlock);
14788
14789 if (!count)
14790 ast_cli(a->fd, "No PRI running\n");
14791 return CLI_SUCCESS;
14792 }
14793 #endif
14794
14795 #if defined(HAVE_PRI)
14796 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14797 {
14798 switch (cmd) {
14799 case CLI_INIT:
14800 e->command = "pri show version";
14801 e->usage =
14802 "Usage: pri show version\n"
14803 "Show libpri version information\n";
14804 return NULL;
14805 case CLI_GENERATE:
14806 return NULL;
14807 }
14808
14809 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14810
14811 return CLI_SUCCESS;
14812 }
14813 #endif
14814
14815 #if defined(HAVE_PRI)
14816 static struct ast_cli_entry dahdi_pri_cli[] = {
14817 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14818 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14819 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14820 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14821 #endif
14822 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14823 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14824 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14825 AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
14826 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14827 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14828 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14829 };
14830 #endif
14831
14832 #ifdef HAVE_OPENR2
14833
14834 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14835 {
14836 switch (cmd) {
14837 case CLI_INIT:
14838 e->command = "mfcr2 show version";
14839 e->usage =
14840 "Usage: mfcr2 show version\n"
14841 " Shows the version of the OpenR2 library being used.\n";
14842 return NULL;
14843 case CLI_GENERATE:
14844 return NULL;
14845 }
14846 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14847 return CLI_SUCCESS;
14848 }
14849
14850 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14851 {
14852 #define FORMAT "%4s %40s\n"
14853 int i = 0;
14854 int numvariants = 0;
14855 const openr2_variant_entry_t *variants;
14856 switch (cmd) {
14857 case CLI_INIT:
14858 e->command = "mfcr2 show variants";
14859 e->usage =
14860 "Usage: mfcr2 show variants\n"
14861 " Shows the list of MFC/R2 variants supported.\n";
14862 return NULL;
14863 case CLI_GENERATE:
14864 return NULL;
14865 }
14866 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14867 ast_cli(a->fd, "Failed to get list of variants.\n");
14868 return CLI_FAILURE;
14869 }
14870 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14871 for (i = 0; i < numvariants; i++) {
14872 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14873 }
14874 return CLI_SUCCESS;
14875 #undef FORMAT
14876 }
14877
14878 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14879 {
14880 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14881 int filtertype = 0;
14882 int targetnum = 0;
14883 char channo[5];
14884 char anino[5];
14885 char dnisno[5];
14886 struct dahdi_pvt *p;
14887 openr2_context_t *r2context;
14888 openr2_variant_t r2variant;
14889 switch (cmd) {
14890 case CLI_INIT:
14891 e->command = "mfcr2 show channels [group|context]";
14892 e->usage =
14893 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14894 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14895 return NULL;
14896 case CLI_GENERATE:
14897 return NULL;
14898 }
14899 if (!((a->argc == 3) || (a->argc == 5))) {
14900 return CLI_SHOWUSAGE;
14901 }
14902 if (a->argc == 5) {
14903 if (!strcasecmp(a->argv[3], "group")) {
14904 targetnum = atoi(a->argv[4]);
14905 if ((targetnum < 0) || (targetnum > 63))
14906 return CLI_SHOWUSAGE;
14907 targetnum = 1 << targetnum;
14908 filtertype = 1;
14909 } else if (!strcasecmp(a->argv[3], "context")) {
14910 filtertype = 2;
14911 } else {
14912 return CLI_SHOWUSAGE;
14913 }
14914 }
14915 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14916 ast_mutex_lock(&iflock);
14917 for (p = iflist; p; p = p->next) {
14918 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14919 continue;
14920 }
14921 if (filtertype) {
14922 switch(filtertype) {
14923 case 1:
14924 if (p->group != targetnum) {
14925 continue;
14926 }
14927 break;
14928 case 2:
14929 if (strcasecmp(p->context, a->argv[4])) {
14930 continue;
14931 }
14932 break;
14933 default:
14934 ;
14935 }
14936 }
14937 r2context = openr2_chan_get_context(p->r2chan);
14938 r2variant = openr2_context_get_variant(r2context);
14939 snprintf(channo, sizeof(channo), "%d", p->channel);
14940 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14941 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14942 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14943 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14944 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14945 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14946 }
14947 ast_mutex_unlock(&iflock);
14948 return CLI_SUCCESS;
14949 #undef FORMAT
14950 }
14951
14952 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14953 {
14954 struct dahdi_pvt *p = NULL;
14955 int channo = 0;
14956 char *toklevel = NULL;
14957 char *saveptr = NULL;
14958 char *logval = NULL;
14959 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14960 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14961 switch (cmd) {
14962 case CLI_INIT:
14963 e->command = "mfcr2 set debug";
14964 e->usage =
14965 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14966 " Set a new logging level for the specified channel.\n"
14967 " If no channel is specified the logging level will be applied to all channels.\n";
14968 return NULL;
14969 case CLI_GENERATE:
14970 return NULL;
14971 }
14972 if (a->argc < 4) {
14973 return CLI_SHOWUSAGE;
14974 }
14975 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14976 logval = ast_strdupa(a->argv[3]);
14977 toklevel = strtok_r(logval, ",", &saveptr);
14978 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14979 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14980 return CLI_FAILURE;
14981 } else if (OR2_LOG_NOTHING == tmplevel) {
14982 loglevel = tmplevel;
14983 } else {
14984 loglevel |= tmplevel;
14985 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14986 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14987 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14988 continue;
14989 }
14990 loglevel |= tmplevel;
14991 }
14992 }
14993 ast_mutex_lock(&iflock);
14994 for (p = iflist; p; p = p->next) {
14995 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14996 continue;
14997 }
14998 if ((channo != -1) && (p->channel != channo )) {
14999 continue;
15000 }
15001 openr2_chan_set_log_level(p->r2chan, loglevel);
15002 if (channo != -1) {
15003 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15004 break;
15005 }
15006 }
15007 if ((channo != -1) && !p) {
15008 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15009 }
15010 if (channo == -1) {
15011 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15012 }
15013 ast_mutex_unlock(&iflock);
15014 return CLI_SUCCESS;
15015 }
15016
15017 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15018 {
15019 struct dahdi_pvt *p = NULL;
15020 int channo = 0;
15021 switch (cmd) {
15022 case CLI_INIT:
15023 e->command = "mfcr2 call files [on|off]";
15024 e->usage =
15025 "Usage: mfcr2 call files [on|off] <channel>\n"
15026 " Enable call files creation on the specified channel.\n"
15027 " If no channel is specified call files creation policy will be applied to all channels.\n";
15028 return NULL;
15029 case CLI_GENERATE:
15030 return NULL;
15031 }
15032 if (a->argc < 4) {
15033 return CLI_SHOWUSAGE;
15034 }
15035 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15036 ast_mutex_lock(&iflock);
15037 for (p = iflist; p; p = p->next) {
15038 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15039 continue;
15040 }
15041 if ((channo != -1) && (p->channel != channo )) {
15042 continue;
15043 }
15044 if (ast_true(a->argv[3])) {
15045 openr2_chan_enable_call_files(p->r2chan);
15046 } else {
15047 openr2_chan_disable_call_files(p->r2chan);
15048 }
15049 if (channo != -1) {
15050 if (ast_true(a->argv[3])) {
15051 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15052 } else {
15053 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15054 }
15055 break;
15056 }
15057 }
15058 if ((channo != -1) && !p) {
15059 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15060 }
15061 if (channo == -1) {
15062 if (ast_true(a->argv[3])) {
15063 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15064 } else {
15065 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15066 }
15067 }
15068 ast_mutex_unlock(&iflock);
15069 return CLI_SUCCESS;
15070 }
15071
15072 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15073 {
15074 struct dahdi_pvt *p = NULL;
15075 int channo = 0;
15076 switch (cmd) {
15077 case CLI_INIT:
15078 e->command = "mfcr2 set idle";
15079 e->usage =
15080 "Usage: mfcr2 set idle <channel>\n"
15081 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15082 " Force the given channel into IDLE state.\n"
15083 " If no channel is specified, all channels will be set to IDLE.\n";
15084 return NULL;
15085 case CLI_GENERATE:
15086 return NULL;
15087 }
15088 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15089 ast_mutex_lock(&iflock);
15090 for (p = iflist; p; p = p->next) {
15091 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15092 continue;
15093 }
15094 if ((channo != -1) && (p->channel != channo )) {
15095 continue;
15096 }
15097 openr2_chan_set_idle(p->r2chan);
15098 ast_mutex_lock(&p->lock);
15099 p->locallyblocked = 0;
15100 p->mfcr2call = 0;
15101 ast_mutex_unlock(&p->lock);
15102 if (channo != -1) {
15103 break;
15104 }
15105 }
15106 if ((channo != -1) && !p) {
15107 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15108 }
15109 ast_mutex_unlock(&iflock);
15110 return CLI_SUCCESS;
15111 }
15112
15113 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15114 {
15115 struct dahdi_pvt *p = NULL;
15116 int channo = 0;
15117 switch (cmd) {
15118 case CLI_INIT:
15119 e->command = "mfcr2 set blocked";
15120 e->usage =
15121 "Usage: mfcr2 set blocked <channel>\n"
15122 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15123 " Force the given channel into BLOCKED state.\n"
15124 " If no channel is specified, all channels will be set to BLOCKED.\n";
15125 return NULL;
15126 case CLI_GENERATE:
15127 return NULL;
15128 }
15129 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15130 ast_mutex_lock(&iflock);
15131 for (p = iflist; p; p = p->next) {
15132 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15133 continue;
15134 }
15135 if ((channo != -1) && (p->channel != channo )) {
15136 continue;
15137 }
15138 openr2_chan_set_blocked(p->r2chan);
15139 ast_mutex_lock(&p->lock);
15140 p->locallyblocked = 1;
15141 ast_mutex_unlock(&p->lock);
15142 if (channo != -1) {
15143 break;
15144 }
15145 }
15146 if ((channo != -1) && !p) {
15147 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15148 }
15149 ast_mutex_unlock(&iflock);
15150 return CLI_SUCCESS;
15151 }
15152
15153 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15154 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15155 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15156 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15157 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15158 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15159 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15160 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15161 };
15162
15163 #endif
15164
15165 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15166 {
15167 int channel;
15168 int ret;
15169 switch (cmd) {
15170 case CLI_INIT:
15171 e->command = "dahdi destroy channel";
15172 e->usage =
15173 "Usage: dahdi destroy channel <chan num>\n"
15174 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15175 return NULL;
15176 case CLI_GENERATE:
15177 return NULL;
15178 }
15179 if (a->argc != 4)
15180 return CLI_SHOWUSAGE;
15181
15182 channel = atoi(a->argv[3]);
15183 ret = dahdi_destroy_channel_bynum(channel);
15184 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15185 }
15186
15187 static void dahdi_softhangup_all(void)
15188 {
15189 struct dahdi_pvt *p;
15190 retry:
15191 ast_mutex_lock(&iflock);
15192 for (p = iflist; p; p = p->next) {
15193 ast_mutex_lock(&p->lock);
15194 if (p->owner && !p->restartpending) {
15195 if (ast_channel_trylock(p->owner)) {
15196 if (option_debug > 2)
15197 ast_verbose("Avoiding deadlock\n");
15198
15199 ast_mutex_unlock(&p->lock);
15200 ast_mutex_unlock(&iflock);
15201 goto retry;
15202 }
15203 if (option_debug > 2)
15204 ast_verbose("Softhanging up on %s\n", p->owner->name);
15205 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15206 p->restartpending = 1;
15207 num_restart_pending++;
15208 ast_channel_unlock(p->owner);
15209 }
15210 ast_mutex_unlock(&p->lock);
15211 }
15212 ast_mutex_unlock(&iflock);
15213 }
15214
15215 static int setup_dahdi(int reload);
15216 static int dahdi_restart(void)
15217 {
15218 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15219 int i, j;
15220 #endif
15221 int cancel_code;
15222 struct dahdi_pvt *p;
15223
15224 ast_mutex_lock(&restart_lock);
15225 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15226 dahdi_softhangup_all();
15227 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15228 #ifdef HAVE_OPENR2
15229 dahdi_r2_destroy_links();
15230 #endif
15231
15232 #if defined(HAVE_PRI)
15233 for (i = 0; i < NUM_SPANS; i++) {
15234 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15235 cancel_code = pthread_cancel(pris[i].pri.master);
15236 pthread_kill(pris[i].pri.master, SIGURG);
15237 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);
15238 pthread_join(pris[i].pri.master, NULL);
15239 ast_debug(4, "Joined thread of span %d\n", i);
15240 }
15241 }
15242 #endif
15243
15244 #if defined(HAVE_SS7)
15245 for (i = 0; i < NUM_SPANS; i++) {
15246 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15247 cancel_code = pthread_cancel(linksets[i].ss7.master);
15248 pthread_kill(linksets[i].ss7.master, SIGURG);
15249 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);
15250 pthread_join(linksets[i].ss7.master, NULL);
15251 ast_debug(4, "Joined thread of span %d\n", i);
15252 }
15253 }
15254 #endif
15255
15256 ast_mutex_lock(&monlock);
15257 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15258 cancel_code = pthread_cancel(monitor_thread);
15259 pthread_kill(monitor_thread, SIGURG);
15260 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15261 pthread_join(monitor_thread, NULL);
15262 ast_debug(4, "Joined monitor thread\n");
15263 }
15264 monitor_thread = AST_PTHREADT_NULL;
15265
15266 ast_mutex_lock(&ss_thread_lock);
15267 while (ss_thread_count > 0) {
15268 int x = DAHDI_FLASH;
15269 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15270
15271 ast_mutex_lock(&iflock);
15272 for (p = iflist; p; p = p->next) {
15273 if (p->owner) {
15274
15275 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15276 }
15277 }
15278 ast_mutex_unlock(&iflock);
15279 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15280 }
15281
15282
15283 dahdi_softhangup_all();
15284 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15285 destroy_all_channels();
15286 memset(round_robin, 0, sizeof(round_robin));
15287 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15288
15289 ast_mutex_unlock(&monlock);
15290
15291 #ifdef HAVE_PRI
15292 for (i = 0; i < NUM_SPANS; i++) {
15293 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15294 dahdi_close_pri_fd(&(pris[i]), j);
15295 }
15296
15297 memset(pris, 0, sizeof(pris));
15298 for (i = 0; i < NUM_SPANS; i++) {
15299 sig_pri_init_pri(&pris[i].pri);
15300 }
15301 pri_set_error(dahdi_pri_error);
15302 pri_set_message(dahdi_pri_message);
15303 #endif
15304 #if defined(HAVE_SS7)
15305 for (i = 0; i < NUM_SPANS; i++) {
15306 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15307 dahdi_close_ss7_fd(&(linksets[i]), j);
15308 }
15309
15310 memset(linksets, 0, sizeof(linksets));
15311 for (i = 0; i < NUM_SPANS; i++) {
15312 sig_ss7_init_linkset(&linksets[i].ss7);
15313 }
15314 ss7_set_error(dahdi_ss7_error);
15315 ss7_set_message(dahdi_ss7_message);
15316 #endif
15317
15318 if (setup_dahdi(2) != 0) {
15319 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15320 ast_mutex_unlock(&ss_thread_lock);
15321 return 1;
15322 }
15323 ast_mutex_unlock(&ss_thread_lock);
15324 ast_mutex_unlock(&restart_lock);
15325 return 0;
15326 }
15327
15328 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15329 {
15330 switch (cmd) {
15331 case CLI_INIT:
15332 e->command = "dahdi restart";
15333 e->usage =
15334 "Usage: dahdi restart\n"
15335 " Restarts the DAHDI channels: destroys them all and then\n"
15336 " re-reads them from chan_dahdi.conf.\n"
15337 " Note that this will STOP any running CALL on DAHDI channels.\n"
15338 "";
15339 return NULL;
15340 case CLI_GENERATE:
15341 return NULL;
15342 }
15343 if (a->argc != 2)
15344 return CLI_SHOWUSAGE;
15345
15346 if (dahdi_restart() != 0)
15347 return CLI_FAILURE;
15348 return CLI_SUCCESS;
15349 }
15350
15351 static int action_dahdirestart(struct mansession *s, const struct message *m)
15352 {
15353 if (dahdi_restart() != 0) {
15354 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15355 return 1;
15356 }
15357 astman_send_ack(s, m, "DAHDIRestart: Success");
15358 return 0;
15359 }
15360
15361 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15362 {
15363 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15364 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15365 ast_group_t targetnum = 0;
15366 int filtertype = 0;
15367 struct dahdi_pvt *tmp = NULL;
15368 char tmps[20] = "";
15369 char statestr[20] = "";
15370 char blockstr[20] = "";
15371
15372 switch (cmd) {
15373 case CLI_INIT:
15374 e->command = "dahdi show channels [group|context]";
15375 e->usage =
15376 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15377 " Shows a list of available channels with optional filtering\n"
15378 " <group> must be a number between 0 and 63\n";
15379 return NULL;
15380 case CLI_GENERATE:
15381 return NULL;
15382 }
15383
15384
15385
15386 if (!((a->argc == 3) || (a->argc == 5)))
15387 return CLI_SHOWUSAGE;
15388
15389 if (a->argc == 5) {
15390 if (!strcasecmp(a->argv[3], "group")) {
15391 targetnum = atoi(a->argv[4]);
15392 if (63 < targetnum) {
15393 return CLI_SHOWUSAGE;
15394 }
15395 targetnum = ((ast_group_t) 1) << targetnum;
15396 filtertype = 1;
15397 } else if (!strcasecmp(a->argv[3], "context")) {
15398 filtertype = 2;
15399 }
15400 }
15401
15402 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15403 ast_mutex_lock(&iflock);
15404 for (tmp = iflist; tmp; tmp = tmp->next) {
15405 if (filtertype) {
15406 switch(filtertype) {
15407 case 1:
15408 if (!(tmp->group & targetnum)) {
15409 continue;
15410 }
15411 break;
15412 case 2:
15413 if (strcasecmp(tmp->context, a->argv[4])) {
15414 continue;
15415 }
15416 break;
15417 default:
15418 break;
15419 }
15420 }
15421 if (tmp->channel > 0) {
15422 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15423 } else
15424 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15425
15426 if (tmp->locallyblocked)
15427 blockstr[0] = 'L';
15428 else
15429 blockstr[0] = ' ';
15430
15431 if (tmp->remotelyblocked)
15432 blockstr[1] = 'R';
15433 else
15434 blockstr[1] = ' ';
15435
15436 blockstr[2] = '\0';
15437
15438 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15439
15440 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15441 }
15442 ast_mutex_unlock(&iflock);
15443 return CLI_SUCCESS;
15444 #undef FORMAT
15445 #undef FORMAT2
15446 }
15447
15448 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15449 {
15450 int channel;
15451 struct dahdi_pvt *tmp = NULL;
15452 struct dahdi_confinfo ci;
15453 struct dahdi_params ps;
15454 int x;
15455
15456 switch (cmd) {
15457 case CLI_INIT:
15458 e->command = "dahdi show channel";
15459 e->usage =
15460 "Usage: dahdi show channel <chan num>\n"
15461 " Detailed information about a given channel\n";
15462 return NULL;
15463 case CLI_GENERATE:
15464 return NULL;
15465 }
15466
15467 if (a->argc != 4)
15468 return CLI_SHOWUSAGE;
15469
15470 channel = atoi(a->argv[3]);
15471
15472 ast_mutex_lock(&iflock);
15473 for (tmp = iflist; tmp; tmp = tmp->next) {
15474 if (tmp->channel == channel) {
15475 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15476 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15477 ast_cli(a->fd, "Span: %d\n", tmp->span);
15478 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15479 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15480 ast_cli(a->fd, "Context: %s\n", tmp->context);
15481 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15482 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15483 #if defined(HAVE_PRI)
15484 #if defined(HAVE_PRI_SUBADDR)
15485 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15486 #endif
15487 #endif
15488 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15489 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15490 if (tmp->vars) {
15491 struct ast_variable *v;
15492 ast_cli(a->fd, "Variables:\n");
15493 for (v = tmp->vars ; v ; v = v->next)
15494 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15495 }
15496 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15497 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15498 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15499 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15500 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15501 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)" : "");
15502 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)" : "");
15503 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)" : "");
15504 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15505 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15506 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15507 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15508 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15509 if (tmp->busydetect) {
15510 #if defined(BUSYDETECT_TONEONLY)
15511 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15512 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15513 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15514 #endif
15515 #ifdef BUSYDETECT_DEBUG
15516 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15517 #endif
15518 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15519 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15520 }
15521 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15522 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15523 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15524 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15525 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15526 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15527 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15528 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15529 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15530 ast_cli(a->fd, "Echo Cancellation:\n");
15531
15532 if (tmp->echocancel.head.tap_length) {
15533 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
15534 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15535 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15536 }
15537 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15538 } else {
15539 ast_cli(a->fd, "\tnone\n");
15540 }
15541 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15542 if (tmp->master)
15543 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15544 for (x = 0; x < MAX_SLAVES; x++) {
15545 if (tmp->slaves[x])
15546 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15547 }
15548 #ifdef HAVE_OPENR2
15549 if (tmp->mfcr2) {
15550 char calldir[OR2_MAX_PATH];
15551 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15552 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15553 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15554 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15555 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15556 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15557 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15558 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15559 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15560 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15561 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15562 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15563 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15564 #endif
15565 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15566 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15567 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15568 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15569 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15570 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15571 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15572 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15573 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15574 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15575 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15576 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15577 }
15578 #endif
15579 #if defined(HAVE_SS7)
15580 if (tmp->ss7) {
15581 struct sig_ss7_chan *chan = tmp->sig_pvt;
15582
15583 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15584 }
15585 #endif
15586 #ifdef HAVE_PRI
15587 if (tmp->pri) {
15588 struct sig_pri_chan *chan = tmp->sig_pvt;
15589
15590 ast_cli(a->fd, "PRI Flags: ");
15591 if (chan->resetting != SIG_PRI_RESET_IDLE) {
15592 ast_cli(a->fd, "Resetting=%u ", chan->resetting);
15593 }
15594 if (chan->call)
15595 ast_cli(a->fd, "Call ");
15596 if (chan->allocated) {
15597 ast_cli(a->fd, "Allocated ");
15598 }
15599 ast_cli(a->fd, "\n");
15600 if (tmp->logicalspan)
15601 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15602 else
15603 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15604 }
15605 #endif
15606 memset(&ci, 0, sizeof(ci));
15607 ps.channo = tmp->channel;
15608 if (tmp->subs[SUB_REAL].dfd > -1) {
15609 memset(&ci, 0, sizeof(ci));
15610 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15611 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
15612 }
15613 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15614 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15615 }
15616 memset(&ps, 0, sizeof(ps));
15617 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15618 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15619 } else {
15620 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15621 }
15622 }
15623 ast_mutex_unlock(&iflock);
15624 return CLI_SUCCESS;
15625 }
15626 }
15627 ast_mutex_unlock(&iflock);
15628
15629 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15630 return CLI_FAILURE;
15631 }
15632
15633 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15634 {
15635 int i, j;
15636 switch (cmd) {
15637 case CLI_INIT:
15638 e->command = "dahdi show cadences";
15639 e->usage =
15640 "Usage: dahdi show cadences\n"
15641 " Shows all cadences currently defined\n";
15642 return NULL;
15643 case CLI_GENERATE:
15644 return NULL;
15645 }
15646 for (i = 0; i < num_cadence; i++) {
15647 char output[1024];
15648 char tmp[16], tmp2[64];
15649 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15650 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15651
15652 for (j = 0; j < 16; j++) {
15653 if (cadences[i].ringcadence[j] == 0)
15654 break;
15655 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15656 if (cidrings[i] * 2 - 1 == j)
15657 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15658 else
15659 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15660 if (j != 0)
15661 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15662 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15663 }
15664 ast_cli(a->fd,"%s\n",output);
15665 }
15666 return CLI_SUCCESS;
15667 }
15668
15669
15670 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15671 {
15672 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15673 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15674 int span;
15675 int res;
15676 char alarmstr[50];
15677
15678 int ctl;
15679 struct dahdi_spaninfo s;
15680
15681 switch (cmd) {
15682 case CLI_INIT:
15683 e->command = "dahdi show status";
15684 e->usage =
15685 "Usage: dahdi show status\n"
15686 " Shows a list of DAHDI cards with status\n";
15687 return NULL;
15688 case CLI_GENERATE:
15689 return NULL;
15690 }
15691 ctl = open("/dev/dahdi/ctl", O_RDWR);
15692 if (ctl < 0) {
15693 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15694 return CLI_FAILURE;
15695 }
15696 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15697
15698 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15699 s.spanno = span;
15700 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15701 if (res) {
15702 continue;
15703 }
15704 alarmstr[0] = '\0';
15705 if (s.alarms > 0) {
15706 if (s.alarms & DAHDI_ALARM_BLUE)
15707 strcat(alarmstr, "BLU/");
15708 if (s.alarms & DAHDI_ALARM_YELLOW)
15709 strcat(alarmstr, "YEL/");
15710 if (s.alarms & DAHDI_ALARM_RED)
15711 strcat(alarmstr, "RED/");
15712 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15713 strcat(alarmstr, "LB/");
15714 if (s.alarms & DAHDI_ALARM_RECOVER)
15715 strcat(alarmstr, "REC/");
15716 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15717 strcat(alarmstr, "NOP/");
15718 if (!strlen(alarmstr))
15719 strcat(alarmstr, "UUU/");
15720 if (strlen(alarmstr)) {
15721
15722 alarmstr[strlen(alarmstr) - 1] = '\0';
15723 }
15724 } else {
15725 if (s.numchans)
15726 strcpy(alarmstr, "OK");
15727 else
15728 strcpy(alarmstr, "UNCONFIGURED");
15729 }
15730
15731 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15732 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15733 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15734 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15735 "CAS",
15736 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15737 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15738 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15739 "Unk",
15740 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15741 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15742 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15743 lbostr[s.lbo]
15744 );
15745 }
15746 close(ctl);
15747
15748 return CLI_SUCCESS;
15749 #undef FORMAT
15750 #undef FORMAT2
15751 }
15752
15753 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15754 {
15755 int pseudo_fd = -1;
15756 struct dahdi_versioninfo vi;
15757
15758 switch (cmd) {
15759 case CLI_INIT:
15760 e->command = "dahdi show version";
15761 e->usage =
15762 "Usage: dahdi show version\n"
15763 " Shows the DAHDI version in use\n";
15764 return NULL;
15765 case CLI_GENERATE:
15766 return NULL;
15767 }
15768 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15769 ast_cli(a->fd, "Failed to open control file to get version.\n");
15770 return CLI_SUCCESS;
15771 }
15772
15773 strcpy(vi.version, "Unknown");
15774 strcpy(vi.echo_canceller, "Unknown");
15775
15776 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15777 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15778 else
15779 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15780
15781 close(pseudo_fd);
15782
15783 return CLI_SUCCESS;
15784 }
15785
15786 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15787 {
15788 int channel;
15789 int gain;
15790 int tx;
15791 struct dahdi_hwgain hwgain;
15792 struct dahdi_pvt *tmp = NULL;
15793
15794 switch (cmd) {
15795 case CLI_INIT:
15796 e->command = "dahdi set hwgain {rx|tx}";
15797 e->usage =
15798 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15799 " Sets the hardware gain on a given channel. Changes take effect\n"
15800 " immediately whether the channel is in use or not.\n"
15801 "\n"
15802 " <rx|tx> which direction do you want to change (relative to our module)\n"
15803 " <chan num> is the channel number relative to the device\n"
15804 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15805 "\n"
15806 " Please note:\n"
15807 " * This is currently the only way to set hwgain by the channel driver.\n"
15808 " * hwgain is only supportable by hardware with analog ports because\n"
15809 " hwgain works on the analog side of an analog-digital conversion.\n";
15810 return NULL;
15811 case CLI_GENERATE:
15812 return NULL;
15813 }
15814
15815 if (a->argc != 6)
15816 return CLI_SHOWUSAGE;
15817
15818 if (!strcasecmp("rx", a->argv[3]))
15819 tx = 0;
15820 else if (!strcasecmp("tx", a->argv[3]))
15821 tx = 1;
15822 else
15823 return CLI_SHOWUSAGE;
15824
15825 channel = atoi(a->argv[4]);
15826 gain = atof(a->argv[5])*10.0;
15827
15828 ast_mutex_lock(&iflock);
15829
15830 for (tmp = iflist; tmp; tmp = tmp->next) {
15831
15832 if (tmp->channel != channel)
15833 continue;
15834
15835 if (tmp->subs[SUB_REAL].dfd == -1)
15836 break;
15837
15838 hwgain.newgain = gain;
15839 hwgain.tx = tx;
15840 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15841 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15842 ast_mutex_unlock(&iflock);
15843 return CLI_FAILURE;
15844 }
15845 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15846 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15847 break;
15848 }
15849
15850 ast_mutex_unlock(&iflock);
15851
15852 if (tmp)
15853 return CLI_SUCCESS;
15854
15855 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15856 return CLI_FAILURE;
15857
15858 }
15859
15860 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15861 {
15862 int channel;
15863 float gain;
15864 int tx;
15865 int res;
15866 struct dahdi_pvt *tmp = NULL;
15867
15868 switch (cmd) {
15869 case CLI_INIT:
15870 e->command = "dahdi set swgain {rx|tx}";
15871 e->usage =
15872 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15873 " Sets the software gain on a given channel and overrides the\n"
15874 " value provided at module loadtime. Changes take effect\n"
15875 " immediately whether the channel is in use or not.\n"
15876 "\n"
15877 " <rx|tx> which direction do you want to change (relative to our module)\n"
15878 " <chan num> is the channel number relative to the device\n"
15879 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15880 return NULL;
15881 case CLI_GENERATE:
15882 return NULL;
15883 }
15884
15885 if (a->argc != 6)
15886 return CLI_SHOWUSAGE;
15887
15888 if (!strcasecmp("rx", a->argv[3]))
15889 tx = 0;
15890 else if (!strcasecmp("tx", a->argv[3]))
15891 tx = 1;
15892 else
15893 return CLI_SHOWUSAGE;
15894
15895 channel = atoi(a->argv[4]);
15896 gain = atof(a->argv[5]);
15897
15898 ast_mutex_lock(&iflock);
15899 for (tmp = iflist; tmp; tmp = tmp->next) {
15900
15901 if (tmp->channel != channel)
15902 continue;
15903
15904 if (tmp->subs[SUB_REAL].dfd == -1)
15905 break;
15906
15907 if (tx)
15908 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15909 else
15910 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15911
15912 if (res) {
15913 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15914 ast_mutex_unlock(&iflock);
15915 return CLI_FAILURE;
15916 }
15917
15918 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15919 tx ? "tx" : "rx", gain, channel);
15920
15921 if (tx) {
15922 tmp->txgain = gain;
15923 } else {
15924 tmp->rxgain = gain;
15925 }
15926 break;
15927 }
15928 ast_mutex_unlock(&iflock);
15929
15930 if (tmp)
15931 return CLI_SUCCESS;
15932
15933 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15934 return CLI_FAILURE;
15935
15936 }
15937
15938 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15939 {
15940 int channel;
15941 int on;
15942 struct dahdi_pvt *dahdi_chan = NULL;
15943
15944 switch (cmd) {
15945 case CLI_INIT:
15946 e->command = "dahdi set dnd";
15947 e->usage =
15948 "Usage: dahdi set dnd <chan#> <on|off>\n"
15949 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15950 " Changes take effect immediately.\n"
15951 " <chan num> is the channel number\n"
15952 " <on|off> Enable or disable DND mode?\n"
15953 ;
15954 return NULL;
15955 case CLI_GENERATE:
15956 return NULL;
15957 }
15958
15959 if (a->argc != 5)
15960 return CLI_SHOWUSAGE;
15961
15962 if ((channel = atoi(a->argv[3])) <= 0) {
15963 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15964 return CLI_SHOWUSAGE;
15965 }
15966
15967 if (ast_true(a->argv[4]))
15968 on = 1;
15969 else if (ast_false(a->argv[4]))
15970 on = 0;
15971 else {
15972 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15973 return CLI_SHOWUSAGE;
15974 }
15975
15976 ast_mutex_lock(&iflock);
15977 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15978 if (dahdi_chan->channel != channel)
15979 continue;
15980
15981
15982 dahdi_dnd(dahdi_chan, on);
15983 break;
15984 }
15985 ast_mutex_unlock(&iflock);
15986
15987 if (!dahdi_chan) {
15988 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15989 return CLI_FAILURE;
15990 }
15991
15992 return CLI_SUCCESS;
15993 }
15994
15995 static struct ast_cli_entry dahdi_cli[] = {
15996 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15997 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15998 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15999 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16000 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16001 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16002 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16003 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16004 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16005 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16006 };
16007
16008 #define TRANSFER 0
16009 #define HANGUP 1
16010
16011 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16012 {
16013 if (p) {
16014 switch (mode) {
16015 case TRANSFER:
16016 p->fake_event = DAHDI_EVENT_WINKFLASH;
16017 break;
16018 case HANGUP:
16019 p->fake_event = DAHDI_EVENT_ONHOOK;
16020 break;
16021 default:
16022 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16023 }
16024 }
16025 return 0;
16026 }
16027 static struct dahdi_pvt *find_channel(int channel)
16028 {
16029 struct dahdi_pvt *p;
16030
16031 ast_mutex_lock(&iflock);
16032 for (p = iflist; p; p = p->next) {
16033 if (p->channel == channel) {
16034 break;
16035 }
16036 }
16037 ast_mutex_unlock(&iflock);
16038 return p;
16039 }
16040
16041
16042
16043
16044
16045
16046
16047
16048
16049
16050 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16051 {
16052 int chan_num;
16053
16054 if (sscanf(channel, "%30d", &chan_num) != 1) {
16055
16056 return NULL;
16057 }
16058
16059 return find_channel(chan_num);
16060 }
16061
16062 static int action_dahdidndon(struct mansession *s, const struct message *m)
16063 {
16064 struct dahdi_pvt *p;
16065 const char *channel = astman_get_header(m, "DAHDIChannel");
16066
16067 if (ast_strlen_zero(channel)) {
16068 astman_send_error(s, m, "No channel specified");
16069 return 0;
16070 }
16071 p = find_channel_from_str(channel);
16072 if (!p) {
16073 astman_send_error(s, m, "No such channel");
16074 return 0;
16075 }
16076 dahdi_dnd(p, 1);
16077 astman_send_ack(s, m, "DND Enabled");
16078 return 0;
16079 }
16080
16081 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16082 {
16083 struct dahdi_pvt *p;
16084 const char *channel = astman_get_header(m, "DAHDIChannel");
16085
16086 if (ast_strlen_zero(channel)) {
16087 astman_send_error(s, m, "No channel specified");
16088 return 0;
16089 }
16090 p = find_channel_from_str(channel);
16091 if (!p) {
16092 astman_send_error(s, m, "No such channel");
16093 return 0;
16094 }
16095 dahdi_dnd(p, 0);
16096 astman_send_ack(s, m, "DND Disabled");
16097 return 0;
16098 }
16099
16100 static int action_transfer(struct mansession *s, const struct message *m)
16101 {
16102 struct dahdi_pvt *p;
16103 const char *channel = astman_get_header(m, "DAHDIChannel");
16104
16105 if (ast_strlen_zero(channel)) {
16106 astman_send_error(s, m, "No channel specified");
16107 return 0;
16108 }
16109 p = find_channel_from_str(channel);
16110 if (!p) {
16111 astman_send_error(s, m, "No such channel");
16112 return 0;
16113 }
16114 if (!analog_lib_handles(p->sig, 0, 0)) {
16115 astman_send_error(s, m, "Channel signaling is not analog");
16116 return 0;
16117 }
16118 dahdi_fake_event(p,TRANSFER);
16119 astman_send_ack(s, m, "DAHDITransfer");
16120 return 0;
16121 }
16122
16123 static int action_transferhangup(struct mansession *s, const struct message *m)
16124 {
16125 struct dahdi_pvt *p;
16126 const char *channel = astman_get_header(m, "DAHDIChannel");
16127
16128 if (ast_strlen_zero(channel)) {
16129 astman_send_error(s, m, "No channel specified");
16130 return 0;
16131 }
16132 p = find_channel_from_str(channel);
16133 if (!p) {
16134 astman_send_error(s, m, "No such channel");
16135 return 0;
16136 }
16137 if (!analog_lib_handles(p->sig, 0, 0)) {
16138 astman_send_error(s, m, "Channel signaling is not analog");
16139 return 0;
16140 }
16141 dahdi_fake_event(p,HANGUP);
16142 astman_send_ack(s, m, "DAHDIHangup");
16143 return 0;
16144 }
16145
16146 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16147 {
16148 struct dahdi_pvt *p;
16149 const char *channel = astman_get_header(m, "DAHDIChannel");
16150 const char *number = astman_get_header(m, "Number");
16151 int i;
16152
16153 if (ast_strlen_zero(channel)) {
16154 astman_send_error(s, m, "No channel specified");
16155 return 0;
16156 }
16157 if (ast_strlen_zero(number)) {
16158 astman_send_error(s, m, "No number specified");
16159 return 0;
16160 }
16161 p = find_channel_from_str(channel);
16162 if (!p) {
16163 astman_send_error(s, m, "No such channel");
16164 return 0;
16165 }
16166 if (!p->owner) {
16167 astman_send_error(s, m, "Channel does not have it's owner");
16168 return 0;
16169 }
16170 for (i = 0; i < strlen(number); i++) {
16171 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16172 dahdi_queue_frame(p, &f);
16173 }
16174 astman_send_ack(s, m, "DAHDIDialOffhook");
16175 return 0;
16176 }
16177
16178 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16179 {
16180 struct dahdi_pvt *tmp = NULL;
16181 const char *id = astman_get_header(m, "ActionID");
16182 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16183 char idText[256] = "";
16184 int channels = 0;
16185 int dahdichanquery;
16186
16187 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16188
16189 dahdichanquery = -1;
16190 }
16191
16192 astman_send_ack(s, m, "DAHDI channel status will follow");
16193 if (!ast_strlen_zero(id))
16194 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16195
16196 ast_mutex_lock(&iflock);
16197
16198 for (tmp = iflist; tmp; tmp = tmp->next) {
16199 if (tmp->channel > 0) {
16200 int alm;
16201
16202
16203 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16204 continue;
16205
16206 alm = get_alarms(tmp);
16207 channels++;
16208 if (tmp->owner) {
16209
16210 astman_append(s,
16211 "Event: DAHDIShowChannels\r\n"
16212 "DAHDIChannel: %d\r\n"
16213 "Channel: %s\r\n"
16214 "Uniqueid: %s\r\n"
16215 "AccountCode: %s\r\n"
16216 "Signalling: %s\r\n"
16217 "SignallingCode: %d\r\n"
16218 "Context: %s\r\n"
16219 "DND: %s\r\n"
16220 "Alarm: %s\r\n"
16221 "%s"
16222 "\r\n",
16223 tmp->channel,
16224 tmp->owner->name,
16225 tmp->owner->uniqueid,
16226 tmp->owner->accountcode,
16227 sig2str(tmp->sig),
16228 tmp->sig,
16229 tmp->context,
16230 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16231 alarm2str(alm), idText);
16232 } else {
16233 astman_append(s,
16234 "Event: DAHDIShowChannels\r\n"
16235 "DAHDIChannel: %d\r\n"
16236 "Signalling: %s\r\n"
16237 "SignallingCode: %d\r\n"
16238 "Context: %s\r\n"
16239 "DND: %s\r\n"
16240 "Alarm: %s\r\n"
16241 "%s"
16242 "\r\n",
16243 tmp->channel, sig2str(tmp->sig), tmp->sig,
16244 tmp->context,
16245 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16246 alarm2str(alm), idText);
16247 }
16248 }
16249 }
16250
16251 ast_mutex_unlock(&iflock);
16252
16253 astman_append(s,
16254 "Event: DAHDIShowChannelsComplete\r\n"
16255 "%s"
16256 "Items: %d\r\n"
16257 "\r\n",
16258 idText,
16259 channels);
16260 return 0;
16261 }
16262
16263 #if defined(HAVE_SS7)
16264 static int linkset_addsigchan(int sigchan)
16265 {
16266 struct dahdi_ss7 *link;
16267 int res;
16268 int curfd;
16269 struct dahdi_params params;
16270 struct dahdi_bufferinfo bi;
16271 struct dahdi_spaninfo si;
16272
16273 if (sigchan < 0) {
16274 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16275 return -1;
16276 }
16277 if (cur_ss7type < 0) {
16278 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16279 return -1;
16280 }
16281 if (cur_pointcode < 0) {
16282 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16283 return -1;
16284 }
16285 if (cur_adjpointcode < 0) {
16286 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16287 return -1;
16288 }
16289 if (cur_defaultdpc < 0) {
16290 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16291 return -1;
16292 }
16293 if (cur_networkindicator < 0) {
16294 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16295 return -1;
16296 }
16297 link = ss7_resolve_linkset(cur_linkset);
16298 if (!link) {
16299 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16300 return -1;
16301 }
16302 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16303 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16304 return -1;
16305 }
16306
16307 curfd = link->ss7.numsigchans;
16308
16309
16310 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16311 if (link->ss7.fds[curfd] < 0) {
16312 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16313 strerror(errno));
16314 return -1;
16315 }
16316 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16317 dahdi_close_ss7_fd(link, curfd);
16318 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16319 strerror(errno));
16320 return -1;
16321 }
16322
16323
16324 memset(¶ms, 0, sizeof(params));
16325 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16326 if (res) {
16327 dahdi_close_ss7_fd(link, curfd);
16328 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16329 strerror(errno));
16330 return -1;
16331 }
16332 if (params.sigtype != DAHDI_SIG_HDLCFCS
16333 && params.sigtype != DAHDI_SIG_HARDHDLC
16334 && params.sigtype != DAHDI_SIG_MTP2) {
16335 dahdi_close_ss7_fd(link, curfd);
16336 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16337 return -1;
16338 }
16339
16340
16341 memset(&bi, 0, sizeof(bi));
16342 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16343 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16344 bi.numbufs = 32;
16345 bi.bufsize = 512;
16346 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16347 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16348 sigchan, strerror(errno));
16349 dahdi_close_ss7_fd(link, curfd);
16350 return -1;
16351 }
16352
16353
16354 memset(&si, 0, sizeof(si));
16355 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16356 if (res) {
16357 dahdi_close_ss7_fd(link, curfd);
16358 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16359 strerror(errno));
16360 }
16361
16362 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16363 (params.sigtype == DAHDI_SIG_MTP2)
16364 ? SS7_TRANSPORT_DAHDIMTP2
16365 : SS7_TRANSPORT_DAHDIDCHAN,
16366 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16367 if (res) {
16368 dahdi_close_ss7_fd(link, curfd);
16369 return -1;
16370 }
16371
16372 ++link->ss7.numsigchans;
16373
16374 return 0;
16375 }
16376 #endif
16377
16378 #if defined(HAVE_SS7)
16379 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16380 {
16381 int span;
16382 switch (cmd) {
16383 case CLI_INIT:
16384 e->command = "ss7 set debug {on|off} linkset";
16385 e->usage =
16386 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16387 " Enables debugging on a given SS7 linkset\n";
16388 return NULL;
16389 case CLI_GENERATE:
16390 return NULL;
16391 }
16392 if (a->argc < 6)
16393 return CLI_SHOWUSAGE;
16394 span = atoi(a->argv[5]);
16395 if ((span < 1) || (span > NUM_SPANS)) {
16396 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16397 return CLI_SUCCESS;
16398 }
16399 if (!linksets[span-1].ss7.ss7) {
16400 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16401 } else {
16402 if (!strcasecmp(a->argv[3], "on")) {
16403 linksets[span - 1].ss7.debug = 1;
16404 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16405 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16406 } else {
16407 linksets[span - 1].ss7.debug = 0;
16408 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16409 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16410 }
16411 }
16412
16413 return CLI_SUCCESS;
16414 }
16415 #endif
16416
16417 #if defined(HAVE_SS7)
16418 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16419 {
16420 int linkset, cic;
16421 int blocked = -1, i;
16422 switch (cmd) {
16423 case CLI_INIT:
16424 e->command = "ss7 block cic";
16425 e->usage =
16426 "Usage: ss7 block cic <linkset> <CIC>\n"
16427 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16428 return NULL;
16429 case CLI_GENERATE:
16430 return NULL;
16431 }
16432 if (a->argc == 5)
16433 linkset = atoi(a->argv[3]);
16434 else
16435 return CLI_SHOWUSAGE;
16436
16437 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16438 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16439 return CLI_SUCCESS;
16440 }
16441
16442 if (!linksets[linkset-1].ss7.ss7) {
16443 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16444 return CLI_SUCCESS;
16445 }
16446
16447 cic = atoi(a->argv[4]);
16448
16449 if (cic < 1) {
16450 ast_cli(a->fd, "Invalid CIC specified!\n");
16451 return CLI_SUCCESS;
16452 }
16453
16454 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16455 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16456 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16457 if (!blocked) {
16458 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16459 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16460 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16461 }
16462 }
16463 }
16464
16465 if (blocked < 0) {
16466 ast_cli(a->fd, "Invalid CIC specified!\n");
16467 return CLI_SUCCESS;
16468 }
16469
16470 if (!blocked)
16471 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16472 else
16473 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16474
16475
16476 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16477
16478 return CLI_SUCCESS;
16479 }
16480 #endif
16481
16482 #if defined(HAVE_SS7)
16483 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16484 {
16485 int linkset;
16486 int i;
16487 switch (cmd) {
16488 case CLI_INIT:
16489 e->command = "ss7 block linkset";
16490 e->usage =
16491 "Usage: ss7 block linkset <linkset number>\n"
16492 " Sends a remote blocking request for all CICs on the given linkset\n";
16493 return NULL;
16494 case CLI_GENERATE:
16495 return NULL;
16496 }
16497 if (a->argc == 4)
16498 linkset = atoi(a->argv[3]);
16499 else
16500 return CLI_SHOWUSAGE;
16501
16502 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16503 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16504 return CLI_SUCCESS;
16505 }
16506
16507 if (!linksets[linkset-1].ss7.ss7) {
16508 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16509 return CLI_SUCCESS;
16510 }
16511
16512 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16513 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16514 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16515 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16516 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16517 }
16518
16519
16520 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16521
16522 return CLI_SUCCESS;
16523 }
16524 #endif
16525
16526 #if defined(HAVE_SS7)
16527 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16528 {
16529 int linkset, cic;
16530 int i, blocked = -1;
16531 switch (cmd) {
16532 case CLI_INIT:
16533 e->command = "ss7 unblock cic";
16534 e->usage =
16535 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16536 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16537 return NULL;
16538 case CLI_GENERATE:
16539 return NULL;
16540 }
16541
16542 if (a->argc == 5)
16543 linkset = atoi(a->argv[3]);
16544 else
16545 return CLI_SHOWUSAGE;
16546
16547 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16548 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16549 return CLI_SUCCESS;
16550 }
16551
16552 if (!linksets[linkset-1].ss7.ss7) {
16553 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16554 return CLI_SUCCESS;
16555 }
16556
16557 cic = atoi(a->argv[4]);
16558
16559 if (cic < 1) {
16560 ast_cli(a->fd, "Invalid CIC specified!\n");
16561 return CLI_SUCCESS;
16562 }
16563
16564 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16565 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16566 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16567 if (blocked) {
16568 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16569 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16570 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16571 }
16572 }
16573 }
16574
16575 if (blocked > 0)
16576 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16577
16578
16579 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16580
16581 return CLI_SUCCESS;
16582 }
16583 #endif
16584
16585 #if defined(HAVE_SS7)
16586 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16587 {
16588 int linkset;
16589 int i;
16590 switch (cmd) {
16591 case CLI_INIT:
16592 e->command = "ss7 unblock linkset";
16593 e->usage =
16594 "Usage: ss7 unblock linkset <linkset number>\n"
16595 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16596 return NULL;
16597 case CLI_GENERATE:
16598 return NULL;
16599 }
16600
16601 if (a->argc == 4)
16602 linkset = atoi(a->argv[3]);
16603 else
16604 return CLI_SHOWUSAGE;
16605
16606 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16607 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16608 return CLI_SUCCESS;
16609 }
16610
16611 if (!linksets[linkset-1].ss7.ss7) {
16612 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16613 return CLI_SUCCESS;
16614 }
16615
16616 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16617 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16618 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16619 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16620 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16621 }
16622
16623
16624 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16625
16626 return CLI_SUCCESS;
16627 }
16628 #endif
16629
16630 #if defined(HAVE_SS7)
16631 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16632 {
16633 int linkset;
16634 struct sig_ss7_linkset *ss7;
16635 switch (cmd) {
16636 case CLI_INIT:
16637 e->command = "ss7 show linkset";
16638 e->usage =
16639 "Usage: ss7 show linkset <span>\n"
16640 " Shows the status of an SS7 linkset.\n";
16641 return NULL;
16642 case CLI_GENERATE:
16643 return NULL;
16644 }
16645
16646 if (a->argc < 4)
16647 return CLI_SHOWUSAGE;
16648 linkset = atoi(a->argv[3]);
16649 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16650 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16651 return CLI_SUCCESS;
16652 }
16653 ss7 = &linksets[linkset - 1].ss7;
16654 if (!ss7->ss7) {
16655 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16656 return CLI_SUCCESS;
16657 }
16658
16659 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16660
16661 return CLI_SUCCESS;
16662 }
16663 #endif
16664
16665 #if defined(HAVE_SS7)
16666 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16667 {
16668 int linkset;
16669
16670 switch (cmd) {
16671 case CLI_INIT:
16672 e->command = "ss7 show channels";
16673 e->usage =
16674 "Usage: ss7 show channels\n"
16675 " Displays SS7 channel information at a glance.\n";
16676 return NULL;
16677 case CLI_GENERATE:
16678 return NULL;
16679 }
16680
16681 if (a->argc != 3)
16682 return CLI_SHOWUSAGE;
16683
16684 sig_ss7_cli_show_channels_header(a->fd);
16685 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16686 if (linksets[linkset].ss7.ss7) {
16687 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16688 }
16689 }
16690 return CLI_SUCCESS;
16691 }
16692 #endif
16693
16694 #if defined(HAVE_SS7)
16695 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16696 {
16697 switch (cmd) {
16698 case CLI_INIT:
16699 e->command = "ss7 show version";
16700 e->usage =
16701 "Usage: ss7 show version\n"
16702 " Show the libss7 version\n";
16703 return NULL;
16704 case CLI_GENERATE:
16705 return NULL;
16706 }
16707
16708 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16709
16710 return CLI_SUCCESS;
16711 }
16712 #endif
16713
16714 #if defined(HAVE_SS7)
16715 static struct ast_cli_entry dahdi_ss7_cli[] = {
16716 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16717 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16718 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16719 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16720 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16721 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16722 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16723 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16724 };
16725 #endif
16726
16727 #if defined(HAVE_PRI)
16728 #if defined(HAVE_PRI_CCSS)
16729
16730
16731
16732
16733
16734
16735
16736
16737
16738
16739
16740
16741
16742
16743
16744
16745
16746 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16747 {
16748 struct dahdi_pvt *pvt;
16749 struct sig_pri_chan *pvt_chan;
16750 int res;
16751
16752 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16753
16754 pvt = chan->tech_pvt;
16755 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16756 pvt_chan = pvt->sig_pvt;
16757 } else {
16758 pvt_chan = NULL;
16759 }
16760 if (!pvt_chan) {
16761 return -1;
16762 }
16763
16764 ast_module_ref(ast_module_info->self);
16765
16766 res = sig_pri_cc_agent_init(agent, pvt_chan);
16767 if (res) {
16768 ast_module_unref(ast_module_info->self);
16769 }
16770 return res;
16771 }
16772 #endif
16773 #endif
16774
16775 #if defined(HAVE_PRI)
16776 #if defined(HAVE_PRI_CCSS)
16777
16778
16779
16780
16781
16782
16783
16784
16785
16786
16787
16788
16789
16790 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16791 {
16792 sig_pri_cc_agent_destructor(agent);
16793
16794 ast_module_unref(ast_module_info->self);
16795 }
16796 #endif
16797 #endif
16798
16799 #if defined(HAVE_PRI)
16800 #if defined(HAVE_PRI_CCSS)
16801 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16802 .type = dahdi_pri_cc_type,
16803 .init = dahdi_pri_cc_agent_init,
16804 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16805 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16806 .respond = sig_pri_cc_agent_req_rsp,
16807 .status_request = sig_pri_cc_agent_status_req,
16808 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16809 .party_b_free = sig_pri_cc_agent_party_b_free,
16810 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16811 .callee_available = sig_pri_cc_agent_callee_available,
16812 .destructor = dahdi_pri_cc_agent_destructor,
16813 };
16814 #endif
16815 #endif
16816
16817 #if defined(HAVE_PRI)
16818 #if defined(HAVE_PRI_CCSS)
16819 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16820 .type = dahdi_pri_cc_type,
16821 .request_cc = sig_pri_cc_monitor_req_cc,
16822 .suspend = sig_pri_cc_monitor_suspend,
16823 .unsuspend = sig_pri_cc_monitor_unsuspend,
16824 .status_response = sig_pri_cc_monitor_status_rsp,
16825 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16826 .destructor = sig_pri_cc_monitor_destructor,
16827 };
16828 #endif
16829 #endif
16830
16831 static int __unload_module(void)
16832 {
16833 struct dahdi_pvt *p;
16834 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16835 int i, j;
16836 #endif
16837
16838 #ifdef HAVE_PRI
16839 for (i = 0; i < NUM_SPANS; i++) {
16840 if (pris[i].pri.master != AST_PTHREADT_NULL) {
16841 pthread_cancel(pris[i].pri.master);
16842 pthread_kill(pris[i].pri.master, SIGURG);
16843 }
16844 }
16845 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16846 ast_unregister_application(dahdi_send_keypad_facility_app);
16847 #ifdef HAVE_PRI_PROG_W_CAUSE
16848 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16849 #endif
16850 #endif
16851 #if defined(HAVE_SS7)
16852 for (i = 0; i < NUM_SPANS; i++) {
16853 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16854 pthread_cancel(linksets[i].ss7.master);
16855 pthread_kill(linksets[i].ss7.master, SIGURG);
16856 }
16857 }
16858 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16859 #endif
16860 #if defined(HAVE_OPENR2)
16861 dahdi_r2_destroy_links();
16862 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16863 ast_unregister_application(dahdi_accept_r2_call_app);
16864 #endif
16865
16866 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16867 ast_manager_unregister("DAHDIDialOffhook");
16868 ast_manager_unregister("DAHDIHangup");
16869 ast_manager_unregister("DAHDITransfer");
16870 ast_manager_unregister("DAHDIDNDoff");
16871 ast_manager_unregister("DAHDIDNDon");
16872 ast_manager_unregister("DAHDIShowChannels");
16873 ast_manager_unregister("DAHDIRestart");
16874 ast_data_unregister(NULL);
16875 ast_channel_unregister(&dahdi_tech);
16876
16877
16878 ast_mutex_lock(&iflock);
16879 for (p = iflist; p; p = p->next) {
16880 if (p->owner)
16881 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16882 }
16883 ast_mutex_unlock(&iflock);
16884
16885 ast_mutex_lock(&monlock);
16886 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16887 pthread_cancel(monitor_thread);
16888 pthread_kill(monitor_thread, SIGURG);
16889 pthread_join(monitor_thread, NULL);
16890 }
16891 monitor_thread = AST_PTHREADT_STOP;
16892 ast_mutex_unlock(&monlock);
16893
16894 destroy_all_channels();
16895
16896 #if defined(HAVE_PRI)
16897 for (i = 0; i < NUM_SPANS; i++) {
16898 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16899 pthread_join(pris[i].pri.master, NULL);
16900 }
16901 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16902 dahdi_close_pri_fd(&(pris[i]), j);
16903 }
16904 sig_pri_stop_pri(&pris[i].pri);
16905 }
16906 #if defined(HAVE_PRI_CCSS)
16907 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16908 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16909 #endif
16910 sig_pri_unload();
16911 #endif
16912
16913 #if defined(HAVE_SS7)
16914 for (i = 0; i < NUM_SPANS; i++) {
16915 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16916 pthread_join(linksets[i].ss7.master, NULL);
16917 }
16918 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16919 dahdi_close_ss7_fd(&(linksets[i]), j);
16920 }
16921 }
16922 #endif
16923 ast_cond_destroy(&ss_thread_complete);
16924 return 0;
16925 }
16926
16927 static int unload_module(void)
16928 {
16929 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16930 int y;
16931 #endif
16932 #ifdef HAVE_PRI
16933 for (y = 0; y < NUM_SPANS; y++)
16934 ast_mutex_destroy(&pris[y].pri.lock);
16935 #endif
16936 #if defined(HAVE_SS7)
16937 for (y = 0; y < NUM_SPANS; y++)
16938 ast_mutex_destroy(&linksets[y].ss7.lock);
16939 #endif
16940 return __unload_module();
16941 }
16942
16943 static void string_replace(char *str, int char1, int char2)
16944 {
16945 for (; *str; str++) {
16946 if (*str == char1) {
16947 *str = char2;
16948 }
16949 }
16950 }
16951
16952 static char *parse_spanchan(char *chanstr, char **subdir)
16953 {
16954 char *p;
16955
16956 if ((p = strrchr(chanstr, '!')) == NULL) {
16957 *subdir = NULL;
16958 return chanstr;
16959 }
16960 *p++ = '\0';
16961 string_replace(chanstr, '!', '/');
16962 *subdir = chanstr;
16963 return p;
16964 }
16965
16966 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16967 {
16968 char *c, *chan;
16969 char *subdir;
16970 int x, start, finish;
16971 struct dahdi_pvt *tmp;
16972
16973 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16974 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16975 return -1;
16976 }
16977
16978 c = ast_strdupa(value);
16979 c = parse_spanchan(c, &subdir);
16980
16981 while ((chan = strsep(&c, ","))) {
16982 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16983
16984 } else if (sscanf(chan, "%30d", &start)) {
16985
16986 finish = start;
16987 } else if (!strcasecmp(chan, "pseudo")) {
16988 finish = start = CHAN_PSEUDO;
16989 if (found_pseudo)
16990 *found_pseudo = 1;
16991 } else {
16992 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16993 return -1;
16994 }
16995 if (finish < start) {
16996 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16997 x = finish;
16998 finish = start;
16999 start = x;
17000 }
17001
17002 for (x = start; x <= finish; x++) {
17003 char fn[PATH_MAX];
17004 int real_channel = x;
17005
17006 if (!ast_strlen_zero(subdir)) {
17007 real_channel = device2chan(subdir, x, fn, sizeof(fn));
17008 if (real_channel < 0) {
17009 if (conf->ignore_failed_channels) {
17010 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17011 subdir, x, real_channel);
17012 continue;
17013 } else {
17014 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17015 subdir, x, real_channel);
17016 return -1;
17017 }
17018 }
17019 }
17020 tmp = mkintf(real_channel, conf, reload);
17021
17022 if (tmp) {
17023 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17024 } else {
17025 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17026 (reload == 1) ? "reconfigure" : "register", value);
17027 return -1;
17028 }
17029 }
17030 }
17031
17032 return 0;
17033 }
17034
17035
17036
17037 #define MAX_CHANLIST_LEN 80
17038
17039 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17040 {
17041 char *parse = ast_strdupa(data);
17042 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17043 unsigned int param_count;
17044 unsigned int x;
17045
17046 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17047 return;
17048
17049 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17050
17051
17052
17053 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17054
17055 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17056 confp->chan.echocancel.head.tap_length = x;
17057 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17058 confp->chan.echocancel.head.tap_length = 128;
17059
17060
17061
17062 for (x = 1; x < param_count; x++) {
17063 struct {
17064 char *name;
17065 char *value;
17066 } param;
17067
17068 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
17069 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
17070 continue;
17071 }
17072
17073 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17074 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
17075 continue;
17076 }
17077
17078 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17079
17080 if (param.value) {
17081 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17082 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
17083 continue;
17084 }
17085 }
17086 confp->chan.echocancel.head.param_count++;
17087 }
17088 }
17089
17090
17091 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
17092
17093 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
17094
17095 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17096 {
17097 struct dahdi_pvt *tmp;
17098 int y;
17099 int found_pseudo = 0;
17100 struct ast_variable *dahdichan = NULL;
17101
17102 for (; v; v = v->next) {
17103 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17104 continue;
17105
17106
17107 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17108 if (options & PROC_DAHDI_OPT_NOCHAN) {
17109 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17110 continue;
17111 }
17112 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17113 if (confp->ignore_failed_channels) {
17114 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17115 continue;
17116 } else {
17117 return -1;
17118 }
17119 }
17120 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17121 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17122 confp->ignore_failed_channels = ast_true(v->value);
17123 } else if (!strcasecmp(v->name, "buffers")) {
17124 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17125 ast_log(LOG_WARNING, "Using default buffer policy.\n");
17126 confp->chan.buf_no = numbufs;
17127 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17128 }
17129 } else if (!strcasecmp(v->name, "faxbuffers")) {
17130 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17131 confp->chan.usefaxbuffers = 1;
17132 }
17133 } else if (!strcasecmp(v->name, "dahdichan")) {
17134
17135 dahdichan = v;
17136 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17137 usedistinctiveringdetection = ast_true(v->value);
17138 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17139 distinctiveringaftercid = ast_true(v->value);
17140 } else if (!strcasecmp(v->name, "dring1context")) {
17141 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17142 } else if (!strcasecmp(v->name, "dring2context")) {
17143 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17144 } else if (!strcasecmp(v->name, "dring3context")) {
17145 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17146 } else if (!strcasecmp(v->name, "dring1range")) {
17147 confp->chan.drings.ringnum[0].range = atoi(v->value);
17148 } else if (!strcasecmp(v->name, "dring2range")) {
17149 confp->chan.drings.ringnum[1].range = atoi(v->value);
17150 } else if (!strcasecmp(v->name, "dring3range")) {
17151 confp->chan.drings.ringnum[2].range = atoi(v->value);
17152 } else if (!strcasecmp(v->name, "dring1")) {
17153 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]);
17154 } else if (!strcasecmp(v->name, "dring2")) {
17155 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]);
17156 } else if (!strcasecmp(v->name, "dring3")) {
17157 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]);
17158 } else if (!strcasecmp(v->name, "usecallerid")) {
17159 confp->chan.use_callerid = ast_true(v->value);
17160 } else if (!strcasecmp(v->name, "cidsignalling")) {
17161 if (!strcasecmp(v->value, "bell"))
17162 confp->chan.cid_signalling = CID_SIG_BELL;
17163 else if (!strcasecmp(v->value, "v23"))
17164 confp->chan.cid_signalling = CID_SIG_V23;
17165 else if (!strcasecmp(v->value, "dtmf"))
17166 confp->chan.cid_signalling = CID_SIG_DTMF;
17167 else if (!strcasecmp(v->value, "smdi"))
17168 confp->chan.cid_signalling = CID_SIG_SMDI;
17169 else if (!strcasecmp(v->value, "v23_jp"))
17170 confp->chan.cid_signalling = CID_SIG_V23_JP;
17171 else if (ast_true(v->value))
17172 confp->chan.cid_signalling = CID_SIG_BELL;
17173 } else if (!strcasecmp(v->name, "cidstart")) {
17174 if (!strcasecmp(v->value, "ring"))
17175 confp->chan.cid_start = CID_START_RING;
17176 else if (!strcasecmp(v->value, "polarity_in"))
17177 confp->chan.cid_start = CID_START_POLARITY_IN;
17178 else if (!strcasecmp(v->value, "polarity"))
17179 confp->chan.cid_start = CID_START_POLARITY;
17180 else if (!strcasecmp(v->value, "dtmf"))
17181 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17182 else if (ast_true(v->value))
17183 confp->chan.cid_start = CID_START_RING;
17184 } else if (!strcasecmp(v->name, "threewaycalling")) {
17185 confp->chan.threewaycalling = ast_true(v->value);
17186 } else if (!strcasecmp(v->name, "cancallforward")) {
17187 confp->chan.cancallforward = ast_true(v->value);
17188 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17189 if (ast_true(v->value))
17190 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17191 else
17192 confp->chan.dtmfrelax = 0;
17193 } else if (!strcasecmp(v->name, "mailbox")) {
17194 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17195 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17196 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17197 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17198 }
17199 } else if (!strcasecmp(v->name, "adsi")) {
17200 confp->chan.adsi = ast_true(v->value);
17201 } else if (!strcasecmp(v->name, "usesmdi")) {
17202 confp->chan.use_smdi = ast_true(v->value);
17203 } else if (!strcasecmp(v->name, "smdiport")) {
17204 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17205 } else if (!strcasecmp(v->name, "transfer")) {
17206 confp->chan.transfer = ast_true(v->value);
17207 } else if (!strcasecmp(v->name, "canpark")) {
17208 confp->chan.canpark = ast_true(v->value);
17209 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17210 confp->chan.echocanbridged = ast_true(v->value);
17211 } else if (!strcasecmp(v->name, "busydetect")) {
17212 confp->chan.busydetect = ast_true(v->value);
17213 } else if (!strcasecmp(v->name, "busycount")) {
17214 confp->chan.busycount = atoi(v->value);
17215 } else if (!strcasecmp(v->name, "busypattern")) {
17216 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17217 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17218 }
17219 } else if (!strcasecmp(v->name, "callprogress")) {
17220 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17221 if (ast_true(v->value))
17222 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17223 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17224 confp->chan.waitfordialtone = atoi(v->value);
17225 } else if (!strcasecmp(v->name, "faxdetect")) {
17226 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17227 if (!strcasecmp(v->value, "incoming")) {
17228 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17229 } else if (!strcasecmp(v->value, "outgoing")) {
17230 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17231 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17232 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17233 } else if (!strcasecmp(v->name, "echocancel")) {
17234 process_echocancel(confp, v->value, v->lineno);
17235 } else if (!strcasecmp(v->name, "echotraining")) {
17236 if (sscanf(v->value, "%30d", &y) == 1) {
17237 if ((y < 10) || (y > 4000)) {
17238 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17239 } else {
17240 confp->chan.echotraining = y;
17241 }
17242 } else if (ast_true(v->value)) {
17243 confp->chan.echotraining = 400;
17244 } else
17245 confp->chan.echotraining = 0;
17246 } else if (!strcasecmp(v->name, "hidecallerid")) {
17247 confp->chan.hidecallerid = ast_true(v->value);
17248 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17249 confp->chan.hidecalleridname = ast_true(v->value);
17250 } else if (!strcasecmp(v->name, "pulsedial")) {
17251 confp->chan.pulse = ast_true(v->value);
17252 } else if (!strcasecmp(v->name, "callreturn")) {
17253 confp->chan.callreturn = ast_true(v->value);
17254 } else if (!strcasecmp(v->name, "callwaiting")) {
17255 confp->chan.callwaiting = ast_true(v->value);
17256 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17257 confp->chan.callwaitingcallerid = ast_true(v->value);
17258 } else if (!strcasecmp(v->name, "context")) {
17259 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17260 } else if (!strcasecmp(v->name, "language")) {
17261 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17262 } else if (!strcasecmp(v->name, "progzone")) {
17263 ast_copy_string(progzone, v->value, sizeof(progzone));
17264 } else if (!strcasecmp(v->name, "mohinterpret")
17265 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17266 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17267 } else if (!strcasecmp(v->name, "mohsuggest")) {
17268 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17269 } else if (!strcasecmp(v->name, "parkinglot")) {
17270 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17271 } else if (!strcasecmp(v->name, "stripmsd")) {
17272 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17273 confp->chan.stripmsd = atoi(v->value);
17274 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17275 numbufs = atoi(v->value);
17276 } else if (!strcasecmp(v->name, "group")) {
17277 confp->chan.group = ast_get_group(v->value);
17278 } else if (!strcasecmp(v->name, "callgroup")) {
17279 if (!strcasecmp(v->value, "none"))
17280 confp->chan.callgroup = 0;
17281 else
17282 confp->chan.callgroup = ast_get_group(v->value);
17283 } else if (!strcasecmp(v->name, "pickupgroup")) {
17284 if (!strcasecmp(v->value, "none"))
17285 confp->chan.pickupgroup = 0;
17286 else
17287 confp->chan.pickupgroup = ast_get_group(v->value);
17288 } else if (!strcasecmp(v->name, "setvar")) {
17289 char *varname = ast_strdupa(v->value), *varval = NULL;
17290 struct ast_variable *tmpvar;
17291 if (varname && (varval = strchr(varname, '='))) {
17292 *varval++ = '\0';
17293 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17294 tmpvar->next = confp->chan.vars;
17295 confp->chan.vars = tmpvar;
17296 }
17297 }
17298 } else if (!strcasecmp(v->name, "immediate")) {
17299 confp->chan.immediate = ast_true(v->value);
17300 } else if (!strcasecmp(v->name, "transfertobusy")) {
17301 confp->chan.transfertobusy = ast_true(v->value);
17302 } else if (!strcasecmp(v->name, "mwimonitor")) {
17303 confp->chan.mwimonitor_neon = 0;
17304 confp->chan.mwimonitor_fsk = 0;
17305 confp->chan.mwimonitor_rpas = 0;
17306 if (strcasestr(v->value, "fsk")) {
17307 confp->chan.mwimonitor_fsk = 1;
17308 }
17309 if (strcasestr(v->value, "rpas")) {
17310 confp->chan.mwimonitor_rpas = 1;
17311 }
17312 if (strcasestr(v->value, "neon")) {
17313 confp->chan.mwimonitor_neon = 1;
17314 }
17315
17316 if (ast_true(v->value)) {
17317 confp->chan.mwimonitor_fsk = 1;
17318 }
17319 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17320 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17321 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17322 }
17323 } else if (!strcasecmp(v->name, "rxgain")) {
17324 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17325 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17326 }
17327 } else if (!strcasecmp(v->name, "txgain")) {
17328 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17329 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17330 }
17331 } else if (!strcasecmp(v->name, "txdrc")) {
17332 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17333 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17334 }
17335 } else if (!strcasecmp(v->name, "rxdrc")) {
17336 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17337 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17338 }
17339 } else if (!strcasecmp(v->name, "tonezone")) {
17340 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17341 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17342 }
17343 } else if (!strcasecmp(v->name, "callerid")) {
17344 if (!strcasecmp(v->value, "asreceived")) {
17345 confp->chan.cid_num[0] = '\0';
17346 confp->chan.cid_name[0] = '\0';
17347 } else {
17348 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17349 }
17350 } else if (!strcasecmp(v->name, "fullname")) {
17351 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17352 } else if (!strcasecmp(v->name, "cid_number")) {
17353 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17354 } else if (!strcasecmp(v->name, "cid_tag")) {
17355 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17356 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17357 confp->chan.dahditrcallerid = ast_true(v->value);
17358 } else if (!strcasecmp(v->name, "restrictcid")) {
17359 confp->chan.restrictcid = ast_true(v->value);
17360 } else if (!strcasecmp(v->name, "usecallingpres")) {
17361 confp->chan.use_callingpres = ast_true(v->value);
17362 } else if (!strcasecmp(v->name, "accountcode")) {
17363 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17364 } else if (!strcasecmp(v->name, "amaflags")) {
17365 y = ast_cdr_amaflags2int(v->value);
17366 if (y < 0)
17367 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17368 else
17369 confp->chan.amaflags = y;
17370 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17371 confp->chan.polarityonanswerdelay = atoi(v->value);
17372 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17373 confp->chan.answeronpolarityswitch = ast_true(v->value);
17374 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17375 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17376 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17377 confp->chan.sendcalleridafter = atoi(v->value);
17378 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17379 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17380 } else if (ast_cc_is_config_param(v->name)) {
17381 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17382 } else if (!strcasecmp(v->name, "mwisendtype")) {
17383 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17384 if (!strcasecmp(v->value, "rpas")) {
17385 mwisend_rpas = 1;
17386 } else {
17387 mwisend_rpas = 0;
17388 }
17389 #else
17390
17391 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17392 if (strcasestr(v->value, "nofsk")) {
17393 confp->chan.mwisend_fsk = 0;
17394 } else {
17395 confp->chan.mwisend_fsk = 1;
17396 }
17397 if (strcasestr(v->value, "rpas")) {
17398 confp->chan.mwisend_rpas = 1;
17399 } else {
17400 confp->chan.mwisend_rpas = 0;
17401 }
17402 if (strcasestr(v->value, "lrev")) {
17403 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17404 }
17405 if (strcasestr(v->value, "hvdc")) {
17406 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17407 }
17408 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17409 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17410 }
17411 #endif
17412 } else if (reload != 1) {
17413 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17414 int orig_radio = confp->chan.radio;
17415 int orig_outsigmod = confp->chan.outsigmod;
17416 int orig_auto = confp->is_sig_auto;
17417
17418 confp->chan.radio = 0;
17419 confp->chan.outsigmod = -1;
17420 confp->is_sig_auto = 0;
17421 if (!strcasecmp(v->value, "em")) {
17422 confp->chan.sig = SIG_EM;
17423 } else if (!strcasecmp(v->value, "em_e1")) {
17424 confp->chan.sig = SIG_EM_E1;
17425 } else if (!strcasecmp(v->value, "em_w")) {
17426 confp->chan.sig = SIG_EMWINK;
17427 } else if (!strcasecmp(v->value, "fxs_ls")) {
17428 confp->chan.sig = SIG_FXSLS;
17429 } else if (!strcasecmp(v->value, "fxs_gs")) {
17430 confp->chan.sig = SIG_FXSGS;
17431 } else if (!strcasecmp(v->value, "fxs_ks")) {
17432 confp->chan.sig = SIG_FXSKS;
17433 } else if (!strcasecmp(v->value, "fxo_ls")) {
17434 confp->chan.sig = SIG_FXOLS;
17435 } else if (!strcasecmp(v->value, "fxo_gs")) {
17436 confp->chan.sig = SIG_FXOGS;
17437 } else if (!strcasecmp(v->value, "fxo_ks")) {
17438 confp->chan.sig = SIG_FXOKS;
17439 } else if (!strcasecmp(v->value, "fxs_rx")) {
17440 confp->chan.sig = SIG_FXSKS;
17441 confp->chan.radio = 1;
17442 } else if (!strcasecmp(v->value, "fxo_rx")) {
17443 confp->chan.sig = SIG_FXOLS;
17444 confp->chan.radio = 1;
17445 } else if (!strcasecmp(v->value, "fxs_tx")) {
17446 confp->chan.sig = SIG_FXSLS;
17447 confp->chan.radio = 1;
17448 } else if (!strcasecmp(v->value, "fxo_tx")) {
17449 confp->chan.sig = SIG_FXOGS;
17450 confp->chan.radio = 1;
17451 } else if (!strcasecmp(v->value, "em_rx")) {
17452 confp->chan.sig = SIG_EM;
17453 confp->chan.radio = 1;
17454 } else if (!strcasecmp(v->value, "em_tx")) {
17455 confp->chan.sig = SIG_EM;
17456 confp->chan.radio = 1;
17457 } else if (!strcasecmp(v->value, "em_rxtx")) {
17458 confp->chan.sig = SIG_EM;
17459 confp->chan.radio = 2;
17460 } else if (!strcasecmp(v->value, "em_txrx")) {
17461 confp->chan.sig = SIG_EM;
17462 confp->chan.radio = 2;
17463 } else if (!strcasecmp(v->value, "sf")) {
17464 confp->chan.sig = SIG_SF;
17465 } else if (!strcasecmp(v->value, "sf_w")) {
17466 confp->chan.sig = SIG_SFWINK;
17467 } else if (!strcasecmp(v->value, "sf_featd")) {
17468 confp->chan.sig = SIG_FEATD;
17469 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17470 confp->chan.sig = SIG_FEATDMF;
17471 } else if (!strcasecmp(v->value, "sf_featb")) {
17472 confp->chan.sig = SIG_SF_FEATB;
17473 } else if (!strcasecmp(v->value, "sf")) {
17474 confp->chan.sig = SIG_SF;
17475 } else if (!strcasecmp(v->value, "sf_rx")) {
17476 confp->chan.sig = SIG_SF;
17477 confp->chan.radio = 1;
17478 } else if (!strcasecmp(v->value, "sf_tx")) {
17479 confp->chan.sig = SIG_SF;
17480 confp->chan.radio = 1;
17481 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17482 confp->chan.sig = SIG_SF;
17483 confp->chan.radio = 2;
17484 } else if (!strcasecmp(v->value, "sf_txrx")) {
17485 confp->chan.sig = SIG_SF;
17486 confp->chan.radio = 2;
17487 } else if (!strcasecmp(v->value, "featd")) {
17488 confp->chan.sig = SIG_FEATD;
17489 } else if (!strcasecmp(v->value, "featdmf")) {
17490 confp->chan.sig = SIG_FEATDMF;
17491 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17492 confp->chan.sig = SIG_FEATDMF_TA;
17493 } else if (!strcasecmp(v->value, "e911")) {
17494 confp->chan.sig = SIG_E911;
17495 } else if (!strcasecmp(v->value, "fgccama")) {
17496 confp->chan.sig = SIG_FGC_CAMA;
17497 } else if (!strcasecmp(v->value, "fgccamamf")) {
17498 confp->chan.sig = SIG_FGC_CAMAMF;
17499 } else if (!strcasecmp(v->value, "featb")) {
17500 confp->chan.sig = SIG_FEATB;
17501 #ifdef HAVE_PRI
17502 } else if (!strcasecmp(v->value, "pri_net")) {
17503 confp->chan.sig = SIG_PRI;
17504 confp->pri.pri.nodetype = PRI_NETWORK;
17505 } else if (!strcasecmp(v->value, "pri_cpe")) {
17506 confp->chan.sig = SIG_PRI;
17507 confp->pri.pri.nodetype = PRI_CPE;
17508 } else if (!strcasecmp(v->value, "bri_cpe")) {
17509 confp->chan.sig = SIG_BRI;
17510 confp->pri.pri.nodetype = PRI_CPE;
17511 } else if (!strcasecmp(v->value, "bri_net")) {
17512 confp->chan.sig = SIG_BRI;
17513 confp->pri.pri.nodetype = PRI_NETWORK;
17514 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17515 confp->chan.sig = SIG_BRI_PTMP;
17516 confp->pri.pri.nodetype = PRI_CPE;
17517 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17518 #if defined(HAVE_PRI_CALL_HOLD)
17519 confp->chan.sig = SIG_BRI_PTMP;
17520 confp->pri.pri.nodetype = PRI_NETWORK;
17521 #else
17522 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17523 #endif
17524 #endif
17525 #if defined(HAVE_SS7)
17526 } else if (!strcasecmp(v->value, "ss7")) {
17527 confp->chan.sig = SIG_SS7;
17528 #endif
17529 #ifdef HAVE_OPENR2
17530 } else if (!strcasecmp(v->value, "mfcr2")) {
17531 confp->chan.sig = SIG_MFCR2;
17532 #endif
17533 } else if (!strcasecmp(v->value, "auto")) {
17534 confp->is_sig_auto = 1;
17535 } else {
17536 confp->chan.outsigmod = orig_outsigmod;
17537 confp->chan.radio = orig_radio;
17538 confp->is_sig_auto = orig_auto;
17539 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17540 }
17541 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17542 if (!strcasecmp(v->value, "em")) {
17543 confp->chan.outsigmod = SIG_EM;
17544 } else if (!strcasecmp(v->value, "em_e1")) {
17545 confp->chan.outsigmod = SIG_EM_E1;
17546 } else if (!strcasecmp(v->value, "em_w")) {
17547 confp->chan.outsigmod = SIG_EMWINK;
17548 } else if (!strcasecmp(v->value, "sf")) {
17549 confp->chan.outsigmod = SIG_SF;
17550 } else if (!strcasecmp(v->value, "sf_w")) {
17551 confp->chan.outsigmod = SIG_SFWINK;
17552 } else if (!strcasecmp(v->value, "sf_featd")) {
17553 confp->chan.outsigmod = SIG_FEATD;
17554 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17555 confp->chan.outsigmod = SIG_FEATDMF;
17556 } else if (!strcasecmp(v->value, "sf_featb")) {
17557 confp->chan.outsigmod = SIG_SF_FEATB;
17558 } else if (!strcasecmp(v->value, "sf")) {
17559 confp->chan.outsigmod = SIG_SF;
17560 } else if (!strcasecmp(v->value, "featd")) {
17561 confp->chan.outsigmod = SIG_FEATD;
17562 } else if (!strcasecmp(v->value, "featdmf")) {
17563 confp->chan.outsigmod = SIG_FEATDMF;
17564 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17565 confp->chan.outsigmod = SIG_FEATDMF_TA;
17566 } else if (!strcasecmp(v->value, "e911")) {
17567 confp->chan.outsigmod = SIG_E911;
17568 } else if (!strcasecmp(v->value, "fgccama")) {
17569 confp->chan.outsigmod = SIG_FGC_CAMA;
17570 } else if (!strcasecmp(v->value, "fgccamamf")) {
17571 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17572 } else if (!strcasecmp(v->value, "featb")) {
17573 confp->chan.outsigmod = SIG_FEATB;
17574 } else {
17575 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17576 }
17577 #ifdef HAVE_PRI
17578 } else if (!strcasecmp(v->name, "pridialplan")) {
17579 if (!strcasecmp(v->value, "national")) {
17580 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17581 } else if (!strcasecmp(v->value, "unknown")) {
17582 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17583 } else if (!strcasecmp(v->value, "private")) {
17584 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17585 } else if (!strcasecmp(v->value, "international")) {
17586 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17587 } else if (!strcasecmp(v->value, "local")) {
17588 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17589 } else if (!strcasecmp(v->value, "dynamic")) {
17590 confp->pri.pri.dialplan = -1;
17591 } else if (!strcasecmp(v->value, "redundant")) {
17592 confp->pri.pri.dialplan = -2;
17593 } else {
17594 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17595 }
17596 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17597 if (!strcasecmp(v->value, "national")) {
17598 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17599 } else if (!strcasecmp(v->value, "unknown")) {
17600 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17601 } else if (!strcasecmp(v->value, "private")) {
17602 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17603 } else if (!strcasecmp(v->value, "international")) {
17604 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17605 } else if (!strcasecmp(v->value, "local")) {
17606 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17607 } else if (!strcasecmp(v->value, "dynamic")) {
17608 confp->pri.pri.localdialplan = -1;
17609 } else if (!strcasecmp(v->value, "redundant")) {
17610 confp->pri.pri.localdialplan = -2;
17611 } else {
17612 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17613 }
17614 } else if (!strcasecmp(v->name, "switchtype")) {
17615 if (!strcasecmp(v->value, "national"))
17616 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17617 else if (!strcasecmp(v->value, "ni1"))
17618 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17619 else if (!strcasecmp(v->value, "dms100"))
17620 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17621 else if (!strcasecmp(v->value, "4ess"))
17622 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17623 else if (!strcasecmp(v->value, "5ess"))
17624 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17625 else if (!strcasecmp(v->value, "euroisdn"))
17626 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17627 else if (!strcasecmp(v->value, "qsig"))
17628 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17629 else {
17630 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17631 return -1;
17632 }
17633 } else if (!strcasecmp(v->name, "msn")) {
17634 ast_copy_string(confp->pri.pri.msn_list, v->value,
17635 sizeof(confp->pri.pri.msn_list));
17636 } else if (!strcasecmp(v->name, "nsf")) {
17637 if (!strcasecmp(v->value, "sdn"))
17638 confp->pri.pri.nsf = PRI_NSF_SDN;
17639 else if (!strcasecmp(v->value, "megacom"))
17640 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17641 else if (!strcasecmp(v->value, "tollfreemegacom"))
17642 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17643 else if (!strcasecmp(v->value, "accunet"))
17644 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17645 else if (!strcasecmp(v->value, "none"))
17646 confp->pri.pri.nsf = PRI_NSF_NONE;
17647 else {
17648 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17649 confp->pri.pri.nsf = PRI_NSF_NONE;
17650 }
17651 } else if (!strcasecmp(v->name, "priindication")) {
17652 if (!strcasecmp(v->value, "outofband"))
17653 confp->chan.priindication_oob = 1;
17654 else if (!strcasecmp(v->value, "inband"))
17655 confp->chan.priindication_oob = 0;
17656 else
17657 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17658 v->value, v->lineno);
17659 } else if (!strcasecmp(v->name, "priexclusive")) {
17660 confp->chan.priexclusive = ast_true(v->value);
17661 } else if (!strcasecmp(v->name, "internationalprefix")) {
17662 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17663 } else if (!strcasecmp(v->name, "nationalprefix")) {
17664 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17665 } else if (!strcasecmp(v->name, "localprefix")) {
17666 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17667 } else if (!strcasecmp(v->name, "privateprefix")) {
17668 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17669 } else if (!strcasecmp(v->name, "unknownprefix")) {
17670 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17671 } else if (!strcasecmp(v->name, "resetinterval")) {
17672 if (!strcasecmp(v->value, "never"))
17673 confp->pri.pri.resetinterval = -1;
17674 else if (atoi(v->value) >= 60)
17675 confp->pri.pri.resetinterval = atoi(v->value);
17676 else
17677 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17678 v->value, v->lineno);
17679 } else if (!strcasecmp(v->name, "minunused")) {
17680 confp->pri.pri.minunused = atoi(v->value);
17681 } else if (!strcasecmp(v->name, "minidle")) {
17682 confp->pri.pri.minidle = atoi(v->value);
17683 } else if (!strcasecmp(v->name, "idleext")) {
17684 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17685 } else if (!strcasecmp(v->name, "idledial")) {
17686 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17687 } else if (!strcasecmp(v->name, "overlapdial")) {
17688 if (ast_true(v->value)) {
17689 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17690 } else if (!strcasecmp(v->value, "incoming")) {
17691 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17692 } else if (!strcasecmp(v->value, "outgoing")) {
17693 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17694 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17695 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17696 } else {
17697 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17698 }
17699 #ifdef HAVE_PRI_PROG_W_CAUSE
17700 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17701 if (!strcasecmp(v->value, "logical")) {
17702 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17703 } else if (!strcasecmp(v->value, "physical")) {
17704 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17705 } else {
17706 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17707 }
17708 #endif
17709 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17710 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17711 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17712 } else if (!strcasecmp(v->name, "service_message_support")) {
17713
17714 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17715 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17716 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17717 confp->pri.pri.enable_service_message_support = 1;
17718 } else {
17719 confp->pri.pri.enable_service_message_support = 0;
17720 }
17721 #endif
17722 #ifdef HAVE_PRI_INBANDDISCONNECT
17723 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17724 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17725 #endif
17726 } else if (!strcasecmp(v->name, "pritimer")) {
17727 #ifdef PRI_GETSET_TIMERS
17728 char tmp[20];
17729 char *timerc;
17730 char *c;
17731 int timer;
17732 int timeridx;
17733
17734 ast_copy_string(tmp, v->value, sizeof(tmp));
17735 c = tmp;
17736 timerc = strsep(&c, ",");
17737 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17738 timeridx = pri_timer2idx(timerc);
17739 timer = atoi(c);
17740 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17741 ast_log(LOG_WARNING,
17742 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17743 v->lineno);
17744 } else if (!timer) {
17745 ast_log(LOG_WARNING,
17746 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17747 c, timerc, v->lineno);
17748 } else {
17749 confp->pri.pri.pritimers[timeridx] = timer;
17750 }
17751 } else {
17752 ast_log(LOG_WARNING,
17753 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17754 v->value, v->lineno);
17755 }
17756 #endif
17757 } else if (!strcasecmp(v->name, "facilityenable")) {
17758 confp->pri.pri.facilityenable = ast_true(v->value);
17759 #if defined(HAVE_PRI_AOC_EVENTS)
17760 } else if (!strcasecmp(v->name, "aoc_enable")) {
17761 confp->pri.pri.aoc_passthrough_flag = 0;
17762 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17763 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17764 }
17765 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17766 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17767 }
17768 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17769 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17770 }
17771 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17772 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17773 #endif
17774 #if defined(HAVE_PRI_CALL_HOLD)
17775 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17776 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17777 #endif
17778 #if defined(HAVE_PRI_CCSS)
17779 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17780 if (!strcasecmp(v->value, "global")) {
17781 confp->pri.pri.cc_ptmp_recall_mode = 0;
17782 } else if (!strcasecmp(v->value, "specific")) {
17783 confp->pri.pri.cc_ptmp_recall_mode = 1;
17784 } else {
17785 confp->pri.pri.cc_ptmp_recall_mode = 1;
17786 }
17787 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17788 if (!strcasecmp(v->value, "release")) {
17789 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17790 } else if (!strcasecmp(v->value, "retain")) {
17791 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17792 } else if (!strcasecmp(v->value, "do_not_care")) {
17793 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17794 } else {
17795 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17796 }
17797 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17798 if (!strcasecmp(v->value, "release")) {
17799 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17800 } else if (!strcasecmp(v->value, "retain")) {
17801 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17802 } else {
17803 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17804 }
17805 #endif
17806 #if defined(HAVE_PRI_CALL_WAITING)
17807 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17808 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17809 if (confp->pri.pri.max_call_waiting_calls < 0) {
17810
17811 confp->pri.pri.max_call_waiting_calls = 0;
17812 }
17813 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17814 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17815 #endif
17816 #if defined(HAVE_PRI_MWI)
17817 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17818 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17819 sizeof(confp->pri.pri.mwi_mailboxes));
17820 #endif
17821 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17822 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17823 } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
17824 confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
17825 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
17826 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
17827 } else if (!strcasecmp(v->name, "layer1_presence")) {
17828 if (!strcasecmp(v->value, "required")) {
17829 confp->pri.pri.layer1_ignored = 0;
17830 } else if (!strcasecmp(v->value, "ignore")) {
17831 confp->pri.pri.layer1_ignored = 1;
17832 } else {
17833
17834 confp->pri.pri.layer1_ignored = 0;
17835 }
17836 #if defined(HAVE_PRI_L2_PERSISTENCE)
17837 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17838 if (!strcasecmp(v->value, "keep_up")) {
17839 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17840 } else if (!strcasecmp(v->value, "leave_down")) {
17841 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17842 } else {
17843 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17844 }
17845 #endif
17846 #endif
17847 #if defined(HAVE_SS7)
17848 } else if (!strcasecmp(v->name, "ss7type")) {
17849 if (!strcasecmp(v->value, "itu")) {
17850 cur_ss7type = SS7_ITU;
17851 } else if (!strcasecmp(v->value, "ansi")) {
17852 cur_ss7type = SS7_ANSI;
17853 } else
17854 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17855 } else if (!strcasecmp(v->name, "linkset")) {
17856 cur_linkset = atoi(v->value);
17857 } else if (!strcasecmp(v->name, "pointcode")) {
17858 cur_pointcode = parse_pointcode(v->value);
17859 } else if (!strcasecmp(v->name, "adjpointcode")) {
17860 cur_adjpointcode = parse_pointcode(v->value);
17861 } else if (!strcasecmp(v->name, "defaultdpc")) {
17862 cur_defaultdpc = parse_pointcode(v->value);
17863 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17864 cur_cicbeginswith = atoi(v->value);
17865 } else if (!strcasecmp(v->name, "networkindicator")) {
17866 if (!strcasecmp(v->value, "national"))
17867 cur_networkindicator = SS7_NI_NAT;
17868 else if (!strcasecmp(v->value, "national_spare"))
17869 cur_networkindicator = SS7_NI_NAT_SPARE;
17870 else if (!strcasecmp(v->value, "international"))
17871 cur_networkindicator = SS7_NI_INT;
17872 else if (!strcasecmp(v->value, "international_spare"))
17873 cur_networkindicator = SS7_NI_INT_SPARE;
17874 else
17875 cur_networkindicator = -1;
17876 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17877 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17878 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17879 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17880 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17881 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17882 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17883 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17884 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17885 if (!strcasecmp(v->value, "national")) {
17886 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17887 } else if (!strcasecmp(v->value, "international")) {
17888 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17889 } else if (!strcasecmp(v->value, "subscriber")) {
17890 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17891 } else if (!strcasecmp(v->value, "unknown")) {
17892 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17893 } else if (!strcasecmp(v->value, "dynamic")) {
17894 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17895 } else {
17896 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17897 }
17898 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17899 if (!strcasecmp(v->value, "national")) {
17900 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17901 } else if (!strcasecmp(v->value, "international")) {
17902 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17903 } else if (!strcasecmp(v->value, "subscriber")) {
17904 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17905 } else if (!strcasecmp(v->value, "unknown")) {
17906 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17907 } else if (!strcasecmp(v->value, "dynamic")) {
17908 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17909 } else {
17910 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17911 }
17912 } else if (!strcasecmp(v->name, "sigchan")) {
17913 int sigchan, res;
17914 sigchan = atoi(v->value);
17915 res = linkset_addsigchan(sigchan);
17916 if (res < 0)
17917 return -1;
17918
17919 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17920 struct dahdi_ss7 *link;
17921 link = ss7_resolve_linkset(cur_linkset);
17922 if (!link) {
17923 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17924 return -1;
17925 }
17926 if (ast_true(v->value))
17927 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17928 #endif
17929 #ifdef HAVE_OPENR2
17930 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17931 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17932 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);
17933 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17934 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17935 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17936 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17937 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17938 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17939 confp->mfcr2.variant = OR2_VAR_ITU;
17940 }
17941 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17942 confp->mfcr2.mfback_timeout = atoi(v->value);
17943 if (!confp->mfcr2.mfback_timeout) {
17944 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17945 confp->mfcr2.mfback_timeout = -1;
17946 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17947 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17948 }
17949 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17950 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17951 if (confp->mfcr2.metering_pulse_timeout > 500) {
17952 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17953 }
17954 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17955 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17956 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17957 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17958 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17959 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17960 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17961 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17962 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17963 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17964 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17965 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17966 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17967 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17968 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17969 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17970 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17971 #endif
17972 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17973 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17974 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17975 confp->mfcr2.max_ani = atoi(v->value);
17976 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17977 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17978 }
17979 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17980 confp->mfcr2.max_dnis = atoi(v->value);
17981 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17982 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17983 }
17984 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17985 confp->mfcr2.category = openr2_proto_get_category(v->value);
17986 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17987 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17988 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17989 v->value, v->lineno);
17990 }
17991 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17992 openr2_log_level_t tmplevel;
17993 char *clevel;
17994 char *logval = ast_strdupa(v->value);
17995 while (logval) {
17996 clevel = strsep(&logval,",");
17997 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17998 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17999 continue;
18000 }
18001 confp->mfcr2.loglevel |= tmplevel;
18002 }
18003 #endif
18004 } else if (!strcasecmp(v->name, "cadence")) {
18005
18006 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18007 int i;
18008 struct dahdi_ring_cadence new_cadence;
18009 int cid_location = -1;
18010 int firstcadencepos = 0;
18011 char original_args[80];
18012 int cadence_is_ok = 1;
18013
18014 ast_copy_string(original_args, v->value, sizeof(original_args));
18015
18016 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]);
18017
18018
18019 if (element_count % 2 == 1) {
18020 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18021 cadence_is_ok = 0;
18022 }
18023
18024
18025 for (i = 0; i < element_count; i++) {
18026 if (c[i] == 0) {
18027 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18028 cadence_is_ok = 0;
18029 break;
18030 } else if (c[i] < 0) {
18031 if (i % 2 == 1) {
18032
18033 if (cid_location == -1) {
18034 cid_location = i;
18035 c[i] *= -1;
18036 } else {
18037 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18038 cadence_is_ok = 0;
18039 break;
18040 }
18041 } else {
18042 if (firstcadencepos == 0) {
18043 firstcadencepos = i;
18044
18045 } else {
18046 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18047 cadence_is_ok = 0;
18048 break;
18049 }
18050 }
18051 }
18052 }
18053
18054
18055 for (i = 0; i < 16; i++) {
18056 new_cadence.ringcadence[i] = c[i];
18057 }
18058
18059 if (cadence_is_ok) {
18060
18061 if (element_count < 2) {
18062 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18063 } else {
18064 if (cid_location == -1) {
18065
18066 cid_location = 1;
18067 } else {
18068
18069 cid_location = (cid_location + 1) / 2;
18070 }
18071
18072 if (!user_has_defined_cadences++)
18073
18074 num_cadence = 0;
18075 if ((num_cadence+1) >= NUM_CADENCE_MAX)
18076 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18077 else {
18078 cadences[num_cadence] = new_cadence;
18079 cidrings[num_cadence++] = cid_location;
18080 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18081 }
18082 }
18083 }
18084 } else if (!strcasecmp(v->name, "ringtimeout")) {
18085 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18086 } else if (!strcasecmp(v->name, "prewink")) {
18087 confp->timing.prewinktime = atoi(v->value);
18088 } else if (!strcasecmp(v->name, "preflash")) {
18089 confp->timing.preflashtime = atoi(v->value);
18090 } else if (!strcasecmp(v->name, "wink")) {
18091 confp->timing.winktime = atoi(v->value);
18092 } else if (!strcasecmp(v->name, "flash")) {
18093 confp->timing.flashtime = atoi(v->value);
18094 } else if (!strcasecmp(v->name, "start")) {
18095 confp->timing.starttime = atoi(v->value);
18096 } else if (!strcasecmp(v->name, "rxwink")) {
18097 confp->timing.rxwinktime = atoi(v->value);
18098 } else if (!strcasecmp(v->name, "rxflash")) {
18099 confp->timing.rxflashtime = atoi(v->value);
18100 } else if (!strcasecmp(v->name, "debounce")) {
18101 confp->timing.debouncetime = atoi(v->value);
18102 } else if (!strcasecmp(v->name, "toneduration")) {
18103 int toneduration;
18104 int ctlfd;
18105 int res;
18106 struct dahdi_dialparams dps;
18107
18108 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18109 if (ctlfd == -1) {
18110 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18111 return -1;
18112 }
18113
18114 toneduration = atoi(v->value);
18115 if (toneduration > -1) {
18116 memset(&dps, 0, sizeof(dps));
18117
18118 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18119 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18120 if (res < 0) {
18121 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18122 close(ctlfd);
18123 return -1;
18124 }
18125 }
18126 close(ctlfd);
18127 } else if (!strcasecmp(v->name, "defaultcic")) {
18128 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18129 } else if (!strcasecmp(v->name, "defaultozz")) {
18130 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18131 } else if (!strcasecmp(v->name, "mwilevel")) {
18132 mwilevel = atoi(v->value);
18133 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18134 dtmfcid_level = atoi(v->value);
18135 } else if (!strcasecmp(v->name, "reportalarms")) {
18136 if (!strcasecmp(v->value, "all"))
18137 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18138 if (!strcasecmp(v->value, "none"))
18139 report_alarms = 0;
18140 else if (!strcasecmp(v->value, "channels"))
18141 report_alarms = REPORT_CHANNEL_ALARMS;
18142 else if (!strcasecmp(v->value, "spans"))
18143 report_alarms = REPORT_SPAN_ALARMS;
18144 }
18145 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18146 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18147 }
18148
18149
18150 if (confp->chan.vars) {
18151 ast_variables_destroy(confp->chan.vars);
18152 confp->chan.vars = NULL;
18153 }
18154
18155 if (dahdichan) {
18156
18157 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18158 &found_pseudo)) {
18159 if (confp->ignore_failed_channels) {
18160 ast_log(LOG_WARNING,
18161 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18162 dahdichan->value);
18163 } else {
18164 return -1;
18165 }
18166 }
18167 }
18168
18169
18170 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18171 if (!tmp->destroy && tmp->span != y) {
18172 tmp->manages_span_alarms = 1;
18173 y = tmp->span;
18174 } else {
18175 tmp->manages_span_alarms = 0;
18176 }
18177 }
18178
18179
18180
18181 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18182
18183
18184
18185
18186 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18187
18188 if (conf.chan.cc_params) {
18189 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18190 } else {
18191 tmp = NULL;
18192 }
18193 if (tmp) {
18194 ast_verb(3, "Automatically generated pseudo channel\n");
18195 } else {
18196 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18197 }
18198 ast_cc_config_params_destroy(conf.chan.cc_params);
18199 }
18200 return 0;
18201 }
18202
18203
18204
18205
18206
18207
18208
18209
18210
18211
18212
18213 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18214 {
18215 struct ast_cc_config_params *cc_params;
18216
18217 cc_params = dest->chan.cc_params;
18218 *dest = *src;
18219 dest->chan.cc_params = cc_params;
18220 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18221 }
18222
18223
18224
18225
18226
18227
18228
18229
18230
18231
18232
18233
18234
18235 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18236 {
18237 struct ast_config *cfg;
18238 struct ast_config *ucfg;
18239 struct ast_variable *v;
18240 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18241 const char *chans;
18242 const char *cat;
18243 int res;
18244
18245 #ifdef HAVE_PRI
18246 char *c;
18247 int spanno;
18248 int i;
18249 int logicalspan;
18250 int trunkgroup;
18251 int dchannels[SIG_PRI_NUM_DCHANS];
18252 #endif
18253 int have_cfg_now;
18254 static int had_cfg_before = 1;
18255
18256 cfg = ast_config_load(config, config_flags);
18257 have_cfg_now = !!cfg;
18258 if (!cfg) {
18259
18260 if (had_cfg_before) {
18261 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18262 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18263 }
18264 cfg = ast_config_new();
18265 if (!cfg) {
18266 return 0;
18267 }
18268 ucfg = ast_config_load("users.conf", config_flags);
18269 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18270 ast_config_destroy(cfg);
18271 return 0;
18272 }
18273 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18274 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18275 ast_config_destroy(cfg);
18276 return 0;
18277 }
18278 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18279 ucfg = ast_config_load("users.conf", config_flags);
18280 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18281 return 0;
18282 }
18283 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18284 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18285 return 0;
18286 }
18287 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18288 cfg = ast_config_load(config, config_flags);
18289 have_cfg_now = !!cfg;
18290 if (!cfg) {
18291 if (had_cfg_before) {
18292
18293 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18294 ast_config_destroy(ucfg);
18295 return 0;
18296 }
18297 cfg = ast_config_new();
18298 if (!cfg) {
18299 ast_config_destroy(ucfg);
18300 return 0;
18301 }
18302 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18303 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18304 ast_config_destroy(ucfg);
18305 return 0;
18306 }
18307 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18308 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18309 return 0;
18310 } else {
18311 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18312 ucfg = ast_config_load("users.conf", config_flags);
18313 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18314 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18315 ast_config_destroy(cfg);
18316 return 0;
18317 }
18318 }
18319 had_cfg_before = have_cfg_now;
18320
18321
18322 ast_mutex_lock(&iflock);
18323 #ifdef HAVE_PRI
18324 if (reload != 1) {
18325
18326 v = ast_variable_browse(cfg, "trunkgroups");
18327 while (v) {
18328 if (!strcasecmp(v->name, "trunkgroup")) {
18329 trunkgroup = atoi(v->value);
18330 if (trunkgroup > 0) {
18331 if ((c = strchr(v->value, ','))) {
18332 i = 0;
18333 memset(dchannels, 0, sizeof(dchannels));
18334 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18335 dchannels[i] = atoi(c + 1);
18336 if (dchannels[i] < 0) {
18337 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);
18338 } else
18339 i++;
18340 c = strchr(c + 1, ',');
18341 }
18342 if (i) {
18343 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18344 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);
18345 } else
18346 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");
18347 } else
18348 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18349 } else
18350 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18351 } else
18352 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18353 } else if (!strcasecmp(v->name, "spanmap")) {
18354 spanno = atoi(v->value);
18355 if (spanno > 0) {
18356 if ((c = strchr(v->value, ','))) {
18357 trunkgroup = atoi(c + 1);
18358 if (trunkgroup > 0) {
18359 if ((c = strchr(c + 1, ',')))
18360 logicalspan = atoi(c + 1);
18361 else
18362 logicalspan = 0;
18363 if (logicalspan >= 0) {
18364 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18365 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18366 } else
18367 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18368 } else
18369 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);
18370 } else
18371 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18372 } else
18373 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18374 } else
18375 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18376 } else {
18377 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18378 }
18379 v = v->next;
18380 }
18381 }
18382 #endif
18383
18384
18385 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18386
18387 mwimonitornotify[0] = '\0';
18388
18389 v = ast_variable_browse(cfg, "channels");
18390 if ((res = process_dahdi(base_conf,
18391 "" ,
18392 v, reload, 0))) {
18393 ast_mutex_unlock(&iflock);
18394 ast_config_destroy(cfg);
18395 if (ucfg) {
18396 ast_config_destroy(ucfg);
18397 }
18398 return res;
18399 }
18400
18401
18402 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18403
18404
18405
18406 if (!strcasecmp(cat, "general") ||
18407 !strcasecmp(cat, "trunkgroups") ||
18408 !strcasecmp(cat, "globals") ||
18409 !strcasecmp(cat, "channels")) {
18410 continue;
18411 }
18412
18413 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18414 if (ast_strlen_zero(chans)) {
18415
18416 continue;
18417 }
18418
18419
18420 deep_copy_dahdi_chan_conf(conf, base_conf);
18421
18422 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18423 ast_mutex_unlock(&iflock);
18424 ast_config_destroy(cfg);
18425 if (ucfg) {
18426 ast_config_destroy(ucfg);
18427 }
18428 return res;
18429 }
18430 }
18431
18432 ast_config_destroy(cfg);
18433
18434 if (ucfg) {
18435
18436 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18437 process_dahdi(base_conf,
18438 "" ,
18439 ast_variable_browse(ucfg, "general"), 1, 0);
18440
18441 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18442 if (!strcasecmp(cat, "general")) {
18443 continue;
18444 }
18445
18446 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18447 if (ast_strlen_zero(chans)) {
18448
18449 continue;
18450 }
18451
18452
18453 deep_copy_dahdi_chan_conf(conf, base_conf);
18454
18455 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18456 ast_config_destroy(ucfg);
18457 ast_mutex_unlock(&iflock);
18458 return res;
18459 }
18460 }
18461 ast_config_destroy(ucfg);
18462 }
18463 ast_mutex_unlock(&iflock);
18464
18465 #ifdef HAVE_PRI
18466 if (reload != 1) {
18467 int x;
18468 for (x = 0; x < NUM_SPANS; x++) {
18469 if (pris[x].pri.pvts[0]) {
18470 prepare_pri(pris + x);
18471 if (sig_pri_start_pri(&pris[x].pri)) {
18472 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18473 return -1;
18474 } else
18475 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18476 }
18477 }
18478 }
18479 #endif
18480 #if defined(HAVE_SS7)
18481 if (reload != 1) {
18482 int x;
18483 for (x = 0; x < NUM_SPANS; x++) {
18484 if (linksets[x].ss7.ss7) {
18485 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18486 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18487 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18488 return -1;
18489 } else
18490 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18491 }
18492 }
18493 }
18494 #endif
18495 #ifdef HAVE_OPENR2
18496 if (reload != 1) {
18497 int x;
18498 for (x = 0; x < r2links_count; x++) {
18499 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18500 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18501 return -1;
18502 } else {
18503 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18504 }
18505 }
18506 }
18507 #endif
18508
18509 restart_monitor();
18510 return 0;
18511 }
18512
18513
18514
18515
18516
18517
18518
18519
18520
18521
18522 static int setup_dahdi(int reload)
18523 {
18524 int res;
18525 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18526 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18527 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18528
18529 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18530 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18531 } else {
18532 res = -1;
18533 }
18534 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18535 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18536 ast_cc_config_params_destroy(conf.chan.cc_params);
18537
18538 return res;
18539 }
18540
18541
18542
18543
18544
18545
18546
18547
18548 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18549 struct ast_data *data_root)
18550 {
18551 int ctl, res, span;
18552 struct ast_data *data_span, *data_alarms;
18553 struct dahdi_spaninfo s;
18554
18555 ctl = open("/dev/dahdi/ctl", O_RDWR);
18556 if (ctl < 0) {
18557 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18558 return -1;
18559 }
18560 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18561 s.spanno = span;
18562 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18563 if (res) {
18564 continue;
18565 }
18566
18567 data_span = ast_data_add_node(data_root, "span");
18568 if (!data_span) {
18569 continue;
18570 }
18571 ast_data_add_str(data_span, "description", s.desc);
18572
18573
18574 data_alarms = ast_data_add_node(data_span, "alarms");
18575 if (!data_alarms) {
18576 continue;
18577 }
18578
18579 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18580 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18581 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18582 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18583 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18584 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18585
18586 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18587 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18588 ast_data_add_int(data_span, "crc4", s.crc4count);
18589 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18590 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18591 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18592 "CAS");
18593 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18594 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18595 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18596 "Unknown");
18597 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18598 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18599 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18600 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18601
18602
18603 if (!ast_data_search_match(search, data_span)) {
18604 ast_data_remove_node(data_root, data_span);
18605 }
18606 }
18607 close(ctl);
18608
18609 return 0;
18610 }
18611
18612
18613
18614
18615
18616
18617
18618
18619 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18620 struct ast_data *data_root)
18621 {
18622 struct dahdi_pvt *tmp;
18623 struct ast_data *data_channel;
18624
18625 ast_mutex_lock(&iflock);
18626 for (tmp = iflist; tmp; tmp = tmp->next) {
18627 data_channel = ast_data_add_node(data_root, "channel");
18628 if (!data_channel) {
18629 continue;
18630 }
18631
18632 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18633
18634
18635 if (!ast_data_search_match(search, data_channel)) {
18636 ast_data_remove_node(data_root, data_channel);
18637 }
18638 }
18639 ast_mutex_unlock(&iflock);
18640
18641 return 0;
18642 }
18643
18644
18645
18646
18647
18648
18649
18650
18651 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18652 struct ast_data *data_root)
18653 {
18654 int pseudo_fd = -1;
18655 struct dahdi_versioninfo vi = {
18656 .version = "Unknown",
18657 .echo_canceller = "Unknown"
18658 };
18659
18660 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18661 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18662 return -1;
18663 }
18664
18665 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18666 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18667 }
18668
18669 close(pseudo_fd);
18670
18671 ast_data_add_str(data_root, "value", vi.version);
18672 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18673
18674 return 0;
18675 }
18676
18677 static const struct ast_data_handler dahdi_status_data_provider = {
18678 .version = AST_DATA_HANDLER_VERSION,
18679 .get = dahdi_status_data_provider_get
18680 };
18681
18682 static const struct ast_data_handler dahdi_channels_data_provider = {
18683 .version = AST_DATA_HANDLER_VERSION,
18684 .get = dahdi_channels_data_provider_get
18685 };
18686
18687 static const struct ast_data_handler dahdi_version_data_provider = {
18688 .version = AST_DATA_HANDLER_VERSION,
18689 .get = dahdi_version_data_provider_get
18690 };
18691
18692 static const struct ast_data_entry dahdi_data_providers[] = {
18693 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18694 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18695 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18696 };
18697
18698 static int load_module(void)
18699 {
18700 int res;
18701 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18702 int y;
18703 #endif
18704
18705 #ifdef HAVE_PRI
18706 memset(pris, 0, sizeof(pris));
18707 for (y = 0; y < NUM_SPANS; y++) {
18708 sig_pri_init_pri(&pris[y].pri);
18709 }
18710 pri_set_error(dahdi_pri_error);
18711 pri_set_message(dahdi_pri_message);
18712 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18713 #ifdef HAVE_PRI_PROG_W_CAUSE
18714 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18715 #endif
18716 #if defined(HAVE_PRI_CCSS)
18717 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18718 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18719 __unload_module();
18720 return AST_MODULE_LOAD_FAILURE;
18721 }
18722 #endif
18723 if (sig_pri_load(
18724 #if defined(HAVE_PRI_CCSS)
18725 dahdi_pri_cc_type
18726 #else
18727 NULL
18728 #endif
18729 )) {
18730 __unload_module();
18731 return AST_MODULE_LOAD_FAILURE;
18732 }
18733 #endif
18734 #if defined(HAVE_SS7)
18735 memset(linksets, 0, sizeof(linksets));
18736 for (y = 0; y < NUM_SPANS; y++) {
18737 sig_ss7_init_linkset(&linksets[y].ss7);
18738 }
18739 ss7_set_error(dahdi_ss7_error);
18740 ss7_set_message(dahdi_ss7_message);
18741 #endif
18742 res = setup_dahdi(0);
18743
18744 if (res)
18745 return AST_MODULE_LOAD_DECLINE;
18746 if (ast_channel_register(&dahdi_tech)) {
18747 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18748 __unload_module();
18749 return AST_MODULE_LOAD_FAILURE;
18750 }
18751 #ifdef HAVE_PRI
18752 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18753 #endif
18754 #if defined(HAVE_SS7)
18755 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18756 #endif
18757 #ifdef HAVE_OPENR2
18758 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18759 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18760 #endif
18761
18762 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18763
18764 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18765 memset(round_robin, 0, sizeof(round_robin));
18766 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18767 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18768 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18769 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18770 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18771 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18772 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18773
18774 ast_cond_init(&ss_thread_complete, NULL);
18775
18776 return res;
18777 }
18778
18779 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18780 {
18781 #define END_SILENCE_LEN 400
18782 #define HEADER_MS 50
18783 #define TRAILER_MS 5
18784 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18785 #define ASCII_BYTES_PER_CHAR 80
18786
18787 unsigned char *buf,*mybuf;
18788 struct dahdi_pvt *p = c->tech_pvt;
18789 struct pollfd fds[1];
18790 int size,res,fd,len,x;
18791 int bytes=0;
18792
18793 float cr = 1.0;
18794 float ci = 0.0;
18795 float scont = 0.0;
18796 int idx;
18797
18798 idx = dahdi_get_index(c, p, 0);
18799 if (idx < 0) {
18800 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18801 return -1;
18802 }
18803 if (!text[0]) return(0);
18804 if ((!p->tdd) && (!p->mate)) return(0);
18805 if (p->mate)
18806 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18807 else
18808 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18809 if (!buf)
18810 return -1;
18811 mybuf = buf;
18812 if (p->mate) {
18813 int codec = AST_LAW(p);
18814 for (x = 0; x < HEADER_MS; x++) {
18815 PUT_CLID_MARKMS;
18816 }
18817
18818 for (x = 0; text[x]; x++) {
18819 PUT_CLID(text[x]);
18820 }
18821 for (x = 0; x < TRAILER_MS; x++) {
18822 PUT_CLID_MARKMS;
18823 }
18824 len = bytes;
18825 buf = mybuf;
18826 } else {
18827 len = tdd_generate(p->tdd, buf, text);
18828 if (len < 1) {
18829 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18830 ast_free(mybuf);
18831 return -1;
18832 }
18833 }
18834 memset(buf + len, 0x7f, END_SILENCE_LEN);
18835 len += END_SILENCE_LEN;
18836 fd = p->subs[idx].dfd;
18837 while (len) {
18838 if (ast_check_hangup(c)) {
18839 ast_free(mybuf);
18840 return -1;
18841 }
18842 size = len;
18843 if (size > READ_SIZE)
18844 size = READ_SIZE;
18845 fds[0].fd = fd;
18846 fds[0].events = POLLOUT | POLLPRI;
18847 fds[0].revents = 0;
18848 res = poll(fds, 1, -1);
18849 if (!res) {
18850 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18851 continue;
18852 }
18853
18854 if (fds[0].revents & POLLPRI) {
18855 ast_free(mybuf);
18856 return -1;
18857 }
18858 if (!(fds[0].revents & POLLOUT)) {
18859 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18860 continue;
18861 }
18862 res = write(fd, buf, size);
18863 if (res != size) {
18864 if (res == -1) {
18865 ast_free(mybuf);
18866 return -1;
18867 }
18868 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18869 break;
18870 }
18871 len -= size;
18872 buf += size;
18873 }
18874 ast_free(mybuf);
18875 return(0);
18876 }
18877
18878
18879 static int reload(void)
18880 {
18881 int res = 0;
18882
18883 res = setup_dahdi(1);
18884 if (res) {
18885 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18886 return -1;
18887 }
18888 return 0;
18889 }
18890
18891
18892
18893
18894
18895 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18896 .load = load_module,
18897 .unload = unload_module,
18898 .reload = reload,
18899 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18900 .nonoptreq = "res_smdi",
18901 );