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: 407817 $")
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_proceeding = 1,
01370
01371 #if defined(HAVE_PRI_CCSS)
01372 .cc_ptmp_recall_mode = 1,
01373 .cc_qsig_signaling_link_req = 1,
01374 .cc_qsig_signaling_link_rsp = 1,
01375 #endif
01376
01377 .minunused = 2,
01378 .idleext = "",
01379 .idledial = "",
01380 .internationalprefix = "",
01381 .nationalprefix = "",
01382 .localprefix = "",
01383 .privateprefix = "",
01384 .unknownprefix = "",
01385 .resetinterval = -1,
01386 },
01387 #endif
01388 #if defined(HAVE_SS7)
01389 .ss7.ss7 = {
01390 .called_nai = SS7_NAI_NATIONAL,
01391 .calling_nai = SS7_NAI_NATIONAL,
01392 .internationalprefix = "",
01393 .nationalprefix = "",
01394 .subscriberprefix = "",
01395 .unknownprefix = ""
01396 },
01397 #endif
01398 #ifdef HAVE_OPENR2
01399 .mfcr2 = {
01400 .variant = OR2_VAR_ITU,
01401 .mfback_timeout = -1,
01402 .metering_pulse_timeout = -1,
01403 .max_ani = 10,
01404 .max_dnis = 4,
01405 .get_ani_first = -1,
01406 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01407 .skip_category_request = -1,
01408 #endif
01409 .call_files = 0,
01410 .allow_collect_calls = 0,
01411 .charge_calls = 1,
01412 .accept_on_offer = 1,
01413 .forced_release = 0,
01414 .double_answer = 0,
01415 .immediate_accept = -1,
01416 .logdir = "",
01417 .r2proto_file = "",
01418 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01419 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01420 },
01421 #endif
01422 .chan = {
01423 .context = "default",
01424 .cid_num = "",
01425 .cid_name = "",
01426 .cid_tag = "",
01427 .mohinterpret = "default",
01428 .mohsuggest = "",
01429 .parkinglot = "",
01430 .transfertobusy = 1,
01431
01432 .cid_signalling = CID_SIG_BELL,
01433 .cid_start = CID_START_RING,
01434 .dahditrcallerid = 0,
01435 .use_callerid = 1,
01436 .sig = -1,
01437 .outsigmod = -1,
01438
01439 .cid_rxgain = +5.0,
01440
01441 .tonezone = -1,
01442
01443 .echocancel.head.tap_length = 1,
01444
01445 .busycount = 3,
01446
01447 .accountcode = "",
01448
01449 .mailbox = "",
01450
01451 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01452 .mwisend_fsk = 1,
01453 #endif
01454 .polarityonanswerdelay = 600,
01455
01456 .sendcalleridafter = DEFAULT_CIDRINGS,
01457
01458 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01459 .buf_no = numbufs,
01460 .usefaxbuffers = 0,
01461 .cc_params = ast_cc_config_params_init(),
01462 },
01463 .timing = {
01464 .prewinktime = -1,
01465 .preflashtime = -1,
01466 .winktime = -1,
01467 .flashtime = -1,
01468 .starttime = -1,
01469 .rxwinktime = -1,
01470 .rxflashtime = -1,
01471 .debouncetime = -1
01472 },
01473 .is_sig_auto = 1,
01474 .smdi_port = "/dev/ttyS0",
01475 };
01476
01477 return conf;
01478 }
01479
01480
01481 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01482 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01483 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01485 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01486 static int dahdi_hangup(struct ast_channel *ast);
01487 static int dahdi_answer(struct ast_channel *ast);
01488 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01489 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01490 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01491 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01492 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01493 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01494 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01495 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01496 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01497 static int dahdi_devicestate(void *data);
01498 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01499
01500 static const struct ast_channel_tech dahdi_tech = {
01501 .type = "DAHDI",
01502 .description = tdesc,
01503 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01504 .requester = dahdi_request,
01505 .send_digit_begin = dahdi_digit_begin,
01506 .send_digit_end = dahdi_digit_end,
01507 .send_text = dahdi_sendtext,
01508 .call = dahdi_call,
01509 .hangup = dahdi_hangup,
01510 .answer = dahdi_answer,
01511 .read = dahdi_read,
01512 .write = dahdi_write,
01513 .bridge = dahdi_bridge,
01514 .exception = dahdi_exception,
01515 .indicate = dahdi_indicate,
01516 .fixup = dahdi_fixup,
01517 .setoption = dahdi_setoption,
01518 .queryoption = dahdi_queryoption,
01519 .func_channel_read = dahdi_func_read,
01520 .func_channel_write = dahdi_func_write,
01521 .devicestate = dahdi_devicestate,
01522 .cc_callback = dahdi_cc_callback,
01523 };
01524
01525 #define GET_CHANNEL(p) ((p)->channel)
01526
01527 #define SIG_PRI_LIB_HANDLE_CASES \
01528 SIG_PRI: \
01529 case SIG_BRI: \
01530 case SIG_BRI_PTMP
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541 static inline int dahdi_sig_pri_lib_handles(int signaling)
01542 {
01543 int handles;
01544
01545 switch (signaling) {
01546 case SIG_PRI_LIB_HANDLE_CASES:
01547 handles = 1;
01548 break;
01549 default:
01550 handles = 0;
01551 break;
01552 }
01553
01554 return handles;
01555 }
01556
01557 static int analog_lib_handles(int signalling, int radio, int oprmode)
01558 {
01559 switch (signalling) {
01560 case SIG_FXOLS:
01561 case SIG_FXOGS:
01562 case SIG_FXOKS:
01563 case SIG_FXSLS:
01564 case SIG_FXSGS:
01565 case SIG_FXSKS:
01566 case SIG_EMWINK:
01567 case SIG_EM:
01568 case SIG_EM_E1:
01569 case SIG_FEATD:
01570 case SIG_FEATDMF:
01571 case SIG_E911:
01572 case SIG_FGC_CAMA:
01573 case SIG_FGC_CAMAMF:
01574 case SIG_FEATB:
01575 case SIG_SFWINK:
01576 case SIG_SF:
01577 case SIG_SF_FEATD:
01578 case SIG_SF_FEATDMF:
01579 case SIG_FEATDMF_TA:
01580 case SIG_SF_FEATB:
01581 break;
01582 default:
01583
01584 return 0;
01585 }
01586
01587 if (radio) {
01588 return 0;
01589 }
01590
01591 if (oprmode) {
01592 return 0;
01593 }
01594
01595 return 1;
01596 }
01597
01598 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01599 {
01600 switch (sig) {
01601 case SIG_FXOLS:
01602 return ANALOG_SIG_FXOLS;
01603 case SIG_FXOGS:
01604 return ANALOG_SIG_FXOGS;
01605 case SIG_FXOKS:
01606 return ANALOG_SIG_FXOKS;
01607 case SIG_FXSLS:
01608 return ANALOG_SIG_FXSLS;
01609 case SIG_FXSGS:
01610 return ANALOG_SIG_FXSGS;
01611 case SIG_FXSKS:
01612 return ANALOG_SIG_FXSKS;
01613 case SIG_EMWINK:
01614 return ANALOG_SIG_EMWINK;
01615 case SIG_EM:
01616 return ANALOG_SIG_EM;
01617 case SIG_EM_E1:
01618 return ANALOG_SIG_EM_E1;
01619 case SIG_FEATD:
01620 return ANALOG_SIG_FEATD;
01621 case SIG_FEATDMF:
01622 return ANALOG_SIG_FEATDMF;
01623 case SIG_E911:
01624 return SIG_E911;
01625 case SIG_FGC_CAMA:
01626 return ANALOG_SIG_FGC_CAMA;
01627 case SIG_FGC_CAMAMF:
01628 return ANALOG_SIG_FGC_CAMAMF;
01629 case SIG_FEATB:
01630 return ANALOG_SIG_FEATB;
01631 case SIG_SFWINK:
01632 return ANALOG_SIG_SFWINK;
01633 case SIG_SF:
01634 return ANALOG_SIG_SF;
01635 case SIG_SF_FEATD:
01636 return ANALOG_SIG_SF_FEATD;
01637 case SIG_SF_FEATDMF:
01638 return ANALOG_SIG_SF_FEATDMF;
01639 case SIG_FEATDMF_TA:
01640 return ANALOG_SIG_FEATDMF_TA;
01641 case SIG_SF_FEATB:
01642 return ANALOG_SIG_FEATB;
01643 default:
01644 return -1;
01645 }
01646 }
01647
01648
01649 static int analog_tone_to_dahditone(enum analog_tone tone)
01650 {
01651 switch (tone) {
01652 case ANALOG_TONE_RINGTONE:
01653 return DAHDI_TONE_RINGTONE;
01654 case ANALOG_TONE_STUTTER:
01655 return DAHDI_TONE_STUTTER;
01656 case ANALOG_TONE_CONGESTION:
01657 return DAHDI_TONE_CONGESTION;
01658 case ANALOG_TONE_DIALTONE:
01659 return DAHDI_TONE_DIALTONE;
01660 case ANALOG_TONE_DIALRECALL:
01661 return DAHDI_TONE_DIALRECALL;
01662 case ANALOG_TONE_INFO:
01663 return DAHDI_TONE_INFO;
01664 default:
01665 return -1;
01666 }
01667 }
01668
01669 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01670 {
01671 int index;
01672
01673 switch (analogsub) {
01674 case ANALOG_SUB_REAL:
01675 index = SUB_REAL;
01676 break;
01677 case ANALOG_SUB_CALLWAIT:
01678 index = SUB_CALLWAIT;
01679 break;
01680 case ANALOG_SUB_THREEWAY:
01681 index = SUB_THREEWAY;
01682 break;
01683 default:
01684 ast_log(LOG_ERROR, "Unidentified sub!\n");
01685 index = SUB_REAL;
01686 }
01687
01688 return index;
01689 }
01690
01691 static enum analog_event dahdievent_to_analogevent(int event);
01692 static int bump_gains(struct dahdi_pvt *p);
01693 static int dahdi_setlinear(int dfd, int linear);
01694
01695 static int my_start_cid_detect(void *pvt, int cid_signalling)
01696 {
01697 struct dahdi_pvt *p = pvt;
01698 int index = SUB_REAL;
01699 p->cs = callerid_new(cid_signalling);
01700 if (!p->cs) {
01701 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01702 return -1;
01703 }
01704 bump_gains(p);
01705 dahdi_setlinear(p->subs[index].dfd, 0);
01706
01707 return 0;
01708 }
01709
01710 static int my_stop_cid_detect(void *pvt)
01711 {
01712 struct dahdi_pvt *p = pvt;
01713 int index = SUB_REAL;
01714 if (p->cs)
01715 callerid_free(p->cs);
01716 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01717 return 0;
01718 }
01719
01720 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01721 {
01722 struct dahdi_pvt *p = pvt;
01723 struct analog_pvt *analog_p = p->sig_pvt;
01724 struct pollfd poller;
01725 char *name, *num;
01726 int index = SUB_REAL;
01727 int res;
01728 unsigned char buf[256];
01729 int flags;
01730
01731 poller.fd = p->subs[SUB_REAL].dfd;
01732 poller.events = POLLPRI | POLLIN;
01733 poller.revents = 0;
01734
01735 res = poll(&poller, 1, timeout);
01736
01737 if (poller.revents & POLLPRI) {
01738 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01739 return 1;
01740 }
01741
01742 if (poller.revents & POLLIN) {
01743
01744
01745
01746
01747
01748 res = read(p->subs[index].dfd, buf, sizeof(buf));
01749 if (res < 0) {
01750 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01751 return -1;
01752 }
01753
01754 if (analog_p->ringt > 0) {
01755 if (!(--analog_p->ringt)) {
01756
01757 return -1;
01758 }
01759 }
01760
01761 if (p->cid_signalling == CID_SIG_V23_JP) {
01762 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01763 } else {
01764 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01765 }
01766 if (res < 0) {
01767
01768
01769
01770
01771 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01772 return -1;
01773 }
01774
01775 if (res == 1) {
01776 callerid_get(p->cs, &name, &num, &flags);
01777 if (name)
01778 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01779 if (num)
01780 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01781
01782 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01783 return 0;
01784 }
01785 }
01786
01787 *ev = ANALOG_EVENT_NONE;
01788 return 2;
01789 }
01790
01791 static const char *event2str(int event);
01792 static int restore_gains(struct dahdi_pvt *p);
01793
01794 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01795 {
01796 unsigned char buf[256];
01797 int distMatches;
01798 int curRingData[RING_PATTERNS];
01799 int receivedRingT;
01800 int counter1;
01801 int counter;
01802 int i;
01803 int res;
01804 int checkaftercid = 0;
01805
01806 struct dahdi_pvt *p = pvt;
01807 struct analog_pvt *analog_p = p->sig_pvt;
01808
01809 if (ringdata == NULL) {
01810 ringdata = curRingData;
01811 } else {
01812 checkaftercid = 1;
01813 }
01814
01815
01816
01817 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01818
01819 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01820 ringdata[receivedRingT] = 0;
01821 receivedRingT = 0;
01822 if (checkaftercid && distinctiveringaftercid)
01823 ast_verb(3, "Detecting post-CID distinctive ring\n");
01824
01825 else if (strcmp(p->context,p->defcontext) != 0) {
01826 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01827 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01828 }
01829
01830 for (;;) {
01831 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01832 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01833 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01834 ast_hangup(chan);
01835 return 1;
01836 }
01837 if (i & DAHDI_IOMUX_SIGEVENT) {
01838 res = dahdi_get_event(p->subs[idx].dfd);
01839 if (res == DAHDI_EVENT_NOALARM) {
01840 p->inalarm = 0;
01841 analog_p->inalarm = 0;
01842 }
01843 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01844 res = 0;
01845
01846
01847 ringdata[receivedRingT] = analog_p->ringt;
01848
01849 if (analog_p->ringt < analog_p->ringt_base/2)
01850 break;
01851
01852
01853 if (++receivedRingT == RING_PATTERNS)
01854 break;
01855 } else if (i & DAHDI_IOMUX_READ) {
01856 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01857 if (res < 0) {
01858 if (errno != ELAST) {
01859 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01860 ast_hangup(chan);
01861 return 1;
01862 }
01863 break;
01864 }
01865 if (analog_p->ringt > 0) {
01866 if (!(--analog_p->ringt)) {
01867 res = -1;
01868 break;
01869 }
01870 }
01871 }
01872 }
01873 }
01874 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01875
01876 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01877 for (counter = 0; counter < 3; counter++) {
01878
01879 distMatches = 0;
01880
01881 ast_verb(3, "Checking %d,%d,%d\n",
01882 p->drings.ringnum[counter].ring[0],
01883 p->drings.ringnum[counter].ring[1],
01884 p->drings.ringnum[counter].ring[2]);
01885 for (counter1 = 0; counter1 < 3; counter1++) {
01886 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01887 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01888 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01889 ringdata[counter1]);
01890 distMatches++;
01891 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01892 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01893 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01894 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01895 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01896 distMatches++;
01897 }
01898 }
01899
01900 if (distMatches == 3) {
01901
01902 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01903 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01904 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01905 break;
01906 }
01907 }
01908 }
01909
01910 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01911 restore_gains(p);
01912
01913 return 0;
01914 }
01915
01916 static int my_stop_callwait(void *pvt)
01917 {
01918 struct dahdi_pvt *p = pvt;
01919 p->callwaitingrepeat = 0;
01920 p->cidcwexpire = 0;
01921 p->cid_suppress_expire = 0;
01922
01923 return 0;
01924 }
01925
01926 static int send_callerid(struct dahdi_pvt *p);
01927 static int save_conference(struct dahdi_pvt *p);
01928 static int restore_conference(struct dahdi_pvt *p);
01929
01930 static int my_callwait(void *pvt)
01931 {
01932 struct dahdi_pvt *p = pvt;
01933 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01934 if (p->cidspill) {
01935 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01936 ast_free(p->cidspill);
01937 }
01938
01939
01940
01941
01942
01943 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01944 return -1;
01945 save_conference(p);
01946
01947 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01948 if (!p->callwaitrings && p->callwaitingcallerid) {
01949 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01950 p->callwaitcas = 1;
01951 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01952 } else {
01953 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01954 p->callwaitcas = 0;
01955 p->cidlen = 2400 + READ_SIZE * 4;
01956 }
01957 p->cidpos = 0;
01958 send_callerid(p);
01959
01960 return 0;
01961 }
01962
01963 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01964 {
01965 struct dahdi_pvt *p = pvt;
01966
01967 ast_debug(2, "Starting cid spill\n");
01968
01969 if (p->cidspill) {
01970 ast_log(LOG_WARNING, "cidspill already exists??\n");
01971 ast_free(p->cidspill);
01972 }
01973
01974 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01975 if (cwcid == 0) {
01976 p->cidlen = ast_callerid_generate(p->cidspill,
01977 caller->id.name.str,
01978 caller->id.number.str,
01979 AST_LAW(p));
01980 } else {
01981 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01982 caller->id.name.str, caller->id.number.str);
01983 p->callwaitcas = 0;
01984 p->cidcwexpire = 0;
01985 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01986 caller->id.name.str,
01987 caller->id.number.str,
01988 AST_LAW(p));
01989 p->cidlen += READ_SIZE * 4;
01990 }
01991 p->cidpos = 0;
01992 p->cid_suppress_expire = 0;
01993 send_callerid(p);
01994 }
01995 return 0;
01996 }
01997
01998 static int my_dsp_reset_and_flush_digits(void *pvt)
01999 {
02000 struct dahdi_pvt *p = pvt;
02001 if (p->dsp)
02002 ast_dsp_digitreset(p->dsp);
02003
02004 return 0;
02005 }
02006
02007 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02008 {
02009 struct dahdi_pvt *p = pvt;
02010
02011 if (p->channel == CHAN_PSEUDO)
02012 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02013
02014 if (mode == ANALOG_DIGITMODE_DTMF) {
02015
02016 if (p->hardwaredtmf) {
02017 if (p->dsp) {
02018 ast_dsp_free(p->dsp);
02019 p->dsp = NULL;
02020 }
02021 return 0;
02022 }
02023
02024 if (!p->dsp) {
02025 p->dsp = ast_dsp_new();
02026 if (!p->dsp) {
02027 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02028 return -1;
02029 }
02030 }
02031
02032 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02033 } else if (mode == ANALOG_DIGITMODE_MF) {
02034 if (!p->dsp) {
02035 p->dsp = ast_dsp_new();
02036 if (!p->dsp) {
02037 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02038 return -1;
02039 }
02040 }
02041 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02042 }
02043 return 0;
02044 }
02045
02046 static int dahdi_wink(struct dahdi_pvt *p, int index);
02047
02048 static int my_wink(void *pvt, enum analog_sub sub)
02049 {
02050 struct dahdi_pvt *p = pvt;
02051 int index = analogsub_to_dahdisub(sub);
02052 if (index != SUB_REAL) {
02053 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02054 }
02055 return dahdi_wink(p, index);
02056 }
02057
02058 static void wakeup_sub(struct dahdi_pvt *p, int a);
02059
02060 static int reset_conf(struct dahdi_pvt *p);
02061
02062 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02063
02064 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02065 {
02066 struct ast_frame *f = *dest;
02067 struct dahdi_pvt *p = pvt;
02068 int idx = analogsub_to_dahdisub(analog_index);
02069
02070 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02071 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02072 f->subclass.integer, f->subclass.integer, ast->name);
02073
02074 if (f->subclass.integer == 'f') {
02075 if (f->frametype == AST_FRAME_DTMF_END) {
02076
02077 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02078
02079 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02080 struct dahdi_bufferinfo bi = {
02081 .txbufpolicy = p->faxbuf_policy,
02082 .bufsize = p->bufsize,
02083 .numbufs = p->faxbuf_no
02084 };
02085 int res;
02086
02087 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02088 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02089 } else {
02090 p->bufferoverrideinuse = 1;
02091 }
02092 }
02093 p->faxhandled = 1;
02094 if (p->dsp) {
02095 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02096 ast_dsp_set_features(p->dsp, p->dsp_features);
02097 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02098 }
02099 if (strcmp(ast->exten, "fax")) {
02100 const char *target_context = S_OR(ast->macrocontext, ast->context);
02101
02102
02103
02104
02105
02106 ast_mutex_unlock(&p->lock);
02107 ast_channel_unlock(ast);
02108 if (ast_exists_extension(ast, target_context, "fax", 1,
02109 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02110 ast_channel_lock(ast);
02111 ast_mutex_lock(&p->lock);
02112 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02113
02114 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02115 if (ast_async_goto(ast, target_context, "fax", 1))
02116 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02117 } else {
02118 ast_channel_lock(ast);
02119 ast_mutex_lock(&p->lock);
02120 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02121 }
02122 } else {
02123 ast_debug(1, "Already in a fax extension, not redirecting\n");
02124 }
02125 } else {
02126 ast_debug(1, "Fax already handled\n");
02127 }
02128 dahdi_confmute(p, 0);
02129 }
02130 p->subs[idx].f.frametype = AST_FRAME_NULL;
02131 p->subs[idx].f.subclass.integer = 0;
02132 *dest = &p->subs[idx].f;
02133 }
02134 }
02135
02136 static void my_lock_private(void *pvt)
02137 {
02138 struct dahdi_pvt *p = pvt;
02139 ast_mutex_lock(&p->lock);
02140 }
02141
02142 static void my_unlock_private(void *pvt)
02143 {
02144 struct dahdi_pvt *p = pvt;
02145 ast_mutex_unlock(&p->lock);
02146 }
02147
02148 static void my_deadlock_avoidance_private(void *pvt)
02149 {
02150 struct dahdi_pvt *p = pvt;
02151
02152 DEADLOCK_AVOIDANCE(&p->lock);
02153 }
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02166 {
02167 char ch_name[20];
02168
02169 if (p->channel < CHAN_PSEUDO) {
02170
02171 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02172 } else if (p->channel == CHAN_PSEUDO) {
02173
02174 strcpy(ch_name, "pseudo");
02175 } else {
02176
02177 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02178 }
02179 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02180 "Channel: %s\r\n"
02181 "Uniqueid: %s\r\n"
02182 "DAHDISpan: %d\r\n"
02183 "DAHDIChannel: %s\r\n",
02184 chan->name,
02185 chan->uniqueid,
02186 p->span,
02187 ch_name);
02188 }
02189
02190 #ifdef HAVE_PRI
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02202 {
02203 struct dahdi_pvt *p = pvt;
02204
02205 dahdi_ami_channel_event(p, chan);
02206 }
02207 #endif
02208
02209
02210
02211
02212 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02213 {
02214 struct dahdi_pvt *p = pvt;
02215 int oldval;
02216 int idx = analogsub_to_dahdisub(sub);
02217
02218 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02219 oldval = p->subs[idx].linear;
02220 p->subs[idx].linear = linear_mode ? 1 : 0;
02221 return oldval;
02222 }
02223
02224 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02225 {
02226 struct dahdi_pvt *p = pvt;
02227 int idx = analogsub_to_dahdisub(sub);
02228
02229 p->subs[idx].inthreeway = inthreeway;
02230 }
02231
02232 static int get_alarms(struct dahdi_pvt *p);
02233 static void handle_alarms(struct dahdi_pvt *p, int alms);
02234 static void my_get_and_handle_alarms(void *pvt)
02235 {
02236 int res;
02237 struct dahdi_pvt *p = pvt;
02238
02239 res = get_alarms(p);
02240 handle_alarms(p, res);
02241 }
02242
02243 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02244 {
02245 struct ast_channel *bridged = ast_bridged_channel(chan);
02246
02247 if (bridged && bridged->tech == &dahdi_tech) {
02248 struct dahdi_pvt *p = bridged->tech_pvt;
02249
02250 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02251 return p->sig_pvt;
02252 }
02253 }
02254 return NULL;
02255 }
02256
02257 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02258 {
02259 struct dahdi_pvt *p = pvt;
02260 int dahdi_sub = analogsub_to_dahdisub(sub);
02261 return p->subs[dahdi_sub].dfd;
02262 }
02263
02264 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02265 {
02266 struct dahdi_pvt *p = pvt;
02267
02268
02269 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02270 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02271 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02272 *cid_rings = cidrings[p->distinctivering - 1];
02273 } else {
02274 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02275 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02276 *cid_rings = p->sendcalleridafter;
02277 }
02278 }
02279
02280 static void my_set_alarm(void *pvt, int in_alarm)
02281 {
02282 struct dahdi_pvt *p = pvt;
02283
02284 p->inalarm = in_alarm;
02285 }
02286
02287 static void my_set_dialing(void *pvt, int is_dialing)
02288 {
02289 struct dahdi_pvt *p = pvt;
02290
02291 p->dialing = is_dialing;
02292 }
02293
02294 static void my_set_outgoing(void *pvt, int is_outgoing)
02295 {
02296 struct dahdi_pvt *p = pvt;
02297
02298 p->outgoing = is_outgoing;
02299 }
02300
02301 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02302 static void my_set_digital(void *pvt, int is_digital)
02303 {
02304 struct dahdi_pvt *p = pvt;
02305
02306 p->digital = is_digital;
02307 }
02308 #endif
02309
02310 #if defined(HAVE_SS7)
02311 static void my_set_inservice(void *pvt, int is_inservice)
02312 {
02313 struct dahdi_pvt *p = pvt;
02314
02315 p->inservice = is_inservice;
02316 }
02317 #endif
02318
02319 #if defined(HAVE_SS7)
02320 static void my_set_locallyblocked(void *pvt, int is_blocked)
02321 {
02322 struct dahdi_pvt *p = pvt;
02323
02324 p->locallyblocked = is_blocked;
02325 }
02326 #endif
02327
02328 #if defined(HAVE_SS7)
02329 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02330 {
02331 struct dahdi_pvt *p = pvt;
02332
02333 p->remotelyblocked = is_blocked;
02334 }
02335 #endif
02336
02337 static void my_set_ringtimeout(void *pvt, int ringt)
02338 {
02339 struct dahdi_pvt *p = pvt;
02340 p->ringt = ringt;
02341 }
02342
02343 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02344 {
02345 struct dahdi_pvt *p = pvt;
02346
02347 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02348 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02349 gettimeofday(&p->waitingfordt, NULL);
02350 ast_setstate(ast, AST_STATE_OFFHOOK);
02351 }
02352 }
02353
02354 static int my_check_waitingfordt(void *pvt)
02355 {
02356 struct dahdi_pvt *p = pvt;
02357
02358 if (p->waitingfordt.tv_usec) {
02359 return 1;
02360 }
02361
02362 return 0;
02363 }
02364
02365 static void my_set_confirmanswer(void *pvt, int flag)
02366 {
02367 struct dahdi_pvt *p = pvt;
02368 p->confirmanswer = flag;
02369 }
02370
02371 static int my_check_confirmanswer(void *pvt)
02372 {
02373 struct dahdi_pvt *p = pvt;
02374 if (p->confirmanswer) {
02375 return 1;
02376 }
02377
02378 return 0;
02379 }
02380
02381 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02382 {
02383 struct dahdi_pvt *p = pvt;
02384
02385 p->callwaiting = callwaiting_enable;
02386 }
02387
02388 static void my_cancel_cidspill(void *pvt)
02389 {
02390 struct dahdi_pvt *p = pvt;
02391
02392 ast_free(p->cidspill);
02393 p->cidspill = NULL;
02394 restore_conference(p);
02395 }
02396
02397 static int my_confmute(void *pvt, int mute)
02398 {
02399 struct dahdi_pvt *p = pvt;
02400 return dahdi_confmute(p, mute);
02401 }
02402
02403 static void my_set_pulsedial(void *pvt, int flag)
02404 {
02405 struct dahdi_pvt *p = pvt;
02406 p->pulsedial = flag;
02407 }
02408
02409 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02410 {
02411 struct dahdi_pvt *p = pvt;
02412
02413 p->owner = new_owner;
02414 }
02415
02416 static const char *my_get_orig_dialstring(void *pvt)
02417 {
02418 struct dahdi_pvt *p = pvt;
02419
02420 return p->dialstring;
02421 }
02422
02423 static void my_increase_ss_count(void)
02424 {
02425 ast_mutex_lock(&ss_thread_lock);
02426 ss_thread_count++;
02427 ast_mutex_unlock(&ss_thread_lock);
02428 }
02429
02430 static void my_decrease_ss_count(void)
02431 {
02432 ast_mutex_lock(&ss_thread_lock);
02433 ss_thread_count--;
02434 ast_cond_signal(&ss_thread_complete);
02435 ast_mutex_unlock(&ss_thread_lock);
02436 }
02437
02438 static void my_all_subchannels_hungup(void *pvt)
02439 {
02440 struct dahdi_pvt *p = pvt;
02441 int res, law;
02442
02443 p->faxhandled = 0;
02444 p->didtdd = 0;
02445
02446 if (p->dsp) {
02447 ast_dsp_free(p->dsp);
02448 p->dsp = NULL;
02449 }
02450
02451 p->law = p->law_default;
02452 law = p->law_default;
02453 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02454 if (res < 0)
02455 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02456
02457 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02458
02459 #if 1
02460 {
02461 int i;
02462 p->owner = NULL;
02463
02464 for (i = 0; i < 3; i++) {
02465 p->subs[i].owner = NULL;
02466 }
02467 }
02468 #endif
02469
02470 reset_conf(p);
02471 if (num_restart_pending == 0) {
02472 restart_monitor();
02473 }
02474 }
02475
02476 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02477
02478 static int my_conf_del(void *pvt, enum analog_sub sub)
02479 {
02480 struct dahdi_pvt *p = pvt;
02481 int x = analogsub_to_dahdisub(sub);
02482
02483 return conf_del(p, &p->subs[x], x);
02484 }
02485
02486 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02487
02488 static int my_conf_add(void *pvt, enum analog_sub sub)
02489 {
02490 struct dahdi_pvt *p = pvt;
02491 int x = analogsub_to_dahdisub(sub);
02492
02493 return conf_add(p, &p->subs[x], x, 0);
02494 }
02495
02496 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02497
02498 static int my_complete_conference_update(void *pvt, int needconference)
02499 {
02500 struct dahdi_pvt *p = pvt;
02501 int needconf = needconference;
02502 int x;
02503 int useslavenative;
02504 struct dahdi_pvt *slave = NULL;
02505
02506 useslavenative = isslavenative(p, &slave);
02507
02508
02509
02510 for (x = 0; x < MAX_SLAVES; x++) {
02511 if (p->slaves[x]) {
02512 if (useslavenative)
02513 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02514 else {
02515 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02516 needconf++;
02517 }
02518 }
02519 }
02520
02521 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02522 if (useslavenative)
02523 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02524 else {
02525 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02526 needconf++;
02527 }
02528 }
02529
02530 if (p->master) {
02531 if (isslavenative(p->master, NULL)) {
02532 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02533 } else {
02534 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02535 }
02536 }
02537 if (!needconf) {
02538
02539
02540 p->confno = -1;
02541 }
02542
02543 return 0;
02544 }
02545
02546 static int check_for_conference(struct dahdi_pvt *p);
02547
02548 static int my_check_for_conference(void *pvt)
02549 {
02550 struct dahdi_pvt *p = pvt;
02551 return check_for_conference(p);
02552 }
02553
02554 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)
02555 {
02556 struct dahdi_pvt *p = pvt;
02557 int da, db;
02558 int tchan;
02559 int tinthreeway;
02560
02561 da = analogsub_to_dahdisub(a);
02562 db = analogsub_to_dahdisub(b);
02563
02564 tchan = p->subs[da].chan;
02565 p->subs[da].chan = p->subs[db].chan;
02566 p->subs[db].chan = tchan;
02567
02568 tinthreeway = p->subs[da].inthreeway;
02569 p->subs[da].inthreeway = p->subs[db].inthreeway;
02570 p->subs[db].inthreeway = tinthreeway;
02571
02572 p->subs[da].owner = ast_a;
02573 p->subs[db].owner = ast_b;
02574
02575 if (ast_a)
02576 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02577 if (ast_b)
02578 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02579
02580 wakeup_sub(p, a);
02581 wakeup_sub(p, b);
02582
02583 return;
02584 }
02585
02586 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02587
02588 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02589 {
02590 struct dahdi_pvt *p = pvt;
02591 int dsub = analogsub_to_dahdisub(sub);
02592
02593 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02594 }
02595
02596 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02597 static int dahdi_setlaw(int dfd, int law)
02598 {
02599 int res;
02600 res = ioctl(dfd, DAHDI_SETLAW, &law);
02601 if (res)
02602 return res;
02603 return 0;
02604 }
02605 #endif
02606
02607 #if defined(HAVE_PRI)
02608 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)
02609 {
02610 struct dahdi_pvt *p = pvt;
02611 int audio;
02612 int newlaw = -1;
02613
02614 switch (p->sig) {
02615 case SIG_PRI_LIB_HANDLE_CASES:
02616 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02617
02618 break;
02619 }
02620
02621 default:
02622
02623 audio = 1;
02624 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02625 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02626 p->channel, audio, strerror(errno));
02627 }
02628 break;
02629 }
02630
02631 if (law != SIG_PRI_DEFLAW) {
02632 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02633 }
02634
02635 ast_copy_string(p->exten, exten, sizeof(p->exten));
02636
02637 switch (law) {
02638 case SIG_PRI_DEFLAW:
02639 newlaw = 0;
02640 break;
02641 case SIG_PRI_ALAW:
02642 newlaw = DAHDI_LAW_ALAW;
02643 break;
02644 case SIG_PRI_ULAW:
02645 newlaw = DAHDI_LAW_MULAW;
02646 break;
02647 }
02648 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02649 }
02650 #endif
02651
02652 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02653
02654 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664 static void my_pri_ss7_open_media(void *p)
02665 {
02666 struct dahdi_pvt *pvt = p;
02667 int res;
02668 int dfd;
02669 int set_val;
02670
02671 dfd = pvt->subs[SUB_REAL].dfd;
02672
02673
02674 set_val = 1;
02675 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02676 if (res < 0) {
02677 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02678 pvt->channel, strerror(errno));
02679 }
02680
02681
02682 res = dahdi_setlaw(dfd, pvt->law);
02683 if (res < 0) {
02684 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02685 }
02686
02687
02688 if (pvt->digital) {
02689 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02690 } else {
02691 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02692 pvt->law);
02693 }
02694 if (res < 0) {
02695 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02696 }
02697
02698 if (pvt->dsp_features && pvt->dsp) {
02699 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02700 pvt->dsp_features = 0;
02701 }
02702 }
02703 #endif
02704
02705 #if defined(HAVE_PRI)
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718 static void my_pri_dial_digits(void *p, const char *dial_string)
02719 {
02720 struct dahdi_dialoperation zo = {
02721 .op = DAHDI_DIAL_OP_APPEND,
02722 };
02723 struct dahdi_pvt *pvt = p;
02724 int res;
02725
02726 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02727 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02728 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02729 if (res) {
02730 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02731 pvt->channel, dial_string, strerror(errno));
02732 } else {
02733 pvt->dialing = 1;
02734 }
02735 }
02736 #endif
02737
02738 static int unalloc_sub(struct dahdi_pvt *p, int x);
02739
02740 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02741 {
02742 struct dahdi_pvt *p = pvt;
02743
02744 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02745 }
02746
02747 static int alloc_sub(struct dahdi_pvt *p, int x);
02748
02749 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02750 {
02751 struct dahdi_pvt *p = pvt;
02752
02753 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02754 }
02755
02756 static int has_voicemail(struct dahdi_pvt *p);
02757
02758 static int my_has_voicemail(void *pvt)
02759 {
02760 struct dahdi_pvt *p = pvt;
02761
02762 return has_voicemail(p);
02763 }
02764
02765 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02766 {
02767 struct dahdi_pvt *p = pvt;
02768 int index;
02769
02770 index = analogsub_to_dahdisub(sub);
02771
02772 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02773 }
02774
02775 static enum analog_event dahdievent_to_analogevent(int event)
02776 {
02777 enum analog_event res;
02778
02779 switch (event) {
02780 case DAHDI_EVENT_ONHOOK:
02781 res = ANALOG_EVENT_ONHOOK;
02782 break;
02783 case DAHDI_EVENT_RINGOFFHOOK:
02784 res = ANALOG_EVENT_RINGOFFHOOK;
02785 break;
02786 case DAHDI_EVENT_WINKFLASH:
02787 res = ANALOG_EVENT_WINKFLASH;
02788 break;
02789 case DAHDI_EVENT_ALARM:
02790 res = ANALOG_EVENT_ALARM;
02791 break;
02792 case DAHDI_EVENT_NOALARM:
02793 res = ANALOG_EVENT_NOALARM;
02794 break;
02795 case DAHDI_EVENT_DIALCOMPLETE:
02796 res = ANALOG_EVENT_DIALCOMPLETE;
02797 break;
02798 case DAHDI_EVENT_RINGERON:
02799 res = ANALOG_EVENT_RINGERON;
02800 break;
02801 case DAHDI_EVENT_RINGEROFF:
02802 res = ANALOG_EVENT_RINGEROFF;
02803 break;
02804 case DAHDI_EVENT_HOOKCOMPLETE:
02805 res = ANALOG_EVENT_HOOKCOMPLETE;
02806 break;
02807 case DAHDI_EVENT_PULSE_START:
02808 res = ANALOG_EVENT_PULSE_START;
02809 break;
02810 case DAHDI_EVENT_POLARITY:
02811 res = ANALOG_EVENT_POLARITY;
02812 break;
02813 case DAHDI_EVENT_RINGBEGIN:
02814 res = ANALOG_EVENT_RINGBEGIN;
02815 break;
02816 case DAHDI_EVENT_EC_DISABLED:
02817 res = ANALOG_EVENT_EC_DISABLED;
02818 break;
02819 case DAHDI_EVENT_REMOVED:
02820 res = ANALOG_EVENT_REMOVED;
02821 break;
02822 case DAHDI_EVENT_NEONMWI_ACTIVE:
02823 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02824 break;
02825 case DAHDI_EVENT_NEONMWI_INACTIVE:
02826 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02827 break;
02828 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02829 case DAHDI_EVENT_TX_CED_DETECTED:
02830 res = ANALOG_EVENT_TX_CED_DETECTED;
02831 break;
02832 case DAHDI_EVENT_RX_CED_DETECTED:
02833 res = ANALOG_EVENT_RX_CED_DETECTED;
02834 break;
02835 case DAHDI_EVENT_EC_NLP_DISABLED:
02836 res = ANALOG_EVENT_EC_NLP_DISABLED;
02837 break;
02838 case DAHDI_EVENT_EC_NLP_ENABLED:
02839 res = ANALOG_EVENT_EC_NLP_ENABLED;
02840 break;
02841 #endif
02842 case DAHDI_EVENT_PULSEDIGIT:
02843 res = ANALOG_EVENT_PULSEDIGIT;
02844 break;
02845 case DAHDI_EVENT_DTMFDOWN:
02846 res = ANALOG_EVENT_DTMFDOWN;
02847 break;
02848 case DAHDI_EVENT_DTMFUP:
02849 res = ANALOG_EVENT_DTMFUP;
02850 break;
02851 default:
02852 switch(event & 0xFFFF0000) {
02853 case DAHDI_EVENT_PULSEDIGIT:
02854 case DAHDI_EVENT_DTMFDOWN:
02855 case DAHDI_EVENT_DTMFUP:
02856
02857
02858
02859
02860 return event;
02861 }
02862
02863 res = ANALOG_EVENT_ERROR;
02864 break;
02865 }
02866
02867 return res;
02868 }
02869
02870 static inline int dahdi_wait_event(int fd);
02871
02872 static int my_wait_event(void *pvt)
02873 {
02874 struct dahdi_pvt *p = pvt;
02875
02876 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02877 }
02878
02879 static int my_get_event(void *pvt)
02880 {
02881 struct dahdi_pvt *p = pvt;
02882 int res;
02883
02884 if (p->fake_event) {
02885 res = p->fake_event;
02886 p->fake_event = 0;
02887 } else
02888 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02889
02890 return dahdievent_to_analogevent(res);
02891 }
02892
02893 static int my_is_off_hook(void *pvt)
02894 {
02895 struct dahdi_pvt *p = pvt;
02896 int res;
02897 struct dahdi_params par;
02898
02899 memset(&par, 0, sizeof(par));
02900
02901 if (p->subs[SUB_REAL].dfd > -1)
02902 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02903 else {
02904
02905 res = 0;
02906 par.rxisoffhook = 0;
02907 }
02908 if (res) {
02909 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02910 }
02911
02912 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02913
02914
02915
02916 return (par.rxbits > -1) || par.rxisoffhook;
02917 }
02918
02919 return par.rxisoffhook;
02920 }
02921
02922 static void dahdi_enable_ec(struct dahdi_pvt *p);
02923 static void dahdi_disable_ec(struct dahdi_pvt *p);
02924
02925 static int my_set_echocanceller(void *pvt, int enable)
02926 {
02927 struct dahdi_pvt *p = pvt;
02928
02929 if (enable)
02930 dahdi_enable_ec(p);
02931 else
02932 dahdi_disable_ec(p);
02933
02934 return 0;
02935 }
02936
02937 static int dahdi_ring_phone(struct dahdi_pvt *p);
02938
02939 static int my_ring(void *pvt)
02940 {
02941 struct dahdi_pvt *p = pvt;
02942
02943 return dahdi_ring_phone(p);
02944 }
02945
02946 static int my_flash(void *pvt)
02947 {
02948 struct dahdi_pvt *p = pvt;
02949 int func = DAHDI_FLASH;
02950 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02951 }
02952
02953 static inline int dahdi_set_hook(int fd, int hs);
02954
02955 static int my_off_hook(void *pvt)
02956 {
02957 struct dahdi_pvt *p = pvt;
02958 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02959 }
02960
02961 static void my_set_needringing(void *pvt, int value)
02962 {
02963 struct dahdi_pvt *p = pvt;
02964 p->subs[SUB_REAL].needringing = value;
02965 }
02966
02967 static void my_set_polarity(void *pvt, int value)
02968 {
02969 struct dahdi_pvt *p = pvt;
02970
02971 if (p->channel == CHAN_PSEUDO) {
02972 return;
02973 }
02974 p->polarity = value;
02975 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02976 }
02977
02978 static void my_start_polarityswitch(void *pvt)
02979 {
02980 struct dahdi_pvt *p = pvt;
02981
02982 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02983 my_set_polarity(pvt, 0);
02984 }
02985 }
02986
02987 static void my_answer_polarityswitch(void *pvt)
02988 {
02989 struct dahdi_pvt *p = pvt;
02990
02991 if (!p->answeronpolarityswitch) {
02992 return;
02993 }
02994
02995 my_set_polarity(pvt, 1);
02996 }
02997
02998 static void my_hangup_polarityswitch(void *pvt)
02999 {
03000 struct dahdi_pvt *p = pvt;
03001
03002 if (!p->hanguponpolarityswitch) {
03003 return;
03004 }
03005
03006 if (p->answeronpolarityswitch) {
03007 my_set_polarity(pvt, 0);
03008 } else {
03009 my_set_polarity(pvt, 1);
03010 }
03011 }
03012
03013 static int my_start(void *pvt)
03014 {
03015 struct dahdi_pvt *p = pvt;
03016 int x = DAHDI_START;
03017
03018 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03019 }
03020
03021 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03022 {
03023 int index = analogsub_to_dahdisub(sub);
03024 int res;
03025 struct dahdi_pvt *p = pvt;
03026 struct dahdi_dialoperation ddop;
03027
03028 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03029 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03030 return -1;
03031 }
03032
03033 if (sub != ANALOG_SUB_REAL) {
03034 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03035 dop->dialstr, p->channel, sub);
03036 return -1;
03037 }
03038
03039 ddop.op = DAHDI_DIAL_OP_REPLACE;
03040 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03041
03042 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03043
03044 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03045 if (res == -1) {
03046 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03047 }
03048
03049 return res;
03050 }
03051
03052 static void dahdi_train_ec(struct dahdi_pvt *p);
03053
03054 static int my_train_echocanceller(void *pvt)
03055 {
03056 struct dahdi_pvt *p = pvt;
03057
03058 dahdi_train_ec(p);
03059
03060 return 0;
03061 }
03062
03063 static int my_is_dialing(void *pvt, enum analog_sub sub)
03064 {
03065 struct dahdi_pvt *p = pvt;
03066 int index;
03067 int x;
03068
03069 index = analogsub_to_dahdisub(sub);
03070
03071 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03072 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03073 return -1;
03074 }
03075
03076 return x;
03077 }
03078
03079 static int my_on_hook(void *pvt)
03080 {
03081 struct dahdi_pvt *p = pvt;
03082 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03083 }
03084
03085 #if defined(HAVE_PRI)
03086 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03087 {
03088 struct dahdi_pvt *old_chan = chan_old;
03089 struct dahdi_pvt *new_chan = chan_new;
03090
03091 new_chan->owner = old_chan->owner;
03092 old_chan->owner = NULL;
03093 if (new_chan->owner) {
03094 new_chan->owner->tech_pvt = new_chan;
03095 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03096 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03097 old_chan->subs[SUB_REAL].owner = NULL;
03098 }
03099
03100 new_chan->dsp = old_chan->dsp;
03101 new_chan->dsp_features = old_chan->dsp_features;
03102 old_chan->dsp = NULL;
03103 old_chan->dsp_features = 0;
03104
03105
03106 new_chan->dialing = old_chan->dialing;
03107 new_chan->digital = old_chan->digital;
03108 new_chan->outgoing = old_chan->outgoing;
03109 old_chan->dialing = 0;
03110 old_chan->digital = 0;
03111 old_chan->outgoing = 0;
03112
03113
03114 new_chan->law = old_chan->law;
03115 strcpy(new_chan->dialstring, old_chan->dialstring);
03116 }
03117 #endif
03118
03119 #if defined(HAVE_PRI)
03120 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03121 {
03122 switch (tone) {
03123 case SIG_PRI_TONE_RINGTONE:
03124 return DAHDI_TONE_RINGTONE;
03125 case SIG_PRI_TONE_STUTTER:
03126 return DAHDI_TONE_STUTTER;
03127 case SIG_PRI_TONE_CONGESTION:
03128 return DAHDI_TONE_CONGESTION;
03129 case SIG_PRI_TONE_DIALTONE:
03130 return DAHDI_TONE_DIALTONE;
03131 case SIG_PRI_TONE_DIALRECALL:
03132 return DAHDI_TONE_DIALRECALL;
03133 case SIG_PRI_TONE_INFO:
03134 return DAHDI_TONE_INFO;
03135 case SIG_PRI_TONE_BUSY:
03136 return DAHDI_TONE_BUSY;
03137 default:
03138 return -1;
03139 }
03140 }
03141 #endif
03142
03143 #if defined(HAVE_PRI)
03144 static int pri_destroy_dchan(struct sig_pri_span *pri);
03145
03146 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03147 {
03148 int x;
03149
03150 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03151 switch (x) {
03152 case DAHDI_EVENT_NONE:
03153 break;
03154 case DAHDI_EVENT_ALARM:
03155 case DAHDI_EVENT_NOALARM:
03156 if (sig_pri_is_alarm_ignored(pri)) {
03157 break;
03158 }
03159
03160 default:
03161 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03162 event2str(x), x, pri->span);
03163 break;
03164 }
03165
03166 switch (x) {
03167 case DAHDI_EVENT_ALARM:
03168 pri_event_alarm(pri, index, 0);
03169 break;
03170 case DAHDI_EVENT_NOALARM:
03171 pri_event_noalarm(pri, index, 0);
03172 break;
03173 case DAHDI_EVENT_REMOVED:
03174 pri_destroy_dchan(pri);
03175 break;
03176 default:
03177 break;
03178 }
03179 }
03180 #endif
03181
03182 #if defined(HAVE_PRI)
03183 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03184 {
03185 struct dahdi_pvt *p = pvt;
03186
03187 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03188 }
03189 #endif
03190
03191 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03203 {
03204 struct dahdi_pvt *p = pvt;
03205
03206 ast_copy_string(p->cid_num,
03207 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03208 sizeof(p->cid_num));
03209 ast_copy_string(p->cid_name,
03210 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03211 sizeof(p->cid_name));
03212 ast_copy_string(p->cid_subaddr,
03213 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03214 sizeof(p->cid_subaddr));
03215 p->cid_ton = caller->id.number.plan;
03216 p->callingpres = ast_party_id_presentation(&caller->id);
03217 if (caller->id.tag) {
03218 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03219 }
03220 ast_copy_string(p->cid_ani,
03221 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03222 sizeof(p->cid_ani));
03223 p->cid_ani2 = caller->ani2;
03224 }
03225 #endif
03226
03227 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238 static void my_set_dnid(void *pvt, const char *dnid)
03239 {
03240 struct dahdi_pvt *p = pvt;
03241
03242 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03243 }
03244 #endif
03245
03246 #if defined(HAVE_PRI)
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257 static void my_set_rdnis(void *pvt, const char *rdnis)
03258 {
03259 struct dahdi_pvt *p = pvt;
03260
03261 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03262 }
03263 #endif
03264
03265 #if defined(HAVE_PRI)
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03291 {
03292 char *dial;
03293 struct dahdi_pvt *pvt;
03294 AST_DECLARE_APP_ARGS(args,
03295 AST_APP_ARG(tech);
03296 AST_APP_ARG(group);
03297
03298
03299
03300 );
03301
03302 pvt = priv;
03303 dial = ast_strdupa(pvt->dialstring);
03304 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03305 if (!args.tech) {
03306 ast_copy_string(buf, pvt->dialstring, buf_size);
03307 return;
03308 }
03309 if (!args.group) {
03310
03311 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03312 return;
03313 }
03314 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03315
03316
03317 ast_copy_string(buf, pvt->dialstring, buf_size);
03318 return;
03319 }
03320
03321 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03322 }
03323 #endif
03324
03325 #if defined(HAVE_PRI)
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03338 {
03339 unsigned idx;
03340 unsigned num_b_chans;
03341 unsigned in_use;
03342 unsigned in_alarm;
03343 enum ast_device_state new_state;
03344
03345
03346 num_b_chans = 0;
03347 in_use = 0;
03348 in_alarm = 1;
03349 for (idx = pri->numchans; idx--;) {
03350 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03351
03352 ++num_b_chans;
03353 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03354 ++in_use;
03355 }
03356 if (!pri->pvts[idx]->inalarm) {
03357
03358 in_alarm = 0;
03359 }
03360 }
03361 }
03362
03363
03364 if (in_alarm) {
03365 new_state = AST_DEVICE_UNAVAILABLE;
03366 } else {
03367 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03368 }
03369 if (pri->congestion_devstate != new_state) {
03370 pri->congestion_devstate = new_state;
03371 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03372 }
03373 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03374
03375 if (in_alarm) {
03376 new_state = AST_DEVICE_UNAVAILABLE;
03377 } else if (!in_use) {
03378 new_state = AST_DEVICE_NOT_INUSE;
03379 } else if (!pri->user_busy_threshold) {
03380 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03381 } else {
03382 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03383 : AST_DEVICE_BUSY;
03384 }
03385 if (pri->threshold_devstate != new_state) {
03386 pri->threshold_devstate = new_state;
03387 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03388 }
03389 #endif
03390 }
03391 #endif
03392
03393 #if defined(HAVE_PRI)
03394
03395
03396
03397
03398
03399
03400
03401 static void my_module_ref(void)
03402 {
03403 ast_module_ref(ast_module_info->self);
03404 }
03405 #endif
03406
03407 #if defined(HAVE_PRI)
03408
03409
03410
03411
03412
03413
03414
03415 static void my_module_unref(void)
03416 {
03417 ast_module_unref(ast_module_info->self);
03418 }
03419 #endif
03420
03421 #if defined(HAVE_PRI)
03422 #if defined(HAVE_PRI_CALL_WAITING)
03423 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03424 #endif
03425 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03426
03427 static struct sig_pri_callback dahdi_pri_callbacks =
03428 {
03429 .handle_dchan_exception = my_handle_dchan_exception,
03430 .play_tone = my_pri_play_tone,
03431 .set_echocanceller = my_set_echocanceller,
03432 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03433 .lock_private = my_lock_private,
03434 .unlock_private = my_unlock_private,
03435 .new_ast_channel = my_new_pri_ast_channel,
03436 .fixup_chans = my_pri_fixup_chans,
03437 .set_alarm = my_set_alarm,
03438 .set_dialing = my_set_dialing,
03439 .set_outgoing = my_set_outgoing,
03440 .set_digital = my_set_digital,
03441 .set_callerid = my_set_callerid,
03442 .set_dnid = my_set_dnid,
03443 .set_rdnis = my_set_rdnis,
03444 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03445 #if defined(HAVE_PRI_CALL_WAITING)
03446 .init_config = my_pri_init_config,
03447 #endif
03448 .get_orig_dialstring = my_get_orig_dialstring,
03449 .make_cc_dialstring = my_pri_make_cc_dialstring,
03450 .update_span_devstate = dahdi_pri_update_span_devstate,
03451 .module_ref = my_module_ref,
03452 .module_unref = my_module_unref,
03453 .dial_digits = my_pri_dial_digits,
03454 .open_media = my_pri_ss7_open_media,
03455 .ami_channel_event = my_ami_channel_event,
03456 };
03457 #endif
03458
03459 #if defined(HAVE_SS7)
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03471 {
03472 int event;
03473
03474 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03475 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03476 linkset->span, which);
03477 return;
03478 }
03479 switch (event) {
03480 case DAHDI_EVENT_NONE:
03481 break;
03482 case DAHDI_EVENT_ALARM:
03483 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03484 event2str(event), event, linkset->span, which);
03485 sig_ss7_link_alarm(linkset, which);
03486 break;
03487 case DAHDI_EVENT_NOALARM:
03488 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03489 event2str(event), event, linkset->span, which);
03490 sig_ss7_link_noalarm(linkset, which);
03491 break;
03492 default:
03493 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03494 event2str(event), event, linkset->span, which);
03495 break;
03496 }
03497 }
03498 #endif
03499
03500 #if defined(HAVE_SS7)
03501 static void my_ss7_set_loopback(void *pvt, int enable)
03502 {
03503 struct dahdi_pvt *p = pvt;
03504
03505 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03506 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03507 strerror(errno));
03508 }
03509 }
03510 #endif
03511
03512 #if defined(HAVE_SS7)
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526
03527 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)
03528 {
03529 struct dahdi_pvt *p = pvt;
03530 int audio;
03531 int newlaw;
03532
03533
03534 audio = 1;
03535 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03536 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03537 p->channel, audio, strerror(errno));
03538
03539 if (law != SIG_SS7_DEFLAW) {
03540 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03541 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03542 }
03543
03544 ast_copy_string(p->exten, exten, sizeof(p->exten));
03545
03546 newlaw = -1;
03547 switch (law) {
03548 case SIG_SS7_DEFLAW:
03549 newlaw = 0;
03550 break;
03551 case SIG_SS7_ALAW:
03552 newlaw = DAHDI_LAW_ALAW;
03553 break;
03554 case SIG_SS7_ULAW:
03555 newlaw = DAHDI_LAW_MULAW;
03556 break;
03557 }
03558 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03559 }
03560 #endif
03561
03562 #if defined(HAVE_SS7)
03563 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03564 {
03565 switch (tone) {
03566 case SIG_SS7_TONE_RINGTONE:
03567 return DAHDI_TONE_RINGTONE;
03568 case SIG_SS7_TONE_STUTTER:
03569 return DAHDI_TONE_STUTTER;
03570 case SIG_SS7_TONE_CONGESTION:
03571 return DAHDI_TONE_CONGESTION;
03572 case SIG_SS7_TONE_DIALTONE:
03573 return DAHDI_TONE_DIALTONE;
03574 case SIG_SS7_TONE_DIALRECALL:
03575 return DAHDI_TONE_DIALRECALL;
03576 case SIG_SS7_TONE_INFO:
03577 return DAHDI_TONE_INFO;
03578 case SIG_SS7_TONE_BUSY:
03579 return DAHDI_TONE_BUSY;
03580 default:
03581 return -1;
03582 }
03583 }
03584 #endif
03585
03586 #if defined(HAVE_SS7)
03587 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03588 {
03589 struct dahdi_pvt *p = pvt;
03590
03591 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03592 }
03593 #endif
03594
03595 #if defined(HAVE_SS7)
03596 static struct sig_ss7_callback dahdi_ss7_callbacks =
03597 {
03598 .lock_private = my_lock_private,
03599 .unlock_private = my_unlock_private,
03600
03601 .set_echocanceller = my_set_echocanceller,
03602 .set_loopback = my_ss7_set_loopback,
03603
03604 .new_ast_channel = my_new_ss7_ast_channel,
03605 .play_tone = my_ss7_play_tone,
03606
03607 .handle_link_exception = my_handle_link_exception,
03608 .set_alarm = my_set_alarm,
03609 .set_dialing = my_set_dialing,
03610 .set_outgoing = my_set_outgoing,
03611 .set_digital = my_set_digital,
03612 .set_inservice = my_set_inservice,
03613 .set_locallyblocked = my_set_locallyblocked,
03614 .set_remotelyblocked = my_set_remotelyblocked,
03615 .set_callerid = my_set_callerid,
03616 .set_dnid = my_set_dnid,
03617 .open_media = my_pri_ss7_open_media,
03618 };
03619 #endif
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639 static void notify_message(char *mailbox_full, int thereornot)
03640 {
03641 char s[sizeof(mwimonitornotify) + 80];
03642 struct ast_event *event;
03643 char *mailbox, *context;
03644
03645
03646 context = mailbox = ast_strdupa(mailbox_full);
03647 strsep(&context, "@");
03648 if (ast_strlen_zero(context))
03649 context = "default";
03650
03651 if (!(event = ast_event_new(AST_EVENT_MWI,
03652 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03653 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03654 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03655 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03656 AST_EVENT_IE_END))) {
03657 return;
03658 }
03659
03660 ast_event_queue_and_cache(event);
03661
03662 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03663 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03664 ast_safe_system(s);
03665 }
03666 }
03667
03668 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03669 {
03670 struct dahdi_pvt *p = pvt;
03671
03672 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03673 return;
03674
03675 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03676 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03677 notify_message(p->mailbox, 1);
03678 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03679 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03680 notify_message(p->mailbox, 0);
03681 }
03682
03683
03684 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03685 ast_hangup(chan);
03686 return;
03687 }
03688 }
03689
03690 static int my_have_progressdetect(void *pvt)
03691 {
03692 struct dahdi_pvt *p = pvt;
03693
03694 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03695 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03696 return 1;
03697 } else {
03698
03699 return 0;
03700 }
03701 }
03702
03703 static struct analog_callback dahdi_analog_callbacks =
03704 {
03705 .play_tone = my_play_tone,
03706 .get_event = my_get_event,
03707 .wait_event = my_wait_event,
03708 .is_off_hook = my_is_off_hook,
03709 .set_echocanceller = my_set_echocanceller,
03710 .ring = my_ring,
03711 .flash = my_flash,
03712 .off_hook = my_off_hook,
03713 .dial_digits = my_dial_digits,
03714 .train_echocanceller = my_train_echocanceller,
03715 .on_hook = my_on_hook,
03716 .is_dialing = my_is_dialing,
03717 .allocate_sub = my_allocate_sub,
03718 .unallocate_sub = my_unallocate_sub,
03719 .swap_subs = my_swap_subchannels,
03720 .has_voicemail = my_has_voicemail,
03721 .check_for_conference = my_check_for_conference,
03722 .conf_add = my_conf_add,
03723 .conf_del = my_conf_del,
03724 .complete_conference_update = my_complete_conference_update,
03725 .start = my_start,
03726 .all_subchannels_hungup = my_all_subchannels_hungup,
03727 .lock_private = my_lock_private,
03728 .unlock_private = my_unlock_private,
03729 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03730 .handle_dtmf = my_handle_dtmf,
03731 .wink = my_wink,
03732 .new_ast_channel = my_new_analog_ast_channel,
03733 .dsp_set_digitmode = my_dsp_set_digitmode,
03734 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03735 .send_callerid = my_send_callerid,
03736 .callwait = my_callwait,
03737 .stop_callwait = my_stop_callwait,
03738 .get_callerid = my_get_callerid,
03739 .start_cid_detect = my_start_cid_detect,
03740 .stop_cid_detect = my_stop_cid_detect,
03741 .handle_notify_message = my_handle_notify_message,
03742 .increase_ss_count = my_increase_ss_count,
03743 .decrease_ss_count = my_decrease_ss_count,
03744 .distinctive_ring = my_distinctive_ring,
03745 .set_linear_mode = my_set_linear_mode,
03746 .set_inthreeway = my_set_inthreeway,
03747 .get_and_handle_alarms = my_get_and_handle_alarms,
03748 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03749 .get_sub_fd = my_get_sub_fd,
03750 .set_cadence = my_set_cadence,
03751 .set_alarm = my_set_alarm,
03752 .set_dialing = my_set_dialing,
03753 .set_outgoing = my_set_outgoing,
03754 .set_ringtimeout = my_set_ringtimeout,
03755 .set_waitingfordt = my_set_waitingfordt,
03756 .check_waitingfordt = my_check_waitingfordt,
03757 .set_confirmanswer = my_set_confirmanswer,
03758 .check_confirmanswer = my_check_confirmanswer,
03759 .set_callwaiting = my_set_callwaiting,
03760 .cancel_cidspill = my_cancel_cidspill,
03761 .confmute = my_confmute,
03762 .set_pulsedial = my_set_pulsedial,
03763 .set_new_owner = my_set_new_owner,
03764 .get_orig_dialstring = my_get_orig_dialstring,
03765 .set_needringing = my_set_needringing,
03766 .set_polarity = my_set_polarity,
03767 .start_polarityswitch = my_start_polarityswitch,
03768 .answer_polarityswitch = my_answer_polarityswitch,
03769 .hangup_polarityswitch = my_hangup_polarityswitch,
03770 .have_progressdetect = my_have_progressdetect,
03771 };
03772
03773
03774 static struct dahdi_pvt *round_robin[32];
03775
03776 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03777 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03778 {
03779 int res;
03780 if (p->subs[SUB_REAL].owner == ast)
03781 res = 0;
03782 else if (p->subs[SUB_CALLWAIT].owner == ast)
03783 res = 1;
03784 else if (p->subs[SUB_THREEWAY].owner == ast)
03785 res = 2;
03786 else {
03787 res = -1;
03788 if (!nullok)
03789 ast_log(LOG_WARNING,
03790 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03791 ast ? ast->name : "", p->channel, fname, line);
03792 }
03793 return res;
03794 }
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807
03808
03809
03810
03811 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03812 {
03813 for (;;) {
03814 if (!pvt->subs[sub_idx].owner) {
03815
03816 break;
03817 }
03818 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03819
03820 break;
03821 }
03822
03823 DEADLOCK_AVOIDANCE(&pvt->lock);
03824 }
03825 }
03826
03827 static void wakeup_sub(struct dahdi_pvt *p, int a)
03828 {
03829 dahdi_lock_sub_owner(p, a);
03830 if (p->subs[a].owner) {
03831 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03832 ast_channel_unlock(p->subs[a].owner);
03833 }
03834 }
03835
03836 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03837 {
03838 for (;;) {
03839 if (p->owner) {
03840 if (ast_channel_trylock(p->owner)) {
03841 DEADLOCK_AVOIDANCE(&p->lock);
03842 } else {
03843 ast_queue_frame(p->owner, f);
03844 ast_channel_unlock(p->owner);
03845 break;
03846 }
03847 } else
03848 break;
03849 }
03850 }
03851
03852 static void handle_clear_alarms(struct dahdi_pvt *p)
03853 {
03854 #if defined(HAVE_PRI)
03855 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03856 return;
03857 }
03858 #endif
03859
03860 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03861 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03862 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03863 }
03864 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03865 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03866 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03867 }
03868 }
03869
03870 #ifdef HAVE_OPENR2
03871
03872 static int dahdi_r2_answer(struct dahdi_pvt *p)
03873 {
03874 int res = 0;
03875
03876
03877
03878 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03879 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03880 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03881 if (!double_answer) {
03882
03883
03884 res = openr2_chan_answer_call(p->r2chan);
03885 } else if (wants_double_answer) {
03886 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03887 } else {
03888 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03889 }
03890 #else
03891 res = openr2_chan_answer_call(p->r2chan);
03892 #endif
03893 return res;
03894 }
03895
03896
03897
03898
03899 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03900 {
03901 openr2_calling_party_category_t cat;
03902 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03903 struct dahdi_pvt *p = c->tech_pvt;
03904 if (ast_strlen_zero(catstr)) {
03905 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03906 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03907 return p->mfcr2_category;
03908 }
03909 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03910 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03911 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03912 return p->mfcr2_category;
03913 }
03914 ast_debug(1, "Using category %s\n", catstr);
03915 return cat;
03916 }
03917
03918 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03919 {
03920 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03921 ast_mutex_lock(&p->lock);
03922 if (p->mfcr2call) {
03923 ast_mutex_unlock(&p->lock);
03924
03925
03926
03927
03928
03929 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03930 return;
03931 }
03932 p->mfcr2call = 1;
03933
03934 p->cid_name[0] = '\0';
03935 p->cid_num[0] = '\0';
03936 p->cid_subaddr[0] = '\0';
03937 p->rdnis[0] = '\0';
03938 p->exten[0] = '\0';
03939 p->mfcr2_ani_index = '\0';
03940 p->mfcr2_dnis_index = '\0';
03941 p->mfcr2_dnis_matched = 0;
03942 p->mfcr2_answer_pending = 0;
03943 p->mfcr2_call_accepted = 0;
03944 ast_mutex_unlock(&p->lock);
03945 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03946 }
03947
03948 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03949 {
03950 int res;
03951 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03952 ast_mutex_lock(&p->lock);
03953 p->inalarm = alarm ? 1 : 0;
03954 if (p->inalarm) {
03955 res = get_alarms(p);
03956 handle_alarms(p, res);
03957 } else {
03958 handle_clear_alarms(p);
03959 }
03960 ast_mutex_unlock(&p->lock);
03961 }
03962
03963 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03964 {
03965 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03966 }
03967
03968 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03969 {
03970 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03971 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03972 if (p->owner) {
03973 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03974 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03975 }
03976 ast_mutex_lock(&p->lock);
03977 p->mfcr2call = 0;
03978 ast_mutex_unlock(&p->lock);
03979 }
03980
03981 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03982 {
03983 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03984 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03985 p->channel, openr2_proto_get_disconnect_string(cause));
03986
03987 openr2_chan_set_idle(p->r2chan);
03988 ast_mutex_lock(&p->lock);
03989 p->mfcr2call = 0;
03990 ast_mutex_unlock(&p->lock);
03991 }
03992 }
03993
03994 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03995 {
03996 struct dahdi_pvt *p;
03997 struct ast_channel *c;
03998 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03999 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04000 openr2_proto_get_category_string(category));
04001 p = openr2_chan_get_client_data(r2chan);
04002
04003 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04004 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04005 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04006 return;
04007 }
04008 ast_mutex_lock(&p->lock);
04009 p->mfcr2_recvd_category = category;
04010
04011 if (!p->use_callerid) {
04012 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04013 p->cid_num[0] = 0;
04014 p->cid_name[0] = 0;
04015 }
04016
04017 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04018 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04019 p->exten[0] = 's';
04020 p->exten[1] = 0;
04021 }
04022 ast_mutex_unlock(&p->lock);
04023 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04024 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04025 p->channel, p->exten, p->context);
04026 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04027 return;
04028 }
04029 if (!p->mfcr2_accept_on_offer) {
04030
04031 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04032 if (c) {
04033
04034
04035
04036 return;
04037 }
04038 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04039 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04040 } else if (p->mfcr2_charge_calls) {
04041 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04042 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04043 } else {
04044 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04045 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04046 }
04047 }
04048
04049 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04050 {
04051 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04052 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04053 ast_mutex_lock(&p->lock);
04054 p->mfcr2call = 0;
04055 ast_mutex_unlock(&p->lock);
04056 }
04057
04058 static void dahdi_enable_ec(struct dahdi_pvt *p);
04059 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04060 {
04061 struct dahdi_pvt *p = NULL;
04062 struct ast_channel *c = NULL;
04063 p = openr2_chan_get_client_data(r2chan);
04064 dahdi_enable_ec(p);
04065 p->mfcr2_call_accepted = 1;
04066
04067 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04068 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04069
04070
04071
04072
04073 if (!p->mfcr2_accept_on_offer) {
04074 openr2_chan_disable_read(r2chan);
04075 if (p->mfcr2_answer_pending) {
04076 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04077 dahdi_r2_answer(p);
04078 }
04079 return;
04080 }
04081 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04082 if (c) {
04083
04084
04085 openr2_chan_disable_read(r2chan);
04086 return;
04087 }
04088 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04089
04090 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04091 return;
04092 }
04093
04094 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04095 p->subs[SUB_REAL].needringing = 1;
04096 p->dialing = 0;
04097
04098 openr2_chan_disable_read(r2chan);
04099 }
04100
04101 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04102 {
04103 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04104 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04105 p->subs[SUB_REAL].needanswer = 1;
04106 }
04107
04108 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04109 {
04110
04111 }
04112
04113 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04114 {
04115 switch (cause) {
04116 case OR2_CAUSE_BUSY_NUMBER:
04117 return AST_CAUSE_BUSY;
04118 case OR2_CAUSE_NETWORK_CONGESTION:
04119 return AST_CAUSE_CONGESTION;
04120 case OR2_CAUSE_OUT_OF_ORDER:
04121 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04122 case OR2_CAUSE_UNALLOCATED_NUMBER:
04123 return AST_CAUSE_UNREGISTERED;
04124 case OR2_CAUSE_NO_ANSWER:
04125 return AST_CAUSE_NO_ANSWER;
04126 case OR2_CAUSE_NORMAL_CLEARING:
04127 return AST_CAUSE_NORMAL_CLEARING;
04128 case OR2_CAUSE_UNSPECIFIED:
04129 default:
04130 return AST_CAUSE_NOTDEFINED;
04131 }
04132 }
04133
04134 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04135 {
04136 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04137 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04138 ast_mutex_lock(&p->lock);
04139 if (!p->owner) {
04140 ast_mutex_unlock(&p->lock);
04141
04142 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04143 return;
04144 }
04145
04146
04147 if (p->owner->_state == AST_STATE_UP) {
04148 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04149 ast_mutex_unlock(&p->lock);
04150 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04151
04152 switch (cause) {
04153 case OR2_CAUSE_BUSY_NUMBER:
04154 p->subs[SUB_REAL].needbusy = 1;
04155 break;
04156 case OR2_CAUSE_NETWORK_CONGESTION:
04157 case OR2_CAUSE_OUT_OF_ORDER:
04158 case OR2_CAUSE_UNALLOCATED_NUMBER:
04159 case OR2_CAUSE_NO_ANSWER:
04160 case OR2_CAUSE_UNSPECIFIED:
04161 case OR2_CAUSE_NORMAL_CLEARING:
04162 p->subs[SUB_REAL].needcongestion = 1;
04163 break;
04164 default:
04165 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04166 }
04167 ast_mutex_unlock(&p->lock);
04168 } else {
04169 ast_mutex_unlock(&p->lock);
04170
04171
04172 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04173 }
04174 }
04175
04176 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04177 {
04178 switch (level) {
04179 case OR2_LOG_NOTICE:
04180 ast_verbose("%s", logmessage);
04181 break;
04182 case OR2_LOG_WARNING:
04183 ast_log(LOG_WARNING, "%s", logmessage);
04184 break;
04185 case OR2_LOG_ERROR:
04186 ast_log(LOG_ERROR, "%s", logmessage);
04187 break;
04188 case OR2_LOG_STACK_TRACE:
04189 case OR2_LOG_MF_TRACE:
04190 case OR2_LOG_CAS_TRACE:
04191 case OR2_LOG_DEBUG:
04192 case OR2_LOG_EX_DEBUG:
04193 ast_log(LOG_DEBUG, "%s", logmessage);
04194 break;
04195 default:
04196 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04197 ast_log(LOG_DEBUG, "%s", logmessage);
04198 break;
04199 }
04200 }
04201
04202 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04203 {
04204 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04205 ast_mutex_lock(&p->lock);
04206 p->remotelyblocked = 1;
04207 ast_mutex_unlock(&p->lock);
04208 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04209 }
04210
04211 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04212 {
04213 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04214 ast_mutex_lock(&p->lock);
04215 p->remotelyblocked = 0;
04216 ast_mutex_unlock(&p->lock);
04217 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04218 }
04219
04220 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04221 __attribute__((format (printf, 3, 0)));
04222 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04223 {
04224 #define CONTEXT_TAG "Context - "
04225 char logmsg[256];
04226 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04227 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04228 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04229 dahdi_r2_write_log(level, completemsg);
04230 #undef CONTEXT_TAG
04231 }
04232
04233 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04234 __attribute__((format (printf, 3, 0)));
04235 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04236 {
04237 #define CHAN_TAG "Chan "
04238 char logmsg[256];
04239 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04240 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04241 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04242 dahdi_r2_write_log(level, completemsg);
04243 }
04244
04245 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04246 {
04247 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04248
04249 if (p->immediate) {
04250 return 0;
04251 }
04252 p->exten[p->mfcr2_dnis_index] = digit;
04253 p->rdnis[p->mfcr2_dnis_index] = digit;
04254 p->mfcr2_dnis_index++;
04255 p->exten[p->mfcr2_dnis_index] = 0;
04256 p->rdnis[p->mfcr2_dnis_index] = 0;
04257
04258 if ((p->mfcr2_dnis_matched ||
04259 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04260 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04261 return 0;
04262 }
04263
04264 return 1;
04265 }
04266
04267 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04268 {
04269 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04270 p->cid_num[p->mfcr2_ani_index] = digit;
04271 p->cid_name[p->mfcr2_ani_index] = digit;
04272 p->mfcr2_ani_index++;
04273 p->cid_num[p->mfcr2_ani_index] = 0;
04274 p->cid_name[p->mfcr2_ani_index] = 0;
04275 }
04276
04277 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04278 {
04279 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04280 }
04281
04282 static openr2_event_interface_t dahdi_r2_event_iface = {
04283 .on_call_init = dahdi_r2_on_call_init,
04284 .on_call_offered = dahdi_r2_on_call_offered,
04285 .on_call_accepted = dahdi_r2_on_call_accepted,
04286 .on_call_answered = dahdi_r2_on_call_answered,
04287 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04288 .on_call_end = dahdi_r2_on_call_end,
04289 .on_call_read = dahdi_r2_on_call_read,
04290 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04291 .on_os_error = dahdi_r2_on_os_error,
04292 .on_protocol_error = dahdi_r2_on_protocol_error,
04293 .on_line_blocked = dahdi_r2_on_line_blocked,
04294 .on_line_idle = dahdi_r2_on_line_idle,
04295
04296 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04297 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04298 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04299
04300 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04301 };
04302
04303 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04304 {
04305 return AST_ALAW(sample);
04306 }
04307
04308 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04309 {
04310 return AST_LIN2A(sample);
04311 }
04312
04313 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04314 dahdi_r2_alaw_to_linear,
04315 dahdi_r2_linear_to_alaw
04316 };
04317
04318 #endif
04319
04320 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04321 {
04322 int tchan;
04323 int tinthreeway;
04324 struct ast_channel *towner;
04325
04326 ast_debug(1, "Swapping %d and %d\n", a, b);
04327
04328 tchan = p->subs[a].chan;
04329 towner = p->subs[a].owner;
04330 tinthreeway = p->subs[a].inthreeway;
04331
04332 p->subs[a].chan = p->subs[b].chan;
04333 p->subs[a].owner = p->subs[b].owner;
04334 p->subs[a].inthreeway = p->subs[b].inthreeway;
04335
04336 p->subs[b].chan = tchan;
04337 p->subs[b].owner = towner;
04338 p->subs[b].inthreeway = tinthreeway;
04339
04340 if (p->subs[a].owner)
04341 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04342 if (p->subs[b].owner)
04343 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04344 wakeup_sub(p, a);
04345 wakeup_sub(p, b);
04346 }
04347
04348 static int dahdi_open(char *fn)
04349 {
04350 int fd;
04351 int isnum;
04352 int chan = 0;
04353 int bs;
04354 int x;
04355 isnum = 1;
04356 for (x = 0; x < strlen(fn); x++) {
04357 if (!isdigit(fn[x])) {
04358 isnum = 0;
04359 break;
04360 }
04361 }
04362 if (isnum) {
04363 chan = atoi(fn);
04364 if (chan < 1) {
04365 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04366 return -1;
04367 }
04368 fn = "/dev/dahdi/channel";
04369 }
04370 fd = open(fn, O_RDWR | O_NONBLOCK);
04371 if (fd < 0) {
04372 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04373 return -1;
04374 }
04375 if (chan) {
04376 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04377 x = errno;
04378 close(fd);
04379 errno = x;
04380 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04381 return -1;
04382 }
04383 }
04384 bs = READ_SIZE;
04385 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04386 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04387 x = errno;
04388 close(fd);
04389 errno = x;
04390 return -1;
04391 }
04392 return fd;
04393 }
04394
04395 static void dahdi_close(int fd)
04396 {
04397 if (fd > 0)
04398 close(fd);
04399 }
04400
04401 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04402 {
04403 dahdi_close(chan_pvt->subs[sub_num].dfd);
04404 chan_pvt->subs[sub_num].dfd = -1;
04405 }
04406
04407 #if defined(HAVE_PRI)
04408 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04409 {
04410 dahdi_close(pri->pri.fds[fd_num]);
04411 pri->pri.fds[fd_num] = -1;
04412 }
04413 #endif
04414
04415 #if defined(HAVE_SS7)
04416 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04417 {
04418 dahdi_close(ss7->ss7.fds[fd_num]);
04419 ss7->ss7.fds[fd_num] = -1;
04420 }
04421 #endif
04422
04423 static int dahdi_setlinear(int dfd, int linear)
04424 {
04425 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04426 }
04427
04428
04429 static int alloc_sub(struct dahdi_pvt *p, int x)
04430 {
04431 struct dahdi_bufferinfo bi;
04432 int res;
04433 if (p->subs[x].dfd >= 0) {
04434 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04435 return -1;
04436 }
04437
04438 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04439 if (p->subs[x].dfd <= -1) {
04440 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04441 return -1;
04442 }
04443
04444 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04445 if (!res) {
04446 bi.txbufpolicy = p->buf_policy;
04447 bi.rxbufpolicy = p->buf_policy;
04448 bi.numbufs = p->buf_no;
04449 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04450 if (res < 0) {
04451 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04452 }
04453 } else
04454 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04455
04456 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04457 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04458 dahdi_close_sub(p, x);
04459 p->subs[x].dfd = -1;
04460 return -1;
04461 }
04462 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04463 return 0;
04464 }
04465
04466 static int unalloc_sub(struct dahdi_pvt *p, int x)
04467 {
04468 if (!x) {
04469 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04470 return -1;
04471 }
04472 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04473 dahdi_close_sub(p, x);
04474 p->subs[x].linear = 0;
04475 p->subs[x].chan = 0;
04476 p->subs[x].owner = NULL;
04477 p->subs[x].inthreeway = 0;
04478 p->polarity = POLARITY_IDLE;
04479 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04480 return 0;
04481 }
04482
04483 static int digit_to_dtmfindex(char digit)
04484 {
04485 if (isdigit(digit))
04486 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04487 else if (digit >= 'A' && digit <= 'D')
04488 return DAHDI_TONE_DTMF_A + (digit - 'A');
04489 else if (digit >= 'a' && digit <= 'd')
04490 return DAHDI_TONE_DTMF_A + (digit - 'a');
04491 else if (digit == '*')
04492 return DAHDI_TONE_DTMF_s;
04493 else if (digit == '#')
04494 return DAHDI_TONE_DTMF_p;
04495 else
04496 return -1;
04497 }
04498
04499 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04500 {
04501 struct dahdi_pvt *pvt;
04502 int idx;
04503 int dtmf = -1;
04504 int res;
04505
04506 pvt = chan->tech_pvt;
04507
04508 ast_mutex_lock(&pvt->lock);
04509
04510 idx = dahdi_get_index(chan, pvt, 0);
04511
04512 if ((idx != SUB_REAL) || !pvt->owner)
04513 goto out;
04514
04515 #ifdef HAVE_PRI
04516 switch (pvt->sig) {
04517 case SIG_PRI_LIB_HANDLE_CASES:
04518 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04519 if (!res)
04520 goto out;
04521 break;
04522 default:
04523 break;
04524 }
04525 #endif
04526 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04527 goto out;
04528
04529 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04530 struct dahdi_dialoperation zo = {
04531 .op = DAHDI_DIAL_OP_APPEND,
04532 };
04533
04534 zo.dialstr[0] = 'T';
04535 zo.dialstr[1] = digit;
04536 zo.dialstr[2] = '\0';
04537 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04538 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04539 chan->name, digit, strerror(errno));
04540 else
04541 pvt->dialing = 1;
04542 } else {
04543 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04544 chan->name, digit);
04545 pvt->dialing = 1;
04546 pvt->begindigit = digit;
04547 }
04548
04549 out:
04550 ast_mutex_unlock(&pvt->lock);
04551
04552 return 0;
04553 }
04554
04555 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04556 {
04557 struct dahdi_pvt *pvt;
04558 int res = 0;
04559 int idx;
04560 int x;
04561
04562 pvt = chan->tech_pvt;
04563
04564 ast_mutex_lock(&pvt->lock);
04565
04566 idx = dahdi_get_index(chan, pvt, 0);
04567
04568 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04569 goto out;
04570
04571 #ifdef HAVE_PRI
04572
04573 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04574 goto out;
04575 }
04576 #endif
04577
04578 if (pvt->begindigit) {
04579 x = -1;
04580 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04581 chan->name, digit);
04582 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04583 pvt->dialing = 0;
04584 pvt->begindigit = 0;
04585 }
04586
04587 out:
04588 ast_mutex_unlock(&pvt->lock);
04589
04590 return res;
04591 }
04592
04593 static const char * const events[] = {
04594 "No event",
04595 "On hook",
04596 "Ring/Answered",
04597 "Wink/Flash",
04598 "Alarm",
04599 "No more alarm",
04600 "HDLC Abort",
04601 "HDLC Overrun",
04602 "HDLC Bad FCS",
04603 "Dial Complete",
04604 "Ringer On",
04605 "Ringer Off",
04606 "Hook Transition Complete",
04607 "Bits Changed",
04608 "Pulse Start",
04609 "Timer Expired",
04610 "Timer Ping",
04611 "Polarity Reversal",
04612 "Ring Begin",
04613 };
04614
04615 static struct {
04616 int alarm;
04617 char *name;
04618 } alarms[] = {
04619 { DAHDI_ALARM_RED, "Red Alarm" },
04620 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04621 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04622 { DAHDI_ALARM_RECOVER, "Recovering" },
04623 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04624 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04625 { DAHDI_ALARM_NONE, "None" },
04626 };
04627
04628 static char *alarm2str(int alm)
04629 {
04630 int x;
04631 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04632 if (alarms[x].alarm & alm)
04633 return alarms[x].name;
04634 }
04635 return alm ? "Unknown Alarm" : "No Alarm";
04636 }
04637
04638 static const char *event2str(int event)
04639 {
04640 static char buf[256];
04641 if ((event < (ARRAY_LEN(events))) && (event > -1))
04642 return events[event];
04643 sprintf(buf, "Event %d", event);
04644 return buf;
04645 }
04646
04647 static char *dahdi_sig2str(int sig)
04648 {
04649 static char buf[256];
04650 switch (sig) {
04651 case SIG_EM:
04652 return "E & M Immediate";
04653 case SIG_EMWINK:
04654 return "E & M Wink";
04655 case SIG_EM_E1:
04656 return "E & M E1";
04657 case SIG_FEATD:
04658 return "Feature Group D (DTMF)";
04659 case SIG_FEATDMF:
04660 return "Feature Group D (MF)";
04661 case SIG_FEATDMF_TA:
04662 return "Feature Groud D (MF) Tandem Access";
04663 case SIG_FEATB:
04664 return "Feature Group B (MF)";
04665 case SIG_E911:
04666 return "E911 (MF)";
04667 case SIG_FGC_CAMA:
04668 return "FGC/CAMA (Dialpulse)";
04669 case SIG_FGC_CAMAMF:
04670 return "FGC/CAMA (MF)";
04671 case SIG_FXSLS:
04672 return "FXS Loopstart";
04673 case SIG_FXSGS:
04674 return "FXS Groundstart";
04675 case SIG_FXSKS:
04676 return "FXS Kewlstart";
04677 case SIG_FXOLS:
04678 return "FXO Loopstart";
04679 case SIG_FXOGS:
04680 return "FXO Groundstart";
04681 case SIG_FXOKS:
04682 return "FXO Kewlstart";
04683 case SIG_PRI:
04684 return "ISDN PRI";
04685 case SIG_BRI:
04686 return "ISDN BRI Point to Point";
04687 case SIG_BRI_PTMP:
04688 return "ISDN BRI Point to MultiPoint";
04689 case SIG_SS7:
04690 return "SS7";
04691 case SIG_MFCR2:
04692 return "MFC/R2";
04693 case SIG_SF:
04694 return "SF (Tone) Immediate";
04695 case SIG_SFWINK:
04696 return "SF (Tone) Wink";
04697 case SIG_SF_FEATD:
04698 return "SF (Tone) with Feature Group D (DTMF)";
04699 case SIG_SF_FEATDMF:
04700 return "SF (Tone) with Feature Group D (MF)";
04701 case SIG_SF_FEATB:
04702 return "SF (Tone) with Feature Group B (MF)";
04703 case 0:
04704 return "Pseudo";
04705 default:
04706 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04707 return buf;
04708 }
04709 }
04710
04711 #define sig2str dahdi_sig2str
04712
04713 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04714 {
04715
04716
04717 struct dahdi_confinfo zi;
04718
04719 memset(&zi, 0, sizeof(zi));
04720 zi.chan = 0;
04721
04722 if (slavechannel > 0) {
04723
04724 zi.confmode = DAHDI_CONF_DIGITALMON;
04725 zi.confno = slavechannel;
04726 } else {
04727 if (!idx) {
04728
04729 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04730 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04731 } else
04732 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04733 zi.confno = p->confno;
04734 }
04735 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04736 return 0;
04737 if (c->dfd < 0)
04738 return 0;
04739 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04740 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04741 return -1;
04742 }
04743 if (slavechannel < 1) {
04744 p->confno = zi.confno;
04745 }
04746 c->curconf = zi;
04747 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04748 return 0;
04749 }
04750
04751 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04752 {
04753
04754 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04755 return 1;
04756
04757 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04758 return 1;
04759 return 0;
04760 }
04761
04762 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04763 {
04764 struct dahdi_confinfo zi;
04765 if (
04766 (c->dfd < 0) ||
04767
04768 !isourconf(p, c)
04769
04770 ) return 0;
04771 memset(&zi, 0, sizeof(zi));
04772 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04773 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04774 return -1;
04775 }
04776 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04777 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04778 return 0;
04779 }
04780
04781 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04782 {
04783 int x;
04784 int useslavenative;
04785 struct dahdi_pvt *slave = NULL;
04786
04787 useslavenative = 1;
04788
04789 for (x = 0; x < 3; x++) {
04790
04791
04792 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04793 useslavenative = 0;
04794 }
04795
04796
04797 if (useslavenative) {
04798 for (x = 0; x < MAX_SLAVES; x++) {
04799 if (p->slaves[x]) {
04800 if (slave) {
04801
04802
04803 slave = NULL;
04804 useslavenative = 0;
04805 break;
04806 } else {
04807
04808 slave = p->slaves[x];
04809 }
04810 }
04811 }
04812 }
04813
04814 if (!slave)
04815 useslavenative = 0;
04816 else if (slave->law != p->law) {
04817 useslavenative = 0;
04818 slave = NULL;
04819 }
04820 if (out)
04821 *out = slave;
04822 return useslavenative;
04823 }
04824
04825 static int reset_conf(struct dahdi_pvt *p)
04826 {
04827 p->confno = -1;
04828 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04829 if (p->subs[SUB_REAL].dfd > -1) {
04830 struct dahdi_confinfo zi;
04831
04832 memset(&zi, 0, sizeof(zi));
04833 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04834 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04835 }
04836 return 0;
04837 }
04838
04839 static int update_conf(struct dahdi_pvt *p)
04840 {
04841 int needconf = 0;
04842 int x;
04843 int useslavenative;
04844 struct dahdi_pvt *slave = NULL;
04845
04846 useslavenative = isslavenative(p, &slave);
04847
04848 for (x = 0; x < 3; x++) {
04849
04850 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04851 conf_add(p, &p->subs[x], x, 0);
04852 needconf++;
04853 } else {
04854 conf_del(p, &p->subs[x], x);
04855 }
04856 }
04857
04858
04859 for (x = 0; x < MAX_SLAVES; x++) {
04860 if (p->slaves[x]) {
04861 if (useslavenative)
04862 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04863 else {
04864 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04865 needconf++;
04866 }
04867 }
04868 }
04869
04870 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04871 if (useslavenative)
04872 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04873 else {
04874 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04875 needconf++;
04876 }
04877 }
04878
04879 if (p->master) {
04880 if (isslavenative(p->master, NULL)) {
04881 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04882 } else {
04883 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04884 }
04885 }
04886 if (!needconf) {
04887
04888
04889 p->confno = -1;
04890 }
04891 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04892 return 0;
04893 }
04894
04895 static void dahdi_enable_ec(struct dahdi_pvt *p)
04896 {
04897 int res;
04898 if (!p)
04899 return;
04900 if (p->echocanon) {
04901 ast_debug(1, "Echo cancellation already on\n");
04902 return;
04903 }
04904 if (p->digital) {
04905 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04906 return;
04907 }
04908 if (p->echocancel.head.tap_length) {
04909 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04910 switch (p->sig) {
04911 #if defined(HAVE_PRI)
04912 case SIG_PRI_LIB_HANDLE_CASES:
04913 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04914
04915
04916
04917
04918 return;
04919 }
04920
04921 #endif
04922 #if defined(HAVE_SS7)
04923 case SIG_SS7:
04924 #endif
04925 {
04926 int x = 1;
04927
04928 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04929 if (res)
04930 ast_log(LOG_WARNING,
04931 "Unable to enable audio mode on channel %d (%s)\n",
04932 p->channel, strerror(errno));
04933 }
04934 break;
04935 default:
04936 break;
04937 }
04938 #endif
04939 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04940 if (res) {
04941 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04942 } else {
04943 p->echocanon = 1;
04944 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04945 }
04946 } else
04947 ast_debug(1, "No echo cancellation requested\n");
04948 }
04949
04950 static void dahdi_train_ec(struct dahdi_pvt *p)
04951 {
04952 int x;
04953 int res;
04954
04955 if (p && p->echocanon && p->echotraining) {
04956 x = p->echotraining;
04957 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04958 if (res)
04959 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04960 else
04961 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04962 } else {
04963 ast_debug(1, "No echo training requested\n");
04964 }
04965 }
04966
04967 static void dahdi_disable_ec(struct dahdi_pvt *p)
04968 {
04969 int res;
04970
04971 if (p->echocanon) {
04972 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04973
04974 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04975
04976 if (res)
04977 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04978 else
04979 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04980 }
04981
04982 p->echocanon = 0;
04983 }
04984
04985
04986 static int drc_sample(int sample, float drc)
04987 {
04988 float neg;
04989 float shallow, steep;
04990 float max = SHRT_MAX;
04991
04992 neg = (sample < 0 ? -1 : 1);
04993 steep = drc*sample;
04994 shallow = neg*(max-max/drc)+(float)sample/drc;
04995 if (abs(steep) < abs(shallow)) {
04996 sample = steep;
04997 }
04998 else {
04999 sample = shallow;
05000 }
05001
05002 return sample;
05003 }
05004
05005
05006 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05007 {
05008 int j;
05009 int k;
05010
05011 float linear_gain = pow(10.0, gain / 20.0);
05012
05013 switch (law) {
05014 case DAHDI_LAW_ALAW:
05015 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05016 if (gain || drc) {
05017 k = AST_ALAW(j);
05018 if (drc) {
05019 k = drc_sample(k, drc);
05020 }
05021 k = (float)k * linear_gain;
05022 if (k > 32767) {
05023 k = 32767;
05024 } else if (k < -32768) {
05025 k = -32768;
05026 }
05027 g->txgain[j] = AST_LIN2A(k);
05028 } else {
05029 g->txgain[j] = j;
05030 }
05031 }
05032 break;
05033 case DAHDI_LAW_MULAW:
05034 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05035 if (gain || drc) {
05036 k = AST_MULAW(j);
05037 if (drc) {
05038 k = drc_sample(k, drc);
05039 }
05040 k = (float)k * linear_gain;
05041 if (k > 32767) {
05042 k = 32767;
05043 } else if (k < -32768) {
05044 k = -32768;
05045 }
05046 g->txgain[j] = AST_LIN2MU(k);
05047
05048 } else {
05049 g->txgain[j] = j;
05050 }
05051 }
05052 break;
05053 }
05054 }
05055
05056 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05057 {
05058 int j;
05059 int k;
05060 float linear_gain = pow(10.0, gain / 20.0);
05061
05062 switch (law) {
05063 case DAHDI_LAW_ALAW:
05064 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05065 if (gain || drc) {
05066 k = AST_ALAW(j);
05067 if (drc) {
05068 k = drc_sample(k, drc);
05069 }
05070 k = (float)k * linear_gain;
05071 if (k > 32767) {
05072 k = 32767;
05073 } else if (k < -32768) {
05074 k = -32768;
05075 }
05076 g->rxgain[j] = AST_LIN2A(k);
05077 } else {
05078 g->rxgain[j] = j;
05079 }
05080 }
05081 break;
05082 case DAHDI_LAW_MULAW:
05083 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05084 if (gain || drc) {
05085 k = AST_MULAW(j);
05086 if (drc) {
05087 k = drc_sample(k, drc);
05088 }
05089 k = (float)k * linear_gain;
05090 if (k > 32767) {
05091 k = 32767;
05092 } else if (k < -32768) {
05093 k = -32768;
05094 }
05095 g->rxgain[j] = AST_LIN2MU(k);
05096 } else {
05097 g->rxgain[j] = j;
05098 }
05099 }
05100 break;
05101 }
05102 }
05103
05104 static int set_actual_txgain(int fd, float gain, float drc, int law)
05105 {
05106 struct dahdi_gains g;
05107 int res;
05108
05109 memset(&g, 0, sizeof(g));
05110 res = ioctl(fd, DAHDI_GETGAINS, &g);
05111 if (res) {
05112 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05113 return res;
05114 }
05115
05116 fill_txgain(&g, gain, drc, law);
05117
05118 return ioctl(fd, DAHDI_SETGAINS, &g);
05119 }
05120
05121 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05122 {
05123 struct dahdi_gains g;
05124 int res;
05125
05126 memset(&g, 0, sizeof(g));
05127 res = ioctl(fd, DAHDI_GETGAINS, &g);
05128 if (res) {
05129 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05130 return res;
05131 }
05132
05133 fill_rxgain(&g, gain, drc, law);
05134
05135 return ioctl(fd, DAHDI_SETGAINS, &g);
05136 }
05137
05138 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05139 {
05140 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05141 }
05142
05143 static int bump_gains(struct dahdi_pvt *p)
05144 {
05145 int res;
05146
05147
05148 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05149 if (res) {
05150 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05151 return -1;
05152 }
05153
05154 return 0;
05155 }
05156
05157 static int restore_gains(struct dahdi_pvt *p)
05158 {
05159 int res;
05160
05161 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05162 if (res) {
05163 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05164 return -1;
05165 }
05166
05167 return 0;
05168 }
05169
05170 static inline int dahdi_set_hook(int fd, int hs)
05171 {
05172 int x, res;
05173
05174 x = hs;
05175 res = ioctl(fd, DAHDI_HOOK, &x);
05176
05177 if (res < 0) {
05178 if (errno == EINPROGRESS)
05179 return 0;
05180 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05181
05182 }
05183
05184 return res;
05185 }
05186
05187 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05188 {
05189 int x, res;
05190
05191 x = muted;
05192 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05193 switch (p->sig) {
05194 #if defined(HAVE_PRI)
05195 case SIG_PRI_LIB_HANDLE_CASES:
05196 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05197
05198 break;
05199 }
05200
05201 #endif
05202 #if defined(HAVE_SS7)
05203 case SIG_SS7:
05204 #endif
05205 {
05206 int y = 1;
05207
05208 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05209 if (res)
05210 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05211 p->channel, strerror(errno));
05212 }
05213 break;
05214 default:
05215 break;
05216 }
05217 #endif
05218 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05219 if (res < 0)
05220 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05221 return res;
05222 }
05223
05224 static int save_conference(struct dahdi_pvt *p)
05225 {
05226 struct dahdi_confinfo c;
05227 int res;
05228 if (p->saveconf.confmode) {
05229 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05230 return -1;
05231 }
05232 p->saveconf.chan = 0;
05233 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05234 if (res) {
05235 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05236 p->saveconf.confmode = 0;
05237 return -1;
05238 }
05239 memset(&c, 0, sizeof(c));
05240 c.confmode = DAHDI_CONF_NORMAL;
05241 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05242 if (res) {
05243 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05244 return -1;
05245 }
05246 ast_debug(1, "Disabled conferencing\n");
05247 return 0;
05248 }
05249
05250 static int restore_conference(struct dahdi_pvt *p)
05251 {
05252 int res;
05253 if (p->saveconf.confmode) {
05254 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05255 p->saveconf.confmode = 0;
05256 if (res) {
05257 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05258 return -1;
05259 }
05260 ast_debug(1, "Restored conferencing\n");
05261 }
05262 return 0;
05263 }
05264
05265 static int send_cwcidspill(struct dahdi_pvt *p)
05266 {
05267 p->callwaitcas = 0;
05268 p->cidcwexpire = 0;
05269 p->cid_suppress_expire = 0;
05270 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05271 return -1;
05272 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05273
05274 p->cidlen += READ_SIZE * 4;
05275 p->cidpos = 0;
05276 send_callerid(p);
05277 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05278 return 0;
05279 }
05280
05281 static int has_voicemail(struct dahdi_pvt *p)
05282 {
05283 int new_msgs;
05284 struct ast_event *event;
05285 char *mailbox, *context;
05286
05287 mailbox = context = ast_strdupa(p->mailbox);
05288 strsep(&context, "@");
05289 if (ast_strlen_zero(context))
05290 context = "default";
05291
05292 event = ast_event_get_cached(AST_EVENT_MWI,
05293 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05294 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05295 AST_EVENT_IE_END);
05296
05297 if (event) {
05298 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05299 ast_event_destroy(event);
05300 } else
05301 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05302
05303 return new_msgs;
05304 }
05305
05306
05307
05308 static int send_callerid(struct dahdi_pvt *p)
05309 {
05310
05311 int res;
05312
05313 if (p->subs[SUB_REAL].linear) {
05314 p->subs[SUB_REAL].linear = 0;
05315 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05316 }
05317 while (p->cidpos < p->cidlen) {
05318 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05319 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05320 if (res < 0) {
05321 if (errno == EAGAIN)
05322 return 0;
05323 else {
05324 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05325 return -1;
05326 }
05327 }
05328 if (!res)
05329 return 0;
05330 p->cidpos += res;
05331 }
05332 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05333 ast_free(p->cidspill);
05334 p->cidspill = NULL;
05335 if (p->callwaitcas) {
05336
05337 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05338 p->cid_suppress_expire = p->cidcwexpire;
05339 } else
05340 restore_conference(p);
05341 return 0;
05342 }
05343
05344 static int dahdi_callwait(struct ast_channel *ast)
05345 {
05346 struct dahdi_pvt *p = ast->tech_pvt;
05347 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05348 if (p->cidspill) {
05349 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05350 ast_free(p->cidspill);
05351 }
05352
05353
05354
05355
05356
05357 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05358 return -1;
05359 save_conference(p);
05360
05361 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05362 if (!p->callwaitrings && p->callwaitingcallerid) {
05363 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05364 p->callwaitcas = 1;
05365 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05366 } else {
05367 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05368 p->callwaitcas = 0;
05369 p->cidlen = 2400 + READ_SIZE * 4;
05370 }
05371 p->cidpos = 0;
05372 send_callerid(p);
05373
05374 return 0;
05375 }
05376
05377 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05378 {
05379 struct dahdi_pvt *p = ast->tech_pvt;
05380 int x, res, mysig;
05381 char dest[256];
05382
05383 ast_mutex_lock(&p->lock);
05384 ast_copy_string(dest, rdest, sizeof(dest));
05385 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05386 if ((ast->_state == AST_STATE_BUSY)) {
05387 p->subs[SUB_REAL].needbusy = 1;
05388 ast_mutex_unlock(&p->lock);
05389 return 0;
05390 }
05391 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05392 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05393 ast_mutex_unlock(&p->lock);
05394 return -1;
05395 }
05396 p->waitingfordt.tv_sec = 0;
05397 p->dialednone = 0;
05398 if ((p->radio || (p->oprmode < 0)))
05399 {
05400
05401 ast_setstate(ast, AST_STATE_UP);
05402 ast_mutex_unlock(&p->lock);
05403 return 0;
05404 }
05405 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05406 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05407 if (res)
05408 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05409 p->outgoing = 1;
05410
05411 if (IS_DIGITAL(ast->transfercapability)){
05412 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05413 } else {
05414 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05415 }
05416
05417 #ifdef HAVE_PRI
05418 if (dahdi_sig_pri_lib_handles(p->sig)) {
05419 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05420 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05421 ast_mutex_unlock(&p->lock);
05422 return res;
05423 }
05424 #endif
05425
05426 #if defined(HAVE_SS7)
05427 if (p->sig == SIG_SS7) {
05428 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05429 ast_mutex_unlock(&p->lock);
05430 return res;
05431 }
05432 #endif
05433
05434
05435 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05436 p->callwaitrings = 0;
05437 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05438 ast_mutex_unlock(&p->lock);
05439 return res;
05440 }
05441
05442 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05443 switch (mysig) {
05444 case 0:
05445
05446 ast_setstate(ast, AST_STATE_UP);
05447 break;
05448 case SIG_MFCR2:
05449 break;
05450 default:
05451 ast_debug(1, "not yet implemented\n");
05452 ast_mutex_unlock(&p->lock);
05453 return -1;
05454 }
05455
05456 #ifdef HAVE_OPENR2
05457 if (p->mfcr2) {
05458 openr2_calling_party_category_t chancat;
05459 int callres = 0;
05460 char *c, *l;
05461
05462
05463 p->dialdest[0] = '\0';
05464
05465 c = strchr(dest, '/');
05466 if (c) {
05467 c++;
05468 } else {
05469 c = "";
05470 }
05471 if (!p->hidecallerid) {
05472 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05473 } else {
05474 l = NULL;
05475 }
05476 if (strlen(c) < p->stripmsd) {
05477 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05478 ast_mutex_unlock(&p->lock);
05479 return -1;
05480 }
05481 p->dialing = 1;
05482 chancat = dahdi_r2_get_channel_category(ast);
05483 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05484 if (-1 == callres) {
05485 ast_mutex_unlock(&p->lock);
05486 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05487 return -1;
05488 }
05489 p->mfcr2_call_accepted = 0;
05490 p->mfcr2_progress = 0;
05491 ast_setstate(ast, AST_STATE_DIALING);
05492 }
05493 #endif
05494 ast_mutex_unlock(&p->lock);
05495 return 0;
05496 }
05497
05498
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05514 {
05515 struct dahdi_pvt *cur;
05516
05517 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05518
05519
05520 for (cur = iflist; cur; cur = cur->next) {
05521 if (pvt->channel < cur->channel) {
05522
05523 pvt->prev = cur->prev;
05524 pvt->next = cur;
05525 if (cur->prev) {
05526
05527 cur->prev->next = pvt;
05528 } else {
05529
05530 iflist = pvt;
05531 }
05532 cur->prev = pvt;
05533 return;
05534 }
05535 }
05536
05537
05538 pvt->prev = ifend;
05539 pvt->next = NULL;
05540 if (ifend) {
05541 ifend->next = pvt;
05542 }
05543 ifend = pvt;
05544 if (!iflist) {
05545
05546 iflist = pvt;
05547 }
05548 }
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05564 {
05565
05566 if (pvt->prev) {
05567 pvt->prev->next = pvt->next;
05568 } else if (iflist == pvt) {
05569
05570 iflist = pvt->next;
05571 }
05572
05573
05574 if (pvt->next) {
05575 pvt->next->prev = pvt->prev;
05576 } else if (ifend == pvt) {
05577
05578 ifend = pvt->prev;
05579 }
05580
05581
05582 pvt->which_iflist = DAHDI_IFLIST_NONE;
05583 pvt->prev = NULL;
05584 pvt->next = NULL;
05585 }
05586
05587 #if defined(HAVE_PRI)
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599
05600
05601
05602
05603
05604 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05605 {
05606 struct dahdi_pvt *cur;
05607
05608 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05609
05610
05611 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05612 if (pvt->channel < cur->channel) {
05613
05614 pvt->prev = cur->prev;
05615 pvt->next = cur;
05616 if (cur->prev) {
05617
05618 cur->prev->next = pvt;
05619 } else {
05620
05621 pri->no_b_chan_iflist = pvt;
05622 }
05623 cur->prev = pvt;
05624 return;
05625 }
05626 }
05627
05628
05629 pvt->prev = pri->no_b_chan_end;
05630 pvt->next = NULL;
05631 if (pri->no_b_chan_end) {
05632 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05633 }
05634 pri->no_b_chan_end = pvt;
05635 if (!pri->no_b_chan_iflist) {
05636
05637 pri->no_b_chan_iflist = pvt;
05638 }
05639 }
05640 #endif
05641
05642 #if defined(HAVE_PRI)
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653
05654
05655
05656
05657 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05658 {
05659
05660 if (pvt->prev) {
05661 pvt->prev->next = pvt->next;
05662 } else if (pri->no_b_chan_iflist == pvt) {
05663
05664 pri->no_b_chan_iflist = pvt->next;
05665 }
05666
05667
05668 if (pvt->next) {
05669 pvt->next->prev = pvt->prev;
05670 } else if (pri->no_b_chan_end == pvt) {
05671
05672 pri->no_b_chan_end = pvt->prev;
05673 }
05674
05675
05676 pvt->which_iflist = DAHDI_IFLIST_NONE;
05677 pvt->prev = NULL;
05678 pvt->next = NULL;
05679 }
05680 #endif
05681
05682 #if defined(HAVE_PRI)
05683
05684
05685
05686
05687
05688
05689
05690
05691
05692 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05693 {
05694 unsigned idx;
05695 struct sig_pri_span *pri;
05696
05697 pri = pvt->pri;
05698 if (!pri) {
05699
05700 return;
05701 }
05702 ast_mutex_lock(&pri->lock);
05703 for (idx = 0; idx < pri->numchans; ++idx) {
05704 if (pri->pvts[idx] == pvt->sig_pvt) {
05705 pri->pvts[idx] = NULL;
05706 ast_mutex_unlock(&pri->lock);
05707 return;
05708 }
05709 }
05710 ast_mutex_unlock(&pri->lock);
05711 }
05712 #endif
05713
05714 #if defined(HAVE_SS7)
05715
05716
05717
05718
05719
05720
05721
05722
05723
05724 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05725 {
05726 unsigned idx;
05727 struct sig_ss7_linkset *ss7;
05728
05729 ss7 = pvt->ss7;
05730 if (!ss7) {
05731
05732 return;
05733 }
05734 ast_mutex_lock(&ss7->lock);
05735 for (idx = 0; idx < ss7->numchans; ++idx) {
05736 if (ss7->pvts[idx] == pvt->sig_pvt) {
05737 ss7->pvts[idx] = NULL;
05738 ast_mutex_unlock(&ss7->lock);
05739 return;
05740 }
05741 }
05742 ast_mutex_unlock(&ss7->lock);
05743 }
05744 #endif
05745
05746 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05747 {
05748 if (cur->next && cur->next->span == cur->span) {
05749 return cur->next;
05750 } else if (cur->prev && cur->prev->span == cur->span) {
05751 return cur->prev;
05752 }
05753
05754 return NULL;
05755 }
05756
05757 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05758 {
05759 struct dahdi_pvt *p = pvt;
05760
05761 if (p->manages_span_alarms) {
05762 struct dahdi_pvt *next = find_next_iface_in_span(p);
05763 if (next) {
05764 next->manages_span_alarms = 1;
05765 }
05766 }
05767
05768
05769 #if defined(HAVE_PRI)
05770 dahdi_unlink_pri_pvt(p);
05771 #endif
05772 #if defined(HAVE_SS7)
05773 dahdi_unlink_ss7_pvt(p);
05774 #endif
05775 switch (pvt->which_iflist) {
05776 case DAHDI_IFLIST_NONE:
05777 break;
05778 case DAHDI_IFLIST_MAIN:
05779 dahdi_iflist_extract(p);
05780 break;
05781 #if defined(HAVE_PRI)
05782 case DAHDI_IFLIST_NO_B_CHAN:
05783 if (p->pri) {
05784 dahdi_nobch_extract(p->pri, p);
05785 }
05786 break;
05787 #endif
05788 }
05789
05790 if (p->sig_pvt) {
05791 if (analog_lib_handles(p->sig, 0, 0)) {
05792 analog_delete(p->sig_pvt);
05793 }
05794 switch (p->sig) {
05795 #if defined(HAVE_PRI)
05796 case SIG_PRI_LIB_HANDLE_CASES:
05797 sig_pri_chan_delete(p->sig_pvt);
05798 break;
05799 #endif
05800 #if defined(HAVE_SS7)
05801 case SIG_SS7:
05802 sig_ss7_chan_delete(p->sig_pvt);
05803 break;
05804 #endif
05805 default:
05806 break;
05807 }
05808 }
05809 ast_free(p->cidspill);
05810 if (p->use_smdi)
05811 ast_smdi_interface_unref(p->smdi_iface);
05812 if (p->mwi_event_sub)
05813 ast_event_unsubscribe(p->mwi_event_sub);
05814 if (p->vars) {
05815 ast_variables_destroy(p->vars);
05816 }
05817 if (p->cc_params) {
05818 ast_cc_config_params_destroy(p->cc_params);
05819 }
05820 ast_mutex_destroy(&p->lock);
05821 dahdi_close_sub(p, SUB_REAL);
05822 if (p->owner)
05823 p->owner->tech_pvt = NULL;
05824 ast_free(p);
05825 }
05826
05827 static void destroy_channel(struct dahdi_pvt *cur, int now)
05828 {
05829 int i;
05830
05831 if (!now) {
05832
05833 if (cur->owner) {
05834 return;
05835 }
05836 for (i = 0; i < 3; i++) {
05837 if (cur->subs[i].owner) {
05838 return;
05839 }
05840 }
05841 }
05842 destroy_dahdi_pvt(cur);
05843 }
05844
05845 static void destroy_all_channels(void)
05846 {
05847 int chan;
05848 #if defined(HAVE_PRI)
05849 unsigned span;
05850 struct sig_pri_span *pri;
05851 #endif
05852 struct dahdi_pvt *p;
05853
05854 while (num_restart_pending) {
05855 usleep(1);
05856 }
05857
05858 ast_mutex_lock(&iflock);
05859
05860 while (iflist) {
05861 p = iflist;
05862
05863 chan = p->channel;
05864 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05865 {
05866 char db_chan_name[20];
05867 char db_answer[5];
05868 char state;
05869 int why = -1;
05870
05871 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05872 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05873 sscanf(db_answer, "%1c:%30d", &state, &why);
05874 }
05875 if (!why) {
05876
05877 ast_db_del(db_chan_name, SRVST_DBKEY);
05878 }
05879 }
05880 #endif
05881
05882 destroy_dahdi_pvt(p);
05883 ast_verb(3, "Unregistered channel %d\n", chan);
05884 }
05885 ifcount = 0;
05886 ast_mutex_unlock(&iflock);
05887
05888 #if defined(HAVE_PRI)
05889
05890 for (span = 0; span < NUM_SPANS; ++span) {
05891 if (!pris[span].dchannels[0]) {
05892 break;
05893 }
05894 pri = &pris[span].pri;
05895 ast_mutex_lock(&pri->lock);
05896 while (pri->no_b_chan_iflist) {
05897 p = pri->no_b_chan_iflist;
05898
05899
05900 destroy_dahdi_pvt(p);
05901 }
05902 ast_mutex_unlock(&pri->lock);
05903 }
05904 #endif
05905 }
05906
05907 #if defined(HAVE_PRI)
05908 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05909
05910 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05911 {
05912
05913 struct dahdi_pvt *p;
05914
05915 if (ast_strlen_zero(digits)) {
05916 ast_debug(1, "No digit string sent to application!\n");
05917 return -1;
05918 }
05919
05920 p = (struct dahdi_pvt *)chan->tech_pvt;
05921
05922 if (!p) {
05923 ast_debug(1, "Unable to find technology private\n");
05924 return -1;
05925 }
05926
05927 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05928
05929 return 0;
05930 }
05931 #endif
05932
05933 #if defined(HAVE_PRI)
05934 #if defined(HAVE_PRI_PROG_W_CAUSE)
05935 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05936
05937 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05938 {
05939
05940 struct dahdi_pvt *pvt;
05941 char *parse;
05942 int res;
05943 AST_DECLARE_APP_ARGS(args,
05944 AST_APP_ARG(destination);
05945 AST_APP_ARG(original);
05946 AST_APP_ARG(reason);
05947 );
05948
05949 if (ast_strlen_zero(data)) {
05950 ast_log(LOG_DEBUG, "No data sent to application!\n");
05951 return -1;
05952 }
05953 if (chan->tech != &dahdi_tech) {
05954 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05955 return -1;
05956 }
05957 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05958 if (!pvt) {
05959 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05960 return -1;
05961 }
05962 switch (pvt->sig) {
05963 case SIG_PRI_LIB_HANDLE_CASES:
05964 break;
05965 default:
05966 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05967 chan->name);
05968 return -1;
05969 }
05970
05971 parse = ast_strdupa(data);
05972 AST_STANDARD_APP_ARGS(args, parse);
05973
05974 if (ast_strlen_zero(args.destination)) {
05975 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05976 return -1;
05977 }
05978
05979 if (ast_strlen_zero(args.original)) {
05980 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05981 args.original = NULL;
05982 }
05983
05984 if (ast_strlen_zero(args.reason)) {
05985 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05986 args.reason = NULL;
05987 }
05988
05989 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05990 args.destination, args.original, args.reason);
05991 if (!res) {
05992
05993
05994
05995
05996 ast_safe_sleep(chan, 5000);
05997 }
05998
05999 return -1;
06000 }
06001 #endif
06002 #endif
06003
06004 #if defined(HAVE_OPENR2)
06005 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06006
06007 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06008 {
06009
06010 openr2_call_mode_t accept_mode;
06011 int res, timeout, maxloops;
06012 struct ast_frame *f;
06013 struct dahdi_pvt *p;
06014 char *parse;
06015 AST_DECLARE_APP_ARGS(args,
06016 AST_APP_ARG(charge);
06017 );
06018
06019 if (ast_strlen_zero(data)) {
06020 ast_log(LOG_DEBUG, "No data sent to application!\n");
06021 return -1;
06022 }
06023
06024 if (chan->tech != &dahdi_tech) {
06025 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06026 return -1;
06027 }
06028
06029 p = (struct dahdi_pvt *)chan->tech_pvt;
06030 if (!p) {
06031 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06032 return -1;
06033 }
06034
06035 parse = ast_strdupa(data);
06036 AST_STANDARD_APP_ARGS(args, parse);
06037
06038 if (ast_strlen_zero(args.charge)) {
06039 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06040 return -1;
06041 }
06042
06043 ast_mutex_lock(&p->lock);
06044 if (!p->mfcr2 || !p->mfcr2call) {
06045 ast_mutex_unlock(&p->lock);
06046 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06047 return -1;
06048 }
06049
06050 if (p->mfcr2_call_accepted) {
06051 ast_mutex_unlock(&p->lock);
06052 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06053 return 0;
06054 }
06055 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06056 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06057 ast_mutex_unlock(&p->lock);
06058 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06059 return -1;
06060 }
06061 ast_mutex_unlock(&p->lock);
06062
06063 res = 0;
06064 timeout = 100;
06065 maxloops = 50;
06066
06067 while (maxloops > 0) {
06068 maxloops--;
06069 if (ast_check_hangup(chan)) {
06070 break;
06071 }
06072 res = ast_waitfor(chan, timeout);
06073 if (res < 0) {
06074 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06075 res = -1;
06076 break;
06077 }
06078 if (res == 0) {
06079 continue;
06080 }
06081 res = 0;
06082 f = ast_read(chan);
06083 if (!f) {
06084 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06085 res = -1;
06086 break;
06087 }
06088 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06089 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06090 ast_frfree(f);
06091 res = -1;
06092 break;
06093 }
06094 ast_frfree(f);
06095 ast_mutex_lock(&p->lock);
06096 if (p->mfcr2_call_accepted) {
06097 ast_mutex_unlock(&p->lock);
06098 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06099 break;
06100 }
06101 ast_mutex_unlock(&p->lock);
06102 }
06103 if (res == -1) {
06104 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06105 }
06106 return res;
06107 }
06108
06109 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06110 {
06111 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06112 switch (cause) {
06113 case AST_CAUSE_USER_BUSY:
06114 case AST_CAUSE_CALL_REJECTED:
06115 case AST_CAUSE_INTERWORKING:
06116 r2cause = OR2_CAUSE_BUSY_NUMBER;
06117 break;
06118
06119 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06120 case AST_CAUSE_SWITCH_CONGESTION:
06121 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06122 break;
06123
06124 case AST_CAUSE_UNALLOCATED:
06125 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06126 break;
06127
06128 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06129 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06130 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06131 break;
06132
06133 case AST_CAUSE_NO_ANSWER:
06134 case AST_CAUSE_NO_USER_RESPONSE:
06135 r2cause = OR2_CAUSE_NO_ANSWER;
06136 break;
06137
06138 default:
06139 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06140 break;
06141 }
06142 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06143 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06144 return r2cause;
06145 }
06146 #endif
06147
06148 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06149 {
06150 if (p->bufferoverrideinuse) {
06151
06152 struct dahdi_bufferinfo bi = {
06153 .txbufpolicy = p->buf_policy,
06154 .rxbufpolicy = p->buf_policy,
06155 .bufsize = p->bufsize,
06156 .numbufs = p->buf_no
06157 };
06158 int bpres;
06159
06160 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06161 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06162 }
06163 p->bufferoverrideinuse = 0;
06164 return bpres;
06165 }
06166
06167 return -1;
06168 }
06169
06170 static int dahdi_hangup(struct ast_channel *ast)
06171 {
06172 int res = 0;
06173 int idx,x;
06174 int law;
06175
06176 struct dahdi_pvt *p = ast->tech_pvt;
06177 struct dahdi_params par;
06178
06179 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06180 if (!ast->tech_pvt) {
06181 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06182 return 0;
06183 }
06184
06185 ast_mutex_lock(&p->lock);
06186 p->exten[0] = '\0';
06187 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06188 dahdi_confmute(p, 0);
06189 restore_gains(p);
06190 p->ignoredtmf = 0;
06191 p->waitingfordt.tv_sec = 0;
06192
06193 res = analog_hangup(p->sig_pvt, ast);
06194 revert_fax_buffers(p, ast);
06195
06196 goto hangup_out;
06197 } else {
06198 p->cid_num[0] = '\0';
06199 p->cid_name[0] = '\0';
06200 p->cid_subaddr[0] = '\0';
06201 }
06202
06203 #if defined(HAVE_PRI)
06204 if (dahdi_sig_pri_lib_handles(p->sig)) {
06205 x = 1;
06206 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06207
06208 dahdi_confmute(p, 0);
06209 p->muting = 0;
06210 restore_gains(p);
06211 if (p->dsp) {
06212 ast_dsp_free(p->dsp);
06213 p->dsp = NULL;
06214 }
06215 p->ignoredtmf = 0;
06216
06217
06218 p->subs[SUB_REAL].owner = NULL;
06219 p->subs[SUB_REAL].needbusy = 0;
06220 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06221
06222 p->owner = NULL;
06223 p->cid_tag[0] = '\0';
06224 p->ringt = 0;
06225 p->distinctivering = 0;
06226 p->confirmanswer = 0;
06227 p->outgoing = 0;
06228 p->digital = 0;
06229 p->faxhandled = 0;
06230 p->pulsedial = 0;
06231
06232 revert_fax_buffers(p, ast);
06233
06234 p->law = p->law_default;
06235 law = p->law_default;
06236 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06237 if (res < 0) {
06238 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06239 p->channel, strerror(errno));
06240 }
06241
06242 sig_pri_hangup(p->sig_pvt, ast);
06243
06244 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06245 dahdi_disable_ec(p);
06246
06247 x = 0;
06248 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06249 p->didtdd = 0;
06250
06251 p->rdnis[0] = '\0';
06252 update_conf(p);
06253 reset_conf(p);
06254
06255
06256 x = 0;
06257 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06258
06259 if (num_restart_pending == 0) {
06260 restart_monitor();
06261 }
06262 goto hangup_out;
06263 }
06264 #endif
06265
06266 #if defined(HAVE_SS7)
06267 if (p->sig == SIG_SS7) {
06268 x = 1;
06269 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06270
06271 dahdi_confmute(p, 0);
06272 p->muting = 0;
06273 restore_gains(p);
06274 if (p->dsp) {
06275 ast_dsp_free(p->dsp);
06276 p->dsp = NULL;
06277 }
06278 p->ignoredtmf = 0;
06279
06280
06281 p->subs[SUB_REAL].owner = NULL;
06282 p->subs[SUB_REAL].needbusy = 0;
06283 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06284
06285 p->owner = NULL;
06286 p->ringt = 0;
06287 p->distinctivering = 0;
06288 p->confirmanswer = 0;
06289 p->outgoing = 0;
06290 p->digital = 0;
06291 p->faxhandled = 0;
06292 p->pulsedial = 0;
06293
06294 revert_fax_buffers(p, ast);
06295
06296 p->law = p->law_default;
06297 law = p->law_default;
06298 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06299 if (res < 0) {
06300 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06301 p->channel, strerror(errno));
06302 }
06303
06304 sig_ss7_hangup(p->sig_pvt, ast);
06305
06306 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06307 dahdi_disable_ec(p);
06308
06309 x = 0;
06310 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06311 p->didtdd = 0;
06312
06313 update_conf(p);
06314 reset_conf(p);
06315
06316
06317 x = 0;
06318 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06319
06320 if (num_restart_pending == 0) {
06321 restart_monitor();
06322 }
06323 goto hangup_out;
06324 }
06325 #endif
06326
06327 idx = dahdi_get_index(ast, p, 1);
06328
06329 dahdi_confmute(p, 0);
06330 p->muting = 0;
06331 restore_gains(p);
06332 if (p->origcid_num) {
06333 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06334 ast_free(p->origcid_num);
06335 p->origcid_num = NULL;
06336 }
06337 if (p->origcid_name) {
06338 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06339 ast_free(p->origcid_name);
06340 p->origcid_name = NULL;
06341 }
06342 if (p->dsp)
06343 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06344
06345 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06346 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06347 p->ignoredtmf = 0;
06348
06349 if (idx > -1) {
06350
06351 p->subs[idx].owner = NULL;
06352 p->subs[idx].needanswer = 0;
06353 p->subs[idx].needflash = 0;
06354 p->subs[idx].needringing = 0;
06355 p->subs[idx].needbusy = 0;
06356 p->subs[idx].needcongestion = 0;
06357 p->subs[idx].linear = 0;
06358 p->polarity = POLARITY_IDLE;
06359 dahdi_setlinear(p->subs[idx].dfd, 0);
06360 if (idx == SUB_REAL) {
06361 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06362 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06363 if (p->subs[SUB_CALLWAIT].inthreeway) {
06364
06365 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06366
06367 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06368 unalloc_sub(p, SUB_CALLWAIT);
06369 p->owner = NULL;
06370 } else {
06371
06372 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06373 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06374 unalloc_sub(p, SUB_THREEWAY);
06375 if (p->subs[SUB_REAL].inthreeway) {
06376
06377
06378 ast_debug(1, "Call was complete, setting owner to former third call\n");
06379 p->owner = p->subs[SUB_REAL].owner;
06380 } else {
06381
06382 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06383 p->owner = NULL;
06384 }
06385 p->subs[SUB_REAL].inthreeway = 0;
06386 }
06387 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06388
06389 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06390 unalloc_sub(p, SUB_CALLWAIT);
06391 p->owner = p->subs[SUB_REAL].owner;
06392 if (p->owner->_state != AST_STATE_UP)
06393 p->subs[SUB_REAL].needanswer = 1;
06394 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06395 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06396 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06397 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06398 unalloc_sub(p, SUB_THREEWAY);
06399 if (p->subs[SUB_REAL].inthreeway) {
06400
06401
06402 ast_debug(1, "Call was complete, setting owner to former third call\n");
06403 p->owner = p->subs[SUB_REAL].owner;
06404 } else {
06405
06406 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06407 p->owner = NULL;
06408 }
06409 p->subs[SUB_REAL].inthreeway = 0;
06410 }
06411 } else if (idx == SUB_CALLWAIT) {
06412
06413 if (p->subs[SUB_CALLWAIT].inthreeway) {
06414
06415
06416 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06417 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06418 S_OR(p->mohsuggest, NULL),
06419 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06420 }
06421 p->subs[SUB_THREEWAY].inthreeway = 0;
06422
06423 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06424 unalloc_sub(p, SUB_THREEWAY);
06425 } else
06426 unalloc_sub(p, SUB_CALLWAIT);
06427 } else if (idx == SUB_THREEWAY) {
06428 if (p->subs[SUB_CALLWAIT].inthreeway) {
06429
06430
06431 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06432 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06433 S_OR(p->mohsuggest, NULL),
06434 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06435 }
06436 p->subs[SUB_CALLWAIT].inthreeway = 0;
06437 }
06438 p->subs[SUB_REAL].inthreeway = 0;
06439
06440
06441 unalloc_sub(p, SUB_THREEWAY);
06442 } else {
06443
06444 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06445 }
06446 }
06447
06448 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06449 p->owner = NULL;
06450 p->ringt = 0;
06451 p->distinctivering = 0;
06452 p->confirmanswer = 0;
06453 p->outgoing = 0;
06454 p->digital = 0;
06455 p->faxhandled = 0;
06456 p->pulsedial = 0;
06457 if (p->dsp) {
06458 ast_dsp_free(p->dsp);
06459 p->dsp = NULL;
06460 }
06461
06462 revert_fax_buffers(p, ast);
06463
06464 p->law = p->law_default;
06465 law = p->law_default;
06466 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06467 if (res < 0)
06468 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06469
06470 #ifdef HAVE_OPENR2
06471 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06472 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06473
06474 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06475 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06476 } else {
06477 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06478 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06479 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06480 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06481 dahdi_r2_disconnect_call(p, r2cause);
06482 }
06483 } else if (p->mfcr2call) {
06484 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06485
06486
06487
06488
06489 p->mfcr2call = 0;
06490 }
06491 #endif
06492 switch (p->sig) {
06493 case SIG_SS7:
06494 case SIG_MFCR2:
06495 case SIG_PRI_LIB_HANDLE_CASES:
06496 case 0:
06497 break;
06498 default:
06499 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06500 break;
06501 }
06502 if (res < 0) {
06503 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06504 }
06505 switch (p->sig) {
06506 case SIG_FXOGS:
06507 case SIG_FXOLS:
06508 case SIG_FXOKS:
06509 memset(&par, 0, sizeof(par));
06510 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06511 if (!res) {
06512 struct analog_pvt *analog_p = p->sig_pvt;
06513 #if 0
06514 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06515 #endif
06516
06517 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06518 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06519 else
06520 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06521 analog_p->fxsoffhookstate = par.rxisoffhook;
06522 }
06523 break;
06524 case SIG_FXSGS:
06525 case SIG_FXSLS:
06526 case SIG_FXSKS:
06527
06528
06529 if (ast->_state != AST_STATE_RESERVED) {
06530 time(&p->guardtime);
06531 p->guardtime += 2;
06532 }
06533 break;
06534 default:
06535 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06536 break;
06537 }
06538 if (p->sig)
06539 dahdi_disable_ec(p);
06540 x = 0;
06541 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06542 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06543 p->didtdd = 0;
06544 p->callwaitcas = 0;
06545 p->callwaiting = p->permcallwaiting;
06546 p->hidecallerid = p->permhidecallerid;
06547 p->waitingfordt.tv_sec = 0;
06548 p->dialing = 0;
06549 p->rdnis[0] = '\0';
06550 update_conf(p);
06551 reset_conf(p);
06552
06553 switch (p->sig) {
06554 case SIG_PRI_LIB_HANDLE_CASES:
06555 case SIG_SS7:
06556 x = 0;
06557 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06558 break;
06559 default:
06560 break;
06561 }
06562 if (num_restart_pending == 0)
06563 restart_monitor();
06564 }
06565
06566 p->callwaitingrepeat = 0;
06567 p->cidcwexpire = 0;
06568 p->cid_suppress_expire = 0;
06569 p->oprmode = 0;
06570 hangup_out:
06571 ast->tech_pvt = NULL;
06572 ast_free(p->cidspill);
06573 p->cidspill = NULL;
06574
06575 ast_mutex_unlock(&p->lock);
06576 ast_verb(3, "Hungup '%s'\n", ast->name);
06577
06578 ast_mutex_lock(&iflock);
06579 if (p->restartpending) {
06580 num_restart_pending--;
06581 }
06582
06583 if (p->destroy) {
06584 destroy_channel(p, 0);
06585 }
06586 ast_mutex_unlock(&iflock);
06587
06588 ast_module_unref(ast_module_info->self);
06589 return 0;
06590 }
06591
06592 static int dahdi_answer(struct ast_channel *ast)
06593 {
06594 struct dahdi_pvt *p = ast->tech_pvt;
06595 int res = 0;
06596 int idx;
06597 ast_setstate(ast, AST_STATE_UP);
06598 ast_mutex_lock(&p->lock);
06599 idx = dahdi_get_index(ast, p, 0);
06600 if (idx < 0)
06601 idx = SUB_REAL;
06602
06603 if ((p->radio || (p->oprmode < 0))) {
06604 ast_mutex_unlock(&p->lock);
06605 return 0;
06606 }
06607
06608 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06609 res = analog_answer(p->sig_pvt, ast);
06610 ast_mutex_unlock(&p->lock);
06611 return res;
06612 }
06613
06614 switch (p->sig) {
06615 #if defined(HAVE_PRI)
06616 case SIG_PRI_LIB_HANDLE_CASES:
06617 res = sig_pri_answer(p->sig_pvt, ast);
06618 break;
06619 #endif
06620 #if defined(HAVE_SS7)
06621 case SIG_SS7:
06622 res = sig_ss7_answer(p->sig_pvt, ast);
06623 break;
06624 #endif
06625 #ifdef HAVE_OPENR2
06626 case SIG_MFCR2:
06627 if (!p->mfcr2_call_accepted) {
06628
06629
06630 p->mfcr2_answer_pending = 1;
06631 if (p->mfcr2_charge_calls) {
06632 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06633 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06634 } else {
06635 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06636 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06637 }
06638 } else {
06639 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06640 dahdi_r2_answer(p);
06641 }
06642 break;
06643 #endif
06644 case 0:
06645 ast_mutex_unlock(&p->lock);
06646 return 0;
06647 default:
06648 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06649 res = -1;
06650 break;
06651 }
06652 ast_mutex_unlock(&p->lock);
06653 return res;
06654 }
06655
06656 static void disable_dtmf_detect(struct dahdi_pvt *p)
06657 {
06658 int val = 0;
06659
06660 p->ignoredtmf = 1;
06661
06662 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06663
06664 if (!p->hardwaredtmf && p->dsp) {
06665 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06666 ast_dsp_set_features(p->dsp, p->dsp_features);
06667 }
06668 }
06669
06670 static void enable_dtmf_detect(struct dahdi_pvt *p)
06671 {
06672 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06673
06674 if (p->channel == CHAN_PSEUDO)
06675 return;
06676
06677 p->ignoredtmf = 0;
06678
06679 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06680
06681 if (!p->hardwaredtmf && p->dsp) {
06682 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06683 ast_dsp_set_features(p->dsp, p->dsp_features);
06684 }
06685 }
06686
06687 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06688 {
06689 char *cp;
06690 struct dahdi_pvt *p = chan->tech_pvt;
06691
06692
06693 if (!p || !data || (*datalen < 1)) {
06694 errno = EINVAL;
06695 return -1;
06696 }
06697
06698 switch (option) {
06699 case AST_OPTION_DIGIT_DETECT:
06700 cp = (char *) data;
06701 *cp = p->ignoredtmf ? 0 : 1;
06702 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06703 break;
06704 case AST_OPTION_FAX_DETECT:
06705 cp = (char *) data;
06706 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06707 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06708 break;
06709 case AST_OPTION_CC_AGENT_TYPE:
06710 #if defined(HAVE_PRI)
06711 #if defined(HAVE_PRI_CCSS)
06712 if (dahdi_sig_pri_lib_handles(p->sig)) {
06713 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06714 break;
06715 }
06716 #endif
06717 #endif
06718 return -1;
06719 default:
06720 return -1;
06721 }
06722
06723 errno = 0;
06724
06725 return 0;
06726 }
06727
06728 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06729 {
06730 char *cp;
06731 signed char *scp;
06732 int x;
06733 int idx;
06734 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06735 struct oprmode *oprmode;
06736
06737
06738
06739 if (!p || !data || (datalen < 1)) {
06740 errno = EINVAL;
06741 return -1;
06742 }
06743
06744 switch (option) {
06745 case AST_OPTION_TXGAIN:
06746 scp = (signed char *) data;
06747 idx = dahdi_get_index(chan, p, 0);
06748 if (idx < 0) {
06749 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06750 return -1;
06751 }
06752 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06753 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06754 case AST_OPTION_RXGAIN:
06755 scp = (signed char *) data;
06756 idx = dahdi_get_index(chan, p, 0);
06757 if (idx < 0) {
06758 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06759 return -1;
06760 }
06761 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06762 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06763 case AST_OPTION_TONE_VERIFY:
06764 if (!p->dsp)
06765 break;
06766 cp = (char *) data;
06767 switch (*cp) {
06768 case 1:
06769 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06770 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06771 break;
06772 case 2:
06773 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06774 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06775 break;
06776 default:
06777 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06778 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06779 break;
06780 }
06781 break;
06782 case AST_OPTION_TDD:
06783
06784 cp = (char *) data;
06785 p->mate = 0;
06786 if (!*cp) {
06787 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06788 if (p->tdd)
06789 tdd_free(p->tdd);
06790 p->tdd = 0;
06791 break;
06792 }
06793 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06794 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06795 dahdi_disable_ec(p);
06796
06797 if (!p->didtdd) {
06798 unsigned char mybuf[41000];
06799 unsigned char *buf;
06800 int size, res, fd, len;
06801 struct pollfd fds[1];
06802
06803 buf = mybuf;
06804 memset(buf, 0x7f, sizeof(mybuf));
06805 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06806 len = 40000;
06807 idx = dahdi_get_index(chan, p, 0);
06808 if (idx < 0) {
06809 ast_log(LOG_WARNING, "No index in TDD?\n");
06810 return -1;
06811 }
06812 fd = p->subs[idx].dfd;
06813 while (len) {
06814 if (ast_check_hangup(chan))
06815 return -1;
06816 size = len;
06817 if (size > READ_SIZE)
06818 size = READ_SIZE;
06819 fds[0].fd = fd;
06820 fds[0].events = POLLPRI | POLLOUT;
06821 fds[0].revents = 0;
06822 res = poll(fds, 1, -1);
06823 if (!res) {
06824 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06825 continue;
06826 }
06827
06828 if (fds[0].revents & POLLPRI)
06829 return -1;
06830 if (!(fds[0].revents & POLLOUT)) {
06831 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06832 continue;
06833 }
06834 res = write(fd, buf, size);
06835 if (res != size) {
06836 if (res == -1) return -1;
06837 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06838 break;
06839 }
06840 len -= size;
06841 buf += size;
06842 }
06843 p->didtdd = 1;
06844 }
06845 if (*cp == 2) {
06846 if (p->tdd)
06847 tdd_free(p->tdd);
06848 p->tdd = 0;
06849 p->mate = 1;
06850 break;
06851 }
06852 if (!p->tdd) {
06853 p->tdd = tdd_new();
06854 }
06855 break;
06856 case AST_OPTION_RELAXDTMF:
06857 if (!p->dsp)
06858 break;
06859 cp = (char *) data;
06860 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06861 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06862 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06863 break;
06864 case AST_OPTION_AUDIO_MODE:
06865 #if defined(HAVE_PRI)
06866 if (dahdi_sig_pri_lib_handles(p->sig)
06867 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06868
06869 break;
06870 }
06871 #endif
06872
06873 cp = (char *) data;
06874 if (!*cp) {
06875 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06876 x = 0;
06877 dahdi_disable_ec(p);
06878 } else {
06879 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06880 x = 1;
06881 }
06882 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06883 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06884 break;
06885 case AST_OPTION_OPRMODE:
06886 oprmode = (struct oprmode *) data;
06887
06888 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06889 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06890 chan->tech->type, oprmode->peer->tech->type);
06891 errno = EINVAL;
06892 return -1;
06893 }
06894 pp = oprmode->peer->tech_pvt;
06895 p->oprmode = pp->oprmode = 0;
06896
06897 p->oprpeer = pp;
06898 pp->oprpeer = p;
06899
06900 if (oprmode->mode)
06901 {
06902 pp->oprmode = oprmode->mode;
06903 p->oprmode = -oprmode->mode;
06904 }
06905 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06906 oprmode->mode, chan->name,oprmode->peer->name);
06907 break;
06908 case AST_OPTION_ECHOCAN:
06909 cp = (char *) data;
06910 if (*cp) {
06911 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06912 dahdi_enable_ec(p);
06913 } else {
06914 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06915 dahdi_disable_ec(p);
06916 }
06917 break;
06918 case AST_OPTION_DIGIT_DETECT:
06919 cp = (char *) data;
06920 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06921 if (*cp) {
06922 enable_dtmf_detect(p);
06923 } else {
06924 disable_dtmf_detect(p);
06925 }
06926 break;
06927 case AST_OPTION_FAX_DETECT:
06928 cp = (char *) data;
06929 if (p->dsp) {
06930 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06931 if (*cp) {
06932 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06933 } else {
06934 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06935 }
06936 ast_dsp_set_features(p->dsp, p->dsp_features);
06937 }
06938 break;
06939 default:
06940 return -1;
06941 }
06942 errno = 0;
06943
06944 return 0;
06945 }
06946
06947 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06948 {
06949 struct dahdi_pvt *p = chan->tech_pvt;
06950 int res = 0;
06951
06952 if (!p) {
06953
06954 *buf = '\0';
06955 return -1;
06956 }
06957
06958 if (!strcasecmp(data, "rxgain")) {
06959 ast_mutex_lock(&p->lock);
06960 snprintf(buf, len, "%f", p->rxgain);
06961 ast_mutex_unlock(&p->lock);
06962 } else if (!strcasecmp(data, "txgain")) {
06963 ast_mutex_lock(&p->lock);
06964 snprintf(buf, len, "%f", p->txgain);
06965 ast_mutex_unlock(&p->lock);
06966 } else if (!strcasecmp(data, "dahdi_channel")) {
06967 ast_mutex_lock(&p->lock);
06968 snprintf(buf, len, "%d", p->channel);
06969 ast_mutex_unlock(&p->lock);
06970 } else if (!strcasecmp(data, "dahdi_span")) {
06971 ast_mutex_lock(&p->lock);
06972 snprintf(buf, len, "%d", p->span);
06973 ast_mutex_unlock(&p->lock);
06974 } else if (!strcasecmp(data, "dahdi_type")) {
06975 ast_mutex_lock(&p->lock);
06976 switch (p->sig) {
06977 #if defined(HAVE_OPENR2)
06978 case SIG_MFCR2:
06979 ast_copy_string(buf, "mfc/r2", len);
06980 break;
06981 #endif
06982 #if defined(HAVE_PRI)
06983 case SIG_PRI_LIB_HANDLE_CASES:
06984 ast_copy_string(buf, "pri", len);
06985 break;
06986 #endif
06987 case 0:
06988 ast_copy_string(buf, "pseudo", len);
06989 break;
06990 #if defined(HAVE_SS7)
06991 case SIG_SS7:
06992 ast_copy_string(buf, "ss7", len);
06993 break;
06994 #endif
06995 default:
06996
06997 ast_copy_string(buf, "analog", len);
06998 break;
06999 }
07000 ast_mutex_unlock(&p->lock);
07001 #if defined(HAVE_PRI)
07002 #if defined(HAVE_PRI_REVERSE_CHARGE)
07003 } else if (!strcasecmp(data, "reversecharge")) {
07004 ast_mutex_lock(&p->lock);
07005 switch (p->sig) {
07006 case SIG_PRI_LIB_HANDLE_CASES:
07007 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07008 break;
07009 default:
07010 *buf = '\0';
07011 res = -1;
07012 break;
07013 }
07014 ast_mutex_unlock(&p->lock);
07015 #endif
07016 #if defined(HAVE_PRI_SETUP_KEYPAD)
07017 } else if (!strcasecmp(data, "keypad_digits")) {
07018 ast_mutex_lock(&p->lock);
07019 switch (p->sig) {
07020 case SIG_PRI_LIB_HANDLE_CASES:
07021 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07022 len);
07023 break;
07024 default:
07025 *buf = '\0';
07026 res = -1;
07027 break;
07028 }
07029 ast_mutex_unlock(&p->lock);
07030 #endif
07031 } else if (!strcasecmp(data, "no_media_path")) {
07032 ast_mutex_lock(&p->lock);
07033 switch (p->sig) {
07034 case SIG_PRI_LIB_HANDLE_CASES:
07035
07036
07037
07038
07039 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07040 break;
07041 default:
07042 *buf = '\0';
07043 res = -1;
07044 break;
07045 }
07046 ast_mutex_unlock(&p->lock);
07047 #endif
07048 } else {
07049 *buf = '\0';
07050 res = -1;
07051 }
07052
07053 return res;
07054 }
07055
07056
07057 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07058 {
07059 int res;
07060 char policy_str[21] = "";
07061
07062 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07063 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07064 return 1;
07065 }
07066 if (*num_buffers < 0) {
07067 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07068 return -1;
07069 }
07070 if (!strcasecmp(policy_str, "full")) {
07071 *policy = DAHDI_POLICY_WHEN_FULL;
07072 } else if (!strcasecmp(policy_str, "immediate")) {
07073 *policy = DAHDI_POLICY_IMMEDIATE;
07074 #if defined(HAVE_DAHDI_HALF_FULL)
07075 } else if (!strcasecmp(policy_str, "half")) {
07076 *policy = DAHDI_POLICY_HALF_FULL;
07077 #endif
07078 } else {
07079 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07080 return -1;
07081 }
07082
07083 return 0;
07084 }
07085
07086 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07087 {
07088 struct dahdi_pvt *p = chan->tech_pvt;
07089 int res = 0;
07090
07091 if (!p) {
07092
07093 return -1;
07094 }
07095
07096 if (!strcasecmp(data, "buffers")) {
07097 int num_bufs, policy;
07098
07099 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07100 struct dahdi_bufferinfo bi = {
07101 .txbufpolicy = policy,
07102 .rxbufpolicy = policy,
07103 .bufsize = p->bufsize,
07104 .numbufs = num_bufs,
07105 };
07106 int bpres;
07107
07108 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07109 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07110 } else {
07111 p->bufferoverrideinuse = 1;
07112 }
07113 } else {
07114 res = -1;
07115 }
07116 } else if (!strcasecmp(data, "echocan_mode")) {
07117 if (!strcasecmp(value, "on")) {
07118 ast_mutex_lock(&p->lock);
07119 dahdi_enable_ec(p);
07120 ast_mutex_unlock(&p->lock);
07121 } else if (!strcasecmp(value, "off")) {
07122 ast_mutex_lock(&p->lock);
07123 dahdi_disable_ec(p);
07124 ast_mutex_unlock(&p->lock);
07125 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07126 } else if (!strcasecmp(value, "fax")) {
07127 int blah = 1;
07128
07129 ast_mutex_lock(&p->lock);
07130 if (!p->echocanon) {
07131 dahdi_enable_ec(p);
07132 }
07133 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07134 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07135 }
07136 ast_mutex_unlock(&p->lock);
07137 } else if (!strcasecmp(value, "voice")) {
07138 int blah = 0;
07139
07140 ast_mutex_lock(&p->lock);
07141 if (!p->echocanon) {
07142 dahdi_enable_ec(p);
07143 }
07144 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07145 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07146 }
07147 ast_mutex_unlock(&p->lock);
07148 #endif
07149 } else {
07150 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07151 res = -1;
07152 }
07153 } else {
07154 res = -1;
07155 }
07156
07157 return res;
07158 }
07159
07160 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07161 {
07162
07163 int x;
07164 int hasslaves;
07165 if (!master)
07166 return;
07167 if (needlock) {
07168 ast_mutex_lock(&master->lock);
07169 if (slave) {
07170 while (ast_mutex_trylock(&slave->lock)) {
07171 DEADLOCK_AVOIDANCE(&master->lock);
07172 }
07173 }
07174 }
07175 hasslaves = 0;
07176 for (x = 0; x < MAX_SLAVES; x++) {
07177 if (master->slaves[x]) {
07178 if (!slave || (master->slaves[x] == slave)) {
07179
07180 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07181 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07182 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07183 master->slaves[x]->master = NULL;
07184 master->slaves[x] = NULL;
07185 } else
07186 hasslaves = 1;
07187 }
07188 if (!hasslaves)
07189 master->inconference = 0;
07190 }
07191 if (!slave) {
07192 if (master->master) {
07193
07194 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07195 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07196 hasslaves = 0;
07197 for (x = 0; x < MAX_SLAVES; x++) {
07198 if (master->master->slaves[x] == master)
07199 master->master->slaves[x] = NULL;
07200 else if (master->master->slaves[x])
07201 hasslaves = 1;
07202 }
07203 if (!hasslaves)
07204 master->master->inconference = 0;
07205 }
07206 master->master = NULL;
07207 }
07208 update_conf(master);
07209 if (needlock) {
07210 if (slave)
07211 ast_mutex_unlock(&slave->lock);
07212 ast_mutex_unlock(&master->lock);
07213 }
07214 }
07215
07216 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07217 int x;
07218 if (!slave || !master) {
07219 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07220 return;
07221 }
07222 for (x = 0; x < MAX_SLAVES; x++) {
07223 if (!master->slaves[x]) {
07224 master->slaves[x] = slave;
07225 break;
07226 }
07227 }
07228 if (x >= MAX_SLAVES) {
07229 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07230 master->slaves[MAX_SLAVES - 1] = slave;
07231 }
07232 if (slave->master)
07233 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07234 slave->master = master;
07235
07236 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07237 }
07238
07239 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)
07240 {
07241 struct ast_channel *who;
07242 struct dahdi_pvt *p0, *p1, *op0, *op1;
07243 struct dahdi_pvt *master = NULL, *slave = NULL;
07244 struct ast_frame *f;
07245 int inconf = 0;
07246 int nothingok = 1;
07247 int ofd0, ofd1;
07248 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07249 int os0 = -1, os1 = -1;
07250 int priority = 0;
07251 struct ast_channel *oc0, *oc1;
07252 enum ast_bridge_result res;
07253 struct timeval start = ast_tvnow();
07254 #ifdef PRI_2BCT
07255 int triedtopribridge = 0;
07256 q931_call *q931c0;
07257 q931_call *q931c1;
07258 #endif
07259
07260
07261
07262
07263
07264
07265 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07266 return AST_BRIDGE_FAILED_NOWARN;
07267
07268 ast_channel_lock(c0);
07269 while (ast_channel_trylock(c1)) {
07270 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07271 }
07272
07273 p0 = c0->tech_pvt;
07274 p1 = c1->tech_pvt;
07275
07276 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07277 ast_channel_unlock(c0);
07278 ast_channel_unlock(c1);
07279 return AST_BRIDGE_FAILED_NOWARN;
07280 }
07281
07282 oi0 = dahdi_get_index(c0, p0, 0);
07283 oi1 = dahdi_get_index(c1, p1, 0);
07284 if ((oi0 < 0) || (oi1 < 0)) {
07285 ast_channel_unlock(c0);
07286 ast_channel_unlock(c1);
07287 return AST_BRIDGE_FAILED;
07288 }
07289
07290 op0 = p0 = c0->tech_pvt;
07291 op1 = p1 = c1->tech_pvt;
07292 ofd0 = c0->fds[0];
07293 ofd1 = c1->fds[0];
07294 oc0 = p0->owner;
07295 oc1 = p1->owner;
07296
07297 if (ast_mutex_trylock(&p0->lock)) {
07298
07299 ast_channel_unlock(c0);
07300 ast_channel_unlock(c1);
07301 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07302 return AST_BRIDGE_RETRY;
07303 }
07304 if (ast_mutex_trylock(&p1->lock)) {
07305
07306 ast_mutex_unlock(&p0->lock);
07307 ast_channel_unlock(c0);
07308 ast_channel_unlock(c1);
07309 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07310 return AST_BRIDGE_RETRY;
07311 }
07312
07313 if ((p0->callwaiting && p0->callwaitingcallerid)
07314 || (p1->callwaiting && p1->callwaitingcallerid)) {
07315
07316
07317
07318
07319
07320
07321
07322
07323
07324 ast_mutex_unlock(&p0->lock);
07325 ast_mutex_unlock(&p1->lock);
07326 ast_channel_unlock(c0);
07327 ast_channel_unlock(c1);
07328 return AST_BRIDGE_FAILED_NOWARN;
07329 }
07330
07331 #if defined(HAVE_PRI)
07332 if ((dahdi_sig_pri_lib_handles(p0->sig)
07333 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07334 || (dahdi_sig_pri_lib_handles(p1->sig)
07335 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07336
07337
07338
07339
07340 ast_mutex_unlock(&p0->lock);
07341 ast_mutex_unlock(&p1->lock);
07342 ast_channel_unlock(c0);
07343 ast_channel_unlock(c1);
07344 return AST_BRIDGE_FAILED_NOWARN;
07345 }
07346 #endif
07347
07348 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07349 if (p0->owner && p1->owner) {
07350
07351 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07352 master = p0;
07353 slave = p1;
07354 inconf = 1;
07355 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07356 master = p1;
07357 slave = p0;
07358 inconf = 1;
07359 } else {
07360 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07361 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07362 p0->channel,
07363 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07364 p0->subs[SUB_REAL].inthreeway, p0->channel,
07365 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07366 p1->subs[SUB_REAL].inthreeway);
07367 }
07368 nothingok = 0;
07369 }
07370 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07371 if (p1->subs[SUB_THREEWAY].inthreeway) {
07372 master = p1;
07373 slave = p0;
07374 nothingok = 0;
07375 }
07376 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07377 if (p0->subs[SUB_THREEWAY].inthreeway) {
07378 master = p0;
07379 slave = p1;
07380 nothingok = 0;
07381 }
07382 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07383
07384
07385 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07386 master = p1;
07387 slave = p0;
07388 nothingok = 0;
07389 }
07390 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07391
07392 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07393 master = p0;
07394 slave = p1;
07395 nothingok = 0;
07396 }
07397 }
07398 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07399 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07400 if (master && slave) {
07401
07402
07403
07404 if ((oi1 == SUB_THREEWAY) &&
07405 p1->subs[SUB_THREEWAY].inthreeway &&
07406 p1->subs[SUB_REAL].owner &&
07407 p1->subs[SUB_REAL].inthreeway &&
07408 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07409 ast_debug(1,
07410 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07411 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07412 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07413 os1 = p1->subs[SUB_REAL].owner->_state;
07414 } else {
07415 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07416 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07417 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07418 }
07419 if ((oi0 == SUB_THREEWAY) &&
07420 p0->subs[SUB_THREEWAY].inthreeway &&
07421 p0->subs[SUB_REAL].owner &&
07422 p0->subs[SUB_REAL].inthreeway &&
07423 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07424 ast_debug(1,
07425 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07426 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07427 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07428 os0 = p0->subs[SUB_REAL].owner->_state;
07429 } else {
07430 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07431 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07432 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07433 }
07434 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07435 if (!p0->echocanbridged || !p1->echocanbridged) {
07436
07437 dahdi_disable_ec(p0);
07438 dahdi_disable_ec(p1);
07439 }
07440 }
07441 dahdi_link(slave, master);
07442 master->inconference = inconf;
07443 } else if (!nothingok)
07444 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07445
07446 update_conf(p0);
07447 update_conf(p1);
07448 t0 = p0->subs[SUB_REAL].inthreeway;
07449 t1 = p1->subs[SUB_REAL].inthreeway;
07450
07451 ast_mutex_unlock(&p0->lock);
07452 ast_mutex_unlock(&p1->lock);
07453
07454 ast_channel_unlock(c0);
07455 ast_channel_unlock(c1);
07456
07457
07458 if ((!master || !slave) && !nothingok) {
07459 dahdi_enable_ec(p0);
07460 dahdi_enable_ec(p1);
07461 return AST_BRIDGE_FAILED;
07462 }
07463
07464 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07465
07466 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07467 disable_dtmf_detect(op0);
07468
07469 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07470 disable_dtmf_detect(op1);
07471
07472 for (;;) {
07473 struct ast_channel *c0_priority[2] = {c0, c1};
07474 struct ast_channel *c1_priority[2] = {c1, c0};
07475 int ms;
07476
07477
07478
07479
07480 ast_channel_lock(c0);
07481 while (ast_channel_trylock(c1)) {
07482 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07483 }
07484
07485 p0 = c0->tech_pvt;
07486 p1 = c1->tech_pvt;
07487
07488 if (op0 == p0)
07489 i0 = dahdi_get_index(c0, p0, 1);
07490 if (op1 == p1)
07491 i1 = dahdi_get_index(c1, p1, 1);
07492
07493 ast_channel_unlock(c0);
07494 ast_channel_unlock(c1);
07495 ms = ast_remaining_ms(start, timeoutms);
07496 if (!ms ||
07497 (op0 != p0) ||
07498 (op1 != p1) ||
07499 (ofd0 != c0->fds[0]) ||
07500 (ofd1 != c1->fds[0]) ||
07501 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07502 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07503 (oc0 != p0->owner) ||
07504 (oc1 != p1->owner) ||
07505 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07506 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07507 (oi0 != i0) ||
07508 (oi1 != i1)) {
07509 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07510 op0->channel, oi0, op1->channel, oi1);
07511 res = AST_BRIDGE_RETRY;
07512 goto return_from_bridge;
07513 }
07514
07515 #ifdef PRI_2BCT
07516 if (!triedtopribridge) {
07517 triedtopribridge = 1;
07518 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07519 ast_mutex_lock(&p0->pri->lock);
07520 switch (p0->sig) {
07521 case SIG_PRI_LIB_HANDLE_CASES:
07522 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07523 break;
07524 default:
07525 q931c0 = NULL;
07526 break;
07527 }
07528 switch (p1->sig) {
07529 case SIG_PRI_LIB_HANDLE_CASES:
07530 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07531 break;
07532 default:
07533 q931c1 = NULL;
07534 break;
07535 }
07536 if (q931c0 && q931c1) {
07537 pri_channel_bridge(q931c0, q931c1);
07538 }
07539 ast_mutex_unlock(&p0->pri->lock);
07540 }
07541 }
07542 #endif
07543
07544 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07545 if (!who) {
07546 ast_debug(1, "Ooh, empty read...\n");
07547 continue;
07548 }
07549 f = ast_read(who);
07550 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07551 *fo = f;
07552 *rc = who;
07553 res = AST_BRIDGE_COMPLETE;
07554 goto return_from_bridge;
07555 }
07556 if (f->frametype == AST_FRAME_DTMF) {
07557 if ((who == c0) && p0->pulsedial) {
07558 ast_write(c1, f);
07559 } else if ((who == c1) && p1->pulsedial) {
07560 ast_write(c0, f);
07561 } else {
07562 *fo = f;
07563 *rc = who;
07564 res = AST_BRIDGE_COMPLETE;
07565 goto return_from_bridge;
07566 }
07567 }
07568 ast_frfree(f);
07569
07570
07571 priority = !priority;
07572 }
07573
07574 return_from_bridge:
07575 if (op0 == p0)
07576 dahdi_enable_ec(p0);
07577
07578 if (op1 == p1)
07579 dahdi_enable_ec(p1);
07580
07581 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07582 enable_dtmf_detect(op0);
07583
07584 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07585 enable_dtmf_detect(op1);
07586
07587 dahdi_unlink(slave, master, 1);
07588
07589 return res;
07590 }
07591
07592 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07593 {
07594 struct dahdi_pvt *p = newchan->tech_pvt;
07595 int x;
07596
07597 ast_mutex_lock(&p->lock);
07598
07599 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07600 if (p->owner == oldchan) {
07601 p->owner = newchan;
07602 }
07603 for (x = 0; x < 3; x++) {
07604 if (p->subs[x].owner == oldchan) {
07605 if (!x) {
07606 dahdi_unlink(NULL, p, 0);
07607 }
07608 p->subs[x].owner = newchan;
07609 }
07610 }
07611 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07612 analog_fixup(oldchan, newchan, p->sig_pvt);
07613 #if defined(HAVE_PRI)
07614 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07615 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07616 #endif
07617 #if defined(HAVE_SS7)
07618 } else if (p->sig == SIG_SS7) {
07619 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07620 #endif
07621 }
07622 update_conf(p);
07623
07624 ast_mutex_unlock(&p->lock);
07625
07626 if (newchan->_state == AST_STATE_RINGING) {
07627 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07628 }
07629 return 0;
07630 }
07631
07632 static int dahdi_ring_phone(struct dahdi_pvt *p)
07633 {
07634 int x;
07635 int res;
07636
07637 x = 0;
07638 x = DAHDI_ONHOOK;
07639 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07640 do {
07641 x = DAHDI_RING;
07642 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07643 if (res) {
07644 switch (errno) {
07645 case EBUSY:
07646 case EINTR:
07647
07648 usleep(10000);
07649 continue;
07650 case EINPROGRESS:
07651 res = 0;
07652 break;
07653 default:
07654 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07655 res = 0;
07656 }
07657 }
07658 } while (res);
07659 return res;
07660 }
07661
07662 static void *analog_ss_thread(void *data);
07663
07664 static int attempt_transfer(struct dahdi_pvt *p)
07665 {
07666
07667
07668
07669 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07670
07671
07672 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07673 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07674 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07675 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07676 }
07677 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07678 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07679 }
07680 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07681 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07682 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07683 return -1;
07684 }
07685
07686 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07687 unalloc_sub(p, SUB_THREEWAY);
07688 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07689 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07690 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07691 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07692 }
07693 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07694 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07695 }
07696 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07697 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07698 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07699 return -1;
07700 }
07701
07702 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07703 ast_channel_unlock(p->subs[SUB_REAL].owner);
07704 unalloc_sub(p, SUB_THREEWAY);
07705
07706 return 1;
07707 } else {
07708 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07709 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07710 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07711 return -1;
07712 }
07713 return 0;
07714 }
07715
07716 static int check_for_conference(struct dahdi_pvt *p)
07717 {
07718 struct dahdi_confinfo ci;
07719
07720 if (p->master || (p->confno > -1))
07721 return 0;
07722 memset(&ci, 0, sizeof(ci));
07723 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07724 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07725 return 0;
07726 }
07727
07728
07729
07730 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07731 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07732 return 1;
07733 }
07734 return 0;
07735 }
07736
07737
07738
07739
07740
07741
07742 static int get_alarms(struct dahdi_pvt *p)
07743 {
07744 int res;
07745 struct dahdi_spaninfo zi;
07746 struct dahdi_params params;
07747
07748 memset(&zi, 0, sizeof(zi));
07749 zi.spanno = p->span;
07750
07751 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07752 if (zi.alarms != DAHDI_ALARM_NONE)
07753 return zi.alarms;
07754 } else {
07755 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07756 return 0;
07757 }
07758
07759
07760 memset(¶ms, 0, sizeof(params));
07761 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07762 return params.chan_alarms;
07763
07764 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07765
07766 return DAHDI_ALARM_NONE;
07767 }
07768
07769 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07770 {
07771 struct dahdi_pvt *p = ast->tech_pvt;
07772 struct ast_frame *f = *dest;
07773
07774 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07775 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07776 f->subclass.integer, f->subclass.integer, ast->name);
07777
07778 if (p->confirmanswer) {
07779 if (f->frametype == AST_FRAME_DTMF_END) {
07780 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07781
07782
07783 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07784 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07785
07786 p->confirmanswer = 0;
07787 } else {
07788 p->subs[idx].f.frametype = AST_FRAME_NULL;
07789 p->subs[idx].f.subclass.integer = 0;
07790 }
07791 *dest = &p->subs[idx].f;
07792 } else if (p->callwaitcas) {
07793 if (f->frametype == AST_FRAME_DTMF_END) {
07794 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07795 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07796 ast_free(p->cidspill);
07797 p->cidspill = NULL;
07798 send_cwcidspill(p);
07799 }
07800 p->callwaitcas = 0;
07801 }
07802 p->subs[idx].f.frametype = AST_FRAME_NULL;
07803 p->subs[idx].f.subclass.integer = 0;
07804 *dest = &p->subs[idx].f;
07805 } else if (f->subclass.integer == 'f') {
07806 if (f->frametype == AST_FRAME_DTMF_END) {
07807
07808 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07809
07810 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07811 struct dahdi_bufferinfo bi = {
07812 .txbufpolicy = p->faxbuf_policy,
07813 .bufsize = p->bufsize,
07814 .numbufs = p->faxbuf_no
07815 };
07816 int res;
07817
07818 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07819 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07820 } else {
07821 p->bufferoverrideinuse = 1;
07822 }
07823 }
07824 p->faxhandled = 1;
07825 if (p->dsp) {
07826 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07827 ast_dsp_set_features(p->dsp, p->dsp_features);
07828 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07829 }
07830 if (strcmp(ast->exten, "fax")) {
07831 const char *target_context = S_OR(ast->macrocontext, ast->context);
07832
07833
07834
07835
07836
07837 ast_mutex_unlock(&p->lock);
07838 ast_channel_unlock(ast);
07839 if (ast_exists_extension(ast, target_context, "fax", 1,
07840 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07841 ast_channel_lock(ast);
07842 ast_mutex_lock(&p->lock);
07843 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07844
07845 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07846 if (ast_async_goto(ast, target_context, "fax", 1))
07847 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07848 } else {
07849 ast_channel_lock(ast);
07850 ast_mutex_lock(&p->lock);
07851 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07852 }
07853 } else {
07854 ast_debug(1, "Already in a fax extension, not redirecting\n");
07855 }
07856 } else {
07857 ast_debug(1, "Fax already handled\n");
07858 }
07859 dahdi_confmute(p, 0);
07860 }
07861 p->subs[idx].f.frametype = AST_FRAME_NULL;
07862 p->subs[idx].f.subclass.integer = 0;
07863 *dest = &p->subs[idx].f;
07864 }
07865 }
07866
07867 static void handle_alarms(struct dahdi_pvt *p, int alms)
07868 {
07869 const char *alarm_str;
07870
07871 #if defined(HAVE_PRI)
07872 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07873 return;
07874 }
07875 #endif
07876
07877 alarm_str = alarm2str(alms);
07878 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07879 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07880 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07881 "Alarm: %s\r\n"
07882 "Channel: %d\r\n",
07883 alarm_str, p->channel);
07884 }
07885
07886 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07887 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07888 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07889 "Alarm: %s\r\n"
07890 "Span: %d\r\n",
07891 alarm_str, p->span);
07892 }
07893 }
07894
07895 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07896 {
07897 int res, x;
07898 int idx, mysig;
07899 char *c;
07900 struct dahdi_pvt *p = ast->tech_pvt;
07901 pthread_t threadid;
07902 struct ast_channel *chan;
07903 struct ast_frame *f;
07904
07905 idx = dahdi_get_index(ast, p, 0);
07906 if (idx < 0) {
07907 return &ast_null_frame;
07908 }
07909 mysig = p->sig;
07910 if (p->outsigmod > -1)
07911 mysig = p->outsigmod;
07912 p->subs[idx].f.frametype = AST_FRAME_NULL;
07913 p->subs[idx].f.subclass.integer = 0;
07914 p->subs[idx].f.datalen = 0;
07915 p->subs[idx].f.samples = 0;
07916 p->subs[idx].f.mallocd = 0;
07917 p->subs[idx].f.offset = 0;
07918 p->subs[idx].f.src = "dahdi_handle_event";
07919 p->subs[idx].f.data.ptr = NULL;
07920 f = &p->subs[idx].f;
07921
07922 if (p->fake_event) {
07923 res = p->fake_event;
07924 p->fake_event = 0;
07925 } else
07926 res = dahdi_get_event(p->subs[idx].dfd);
07927
07928 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07929
07930 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07931 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07932 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07933 #if defined(HAVE_PRI)
07934 if (dahdi_sig_pri_lib_handles(p->sig)
07935 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07936 && p->pri
07937 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07938
07939 } else
07940 #endif
07941 {
07942
07943 dahdi_confmute(p, 0);
07944 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07945 p->subs[idx].f.subclass.integer = res & 0xff;
07946 dahdi_handle_dtmf(ast, idx, &f);
07947 }
07948 return f;
07949 }
07950
07951 if (res & DAHDI_EVENT_DTMFDOWN) {
07952 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07953 #if defined(HAVE_PRI)
07954 if (dahdi_sig_pri_lib_handles(p->sig)
07955 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07956 && p->pri
07957 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07958
07959 } else
07960 #endif
07961 {
07962
07963 dahdi_confmute(p, 1);
07964 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07965 p->subs[idx].f.subclass.integer = res & 0xff;
07966 dahdi_handle_dtmf(ast, idx, &f);
07967 }
07968 return &p->subs[idx].f;
07969 }
07970
07971 switch (res) {
07972 case DAHDI_EVENT_EC_DISABLED:
07973 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07974 p->echocanon = 0;
07975 break;
07976 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07977 case DAHDI_EVENT_TX_CED_DETECTED:
07978 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07979 break;
07980 case DAHDI_EVENT_RX_CED_DETECTED:
07981 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07982 break;
07983 case DAHDI_EVENT_EC_NLP_DISABLED:
07984 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07985 break;
07986 case DAHDI_EVENT_EC_NLP_ENABLED:
07987 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07988 break;
07989 #endif
07990 case DAHDI_EVENT_BITSCHANGED:
07991 #ifdef HAVE_OPENR2
07992 if (p->sig != SIG_MFCR2) {
07993 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07994 } else {
07995 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07996 openr2_chan_handle_cas(p->r2chan);
07997 }
07998 #else
07999 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08000 #endif
08001 break;
08002 case DAHDI_EVENT_PULSE_START:
08003
08004 if (!ast->pbx)
08005 tone_zone_play_tone(p->subs[idx].dfd, -1);
08006 break;
08007 case DAHDI_EVENT_DIALCOMPLETE:
08008
08009 #if defined(HAVE_PRI)
08010 if (dahdi_sig_pri_lib_handles(p->sig)) {
08011 if (p->inalarm) {
08012 break;
08013 }
08014 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08015 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08016 strerror(errno));
08017 return NULL;
08018 }
08019 if (x) {
08020
08021 break;
08022 }
08023
08024
08025
08026
08027 sig_pri_dial_complete(p->sig_pvt, ast);
08028 break;
08029 }
08030 #endif
08031 #ifdef HAVE_OPENR2
08032 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08033
08034
08035 break;
08036 }
08037 #endif
08038 if (p->inalarm) break;
08039 if ((p->radio || (p->oprmode < 0))) break;
08040 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08041 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08042 return NULL;
08043 }
08044 if (!x) {
08045 dahdi_enable_ec(p);
08046 if (p->echobreak) {
08047 dahdi_train_ec(p);
08048 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08049 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08050 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08051 p->echobreak = 0;
08052 } else {
08053 p->dialing = 0;
08054 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08055
08056 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08057 ast_setstate(ast, AST_STATE_UP);
08058 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08059 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08060 break;
08061 } else {
08062
08063 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08064 }
08065 }
08066 if (ast->_state == AST_STATE_DIALING) {
08067 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08068 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08069 } else if (p->confirmanswer || (!p->dialednone
08070 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08071 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08072 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08073 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08074 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08075 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08076 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08077 || (mysig == SIG_SF_FEATB)))) {
08078 ast_setstate(ast, AST_STATE_RINGING);
08079 } else if (!p->answeronpolarityswitch) {
08080 ast_setstate(ast, AST_STATE_UP);
08081 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08082 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08083
08084 p->polarity = POLARITY_REV;
08085 } else {
08086
08087 p->polarity = POLARITY_IDLE;
08088 }
08089 }
08090 }
08091 }
08092 break;
08093 case DAHDI_EVENT_ALARM:
08094 switch (p->sig) {
08095 #if defined(HAVE_PRI)
08096 case SIG_PRI_LIB_HANDLE_CASES:
08097 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08098 break;
08099 #endif
08100 #if defined(HAVE_SS7)
08101 case SIG_SS7:
08102 sig_ss7_set_alarm(p->sig_pvt, 1);
08103 break;
08104 #endif
08105 default:
08106 p->inalarm = 1;
08107 break;
08108 }
08109 res = get_alarms(p);
08110 handle_alarms(p, res);
08111 #ifdef HAVE_PRI
08112 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08113
08114 } else {
08115 break;
08116 }
08117 #endif
08118 #if defined(HAVE_SS7)
08119 if (p->sig == SIG_SS7)
08120 break;
08121 #endif
08122 #ifdef HAVE_OPENR2
08123 if (p->sig == SIG_MFCR2)
08124 break;
08125 #endif
08126 case DAHDI_EVENT_ONHOOK:
08127 if (p->radio) {
08128 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08129 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08130 break;
08131 }
08132 if (p->oprmode < 0)
08133 {
08134 if (p->oprmode != -1) break;
08135 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08136 {
08137
08138 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08139 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08140 save_conference(p->oprpeer);
08141 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08142 }
08143 break;
08144 }
08145 switch (p->sig) {
08146 case SIG_FXOLS:
08147 case SIG_FXOGS:
08148 case SIG_FXOKS:
08149
08150 if (idx == SUB_REAL) {
08151
08152 if (p->subs[SUB_CALLWAIT].owner) {
08153
08154 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08155 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08156 unalloc_sub(p, SUB_CALLWAIT);
08157 #if 0
08158 p->subs[idx].needanswer = 0;
08159 p->subs[idx].needringing = 0;
08160 #endif
08161 p->callwaitingrepeat = 0;
08162 p->cidcwexpire = 0;
08163 p->cid_suppress_expire = 0;
08164 p->owner = NULL;
08165
08166 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08167 p->dialing = 1;
08168 dahdi_ring_phone(p);
08169 } else if (p->subs[SUB_THREEWAY].owner) {
08170 unsigned int mssinceflash;
08171
08172
08173 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08174
08175 DLA_UNLOCK(&p->lock);
08176 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08177
08178
08179
08180 DLA_LOCK(&p->lock);
08181 if (p->owner != ast) {
08182 ast_log(LOG_WARNING, "This isn't good...\n");
08183 return NULL;
08184 }
08185 }
08186 if (!p->subs[SUB_THREEWAY].owner) {
08187 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08188 return NULL;
08189 }
08190 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08191 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08192 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08193
08194
08195 if (p->subs[SUB_THREEWAY].owner)
08196 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08197 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08198 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08199 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08200 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08201 if (p->transfer) {
08202
08203 p->subs[SUB_REAL].inthreeway = 0;
08204 p->subs[SUB_THREEWAY].inthreeway = 0;
08205
08206 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08207 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08208
08209 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08210 p->owner = NULL;
08211
08212 dahdi_ring_phone(p);
08213 } else {
08214 if ((res = attempt_transfer(p)) < 0) {
08215 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08216 if (p->subs[SUB_THREEWAY].owner)
08217 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08218 } else if (res) {
08219
08220 if (p->subs[SUB_THREEWAY].owner)
08221 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08222 break;
08223 }
08224 }
08225 } else {
08226 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08227 if (p->subs[SUB_THREEWAY].owner)
08228 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08229 }
08230 } else {
08231 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08232
08233 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08234 p->owner = NULL;
08235
08236 dahdi_ring_phone(p);
08237 }
08238 }
08239 } else {
08240 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08241 }
08242
08243 default:
08244 dahdi_disable_ec(p);
08245 return NULL;
08246 }
08247 break;
08248 case DAHDI_EVENT_RINGOFFHOOK:
08249 if (p->inalarm) break;
08250 if (p->oprmode < 0)
08251 {
08252 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08253 {
08254
08255 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08256 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08257 restore_conference(p->oprpeer);
08258 }
08259 break;
08260 }
08261 if (p->radio)
08262 {
08263 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08264 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08265 break;
08266 }
08267
08268
08269 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08270 c = strchr(p->dialdest, '/');
08271 if (c)
08272 c++;
08273 else
08274 c = p->dialdest;
08275 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08276 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08277 if (strlen(p->dop.dialstr) > 4) {
08278 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08279 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08280 p->echorest[sizeof(p->echorest) - 1] = '\0';
08281 p->echobreak = 1;
08282 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08283 } else
08284 p->echobreak = 0;
08285 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08286 int saveerr = errno;
08287
08288 x = DAHDI_ONHOOK;
08289 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08290 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08291 return NULL;
08292 }
08293 p->dialing = 1;
08294 return &p->subs[idx].f;
08295 }
08296 switch (p->sig) {
08297 case SIG_FXOLS:
08298 case SIG_FXOGS:
08299 case SIG_FXOKS:
08300 switch (ast->_state) {
08301 case AST_STATE_RINGING:
08302 dahdi_enable_ec(p);
08303 dahdi_train_ec(p);
08304 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08305 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08306
08307 p->subs[SUB_REAL].needringing = 0;
08308 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08309 ast_debug(1, "channel %d answered\n", p->channel);
08310
08311
08312 ast_free(p->cidspill);
08313 p->cidspill = NULL;
08314 restore_conference(p);
08315
08316 p->dialing = 0;
08317 p->callwaitcas = 0;
08318 if (p->confirmanswer) {
08319
08320 p->subs[idx].f.frametype = AST_FRAME_NULL;
08321 p->subs[idx].f.subclass.integer = 0;
08322 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08323
08324 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08325 if (res < 0) {
08326 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08327 p->dop.dialstr[0] = '\0';
08328 return NULL;
08329 } else {
08330 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08331 p->subs[idx].f.frametype = AST_FRAME_NULL;
08332 p->subs[idx].f.subclass.integer = 0;
08333 p->dialing = 1;
08334 }
08335 p->dop.dialstr[0] = '\0';
08336 ast_setstate(ast, AST_STATE_DIALING);
08337 } else
08338 ast_setstate(ast, AST_STATE_UP);
08339 return &p->subs[idx].f;
08340 case AST_STATE_DOWN:
08341 ast_setstate(ast, AST_STATE_RING);
08342 ast->rings = 1;
08343 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08344 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08345 ast_debug(1, "channel %d picked up\n", p->channel);
08346 return &p->subs[idx].f;
08347 case AST_STATE_UP:
08348
08349 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08350
08351 if (ast_bridged_channel(p->owner))
08352 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08353 p->subs[idx].needunhold = 1;
08354 break;
08355 case AST_STATE_RESERVED:
08356
08357 if (has_voicemail(p))
08358 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08359 else
08360 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08361 break;
08362 default:
08363 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08364 }
08365 break;
08366 case SIG_FXSLS:
08367 case SIG_FXSGS:
08368 case SIG_FXSKS:
08369 if (ast->_state == AST_STATE_RING) {
08370 p->ringt = p->ringt_base;
08371 }
08372
08373
08374
08375 ast_debug(1, "Setting IDLE polarity due "
08376 "to ring. Old polarity was %d\n",
08377 p->polarity);
08378 p->polarity = POLARITY_IDLE;
08379
08380
08381 case SIG_EM:
08382 case SIG_EM_E1:
08383 case SIG_EMWINK:
08384 case SIG_FEATD:
08385 case SIG_FEATDMF:
08386 case SIG_FEATDMF_TA:
08387 case SIG_E911:
08388 case SIG_FGC_CAMA:
08389 case SIG_FGC_CAMAMF:
08390 case SIG_FEATB:
08391 case SIG_SF:
08392 case SIG_SFWINK:
08393 case SIG_SF_FEATD:
08394 case SIG_SF_FEATDMF:
08395 case SIG_SF_FEATB:
08396 if (ast->_state == AST_STATE_PRERING)
08397 ast_setstate(ast, AST_STATE_RING);
08398 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08399 ast_debug(1, "Ring detected\n");
08400 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08401 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08402 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08403 ast_debug(1, "Line answered\n");
08404 if (p->confirmanswer) {
08405 p->subs[idx].f.frametype = AST_FRAME_NULL;
08406 p->subs[idx].f.subclass.integer = 0;
08407 } else {
08408 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08409 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08410 ast_setstate(ast, AST_STATE_UP);
08411 }
08412 } else if (ast->_state != AST_STATE_RING)
08413 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08414 break;
08415 default:
08416 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08417 }
08418 break;
08419 case DAHDI_EVENT_RINGBEGIN:
08420 switch (p->sig) {
08421 case SIG_FXSLS:
08422 case SIG_FXSGS:
08423 case SIG_FXSKS:
08424 if (ast->_state == AST_STATE_RING) {
08425 p->ringt = p->ringt_base;
08426 }
08427 break;
08428 }
08429 break;
08430 case DAHDI_EVENT_RINGERON:
08431 break;
08432 case DAHDI_EVENT_NOALARM:
08433 switch (p->sig) {
08434 #if defined(HAVE_PRI)
08435 case SIG_PRI_LIB_HANDLE_CASES:
08436 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08437 break;
08438 #endif
08439 #if defined(HAVE_SS7)
08440 case SIG_SS7:
08441 sig_ss7_set_alarm(p->sig_pvt, 0);
08442 break;
08443 #endif
08444 default:
08445 p->inalarm = 0;
08446 break;
08447 }
08448 handle_clear_alarms(p);
08449 break;
08450 case DAHDI_EVENT_WINKFLASH:
08451 if (p->inalarm) break;
08452 if (p->radio) break;
08453 if (p->oprmode < 0) break;
08454 if (p->oprmode > 1)
08455 {
08456 struct dahdi_params par;
08457
08458 memset(&par, 0, sizeof(par));
08459 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08460 {
08461 if (!par.rxisoffhook)
08462 {
08463
08464 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08465 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08466 save_conference(p);
08467 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08468 }
08469 }
08470 break;
08471 }
08472
08473 p->flashtime = ast_tvnow();
08474 switch (mysig) {
08475 case SIG_FXOLS:
08476 case SIG_FXOGS:
08477 case SIG_FXOKS:
08478 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08479 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08480
08481
08482 ast_free(p->cidspill);
08483 p->cidspill = NULL;
08484 restore_conference(p);
08485 p->callwaitcas = 0;
08486
08487 if (idx != SUB_REAL) {
08488 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08489 goto winkflashdone;
08490 }
08491
08492 if (p->subs[SUB_CALLWAIT].owner) {
08493
08494 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08495 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08496 p->owner = p->subs[SUB_REAL].owner;
08497 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08498 if (p->owner->_state == AST_STATE_RINGING) {
08499 ast_setstate(p->owner, AST_STATE_UP);
08500 p->subs[SUB_REAL].needanswer = 1;
08501 }
08502 p->callwaitingrepeat = 0;
08503 p->cidcwexpire = 0;
08504 p->cid_suppress_expire = 0;
08505
08506 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08507 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08508 S_OR(p->mohsuggest, NULL),
08509 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08510 }
08511 p->subs[SUB_CALLWAIT].needhold = 1;
08512 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08513 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08514 S_OR(p->mohsuggest, NULL),
08515 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08516 }
08517 p->subs[SUB_REAL].needunhold = 1;
08518 } else if (!p->subs[SUB_THREEWAY].owner) {
08519 if (!p->threewaycalling) {
08520
08521 p->subs[SUB_REAL].needflash = 1;
08522 goto winkflashdone;
08523 } else if (!check_for_conference(p)) {
08524 char cid_num[256];
08525 char cid_name[256];
08526
08527 cid_num[0] = 0;
08528 cid_name[0] = 0;
08529 if (p->dahditrcallerid && p->owner) {
08530 if (p->owner->caller.id.number.valid
08531 && p->owner->caller.id.number.str) {
08532 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08533 sizeof(cid_num));
08534 }
08535 if (p->owner->caller.id.name.valid
08536 && p->owner->caller.id.name.str) {
08537 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08538 sizeof(cid_name));
08539 }
08540 }
08541
08542
08543 if (!((ast->pbx) ||
08544 (ast->_state == AST_STATE_UP) ||
08545 (ast->_state == AST_STATE_RING))) {
08546 ast_debug(1, "Flash when call not up or ringing\n");
08547 goto winkflashdone;
08548 }
08549 if (alloc_sub(p, SUB_THREEWAY)) {
08550 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08551 goto winkflashdone;
08552 }
08553
08554
08555
08556
08557
08558
08559
08560 ast_mutex_unlock(&p->lock);
08561 ast_channel_unlock(ast);
08562 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08563 ast_channel_lock(ast);
08564 ast_mutex_lock(&p->lock);
08565 if (p->dahditrcallerid) {
08566 if (!p->origcid_num)
08567 p->origcid_num = ast_strdup(p->cid_num);
08568 if (!p->origcid_name)
08569 p->origcid_name = ast_strdup(p->cid_name);
08570 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08571 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08572 }
08573
08574 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08575
08576 dahdi_disable_ec(p);
08577 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08578 if (res)
08579 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08580 p->owner = chan;
08581 if (!chan) {
08582 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08583 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08584 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08585 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08586 dahdi_enable_ec(p);
08587 ast_hangup(chan);
08588 } else {
08589 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08590
08591
08592 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08593 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08594 S_OR(p->mohsuggest, NULL),
08595 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08596 }
08597 p->subs[SUB_THREEWAY].needhold = 1;
08598 }
08599 }
08600 } else {
08601
08602 if (p->subs[SUB_THREEWAY].inthreeway) {
08603
08604 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08605
08606 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08607
08608 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08609 p->owner = p->subs[SUB_REAL].owner;
08610 }
08611
08612 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08613 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08614 p->subs[SUB_REAL].inthreeway = 0;
08615 p->subs[SUB_THREEWAY].inthreeway = 0;
08616 } else {
08617
08618 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08619 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08620 int otherindex = SUB_THREEWAY;
08621
08622 ast_verb(3, "Building conference call with %s and %s\n",
08623 p->subs[SUB_THREEWAY].owner->name,
08624 p->subs[SUB_REAL].owner->name);
08625
08626 p->subs[SUB_THREEWAY].inthreeway = 1;
08627 p->subs[SUB_REAL].inthreeway = 1;
08628 if (ast->_state == AST_STATE_UP) {
08629 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08630 otherindex = SUB_REAL;
08631 }
08632 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08633 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08634 p->subs[otherindex].needunhold = 1;
08635 p->owner = p->subs[SUB_REAL].owner;
08636 } else {
08637 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08638 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08639 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08640 p->owner = p->subs[SUB_REAL].owner;
08641 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08642 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08643 p->subs[SUB_REAL].needunhold = 1;
08644 dahdi_enable_ec(p);
08645 }
08646 }
08647 }
08648 winkflashdone:
08649 update_conf(p);
08650 break;
08651 case SIG_EM:
08652 case SIG_EM_E1:
08653 case SIG_FEATD:
08654 case SIG_SF:
08655 case SIG_SFWINK:
08656 case SIG_SF_FEATD:
08657 case SIG_FXSLS:
08658 case SIG_FXSGS:
08659 if (p->dialing)
08660 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08661 else
08662 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08663 break;
08664 case SIG_FEATDMF_TA:
08665 switch (p->whichwink) {
08666 case 0:
08667 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08668 S_COR(p->owner->caller.ani.number.valid,
08669 p->owner->caller.ani.number.str, ""));
08670 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08671 p->owner->caller.ani2,
08672 S_COR(p->owner->caller.ani.number.valid,
08673 p->owner->caller.ani.number.str, ""));
08674 break;
08675 case 1:
08676 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08677 break;
08678 case 2:
08679 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08680 return NULL;
08681 }
08682 p->whichwink++;
08683
08684 case SIG_FEATDMF:
08685 case SIG_E911:
08686 case SIG_FGC_CAMAMF:
08687 case SIG_FGC_CAMA:
08688 case SIG_FEATB:
08689 case SIG_SF_FEATDMF:
08690 case SIG_SF_FEATB:
08691 case SIG_EMWINK:
08692
08693 if (!ast_strlen_zero(p->dop.dialstr)) {
08694 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08695 if (res < 0) {
08696 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08697 p->dop.dialstr[0] = '\0';
08698 return NULL;
08699 } else
08700 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08701 }
08702 p->dop.dialstr[0] = '\0';
08703 break;
08704 default:
08705 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08706 }
08707 break;
08708 case DAHDI_EVENT_HOOKCOMPLETE:
08709 if (p->inalarm) break;
08710 if ((p->radio || (p->oprmode < 0))) break;
08711 if (p->waitingfordt.tv_sec) break;
08712 switch (mysig) {
08713 case SIG_FXSLS:
08714 case SIG_FXSGS:
08715 case SIG_FXSKS:
08716 case SIG_EM:
08717 case SIG_EM_E1:
08718 case SIG_EMWINK:
08719 case SIG_FEATD:
08720 case SIG_SF:
08721 case SIG_SFWINK:
08722 case SIG_SF_FEATD:
08723 if (!ast_strlen_zero(p->dop.dialstr)) {
08724 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08725 if (res < 0) {
08726 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08727 p->dop.dialstr[0] = '\0';
08728 return NULL;
08729 } else
08730 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08731 }
08732 p->dop.dialstr[0] = '\0';
08733 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08734 break;
08735 case SIG_FEATDMF:
08736 case SIG_FEATDMF_TA:
08737 case SIG_E911:
08738 case SIG_FGC_CAMA:
08739 case SIG_FGC_CAMAMF:
08740 case SIG_FEATB:
08741 case SIG_SF_FEATDMF:
08742 case SIG_SF_FEATB:
08743 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08744 break;
08745 default:
08746 break;
08747 }
08748 break;
08749 case DAHDI_EVENT_POLARITY:
08750
08751
08752
08753
08754
08755
08756 if (p->polarity == POLARITY_IDLE) {
08757 p->polarity = POLARITY_REV;
08758 if (p->answeronpolarityswitch &&
08759 ((ast->_state == AST_STATE_DIALING) ||
08760 (ast->_state == AST_STATE_RINGING))) {
08761 ast_debug(1, "Answering on polarity switch!\n");
08762 ast_setstate(p->owner, AST_STATE_UP);
08763 if (p->hanguponpolarityswitch) {
08764 p->polaritydelaytv = ast_tvnow();
08765 }
08766 } else
08767 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08768 }
08769
08770
08771 if (p->hanguponpolarityswitch &&
08772 (p->polarityonanswerdelay > 0) &&
08773 (p->polarity == POLARITY_REV) &&
08774 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08775
08776 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, 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) );
08777
08778 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08779 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08780 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08781 p->polarity = POLARITY_IDLE;
08782 } else
08783 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
08784
08785 } else {
08786 p->polarity = POLARITY_IDLE;
08787 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08788 }
08789
08790 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, 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) );
08791 break;
08792 default:
08793 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08794 }
08795 return &p->subs[idx].f;
08796 }
08797
08798 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08799 {
08800 int res;
08801 int idx;
08802 struct ast_frame *f;
08803 int usedindex = -1;
08804 struct dahdi_pvt *p = ast->tech_pvt;
08805
08806 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08807 idx = SUB_REAL;
08808 }
08809
08810 p->subs[idx].f.frametype = AST_FRAME_NULL;
08811 p->subs[idx].f.datalen = 0;
08812 p->subs[idx].f.samples = 0;
08813 p->subs[idx].f.mallocd = 0;
08814 p->subs[idx].f.offset = 0;
08815 p->subs[idx].f.subclass.integer = 0;
08816 p->subs[idx].f.delivery = ast_tv(0,0);
08817 p->subs[idx].f.src = "dahdi_exception";
08818 p->subs[idx].f.data.ptr = NULL;
08819
08820
08821 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08822
08823
08824
08825
08826
08827 if (p->fake_event) {
08828 res = p->fake_event;
08829 p->fake_event = 0;
08830 } else
08831 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08832
08833 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08834 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08835 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08836 p->owner = p->subs[SUB_REAL].owner;
08837 if (p->owner && ast_bridged_channel(p->owner))
08838 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08839 p->subs[SUB_REAL].needunhold = 1;
08840 }
08841 switch (res) {
08842 case DAHDI_EVENT_ONHOOK:
08843 dahdi_disable_ec(p);
08844 if (p->owner) {
08845 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08846 dahdi_ring_phone(p);
08847 p->callwaitingrepeat = 0;
08848 p->cidcwexpire = 0;
08849 p->cid_suppress_expire = 0;
08850 } else
08851 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08852 update_conf(p);
08853 break;
08854 case DAHDI_EVENT_RINGOFFHOOK:
08855 dahdi_enable_ec(p);
08856 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08857 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08858 p->subs[SUB_REAL].needanswer = 1;
08859 p->dialing = 0;
08860 }
08861 break;
08862 case DAHDI_EVENT_HOOKCOMPLETE:
08863 case DAHDI_EVENT_RINGERON:
08864 case DAHDI_EVENT_RINGEROFF:
08865
08866 break;
08867 case DAHDI_EVENT_WINKFLASH:
08868 p->flashtime = ast_tvnow();
08869 if (p->owner) {
08870 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08871 if (p->owner->_state != AST_STATE_UP) {
08872
08873 usedindex = dahdi_get_index(p->owner, p, 0);
08874 if (usedindex > -1) {
08875 p->subs[usedindex].needanswer = 1;
08876 }
08877 ast_setstate(p->owner, AST_STATE_UP);
08878 }
08879 p->callwaitingrepeat = 0;
08880 p->cidcwexpire = 0;
08881 p->cid_suppress_expire = 0;
08882 if (ast_bridged_channel(p->owner))
08883 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08884 p->subs[SUB_REAL].needunhold = 1;
08885 } else
08886 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08887 update_conf(p);
08888 break;
08889 default:
08890 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08891 }
08892 f = &p->subs[idx].f;
08893 return f;
08894 }
08895 if (!(p->radio || (p->oprmode < 0)))
08896 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08897
08898 if (ast != p->owner) {
08899 if (p->owner) {
08900 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08901 }
08902 f = &p->subs[idx].f;
08903 return f;
08904 }
08905
08906 f = dahdi_handle_event(ast);
08907 if (!f) {
08908 const char *name = ast_strdupa(ast->name);
08909
08910
08911 ast_mutex_unlock(&p->lock);
08912 ast_channel_unlock(ast);
08913 ast_set_hangupsource(ast, name, 0);
08914 ast_channel_lock(ast);
08915 ast_mutex_lock(&p->lock);
08916 }
08917 return f;
08918 }
08919
08920 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08921 {
08922 struct dahdi_pvt *p = ast->tech_pvt;
08923 struct ast_frame *f;
08924 ast_mutex_lock(&p->lock);
08925 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08926 struct analog_pvt *analog_p = p->sig_pvt;
08927 f = analog_exception(analog_p, ast);
08928 } else {
08929 f = __dahdi_exception(ast);
08930 }
08931 ast_mutex_unlock(&p->lock);
08932 return f;
08933 }
08934
08935 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08936 {
08937 struct dahdi_pvt *p;
08938 int res;
08939 int idx;
08940 void *readbuf;
08941 struct ast_frame *f;
08942
08943
08944
08945
08946
08947
08948 p = ast->tech_pvt;
08949 while (ast_mutex_trylock(&p->lock)) {
08950 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08951
08952
08953
08954
08955
08956
08957
08958
08959
08960
08961
08962
08963 if (ast->tech_pvt != p) {
08964
08965 return &ast_null_frame;
08966 }
08967 }
08968
08969 idx = dahdi_get_index(ast, p, 0);
08970
08971
08972 if (idx < 0) {
08973 ast_log(LOG_WARNING, "We don't exist?\n");
08974 ast_mutex_unlock(&p->lock);
08975 return NULL;
08976 }
08977
08978 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08979 ast_mutex_unlock(&p->lock);
08980 return NULL;
08981 }
08982
08983 p->subs[idx].f.frametype = AST_FRAME_NULL;
08984 p->subs[idx].f.datalen = 0;
08985 p->subs[idx].f.samples = 0;
08986 p->subs[idx].f.mallocd = 0;
08987 p->subs[idx].f.offset = 0;
08988 p->subs[idx].f.subclass.integer = 0;
08989 p->subs[idx].f.delivery = ast_tv(0,0);
08990 p->subs[idx].f.src = "dahdi_read";
08991 p->subs[idx].f.data.ptr = NULL;
08992
08993
08994 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08995 {
08996 struct dahdi_params ps;
08997
08998 memset(&ps, 0, sizeof(ps));
08999 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09000 ast_mutex_unlock(&p->lock);
09001 return NULL;
09002 }
09003 p->firstradio = 1;
09004 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09005 if (ps.rxisoffhook)
09006 {
09007 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09008 }
09009 else
09010 {
09011 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09012 }
09013 ast_mutex_unlock(&p->lock);
09014 return &p->subs[idx].f;
09015 }
09016 if (p->ringt > 0) {
09017 if (!(--p->ringt)) {
09018 ast_mutex_unlock(&p->lock);
09019 return NULL;
09020 }
09021 }
09022
09023 #ifdef HAVE_OPENR2
09024 if (p->mfcr2) {
09025 openr2_chan_process_event(p->r2chan);
09026 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09027 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09028
09029
09030 if (p->mfcr2_call_accepted &&
09031 !p->mfcr2_progress &&
09032 ast->_state == AST_STATE_RINGING) {
09033 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09034 ast_queue_frame(p->owner, &f);
09035 p->mfcr2_progress = 1;
09036 }
09037 }
09038 }
09039 #endif
09040
09041 if (p->subs[idx].needringing) {
09042
09043 p->subs[idx].needringing = 0;
09044 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09045 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09046 ast_setstate(ast, AST_STATE_RINGING);
09047 ast_mutex_unlock(&p->lock);
09048 return &p->subs[idx].f;
09049 }
09050
09051 if (p->subs[idx].needbusy) {
09052
09053 p->subs[idx].needbusy = 0;
09054 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09055 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09056 ast_mutex_unlock(&p->lock);
09057 return &p->subs[idx].f;
09058 }
09059
09060 if (p->subs[idx].needcongestion) {
09061
09062 p->subs[idx].needcongestion = 0;
09063 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09064 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09065 ast_mutex_unlock(&p->lock);
09066 return &p->subs[idx].f;
09067 }
09068
09069 if (p->subs[idx].needanswer) {
09070
09071 p->subs[idx].needanswer = 0;
09072 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09073 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09074 ast_mutex_unlock(&p->lock);
09075 return &p->subs[idx].f;
09076 }
09077 #ifdef HAVE_OPENR2
09078 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09079
09080
09081
09082
09083 ast_mutex_unlock(&p->lock);
09084 return &ast_null_frame;
09085 }
09086 #endif
09087
09088 if (p->subs[idx].needflash) {
09089
09090 p->subs[idx].needflash = 0;
09091 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09092 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09093 ast_mutex_unlock(&p->lock);
09094 return &p->subs[idx].f;
09095 }
09096
09097 if (p->subs[idx].needhold) {
09098
09099 p->subs[idx].needhold = 0;
09100 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09101 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09102 ast_mutex_unlock(&p->lock);
09103 ast_debug(1, "Sending hold on '%s'\n", ast->name);
09104 return &p->subs[idx].f;
09105 }
09106
09107 if (p->subs[idx].needunhold) {
09108
09109 p->subs[idx].needunhold = 0;
09110 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09111 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09112 ast_mutex_unlock(&p->lock);
09113 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09114 return &p->subs[idx].f;
09115 }
09116
09117
09118
09119
09120
09121 if (p->fake_event && p->owner == ast) {
09122 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09123 struct analog_pvt *analog_p = p->sig_pvt;
09124
09125 f = analog_exception(analog_p, ast);
09126 } else {
09127 f = __dahdi_exception(ast);
09128 }
09129 ast_mutex_unlock(&p->lock);
09130 return f;
09131 }
09132
09133 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09134 if (!p->subs[idx].linear) {
09135 p->subs[idx].linear = 1;
09136 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09137 if (res)
09138 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09139 }
09140 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09141 (ast->rawreadformat == AST_FORMAT_ALAW)) {
09142 if (p->subs[idx].linear) {
09143 p->subs[idx].linear = 0;
09144 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09145 if (res)
09146 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09147 }
09148 } else {
09149 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09150 ast_mutex_unlock(&p->lock);
09151 return NULL;
09152 }
09153 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09154 CHECK_BLOCKING(ast);
09155 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09156 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09157
09158 if (res < 0) {
09159 f = NULL;
09160 if (res == -1) {
09161 if (errno == EAGAIN) {
09162
09163 ast_mutex_unlock(&p->lock);
09164 return &p->subs[idx].f;
09165 } else if (errno == ELAST) {
09166 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09167 struct analog_pvt *analog_p = p->sig_pvt;
09168 f = analog_exception(analog_p, ast);
09169 } else {
09170 f = __dahdi_exception(ast);
09171 }
09172 } else
09173 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09174 }
09175 ast_mutex_unlock(&p->lock);
09176 return f;
09177 }
09178 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09179 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09180 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09181 struct analog_pvt *analog_p = p->sig_pvt;
09182 f = analog_exception(analog_p, ast);
09183 } else {
09184 f = __dahdi_exception(ast);
09185 }
09186 ast_mutex_unlock(&p->lock);
09187 return f;
09188 }
09189 if (p->tdd) {
09190 int c;
09191
09192 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09193 if (c < 0) {
09194 ast_debug(1,"tdd_feed failed\n");
09195 ast_mutex_unlock(&p->lock);
09196 return NULL;
09197 }
09198 if (c) {
09199 p->subs[idx].f.subclass.integer = 0;
09200 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09201 p->subs[idx].f.mallocd = 0;
09202 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09203 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09204 p->subs[idx].f.datalen = 1;
09205 *((char *) p->subs[idx].f.data.ptr) = c;
09206 ast_mutex_unlock(&p->lock);
09207 return &p->subs[idx].f;
09208 }
09209 }
09210 if (idx == SUB_REAL) {
09211
09212 if (p->cidcwexpire) {
09213 if (!--p->cidcwexpire) {
09214
09215 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09216 restore_conference(p);
09217 }
09218 }
09219 if (p->cid_suppress_expire) {
09220 --p->cid_suppress_expire;
09221 }
09222 if (p->callwaitingrepeat) {
09223 if (!--p->callwaitingrepeat) {
09224
09225 ++p->callwaitrings;
09226 dahdi_callwait(ast);
09227 }
09228 }
09229 }
09230 if (p->subs[idx].linear) {
09231 p->subs[idx].f.datalen = READ_SIZE * 2;
09232 } else
09233 p->subs[idx].f.datalen = READ_SIZE;
09234
09235
09236 if ((p->owner == ast) && p->cidspill) {
09237 send_callerid(p);
09238 }
09239
09240 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09241 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09242 p->subs[idx].f.samples = READ_SIZE;
09243 p->subs[idx].f.mallocd = 0;
09244 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09245 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09246 #if 0
09247 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09248 #endif
09249 if (p->dialing || p->radio ||
09250 (idx && (ast->_state != AST_STATE_UP)) ||
09251 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09252 ) {
09253
09254
09255 p->subs[idx].f.frametype = AST_FRAME_NULL;
09256 p->subs[idx].f.subclass.integer = 0;
09257 p->subs[idx].f.samples = 0;
09258 p->subs[idx].f.mallocd = 0;
09259 p->subs[idx].f.offset = 0;
09260 p->subs[idx].f.data.ptr = NULL;
09261 p->subs[idx].f.datalen= 0;
09262 }
09263 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09264
09265 int mute;
09266
09267 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09268
09269
09270 mute = ast_dsp_was_muted(p->dsp);
09271 if (p->muting != mute) {
09272 p->muting = mute;
09273 dahdi_confmute(p, mute);
09274 }
09275
09276 if (f) {
09277 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09278 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09279
09280
09281 ast_frfree(f);
09282 f = NULL;
09283 }
09284 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09285 || f->frametype == AST_FRAME_DTMF_END) {
09286 #ifdef HAVE_PRI
09287 if (dahdi_sig_pri_lib_handles(p->sig)
09288 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09289 && p->pri
09290 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09291 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09292
09293 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09294 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09295 f->subclass.integer, f->subclass.integer, ast->name);
09296
09297 f->frametype = AST_FRAME_NULL;
09298 f->subclass.integer = 0;
09299 }
09300 #endif
09301
09302 p->pulsedial = 0;
09303 } else if (p->waitingfordt.tv_sec) {
09304 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09305 p->waitingfordt.tv_sec = 0;
09306 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09307 ast_frfree(f);
09308 f = NULL;
09309 } else if (f->frametype == AST_FRAME_VOICE) {
09310 f->frametype = AST_FRAME_NULL;
09311 f->subclass.integer = 0;
09312 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) {
09313 p->waitingfordt.tv_sec = 0;
09314 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09315 ast_dsp_set_features(p->dsp, p->dsp_features);
09316 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09317 if (!ast_strlen_zero(p->dop.dialstr)) {
09318 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09319 if (res < 0) {
09320 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09321 p->dop.dialstr[0] = '\0';
09322 ast_mutex_unlock(&p->lock);
09323 ast_frfree(f);
09324 return NULL;
09325 } else {
09326 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09327 p->dialing = 1;
09328 p->dop.dialstr[0] = '\0';
09329 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09330 ast_setstate(ast, AST_STATE_DIALING);
09331 }
09332 }
09333 }
09334 }
09335 }
09336 }
09337 } else
09338 f = &p->subs[idx].f;
09339
09340 if (f) {
09341 switch (f->frametype) {
09342 case AST_FRAME_DTMF_BEGIN:
09343 case AST_FRAME_DTMF_END:
09344 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09345 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09346 } else {
09347 dahdi_handle_dtmf(ast, idx, &f);
09348 }
09349 break;
09350 case AST_FRAME_VOICE:
09351 if (p->cidspill || p->cid_suppress_expire) {
09352
09353 p->subs[idx].f.frametype = AST_FRAME_NULL;
09354 p->subs[idx].f.subclass.integer = 0;
09355 p->subs[idx].f.samples = 0;
09356 p->subs[idx].f.mallocd = 0;
09357 p->subs[idx].f.offset = 0;
09358 p->subs[idx].f.data.ptr = NULL;
09359 p->subs[idx].f.datalen= 0;
09360 }
09361 break;
09362 default:
09363 break;
09364 }
09365 }
09366
09367 ast_mutex_unlock(&p->lock);
09368 return f;
09369 }
09370
09371 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09372 {
09373 int sent=0;
09374 int size;
09375 int res;
09376 int fd;
09377 fd = p->subs[idx].dfd;
09378 while (len) {
09379 size = len;
09380 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09381 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09382 res = write(fd, buf, size);
09383 if (res != size) {
09384 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09385 return sent;
09386 }
09387 len -= size;
09388 buf += size;
09389 }
09390 return sent;
09391 }
09392
09393 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09394 {
09395 struct dahdi_pvt *p = ast->tech_pvt;
09396 int res;
09397 int idx;
09398 idx = dahdi_get_index(ast, p, 0);
09399 if (idx < 0) {
09400 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09401 return -1;
09402 }
09403
09404
09405 if (frame->frametype != AST_FRAME_VOICE) {
09406 if (frame->frametype != AST_FRAME_IMAGE)
09407 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09408 return 0;
09409 }
09410 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09411 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09412 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09413 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09414 return -1;
09415 }
09416 if (p->dialing) {
09417 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09418 return 0;
09419 }
09420 if (!p->owner) {
09421 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09422 return 0;
09423 }
09424 if (p->cidspill) {
09425 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09426 ast->name);
09427 return 0;
09428 }
09429
09430 if (!frame->data.ptr || !frame->datalen)
09431 return 0;
09432
09433 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09434 if (!p->subs[idx].linear) {
09435 p->subs[idx].linear = 1;
09436 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09437 if (res)
09438 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09439 }
09440 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09441 } else {
09442
09443 if (p->subs[idx].linear) {
09444 p->subs[idx].linear = 0;
09445 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09446 if (res)
09447 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09448 }
09449 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09450 }
09451 if (res < 0) {
09452 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09453 return -1;
09454 }
09455 return 0;
09456 }
09457
09458 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09459 {
09460 struct dahdi_pvt *p = chan->tech_pvt;
09461 int res=-1;
09462 int idx;
09463 int func = DAHDI_FLASH;
09464
09465 ast_mutex_lock(&p->lock);
09466 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09467 switch (p->sig) {
09468 #if defined(HAVE_PRI)
09469 case SIG_PRI_LIB_HANDLE_CASES:
09470 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09471 ast_mutex_unlock(&p->lock);
09472 return res;
09473 #endif
09474 #if defined(HAVE_SS7)
09475 case SIG_SS7:
09476 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09477 ast_mutex_unlock(&p->lock);
09478 return res;
09479 #endif
09480 default:
09481 break;
09482 }
09483 #ifdef HAVE_OPENR2
09484 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09485 ast_mutex_unlock(&p->lock);
09486
09487
09488 return 0;
09489 }
09490 #endif
09491 idx = dahdi_get_index(chan, p, 0);
09492 if (idx == SUB_REAL) {
09493 switch (condition) {
09494 case AST_CONTROL_BUSY:
09495 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09496 break;
09497 case AST_CONTROL_RINGING:
09498 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09499
09500 if (chan->_state != AST_STATE_UP) {
09501 if ((chan->_state != AST_STATE_RING) ||
09502 ((p->sig != SIG_FXSKS) &&
09503 (p->sig != SIG_FXSLS) &&
09504 (p->sig != SIG_FXSGS)))
09505 ast_setstate(chan, AST_STATE_RINGING);
09506 }
09507 break;
09508 case AST_CONTROL_INCOMPLETE:
09509 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09510
09511 res = 0;
09512 break;
09513 case AST_CONTROL_PROCEEDING:
09514 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09515
09516 res = 0;
09517 break;
09518 case AST_CONTROL_PROGRESS:
09519 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09520
09521 res = 0;
09522 break;
09523 case AST_CONTROL_CONGESTION:
09524
09525 switch (chan->hangupcause) {
09526 case AST_CAUSE_USER_BUSY:
09527 case AST_CAUSE_NORMAL_CLEARING:
09528 case 0:
09529
09530 chan->hangupcause = AST_CAUSE_CONGESTION;
09531 break;
09532 default:
09533 break;
09534 }
09535 break;
09536 case AST_CONTROL_HOLD:
09537 ast_moh_start(chan, data, p->mohinterpret);
09538 break;
09539 case AST_CONTROL_UNHOLD:
09540 ast_moh_stop(chan);
09541 break;
09542 case AST_CONTROL_RADIO_KEY:
09543 if (p->radio)
09544 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09545 res = 0;
09546 break;
09547 case AST_CONTROL_RADIO_UNKEY:
09548 if (p->radio)
09549 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09550 res = 0;
09551 break;
09552 case AST_CONTROL_FLASH:
09553
09554 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09555
09556 p->dop.dialstr[0] = '\0';
09557 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09558 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09559 chan->name, strerror(errno));
09560 } else
09561 res = 0;
09562 } else
09563 res = 0;
09564 break;
09565 case AST_CONTROL_SRCUPDATE:
09566 res = 0;
09567 break;
09568 case -1:
09569 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09570 break;
09571 }
09572 } else {
09573 res = 0;
09574 }
09575 ast_mutex_unlock(&p->lock);
09576 return res;
09577 }
09578
09579 #if defined(HAVE_PRI)
09580 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09581 #else
09582 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09583 #endif
09584 {
09585 struct ast_str *chan_name;
09586 int x, y;
09587
09588
09589 if (!(chan_name = ast_str_create(32))) {
09590 return NULL;
09591 }
09592 if (i->channel == CHAN_PSEUDO) {
09593 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09594 #if defined(HAVE_PRI)
09595 } else if (i->pri) {
09596 ast_mutex_lock(&i->pri->lock);
09597 y = ++i->pri->new_chan_seq;
09598 if (is_outgoing) {
09599 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09600 address[0] = '\0';
09601 } else if (ast_strlen_zero(i->cid_subaddr)) {
09602
09603 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09604 } else {
09605
09606 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09607 i->cid_subaddr, y);
09608 }
09609 ast_mutex_unlock(&i->pri->lock);
09610 #endif
09611 } else {
09612 y = 1;
09613 do {
09614 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09615 for (x = 0; x < 3; ++x) {
09616 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09617 i->subs[x].owner->name + 6)) {
09618 break;
09619 }
09620 }
09621 ++y;
09622 } while (x < 3);
09623 }
09624 return chan_name;
09625 }
09626
09627 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09628 {
09629 struct ast_channel *tmp;
09630 format_t deflaw;
09631 int x;
09632 int features;
09633 struct ast_str *chan_name;
09634 struct ast_variable *v;
09635 char *dashptr;
09636 char device_name[AST_CHANNEL_NAME];
09637
09638 if (i->subs[idx].owner) {
09639 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09640 return NULL;
09641 }
09642
09643 #if defined(HAVE_PRI)
09644
09645
09646
09647
09648 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09649 #else
09650 chan_name = create_channel_name(i);
09651 #endif
09652 if (!chan_name) {
09653 return NULL;
09654 }
09655
09656 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));
09657 ast_free(chan_name);
09658 if (!tmp)
09659 return NULL;
09660 tmp->tech = &dahdi_tech;
09661 #if defined(HAVE_PRI)
09662 if (i->pri) {
09663 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09664 }
09665 #endif
09666 ast_channel_cc_params_init(tmp, i->cc_params);
09667 if (law) {
09668 i->law = law;
09669 if (law == DAHDI_LAW_ALAW) {
09670 deflaw = AST_FORMAT_ALAW;
09671 } else {
09672 deflaw = AST_FORMAT_ULAW;
09673 }
09674 } else {
09675 switch (i->sig) {
09676 case SIG_PRI_LIB_HANDLE_CASES:
09677
09678 i->law = (i->law_default == DAHDI_LAW_ALAW)
09679 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09680 break;
09681 default:
09682 i->law = i->law_default;
09683 break;
09684 }
09685 if (i->law_default == DAHDI_LAW_ALAW) {
09686 deflaw = AST_FORMAT_ALAW;
09687 } else {
09688 deflaw = AST_FORMAT_ULAW;
09689 }
09690 }
09691 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09692 tmp->nativeformats = deflaw;
09693
09694 tmp->rawreadformat = deflaw;
09695 tmp->readformat = deflaw;
09696 tmp->rawwriteformat = deflaw;
09697 tmp->writeformat = deflaw;
09698 i->subs[idx].linear = 0;
09699 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09700 features = 0;
09701 if (idx == SUB_REAL) {
09702 if (i->busydetect && CANBUSYDETECT(i))
09703 features |= DSP_FEATURE_BUSY_DETECT;
09704 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09705 features |= DSP_FEATURE_CALL_PROGRESS;
09706 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09707 features |= DSP_FEATURE_WAITDIALTONE;
09708 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09709 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09710 features |= DSP_FEATURE_FAX_DETECT;
09711 }
09712 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09713 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09714 i->hardwaredtmf = 0;
09715 features |= DSP_FEATURE_DIGIT_DETECT;
09716 } else if (NEED_MFDETECT(i)) {
09717 i->hardwaredtmf = 1;
09718 features |= DSP_FEATURE_DIGIT_DETECT;
09719 }
09720 }
09721 if (features) {
09722 if (i->dsp) {
09723 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09724 } else {
09725 if (i->channel != CHAN_PSEUDO)
09726 i->dsp = ast_dsp_new();
09727 else
09728 i->dsp = NULL;
09729 if (i->dsp) {
09730 i->dsp_features = features;
09731 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09732
09733 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09734
09735
09736 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09737 features = 0;
09738 }
09739 #endif
09740 ast_dsp_set_features(i->dsp, features);
09741 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09742 if (!ast_strlen_zero(progzone))
09743 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09744 if (i->busydetect && CANBUSYDETECT(i)) {
09745 ast_dsp_set_busy_count(i->dsp, i->busycount);
09746 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09747 }
09748 }
09749 }
09750 }
09751
09752 if (state == AST_STATE_RING)
09753 tmp->rings = 1;
09754 tmp->tech_pvt = i;
09755 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09756
09757 tmp->callgroup = i->callgroup;
09758 tmp->pickupgroup = i->pickupgroup;
09759 }
09760 if (!ast_strlen_zero(i->parkinglot))
09761 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09762 if (!ast_strlen_zero(i->language))
09763 ast_string_field_set(tmp, language, i->language);
09764 if (!i->owner)
09765 i->owner = tmp;
09766 if (!ast_strlen_zero(i->accountcode))
09767 ast_string_field_set(tmp, accountcode, i->accountcode);
09768 if (i->amaflags)
09769 tmp->amaflags = i->amaflags;
09770 i->subs[idx].owner = tmp;
09771 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09772 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09773 ast_string_field_set(tmp, call_forward, i->call_forward);
09774 }
09775
09776 if (!i->adsi)
09777 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09778 if (!ast_strlen_zero(i->exten))
09779 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09780 if (!ast_strlen_zero(i->rdnis)) {
09781 tmp->redirecting.from.number.valid = 1;
09782 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09783 }
09784 if (!ast_strlen_zero(i->dnid)) {
09785 tmp->dialed.number.str = ast_strdup(i->dnid);
09786 }
09787
09788
09789
09790 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09791 if (!ast_strlen_zero(i->cid_ani)) {
09792 tmp->caller.ani.number.valid = 1;
09793 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09794 } else if (!ast_strlen_zero(i->cid_num)) {
09795 tmp->caller.ani.number.valid = 1;
09796 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09797 }
09798 #else
09799 if (!ast_strlen_zero(i->cid_num)) {
09800 tmp->caller.ani.number.valid = 1;
09801 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09802 }
09803 #endif
09804 tmp->caller.id.name.presentation = i->callingpres;
09805 tmp->caller.id.number.presentation = i->callingpres;
09806 tmp->caller.id.number.plan = i->cid_ton;
09807 tmp->caller.ani2 = i->cid_ani2;
09808 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09809
09810 i->fake_event = 0;
09811
09812 dahdi_confmute(i, 0);
09813 i->muting = 0;
09814
09815 ast_jb_configure(tmp, &global_jbconf);
09816
09817
09818 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09819 dashptr = strrchr(device_name, '-');
09820 if (dashptr) {
09821 *dashptr = '\0';
09822 }
09823 tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09824 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09825
09826 for (v = i->vars ; v ; v = v->next)
09827 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09828
09829 ast_module_ref(ast_module_info->self);
09830
09831 dahdi_ami_channel_event(i, tmp);
09832 if (startpbx) {
09833 #ifdef HAVE_OPENR2
09834 if (i->mfcr2call) {
09835 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09836 }
09837 #endif
09838 if (ast_pbx_start(tmp)) {
09839 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09840 ast_hangup(tmp);
09841 return NULL;
09842 }
09843 }
09844 return tmp;
09845 }
09846
09847
09848 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09849 {
09850 char c;
09851
09852 *str = 0;
09853 for (;;)
09854 {
09855
09856 c = ast_waitfordigit(chan, ms);
09857
09858 if (c < 1)
09859 return c;
09860 *str++ = c;
09861 *str = 0;
09862 if (strchr(term, c))
09863 return 1;
09864 }
09865 }
09866
09867 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09868 {
09869 int j;
09870 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09871 for (;;)
09872 {
09873
09874 j = DAHDI_IOMUX_SIGEVENT;
09875
09876 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09877
09878 if (j & DAHDI_IOMUX_SIGEVENT) break;
09879 }
09880
09881 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09882 return 0;
09883 }
09884
09885
09886
09887
09888
09889
09890
09891
09892
09893
09894 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09895 {
09896 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09897 return analog_dnd(dahdichan->sig_pvt, flag);
09898 }
09899
09900 if (flag == -1) {
09901 return dahdichan->dnd;
09902 }
09903
09904
09905 dahdichan->dnd = flag;
09906 ast_verb(3, "%s DND on channel %d\n",
09907 flag? "Enabled" : "Disabled",
09908 dahdichan->channel);
09909 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09910 "Channel: DAHDI/%d\r\n"
09911 "Status: %s\r\n", dahdichan->channel,
09912 flag? "enabled" : "disabled");
09913
09914 return 0;
09915 }
09916
09917 static int canmatch_featurecode(const char *exten)
09918 {
09919 int extlen = strlen(exten);
09920 const char *pickup_ext;
09921 if (!extlen) {
09922 return 1;
09923 }
09924 pickup_ext = ast_pickup_ext();
09925 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09926 return 1;
09927 }
09928
09929 if (exten[0] == '*' && extlen < 3) {
09930 if (extlen == 1) {
09931 return 1;
09932 }
09933
09934 switch (exten[1]) {
09935 case '6':
09936 case '7':
09937 case '8':
09938 return 1;
09939 }
09940 }
09941 return 0;
09942 }
09943
09944 static void *analog_ss_thread(void *data)
09945 {
09946 struct ast_channel *chan = data;
09947 struct dahdi_pvt *p = chan->tech_pvt;
09948 char exten[AST_MAX_EXTENSION] = "";
09949 char exten2[AST_MAX_EXTENSION] = "";
09950 unsigned char buf[256];
09951 char dtmfcid[300];
09952 char dtmfbuf[300];
09953 struct callerid_state *cs = NULL;
09954 char *name = NULL, *number = NULL;
09955 int distMatches;
09956 int curRingData[3];
09957 int receivedRingT;
09958 int counter1;
09959 int counter;
09960 int samples = 0;
09961 struct ast_smdi_md_message *smdi_msg = NULL;
09962 int flags = 0;
09963 int i;
09964 int timeout;
09965 int getforward = 0;
09966 char *s1, *s2;
09967 int len = 0;
09968 int res;
09969 int idx;
09970
09971 ast_mutex_lock(&ss_thread_lock);
09972 ss_thread_count++;
09973 ast_mutex_unlock(&ss_thread_lock);
09974
09975
09976
09977 if (!p) {
09978 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09979 ast_hangup(chan);
09980 goto quit;
09981 }
09982 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09983 idx = dahdi_get_index(chan, p, 1);
09984 if (idx < 0) {
09985 ast_log(LOG_WARNING, "Huh?\n");
09986 ast_hangup(chan);
09987 goto quit;
09988 }
09989 if (p->dsp)
09990 ast_dsp_digitreset(p->dsp);
09991 switch (p->sig) {
09992 case SIG_FEATD:
09993 case SIG_FEATDMF:
09994 case SIG_FEATDMF_TA:
09995 case SIG_E911:
09996 case SIG_FGC_CAMAMF:
09997 case SIG_FEATB:
09998 case SIG_EMWINK:
09999 case SIG_SF_FEATD:
10000 case SIG_SF_FEATDMF:
10001 case SIG_SF_FEATB:
10002 case SIG_SFWINK:
10003 if (dahdi_wink(p, idx))
10004 goto quit;
10005
10006 case SIG_EM:
10007 case SIG_EM_E1:
10008 case SIG_SF:
10009 case SIG_FGC_CAMA:
10010 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10011 if (p->dsp)
10012 ast_dsp_digitreset(p->dsp);
10013
10014 if (p->dsp) {
10015 if (NEED_MFDETECT(p))
10016 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10017 else
10018 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10019 }
10020 memset(dtmfbuf, 0, sizeof(dtmfbuf));
10021
10022 if (!p->immediate)
10023
10024 res = ast_waitfordigit(chan, 5000);
10025 else
10026 res = 0;
10027 if (res > 0) {
10028
10029 dtmfbuf[0] = res;
10030 switch (p->sig) {
10031 case SIG_FEATD:
10032 case SIG_SF_FEATD:
10033 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10034 if (res > 0)
10035 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10036 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10037 break;
10038 case SIG_FEATDMF_TA:
10039 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10040 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10041 if (dahdi_wink(p, idx)) goto quit;
10042 dtmfbuf[0] = 0;
10043
10044 res = ast_waitfordigit(chan, 5000);
10045 if (res <= 0) break;
10046 dtmfbuf[0] = res;
10047
10048 case SIG_FEATDMF:
10049 case SIG_E911:
10050 case SIG_FGC_CAMAMF:
10051 case SIG_SF_FEATDMF:
10052 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10053
10054 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10055 {
10056 if (dahdi_wink(p, idx)) goto quit;
10057 dtmfbuf[0] = 0;
10058
10059 res = ast_waitfordigit(chan, 5000);
10060 if (res <= 0) break;
10061 dtmfbuf[0] = res;
10062 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10063 }
10064 if (res > 0) {
10065
10066 if (p->sig == SIG_E911)
10067 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10068 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10069 }
10070 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10071 break;
10072 case SIG_FEATB:
10073 case SIG_SF_FEATB:
10074 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10075 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10076 break;
10077 case SIG_EMWINK:
10078
10079
10080
10081
10082 if (res == '*') {
10083 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10084 if (res > 0)
10085 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10086 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10087 break;
10088 }
10089 default:
10090
10091 len = 1;
10092 dtmfbuf[len] = '\0';
10093 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10094 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10095 timeout = matchdigittimeout;
10096 } else {
10097 timeout = gendigittimeout;
10098 }
10099 res = ast_waitfordigit(chan, timeout);
10100 if (res < 0) {
10101 ast_debug(1, "waitfordigit returned < 0...\n");
10102 ast_hangup(chan);
10103 goto quit;
10104 } else if (res) {
10105 dtmfbuf[len++] = res;
10106 dtmfbuf[len] = '\0';
10107 } else {
10108 break;
10109 }
10110 }
10111 break;
10112 }
10113 }
10114 if (res == -1) {
10115 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10116 ast_hangup(chan);
10117 goto quit;
10118 } else if (res < 0) {
10119 ast_debug(1, "Got hung up before digits finished\n");
10120 ast_hangup(chan);
10121 goto quit;
10122 }
10123
10124 if (p->sig == SIG_FGC_CAMA) {
10125 char anibuf[100];
10126
10127 if (ast_safe_sleep(chan,1000) == -1) {
10128 ast_hangup(chan);
10129 goto quit;
10130 }
10131 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10132 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10133 res = my_getsigstr(chan, anibuf, "#", 10000);
10134 if ((res > 0) && (strlen(anibuf) > 2)) {
10135 if (anibuf[strlen(anibuf) - 1] == '#')
10136 anibuf[strlen(anibuf) - 1] = 0;
10137 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10138 }
10139 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10140 }
10141
10142 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10143 if (ast_strlen_zero(exten))
10144 ast_copy_string(exten, "s", sizeof(exten));
10145 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10146
10147 if (exten[0] == '*') {
10148 char *stringp=NULL;
10149 ast_copy_string(exten2, exten, sizeof(exten2));
10150
10151 stringp=exten2 +1;
10152 s1 = strsep(&stringp, "*");
10153 s2 = strsep(&stringp, "*");
10154 if (s2) {
10155 if (!ast_strlen_zero(p->cid_num))
10156 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10157 else
10158 ast_set_callerid(chan, s1, NULL, s1);
10159 ast_copy_string(exten, s2, sizeof(exten));
10160 } else
10161 ast_copy_string(exten, s1, sizeof(exten));
10162 } else if (p->sig == SIG_FEATD)
10163 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10164 }
10165 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10166 if (exten[0] == '*') {
10167 char *stringp=NULL;
10168 ast_copy_string(exten2, exten, sizeof(exten2));
10169
10170 stringp=exten2 +1;
10171 s1 = strsep(&stringp, "#");
10172 s2 = strsep(&stringp, "#");
10173 if (s2) {
10174 if (!ast_strlen_zero(p->cid_num))
10175 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10176 else
10177 if (*(s1 + 2))
10178 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10179 ast_copy_string(exten, s2 + 1, sizeof(exten));
10180 } else
10181 ast_copy_string(exten, s1 + 2, sizeof(exten));
10182 } else
10183 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10184 }
10185 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10186 if (exten[0] == '*') {
10187 char *stringp=NULL;
10188 ast_copy_string(exten2, exten, sizeof(exten2));
10189
10190 stringp=exten2 +1;
10191 s1 = strsep(&stringp, "#");
10192 s2 = strsep(&stringp, "#");
10193 if (s2 && (*(s2 + 1) == '0')) {
10194 if (*(s2 + 2))
10195 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10196 }
10197 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10198 else ast_copy_string(exten, "911", sizeof(exten));
10199 } else
10200 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10201 }
10202 if (p->sig == SIG_FEATB) {
10203 if (exten[0] == '*') {
10204 char *stringp=NULL;
10205 ast_copy_string(exten2, exten, sizeof(exten2));
10206
10207 stringp=exten2 +1;
10208 s1 = strsep(&stringp, "#");
10209 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10210 } else
10211 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10212 }
10213 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10214 dahdi_wink(p, idx);
10215
10216
10217
10218 if (ast_safe_sleep(chan, 100)) {
10219 ast_hangup(chan);
10220 goto quit;
10221 }
10222 }
10223 dahdi_enable_ec(p);
10224 if (NEED_MFDETECT(p)) {
10225 if (p->dsp) {
10226 if (!p->hardwaredtmf)
10227 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10228 else {
10229 ast_dsp_free(p->dsp);
10230 p->dsp = NULL;
10231 }
10232 }
10233 }
10234
10235 if (ast_exists_extension(chan, chan->context, exten, 1,
10236 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10237 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10238 if (p->dsp) ast_dsp_digitreset(p->dsp);
10239 res = ast_pbx_run(chan);
10240 if (res) {
10241 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10242 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10243 }
10244 goto quit;
10245 } else {
10246 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10247 sleep(2);
10248 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10249 if (res < 0)
10250 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10251 else
10252 sleep(1);
10253 res = ast_streamfile(chan, "ss-noservice", chan->language);
10254 if (res >= 0)
10255 ast_waitstream(chan, "");
10256 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10257 ast_hangup(chan);
10258 goto quit;
10259 }
10260 break;
10261 case SIG_FXOLS:
10262 case SIG_FXOGS:
10263 case SIG_FXOKS:
10264
10265 timeout = firstdigittimeout;
10266
10267
10268 if (p->subs[SUB_THREEWAY].owner)
10269 timeout = 999999;
10270 while (len < AST_MAX_EXTENSION-1) {
10271
10272
10273 if (p->immediate)
10274 res = 's';
10275 else
10276 res = ast_waitfordigit(chan, timeout);
10277 timeout = 0;
10278 if (res < 0) {
10279 ast_debug(1, "waitfordigit returned < 0...\n");
10280 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10281 ast_hangup(chan);
10282 goto quit;
10283 } else if (res) {
10284 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10285 exten[len++]=res;
10286 exten[len] = '\0';
10287 }
10288 if (!ast_ignore_pattern(chan->context, exten))
10289 tone_zone_play_tone(p->subs[idx].dfd, -1);
10290 else
10291 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10292 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10293 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10294 if (getforward) {
10295
10296 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10297 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10298 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10299 if (res)
10300 break;
10301 usleep(500000);
10302 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10303 sleep(1);
10304 memset(exten, 0, sizeof(exten));
10305 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10306 len = 0;
10307 getforward = 0;
10308 } else {
10309 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10310 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10311 if (!ast_strlen_zero(p->cid_num)) {
10312 if (!p->hidecallerid)
10313 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10314 else
10315 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10316 }
10317 if (!ast_strlen_zero(p->cid_name)) {
10318 if (!p->hidecallerid)
10319 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10320 }
10321 ast_setstate(chan, AST_STATE_RING);
10322 dahdi_enable_ec(p);
10323 res = ast_pbx_run(chan);
10324 if (res) {
10325 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10326 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10327 }
10328 goto quit;
10329 }
10330 } else {
10331
10332
10333 timeout = matchdigittimeout;
10334 }
10335 } else if (res == 0) {
10336 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10337 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10338 dahdi_wait_event(p->subs[idx].dfd);
10339 ast_hangup(chan);
10340 goto quit;
10341 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10342 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10343
10344 p->callwaiting = 0;
10345 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10346 if (res) {
10347 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10348 chan->name, strerror(errno));
10349 }
10350 len = 0;
10351 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10352 memset(exten, 0, sizeof(exten));
10353 timeout = firstdigittimeout;
10354
10355 } else if (!strcmp(exten,ast_pickup_ext())) {
10356
10357
10358
10359
10360 if (idx == SUB_REAL) {
10361
10362 if (p->subs[SUB_THREEWAY].owner) {
10363
10364
10365 alloc_sub(p, SUB_CALLWAIT);
10366 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10367 unalloc_sub(p, SUB_THREEWAY);
10368 }
10369 dahdi_enable_ec(p);
10370 if (ast_pickup_call(chan)) {
10371 ast_debug(1, "No call pickup possible...\n");
10372 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10373 dahdi_wait_event(p->subs[idx].dfd);
10374 }
10375 ast_hangup(chan);
10376 goto quit;
10377 } else {
10378 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10379 ast_hangup(chan);
10380 goto quit;
10381 }
10382
10383 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10384 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10385
10386 p->hidecallerid = 1;
10387 ast_party_number_free(&chan->caller.id.number);
10388 ast_party_number_init(&chan->caller.id.number);
10389 ast_party_name_free(&chan->caller.id.name);
10390 ast_party_name_init(&chan->caller.id.name);
10391 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10392 if (res) {
10393 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10394 chan->name, strerror(errno));
10395 }
10396 len = 0;
10397 memset(exten, 0, sizeof(exten));
10398 timeout = firstdigittimeout;
10399 } else if (p->callreturn && !strcmp(exten, "*69")) {
10400 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10401 break;
10402 } else if (!strcmp(exten, "*78")) {
10403 dahdi_dnd(p, 1);
10404
10405 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10406 getforward = 0;
10407 memset(exten, 0, sizeof(exten));
10408 len = 0;
10409 } else if (!strcmp(exten, "*79")) {
10410 dahdi_dnd(p, 0);
10411
10412 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10413 getforward = 0;
10414 memset(exten, 0, sizeof(exten));
10415 len = 0;
10416 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10417 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10418 getforward = 1;
10419 memset(exten, 0, sizeof(exten));
10420 len = 0;
10421 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10422 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10423 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10424 memset(p->call_forward, 0, sizeof(p->call_forward));
10425 getforward = 0;
10426 memset(exten, 0, sizeof(exten));
10427 len = 0;
10428 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10429 p->subs[SUB_THREEWAY].owner &&
10430 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10431
10432
10433 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10434 chan, exten, chan->context, 0, NULL);
10435 ast_verb(3, "Parking call to '%s'\n", chan->name);
10436 break;
10437 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10438 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10439
10440 p->hidecallerid = 0;
10441 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10442 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10443 if (res) {
10444 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10445 chan->name, strerror(errno));
10446 }
10447 len = 0;
10448 memset(exten, 0, sizeof(exten));
10449 timeout = firstdigittimeout;
10450 } else if (!strcmp(exten, "*0")) {
10451 struct ast_channel *nbridge =
10452 p->subs[SUB_THREEWAY].owner;
10453 struct dahdi_pvt *pbridge = NULL;
10454
10455 if (nbridge && ast_bridged_channel(nbridge))
10456 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10457 if (nbridge && pbridge &&
10458 (nbridge->tech == &dahdi_tech) &&
10459 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10460 ISTRUNK(pbridge)) {
10461 int func = DAHDI_FLASH;
10462
10463 p->dop.dialstr[0] = '\0';
10464
10465 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10466 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10467 nbridge->name, strerror(errno));
10468 }
10469 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10470 unalloc_sub(p, SUB_THREEWAY);
10471 p->owner = p->subs[SUB_REAL].owner;
10472 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10473 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10474 ast_hangup(chan);
10475 goto quit;
10476 } else {
10477 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10478 dahdi_wait_event(p->subs[idx].dfd);
10479 tone_zone_play_tone(p->subs[idx].dfd, -1);
10480 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10481 unalloc_sub(p, SUB_THREEWAY);
10482 p->owner = p->subs[SUB_REAL].owner;
10483 ast_hangup(chan);
10484 goto quit;
10485 }
10486 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10487 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10488 && !canmatch_featurecode(exten)) {
10489 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10490 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10491 chan->context);
10492 break;
10493 }
10494 if (!timeout)
10495 timeout = gendigittimeout;
10496 if (len && !ast_ignore_pattern(chan->context, exten))
10497 tone_zone_play_tone(p->subs[idx].dfd, -1);
10498 }
10499 break;
10500 case SIG_FXSLS:
10501 case SIG_FXSGS:
10502 case SIG_FXSKS:
10503
10504 if (p->use_smdi && p->smdi_iface) {
10505 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10506
10507 if (smdi_msg != NULL) {
10508 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10509
10510 if (smdi_msg->type == 'B')
10511 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10512 else if (smdi_msg->type == 'N')
10513 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10514
10515 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10516 } else {
10517 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10518 }
10519 }
10520
10521 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10522 number = smdi_msg->calling_st;
10523
10524
10525
10526
10527 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10528 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10529
10530 if (p->cid_signalling == CID_SIG_DTMF) {
10531 int k = 0;
10532 int off_ms;
10533 struct timeval start = ast_tvnow();
10534 int ms;
10535 cs = NULL;
10536 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10537 dahdi_setlinear(p->subs[idx].dfd, 0);
10538
10539
10540
10541
10542
10543
10544 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10545 off_ms = 4000;
10546 for (;;) {
10547 struct ast_frame *f;
10548
10549 ms = ast_remaining_ms(start, off_ms);
10550 res = ast_waitfor(chan, ms);
10551 if (res <= 0) {
10552
10553
10554
10555
10556
10557 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10558 "Exiting simple switch\n");
10559 ast_hangup(chan);
10560 goto quit;
10561 }
10562 f = ast_read(chan);
10563 if (!f)
10564 break;
10565 if (f->frametype == AST_FRAME_DTMF) {
10566 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10567 dtmfbuf[k++] = f->subclass.integer;
10568 }
10569 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10570 start = ast_tvnow();
10571 }
10572 ast_frfree(f);
10573 if (chan->_state == AST_STATE_RING ||
10574 chan->_state == AST_STATE_RINGING)
10575 break;
10576 }
10577 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10578 dtmfbuf[k] = '\0';
10579 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10580
10581 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10582 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10583 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10584
10585 if (!ast_strlen_zero(dtmfcid))
10586 number = dtmfcid;
10587 else
10588 number = NULL;
10589
10590 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10591 cs = callerid_new(p->cid_signalling);
10592 if (cs) {
10593 int off_ms;
10594 struct timeval start;
10595 int ms;
10596 samples = 0;
10597 #if 1
10598 bump_gains(p);
10599 #endif
10600
10601 dahdi_setlinear(p->subs[idx].dfd, 0);
10602
10603
10604 for (;;) {
10605 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10606 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10607 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10608 callerid_free(cs);
10609 ast_hangup(chan);
10610 goto quit;
10611 }
10612 if (i & DAHDI_IOMUX_SIGEVENT) {
10613 res = dahdi_get_event(p->subs[idx].dfd);
10614 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10615 if (res == DAHDI_EVENT_NOALARM) {
10616 p->inalarm = 0;
10617 }
10618
10619 if (p->cid_signalling == CID_SIG_V23_JP) {
10620 if (res == DAHDI_EVENT_RINGBEGIN) {
10621 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10622 usleep(1);
10623 }
10624 } else {
10625 res = 0;
10626 break;
10627 }
10628 } else if (i & DAHDI_IOMUX_READ) {
10629 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10630 if (res < 0) {
10631 if (errno != ELAST) {
10632 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10633 callerid_free(cs);
10634 ast_hangup(chan);
10635 goto quit;
10636 }
10637 break;
10638 }
10639 samples += res;
10640
10641 if (p->cid_signalling == CID_SIG_V23_JP) {
10642 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10643 } else {
10644 res = callerid_feed(cs, buf, res, AST_LAW(p));
10645 }
10646 if (res < 0) {
10647
10648
10649
10650
10651 ast_log(LOG_WARNING,
10652 "Failed to decode CallerID on channel '%s'\n",
10653 chan->name);
10654 break;
10655 } else if (res)
10656 break;
10657 else if (samples > (8000 * 10))
10658 break;
10659 }
10660 }
10661 if (res == 1) {
10662 callerid_get(cs, &name, &number, &flags);
10663 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10664 }
10665
10666 if (p->cid_signalling == CID_SIG_V23_JP) {
10667 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10668 usleep(1);
10669 }
10670
10671
10672 start = ast_tvnow();
10673 off_ms = 4000;
10674 for (;;) {
10675 struct ast_frame *f;
10676
10677 ms = ast_remaining_ms(start, off_ms);
10678 res = ast_waitfor(chan, ms);
10679 if (res <= 0) {
10680 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10681 "Exiting simple switch\n");
10682 ast_hangup(chan);
10683 goto quit;
10684 }
10685 if (!(f = ast_read(chan))) {
10686 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10687 ast_hangup(chan);
10688 goto quit;
10689 }
10690 ast_frfree(f);
10691 if (chan->_state == AST_STATE_RING ||
10692 chan->_state == AST_STATE_RINGING)
10693 break;
10694 }
10695
10696
10697
10698 if (p->usedistinctiveringdetection) {
10699 len = 0;
10700 distMatches = 0;
10701
10702 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10703 curRingData[receivedRingT] = 0;
10704 receivedRingT = 0;
10705 counter = 0;
10706 counter1 = 0;
10707
10708 if (strcmp(p->context,p->defcontext) != 0) {
10709 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10710 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10711 }
10712
10713 for (;;) {
10714 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10715 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10716 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10717 callerid_free(cs);
10718 ast_hangup(chan);
10719 goto quit;
10720 }
10721 if (i & DAHDI_IOMUX_SIGEVENT) {
10722 res = dahdi_get_event(p->subs[idx].dfd);
10723 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10724 if (res == DAHDI_EVENT_NOALARM) {
10725 p->inalarm = 0;
10726 }
10727 res = 0;
10728
10729
10730 curRingData[receivedRingT] = p->ringt;
10731
10732 if (p->ringt < p->ringt_base/2)
10733 break;
10734
10735
10736 if (++receivedRingT == ARRAY_LEN(curRingData))
10737 break;
10738 } else if (i & DAHDI_IOMUX_READ) {
10739 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10740 if (res < 0) {
10741 if (errno != ELAST) {
10742 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10743 callerid_free(cs);
10744 ast_hangup(chan);
10745 goto quit;
10746 }
10747 break;
10748 }
10749 if (p->ringt > 0) {
10750 if (!(--p->ringt)) {
10751 res = -1;
10752 break;
10753 }
10754 }
10755 }
10756 }
10757
10758 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10759 for (counter = 0; counter < 3; counter++) {
10760
10761
10762 distMatches = 0;
10763 for (counter1 = 0; counter1 < 3; counter1++) {
10764 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10765 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10766 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10767 curRingData[counter1]);
10768 distMatches++;
10769 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10770 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10771 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10772 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10773 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10774 distMatches++;
10775 }
10776 }
10777
10778 if (distMatches == 3) {
10779
10780 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10781 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10782 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10783 break;
10784 }
10785 }
10786 }
10787
10788 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10789 #if 1
10790 restore_gains(p);
10791 #endif
10792 } else
10793 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10794 } else {
10795 ast_log(LOG_WARNING, "Channel %s in prering "
10796 "state, but I have nothing to do. "
10797 "Terminating simple switch, should be "
10798 "restarted by the actual ring.\n",
10799 chan->name);
10800 ast_hangup(chan);
10801 goto quit;
10802 }
10803 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10804 if (p->cid_signalling == CID_SIG_DTMF) {
10805 int k = 0;
10806 int off_ms;
10807 struct timeval start;
10808 int ms;
10809 cs = NULL;
10810 dahdi_setlinear(p->subs[idx].dfd, 0);
10811 off_ms = 2000;
10812 start = ast_tvnow();
10813 for (;;) {
10814 struct ast_frame *f;
10815
10816 ms = ast_remaining_ms(start, off_ms);
10817 res = ast_waitfor(chan, ms);
10818 if (res <= 0) {
10819 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10820 "Exiting simple switch\n");
10821 ast_hangup(chan);
10822 goto quit;
10823 }
10824 f = ast_read(chan);
10825 if (!f) {
10826
10827 ast_hangup(chan);
10828 goto quit;
10829 }
10830 if (f->frametype == AST_FRAME_DTMF) {
10831 dtmfbuf[k++] = f->subclass.integer;
10832 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10833 start = ast_tvnow();
10834 }
10835 ast_frfree(f);
10836
10837 if (p->ringt_base == p->ringt)
10838 break;
10839 }
10840 dtmfbuf[k] = '\0';
10841 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10842
10843 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10844 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10845 dtmfcid, flags);
10846
10847 if (!ast_strlen_zero(dtmfcid))
10848 number = dtmfcid;
10849 else
10850 number = NULL;
10851
10852 } else {
10853
10854 cs = callerid_new(p->cid_signalling);
10855 if (cs) {
10856 #if 1
10857 bump_gains(p);
10858 #endif
10859 samples = 0;
10860 len = 0;
10861 distMatches = 0;
10862
10863 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10864 curRingData[receivedRingT] = 0;
10865 receivedRingT = 0;
10866 counter = 0;
10867 counter1 = 0;
10868
10869 if (strcmp(p->context,p->defcontext) != 0) {
10870 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10871 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10872 }
10873
10874
10875 dahdi_setlinear(p->subs[idx].dfd, 0);
10876 for (;;) {
10877 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10878 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10879 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10880 callerid_free(cs);
10881 ast_hangup(chan);
10882 goto quit;
10883 }
10884 if (i & DAHDI_IOMUX_SIGEVENT) {
10885 res = dahdi_get_event(p->subs[idx].dfd);
10886 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10887 if (res == DAHDI_EVENT_NOALARM) {
10888 p->inalarm = 0;
10889 }
10890
10891 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10892 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10893 p->polarity = POLARITY_IDLE;
10894 callerid_free(cs);
10895 ast_hangup(chan);
10896 goto quit;
10897 }
10898 res = 0;
10899
10900
10901 curRingData[receivedRingT] = p->ringt;
10902
10903 if (p->ringt < p->ringt_base/2)
10904 break;
10905
10906
10907 if (++receivedRingT == ARRAY_LEN(curRingData))
10908 break;
10909 } else if (i & DAHDI_IOMUX_READ) {
10910 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10911 if (res < 0) {
10912 if (errno != ELAST) {
10913 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10914 callerid_free(cs);
10915 ast_hangup(chan);
10916 goto quit;
10917 }
10918 break;
10919 }
10920 if (p->ringt > 0) {
10921 if (!(--p->ringt)) {
10922 res = -1;
10923 break;
10924 }
10925 }
10926 samples += res;
10927 res = callerid_feed(cs, buf, res, AST_LAW(p));
10928 if (res < 0) {
10929
10930
10931
10932
10933 ast_log(LOG_WARNING,
10934 "Failed to decode CallerID on channel '%s'\n",
10935 chan->name);
10936 break;
10937 } else if (res)
10938 break;
10939 else if (samples > (8000 * 10))
10940 break;
10941 }
10942 }
10943 if (res == 1) {
10944 callerid_get(cs, &name, &number, &flags);
10945 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10946 }
10947 if (distinctiveringaftercid == 1) {
10948
10949 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10950 curRingData[receivedRingT] = 0;
10951 }
10952 receivedRingT = 0;
10953 ast_verb(3, "Detecting post-CID distinctive ring\n");
10954 for (;;) {
10955 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10956 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10957 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10958 callerid_free(cs);
10959 ast_hangup(chan);
10960 goto quit;
10961 }
10962 if (i & DAHDI_IOMUX_SIGEVENT) {
10963 res = dahdi_get_event(p->subs[idx].dfd);
10964 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10965 if (res == DAHDI_EVENT_NOALARM) {
10966 p->inalarm = 0;
10967 }
10968 res = 0;
10969
10970
10971 curRingData[receivedRingT] = p->ringt;
10972
10973 if (p->ringt < p->ringt_base/2)
10974 break;
10975
10976
10977 if (++receivedRingT == ARRAY_LEN(curRingData))
10978 break;
10979 } else if (i & DAHDI_IOMUX_READ) {
10980 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10981 if (res < 0) {
10982 if (errno != ELAST) {
10983 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10984 callerid_free(cs);
10985 ast_hangup(chan);
10986 goto quit;
10987 }
10988 break;
10989 }
10990 if (p->ringt > 0) {
10991 if (!(--p->ringt)) {
10992 res = -1;
10993 break;
10994 }
10995 }
10996 }
10997 }
10998 }
10999 if (p->usedistinctiveringdetection) {
11000
11001 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11002
11003 for (counter = 0; counter < 3; counter++) {
11004
11005
11006
11007 ast_verb(3, "Checking %d,%d,%d\n",
11008 p->drings.ringnum[counter].ring[0],
11009 p->drings.ringnum[counter].ring[1],
11010 p->drings.ringnum[counter].ring[2]);
11011 distMatches = 0;
11012 for (counter1 = 0; counter1 < 3; counter1++) {
11013 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11014 if (p->drings.ringnum[counter].ring[counter1] == -1) {
11015 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11016 curRingData[counter1]);
11017 distMatches++;
11018 }
11019 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11020 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11021 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11022 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11023 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11024 distMatches++;
11025 }
11026 }
11027 if (distMatches == 3) {
11028
11029 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11030 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11031 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11032 break;
11033 }
11034 }
11035 }
11036
11037 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11038 #if 1
11039 restore_gains(p);
11040 #endif
11041 if (res < 0) {
11042 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11043 }
11044 } else
11045 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11046 }
11047 } else
11048 cs = NULL;
11049
11050 if (number)
11051 ast_shrink_phone_number(number);
11052 ast_set_callerid(chan, number, name, number);
11053
11054 if (smdi_msg)
11055 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11056
11057 if (cs)
11058 callerid_free(cs);
11059
11060 my_handle_notify_message(chan, p, flags, -1);
11061
11062 ast_setstate(chan, AST_STATE_RING);
11063 chan->rings = 1;
11064 p->ringt = p->ringt_base;
11065 res = ast_pbx_run(chan);
11066 if (res) {
11067 ast_hangup(chan);
11068 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11069 }
11070 goto quit;
11071 default:
11072 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11073 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11074 if (res < 0)
11075 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11076 }
11077 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11078 if (res < 0)
11079 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11080 ast_hangup(chan);
11081 quit:
11082 ast_mutex_lock(&ss_thread_lock);
11083 ss_thread_count--;
11084 ast_cond_signal(&ss_thread_complete);
11085 ast_mutex_unlock(&ss_thread_lock);
11086 return NULL;
11087 }
11088
11089 struct mwi_thread_data {
11090 struct dahdi_pvt *pvt;
11091 unsigned char buf[READ_SIZE];
11092 size_t len;
11093 };
11094
11095 static int calc_energy(const unsigned char *buf, int len, format_t law)
11096 {
11097 int x;
11098 int sum = 0;
11099
11100 if (!len)
11101 return 0;
11102
11103 for (x = 0; x < len; x++)
11104 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11105
11106 return sum / len;
11107 }
11108
11109 static void *mwi_thread(void *data)
11110 {
11111 struct mwi_thread_data *mtd = data;
11112 struct callerid_state *cs;
11113 pthread_t threadid;
11114 int samples = 0;
11115 char *name, *number;
11116 int flags;
11117 int i, res;
11118 unsigned int spill_done = 0;
11119 int spill_result = -1;
11120
11121 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11122 goto quit_no_clean;
11123 }
11124
11125 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11126
11127 bump_gains(mtd->pvt);
11128
11129 for (;;) {
11130 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11131 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11132 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11133 goto quit;
11134 }
11135
11136 if (i & DAHDI_IOMUX_SIGEVENT) {
11137 struct ast_channel *chan;
11138
11139
11140
11141
11142 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11143
11144 switch (res) {
11145 case DAHDI_EVENT_NEONMWI_ACTIVE:
11146 case DAHDI_EVENT_NEONMWI_INACTIVE:
11147 case DAHDI_EVENT_NONE:
11148 case DAHDI_EVENT_BITSCHANGED:
11149 break;
11150 case DAHDI_EVENT_NOALARM:
11151 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11152 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11153
11154 analog_p->inalarm = 0;
11155 }
11156 mtd->pvt->inalarm = 0;
11157 handle_clear_alarms(mtd->pvt);
11158 break;
11159 case DAHDI_EVENT_ALARM:
11160 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11161 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11162
11163 analog_p->inalarm = 1;
11164 }
11165 mtd->pvt->inalarm = 1;
11166 res = get_alarms(mtd->pvt);
11167 handle_alarms(mtd->pvt, res);
11168 break;
11169 default:
11170 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11171 callerid_free(cs);
11172
11173 restore_gains(mtd->pvt);
11174 mtd->pvt->ringt = mtd->pvt->ringt_base;
11175
11176 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11177 int result;
11178
11179 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11180 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11181 } else {
11182 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11183 }
11184 if (result) {
11185 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11186 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11187 if (res < 0)
11188 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11189 ast_hangup(chan);
11190 }
11191 } else {
11192 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11193 }
11194 goto quit_no_clean;
11195 }
11196 } else if (i & DAHDI_IOMUX_READ) {
11197 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11198 if (errno != ELAST) {
11199 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11200 goto quit;
11201 }
11202 break;
11203 }
11204 samples += res;
11205 if (!spill_done) {
11206 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11207
11208
11209
11210
11211 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11212 break;
11213 } else if (spill_result) {
11214 spill_done = 1;
11215 }
11216 } else {
11217
11218
11219
11220 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11221 break;
11222 }
11223 if (samples > (8000 * 4))
11224 break;
11225 }
11226 }
11227
11228 if (spill_result == 1) {
11229 callerid_get(cs, &name, &number, &flags);
11230 if (flags & CID_MSGWAITING) {
11231 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11232 notify_message(mtd->pvt->mailbox, 1);
11233 } else if (flags & CID_NOMSGWAITING) {
11234 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11235 notify_message(mtd->pvt->mailbox, 0);
11236 } else {
11237 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11238 }
11239 }
11240
11241
11242 quit:
11243 callerid_free(cs);
11244
11245 restore_gains(mtd->pvt);
11246
11247 quit_no_clean:
11248 mtd->pvt->mwimonitoractive = 0;
11249 ast_free(mtd);
11250
11251 return NULL;
11252 }
11253
11254
11255
11256
11257
11258
11259
11260
11261 static int mwi_send_init(struct dahdi_pvt * pvt)
11262 {
11263 int x;
11264
11265 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11266
11267 if (pvt->mwisend_rpas) {
11268 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11269 pvt->mwisendactive = 1;
11270 } else if (pvt->mwisend_fsk) {
11271 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11272 pvt->mwisendactive = 1;
11273 } else {
11274 pvt->mwisendactive = 0;
11275 return 0;
11276 }
11277 #else
11278 if (mwisend_rpas) {
11279 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11280 } else {
11281 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11282 }
11283 pvt->mwisendactive = 1;
11284 #endif
11285
11286 if (pvt->cidspill) {
11287 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11288 ast_free(pvt->cidspill);
11289 pvt->cidspill = NULL;
11290 pvt->cidpos = 0;
11291 pvt->cidlen = 0;
11292 }
11293 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11294 if (!pvt->cidspill) {
11295 pvt->mwisendactive = 0;
11296 return -1;
11297 }
11298 x = DAHDI_FLUSH_BOTH;
11299 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11300 x = 3000;
11301 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11302 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11303 if (pvt->mwisend_fsk) {
11304 #endif
11305 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11306 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11307 pvt->cidpos = 0;
11308 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11309 }
11310 #endif
11311 return 0;
11312 }
11313
11314 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11315 {
11316 struct timeval now;
11317 int res;
11318
11319
11320
11321
11322 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11323 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11324 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11325
11326 switch ( pvt->mwisend_data.mwisend_current) {
11327 case MWI_SEND_SA:
11328
11329 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11330 if (res) {
11331 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11332 goto quit;
11333 }
11334 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11335 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11336 break;
11337 case MWI_SEND_SA_WAIT:
11338 break;
11339 case MWI_SEND_PAUSE:
11340 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11341 if (pvt->mwisend_fsk) {
11342 #endif
11343 gettimeofday(&now, NULL);
11344 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11345 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11346 }
11347 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11348 } else {
11349 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11350 }
11351 #endif
11352 break;
11353 case MWI_SEND_SPILL:
11354
11355 if(0 < num_read) {
11356 if (num_read > pvt->cidlen - pvt->cidpos)
11357 num_read = pvt->cidlen - pvt->cidpos;
11358 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11359 if (res > 0) {
11360 pvt->cidpos += res;
11361 if (pvt->cidpos >= pvt->cidlen) {
11362 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11363 }
11364 } else {
11365 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11366 goto quit;
11367 }
11368 }
11369 break;
11370 case MWI_SEND_CLEANUP:
11371
11372 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11373 break;
11374 default:
11375
11376 goto quit;
11377 }
11378 }
11379
11380 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11381 if (pvt->cidspill) {
11382 ast_free(pvt->cidspill);
11383 pvt->cidspill = NULL;
11384 pvt->cidpos = 0;
11385 pvt->cidlen = 0;
11386 }
11387 pvt->mwisendactive = 0;
11388 }
11389 return 0;
11390 quit:
11391 if (pvt->cidspill) {
11392 ast_free(pvt->cidspill);
11393 pvt->cidspill = NULL;
11394 pvt->cidpos = 0;
11395 pvt->cidlen = 0;
11396 }
11397 pvt->mwisendactive = 0;
11398 return -1;
11399 }
11400
11401 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11402 {
11403 int handled = 0;
11404
11405 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11406 switch (event) {
11407 case DAHDI_EVENT_RINGEROFF:
11408 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11409 handled = 1;
11410
11411 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11412 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11413 ast_free(pvt->cidspill);
11414 pvt->cidspill = NULL;
11415 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11416 pvt->mwisendactive = 0;
11417 } else {
11418 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11419 gettimeofday(&pvt->mwisend_data.pause, NULL);
11420 }
11421 }
11422 break;
11423
11424 case DAHDI_EVENT_RINGOFFHOOK:
11425 if (pvt->cidspill) {
11426 ast_free(pvt->cidspill);
11427 pvt->cidspill = NULL;
11428 pvt->cidpos = 0;
11429 pvt->cidlen = 0;
11430 }
11431 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11432 pvt->mwisendactive = 0;
11433 break;
11434 case DAHDI_EVENT_RINGERON:
11435 case DAHDI_EVENT_HOOKCOMPLETE:
11436 break;
11437 default:
11438 break;
11439 }
11440 }
11441 return handled;
11442 }
11443
11444
11445 static int dahdi_destroy_channel_bynum(int channel)
11446 {
11447 struct dahdi_pvt *cur;
11448
11449 ast_mutex_lock(&iflock);
11450 for (cur = iflist; cur; cur = cur->next) {
11451 if (cur->channel == channel) {
11452 int x = DAHDI_FLASH;
11453
11454
11455 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11456
11457 destroy_channel(cur, 1);
11458 ast_mutex_unlock(&iflock);
11459 ast_module_unref(ast_module_info->self);
11460 return RESULT_SUCCESS;
11461 }
11462 }
11463 ast_mutex_unlock(&iflock);
11464 return RESULT_FAILURE;
11465 }
11466
11467 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11468 {
11469 int res;
11470 pthread_t threadid;
11471 struct ast_channel *chan;
11472
11473
11474
11475 switch (event) {
11476 case DAHDI_EVENT_NONE:
11477 case DAHDI_EVENT_BITSCHANGED:
11478 break;
11479 case DAHDI_EVENT_WINKFLASH:
11480 case DAHDI_EVENT_RINGOFFHOOK:
11481 if (i->inalarm) break;
11482 if (i->radio) break;
11483
11484 switch (i->sig) {
11485 case SIG_FXOLS:
11486 case SIG_FXOGS:
11487 case SIG_FXOKS:
11488 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11489 if (res && (errno == EBUSY))
11490 break;
11491
11492
11493 ast_free(i->cidspill);
11494 i->cidspill = NULL;
11495 restore_conference(i);
11496
11497 if (i->immediate) {
11498 dahdi_enable_ec(i);
11499
11500 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11501 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11502 if (!chan) {
11503 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11504 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11505 if (res < 0)
11506 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11507 }
11508 } else {
11509
11510 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11511 if (chan) {
11512 if (has_voicemail(i))
11513 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11514 else
11515 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11516 if (res < 0)
11517 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11518 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11519 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11520 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11521 if (res < 0)
11522 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11523 ast_hangup(chan);
11524 }
11525 } else
11526 ast_log(LOG_WARNING, "Unable to create channel\n");
11527 }
11528 break;
11529 case SIG_FXSLS:
11530 case SIG_FXSGS:
11531 case SIG_FXSKS:
11532 i->ringt = i->ringt_base;
11533
11534 case SIG_EMWINK:
11535 case SIG_FEATD:
11536 case SIG_FEATDMF:
11537 case SIG_FEATDMF_TA:
11538 case SIG_E911:
11539 case SIG_FGC_CAMA:
11540 case SIG_FGC_CAMAMF:
11541 case SIG_FEATB:
11542 case SIG_EM:
11543 case SIG_EM_E1:
11544 case SIG_SFWINK:
11545 case SIG_SF_FEATD:
11546 case SIG_SF_FEATDMF:
11547 case SIG_SF_FEATB:
11548 case SIG_SF:
11549
11550 if (i->cid_start == CID_START_POLARITY_IN) {
11551 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11552 } else {
11553 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11554 }
11555
11556 if (!chan) {
11557 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11558 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11559 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11560 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11561 if (res < 0) {
11562 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11563 }
11564 ast_hangup(chan);
11565 }
11566 break;
11567 default:
11568 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11569 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11570 if (res < 0)
11571 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11572 return NULL;
11573 }
11574 break;
11575 case DAHDI_EVENT_NOALARM:
11576 switch (i->sig) {
11577 #if defined(HAVE_PRI)
11578 case SIG_PRI_LIB_HANDLE_CASES:
11579 ast_mutex_lock(&i->lock);
11580 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11581 ast_mutex_unlock(&i->lock);
11582 break;
11583 #endif
11584 #if defined(HAVE_SS7)
11585 case SIG_SS7:
11586 sig_ss7_set_alarm(i->sig_pvt, 0);
11587 break;
11588 #endif
11589 default:
11590 i->inalarm = 0;
11591 break;
11592 }
11593 handle_clear_alarms(i);
11594 break;
11595 case DAHDI_EVENT_ALARM:
11596 switch (i->sig) {
11597 #if defined(HAVE_PRI)
11598 case SIG_PRI_LIB_HANDLE_CASES:
11599 ast_mutex_lock(&i->lock);
11600 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11601 ast_mutex_unlock(&i->lock);
11602 break;
11603 #endif
11604 #if defined(HAVE_SS7)
11605 case SIG_SS7:
11606 sig_ss7_set_alarm(i->sig_pvt, 1);
11607 break;
11608 #endif
11609 default:
11610 i->inalarm = 1;
11611 break;
11612 }
11613 res = get_alarms(i);
11614 handle_alarms(i, res);
11615
11616 case DAHDI_EVENT_ONHOOK:
11617 if (i->radio)
11618 break;
11619
11620 switch (i->sig) {
11621 case SIG_FXOLS:
11622 case SIG_FXOGS:
11623 case SIG_FEATD:
11624 case SIG_FEATDMF:
11625 case SIG_FEATDMF_TA:
11626 case SIG_E911:
11627 case SIG_FGC_CAMA:
11628 case SIG_FGC_CAMAMF:
11629 case SIG_FEATB:
11630 case SIG_EM:
11631 case SIG_EM_E1:
11632 case SIG_EMWINK:
11633 case SIG_SF_FEATD:
11634 case SIG_SF_FEATDMF:
11635 case SIG_SF_FEATB:
11636 case SIG_SF:
11637 case SIG_SFWINK:
11638 case SIG_FXSLS:
11639 case SIG_FXSGS:
11640 case SIG_FXSKS:
11641 case SIG_FXOKS:
11642 dahdi_disable_ec(i);
11643
11644 #ifdef ZHONE_HACK
11645 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11646 usleep(1);
11647 #endif
11648 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11649 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11650 break;
11651 case SIG_SS7:
11652 case SIG_PRI_LIB_HANDLE_CASES:
11653 dahdi_disable_ec(i);
11654 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11655 break;
11656 default:
11657 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11658 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11659 return NULL;
11660 }
11661 break;
11662 case DAHDI_EVENT_POLARITY:
11663 switch (i->sig) {
11664 case SIG_FXSLS:
11665 case SIG_FXSKS:
11666 case SIG_FXSGS:
11667
11668
11669
11670
11671 if (i->hanguponpolarityswitch)
11672 i->polarity = POLARITY_REV;
11673 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11674 i->polarity = POLARITY_REV;
11675 ast_verb(2, "Starting post polarity "
11676 "CID detection on channel %d\n",
11677 i->channel);
11678 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11679 if (!chan) {
11680 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11681 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11682 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11683 ast_hangup(chan);
11684 }
11685 }
11686 break;
11687 default:
11688 ast_log(LOG_WARNING, "handle_init_event detected "
11689 "polarity reversal on non-FXO (SIG_FXS) "
11690 "interface %d\n", i->channel);
11691 }
11692 break;
11693 case DAHDI_EVENT_REMOVED:
11694 ast_log(LOG_NOTICE,
11695 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11696 i->channel);
11697 return i;
11698 case DAHDI_EVENT_NEONMWI_ACTIVE:
11699 if (i->mwimonitor_neon) {
11700 notify_message(i->mailbox, 1);
11701 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11702 }
11703 break;
11704 case DAHDI_EVENT_NEONMWI_INACTIVE:
11705 if (i->mwimonitor_neon) {
11706 notify_message(i->mailbox, 0);
11707 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11708 }
11709 break;
11710 }
11711 return NULL;
11712 }
11713
11714 static void monitor_pfds_clean(void *arg) {
11715 struct pollfd **pfds = arg;
11716 ast_free(*pfds);
11717 }
11718
11719 static void *do_monitor(void *data)
11720 {
11721 int count, res, res2, spoint, pollres=0;
11722 struct dahdi_pvt *i;
11723 struct dahdi_pvt *last = NULL;
11724 struct dahdi_pvt *doomed;
11725 time_t thispass = 0, lastpass = 0;
11726 int found;
11727 char buf[1024];
11728 struct pollfd *pfds=NULL;
11729 int lastalloc = -1;
11730
11731
11732
11733 #if 0
11734 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11735 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11736 return NULL;
11737 }
11738 ast_debug(1, "Monitor starting...\n");
11739 #endif
11740 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11741
11742 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11743 for (;;) {
11744
11745 ast_mutex_lock(&iflock);
11746 if (!pfds || (lastalloc != ifcount)) {
11747 if (pfds) {
11748 ast_free(pfds);
11749 pfds = NULL;
11750 }
11751 if (ifcount) {
11752 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11753 ast_mutex_unlock(&iflock);
11754 return NULL;
11755 }
11756 }
11757 lastalloc = ifcount;
11758 }
11759
11760
11761 count = 0;
11762 for (i = iflist; i; i = i->next) {
11763 ast_mutex_lock(&i->lock);
11764 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11765 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11766 struct analog_pvt *p = i->sig_pvt;
11767
11768 if (!p) {
11769 ast_log(LOG_ERROR, "No sig_pvt?\n");
11770 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11771
11772 pfds[count].fd = i->subs[SUB_REAL].dfd;
11773 pfds[count].events = POLLPRI;
11774 pfds[count].revents = 0;
11775
11776 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11777 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11778 pfds[count].events |= POLLIN;
11779 }
11780 count++;
11781 }
11782 } else {
11783 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11784
11785 pfds[count].fd = i->subs[SUB_REAL].dfd;
11786 pfds[count].events = POLLPRI;
11787 pfds[count].revents = 0;
11788
11789
11790 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11791 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11792 pfds[count].events |= POLLIN;
11793 }
11794 count++;
11795 }
11796 }
11797 }
11798 ast_mutex_unlock(&i->lock);
11799 }
11800
11801 ast_mutex_unlock(&iflock);
11802
11803 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11804 pthread_testcancel();
11805
11806 res = poll(pfds, count, 1000);
11807 pthread_testcancel();
11808 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11809
11810
11811 if (res < 0) {
11812 if ((errno != EAGAIN) && (errno != EINTR))
11813 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11814 continue;
11815 }
11816
11817
11818 ast_mutex_lock(&iflock);
11819 found = 0;
11820 spoint = 0;
11821 lastpass = thispass;
11822 thispass = time(NULL);
11823 doomed = NULL;
11824 for (i = iflist;; i = i->next) {
11825 if (doomed) {
11826 int res;
11827 res = dahdi_destroy_channel_bynum(doomed->channel);
11828 if (res != RESULT_SUCCESS) {
11829 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11830 }
11831 doomed = NULL;
11832 }
11833 if (!i) {
11834 break;
11835 }
11836
11837 if (thispass != lastpass) {
11838 if (!found && ((i == last) || ((i == iflist) && !last))) {
11839 last = i;
11840 if (last) {
11841 struct analog_pvt *analog_p = last->sig_pvt;
11842
11843 if (analog_p
11844 && !last->mwisendactive
11845 && (last->sig & __DAHDI_SIG_FXO)
11846 && !analog_p->fxsoffhookstate
11847 && !last->owner
11848 && !ast_strlen_zero(last->mailbox)
11849 && (thispass - analog_p->onhooktime > 3)) {
11850 res = has_voicemail(last);
11851 if (analog_p->msgstate != res) {
11852
11853 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11854 if (res2) {
11855
11856 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11857 }
11858
11859 if (mwi_send_init(last)) {
11860 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11861 }
11862 analog_p->msgstate = res;
11863 found ++;
11864 }
11865 }
11866 last = last->next;
11867 }
11868 }
11869 }
11870 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11871 if (i->radio && !i->owner)
11872 {
11873 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11874 if (res)
11875 {
11876 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11877
11878 ast_mutex_unlock(&iflock);
11879 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11880 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11881 else
11882 doomed = handle_init_event(i, res);
11883 ast_mutex_lock(&iflock);
11884 }
11885 continue;
11886 }
11887 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11888 if (pollres & POLLIN) {
11889 if (i->owner || i->subs[SUB_REAL].owner) {
11890 #ifdef HAVE_PRI
11891 if (!i->pri)
11892 #endif
11893 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11894 continue;
11895 }
11896 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11897 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11898 continue;
11899 }
11900 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11901 if (res > 0) {
11902 if (i->mwimonitor_fsk) {
11903 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11904 pthread_attr_t attr;
11905 pthread_t threadid;
11906 struct mwi_thread_data *mtd;
11907
11908 pthread_attr_init(&attr);
11909 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11910
11911 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11912 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11913 mtd->pvt = i;
11914 memcpy(mtd->buf, buf, res);
11915 mtd->len = res;
11916 i->mwimonitoractive = 1;
11917 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11918 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11919 i->mwimonitoractive = 0;
11920 ast_free(mtd);
11921 }
11922 }
11923 }
11924
11925 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11926 int energy;
11927 struct timeval now;
11928
11929
11930
11931 if (1 == i->dtmfcid_holdoff_state) {
11932 gettimeofday(&i->dtmfcid_delay, NULL);
11933 i->dtmfcid_holdoff_state = 2;
11934 } else if (2 == i->dtmfcid_holdoff_state) {
11935 gettimeofday(&now, NULL);
11936 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11937 i->dtmfcid_holdoff_state = 0;
11938 }
11939 } else {
11940 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11941 if (!i->mwisendactive && energy > dtmfcid_level) {
11942 pthread_t threadid;
11943 struct ast_channel *chan;
11944 ast_mutex_unlock(&iflock);
11945 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11946
11947 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11948 i->dtmfcid_holdoff_state = 1;
11949 } else {
11950 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11951 if (!chan) {
11952 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11953 } else {
11954 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11955 if (res) {
11956 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11957 ast_hangup(chan);
11958 } else {
11959 i->dtmfcid_holdoff_state = 1;
11960 }
11961 }
11962 }
11963 ast_mutex_lock(&iflock);
11964 }
11965 }
11966 }
11967 if (i->mwisendactive) {
11968 mwi_send_process_buffer(i, res);
11969 }
11970 } else {
11971 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11972 }
11973 }
11974 if (pollres & POLLPRI) {
11975 if (i->owner || i->subs[SUB_REAL].owner) {
11976 #ifdef HAVE_PRI
11977 if (!i->pri)
11978 #endif
11979 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11980 continue;
11981 }
11982 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11983 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11984
11985 ast_mutex_unlock(&iflock);
11986 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11987 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11988 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11989 else
11990 doomed = handle_init_event(i, res);
11991 }
11992 ast_mutex_lock(&iflock);
11993 }
11994 }
11995 }
11996 ast_mutex_unlock(&iflock);
11997 }
11998
11999 pthread_cleanup_pop(1);
12000 return NULL;
12001
12002 }
12003
12004 static int restart_monitor(void)
12005 {
12006
12007 if (monitor_thread == AST_PTHREADT_STOP)
12008 return 0;
12009 ast_mutex_lock(&monlock);
12010 if (monitor_thread == pthread_self()) {
12011 ast_mutex_unlock(&monlock);
12012 ast_log(LOG_WARNING, "Cannot kill myself\n");
12013 return -1;
12014 }
12015 if (monitor_thread != AST_PTHREADT_NULL) {
12016
12017 pthread_kill(monitor_thread, SIGURG);
12018 } else {
12019
12020 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12021 ast_mutex_unlock(&monlock);
12022 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12023 return -1;
12024 }
12025 }
12026 ast_mutex_unlock(&monlock);
12027 return 0;
12028 }
12029
12030 #if defined(HAVE_PRI)
12031 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12032 {
12033 int x;
12034 int trunkgroup;
12035
12036 trunkgroup = pris[*span].mastertrunkgroup;
12037 if (trunkgroup) {
12038
12039 for (x = 0; x < NUM_SPANS; x++) {
12040 if (pris[x].pri.trunkgroup == trunkgroup) {
12041 *span = x;
12042 return 0;
12043 }
12044 }
12045 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12046 *span = -1;
12047 } else {
12048 if (pris[*span].pri.trunkgroup) {
12049 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);
12050 *span = -1;
12051 } else if (pris[*span].mastertrunkgroup) {
12052 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12053 *span = -1;
12054 } else {
12055 if (si->totalchans == 31) {
12056
12057 pris[*span].dchannels[0] = 16 + offset;
12058 } else if (si->totalchans == 24) {
12059
12060 pris[*span].dchannels[0] = 24 + offset;
12061 } else if (si->totalchans == 3) {
12062
12063 pris[*span].dchannels[0] = 3 + offset;
12064 } else {
12065 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);
12066 *span = -1;
12067 return 0;
12068 }
12069 pris[*span].pri.span = *span + 1;
12070 }
12071 }
12072 return 0;
12073 }
12074 #endif
12075
12076 #if defined(HAVE_PRI)
12077 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12078 {
12079 struct dahdi_spaninfo si;
12080 struct dahdi_params p;
12081 int fd;
12082 int span;
12083 int ospan=0;
12084 int x,y;
12085 for (x = 0; x < NUM_SPANS; x++) {
12086 if (pris[x].pri.trunkgroup == trunkgroup) {
12087 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12088 return -1;
12089 }
12090 }
12091 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12092 if (!channels[y])
12093 break;
12094 memset(&si, 0, sizeof(si));
12095 memset(&p, 0, sizeof(p));
12096 fd = open("/dev/dahdi/channel", O_RDWR);
12097 if (fd < 0) {
12098 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12099 return -1;
12100 }
12101 x = channels[y];
12102 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12103 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12104 close(fd);
12105 return -1;
12106 }
12107 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12108 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12109 return -1;
12110 }
12111 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12112 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12113 close(fd);
12114 return -1;
12115 }
12116 span = p.spanno - 1;
12117 if (pris[span].pri.trunkgroup) {
12118 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12119 close(fd);
12120 return -1;
12121 }
12122 if (pris[span].pri.pvts[0]) {
12123 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12124 close(fd);
12125 return -1;
12126 }
12127 if (!y) {
12128 pris[span].pri.trunkgroup = trunkgroup;
12129 ospan = span;
12130 }
12131 pris[ospan].dchannels[y] = channels[y];
12132 pris[span].pri.span = span + 1;
12133 close(fd);
12134 }
12135 return 0;
12136 }
12137 #endif
12138
12139 #if defined(HAVE_PRI)
12140 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12141 {
12142 if (pris[span].mastertrunkgroup) {
12143 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);
12144 return -1;
12145 }
12146 pris[span].mastertrunkgroup = trunkgroup;
12147 pris[span].prilogicalspan = logicalspan;
12148 return 0;
12149 }
12150 #endif
12151
12152 #if defined(HAVE_SS7)
12153 static unsigned int parse_pointcode(const char *pcstring)
12154 {
12155 unsigned int code1, code2, code3;
12156 int numvals;
12157
12158 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12159 if (numvals == 1)
12160 return code1;
12161 if (numvals == 3)
12162 return (code1 << 16) | (code2 << 8) | code3;
12163
12164 return 0;
12165 }
12166 #endif
12167
12168 #if defined(HAVE_SS7)
12169 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12170 {
12171 if ((linkset < 0) || (linkset >= NUM_SPANS))
12172 return NULL;
12173 else
12174 return &linksets[linkset - 1];
12175 }
12176 #endif
12177
12178 #ifdef HAVE_OPENR2
12179 static void dahdi_r2_destroy_links(void)
12180 {
12181 int i = 0;
12182 if (!r2links) {
12183 return;
12184 }
12185 for (; i < r2links_count; i++) {
12186 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12187 pthread_cancel(r2links[i]->r2master);
12188 pthread_join(r2links[i]->r2master, NULL);
12189 openr2_context_delete(r2links[i]->protocol_context);
12190 }
12191 ast_free(r2links[i]);
12192 }
12193 ast_free(r2links);
12194 r2links = NULL;
12195 r2links_count = 0;
12196 }
12197
12198
12199 #define R2_LINK_CAPACITY 30
12200 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12201 {
12202 struct dahdi_mfcr2 *new_r2link = NULL;
12203 struct dahdi_mfcr2 **new_r2links = NULL;
12204
12205
12206
12207
12208
12209 if (!r2links_count ||
12210 memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12211 (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12212 new_r2link = ast_calloc(1, sizeof(**r2links));
12213 if (!new_r2link) {
12214 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12215 return NULL;
12216 }
12217 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12218 if (!new_r2links) {
12219 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12220 ast_free(new_r2link);
12221 return NULL;
12222 }
12223 r2links = new_r2links;
12224 new_r2link->r2master = AST_PTHREADT_NULL;
12225 r2links[r2links_count] = new_r2link;
12226 r2links_count++;
12227 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12228 }
12229 return r2links[r2links_count - 1];
12230 }
12231
12232 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12233 {
12234 char tmplogdir[] = "/tmp";
12235 char logdir[OR2_MAX_PATH];
12236 int threshold = 0;
12237 int snres = 0;
12238 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12239 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12240 conf->mfcr2.max_dnis);
12241 if (!r2_link->protocol_context) {
12242 return -1;
12243 }
12244 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12245 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12246 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12247 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12248 #endif
12249 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12250 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12251 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12252 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12253 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12254 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12255 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12256 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12257 }
12258 } else {
12259 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12260 if (snres >= sizeof(logdir)) {
12261 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12262 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12263 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12264 }
12265 } else {
12266 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12267 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12268 }
12269 }
12270 }
12271 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12272 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12273 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12274 }
12275 }
12276
12277 memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12278 return 0;
12279 }
12280 #endif
12281
12282
12283
12284
12285
12286
12287 static int sigtype_to_signalling(int sigtype)
12288 {
12289 return sigtype;
12290 }
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12305 {
12306 struct stat stbuf;
12307 int num;
12308
12309 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12310 if (stat(path, &stbuf) < 0) {
12311 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12312 return -errno;
12313 }
12314 if (!S_ISCHR(stbuf.st_mode)) {
12315 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12316 return -EINVAL;
12317 }
12318 num = minor(stbuf.st_rdev);
12319 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12320 return num;
12321
12322 }
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333
12334
12335
12336
12337
12338 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12339 {
12340
12341 struct dahdi_pvt *tmp;
12342 char fn[80];
12343 struct dahdi_bufferinfo bi;
12344
12345 int res;
12346 #if defined(HAVE_PRI)
12347 int span = 0;
12348 #endif
12349 int here = 0;
12350 int x;
12351 struct analog_pvt *analog_p = NULL;
12352 struct dahdi_params p;
12353 #if defined(HAVE_PRI)
12354 struct dahdi_spaninfo si;
12355 struct sig_pri_chan *pri_chan = NULL;
12356 #endif
12357 #if defined(HAVE_SS7)
12358 struct sig_ss7_chan *ss7_chan = NULL;
12359 #endif
12360
12361
12362 for (tmp = iflist; tmp; tmp = tmp->next) {
12363 if (!tmp->destroy) {
12364 if (tmp->channel == channel) {
12365
12366 here = 1;
12367 break;
12368 }
12369 if (tmp->channel > channel) {
12370
12371 tmp = NULL;
12372 break;
12373 }
12374 }
12375 }
12376
12377 if (!here && reloading != 1) {
12378 tmp = ast_calloc(1, sizeof(*tmp));
12379 if (!tmp) {
12380 return NULL;
12381 }
12382 tmp->cc_params = ast_cc_config_params_init();
12383 if (!tmp->cc_params) {
12384 ast_free(tmp);
12385 return NULL;
12386 }
12387 ast_mutex_init(&tmp->lock);
12388 ifcount++;
12389 for (x = 0; x < 3; x++)
12390 tmp->subs[x].dfd = -1;
12391 tmp->channel = channel;
12392 tmp->priindication_oob = conf->chan.priindication_oob;
12393 }
12394
12395 if (tmp) {
12396 int chan_sig = conf->chan.sig;
12397
12398
12399 if (reloading && tmp->vars) {
12400 ast_variables_destroy(tmp->vars);
12401 tmp->vars = NULL;
12402 }
12403
12404
12405 if (!here) {
12406
12407 if ((channel != CHAN_PSEUDO)) {
12408 int count = 0;
12409
12410 snprintf(fn, sizeof(fn), "%d", channel);
12411
12412 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12413 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12414 usleep(1);
12415 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12416 count++;
12417 }
12418
12419 if (tmp->subs[SUB_REAL].dfd < 0) {
12420 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);
12421 destroy_dahdi_pvt(tmp);
12422 return NULL;
12423 }
12424 memset(&p, 0, sizeof(p));
12425 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12426 if (res < 0) {
12427 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12428 destroy_dahdi_pvt(tmp);
12429 return NULL;
12430 }
12431 if (conf->is_sig_auto)
12432 chan_sig = sigtype_to_signalling(p.sigtype);
12433 if (p.sigtype != (chan_sig & 0x3ffff)) {
12434 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));
12435 destroy_dahdi_pvt(tmp);
12436 return NULL;
12437 }
12438 tmp->law_default = p.curlaw;
12439 tmp->law = p.curlaw;
12440 tmp->span = p.spanno;
12441 #if defined(HAVE_PRI)
12442 span = p.spanno - 1;
12443 #endif
12444 } else {
12445 chan_sig = 0;
12446 }
12447 tmp->sig = chan_sig;
12448 tmp->outsigmod = conf->chan.outsigmod;
12449
12450 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12451 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12452 if (!analog_p) {
12453 destroy_dahdi_pvt(tmp);
12454 return NULL;
12455 }
12456 tmp->sig_pvt = analog_p;
12457 }
12458 #if defined(HAVE_SS7)
12459 if (chan_sig == SIG_SS7) {
12460 struct dahdi_ss7 *ss7;
12461 int clear = 0;
12462
12463 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12464 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12465 destroy_dahdi_pvt(tmp);
12466 return NULL;
12467 }
12468
12469 ss7 = ss7_resolve_linkset(cur_linkset);
12470 if (!ss7) {
12471 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12472 destroy_dahdi_pvt(tmp);
12473 return NULL;
12474 }
12475 ss7->ss7.span = cur_linkset;
12476 if (cur_cicbeginswith < 0) {
12477 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12478 destroy_dahdi_pvt(tmp);
12479 return NULL;
12480 }
12481 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12482 if (!ss7_chan) {
12483 destroy_dahdi_pvt(tmp);
12484 return NULL;
12485 }
12486 tmp->sig_pvt = ss7_chan;
12487 tmp->ss7 = &ss7->ss7;
12488
12489 ss7_chan->channel = tmp->channel;
12490 ss7_chan->cic = cur_cicbeginswith++;
12491
12492
12493 ss7_chan->dpc = cur_defaultdpc;
12494
12495 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12496
12497 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12498 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12499 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12500 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12501
12502 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12503 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12504 }
12505 #endif
12506 #ifdef HAVE_OPENR2
12507 if (chan_sig == SIG_MFCR2) {
12508 struct dahdi_mfcr2 *r2_link;
12509 r2_link = dahdi_r2_get_link(conf);
12510 if (!r2_link) {
12511 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12512 destroy_dahdi_pvt(tmp);
12513 return NULL;
12514 }
12515 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12516 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12517 destroy_dahdi_pvt(tmp);
12518 return NULL;
12519 }
12520 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12521 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12522 destroy_dahdi_pvt(tmp);
12523 return NULL;
12524 }
12525 r2_link->pvts[r2_link->numchans++] = tmp;
12526 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12527 tmp->subs[SUB_REAL].dfd,
12528 NULL, NULL);
12529 if (!tmp->r2chan) {
12530 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12531 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12532 destroy_dahdi_pvt(tmp);
12533 return NULL;
12534 }
12535 tmp->mfcr2 = r2_link;
12536 if (conf->mfcr2.call_files) {
12537 openr2_chan_enable_call_files(tmp->r2chan);
12538 }
12539 openr2_chan_set_client_data(tmp->r2chan, tmp);
12540
12541 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12542 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12543 tmp->mfcr2_category = conf->mfcr2.category;
12544 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12545 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12546 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12547 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12548 tmp->mfcr2call = 0;
12549 tmp->mfcr2_dnis_index = 0;
12550 tmp->mfcr2_ani_index = 0;
12551 }
12552 #endif
12553 #ifdef HAVE_PRI
12554 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12555 int offset;
12556 int matchesdchan;
12557 int x,y;
12558 int myswitchtype = 0;
12559
12560 offset = 0;
12561 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12562 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12563 destroy_dahdi_pvt(tmp);
12564 return NULL;
12565 }
12566 if (span >= NUM_SPANS) {
12567 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12568 destroy_dahdi_pvt(tmp);
12569 return NULL;
12570 } else {
12571 si.spanno = 0;
12572 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12573 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12574 destroy_dahdi_pvt(tmp);
12575 return NULL;
12576 }
12577
12578 tmp->logicalspan = pris[span].prilogicalspan;
12579 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12580 if (span < 0) {
12581 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12582 destroy_dahdi_pvt(tmp);
12583 return NULL;
12584 }
12585 myswitchtype = conf->pri.pri.switchtype;
12586
12587 matchesdchan=0;
12588 for (x = 0; x < NUM_SPANS; x++) {
12589 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12590 if (pris[x].dchannels[y] == tmp->channel) {
12591 matchesdchan = 1;
12592 break;
12593 }
12594 }
12595 }
12596 if (!matchesdchan) {
12597 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12598 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12599 destroy_dahdi_pvt(tmp);
12600 return NULL;
12601 }
12602 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12603 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12604 destroy_dahdi_pvt(tmp);
12605 return NULL;
12606 }
12607 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12608 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));
12609 destroy_dahdi_pvt(tmp);
12610 return NULL;
12611 }
12612 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12613 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12614 destroy_dahdi_pvt(tmp);
12615 return NULL;
12616 }
12617 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12618 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12619 destroy_dahdi_pvt(tmp);
12620 return NULL;
12621 }
12622 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12623 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12624 destroy_dahdi_pvt(tmp);
12625 return NULL;
12626 }
12627 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12628 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12629 destroy_dahdi_pvt(tmp);
12630 return NULL;
12631 }
12632 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12633 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12634 pris[span].pri.trunkgroup);
12635 destroy_dahdi_pvt(tmp);
12636 return NULL;
12637 }
12638
12639 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12640 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12641 if (!pri_chan) {
12642 destroy_dahdi_pvt(tmp);
12643 return NULL;
12644 }
12645 tmp->sig_pvt = pri_chan;
12646 tmp->pri = &pris[span].pri;
12647
12648 tmp->priexclusive = conf->chan.priexclusive;
12649
12650 if (!tmp->pri->cc_params) {
12651 tmp->pri->cc_params = ast_cc_config_params_init();
12652 if (!tmp->pri->cc_params) {
12653 destroy_dahdi_pvt(tmp);
12654 return NULL;
12655 }
12656 }
12657 ast_cc_copy_config_params(tmp->pri->cc_params,
12658 conf->chan.cc_params);
12659
12660 pris[span].pri.sig = chan_sig;
12661 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12662 pris[span].pri.switchtype = myswitchtype;
12663 pris[span].pri.nsf = conf->pri.pri.nsf;
12664 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12665 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12666 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12667 pris[span].pri.minunused = conf->pri.pri.minunused;
12668 pris[span].pri.minidle = conf->pri.pri.minidle;
12669 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12670 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12671 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12672 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12673 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12674 #endif
12675 #ifdef HAVE_PRI_INBANDDISCONNECT
12676 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12677 #endif
12678 #if defined(HAVE_PRI_CALL_HOLD)
12679 pris[span].pri.hold_disconnect_transfer =
12680 conf->pri.pri.hold_disconnect_transfer;
12681 #endif
12682 #if defined(HAVE_PRI_CCSS)
12683 pris[span].pri.cc_ptmp_recall_mode =
12684 conf->pri.pri.cc_ptmp_recall_mode;
12685 pris[span].pri.cc_qsig_signaling_link_req =
12686 conf->pri.pri.cc_qsig_signaling_link_req;
12687 pris[span].pri.cc_qsig_signaling_link_rsp =
12688 conf->pri.pri.cc_qsig_signaling_link_rsp;
12689 #endif
12690 #if defined(HAVE_PRI_CALL_WAITING)
12691 pris[span].pri.max_call_waiting_calls =
12692 conf->pri.pri.max_call_waiting_calls;
12693 pris[span].pri.allow_call_waiting_calls =
12694 conf->pri.pri.allow_call_waiting_calls;
12695 #endif
12696 pris[span].pri.transfer = conf->chan.transfer;
12697 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12698 #if defined(HAVE_PRI_L2_PERSISTENCE)
12699 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12700 #endif
12701 #if defined(HAVE_PRI_AOC_EVENTS)
12702 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12703 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12704 #endif
12705 if (chan_sig == SIG_BRI_PTMP) {
12706 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12707 } else {
12708
12709 pris[span].pri.layer1_ignored = 0;
12710 }
12711 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12712 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12713 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12714 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12715 #if defined(HAVE_PRI_MWI)
12716 ast_copy_string(pris[span].pri.mwi_mailboxes,
12717 conf->pri.pri.mwi_mailboxes,
12718 sizeof(pris[span].pri.mwi_mailboxes));
12719 #endif
12720 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12721 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12722 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12723 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12724 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12725 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12726 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12727 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12728
12729 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12730 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12731 }
12732
12733 #if defined(HAVE_PRI_CALL_WAITING)
12734
12735 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12736 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12737 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12738 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12739 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12740 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12741 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12742 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12743 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12744 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12745 #endif
12746 } else {
12747 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12748 destroy_dahdi_pvt(tmp);
12749 return NULL;
12750 }
12751 }
12752 }
12753 #endif
12754 } else {
12755
12756 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));
12757 chan_sig = tmp->sig;
12758 if (tmp->subs[SUB_REAL].dfd > -1) {
12759 memset(&p, 0, sizeof(p));
12760 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12761 }
12762 }
12763
12764 switch (chan_sig) {
12765 case SIG_FXSKS:
12766 case SIG_FXSLS:
12767 case SIG_EM:
12768 case SIG_EM_E1:
12769 case SIG_EMWINK:
12770 case SIG_FEATD:
12771 case SIG_FEATDMF:
12772 case SIG_FEATDMF_TA:
12773 case SIG_FEATB:
12774 case SIG_E911:
12775 case SIG_SF:
12776 case SIG_SFWINK:
12777 case SIG_FGC_CAMA:
12778 case SIG_FGC_CAMAMF:
12779 case SIG_SF_FEATD:
12780 case SIG_SF_FEATDMF:
12781 case SIG_SF_FEATB:
12782 p.starttime = 250;
12783 break;
12784 }
12785
12786 if (tmp->radio) {
12787
12788 p.channo = channel;
12789 p.rxwinktime = 1;
12790 p.rxflashtime = 1;
12791 p.starttime = 1;
12792 p.debouncetime = 5;
12793 } else {
12794 p.channo = channel;
12795
12796 if (conf->timing.prewinktime >= 0)
12797 p.prewinktime = conf->timing.prewinktime;
12798 if (conf->timing.preflashtime >= 0)
12799 p.preflashtime = conf->timing.preflashtime;
12800 if (conf->timing.winktime >= 0)
12801 p.winktime = conf->timing.winktime;
12802 if (conf->timing.flashtime >= 0)
12803 p.flashtime = conf->timing.flashtime;
12804 if (conf->timing.starttime >= 0)
12805 p.starttime = conf->timing.starttime;
12806 if (conf->timing.rxwinktime >= 0)
12807 p.rxwinktime = conf->timing.rxwinktime;
12808 if (conf->timing.rxflashtime >= 0)
12809 p.rxflashtime = conf->timing.rxflashtime;
12810 if (conf->timing.debouncetime >= 0)
12811 p.debouncetime = conf->timing.debouncetime;
12812 }
12813
12814
12815 if (tmp->subs[SUB_REAL].dfd >= 0)
12816 {
12817 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12818 if (res < 0) {
12819 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12820 destroy_dahdi_pvt(tmp);
12821 return NULL;
12822 }
12823 }
12824 #if 1
12825 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12826 memset(&bi, 0, sizeof(bi));
12827 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12828 if (!res) {
12829 bi.txbufpolicy = conf->chan.buf_policy;
12830 bi.rxbufpolicy = conf->chan.buf_policy;
12831 bi.numbufs = conf->chan.buf_no;
12832 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12833 if (res < 0) {
12834 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12835 }
12836 } else {
12837 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12838 }
12839 tmp->buf_policy = conf->chan.buf_policy;
12840 tmp->buf_no = conf->chan.buf_no;
12841 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12842 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12843 tmp->faxbuf_no = conf->chan.faxbuf_no;
12844
12845
12846
12847
12848 tmp->bufsize = bi.bufsize;
12849 }
12850 #endif
12851 tmp->immediate = conf->chan.immediate;
12852 tmp->transfertobusy = conf->chan.transfertobusy;
12853 if (chan_sig & __DAHDI_SIG_FXS) {
12854 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12855 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12856 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12857 }
12858 tmp->ringt_base = ringt_base;
12859 tmp->firstradio = 0;
12860 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12861 tmp->permcallwaiting = conf->chan.callwaiting;
12862 else
12863 tmp->permcallwaiting = 0;
12864
12865 tmp->destroy = 0;
12866 tmp->drings = conf->chan.drings;
12867
12868
12869 if (tmp->drings.ringnum[0].range == 0)
12870 tmp->drings.ringnum[0].range = 10;
12871 if (tmp->drings.ringnum[1].range == 0)
12872 tmp->drings.ringnum[1].range = 10;
12873 if (tmp->drings.ringnum[2].range == 0)
12874 tmp->drings.ringnum[2].range = 10;
12875
12876 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12877 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12878 tmp->threewaycalling = conf->chan.threewaycalling;
12879 tmp->adsi = conf->chan.adsi;
12880 tmp->use_smdi = conf->chan.use_smdi;
12881 tmp->permhidecallerid = conf->chan.hidecallerid;
12882 tmp->hidecalleridname = conf->chan.hidecalleridname;
12883 tmp->callreturn = conf->chan.callreturn;
12884 tmp->echocancel = conf->chan.echocancel;
12885 tmp->echotraining = conf->chan.echotraining;
12886 tmp->pulse = conf->chan.pulse;
12887 if (tmp->echocancel.head.tap_length) {
12888 tmp->echocanbridged = conf->chan.echocanbridged;
12889 } else {
12890 if (conf->chan.echocanbridged)
12891 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12892 tmp->echocanbridged = 0;
12893 }
12894 tmp->busydetect = conf->chan.busydetect;
12895 tmp->busycount = conf->chan.busycount;
12896 tmp->busy_tonelength = conf->chan.busy_tonelength;
12897 tmp->busy_quietlength = conf->chan.busy_quietlength;
12898 tmp->callprogress = conf->chan.callprogress;
12899 tmp->waitfordialtone = conf->chan.waitfordialtone;
12900 tmp->cancallforward = conf->chan.cancallforward;
12901 tmp->dtmfrelax = conf->chan.dtmfrelax;
12902 tmp->callwaiting = tmp->permcallwaiting;
12903 tmp->hidecallerid = tmp->permhidecallerid;
12904 tmp->channel = channel;
12905 tmp->stripmsd = conf->chan.stripmsd;
12906 tmp->use_callerid = conf->chan.use_callerid;
12907 tmp->cid_signalling = conf->chan.cid_signalling;
12908 tmp->cid_start = conf->chan.cid_start;
12909 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12910 tmp->restrictcid = conf->chan.restrictcid;
12911 tmp->use_callingpres = conf->chan.use_callingpres;
12912 if (tmp->usedistinctiveringdetection) {
12913 if (!tmp->use_callerid) {
12914 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12915 tmp->use_callerid = 1;
12916 }
12917 }
12918
12919 if (tmp->cid_signalling == CID_SIG_SMDI) {
12920 if (!tmp->use_smdi) {
12921 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12922 tmp->use_smdi = 1;
12923 }
12924 }
12925 if (tmp->use_smdi) {
12926 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12927 if (!(tmp->smdi_iface)) {
12928 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12929 tmp->use_smdi = 0;
12930 }
12931 }
12932
12933 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12934 tmp->amaflags = conf->chan.amaflags;
12935 if (!here) {
12936 tmp->confno = -1;
12937 tmp->propconfno = -1;
12938 }
12939 tmp->canpark = conf->chan.canpark;
12940 tmp->transfer = conf->chan.transfer;
12941 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12942 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12943 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12944 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12945 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12946 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12947 tmp->cid_ton = 0;
12948 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12949 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12950 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12951 } else {
12952 tmp->cid_num[0] = '\0';
12953 tmp->cid_name[0] = '\0';
12954 }
12955 #if defined(HAVE_PRI)
12956 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12957 tmp->cid_tag[0] = '\0';
12958 } else
12959 #endif
12960 {
12961 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12962 }
12963 tmp->cid_subaddr[0] = '\0';
12964 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12965 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12966 char *mailbox, *context;
12967 mailbox = context = ast_strdupa(tmp->mailbox);
12968 strsep(&context, "@");
12969 if (ast_strlen_zero(context))
12970 context = "default";
12971 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12972 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12973 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12974 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12975 AST_EVENT_IE_END);
12976 }
12977 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12978 tmp->mwisend_setting = conf->chan.mwisend_setting;
12979 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12980 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12981 #endif
12982
12983 tmp->group = conf->chan.group;
12984 tmp->callgroup = conf->chan.callgroup;
12985 tmp->pickupgroup= conf->chan.pickupgroup;
12986 if (conf->chan.vars) {
12987 struct ast_variable *v, *tmpvar;
12988 for (v = conf->chan.vars ; v ; v = v->next) {
12989 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12990 tmpvar->next = tmp->vars;
12991 tmp->vars = tmpvar;
12992 }
12993 }
12994 }
12995 tmp->cid_rxgain = conf->chan.cid_rxgain;
12996 tmp->rxgain = conf->chan.rxgain;
12997 tmp->txgain = conf->chan.txgain;
12998 tmp->txdrc = conf->chan.txdrc;
12999 tmp->rxdrc = conf->chan.rxdrc;
13000 tmp->tonezone = conf->chan.tonezone;
13001 if (tmp->subs[SUB_REAL].dfd > -1) {
13002 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13003 if (tmp->dsp)
13004 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13005 update_conf(tmp);
13006 if (!here) {
13007 switch (chan_sig) {
13008 case SIG_PRI_LIB_HANDLE_CASES:
13009 case SIG_SS7:
13010 case SIG_MFCR2:
13011 break;
13012 default:
13013
13014 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13015 break;
13016 }
13017 }
13018 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13019 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13020
13021 switch (tmp->sig) {
13022 #ifdef HAVE_PRI
13023 case SIG_PRI_LIB_HANDLE_CASES:
13024 sig_pri_set_alarm(tmp->sig_pvt, 1);
13025 break;
13026 #endif
13027 #if defined(HAVE_SS7)
13028 case SIG_SS7:
13029 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13030 break;
13031 #endif
13032 default:
13033
13034 analog_p = tmp->sig_pvt;
13035 if (analog_p) {
13036 analog_p->inalarm = 1;
13037 }
13038 tmp->inalarm = 1;
13039 break;
13040 }
13041 handle_alarms(tmp, res);
13042 }
13043 }
13044
13045 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13046 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13047 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13048 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13049 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13050
13051 if (!here) {
13052 tmp->locallyblocked = 0;
13053 tmp->remotelyblocked = 0;
13054 switch (tmp->sig) {
13055 #if defined(HAVE_PRI)
13056 case SIG_PRI_LIB_HANDLE_CASES:
13057 tmp->inservice = 1;
13058 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13059 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13060 if (chan_sig == SIG_PRI) {
13061 char db_chan_name[20];
13062 char db_answer[5];
13063
13064
13065
13066
13067
13068 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13069 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13070 unsigned *why;
13071
13072 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13073 if (tmp->pri->enable_service_message_support) {
13074 char state;
13075
13076 sscanf(db_answer, "%1c:%30u", &state, why);
13077
13078
13079 *why &= (SRVST_NEAREND | SRVST_FAREND);
13080 }
13081 if (!*why) {
13082 ast_db_del(db_chan_name, SRVST_DBKEY);
13083 }
13084 }
13085 }
13086 #endif
13087 break;
13088 #endif
13089 #if defined(HAVE_SS7)
13090 case SIG_SS7:
13091 tmp->inservice = 0;
13092 break;
13093 #endif
13094 default:
13095
13096 tmp->inservice = 1;
13097 break;
13098 }
13099 }
13100
13101 switch (tmp->sig) {
13102 #if defined(HAVE_PRI)
13103 case SIG_PRI_LIB_HANDLE_CASES:
13104 if (pri_chan) {
13105 pri_chan->channel = tmp->channel;
13106 pri_chan->hidecallerid = tmp->hidecallerid;
13107 pri_chan->hidecalleridname = tmp->hidecalleridname;
13108 pri_chan->immediate = tmp->immediate;
13109 pri_chan->inalarm = tmp->inalarm;
13110 pri_chan->priexclusive = tmp->priexclusive;
13111 pri_chan->priindication_oob = tmp->priindication_oob;
13112 pri_chan->use_callerid = tmp->use_callerid;
13113 pri_chan->use_callingpres = tmp->use_callingpres;
13114 ast_copy_string(pri_chan->context, tmp->context,
13115 sizeof(pri_chan->context));
13116 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13117 sizeof(pri_chan->mohinterpret));
13118 pri_chan->stripmsd = tmp->stripmsd;
13119 }
13120 break;
13121 #endif
13122 #if defined(HAVE_SS7)
13123 case SIG_SS7:
13124 if (ss7_chan) {
13125 ss7_chan->inalarm = tmp->inalarm;
13126
13127 ss7_chan->stripmsd = tmp->stripmsd;
13128 ss7_chan->hidecallerid = tmp->hidecallerid;
13129 ss7_chan->use_callerid = tmp->use_callerid;
13130 ss7_chan->use_callingpres = tmp->use_callingpres;
13131 ss7_chan->immediate = tmp->immediate;
13132 ss7_chan->locallyblocked = tmp->locallyblocked;
13133 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13134 ast_copy_string(ss7_chan->context, tmp->context,
13135 sizeof(ss7_chan->context));
13136 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13137 sizeof(ss7_chan->mohinterpret));
13138 }
13139 break;
13140 #endif
13141 default:
13142
13143 analog_p = tmp->sig_pvt;
13144 if (analog_p) {
13145 analog_p->channel = tmp->channel;
13146 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13147 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13148 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13149 analog_p->permcallwaiting = conf->chan.callwaiting;
13150 analog_p->callreturn = conf->chan.callreturn;
13151 analog_p->cancallforward = conf->chan.cancallforward;
13152 analog_p->canpark = conf->chan.canpark;
13153 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13154 analog_p->immediate = conf->chan.immediate;
13155 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13156 analog_p->pulse = conf->chan.pulse;
13157 analog_p->threewaycalling = conf->chan.threewaycalling;
13158 analog_p->transfer = conf->chan.transfer;
13159 analog_p->transfertobusy = conf->chan.transfertobusy;
13160 analog_p->use_callerid = tmp->use_callerid;
13161 analog_p->use_smdi = tmp->use_smdi;
13162 analog_p->smdi_iface = tmp->smdi_iface;
13163 analog_p->outsigmod = ANALOG_SIG_NONE;
13164 analog_p->echotraining = conf->chan.echotraining;
13165 analog_p->cid_signalling = conf->chan.cid_signalling;
13166 analog_p->stripmsd = conf->chan.stripmsd;
13167 switch (conf->chan.cid_start) {
13168 case CID_START_POLARITY:
13169 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13170 break;
13171 case CID_START_POLARITY_IN:
13172 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13173 break;
13174 case CID_START_DTMF_NOALERT:
13175 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13176 break;
13177 default:
13178 analog_p->cid_start = ANALOG_CID_START_RING;
13179 break;
13180 }
13181 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13182 analog_p->ringt = conf->chan.ringt;
13183 analog_p->ringt_base = ringt_base;
13184 analog_p->onhooktime = time(NULL);
13185 if (chan_sig & __DAHDI_SIG_FXO) {
13186 memset(&p, 0, sizeof(p));
13187 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13188 if (!res) {
13189 analog_p->fxsoffhookstate = p.rxisoffhook;
13190 }
13191 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13192 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13193 #endif
13194 }
13195 analog_p->msgstate = -1;
13196
13197 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13198 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13199 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13200
13201 analog_config_complete(analog_p);
13202 }
13203 break;
13204 }
13205 #if defined(HAVE_PRI)
13206 if (tmp->channel == CHAN_PSEUDO) {
13207
13208
13209
13210
13211 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13212 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13213 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13214 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13215 }
13216 #endif
13217 }
13218 if (tmp && !here) {
13219
13220 dahdi_iflist_insert(tmp);
13221 }
13222 return tmp;
13223 }
13224
13225 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13226 {
13227 #if defined(HAVE_PRI)
13228 if (0 < span) {
13229
13230 if (!p->pri || p->pri->span != span) {
13231 return 0;
13232 }
13233 if (!groupmatch && channelmatch == -1) {
13234
13235 *groupmatched = 1;
13236 return 1;
13237 }
13238 }
13239 #endif
13240
13241 if (groupmatch) {
13242 if ((p->group & groupmatch) != groupmatch)
13243
13244 return 0;
13245 *groupmatched = 1;
13246 }
13247
13248 if (channelmatch != -1) {
13249 if (p->channel != channelmatch)
13250
13251 return 0;
13252 *channelmatched = 1;
13253 }
13254
13255 return 1;
13256 }
13257
13258 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13259 {
13260 struct dahdi_pvt *p = *pvt;
13261
13262 if (p->inalarm)
13263 return 0;
13264
13265 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13266 return analog_available(p->sig_pvt);
13267
13268 switch (p->sig) {
13269 #if defined(HAVE_PRI)
13270 case SIG_PRI_LIB_HANDLE_CASES:
13271 {
13272 struct sig_pri_chan *pvt_chan;
13273 int res;
13274
13275 pvt_chan = p->sig_pvt;
13276 res = sig_pri_available(&pvt_chan, is_specific_channel);
13277 *pvt = pvt_chan->chan_pvt;
13278 return res;
13279 }
13280 #endif
13281 #if defined(HAVE_SS7)
13282 case SIG_SS7:
13283 return sig_ss7_available(p->sig_pvt);
13284 #endif
13285 default:
13286 break;
13287 }
13288
13289 if (p->locallyblocked || p->remotelyblocked) {
13290 return 0;
13291 }
13292
13293
13294 if (!p->owner) {
13295 #ifdef HAVE_OPENR2
13296
13297 if (p->mfcr2) {
13298 if (p->mfcr2call) {
13299 return 0;
13300 } else {
13301 return 1;
13302 }
13303 }
13304 #endif
13305 return 1;
13306 }
13307
13308 return 0;
13309 }
13310
13311 #if defined(HAVE_PRI)
13312 #if defined(HAVE_PRI_CALL_WAITING)
13313
13314
13315
13316
13317
13318
13319
13320
13321
13322
13323
13324
13325 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13326 {
13327 struct dahdi_pvt *pvt = priv;
13328
13329 pvt->stripmsd = pri->ch_cfg.stripmsd;
13330 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13331 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13332 pvt->immediate = pri->ch_cfg.immediate;
13333 pvt->priexclusive = pri->ch_cfg.priexclusive;
13334 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13335 pvt->use_callerid = pri->ch_cfg.use_callerid;
13336 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13337 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13338 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13339 }
13340 #endif
13341 #endif
13342
13343 #if defined(HAVE_PRI)
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353
13354
13355
13356 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13357 {
13358 int pvt_idx;
13359 int res;
13360 unsigned idx;
13361 struct dahdi_pvt *pvt;
13362 struct sig_pri_chan *chan;
13363 struct dahdi_bufferinfo bi;
13364
13365 static int nobch_channel = CHAN_PSEUDO;
13366
13367
13368 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13369 if (!pri->pvts[pvt_idx]) {
13370 break;
13371 }
13372 }
13373 if (pri->numchans == pvt_idx) {
13374 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13375 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13376 return -1;
13377 }
13378
13379
13380 pri->pvts[pvt_idx] = NULL;
13381 ++pri->numchans;
13382 }
13383
13384 pvt = ast_calloc(1, sizeof(*pvt));
13385 if (!pvt) {
13386 return -1;
13387 }
13388 pvt->cc_params = ast_cc_config_params_init();
13389 if (!pvt->cc_params) {
13390 ast_free(pvt);
13391 return -1;
13392 }
13393 ast_mutex_init(&pvt->lock);
13394 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13395 pvt->subs[idx].dfd = -1;
13396 }
13397 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13398 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13399 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13400 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13401
13402 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13403 if (!chan) {
13404 destroy_dahdi_pvt(pvt);
13405 return -1;
13406 }
13407 chan->no_b_channel = 1;
13408
13409
13410
13411
13412
13413
13414 pvt->law_default = DAHDI_LAW_ALAW;
13415
13416 pvt->sig = pri->sig;
13417 pvt->outsigmod = -1;
13418 pvt->pri = pri;
13419 pvt->sig_pvt = chan;
13420 pri->pvts[pvt_idx] = chan;
13421
13422 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13423 if (pvt->subs[SUB_REAL].dfd < 0) {
13424 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13425 strerror(errno));
13426 destroy_dahdi_pvt(pvt);
13427 return -1;
13428 }
13429 memset(&bi, 0, sizeof(bi));
13430 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13431 if (!res) {
13432 pvt->bufsize = bi.bufsize;
13433 bi.txbufpolicy = pvt->buf_policy;
13434 bi.rxbufpolicy = pvt->buf_policy;
13435 bi.numbufs = pvt->buf_no;
13436 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13437 if (res < 0) {
13438 ast_log(LOG_WARNING,
13439 "Unable to set buffer policy on no B channel interface: %s\n",
13440 strerror(errno));
13441 }
13442 } else
13443 ast_log(LOG_WARNING,
13444 "Unable to check buffer policy on no B channel interface: %s\n",
13445 strerror(errno));
13446
13447 --nobch_channel;
13448 if (CHAN_PSEUDO < nobch_channel) {
13449 nobch_channel = CHAN_PSEUDO - 1;
13450 }
13451 pvt->channel = nobch_channel;
13452 pvt->span = pri->span;
13453 chan->channel = pvt->channel;
13454
13455 dahdi_nobch_insert(pri, pvt);
13456
13457 return pvt_idx;
13458 }
13459 #endif
13460
13461
13462
13463
13464
13465
13466 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13467 {
13468 struct dahdi_pvt *p;
13469 struct dahdi_bufferinfo bi;
13470 int res;
13471
13472 p = ast_malloc(sizeof(*p));
13473 if (!p) {
13474 return NULL;
13475 }
13476 *p = *src;
13477
13478
13479 p->cc_params = ast_cc_config_params_init();
13480 if (!p->cc_params) {
13481 ast_free(p);
13482 return NULL;
13483 }
13484 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13485
13486 p->which_iflist = DAHDI_IFLIST_NONE;
13487 p->next = NULL;
13488 p->prev = NULL;
13489 ast_mutex_init(&p->lock);
13490 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13491 if (p->subs[SUB_REAL].dfd < 0) {
13492 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13493 destroy_dahdi_pvt(p);
13494 return NULL;
13495 }
13496 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13497 if (!res) {
13498 bi.txbufpolicy = src->buf_policy;
13499 bi.rxbufpolicy = src->buf_policy;
13500 bi.numbufs = src->buf_no;
13501 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13502 if (res < 0) {
13503 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13504 }
13505 } else
13506 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13507 p->destroy = 1;
13508 dahdi_iflist_insert(p);
13509 return p;
13510 }
13511
13512 struct dahdi_starting_point {
13513
13514 ast_group_t groupmatch;
13515
13516 int channelmatch;
13517
13518 int rr_starting_point;
13519
13520 int span;
13521
13522 int cadance;
13523
13524 char opt;
13525
13526 char backwards;
13527
13528 char roundrobin;
13529 };
13530 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13531 {
13532 char *dest;
13533 char *s;
13534 int x;
13535 int res = 0;
13536 struct dahdi_pvt *p;
13537 char *subdir = NULL;
13538 AST_DECLARE_APP_ARGS(args,
13539 AST_APP_ARG(group);
13540
13541
13542 AST_APP_ARG(other);
13543 );
13544
13545
13546
13547
13548
13549
13550
13551
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561
13562
13563
13564
13565
13566
13567
13568 if (data) {
13569 dest = ast_strdupa(data);
13570 } else {
13571 ast_log(LOG_WARNING, "Channel requested with no data\n");
13572 return NULL;
13573 }
13574 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13575 if (!args.argc || ast_strlen_zero(args.group)) {
13576 ast_log(LOG_WARNING, "No channel/group specified\n");
13577 return NULL;
13578 }
13579
13580
13581 memset(param, 0, sizeof(*param));
13582 param->channelmatch = -1;
13583
13584 if (strchr(args.group, '!') != NULL) {
13585 char *prev = args.group;
13586 while ((s = strchr(prev, '!')) != NULL) {
13587 *s++ = '/';
13588 prev = s;
13589 }
13590 *(prev - 1) = '\0';
13591 subdir = args.group;
13592 args.group = prev;
13593 } else if (args.group[0] == 'i') {
13594
13595 res = sscanf(args.group + 1, "%30d", &x);
13596 if (res < 1) {
13597 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13598 return NULL;
13599 }
13600 param->span = x;
13601
13602
13603 s = strchr(args.group, '-');
13604 if (!s) {
13605
13606 return iflist;
13607 }
13608 args.group = s + 1;
13609 res = 0;
13610 }
13611 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13612
13613 s = args.group + 1;
13614 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13615 if (res < 1) {
13616 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13617 return NULL;
13618 }
13619 param->groupmatch = ((ast_group_t) 1 << x);
13620
13621 if (toupper(args.group[0]) == 'G') {
13622 if (args.group[0] == 'G') {
13623 param->backwards = 1;
13624 p = ifend;
13625 } else
13626 p = iflist;
13627 } else {
13628 if (ARRAY_LEN(round_robin) <= x) {
13629 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13630 x, data);
13631 return NULL;
13632 }
13633 if (args.group[0] == 'R') {
13634 param->backwards = 1;
13635 p = round_robin[x] ? round_robin[x]->prev : ifend;
13636 if (!p)
13637 p = ifend;
13638 } else {
13639 p = round_robin[x] ? round_robin[x]->next : iflist;
13640 if (!p)
13641 p = iflist;
13642 }
13643 param->roundrobin = 1;
13644 param->rr_starting_point = x;
13645 }
13646 } else {
13647 s = args.group;
13648 if (!strcasecmp(s, "pseudo")) {
13649
13650 x = CHAN_PSEUDO;
13651 param->channelmatch = x;
13652 } else {
13653 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13654 if (res < 1) {
13655 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13656 return NULL;
13657 } else {
13658 param->channelmatch = x;
13659 }
13660 }
13661 if (subdir) {
13662 char path[PATH_MAX];
13663 struct stat stbuf;
13664
13665 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13666 subdir, param->channelmatch);
13667 if (stat(path, &stbuf) < 0) {
13668 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13669 path, strerror(errno));
13670 return NULL;
13671 }
13672 if (!S_ISCHR(stbuf.st_mode)) {
13673 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13674 path);
13675 return NULL;
13676 }
13677 param->channelmatch = minor(stbuf.st_rdev);
13678 }
13679
13680 p = iflist;
13681 }
13682
13683 if (param->opt == 'r' && res < 3) {
13684 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13685 param->opt = '\0';
13686 }
13687
13688 return p;
13689 }
13690
13691 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13692 {
13693 int callwait = 0;
13694 struct dahdi_pvt *p;
13695 struct ast_channel *tmp = NULL;
13696 struct dahdi_pvt *exitpvt;
13697 int channelmatched = 0;
13698 int groupmatched = 0;
13699 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13700 int transcapdigital = 0;
13701 #endif
13702 struct dahdi_starting_point start;
13703
13704 ast_mutex_lock(&iflock);
13705 p = determine_starting_point(data, &start);
13706 if (!p) {
13707
13708 ast_mutex_unlock(&iflock);
13709 return NULL;
13710 }
13711
13712
13713 exitpvt = p;
13714 while (p && !tmp) {
13715 if (start.roundrobin)
13716 round_robin[start.rr_starting_point] = p;
13717
13718 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13719 && available(&p, channelmatched)) {
13720 ast_debug(1, "Using channel %d\n", p->channel);
13721
13722 callwait = (p->owner != NULL);
13723 #ifdef HAVE_OPENR2
13724 if (p->mfcr2) {
13725 ast_mutex_lock(&p->lock);
13726 if (p->mfcr2call) {
13727 ast_mutex_unlock(&p->lock);
13728 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13729 goto next;
13730 }
13731 p->mfcr2call = 1;
13732 ast_mutex_unlock(&p->lock);
13733 }
13734 #endif
13735 if (p->channel == CHAN_PSEUDO) {
13736 p = duplicate_pseudo(p);
13737 if (!p) {
13738 break;
13739 }
13740 }
13741
13742 p->distinctivering = 0;
13743
13744 switch (start.opt) {
13745 case '\0':
13746
13747 break;
13748 case 'c':
13749
13750 p->confirmanswer = 1;
13751 break;
13752 case 'r':
13753
13754 p->distinctivering = start.cadance;
13755 break;
13756 case 'd':
13757 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13758
13759 transcapdigital = AST_TRANS_CAP_DIGITAL;
13760 #endif
13761 break;
13762 default:
13763 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13764 break;
13765 }
13766
13767 p->outgoing = 1;
13768 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13769 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13770 #ifdef HAVE_PRI
13771 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13772
13773
13774
13775
13776
13777 ast_mutex_lock(&p->lock);
13778 ast_mutex_unlock(&p->lock);
13779
13780 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13781 sizeof(p->dnid));
13782 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13783 #endif
13784 #if defined(HAVE_SS7)
13785 } else if (p->sig == SIG_SS7) {
13786 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13787 #endif
13788 } else {
13789 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13790 }
13791 if (!tmp) {
13792 p->outgoing = 0;
13793 #if defined(HAVE_PRI)
13794 switch (p->sig) {
13795 case SIG_PRI_LIB_HANDLE_CASES:
13796 #if defined(HAVE_PRI_CALL_WAITING)
13797 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13798 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13799 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13800 }
13801 #endif
13802
13803
13804
13805
13806 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13807 break;
13808 default:
13809 break;
13810 }
13811 #endif
13812 } else {
13813 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13814 }
13815 break;
13816 }
13817 #ifdef HAVE_OPENR2
13818 next:
13819 #endif
13820 if (start.backwards) {
13821 p = p->prev;
13822 if (!p)
13823 p = ifend;
13824 } else {
13825 p = p->next;
13826 if (!p)
13827 p = iflist;
13828 }
13829
13830 if (p == exitpvt)
13831 break;
13832 }
13833 ast_mutex_unlock(&iflock);
13834 restart_monitor();
13835 if (cause && !tmp) {
13836 if (callwait || channelmatched) {
13837 *cause = AST_CAUSE_BUSY;
13838 } else if (groupmatched) {
13839 *cause = AST_CAUSE_CONGESTION;
13840 } else {
13841
13842
13843
13844
13845 }
13846 }
13847
13848 return tmp;
13849 }
13850
13851
13852
13853
13854
13855
13856
13857
13858
13859
13860
13861 static int dahdi_devicestate(void *data)
13862 {
13863 #if defined(HAVE_PRI)
13864 char *device;
13865 unsigned span;
13866 int res;
13867
13868 device = data;
13869
13870 if (*device != 'I') {
13871
13872 return AST_DEVICE_UNKNOWN;
13873 }
13874 res = sscanf(device, "I%30u", &span);
13875 if (res != 1 || !span || NUM_SPANS < span) {
13876
13877 return AST_DEVICE_UNKNOWN;
13878 }
13879 device = strchr(device, '/');
13880 if (!device) {
13881
13882 return AST_DEVICE_UNKNOWN;
13883 }
13884
13885
13886
13887
13888
13889 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13890 ++device;
13891 if (!strcmp(device, "congestion"))
13892 #endif
13893 {
13894 return pris[span - 1].pri.congestion_devstate;
13895 }
13896 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13897 else if (!strcmp(device, "threshold")) {
13898 return pris[span - 1].pri.threshold_devstate;
13899 }
13900 return AST_DEVICE_UNKNOWN;
13901 #endif
13902 #else
13903 return AST_DEVICE_UNKNOWN;
13904 #endif
13905 }
13906
13907
13908
13909
13910
13911
13912
13913
13914
13915
13916
13917
13918
13919
13920
13921
13922
13923 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13924 {
13925 struct dahdi_pvt *p;
13926 struct dahdi_pvt *exitpvt;
13927 struct dahdi_starting_point start;
13928 int groupmatched = 0;
13929 int channelmatched = 0;
13930
13931 ast_mutex_lock(&iflock);
13932 p = determine_starting_point(dest, &start);
13933 if (!p) {
13934 ast_mutex_unlock(&iflock);
13935 return -1;
13936 }
13937 exitpvt = p;
13938 for (;;) {
13939 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13940
13941 struct ast_str *device_name;
13942 char *dash;
13943 const char *monitor_type;
13944 char dialstring[AST_CHANNEL_NAME];
13945 char full_device_name[AST_CHANNEL_NAME];
13946
13947 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13948 case AST_CC_MONITOR_NEVER:
13949 break;
13950 case AST_CC_MONITOR_NATIVE:
13951 case AST_CC_MONITOR_ALWAYS:
13952 case AST_CC_MONITOR_GENERIC:
13953 #if defined(HAVE_PRI)
13954 if (dahdi_sig_pri_lib_handles(p->sig)) {
13955
13956
13957
13958
13959 snprintf(full_device_name, sizeof(full_device_name),
13960 "DAHDI/I%d/congestion", p->pri->span);
13961 } else
13962 #endif
13963 {
13964 #if defined(HAVE_PRI)
13965 device_name = create_channel_name(p, 1, "");
13966 #else
13967 device_name = create_channel_name(p);
13968 #endif
13969 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13970 device_name ? ast_str_buffer(device_name) : "");
13971 ast_free(device_name);
13972
13973
13974
13975
13976
13977 dash = strrchr(full_device_name, '-');
13978 if (dash) {
13979 *dash = '\0';
13980 }
13981 }
13982 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13983
13984
13985
13986
13987
13988
13989
13990 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13991 callback(inbound,
13992 #if defined(HAVE_PRI)
13993 p->pri ? p->pri->cc_params : p->cc_params,
13994 #else
13995 p->cc_params,
13996 #endif
13997 monitor_type, full_device_name, dialstring, NULL);
13998 break;
13999 }
14000 }
14001 p = start.backwards ? p->prev : p->next;
14002 if (!p) {
14003 p = start.backwards ? ifend : iflist;
14004 }
14005 if (p == exitpvt) {
14006 break;
14007 }
14008 }
14009 ast_mutex_unlock(&iflock);
14010 return 0;
14011 }
14012
14013 #if defined(HAVE_SS7)
14014 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14015 {
14016 int i;
14017
14018 if (ss7) {
14019 for (i = 0; i < NUM_SPANS; i++) {
14020 if (linksets[i].ss7.ss7 == ss7) {
14021 ast_verbose("[%d] %s", i + 1, s);
14022 return;
14023 }
14024 }
14025 }
14026 ast_verbose("%s", s);
14027 }
14028 #endif
14029
14030 #if defined(HAVE_SS7)
14031 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14032 {
14033 int i;
14034
14035 if (ss7) {
14036 for (i = 0; i < NUM_SPANS; i++) {
14037 if (linksets[i].ss7.ss7 == ss7) {
14038 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14039 return;
14040 }
14041 }
14042 }
14043 ast_log(LOG_ERROR, "%s", s);
14044 }
14045 #endif
14046
14047 #if defined(HAVE_OPENR2)
14048 static void *mfcr2_monitor(void *data)
14049 {
14050 struct dahdi_mfcr2 *mfcr2 = data;
14051
14052
14053
14054
14055
14056 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14057 int res = 0;
14058 int i = 0;
14059 int oldstate = 0;
14060 int quit_loop = 0;
14061 int maxsleep = 20;
14062 int was_idle = 0;
14063 int pollsize = 0;
14064
14065
14066 for (i = 0; i < mfcr2->numchans; i++) {
14067 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14068 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14069 }
14070 while (1) {
14071
14072
14073 pollsize = 0;
14074 for (i = 0; i < mfcr2->numchans; i++) {
14075 pollers[i].revents = 0;
14076 pollers[i].events = 0;
14077 if (mfcr2->pvts[i]->owner) {
14078 continue;
14079 }
14080 if (!mfcr2->pvts[i]->r2chan) {
14081 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14082 quit_loop = 1;
14083 break;
14084 }
14085 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14086 pollers[i].events = POLLIN | POLLPRI;
14087 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14088 pollsize++;
14089 }
14090 if (quit_loop) {
14091 break;
14092 }
14093 if (pollsize == 0) {
14094 if (!was_idle) {
14095 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14096 was_idle = 1;
14097 }
14098 poll(NULL, 0, maxsleep);
14099 continue;
14100 }
14101 was_idle = 0;
14102
14103
14104 pthread_testcancel();
14105 res = poll(pollers, mfcr2->numchans, maxsleep);
14106 pthread_testcancel();
14107 if ((res < 0) && (errno != EINTR)) {
14108 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14109 break;
14110 }
14111
14112 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14113 for (i = 0; i < mfcr2->numchans; i++) {
14114 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14115 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14116 }
14117 }
14118 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14119 }
14120 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14121 return 0;
14122 }
14123 #endif
14124
14125 #if defined(HAVE_PRI)
14126 static void dahdi_pri_message(struct pri *pri, char *s)
14127 {
14128 int x;
14129 int y;
14130 int dchan = -1;
14131 int span = -1;
14132 int dchancount = 0;
14133
14134 if (pri) {
14135 for (x = 0; x < NUM_SPANS; x++) {
14136 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14137 if (pris[x].pri.dchans[y]) {
14138 dchancount++;
14139 }
14140
14141 if (pris[x].pri.dchans[y] == pri) {
14142 dchan = y;
14143 }
14144 }
14145 if (dchan >= 0) {
14146 span = x;
14147 break;
14148 }
14149 dchancount = 0;
14150 }
14151 if (-1 < span) {
14152 if (1 < dchancount) {
14153 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14154 } else {
14155 ast_verbose("PRI Span: %d %s", span + 1, s);
14156 }
14157 } else {
14158 ast_verbose("PRI Span: ? %s", s);
14159 }
14160 } else {
14161 ast_verbose("PRI Span: ? %s", s);
14162 }
14163
14164 ast_mutex_lock(&pridebugfdlock);
14165
14166 if (pridebugfd >= 0) {
14167 if (write(pridebugfd, s, strlen(s)) < 0) {
14168 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14169 }
14170 }
14171
14172 ast_mutex_unlock(&pridebugfdlock);
14173 }
14174 #endif
14175
14176 #if defined(HAVE_PRI)
14177 static void dahdi_pri_error(struct pri *pri, char *s)
14178 {
14179 int x;
14180 int y;
14181 int dchan = -1;
14182 int span = -1;
14183 int dchancount = 0;
14184
14185 if (pri) {
14186 for (x = 0; x < NUM_SPANS; x++) {
14187 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14188 if (pris[x].pri.dchans[y]) {
14189 dchancount++;
14190 }
14191
14192 if (pris[x].pri.dchans[y] == pri) {
14193 dchan = y;
14194 }
14195 }
14196 if (dchan >= 0) {
14197 span = x;
14198 break;
14199 }
14200 dchancount = 0;
14201 }
14202 if (-1 < span) {
14203 if (1 < dchancount) {
14204 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14205 } else {
14206 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14207 }
14208 } else {
14209 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14210 }
14211 } else {
14212 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14213 }
14214
14215 ast_mutex_lock(&pridebugfdlock);
14216
14217 if (pridebugfd >= 0) {
14218 if (write(pridebugfd, s, strlen(s)) < 0) {
14219 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14220 }
14221 }
14222
14223 ast_mutex_unlock(&pridebugfdlock);
14224 }
14225 #endif
14226
14227 #if defined(HAVE_PRI)
14228 static int prepare_pri(struct dahdi_pri *pri)
14229 {
14230 int i, res, x;
14231 struct dahdi_params p;
14232 struct dahdi_bufferinfo bi;
14233 struct dahdi_spaninfo si;
14234
14235 pri->pri.calls = &dahdi_pri_callbacks;
14236
14237 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14238 if (!pri->dchannels[i])
14239 break;
14240 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14241 x = pri->dchannels[i];
14242 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14243 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14244 return -1;
14245 }
14246 memset(&p, 0, sizeof(p));
14247 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14248 if (res) {
14249 dahdi_close_pri_fd(pri, i);
14250 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14251 return -1;
14252 }
14253 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14254 dahdi_close_pri_fd(pri, i);
14255 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14256 return -1;
14257 }
14258 memset(&si, 0, sizeof(si));
14259 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14260 if (res) {
14261 dahdi_close_pri_fd(pri, i);
14262 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14263 }
14264 if (!si.alarms) {
14265 pri_event_noalarm(&pri->pri, i, 1);
14266 } else {
14267 pri_event_alarm(&pri->pri, i, 1);
14268 }
14269 memset(&bi, 0, sizeof(bi));
14270 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14271 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14272 bi.numbufs = 32;
14273 bi.bufsize = 1024;
14274 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14275 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14276 dahdi_close_pri_fd(pri, i);
14277 return -1;
14278 }
14279 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14280 }
14281 return 0;
14282 }
14283 #endif
14284
14285 #if defined(HAVE_PRI)
14286 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14287 {
14288 int which, span;
14289 char *ret = NULL;
14290
14291 if (pos != rpos)
14292 return ret;
14293
14294 for (which = span = 0; span < NUM_SPANS; span++) {
14295 if (pris[span].pri.pri && ++which > state) {
14296 if (ast_asprintf(&ret, "%d", span + 1) < 0) {
14297 ret = NULL;
14298 }
14299 break;
14300 }
14301 }
14302 return ret;
14303 }
14304 #endif
14305
14306 #if defined(HAVE_PRI)
14307 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14308 {
14309 return complete_span_helper(line,word,pos,state,3);
14310 }
14311 #endif
14312
14313 #if defined(HAVE_PRI)
14314 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14315 {
14316 int myfd;
14317 switch (cmd) {
14318 case CLI_INIT:
14319 e->command = "pri set debug file";
14320 e->usage = "Usage: pri set debug file [output-file]\n"
14321 " Sends PRI debug output to the specified output file\n";
14322 return NULL;
14323 case CLI_GENERATE:
14324 return NULL;
14325 }
14326 if (a->argc < 5)
14327 return CLI_SHOWUSAGE;
14328
14329 if (ast_strlen_zero(a->argv[4]))
14330 return CLI_SHOWUSAGE;
14331
14332 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14333 if (myfd < 0) {
14334 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14335 return CLI_SUCCESS;
14336 }
14337
14338 ast_mutex_lock(&pridebugfdlock);
14339
14340 if (pridebugfd >= 0)
14341 close(pridebugfd);
14342
14343 pridebugfd = myfd;
14344 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14345 ast_mutex_unlock(&pridebugfdlock);
14346 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14347 return CLI_SUCCESS;
14348 }
14349 #endif
14350
14351 #if defined(HAVE_PRI)
14352 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14353 {
14354 int span;
14355 int x;
14356 int level = 0;
14357 switch (cmd) {
14358 case CLI_INIT:
14359 e->command = "pri set debug {on|off|0|1|2} span";
14360 e->usage =
14361 "Usage: pri set debug {<level>|on|off} span <span>\n"
14362 " Enables debugging on a given PRI span\n";
14363 return NULL;
14364 case CLI_GENERATE:
14365 return complete_span_4(a->line, a->word, a->pos, a->n);
14366 }
14367 if (a->argc < 6) {
14368 return CLI_SHOWUSAGE;
14369 }
14370
14371 if (!strcasecmp(a->argv[3], "on")) {
14372 level = 1;
14373 } else if (!strcasecmp(a->argv[3], "off")) {
14374 level = 0;
14375 } else {
14376 level = atoi(a->argv[3]);
14377 }
14378 span = atoi(a->argv[5]);
14379 if ((span < 1) || (span > NUM_SPANS)) {
14380 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14381 return CLI_SUCCESS;
14382 }
14383 if (!pris[span-1].pri.pri) {
14384 ast_cli(a->fd, "No PRI running on span %d\n", span);
14385 return CLI_SUCCESS;
14386 }
14387
14388
14389 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14390 if (pris[span - 1].pri.dchans[x]) {
14391 switch (level) {
14392 case 0:
14393 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14394 break;
14395 case 1:
14396 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14397 break;
14398 default:
14399 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14400 break;
14401 }
14402 }
14403 }
14404 if (level == 0) {
14405
14406 ast_mutex_lock(&pridebugfdlock);
14407 if (0 <= pridebugfd) {
14408 close(pridebugfd);
14409 pridebugfd = -1;
14410 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14411 pridebugfilename);
14412 }
14413 ast_mutex_unlock(&pridebugfdlock);
14414 }
14415 pris[span - 1].pri.debug = (level) ? 1 : 0;
14416 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14417 return CLI_SUCCESS;
14418 }
14419 #endif
14420
14421 #if defined(HAVE_PRI)
14422 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14423 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14424 {
14425 unsigned *why;
14426 int channel;
14427 int trunkgroup;
14428 int x, y, fd = a->fd;
14429 int interfaceid = 0;
14430 char db_chan_name[20], db_answer[5];
14431 struct dahdi_pvt *tmp;
14432 struct dahdi_pri *pri;
14433
14434 if (a->argc < 5 || a->argc > 6)
14435 return CLI_SHOWUSAGE;
14436 if (strchr(a->argv[4], ':')) {
14437 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14438 return CLI_SHOWUSAGE;
14439 if ((trunkgroup < 1) || (channel < 1))
14440 return CLI_SHOWUSAGE;
14441 pri = NULL;
14442 for (x=0;x<NUM_SPANS;x++) {
14443 if (pris[x].pri.trunkgroup == trunkgroup) {
14444 pri = pris + x;
14445 break;
14446 }
14447 }
14448 if (!pri) {
14449 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14450 return CLI_FAILURE;
14451 }
14452 } else
14453 channel = atoi(a->argv[4]);
14454
14455 if (a->argc == 6)
14456 interfaceid = atoi(a->argv[5]);
14457
14458
14459 for (x = 0; x < NUM_SPANS; x++) {
14460 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14461 if (pris[x].dchannels[y] == channel) {
14462 pri = pris + x;
14463 if (pri->pri.enable_service_message_support) {
14464 ast_mutex_lock(&pri->pri.lock);
14465 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14466 ast_mutex_unlock(&pri->pri.lock);
14467 } else {
14468 ast_cli(fd,
14469 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14470 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14471 }
14472 return CLI_SUCCESS;
14473 }
14474 }
14475 }
14476
14477
14478 ast_mutex_lock(&iflock);
14479 for (tmp = iflist; tmp; tmp = tmp->next) {
14480 if (tmp->pri && tmp->channel == channel) {
14481 ast_mutex_unlock(&iflock);
14482 ast_mutex_lock(&tmp->pri->lock);
14483 if (!tmp->pri->enable_service_message_support) {
14484 ast_mutex_unlock(&tmp->pri->lock);
14485 ast_cli(fd,
14486 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14487 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14488 return CLI_SUCCESS;
14489 }
14490 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14491 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14492 switch(changestatus) {
14493 case 0:
14494
14495 ast_db_del(db_chan_name, SRVST_DBKEY);
14496 *why &= ~SRVST_NEAREND;
14497 if (*why) {
14498 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14499 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14500 } else {
14501 dahdi_pri_update_span_devstate(tmp->pri);
14502 }
14503 break;
14504
14505 case 2:
14506
14507 ast_db_del(db_chan_name, SRVST_DBKEY);
14508 *why |= SRVST_NEAREND;
14509 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14510 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14511 dahdi_pri_update_span_devstate(tmp->pri);
14512 break;
14513
14514
14515 default:
14516 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14517 break;
14518 }
14519 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14520 ast_mutex_unlock(&tmp->pri->lock);
14521 return CLI_SUCCESS;
14522 }
14523 }
14524 ast_mutex_unlock(&iflock);
14525
14526 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14527 return CLI_FAILURE;
14528 }
14529
14530 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14531 {
14532 switch (cmd) {
14533 case CLI_INIT:
14534 e->command = "pri service enable channel";
14535 e->usage =
14536 "Usage: pri service enable channel <channel> [<interface id>]\n"
14537 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14538 " to restore a channel to service, with optional interface id\n"
14539 " as agreed upon with remote switch operator\n";
14540 return NULL;
14541 case CLI_GENERATE:
14542 return NULL;
14543 }
14544 return handle_pri_service_generic(e, cmd, a, 0);
14545 }
14546
14547 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14548 {
14549 switch (cmd) {
14550 case CLI_INIT:
14551 e->command = "pri service disable channel";
14552 e->usage =
14553 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14554 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14555 " to remove a channel from service, with optional interface id\n"
14556 " as agreed upon with remote switch operator\n";
14557 return NULL;
14558 case CLI_GENERATE:
14559 return NULL;
14560 }
14561 return handle_pri_service_generic(e, cmd, a, 2);
14562 }
14563 #endif
14564 #endif
14565
14566 #if defined(HAVE_PRI)
14567 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14568 {
14569 int span;
14570
14571 switch (cmd) {
14572 case CLI_INIT:
14573 e->command = "pri show channels";
14574 e->usage =
14575 "Usage: pri show channels\n"
14576 " Displays PRI channel information such as the current mapping\n"
14577 " of DAHDI B channels to Asterisk channel names and which calls\n"
14578 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14579 " are not associated with any B channel.\n";
14580 return NULL;
14581 case CLI_GENERATE:
14582 return NULL;
14583 }
14584
14585 if (a->argc != 3)
14586 return CLI_SHOWUSAGE;
14587
14588 sig_pri_cli_show_channels_header(a->fd);
14589 for (span = 0; span < NUM_SPANS; ++span) {
14590 if (pris[span].pri.pri) {
14591 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14592 }
14593 }
14594 return CLI_SUCCESS;
14595 }
14596 #endif
14597
14598 #if defined(HAVE_PRI)
14599 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14600 {
14601 int span;
14602
14603 switch (cmd) {
14604 case CLI_INIT:
14605 e->command = "pri show spans";
14606 e->usage =
14607 "Usage: pri show spans\n"
14608 " Displays PRI span information\n";
14609 return NULL;
14610 case CLI_GENERATE:
14611 return NULL;
14612 }
14613
14614 if (a->argc != 3)
14615 return CLI_SHOWUSAGE;
14616
14617 for (span = 0; span < NUM_SPANS; span++) {
14618 if (pris[span].pri.pri) {
14619 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14620 }
14621 }
14622 return CLI_SUCCESS;
14623 }
14624 #endif
14625
14626 #if defined(HAVE_PRI)
14627 #define container_of(ptr, type, member) \
14628 ((type *)((char *)(ptr) - offsetof(type, member)))
14629
14630
14631
14632
14633
14634
14635
14636
14637
14638
14639
14640
14641
14642 static int pri_destroy_dchan(struct sig_pri_span *pri)
14643 {
14644 int i;
14645 struct dahdi_pri* dahdi_pri;
14646
14647 if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14648 return 0;
14649 }
14650 pthread_cancel(pri->master);
14651 pthread_join(pri->master, NULL);
14652
14653
14654 dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14655 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14656 ast_debug(4, "closing pri_fd %d\n", i);
14657 dahdi_close_pri_fd(dahdi_pri, i);
14658 }
14659 pri->pri = NULL;
14660 ast_debug(1, "PRI span %d destroyed\n", pri->span);
14661 return 1;
14662 }
14663
14664 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14665 struct ast_cli_args *a)
14666 {
14667 int span;
14668 int i;
14669 int res;
14670
14671 switch (cmd) {
14672 case CLI_INIT:
14673 e->command = "pri destroy span";
14674 e->usage =
14675 "Usage: pri destroy span <span>\n"
14676 " Destorys D-channel of span and its B-channels.\n"
14677 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14678 return NULL;
14679 case CLI_GENERATE:
14680 return complete_span_4(a->line, a->word, a->pos, a->n);
14681 }
14682
14683 if (a->argc < 4) {
14684 return CLI_SHOWUSAGE;
14685 }
14686 res = sscanf(a->argv[3], "%30d", &span);
14687 if ((res != 1) || span < 1 || span > NUM_SPANS) {
14688 ast_cli(a->fd,
14689 "Invalid span '%s'. Should be a number from %d to %d\n",
14690 a->argv[3], 1, NUM_SPANS);
14691 return CLI_SUCCESS;
14692 }
14693 if (!pris[span - 1].pri.pri) {
14694 ast_cli(a->fd, "No PRI running on span %d\n", span);
14695 return CLI_SUCCESS;
14696 }
14697
14698 for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14699 int channel;
14700 struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14701
14702 if (!pvt) {
14703 continue;
14704 }
14705 channel = pvt->channel;
14706 ast_debug(2, "About to destroy B-channel %d.\n", channel);
14707 dahdi_destroy_channel_bynum(channel);
14708 }
14709 ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14710 pri_destroy_dchan(&pris[span - 1].pri);
14711
14712 return CLI_SUCCESS;
14713 }
14714
14715 #endif
14716
14717 #if defined(HAVE_PRI)
14718 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14719 {
14720 int span;
14721
14722 switch (cmd) {
14723 case CLI_INIT:
14724 e->command = "pri show span";
14725 e->usage =
14726 "Usage: pri show span <span>\n"
14727 " Displays PRI Information on a given PRI span\n";
14728 return NULL;
14729 case CLI_GENERATE:
14730 return complete_span_4(a->line, a->word, a->pos, a->n);
14731 }
14732
14733 if (a->argc < 4)
14734 return CLI_SHOWUSAGE;
14735 span = atoi(a->argv[3]);
14736 if ((span < 1) || (span > NUM_SPANS)) {
14737 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14738 return CLI_SUCCESS;
14739 }
14740 if (!pris[span-1].pri.pri) {
14741 ast_cli(a->fd, "No PRI running on span %d\n", span);
14742 return CLI_SUCCESS;
14743 }
14744
14745 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14746
14747 return CLI_SUCCESS;
14748 }
14749 #endif
14750
14751 #if defined(HAVE_PRI)
14752 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14753 {
14754 int x;
14755 int span;
14756 int count=0;
14757 int debug;
14758
14759 switch (cmd) {
14760 case CLI_INIT:
14761 e->command = "pri show debug";
14762 e->usage =
14763 "Usage: pri show debug\n"
14764 " Show the debug state of pri spans\n";
14765 return NULL;
14766 case CLI_GENERATE:
14767 return NULL;
14768 }
14769
14770 for (span = 0; span < NUM_SPANS; span++) {
14771 if (pris[span].pri.pri) {
14772 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14773 if (pris[span].pri.dchans[x]) {
14774 debug = pri_get_debug(pris[span].pri.dchans[x]);
14775 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" );
14776 count++;
14777 }
14778 }
14779 }
14780
14781 }
14782 ast_mutex_lock(&pridebugfdlock);
14783 if (pridebugfd >= 0)
14784 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14785 ast_mutex_unlock(&pridebugfdlock);
14786
14787 if (!count)
14788 ast_cli(a->fd, "No PRI running\n");
14789 return CLI_SUCCESS;
14790 }
14791 #endif
14792
14793 #if defined(HAVE_PRI)
14794 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14795 {
14796 switch (cmd) {
14797 case CLI_INIT:
14798 e->command = "pri show version";
14799 e->usage =
14800 "Usage: pri show version\n"
14801 "Show libpri version information\n";
14802 return NULL;
14803 case CLI_GENERATE:
14804 return NULL;
14805 }
14806
14807 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14808
14809 return CLI_SUCCESS;
14810 }
14811 #endif
14812
14813 #if defined(HAVE_PRI)
14814 static struct ast_cli_entry dahdi_pri_cli[] = {
14815 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14816 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14817 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14818 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14819 #endif
14820 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14821 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14822 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14823 AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
14824 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14825 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14826 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14827 };
14828 #endif
14829
14830 #ifdef HAVE_OPENR2
14831
14832 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14833 {
14834 switch (cmd) {
14835 case CLI_INIT:
14836 e->command = "mfcr2 show version";
14837 e->usage =
14838 "Usage: mfcr2 show version\n"
14839 " Shows the version of the OpenR2 library being used.\n";
14840 return NULL;
14841 case CLI_GENERATE:
14842 return NULL;
14843 }
14844 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14845 return CLI_SUCCESS;
14846 }
14847
14848 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14849 {
14850 #define FORMAT "%4s %40s\n"
14851 int i = 0;
14852 int numvariants = 0;
14853 const openr2_variant_entry_t *variants;
14854 switch (cmd) {
14855 case CLI_INIT:
14856 e->command = "mfcr2 show variants";
14857 e->usage =
14858 "Usage: mfcr2 show variants\n"
14859 " Shows the list of MFC/R2 variants supported.\n";
14860 return NULL;
14861 case CLI_GENERATE:
14862 return NULL;
14863 }
14864 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14865 ast_cli(a->fd, "Failed to get list of variants.\n");
14866 return CLI_FAILURE;
14867 }
14868 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14869 for (i = 0; i < numvariants; i++) {
14870 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14871 }
14872 return CLI_SUCCESS;
14873 #undef FORMAT
14874 }
14875
14876 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14877 {
14878 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14879 int filtertype = 0;
14880 int targetnum = 0;
14881 char channo[5];
14882 char anino[5];
14883 char dnisno[5];
14884 struct dahdi_pvt *p;
14885 openr2_context_t *r2context;
14886 openr2_variant_t r2variant;
14887 switch (cmd) {
14888 case CLI_INIT:
14889 e->command = "mfcr2 show channels [group|context]";
14890 e->usage =
14891 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14892 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14893 return NULL;
14894 case CLI_GENERATE:
14895 return NULL;
14896 }
14897 if (!((a->argc == 3) || (a->argc == 5))) {
14898 return CLI_SHOWUSAGE;
14899 }
14900 if (a->argc == 5) {
14901 if (!strcasecmp(a->argv[3], "group")) {
14902 targetnum = atoi(a->argv[4]);
14903 if ((targetnum < 0) || (targetnum > 63))
14904 return CLI_SHOWUSAGE;
14905 targetnum = 1 << targetnum;
14906 filtertype = 1;
14907 } else if (!strcasecmp(a->argv[3], "context")) {
14908 filtertype = 2;
14909 } else {
14910 return CLI_SHOWUSAGE;
14911 }
14912 }
14913 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14914 ast_mutex_lock(&iflock);
14915 for (p = iflist; p; p = p->next) {
14916 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14917 continue;
14918 }
14919 if (filtertype) {
14920 switch(filtertype) {
14921 case 1:
14922 if (p->group != targetnum) {
14923 continue;
14924 }
14925 break;
14926 case 2:
14927 if (strcasecmp(p->context, a->argv[4])) {
14928 continue;
14929 }
14930 break;
14931 default:
14932 ;
14933 }
14934 }
14935 r2context = openr2_chan_get_context(p->r2chan);
14936 r2variant = openr2_context_get_variant(r2context);
14937 snprintf(channo, sizeof(channo), "%d", p->channel);
14938 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14939 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14940 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14941 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14942 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14943 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14944 }
14945 ast_mutex_unlock(&iflock);
14946 return CLI_SUCCESS;
14947 #undef FORMAT
14948 }
14949
14950 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14951 {
14952 struct dahdi_pvt *p = NULL;
14953 int channo = 0;
14954 char *toklevel = NULL;
14955 char *saveptr = NULL;
14956 char *logval = NULL;
14957 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14958 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14959 switch (cmd) {
14960 case CLI_INIT:
14961 e->command = "mfcr2 set debug";
14962 e->usage =
14963 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14964 " Set a new logging level for the specified channel.\n"
14965 " If no channel is specified the logging level will be applied to all channels.\n";
14966 return NULL;
14967 case CLI_GENERATE:
14968 return NULL;
14969 }
14970 if (a->argc < 4) {
14971 return CLI_SHOWUSAGE;
14972 }
14973 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14974 logval = ast_strdupa(a->argv[3]);
14975 toklevel = strtok_r(logval, ",", &saveptr);
14976 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14977 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14978 return CLI_FAILURE;
14979 } else if (OR2_LOG_NOTHING == tmplevel) {
14980 loglevel = tmplevel;
14981 } else {
14982 loglevel |= tmplevel;
14983 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14984 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14985 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14986 continue;
14987 }
14988 loglevel |= tmplevel;
14989 }
14990 }
14991 ast_mutex_lock(&iflock);
14992 for (p = iflist; p; p = p->next) {
14993 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14994 continue;
14995 }
14996 if ((channo != -1) && (p->channel != channo )) {
14997 continue;
14998 }
14999 openr2_chan_set_log_level(p->r2chan, loglevel);
15000 if (channo != -1) {
15001 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15002 break;
15003 }
15004 }
15005 if ((channo != -1) && !p) {
15006 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15007 }
15008 if (channo == -1) {
15009 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15010 }
15011 ast_mutex_unlock(&iflock);
15012 return CLI_SUCCESS;
15013 }
15014
15015 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15016 {
15017 struct dahdi_pvt *p = NULL;
15018 int channo = 0;
15019 switch (cmd) {
15020 case CLI_INIT:
15021 e->command = "mfcr2 call files [on|off]";
15022 e->usage =
15023 "Usage: mfcr2 call files [on|off] <channel>\n"
15024 " Enable call files creation on the specified channel.\n"
15025 " If no channel is specified call files creation policy will be applied to all channels.\n";
15026 return NULL;
15027 case CLI_GENERATE:
15028 return NULL;
15029 }
15030 if (a->argc < 4) {
15031 return CLI_SHOWUSAGE;
15032 }
15033 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15034 ast_mutex_lock(&iflock);
15035 for (p = iflist; p; p = p->next) {
15036 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15037 continue;
15038 }
15039 if ((channo != -1) && (p->channel != channo )) {
15040 continue;
15041 }
15042 if (ast_true(a->argv[3])) {
15043 openr2_chan_enable_call_files(p->r2chan);
15044 } else {
15045 openr2_chan_disable_call_files(p->r2chan);
15046 }
15047 if (channo != -1) {
15048 if (ast_true(a->argv[3])) {
15049 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15050 } else {
15051 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15052 }
15053 break;
15054 }
15055 }
15056 if ((channo != -1) && !p) {
15057 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15058 }
15059 if (channo == -1) {
15060 if (ast_true(a->argv[3])) {
15061 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15062 } else {
15063 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15064 }
15065 }
15066 ast_mutex_unlock(&iflock);
15067 return CLI_SUCCESS;
15068 }
15069
15070 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15071 {
15072 struct dahdi_pvt *p = NULL;
15073 int channo = 0;
15074 switch (cmd) {
15075 case CLI_INIT:
15076 e->command = "mfcr2 set idle";
15077 e->usage =
15078 "Usage: mfcr2 set idle <channel>\n"
15079 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15080 " Force the given channel into IDLE state.\n"
15081 " If no channel is specified, all channels will be set to IDLE.\n";
15082 return NULL;
15083 case CLI_GENERATE:
15084 return NULL;
15085 }
15086 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15087 ast_mutex_lock(&iflock);
15088 for (p = iflist; p; p = p->next) {
15089 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15090 continue;
15091 }
15092 if ((channo != -1) && (p->channel != channo )) {
15093 continue;
15094 }
15095 openr2_chan_set_idle(p->r2chan);
15096 ast_mutex_lock(&p->lock);
15097 p->locallyblocked = 0;
15098 p->mfcr2call = 0;
15099 ast_mutex_unlock(&p->lock);
15100 if (channo != -1) {
15101 break;
15102 }
15103 }
15104 if ((channo != -1) && !p) {
15105 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15106 }
15107 ast_mutex_unlock(&iflock);
15108 return CLI_SUCCESS;
15109 }
15110
15111 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15112 {
15113 struct dahdi_pvt *p = NULL;
15114 int channo = 0;
15115 switch (cmd) {
15116 case CLI_INIT:
15117 e->command = "mfcr2 set blocked";
15118 e->usage =
15119 "Usage: mfcr2 set blocked <channel>\n"
15120 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15121 " Force the given channel into BLOCKED state.\n"
15122 " If no channel is specified, all channels will be set to BLOCKED.\n";
15123 return NULL;
15124 case CLI_GENERATE:
15125 return NULL;
15126 }
15127 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15128 ast_mutex_lock(&iflock);
15129 for (p = iflist; p; p = p->next) {
15130 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15131 continue;
15132 }
15133 if ((channo != -1) && (p->channel != channo )) {
15134 continue;
15135 }
15136 openr2_chan_set_blocked(p->r2chan);
15137 ast_mutex_lock(&p->lock);
15138 p->locallyblocked = 1;
15139 ast_mutex_unlock(&p->lock);
15140 if (channo != -1) {
15141 break;
15142 }
15143 }
15144 if ((channo != -1) && !p) {
15145 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15146 }
15147 ast_mutex_unlock(&iflock);
15148 return CLI_SUCCESS;
15149 }
15150
15151 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15152 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15153 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15154 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15155 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15156 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15157 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15158 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15159 };
15160
15161 #endif
15162
15163 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15164 {
15165 int channel;
15166 int ret;
15167 switch (cmd) {
15168 case CLI_INIT:
15169 e->command = "dahdi destroy channel";
15170 e->usage =
15171 "Usage: dahdi destroy channel <chan num>\n"
15172 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15173 return NULL;
15174 case CLI_GENERATE:
15175 return NULL;
15176 }
15177 if (a->argc != 4)
15178 return CLI_SHOWUSAGE;
15179
15180 channel = atoi(a->argv[3]);
15181 ret = dahdi_destroy_channel_bynum(channel);
15182 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15183 }
15184
15185 static void dahdi_softhangup_all(void)
15186 {
15187 struct dahdi_pvt *p;
15188 retry:
15189 ast_mutex_lock(&iflock);
15190 for (p = iflist; p; p = p->next) {
15191 ast_mutex_lock(&p->lock);
15192 if (p->owner && !p->restartpending) {
15193 if (ast_channel_trylock(p->owner)) {
15194 if (option_debug > 2)
15195 ast_verbose("Avoiding deadlock\n");
15196
15197 ast_mutex_unlock(&p->lock);
15198 ast_mutex_unlock(&iflock);
15199 goto retry;
15200 }
15201 if (option_debug > 2)
15202 ast_verbose("Softhanging up on %s\n", p->owner->name);
15203 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15204 p->restartpending = 1;
15205 num_restart_pending++;
15206 ast_channel_unlock(p->owner);
15207 }
15208 ast_mutex_unlock(&p->lock);
15209 }
15210 ast_mutex_unlock(&iflock);
15211 }
15212
15213 static int setup_dahdi(int reload);
15214 static int dahdi_restart(void)
15215 {
15216 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15217 int i, j;
15218 #endif
15219 int cancel_code;
15220 struct dahdi_pvt *p;
15221
15222 ast_mutex_lock(&restart_lock);
15223 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15224 dahdi_softhangup_all();
15225 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15226 #ifdef HAVE_OPENR2
15227 dahdi_r2_destroy_links();
15228 #endif
15229
15230 #if defined(HAVE_PRI)
15231 for (i = 0; i < NUM_SPANS; i++) {
15232 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15233 cancel_code = pthread_cancel(pris[i].pri.master);
15234 pthread_kill(pris[i].pri.master, SIGURG);
15235 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);
15236 pthread_join(pris[i].pri.master, NULL);
15237 ast_debug(4, "Joined thread of span %d\n", i);
15238 }
15239 }
15240 #endif
15241
15242 #if defined(HAVE_SS7)
15243 for (i = 0; i < NUM_SPANS; i++) {
15244 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15245 cancel_code = pthread_cancel(linksets[i].ss7.master);
15246 pthread_kill(linksets[i].ss7.master, SIGURG);
15247 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);
15248 pthread_join(linksets[i].ss7.master, NULL);
15249 ast_debug(4, "Joined thread of span %d\n", i);
15250 }
15251 }
15252 #endif
15253
15254 ast_mutex_lock(&monlock);
15255 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15256 cancel_code = pthread_cancel(monitor_thread);
15257 pthread_kill(monitor_thread, SIGURG);
15258 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15259 pthread_join(monitor_thread, NULL);
15260 ast_debug(4, "Joined monitor thread\n");
15261 }
15262 monitor_thread = AST_PTHREADT_NULL;
15263
15264 ast_mutex_lock(&ss_thread_lock);
15265 while (ss_thread_count > 0) {
15266 int x = DAHDI_FLASH;
15267 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15268
15269 ast_mutex_lock(&iflock);
15270 for (p = iflist; p; p = p->next) {
15271 if (p->owner) {
15272
15273 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15274 }
15275 }
15276 ast_mutex_unlock(&iflock);
15277 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15278 }
15279
15280
15281 dahdi_softhangup_all();
15282 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15283 destroy_all_channels();
15284 memset(round_robin, 0, sizeof(round_robin));
15285 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15286
15287 ast_mutex_unlock(&monlock);
15288
15289 #ifdef HAVE_PRI
15290 for (i = 0; i < NUM_SPANS; i++) {
15291 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15292 dahdi_close_pri_fd(&(pris[i]), j);
15293 }
15294
15295 memset(pris, 0, sizeof(pris));
15296 for (i = 0; i < NUM_SPANS; i++) {
15297 sig_pri_init_pri(&pris[i].pri);
15298 }
15299 pri_set_error(dahdi_pri_error);
15300 pri_set_message(dahdi_pri_message);
15301 #endif
15302 #if defined(HAVE_SS7)
15303 for (i = 0; i < NUM_SPANS; i++) {
15304 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15305 dahdi_close_ss7_fd(&(linksets[i]), j);
15306 }
15307
15308 memset(linksets, 0, sizeof(linksets));
15309 for (i = 0; i < NUM_SPANS; i++) {
15310 sig_ss7_init_linkset(&linksets[i].ss7);
15311 }
15312 ss7_set_error(dahdi_ss7_error);
15313 ss7_set_message(dahdi_ss7_message);
15314 #endif
15315
15316 if (setup_dahdi(2) != 0) {
15317 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15318 ast_mutex_unlock(&ss_thread_lock);
15319 return 1;
15320 }
15321 ast_mutex_unlock(&ss_thread_lock);
15322 ast_mutex_unlock(&restart_lock);
15323 return 0;
15324 }
15325
15326 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15327 {
15328 switch (cmd) {
15329 case CLI_INIT:
15330 e->command = "dahdi restart";
15331 e->usage =
15332 "Usage: dahdi restart\n"
15333 " Restarts the DAHDI channels: destroys them all and then\n"
15334 " re-reads them from chan_dahdi.conf.\n"
15335 " Note that this will STOP any running CALL on DAHDI channels.\n"
15336 "";
15337 return NULL;
15338 case CLI_GENERATE:
15339 return NULL;
15340 }
15341 if (a->argc != 2)
15342 return CLI_SHOWUSAGE;
15343
15344 if (dahdi_restart() != 0)
15345 return CLI_FAILURE;
15346 return CLI_SUCCESS;
15347 }
15348
15349 static int action_dahdirestart(struct mansession *s, const struct message *m)
15350 {
15351 if (dahdi_restart() != 0) {
15352 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15353 return 1;
15354 }
15355 astman_send_ack(s, m, "DAHDIRestart: Success");
15356 return 0;
15357 }
15358
15359 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15360 {
15361 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15362 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15363 ast_group_t targetnum = 0;
15364 int filtertype = 0;
15365 struct dahdi_pvt *tmp = NULL;
15366 char tmps[20] = "";
15367 char statestr[20] = "";
15368 char blockstr[20] = "";
15369
15370 switch (cmd) {
15371 case CLI_INIT:
15372 e->command = "dahdi show channels [group|context]";
15373 e->usage =
15374 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15375 " Shows a list of available channels with optional filtering\n"
15376 " <group> must be a number between 0 and 63\n";
15377 return NULL;
15378 case CLI_GENERATE:
15379 return NULL;
15380 }
15381
15382
15383
15384 if (!((a->argc == 3) || (a->argc == 5)))
15385 return CLI_SHOWUSAGE;
15386
15387 if (a->argc == 5) {
15388 if (!strcasecmp(a->argv[3], "group")) {
15389 targetnum = atoi(a->argv[4]);
15390 if (63 < targetnum) {
15391 return CLI_SHOWUSAGE;
15392 }
15393 targetnum = ((ast_group_t) 1) << targetnum;
15394 filtertype = 1;
15395 } else if (!strcasecmp(a->argv[3], "context")) {
15396 filtertype = 2;
15397 }
15398 }
15399
15400 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15401 ast_mutex_lock(&iflock);
15402 for (tmp = iflist; tmp; tmp = tmp->next) {
15403 if (filtertype) {
15404 switch(filtertype) {
15405 case 1:
15406 if (!(tmp->group & targetnum)) {
15407 continue;
15408 }
15409 break;
15410 case 2:
15411 if (strcasecmp(tmp->context, a->argv[4])) {
15412 continue;
15413 }
15414 break;
15415 default:
15416 break;
15417 }
15418 }
15419 if (tmp->channel > 0) {
15420 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15421 } else
15422 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15423
15424 if (tmp->locallyblocked)
15425 blockstr[0] = 'L';
15426 else
15427 blockstr[0] = ' ';
15428
15429 if (tmp->remotelyblocked)
15430 blockstr[1] = 'R';
15431 else
15432 blockstr[1] = ' ';
15433
15434 blockstr[2] = '\0';
15435
15436 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15437
15438 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15439 }
15440 ast_mutex_unlock(&iflock);
15441 return CLI_SUCCESS;
15442 #undef FORMAT
15443 #undef FORMAT2
15444 }
15445
15446 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15447 {
15448 int channel;
15449 struct dahdi_pvt *tmp = NULL;
15450 struct dahdi_confinfo ci;
15451 struct dahdi_params ps;
15452 int x;
15453
15454 switch (cmd) {
15455 case CLI_INIT:
15456 e->command = "dahdi show channel";
15457 e->usage =
15458 "Usage: dahdi show channel <chan num>\n"
15459 " Detailed information about a given channel\n";
15460 return NULL;
15461 case CLI_GENERATE:
15462 return NULL;
15463 }
15464
15465 if (a->argc != 4)
15466 return CLI_SHOWUSAGE;
15467
15468 channel = atoi(a->argv[3]);
15469
15470 ast_mutex_lock(&iflock);
15471 for (tmp = iflist; tmp; tmp = tmp->next) {
15472 if (tmp->channel == channel) {
15473 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15474 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15475 ast_cli(a->fd, "Span: %d\n", tmp->span);
15476 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15477 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15478 ast_cli(a->fd, "Context: %s\n", tmp->context);
15479 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15480 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15481 #if defined(HAVE_PRI)
15482 #if defined(HAVE_PRI_SUBADDR)
15483 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15484 #endif
15485 #endif
15486 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15487 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15488 if (tmp->vars) {
15489 struct ast_variable *v;
15490 ast_cli(a->fd, "Variables:\n");
15491 for (v = tmp->vars ; v ; v = v->next)
15492 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15493 }
15494 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15495 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15496 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15497 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15498 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15499 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)" : "");
15500 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)" : "");
15501 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)" : "");
15502 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15503 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15504 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15505 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15506 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15507 if (tmp->busydetect) {
15508 #if defined(BUSYDETECT_TONEONLY)
15509 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15510 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15511 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15512 #endif
15513 #ifdef BUSYDETECT_DEBUG
15514 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15515 #endif
15516 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15517 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15518 }
15519 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15520 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15521 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15522 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15523 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15524 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15525 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15526 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15527 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15528 ast_cli(a->fd, "Echo Cancellation:\n");
15529
15530 if (tmp->echocancel.head.tap_length) {
15531 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15532 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15533 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15534 }
15535 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15536 } else {
15537 ast_cli(a->fd, "\tnone\n");
15538 }
15539 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15540 if (tmp->master)
15541 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15542 for (x = 0; x < MAX_SLAVES; x++) {
15543 if (tmp->slaves[x])
15544 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15545 }
15546 #ifdef HAVE_OPENR2
15547 if (tmp->mfcr2) {
15548 char calldir[OR2_MAX_PATH];
15549 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15550 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15551 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15552 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15553 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15554 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15555 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15556 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15557 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15558 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15559 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15560 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15561 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15562 #endif
15563 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15564 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15565 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15566 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15567 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15568 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15569 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15570 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15571 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15572 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15573 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15574 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15575 }
15576 #endif
15577 #if defined(HAVE_SS7)
15578 if (tmp->ss7) {
15579 struct sig_ss7_chan *chan = tmp->sig_pvt;
15580
15581 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15582 }
15583 #endif
15584 #ifdef HAVE_PRI
15585 if (tmp->pri) {
15586 struct sig_pri_chan *chan = tmp->sig_pvt;
15587
15588 ast_cli(a->fd, "PRI Flags: ");
15589 if (chan->resetting != SIG_PRI_RESET_IDLE) {
15590 ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15591 }
15592 if (chan->call)
15593 ast_cli(a->fd, "Call ");
15594 if (chan->allocated) {
15595 ast_cli(a->fd, "Allocated ");
15596 }
15597 ast_cli(a->fd, "\n");
15598 if (tmp->logicalspan)
15599 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15600 else
15601 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15602 }
15603 #endif
15604 memset(&ci, 0, sizeof(ci));
15605 ps.channo = tmp->channel;
15606 if (tmp->subs[SUB_REAL].dfd > -1) {
15607 memset(&ci, 0, sizeof(ci));
15608 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15609 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15610 }
15611 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15612 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15613 }
15614 memset(&ps, 0, sizeof(ps));
15615 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15616 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15617 } else {
15618 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15619 }
15620 }
15621 ast_mutex_unlock(&iflock);
15622 return CLI_SUCCESS;
15623 }
15624 }
15625 ast_mutex_unlock(&iflock);
15626
15627 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15628 return CLI_FAILURE;
15629 }
15630
15631 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15632 {
15633 int i, j;
15634 switch (cmd) {
15635 case CLI_INIT:
15636 e->command = "dahdi show cadences";
15637 e->usage =
15638 "Usage: dahdi show cadences\n"
15639 " Shows all cadences currently defined\n";
15640 return NULL;
15641 case CLI_GENERATE:
15642 return NULL;
15643 }
15644 for (i = 0; i < num_cadence; i++) {
15645 char output[1024];
15646 char tmp[16], tmp2[64];
15647 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15648 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15649
15650 for (j = 0; j < 16; j++) {
15651 if (cadences[i].ringcadence[j] == 0)
15652 break;
15653 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15654 if (cidrings[i] * 2 - 1 == j)
15655 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15656 else
15657 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15658 if (j != 0)
15659 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15660 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15661 }
15662 ast_cli(a->fd,"%s\n",output);
15663 }
15664 return CLI_SUCCESS;
15665 }
15666
15667
15668 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15669 {
15670 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15671 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15672 int span;
15673 int res;
15674 char alarmstr[50];
15675
15676 int ctl;
15677 struct dahdi_spaninfo s;
15678
15679 switch (cmd) {
15680 case CLI_INIT:
15681 e->command = "dahdi show status";
15682 e->usage =
15683 "Usage: dahdi show status\n"
15684 " Shows a list of DAHDI cards with status\n";
15685 return NULL;
15686 case CLI_GENERATE:
15687 return NULL;
15688 }
15689 ctl = open("/dev/dahdi/ctl", O_RDWR);
15690 if (ctl < 0) {
15691 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15692 return CLI_FAILURE;
15693 }
15694 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15695
15696 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15697 s.spanno = span;
15698 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15699 if (res) {
15700 continue;
15701 }
15702 alarmstr[0] = '\0';
15703 if (s.alarms > 0) {
15704 if (s.alarms & DAHDI_ALARM_BLUE)
15705 strcat(alarmstr, "BLU/");
15706 if (s.alarms & DAHDI_ALARM_YELLOW)
15707 strcat(alarmstr, "YEL/");
15708 if (s.alarms & DAHDI_ALARM_RED)
15709 strcat(alarmstr, "RED/");
15710 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15711 strcat(alarmstr, "LB/");
15712 if (s.alarms & DAHDI_ALARM_RECOVER)
15713 strcat(alarmstr, "REC/");
15714 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15715 strcat(alarmstr, "NOP/");
15716 if (!strlen(alarmstr))
15717 strcat(alarmstr, "UUU/");
15718 if (strlen(alarmstr)) {
15719
15720 alarmstr[strlen(alarmstr) - 1] = '\0';
15721 }
15722 } else {
15723 if (s.numchans)
15724 strcpy(alarmstr, "OK");
15725 else
15726 strcpy(alarmstr, "UNCONFIGURED");
15727 }
15728
15729 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15730 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15731 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15732 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15733 "CAS",
15734 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15735 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15736 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15737 "Unk",
15738 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15739 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15740 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15741 lbostr[s.lbo]
15742 );
15743 }
15744 close(ctl);
15745
15746 return CLI_SUCCESS;
15747 #undef FORMAT
15748 #undef FORMAT2
15749 }
15750
15751 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15752 {
15753 int pseudo_fd = -1;
15754 struct dahdi_versioninfo vi;
15755
15756 switch (cmd) {
15757 case CLI_INIT:
15758 e->command = "dahdi show version";
15759 e->usage =
15760 "Usage: dahdi show version\n"
15761 " Shows the DAHDI version in use\n";
15762 return NULL;
15763 case CLI_GENERATE:
15764 return NULL;
15765 }
15766 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15767 ast_cli(a->fd, "Failed to open control file to get version.\n");
15768 return CLI_SUCCESS;
15769 }
15770
15771 strcpy(vi.version, "Unknown");
15772 strcpy(vi.echo_canceller, "Unknown");
15773
15774 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15775 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15776 else
15777 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15778
15779 close(pseudo_fd);
15780
15781 return CLI_SUCCESS;
15782 }
15783
15784 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15785 {
15786 int channel;
15787 int gain;
15788 int tx;
15789 struct dahdi_hwgain hwgain;
15790 struct dahdi_pvt *tmp = NULL;
15791
15792 switch (cmd) {
15793 case CLI_INIT:
15794 e->command = "dahdi set hwgain {rx|tx}";
15795 e->usage =
15796 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15797 " Sets the hardware gain on a given channel. Changes take effect\n"
15798 " immediately whether the channel is in use or not.\n"
15799 "\n"
15800 " <rx|tx> which direction do you want to change (relative to our module)\n"
15801 " <chan num> is the channel number relative to the device\n"
15802 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15803 "\n"
15804 " Please note:\n"
15805 " * This is currently the only way to set hwgain by the channel driver.\n"
15806 " * hwgain is only supportable by hardware with analog ports because\n"
15807 " hwgain works on the analog side of an analog-digital conversion.\n";
15808 return NULL;
15809 case CLI_GENERATE:
15810 return NULL;
15811 }
15812
15813 if (a->argc != 6)
15814 return CLI_SHOWUSAGE;
15815
15816 if (!strcasecmp("rx", a->argv[3]))
15817 tx = 0;
15818 else if (!strcasecmp("tx", a->argv[3]))
15819 tx = 1;
15820 else
15821 return CLI_SHOWUSAGE;
15822
15823 channel = atoi(a->argv[4]);
15824 gain = atof(a->argv[5])*10.0;
15825
15826 ast_mutex_lock(&iflock);
15827
15828 for (tmp = iflist; tmp; tmp = tmp->next) {
15829
15830 if (tmp->channel != channel)
15831 continue;
15832
15833 if (tmp->subs[SUB_REAL].dfd == -1)
15834 break;
15835
15836 hwgain.newgain = gain;
15837 hwgain.tx = tx;
15838 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15839 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15840 ast_mutex_unlock(&iflock);
15841 return CLI_FAILURE;
15842 }
15843 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15844 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15845 break;
15846 }
15847
15848 ast_mutex_unlock(&iflock);
15849
15850 if (tmp)
15851 return CLI_SUCCESS;
15852
15853 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15854 return CLI_FAILURE;
15855
15856 }
15857
15858 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15859 {
15860 int channel;
15861 float gain;
15862 int tx;
15863 int res;
15864 struct dahdi_pvt *tmp = NULL;
15865
15866 switch (cmd) {
15867 case CLI_INIT:
15868 e->command = "dahdi set swgain {rx|tx}";
15869 e->usage =
15870 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15871 " Sets the software gain on a given channel and overrides the\n"
15872 " value provided at module loadtime. Changes take effect\n"
15873 " immediately whether the channel is in use or not.\n"
15874 "\n"
15875 " <rx|tx> which direction do you want to change (relative to our module)\n"
15876 " <chan num> is the channel number relative to the device\n"
15877 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15878 return NULL;
15879 case CLI_GENERATE:
15880 return NULL;
15881 }
15882
15883 if (a->argc != 6)
15884 return CLI_SHOWUSAGE;
15885
15886 if (!strcasecmp("rx", a->argv[3]))
15887 tx = 0;
15888 else if (!strcasecmp("tx", a->argv[3]))
15889 tx = 1;
15890 else
15891 return CLI_SHOWUSAGE;
15892
15893 channel = atoi(a->argv[4]);
15894 gain = atof(a->argv[5]);
15895
15896 ast_mutex_lock(&iflock);
15897 for (tmp = iflist; tmp; tmp = tmp->next) {
15898
15899 if (tmp->channel != channel)
15900 continue;
15901
15902 if (tmp->subs[SUB_REAL].dfd == -1)
15903 break;
15904
15905 if (tx)
15906 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15907 else
15908 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15909
15910 if (res) {
15911 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15912 ast_mutex_unlock(&iflock);
15913 return CLI_FAILURE;
15914 }
15915
15916 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15917 tx ? "tx" : "rx", gain, channel);
15918
15919 if (tx) {
15920 tmp->txgain = gain;
15921 } else {
15922 tmp->rxgain = gain;
15923 }
15924 break;
15925 }
15926 ast_mutex_unlock(&iflock);
15927
15928 if (tmp)
15929 return CLI_SUCCESS;
15930
15931 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15932 return CLI_FAILURE;
15933
15934 }
15935
15936 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15937 {
15938 int channel;
15939 int on;
15940 struct dahdi_pvt *dahdi_chan = NULL;
15941
15942 switch (cmd) {
15943 case CLI_INIT:
15944 e->command = "dahdi set dnd";
15945 e->usage =
15946 "Usage: dahdi set dnd <chan#> <on|off>\n"
15947 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15948 " Changes take effect immediately.\n"
15949 " <chan num> is the channel number\n"
15950 " <on|off> Enable or disable DND mode?\n"
15951 ;
15952 return NULL;
15953 case CLI_GENERATE:
15954 return NULL;
15955 }
15956
15957 if (a->argc != 5)
15958 return CLI_SHOWUSAGE;
15959
15960 if ((channel = atoi(a->argv[3])) <= 0) {
15961 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15962 return CLI_SHOWUSAGE;
15963 }
15964
15965 if (ast_true(a->argv[4]))
15966 on = 1;
15967 else if (ast_false(a->argv[4]))
15968 on = 0;
15969 else {
15970 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15971 return CLI_SHOWUSAGE;
15972 }
15973
15974 ast_mutex_lock(&iflock);
15975 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15976 if (dahdi_chan->channel != channel)
15977 continue;
15978
15979
15980 dahdi_dnd(dahdi_chan, on);
15981 break;
15982 }
15983 ast_mutex_unlock(&iflock);
15984
15985 if (!dahdi_chan) {
15986 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15987 return CLI_FAILURE;
15988 }
15989
15990 return CLI_SUCCESS;
15991 }
15992
15993 static struct ast_cli_entry dahdi_cli[] = {
15994 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15995 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15996 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15997 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15998 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15999 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16000 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16001 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16002 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16003 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16004 };
16005
16006 #define TRANSFER 0
16007 #define HANGUP 1
16008
16009 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16010 {
16011 if (p) {
16012 switch (mode) {
16013 case TRANSFER:
16014 p->fake_event = DAHDI_EVENT_WINKFLASH;
16015 break;
16016 case HANGUP:
16017 p->fake_event = DAHDI_EVENT_ONHOOK;
16018 break;
16019 default:
16020 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16021 }
16022 }
16023 return 0;
16024 }
16025 static struct dahdi_pvt *find_channel(int channel)
16026 {
16027 struct dahdi_pvt *p;
16028
16029 ast_mutex_lock(&iflock);
16030 for (p = iflist; p; p = p->next) {
16031 if (p->channel == channel) {
16032 break;
16033 }
16034 }
16035 ast_mutex_unlock(&iflock);
16036 return p;
16037 }
16038
16039
16040
16041
16042
16043
16044
16045
16046
16047
16048 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16049 {
16050 int chan_num;
16051
16052 if (sscanf(channel, "%30d", &chan_num) != 1) {
16053
16054 return NULL;
16055 }
16056
16057 return find_channel(chan_num);
16058 }
16059
16060 static int action_dahdidndon(struct mansession *s, const struct message *m)
16061 {
16062 struct dahdi_pvt *p;
16063 const char *channel = astman_get_header(m, "DAHDIChannel");
16064
16065 if (ast_strlen_zero(channel)) {
16066 astman_send_error(s, m, "No channel specified");
16067 return 0;
16068 }
16069 p = find_channel_from_str(channel);
16070 if (!p) {
16071 astman_send_error(s, m, "No such channel");
16072 return 0;
16073 }
16074 dahdi_dnd(p, 1);
16075 astman_send_ack(s, m, "DND Enabled");
16076 return 0;
16077 }
16078
16079 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16080 {
16081 struct dahdi_pvt *p;
16082 const char *channel = astman_get_header(m, "DAHDIChannel");
16083
16084 if (ast_strlen_zero(channel)) {
16085 astman_send_error(s, m, "No channel specified");
16086 return 0;
16087 }
16088 p = find_channel_from_str(channel);
16089 if (!p) {
16090 astman_send_error(s, m, "No such channel");
16091 return 0;
16092 }
16093 dahdi_dnd(p, 0);
16094 astman_send_ack(s, m, "DND Disabled");
16095 return 0;
16096 }
16097
16098 static int action_transfer(struct mansession *s, const struct message *m)
16099 {
16100 struct dahdi_pvt *p;
16101 const char *channel = astman_get_header(m, "DAHDIChannel");
16102
16103 if (ast_strlen_zero(channel)) {
16104 astman_send_error(s, m, "No channel specified");
16105 return 0;
16106 }
16107 p = find_channel_from_str(channel);
16108 if (!p) {
16109 astman_send_error(s, m, "No such channel");
16110 return 0;
16111 }
16112 if (!analog_lib_handles(p->sig, 0, 0)) {
16113 astman_send_error(s, m, "Channel signaling is not analog");
16114 return 0;
16115 }
16116 dahdi_fake_event(p,TRANSFER);
16117 astman_send_ack(s, m, "DAHDITransfer");
16118 return 0;
16119 }
16120
16121 static int action_transferhangup(struct mansession *s, const struct message *m)
16122 {
16123 struct dahdi_pvt *p;
16124 const char *channel = astman_get_header(m, "DAHDIChannel");
16125
16126 if (ast_strlen_zero(channel)) {
16127 astman_send_error(s, m, "No channel specified");
16128 return 0;
16129 }
16130 p = find_channel_from_str(channel);
16131 if (!p) {
16132 astman_send_error(s, m, "No such channel");
16133 return 0;
16134 }
16135 if (!analog_lib_handles(p->sig, 0, 0)) {
16136 astman_send_error(s, m, "Channel signaling is not analog");
16137 return 0;
16138 }
16139 dahdi_fake_event(p,HANGUP);
16140 astman_send_ack(s, m, "DAHDIHangup");
16141 return 0;
16142 }
16143
16144 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16145 {
16146 struct dahdi_pvt *p;
16147 const char *channel = astman_get_header(m, "DAHDIChannel");
16148 const char *number = astman_get_header(m, "Number");
16149 int i;
16150
16151 if (ast_strlen_zero(channel)) {
16152 astman_send_error(s, m, "No channel specified");
16153 return 0;
16154 }
16155 if (ast_strlen_zero(number)) {
16156 astman_send_error(s, m, "No number specified");
16157 return 0;
16158 }
16159 p = find_channel_from_str(channel);
16160 if (!p) {
16161 astman_send_error(s, m, "No such channel");
16162 return 0;
16163 }
16164 if (!p->owner) {
16165 astman_send_error(s, m, "Channel does not have it's owner");
16166 return 0;
16167 }
16168 for (i = 0; i < strlen(number); i++) {
16169 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16170 dahdi_queue_frame(p, &f);
16171 }
16172 astman_send_ack(s, m, "DAHDIDialOffhook");
16173 return 0;
16174 }
16175
16176 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16177 {
16178 struct dahdi_pvt *tmp = NULL;
16179 const char *id = astman_get_header(m, "ActionID");
16180 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16181 char idText[256] = "";
16182 int channels = 0;
16183 int dahdichanquery;
16184
16185 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16186
16187 dahdichanquery = -1;
16188 }
16189
16190 astman_send_ack(s, m, "DAHDI channel status will follow");
16191 if (!ast_strlen_zero(id))
16192 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16193
16194 ast_mutex_lock(&iflock);
16195
16196 for (tmp = iflist; tmp; tmp = tmp->next) {
16197 if (tmp->channel > 0) {
16198 int alm;
16199
16200
16201 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16202 continue;
16203
16204 alm = get_alarms(tmp);
16205 channels++;
16206 if (tmp->owner) {
16207
16208 astman_append(s,
16209 "Event: DAHDIShowChannels\r\n"
16210 "DAHDIChannel: %d\r\n"
16211 "Channel: %s\r\n"
16212 "Uniqueid: %s\r\n"
16213 "AccountCode: %s\r\n"
16214 "Signalling: %s\r\n"
16215 "SignallingCode: %d\r\n"
16216 "Context: %s\r\n"
16217 "DND: %s\r\n"
16218 "Alarm: %s\r\n"
16219 "%s"
16220 "\r\n",
16221 tmp->channel,
16222 tmp->owner->name,
16223 tmp->owner->uniqueid,
16224 tmp->owner->accountcode,
16225 sig2str(tmp->sig),
16226 tmp->sig,
16227 tmp->context,
16228 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16229 alarm2str(alm), idText);
16230 } else {
16231 astman_append(s,
16232 "Event: DAHDIShowChannels\r\n"
16233 "DAHDIChannel: %d\r\n"
16234 "Signalling: %s\r\n"
16235 "SignallingCode: %d\r\n"
16236 "Context: %s\r\n"
16237 "DND: %s\r\n"
16238 "Alarm: %s\r\n"
16239 "%s"
16240 "\r\n",
16241 tmp->channel, sig2str(tmp->sig), tmp->sig,
16242 tmp->context,
16243 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16244 alarm2str(alm), idText);
16245 }
16246 }
16247 }
16248
16249 ast_mutex_unlock(&iflock);
16250
16251 astman_append(s,
16252 "Event: DAHDIShowChannelsComplete\r\n"
16253 "%s"
16254 "Items: %d\r\n"
16255 "\r\n",
16256 idText,
16257 channels);
16258 return 0;
16259 }
16260
16261 #if defined(HAVE_SS7)
16262 static int linkset_addsigchan(int sigchan)
16263 {
16264 struct dahdi_ss7 *link;
16265 int res;
16266 int curfd;
16267 struct dahdi_params params;
16268 struct dahdi_bufferinfo bi;
16269 struct dahdi_spaninfo si;
16270
16271 if (sigchan < 0) {
16272 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16273 return -1;
16274 }
16275 if (cur_ss7type < 0) {
16276 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16277 return -1;
16278 }
16279 if (cur_pointcode < 0) {
16280 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16281 return -1;
16282 }
16283 if (cur_adjpointcode < 0) {
16284 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16285 return -1;
16286 }
16287 if (cur_defaultdpc < 0) {
16288 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16289 return -1;
16290 }
16291 if (cur_networkindicator < 0) {
16292 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16293 return -1;
16294 }
16295 link = ss7_resolve_linkset(cur_linkset);
16296 if (!link) {
16297 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16298 return -1;
16299 }
16300 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16301 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16302 return -1;
16303 }
16304
16305 curfd = link->ss7.numsigchans;
16306
16307
16308 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16309 if (link->ss7.fds[curfd] < 0) {
16310 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16311 strerror(errno));
16312 return -1;
16313 }
16314 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16315 dahdi_close_ss7_fd(link, curfd);
16316 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16317 strerror(errno));
16318 return -1;
16319 }
16320
16321
16322 memset(¶ms, 0, sizeof(params));
16323 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16324 if (res) {
16325 dahdi_close_ss7_fd(link, curfd);
16326 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16327 strerror(errno));
16328 return -1;
16329 }
16330 if (params.sigtype != DAHDI_SIG_HDLCFCS
16331 && params.sigtype != DAHDI_SIG_HARDHDLC
16332 && params.sigtype != DAHDI_SIG_MTP2) {
16333 dahdi_close_ss7_fd(link, curfd);
16334 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16335 return -1;
16336 }
16337
16338
16339 memset(&bi, 0, sizeof(bi));
16340 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16341 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16342 bi.numbufs = 32;
16343 bi.bufsize = 512;
16344 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16345 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16346 sigchan, strerror(errno));
16347 dahdi_close_ss7_fd(link, curfd);
16348 return -1;
16349 }
16350
16351
16352 memset(&si, 0, sizeof(si));
16353 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16354 if (res) {
16355 dahdi_close_ss7_fd(link, curfd);
16356 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16357 strerror(errno));
16358 }
16359
16360 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16361 (params.sigtype == DAHDI_SIG_MTP2)
16362 ? SS7_TRANSPORT_DAHDIMTP2
16363 : SS7_TRANSPORT_DAHDIDCHAN,
16364 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16365 if (res) {
16366 dahdi_close_ss7_fd(link, curfd);
16367 return -1;
16368 }
16369
16370 ++link->ss7.numsigchans;
16371
16372 return 0;
16373 }
16374 #endif
16375
16376 #if defined(HAVE_SS7)
16377 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16378 {
16379 int span;
16380 switch (cmd) {
16381 case CLI_INIT:
16382 e->command = "ss7 set debug {on|off} linkset";
16383 e->usage =
16384 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16385 " Enables debugging on a given SS7 linkset\n";
16386 return NULL;
16387 case CLI_GENERATE:
16388 return NULL;
16389 }
16390 if (a->argc < 6)
16391 return CLI_SHOWUSAGE;
16392 span = atoi(a->argv[5]);
16393 if ((span < 1) || (span > NUM_SPANS)) {
16394 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16395 return CLI_SUCCESS;
16396 }
16397 if (!linksets[span-1].ss7.ss7) {
16398 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16399 } else {
16400 if (!strcasecmp(a->argv[3], "on")) {
16401 linksets[span - 1].ss7.debug = 1;
16402 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16403 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16404 } else {
16405 linksets[span - 1].ss7.debug = 0;
16406 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16407 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16408 }
16409 }
16410
16411 return CLI_SUCCESS;
16412 }
16413 #endif
16414
16415 #if defined(HAVE_SS7)
16416 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16417 {
16418 int linkset, cic;
16419 int blocked = -1, i;
16420 switch (cmd) {
16421 case CLI_INIT:
16422 e->command = "ss7 block cic";
16423 e->usage =
16424 "Usage: ss7 block cic <linkset> <CIC>\n"
16425 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16426 return NULL;
16427 case CLI_GENERATE:
16428 return NULL;
16429 }
16430 if (a->argc == 5)
16431 linkset = atoi(a->argv[3]);
16432 else
16433 return CLI_SHOWUSAGE;
16434
16435 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16436 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16437 return CLI_SUCCESS;
16438 }
16439
16440 if (!linksets[linkset-1].ss7.ss7) {
16441 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16442 return CLI_SUCCESS;
16443 }
16444
16445 cic = atoi(a->argv[4]);
16446
16447 if (cic < 1) {
16448 ast_cli(a->fd, "Invalid CIC specified!\n");
16449 return CLI_SUCCESS;
16450 }
16451
16452 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16453 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16454 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16455 if (!blocked) {
16456 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16457 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16458 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16459 }
16460 }
16461 }
16462
16463 if (blocked < 0) {
16464 ast_cli(a->fd, "Invalid CIC specified!\n");
16465 return CLI_SUCCESS;
16466 }
16467
16468 if (!blocked)
16469 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16470 else
16471 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16472
16473
16474 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16475
16476 return CLI_SUCCESS;
16477 }
16478 #endif
16479
16480 #if defined(HAVE_SS7)
16481 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16482 {
16483 int linkset;
16484 int i;
16485 switch (cmd) {
16486 case CLI_INIT:
16487 e->command = "ss7 block linkset";
16488 e->usage =
16489 "Usage: ss7 block linkset <linkset number>\n"
16490 " Sends a remote blocking request for all CICs on the given linkset\n";
16491 return NULL;
16492 case CLI_GENERATE:
16493 return NULL;
16494 }
16495 if (a->argc == 4)
16496 linkset = atoi(a->argv[3]);
16497 else
16498 return CLI_SHOWUSAGE;
16499
16500 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16501 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16502 return CLI_SUCCESS;
16503 }
16504
16505 if (!linksets[linkset-1].ss7.ss7) {
16506 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16507 return CLI_SUCCESS;
16508 }
16509
16510 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16511 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16512 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16513 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16514 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16515 }
16516
16517
16518 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16519
16520 return CLI_SUCCESS;
16521 }
16522 #endif
16523
16524 #if defined(HAVE_SS7)
16525 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16526 {
16527 int linkset, cic;
16528 int i, blocked = -1;
16529 switch (cmd) {
16530 case CLI_INIT:
16531 e->command = "ss7 unblock cic";
16532 e->usage =
16533 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16534 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16535 return NULL;
16536 case CLI_GENERATE:
16537 return NULL;
16538 }
16539
16540 if (a->argc == 5)
16541 linkset = atoi(a->argv[3]);
16542 else
16543 return CLI_SHOWUSAGE;
16544
16545 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16546 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16547 return CLI_SUCCESS;
16548 }
16549
16550 if (!linksets[linkset-1].ss7.ss7) {
16551 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16552 return CLI_SUCCESS;
16553 }
16554
16555 cic = atoi(a->argv[4]);
16556
16557 if (cic < 1) {
16558 ast_cli(a->fd, "Invalid CIC specified!\n");
16559 return CLI_SUCCESS;
16560 }
16561
16562 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16563 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16564 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16565 if (blocked) {
16566 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16567 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16568 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16569 }
16570 }
16571 }
16572
16573 if (blocked > 0)
16574 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16575
16576
16577 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16578
16579 return CLI_SUCCESS;
16580 }
16581 #endif
16582
16583 #if defined(HAVE_SS7)
16584 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16585 {
16586 int linkset;
16587 int i;
16588 switch (cmd) {
16589 case CLI_INIT:
16590 e->command = "ss7 unblock linkset";
16591 e->usage =
16592 "Usage: ss7 unblock linkset <linkset number>\n"
16593 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16594 return NULL;
16595 case CLI_GENERATE:
16596 return NULL;
16597 }
16598
16599 if (a->argc == 4)
16600 linkset = atoi(a->argv[3]);
16601 else
16602 return CLI_SHOWUSAGE;
16603
16604 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16605 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16606 return CLI_SUCCESS;
16607 }
16608
16609 if (!linksets[linkset-1].ss7.ss7) {
16610 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16611 return CLI_SUCCESS;
16612 }
16613
16614 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16615 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16616 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16617 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16618 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16619 }
16620
16621
16622 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16623
16624 return CLI_SUCCESS;
16625 }
16626 #endif
16627
16628 #if defined(HAVE_SS7)
16629 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16630 {
16631 int linkset;
16632 struct sig_ss7_linkset *ss7;
16633 switch (cmd) {
16634 case CLI_INIT:
16635 e->command = "ss7 show linkset";
16636 e->usage =
16637 "Usage: ss7 show linkset <span>\n"
16638 " Shows the status of an SS7 linkset.\n";
16639 return NULL;
16640 case CLI_GENERATE:
16641 return NULL;
16642 }
16643
16644 if (a->argc < 4)
16645 return CLI_SHOWUSAGE;
16646 linkset = atoi(a->argv[3]);
16647 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16648 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16649 return CLI_SUCCESS;
16650 }
16651 ss7 = &linksets[linkset - 1].ss7;
16652 if (!ss7->ss7) {
16653 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16654 return CLI_SUCCESS;
16655 }
16656
16657 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16658
16659 return CLI_SUCCESS;
16660 }
16661 #endif
16662
16663 #if defined(HAVE_SS7)
16664 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16665 {
16666 int linkset;
16667
16668 switch (cmd) {
16669 case CLI_INIT:
16670 e->command = "ss7 show channels";
16671 e->usage =
16672 "Usage: ss7 show channels\n"
16673 " Displays SS7 channel information at a glance.\n";
16674 return NULL;
16675 case CLI_GENERATE:
16676 return NULL;
16677 }
16678
16679 if (a->argc != 3)
16680 return CLI_SHOWUSAGE;
16681
16682 sig_ss7_cli_show_channels_header(a->fd);
16683 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16684 if (linksets[linkset].ss7.ss7) {
16685 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16686 }
16687 }
16688 return CLI_SUCCESS;
16689 }
16690 #endif
16691
16692 #if defined(HAVE_SS7)
16693 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16694 {
16695 switch (cmd) {
16696 case CLI_INIT:
16697 e->command = "ss7 show version";
16698 e->usage =
16699 "Usage: ss7 show version\n"
16700 " Show the libss7 version\n";
16701 return NULL;
16702 case CLI_GENERATE:
16703 return NULL;
16704 }
16705
16706 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16707
16708 return CLI_SUCCESS;
16709 }
16710 #endif
16711
16712 #if defined(HAVE_SS7)
16713 static struct ast_cli_entry dahdi_ss7_cli[] = {
16714 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16715 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16716 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16717 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16718 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16719 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16720 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16721 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16722 };
16723 #endif
16724
16725 #if defined(HAVE_PRI)
16726 #if defined(HAVE_PRI_CCSS)
16727
16728
16729
16730
16731
16732
16733
16734
16735
16736
16737
16738
16739
16740
16741
16742
16743
16744 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16745 {
16746 struct dahdi_pvt *pvt;
16747 struct sig_pri_chan *pvt_chan;
16748 int res;
16749
16750 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16751
16752 pvt = chan->tech_pvt;
16753 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16754 pvt_chan = pvt->sig_pvt;
16755 } else {
16756 pvt_chan = NULL;
16757 }
16758 if (!pvt_chan) {
16759 return -1;
16760 }
16761
16762 ast_module_ref(ast_module_info->self);
16763
16764 res = sig_pri_cc_agent_init(agent, pvt_chan);
16765 if (res) {
16766 ast_module_unref(ast_module_info->self);
16767 }
16768 return res;
16769 }
16770 #endif
16771 #endif
16772
16773 #if defined(HAVE_PRI)
16774 #if defined(HAVE_PRI_CCSS)
16775
16776
16777
16778
16779
16780
16781
16782
16783
16784
16785
16786
16787
16788 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16789 {
16790 sig_pri_cc_agent_destructor(agent);
16791
16792 ast_module_unref(ast_module_info->self);
16793 }
16794 #endif
16795 #endif
16796
16797 #if defined(HAVE_PRI)
16798 #if defined(HAVE_PRI_CCSS)
16799 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16800 .type = dahdi_pri_cc_type,
16801 .init = dahdi_pri_cc_agent_init,
16802 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16803 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16804 .respond = sig_pri_cc_agent_req_rsp,
16805 .status_request = sig_pri_cc_agent_status_req,
16806 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16807 .party_b_free = sig_pri_cc_agent_party_b_free,
16808 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16809 .callee_available = sig_pri_cc_agent_callee_available,
16810 .destructor = dahdi_pri_cc_agent_destructor,
16811 };
16812 #endif
16813 #endif
16814
16815 #if defined(HAVE_PRI)
16816 #if defined(HAVE_PRI_CCSS)
16817 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16818 .type = dahdi_pri_cc_type,
16819 .request_cc = sig_pri_cc_monitor_req_cc,
16820 .suspend = sig_pri_cc_monitor_suspend,
16821 .unsuspend = sig_pri_cc_monitor_unsuspend,
16822 .status_response = sig_pri_cc_monitor_status_rsp,
16823 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16824 .destructor = sig_pri_cc_monitor_destructor,
16825 };
16826 #endif
16827 #endif
16828
16829 static int __unload_module(void)
16830 {
16831 struct dahdi_pvt *p;
16832 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16833 int i, j;
16834 #endif
16835
16836 #ifdef HAVE_PRI
16837 for (i = 0; i < NUM_SPANS; i++) {
16838 if (pris[i].pri.master != AST_PTHREADT_NULL) {
16839 pthread_cancel(pris[i].pri.master);
16840 pthread_kill(pris[i].pri.master, SIGURG);
16841 }
16842 }
16843 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16844 ast_unregister_application(dahdi_send_keypad_facility_app);
16845 #ifdef HAVE_PRI_PROG_W_CAUSE
16846 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16847 #endif
16848 #endif
16849 #if defined(HAVE_SS7)
16850 for (i = 0; i < NUM_SPANS; i++) {
16851 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16852 pthread_cancel(linksets[i].ss7.master);
16853 pthread_kill(linksets[i].ss7.master, SIGURG);
16854 }
16855 }
16856 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16857 #endif
16858 #if defined(HAVE_OPENR2)
16859 dahdi_r2_destroy_links();
16860 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16861 ast_unregister_application(dahdi_accept_r2_call_app);
16862 #endif
16863
16864 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16865 ast_manager_unregister("DAHDIDialOffhook");
16866 ast_manager_unregister("DAHDIHangup");
16867 ast_manager_unregister("DAHDITransfer");
16868 ast_manager_unregister("DAHDIDNDoff");
16869 ast_manager_unregister("DAHDIDNDon");
16870 ast_manager_unregister("DAHDIShowChannels");
16871 ast_manager_unregister("DAHDIRestart");
16872 ast_data_unregister(NULL);
16873 ast_channel_unregister(&dahdi_tech);
16874
16875
16876 ast_mutex_lock(&iflock);
16877 for (p = iflist; p; p = p->next) {
16878 if (p->owner)
16879 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16880 }
16881 ast_mutex_unlock(&iflock);
16882
16883 ast_mutex_lock(&monlock);
16884 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16885 pthread_cancel(monitor_thread);
16886 pthread_kill(monitor_thread, SIGURG);
16887 pthread_join(monitor_thread, NULL);
16888 }
16889 monitor_thread = AST_PTHREADT_STOP;
16890 ast_mutex_unlock(&monlock);
16891
16892 destroy_all_channels();
16893
16894 #if defined(HAVE_PRI)
16895 for (i = 0; i < NUM_SPANS; i++) {
16896 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16897 pthread_join(pris[i].pri.master, NULL);
16898 }
16899 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16900 dahdi_close_pri_fd(&(pris[i]), j);
16901 }
16902 sig_pri_stop_pri(&pris[i].pri);
16903 }
16904 #if defined(HAVE_PRI_CCSS)
16905 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16906 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16907 #endif
16908 sig_pri_unload();
16909 #endif
16910
16911 #if defined(HAVE_SS7)
16912 for (i = 0; i < NUM_SPANS; i++) {
16913 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16914 pthread_join(linksets[i].ss7.master, NULL);
16915 }
16916 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16917 dahdi_close_ss7_fd(&(linksets[i]), j);
16918 }
16919 }
16920 #endif
16921 ast_cond_destroy(&ss_thread_complete);
16922 return 0;
16923 }
16924
16925 static int unload_module(void)
16926 {
16927 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16928 int y;
16929 #endif
16930 #ifdef HAVE_PRI
16931 for (y = 0; y < NUM_SPANS; y++)
16932 ast_mutex_destroy(&pris[y].pri.lock);
16933 #endif
16934 #if defined(HAVE_SS7)
16935 for (y = 0; y < NUM_SPANS; y++)
16936 ast_mutex_destroy(&linksets[y].ss7.lock);
16937 #endif
16938 return __unload_module();
16939 }
16940
16941 static void string_replace(char *str, int char1, int char2)
16942 {
16943 for (; *str; str++) {
16944 if (*str == char1) {
16945 *str = char2;
16946 }
16947 }
16948 }
16949
16950 static char *parse_spanchan(char *chanstr, char **subdir)
16951 {
16952 char *p;
16953
16954 if ((p = strrchr(chanstr, '!')) == NULL) {
16955 *subdir = NULL;
16956 return chanstr;
16957 }
16958 *p++ = '\0';
16959 string_replace(chanstr, '!', '/');
16960 *subdir = chanstr;
16961 return p;
16962 }
16963
16964 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16965 {
16966 char *c, *chan;
16967 char *subdir;
16968 int x, start, finish;
16969 struct dahdi_pvt *tmp;
16970
16971 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16972 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16973 return -1;
16974 }
16975
16976 c = ast_strdupa(value);
16977 c = parse_spanchan(c, &subdir);
16978
16979 while ((chan = strsep(&c, ","))) {
16980 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16981
16982 } else if (sscanf(chan, "%30d", &start)) {
16983
16984 finish = start;
16985 } else if (!strcasecmp(chan, "pseudo")) {
16986 finish = start = CHAN_PSEUDO;
16987 if (found_pseudo)
16988 *found_pseudo = 1;
16989 } else {
16990 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16991 return -1;
16992 }
16993 if (finish < start) {
16994 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16995 x = finish;
16996 finish = start;
16997 start = x;
16998 }
16999
17000 for (x = start; x <= finish; x++) {
17001 char fn[PATH_MAX];
17002 int real_channel = x;
17003
17004 if (!ast_strlen_zero(subdir)) {
17005 real_channel = device2chan(subdir, x, fn, sizeof(fn));
17006 if (real_channel < 0) {
17007 if (conf->ignore_failed_channels) {
17008 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17009 subdir, x, real_channel);
17010 continue;
17011 } else {
17012 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17013 subdir, x, real_channel);
17014 return -1;
17015 }
17016 }
17017 }
17018 tmp = mkintf(real_channel, conf, reload);
17019
17020 if (tmp) {
17021 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17022 } else {
17023 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17024 (reload == 1) ? "reconfigure" : "register", value);
17025 return -1;
17026 }
17027 }
17028 }
17029
17030 return 0;
17031 }
17032
17033
17034
17035 #define MAX_CHANLIST_LEN 80
17036
17037 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17038 {
17039 char *parse = ast_strdupa(data);
17040 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17041 unsigned int param_count;
17042 unsigned int x;
17043
17044 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17045 return;
17046
17047 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17048
17049
17050
17051 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17052
17053 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17054 confp->chan.echocancel.head.tap_length = x;
17055 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17056 confp->chan.echocancel.head.tap_length = 128;
17057
17058
17059
17060 for (x = 1; x < param_count; x++) {
17061 struct {
17062 char *name;
17063 char *value;
17064 } param;
17065
17066 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
17067 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
17068 continue;
17069 }
17070
17071 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17072 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
17073 continue;
17074 }
17075
17076 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17077
17078 if (param.value) {
17079 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17080 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
17081 continue;
17082 }
17083 }
17084 confp->chan.echocancel.head.param_count++;
17085 }
17086 }
17087
17088
17089 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
17090
17091 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
17092
17093 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17094 {
17095 struct dahdi_pvt *tmp;
17096 int y;
17097 int found_pseudo = 0;
17098 struct ast_variable *dahdichan = NULL;
17099
17100 for (; v; v = v->next) {
17101 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17102 continue;
17103
17104
17105 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17106 if (options & PROC_DAHDI_OPT_NOCHAN) {
17107 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17108 continue;
17109 }
17110 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17111 if (confp->ignore_failed_channels) {
17112 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17113 continue;
17114 } else {
17115 return -1;
17116 }
17117 }
17118 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17119 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17120 confp->ignore_failed_channels = ast_true(v->value);
17121 } else if (!strcasecmp(v->name, "buffers")) {
17122 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17123 ast_log(LOG_WARNING, "Using default buffer policy.\n");
17124 confp->chan.buf_no = numbufs;
17125 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17126 }
17127 } else if (!strcasecmp(v->name, "faxbuffers")) {
17128 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17129 confp->chan.usefaxbuffers = 1;
17130 }
17131 } else if (!strcasecmp(v->name, "dahdichan")) {
17132
17133 dahdichan = v;
17134 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17135 usedistinctiveringdetection = ast_true(v->value);
17136 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17137 distinctiveringaftercid = ast_true(v->value);
17138 } else if (!strcasecmp(v->name, "dring1context")) {
17139 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17140 } else if (!strcasecmp(v->name, "dring2context")) {
17141 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17142 } else if (!strcasecmp(v->name, "dring3context")) {
17143 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17144 } else if (!strcasecmp(v->name, "dring1range")) {
17145 confp->chan.drings.ringnum[0].range = atoi(v->value);
17146 } else if (!strcasecmp(v->name, "dring2range")) {
17147 confp->chan.drings.ringnum[1].range = atoi(v->value);
17148 } else if (!strcasecmp(v->name, "dring3range")) {
17149 confp->chan.drings.ringnum[2].range = atoi(v->value);
17150 } else if (!strcasecmp(v->name, "dring1")) {
17151 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]);
17152 } else if (!strcasecmp(v->name, "dring2")) {
17153 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]);
17154 } else if (!strcasecmp(v->name, "dring3")) {
17155 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]);
17156 } else if (!strcasecmp(v->name, "usecallerid")) {
17157 confp->chan.use_callerid = ast_true(v->value);
17158 } else if (!strcasecmp(v->name, "cidsignalling")) {
17159 if (!strcasecmp(v->value, "bell"))
17160 confp->chan.cid_signalling = CID_SIG_BELL;
17161 else if (!strcasecmp(v->value, "v23"))
17162 confp->chan.cid_signalling = CID_SIG_V23;
17163 else if (!strcasecmp(v->value, "dtmf"))
17164 confp->chan.cid_signalling = CID_SIG_DTMF;
17165 else if (!strcasecmp(v->value, "smdi"))
17166 confp->chan.cid_signalling = CID_SIG_SMDI;
17167 else if (!strcasecmp(v->value, "v23_jp"))
17168 confp->chan.cid_signalling = CID_SIG_V23_JP;
17169 else if (ast_true(v->value))
17170 confp->chan.cid_signalling = CID_SIG_BELL;
17171 } else if (!strcasecmp(v->name, "cidstart")) {
17172 if (!strcasecmp(v->value, "ring"))
17173 confp->chan.cid_start = CID_START_RING;
17174 else if (!strcasecmp(v->value, "polarity_in"))
17175 confp->chan.cid_start = CID_START_POLARITY_IN;
17176 else if (!strcasecmp(v->value, "polarity"))
17177 confp->chan.cid_start = CID_START_POLARITY;
17178 else if (!strcasecmp(v->value, "dtmf"))
17179 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17180 else if (ast_true(v->value))
17181 confp->chan.cid_start = CID_START_RING;
17182 } else if (!strcasecmp(v->name, "threewaycalling")) {
17183 confp->chan.threewaycalling = ast_true(v->value);
17184 } else if (!strcasecmp(v->name, "cancallforward")) {
17185 confp->chan.cancallforward = ast_true(v->value);
17186 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17187 if (ast_true(v->value))
17188 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17189 else
17190 confp->chan.dtmfrelax = 0;
17191 } else if (!strcasecmp(v->name, "mailbox")) {
17192 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17193 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17194 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17195 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17196 }
17197 } else if (!strcasecmp(v->name, "adsi")) {
17198 confp->chan.adsi = ast_true(v->value);
17199 } else if (!strcasecmp(v->name, "usesmdi")) {
17200 confp->chan.use_smdi = ast_true(v->value);
17201 } else if (!strcasecmp(v->name, "smdiport")) {
17202 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17203 } else if (!strcasecmp(v->name, "transfer")) {
17204 confp->chan.transfer = ast_true(v->value);
17205 } else if (!strcasecmp(v->name, "canpark")) {
17206 confp->chan.canpark = ast_true(v->value);
17207 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17208 confp->chan.echocanbridged = ast_true(v->value);
17209 } else if (!strcasecmp(v->name, "busydetect")) {
17210 confp->chan.busydetect = ast_true(v->value);
17211 } else if (!strcasecmp(v->name, "busycount")) {
17212 confp->chan.busycount = atoi(v->value);
17213 } else if (!strcasecmp(v->name, "busypattern")) {
17214 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17215 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17216 }
17217 } else if (!strcasecmp(v->name, "callprogress")) {
17218 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17219 if (ast_true(v->value))
17220 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17221 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17222 confp->chan.waitfordialtone = atoi(v->value);
17223 } else if (!strcasecmp(v->name, "faxdetect")) {
17224 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17225 if (!strcasecmp(v->value, "incoming")) {
17226 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17227 } else if (!strcasecmp(v->value, "outgoing")) {
17228 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17229 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17230 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17231 } else if (!strcasecmp(v->name, "echocancel")) {
17232 process_echocancel(confp, v->value, v->lineno);
17233 } else if (!strcasecmp(v->name, "echotraining")) {
17234 if (sscanf(v->value, "%30d", &y) == 1) {
17235 if ((y < 10) || (y > 4000)) {
17236 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17237 } else {
17238 confp->chan.echotraining = y;
17239 }
17240 } else if (ast_true(v->value)) {
17241 confp->chan.echotraining = 400;
17242 } else
17243 confp->chan.echotraining = 0;
17244 } else if (!strcasecmp(v->name, "hidecallerid")) {
17245 confp->chan.hidecallerid = ast_true(v->value);
17246 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17247 confp->chan.hidecalleridname = ast_true(v->value);
17248 } else if (!strcasecmp(v->name, "pulsedial")) {
17249 confp->chan.pulse = ast_true(v->value);
17250 } else if (!strcasecmp(v->name, "callreturn")) {
17251 confp->chan.callreturn = ast_true(v->value);
17252 } else if (!strcasecmp(v->name, "callwaiting")) {
17253 confp->chan.callwaiting = ast_true(v->value);
17254 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17255 confp->chan.callwaitingcallerid = ast_true(v->value);
17256 } else if (!strcasecmp(v->name, "context")) {
17257 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17258 } else if (!strcasecmp(v->name, "language")) {
17259 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17260 } else if (!strcasecmp(v->name, "progzone")) {
17261 ast_copy_string(progzone, v->value, sizeof(progzone));
17262 } else if (!strcasecmp(v->name, "mohinterpret")
17263 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17264 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17265 } else if (!strcasecmp(v->name, "mohsuggest")) {
17266 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17267 } else if (!strcasecmp(v->name, "parkinglot")) {
17268 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17269 } else if (!strcasecmp(v->name, "stripmsd")) {
17270 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17271 confp->chan.stripmsd = atoi(v->value);
17272 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17273 numbufs = atoi(v->value);
17274 } else if (!strcasecmp(v->name, "group")) {
17275 confp->chan.group = ast_get_group(v->value);
17276 } else if (!strcasecmp(v->name, "callgroup")) {
17277 if (!strcasecmp(v->value, "none"))
17278 confp->chan.callgroup = 0;
17279 else
17280 confp->chan.callgroup = ast_get_group(v->value);
17281 } else if (!strcasecmp(v->name, "pickupgroup")) {
17282 if (!strcasecmp(v->value, "none"))
17283 confp->chan.pickupgroup = 0;
17284 else
17285 confp->chan.pickupgroup = ast_get_group(v->value);
17286 } else if (!strcasecmp(v->name, "setvar")) {
17287 char *varname = ast_strdupa(v->value), *varval = NULL;
17288 struct ast_variable *tmpvar;
17289 if (varname && (varval = strchr(varname, '='))) {
17290 *varval++ = '\0';
17291 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17292 tmpvar->next = confp->chan.vars;
17293 confp->chan.vars = tmpvar;
17294 }
17295 }
17296 } else if (!strcasecmp(v->name, "immediate")) {
17297 confp->chan.immediate = ast_true(v->value);
17298 } else if (!strcasecmp(v->name, "transfertobusy")) {
17299 confp->chan.transfertobusy = ast_true(v->value);
17300 } else if (!strcasecmp(v->name, "mwimonitor")) {
17301 confp->chan.mwimonitor_neon = 0;
17302 confp->chan.mwimonitor_fsk = 0;
17303 confp->chan.mwimonitor_rpas = 0;
17304 if (strcasestr(v->value, "fsk")) {
17305 confp->chan.mwimonitor_fsk = 1;
17306 }
17307 if (strcasestr(v->value, "rpas")) {
17308 confp->chan.mwimonitor_rpas = 1;
17309 }
17310 if (strcasestr(v->value, "neon")) {
17311 confp->chan.mwimonitor_neon = 1;
17312 }
17313
17314 if (ast_true(v->value)) {
17315 confp->chan.mwimonitor_fsk = 1;
17316 }
17317 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17318 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17319 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17320 }
17321 } else if (!strcasecmp(v->name, "rxgain")) {
17322 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17323 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17324 }
17325 } else if (!strcasecmp(v->name, "txgain")) {
17326 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17327 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17328 }
17329 } else if (!strcasecmp(v->name, "txdrc")) {
17330 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17331 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17332 }
17333 } else if (!strcasecmp(v->name, "rxdrc")) {
17334 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17335 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17336 }
17337 } else if (!strcasecmp(v->name, "tonezone")) {
17338 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17339 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17340 }
17341 } else if (!strcasecmp(v->name, "callerid")) {
17342 if (!strcasecmp(v->value, "asreceived")) {
17343 confp->chan.cid_num[0] = '\0';
17344 confp->chan.cid_name[0] = '\0';
17345 } else {
17346 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17347 }
17348 } else if (!strcasecmp(v->name, "fullname")) {
17349 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17350 } else if (!strcasecmp(v->name, "cid_number")) {
17351 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17352 } else if (!strcasecmp(v->name, "cid_tag")) {
17353 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17354 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17355 confp->chan.dahditrcallerid = ast_true(v->value);
17356 } else if (!strcasecmp(v->name, "restrictcid")) {
17357 confp->chan.restrictcid = ast_true(v->value);
17358 } else if (!strcasecmp(v->name, "usecallingpres")) {
17359 confp->chan.use_callingpres = ast_true(v->value);
17360 } else if (!strcasecmp(v->name, "accountcode")) {
17361 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17362 } else if (!strcasecmp(v->name, "amaflags")) {
17363 y = ast_cdr_amaflags2int(v->value);
17364 if (y < 0)
17365 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17366 else
17367 confp->chan.amaflags = y;
17368 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17369 confp->chan.polarityonanswerdelay = atoi(v->value);
17370 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17371 confp->chan.answeronpolarityswitch = ast_true(v->value);
17372 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17373 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17374 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17375 confp->chan.sendcalleridafter = atoi(v->value);
17376 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17377 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17378 } else if (ast_cc_is_config_param(v->name)) {
17379 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17380 } else if (!strcasecmp(v->name, "mwisendtype")) {
17381 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17382 if (!strcasecmp(v->value, "rpas")) {
17383 mwisend_rpas = 1;
17384 } else {
17385 mwisend_rpas = 0;
17386 }
17387 #else
17388
17389 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17390 if (strcasestr(v->value, "nofsk")) {
17391 confp->chan.mwisend_fsk = 0;
17392 } else {
17393 confp->chan.mwisend_fsk = 1;
17394 }
17395 if (strcasestr(v->value, "rpas")) {
17396 confp->chan.mwisend_rpas = 1;
17397 } else {
17398 confp->chan.mwisend_rpas = 0;
17399 }
17400 if (strcasestr(v->value, "lrev")) {
17401 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17402 }
17403 if (strcasestr(v->value, "hvdc")) {
17404 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17405 }
17406 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17407 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17408 }
17409 #endif
17410 } else if (reload != 1) {
17411 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17412 int orig_radio = confp->chan.radio;
17413 int orig_outsigmod = confp->chan.outsigmod;
17414 int orig_auto = confp->is_sig_auto;
17415
17416 confp->chan.radio = 0;
17417 confp->chan.outsigmod = -1;
17418 confp->is_sig_auto = 0;
17419 if (!strcasecmp(v->value, "em")) {
17420 confp->chan.sig = SIG_EM;
17421 } else if (!strcasecmp(v->value, "em_e1")) {
17422 confp->chan.sig = SIG_EM_E1;
17423 } else if (!strcasecmp(v->value, "em_w")) {
17424 confp->chan.sig = SIG_EMWINK;
17425 } else if (!strcasecmp(v->value, "fxs_ls")) {
17426 confp->chan.sig = SIG_FXSLS;
17427 } else if (!strcasecmp(v->value, "fxs_gs")) {
17428 confp->chan.sig = SIG_FXSGS;
17429 } else if (!strcasecmp(v->value, "fxs_ks")) {
17430 confp->chan.sig = SIG_FXSKS;
17431 } else if (!strcasecmp(v->value, "fxo_ls")) {
17432 confp->chan.sig = SIG_FXOLS;
17433 } else if (!strcasecmp(v->value, "fxo_gs")) {
17434 confp->chan.sig = SIG_FXOGS;
17435 } else if (!strcasecmp(v->value, "fxo_ks")) {
17436 confp->chan.sig = SIG_FXOKS;
17437 } else if (!strcasecmp(v->value, "fxs_rx")) {
17438 confp->chan.sig = SIG_FXSKS;
17439 confp->chan.radio = 1;
17440 } else if (!strcasecmp(v->value, "fxo_rx")) {
17441 confp->chan.sig = SIG_FXOLS;
17442 confp->chan.radio = 1;
17443 } else if (!strcasecmp(v->value, "fxs_tx")) {
17444 confp->chan.sig = SIG_FXSLS;
17445 confp->chan.radio = 1;
17446 } else if (!strcasecmp(v->value, "fxo_tx")) {
17447 confp->chan.sig = SIG_FXOGS;
17448 confp->chan.radio = 1;
17449 } else if (!strcasecmp(v->value, "em_rx")) {
17450 confp->chan.sig = SIG_EM;
17451 confp->chan.radio = 1;
17452 } else if (!strcasecmp(v->value, "em_tx")) {
17453 confp->chan.sig = SIG_EM;
17454 confp->chan.radio = 1;
17455 } else if (!strcasecmp(v->value, "em_rxtx")) {
17456 confp->chan.sig = SIG_EM;
17457 confp->chan.radio = 2;
17458 } else if (!strcasecmp(v->value, "em_txrx")) {
17459 confp->chan.sig = SIG_EM;
17460 confp->chan.radio = 2;
17461 } else if (!strcasecmp(v->value, "sf")) {
17462 confp->chan.sig = SIG_SF;
17463 } else if (!strcasecmp(v->value, "sf_w")) {
17464 confp->chan.sig = SIG_SFWINK;
17465 } else if (!strcasecmp(v->value, "sf_featd")) {
17466 confp->chan.sig = SIG_FEATD;
17467 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17468 confp->chan.sig = SIG_FEATDMF;
17469 } else if (!strcasecmp(v->value, "sf_featb")) {
17470 confp->chan.sig = SIG_SF_FEATB;
17471 } else if (!strcasecmp(v->value, "sf")) {
17472 confp->chan.sig = SIG_SF;
17473 } else if (!strcasecmp(v->value, "sf_rx")) {
17474 confp->chan.sig = SIG_SF;
17475 confp->chan.radio = 1;
17476 } else if (!strcasecmp(v->value, "sf_tx")) {
17477 confp->chan.sig = SIG_SF;
17478 confp->chan.radio = 1;
17479 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17480 confp->chan.sig = SIG_SF;
17481 confp->chan.radio = 2;
17482 } else if (!strcasecmp(v->value, "sf_txrx")) {
17483 confp->chan.sig = SIG_SF;
17484 confp->chan.radio = 2;
17485 } else if (!strcasecmp(v->value, "featd")) {
17486 confp->chan.sig = SIG_FEATD;
17487 } else if (!strcasecmp(v->value, "featdmf")) {
17488 confp->chan.sig = SIG_FEATDMF;
17489 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17490 confp->chan.sig = SIG_FEATDMF_TA;
17491 } else if (!strcasecmp(v->value, "e911")) {
17492 confp->chan.sig = SIG_E911;
17493 } else if (!strcasecmp(v->value, "fgccama")) {
17494 confp->chan.sig = SIG_FGC_CAMA;
17495 } else if (!strcasecmp(v->value, "fgccamamf")) {
17496 confp->chan.sig = SIG_FGC_CAMAMF;
17497 } else if (!strcasecmp(v->value, "featb")) {
17498 confp->chan.sig = SIG_FEATB;
17499 #ifdef HAVE_PRI
17500 } else if (!strcasecmp(v->value, "pri_net")) {
17501 confp->chan.sig = SIG_PRI;
17502 confp->pri.pri.nodetype = PRI_NETWORK;
17503 } else if (!strcasecmp(v->value, "pri_cpe")) {
17504 confp->chan.sig = SIG_PRI;
17505 confp->pri.pri.nodetype = PRI_CPE;
17506 } else if (!strcasecmp(v->value, "bri_cpe")) {
17507 confp->chan.sig = SIG_BRI;
17508 confp->pri.pri.nodetype = PRI_CPE;
17509 } else if (!strcasecmp(v->value, "bri_net")) {
17510 confp->chan.sig = SIG_BRI;
17511 confp->pri.pri.nodetype = PRI_NETWORK;
17512 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17513 confp->chan.sig = SIG_BRI_PTMP;
17514 confp->pri.pri.nodetype = PRI_CPE;
17515 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17516 #if defined(HAVE_PRI_CALL_HOLD)
17517 confp->chan.sig = SIG_BRI_PTMP;
17518 confp->pri.pri.nodetype = PRI_NETWORK;
17519 #else
17520 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17521 #endif
17522 #endif
17523 #if defined(HAVE_SS7)
17524 } else if (!strcasecmp(v->value, "ss7")) {
17525 confp->chan.sig = SIG_SS7;
17526 #endif
17527 #ifdef HAVE_OPENR2
17528 } else if (!strcasecmp(v->value, "mfcr2")) {
17529 confp->chan.sig = SIG_MFCR2;
17530 #endif
17531 } else if (!strcasecmp(v->value, "auto")) {
17532 confp->is_sig_auto = 1;
17533 } else {
17534 confp->chan.outsigmod = orig_outsigmod;
17535 confp->chan.radio = orig_radio;
17536 confp->is_sig_auto = orig_auto;
17537 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17538 }
17539 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17540 if (!strcasecmp(v->value, "em")) {
17541 confp->chan.outsigmod = SIG_EM;
17542 } else if (!strcasecmp(v->value, "em_e1")) {
17543 confp->chan.outsigmod = SIG_EM_E1;
17544 } else if (!strcasecmp(v->value, "em_w")) {
17545 confp->chan.outsigmod = SIG_EMWINK;
17546 } else if (!strcasecmp(v->value, "sf")) {
17547 confp->chan.outsigmod = SIG_SF;
17548 } else if (!strcasecmp(v->value, "sf_w")) {
17549 confp->chan.outsigmod = SIG_SFWINK;
17550 } else if (!strcasecmp(v->value, "sf_featd")) {
17551 confp->chan.outsigmod = SIG_FEATD;
17552 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17553 confp->chan.outsigmod = SIG_FEATDMF;
17554 } else if (!strcasecmp(v->value, "sf_featb")) {
17555 confp->chan.outsigmod = SIG_SF_FEATB;
17556 } else if (!strcasecmp(v->value, "sf")) {
17557 confp->chan.outsigmod = SIG_SF;
17558 } else if (!strcasecmp(v->value, "featd")) {
17559 confp->chan.outsigmod = SIG_FEATD;
17560 } else if (!strcasecmp(v->value, "featdmf")) {
17561 confp->chan.outsigmod = SIG_FEATDMF;
17562 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17563 confp->chan.outsigmod = SIG_FEATDMF_TA;
17564 } else if (!strcasecmp(v->value, "e911")) {
17565 confp->chan.outsigmod = SIG_E911;
17566 } else if (!strcasecmp(v->value, "fgccama")) {
17567 confp->chan.outsigmod = SIG_FGC_CAMA;
17568 } else if (!strcasecmp(v->value, "fgccamamf")) {
17569 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17570 } else if (!strcasecmp(v->value, "featb")) {
17571 confp->chan.outsigmod = SIG_FEATB;
17572 } else {
17573 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17574 }
17575 #ifdef HAVE_PRI
17576 } else if (!strcasecmp(v->name, "pridialplan")) {
17577 if (!strcasecmp(v->value, "national")) {
17578 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17579 } else if (!strcasecmp(v->value, "unknown")) {
17580 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17581 } else if (!strcasecmp(v->value, "private")) {
17582 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17583 } else if (!strcasecmp(v->value, "international")) {
17584 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17585 } else if (!strcasecmp(v->value, "local")) {
17586 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17587 } else if (!strcasecmp(v->value, "dynamic")) {
17588 confp->pri.pri.dialplan = -1;
17589 } else if (!strcasecmp(v->value, "redundant")) {
17590 confp->pri.pri.dialplan = -2;
17591 } else {
17592 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17593 }
17594 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17595 if (!strcasecmp(v->value, "national")) {
17596 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17597 } else if (!strcasecmp(v->value, "unknown")) {
17598 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17599 } else if (!strcasecmp(v->value, "private")) {
17600 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17601 } else if (!strcasecmp(v->value, "international")) {
17602 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17603 } else if (!strcasecmp(v->value, "local")) {
17604 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17605 } else if (!strcasecmp(v->value, "dynamic")) {
17606 confp->pri.pri.localdialplan = -1;
17607 } else if (!strcasecmp(v->value, "redundant")) {
17608 confp->pri.pri.localdialplan = -2;
17609 } else {
17610 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17611 }
17612 } else if (!strcasecmp(v->name, "switchtype")) {
17613 if (!strcasecmp(v->value, "national"))
17614 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17615 else if (!strcasecmp(v->value, "ni1"))
17616 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17617 else if (!strcasecmp(v->value, "dms100"))
17618 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17619 else if (!strcasecmp(v->value, "4ess"))
17620 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17621 else if (!strcasecmp(v->value, "5ess"))
17622 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17623 else if (!strcasecmp(v->value, "euroisdn"))
17624 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17625 else if (!strcasecmp(v->value, "qsig"))
17626 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17627 else {
17628 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17629 return -1;
17630 }
17631 } else if (!strcasecmp(v->name, "msn")) {
17632 ast_copy_string(confp->pri.pri.msn_list, v->value,
17633 sizeof(confp->pri.pri.msn_list));
17634 } else if (!strcasecmp(v->name, "nsf")) {
17635 if (!strcasecmp(v->value, "sdn"))
17636 confp->pri.pri.nsf = PRI_NSF_SDN;
17637 else if (!strcasecmp(v->value, "megacom"))
17638 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17639 else if (!strcasecmp(v->value, "tollfreemegacom"))
17640 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17641 else if (!strcasecmp(v->value, "accunet"))
17642 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17643 else if (!strcasecmp(v->value, "none"))
17644 confp->pri.pri.nsf = PRI_NSF_NONE;
17645 else {
17646 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17647 confp->pri.pri.nsf = PRI_NSF_NONE;
17648 }
17649 } else if (!strcasecmp(v->name, "priindication")) {
17650 if (!strcasecmp(v->value, "outofband"))
17651 confp->chan.priindication_oob = 1;
17652 else if (!strcasecmp(v->value, "inband"))
17653 confp->chan.priindication_oob = 0;
17654 else
17655 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17656 v->value, v->lineno);
17657 } else if (!strcasecmp(v->name, "priexclusive")) {
17658 confp->chan.priexclusive = ast_true(v->value);
17659 } else if (!strcasecmp(v->name, "internationalprefix")) {
17660 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17661 } else if (!strcasecmp(v->name, "nationalprefix")) {
17662 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17663 } else if (!strcasecmp(v->name, "localprefix")) {
17664 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17665 } else if (!strcasecmp(v->name, "privateprefix")) {
17666 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17667 } else if (!strcasecmp(v->name, "unknownprefix")) {
17668 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17669 } else if (!strcasecmp(v->name, "resetinterval")) {
17670 if (!strcasecmp(v->value, "never"))
17671 confp->pri.pri.resetinterval = -1;
17672 else if (atoi(v->value) >= 60)
17673 confp->pri.pri.resetinterval = atoi(v->value);
17674 else
17675 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17676 v->value, v->lineno);
17677 } else if (!strcasecmp(v->name, "minunused")) {
17678 confp->pri.pri.minunused = atoi(v->value);
17679 } else if (!strcasecmp(v->name, "minidle")) {
17680 confp->pri.pri.minidle = atoi(v->value);
17681 } else if (!strcasecmp(v->name, "idleext")) {
17682 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17683 } else if (!strcasecmp(v->name, "idledial")) {
17684 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17685 } else if (!strcasecmp(v->name, "overlapdial")) {
17686 if (ast_true(v->value)) {
17687 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17688 } else if (!strcasecmp(v->value, "incoming")) {
17689 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17690 } else if (!strcasecmp(v->value, "outgoing")) {
17691 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17692 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17693 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17694 } else {
17695 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17696 }
17697 #ifdef HAVE_PRI_PROG_W_CAUSE
17698 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17699 if (!strcasecmp(v->value, "logical")) {
17700 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17701 } else if (!strcasecmp(v->value, "physical")) {
17702 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17703 } else {
17704 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17705 }
17706 #endif
17707 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17708 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17709 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17710 } else if (!strcasecmp(v->name, "service_message_support")) {
17711
17712 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17713 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17714 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17715 confp->pri.pri.enable_service_message_support = 1;
17716 } else {
17717 confp->pri.pri.enable_service_message_support = 0;
17718 }
17719 #endif
17720 #ifdef HAVE_PRI_INBANDDISCONNECT
17721 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17722 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17723 #endif
17724 } else if (!strcasecmp(v->name, "pritimer")) {
17725 #ifdef PRI_GETSET_TIMERS
17726 char tmp[20];
17727 char *timerc;
17728 char *c;
17729 int timer;
17730 int timeridx;
17731
17732 ast_copy_string(tmp, v->value, sizeof(tmp));
17733 c = tmp;
17734 timerc = strsep(&c, ",");
17735 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17736 timeridx = pri_timer2idx(timerc);
17737 timer = atoi(c);
17738 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17739 ast_log(LOG_WARNING,
17740 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17741 v->lineno);
17742 } else if (!timer) {
17743 ast_log(LOG_WARNING,
17744 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17745 c, timerc, v->lineno);
17746 } else {
17747 confp->pri.pri.pritimers[timeridx] = timer;
17748 }
17749 } else {
17750 ast_log(LOG_WARNING,
17751 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17752 v->value, v->lineno);
17753 }
17754 #endif
17755 } else if (!strcasecmp(v->name, "facilityenable")) {
17756 confp->pri.pri.facilityenable = ast_true(v->value);
17757 #if defined(HAVE_PRI_AOC_EVENTS)
17758 } else if (!strcasecmp(v->name, "aoc_enable")) {
17759 confp->pri.pri.aoc_passthrough_flag = 0;
17760 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17761 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17762 }
17763 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17764 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17765 }
17766 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17767 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17768 }
17769 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17770 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17771 #endif
17772 #if defined(HAVE_PRI_CALL_HOLD)
17773 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17774 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17775 #endif
17776 #if defined(HAVE_PRI_CCSS)
17777 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17778 if (!strcasecmp(v->value, "global")) {
17779 confp->pri.pri.cc_ptmp_recall_mode = 0;
17780 } else if (!strcasecmp(v->value, "specific")) {
17781 confp->pri.pri.cc_ptmp_recall_mode = 1;
17782 } else {
17783 confp->pri.pri.cc_ptmp_recall_mode = 1;
17784 }
17785 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17786 if (!strcasecmp(v->value, "release")) {
17787 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17788 } else if (!strcasecmp(v->value, "retain")) {
17789 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17790 } else if (!strcasecmp(v->value, "do_not_care")) {
17791 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17792 } else {
17793 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17794 }
17795 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17796 if (!strcasecmp(v->value, "release")) {
17797 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17798 } else if (!strcasecmp(v->value, "retain")) {
17799 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17800 } else {
17801 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17802 }
17803 #endif
17804 #if defined(HAVE_PRI_CALL_WAITING)
17805 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17806 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17807 if (confp->pri.pri.max_call_waiting_calls < 0) {
17808
17809 confp->pri.pri.max_call_waiting_calls = 0;
17810 }
17811 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17812 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17813 #endif
17814 #if defined(HAVE_PRI_MWI)
17815 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17816 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17817 sizeof(confp->pri.pri.mwi_mailboxes));
17818 #endif
17819 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17820 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17821 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
17822 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
17823 } else if (!strcasecmp(v->name, "layer1_presence")) {
17824 if (!strcasecmp(v->value, "required")) {
17825 confp->pri.pri.layer1_ignored = 0;
17826 } else if (!strcasecmp(v->value, "ignore")) {
17827 confp->pri.pri.layer1_ignored = 1;
17828 } else {
17829
17830 confp->pri.pri.layer1_ignored = 0;
17831 }
17832 #if defined(HAVE_PRI_L2_PERSISTENCE)
17833 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17834 if (!strcasecmp(v->value, "keep_up")) {
17835 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17836 } else if (!strcasecmp(v->value, "leave_down")) {
17837 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17838 } else {
17839 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17840 }
17841 #endif
17842 #endif
17843 #if defined(HAVE_SS7)
17844 } else if (!strcasecmp(v->name, "ss7type")) {
17845 if (!strcasecmp(v->value, "itu")) {
17846 cur_ss7type = SS7_ITU;
17847 } else if (!strcasecmp(v->value, "ansi")) {
17848 cur_ss7type = SS7_ANSI;
17849 } else
17850 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17851 } else if (!strcasecmp(v->name, "linkset")) {
17852 cur_linkset = atoi(v->value);
17853 } else if (!strcasecmp(v->name, "pointcode")) {
17854 cur_pointcode = parse_pointcode(v->value);
17855 } else if (!strcasecmp(v->name, "adjpointcode")) {
17856 cur_adjpointcode = parse_pointcode(v->value);
17857 } else if (!strcasecmp(v->name, "defaultdpc")) {
17858 cur_defaultdpc = parse_pointcode(v->value);
17859 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17860 cur_cicbeginswith = atoi(v->value);
17861 } else if (!strcasecmp(v->name, "networkindicator")) {
17862 if (!strcasecmp(v->value, "national"))
17863 cur_networkindicator = SS7_NI_NAT;
17864 else if (!strcasecmp(v->value, "national_spare"))
17865 cur_networkindicator = SS7_NI_NAT_SPARE;
17866 else if (!strcasecmp(v->value, "international"))
17867 cur_networkindicator = SS7_NI_INT;
17868 else if (!strcasecmp(v->value, "international_spare"))
17869 cur_networkindicator = SS7_NI_INT_SPARE;
17870 else
17871 cur_networkindicator = -1;
17872 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17873 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17874 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17875 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17876 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17877 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17878 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17879 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17880 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17881 if (!strcasecmp(v->value, "national")) {
17882 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17883 } else if (!strcasecmp(v->value, "international")) {
17884 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17885 } else if (!strcasecmp(v->value, "subscriber")) {
17886 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17887 } else if (!strcasecmp(v->value, "unknown")) {
17888 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17889 } else if (!strcasecmp(v->value, "dynamic")) {
17890 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17891 } else {
17892 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17893 }
17894 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17895 if (!strcasecmp(v->value, "national")) {
17896 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17897 } else if (!strcasecmp(v->value, "international")) {
17898 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17899 } else if (!strcasecmp(v->value, "subscriber")) {
17900 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17901 } else if (!strcasecmp(v->value, "unknown")) {
17902 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17903 } else if (!strcasecmp(v->value, "dynamic")) {
17904 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17905 } else {
17906 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17907 }
17908 } else if (!strcasecmp(v->name, "sigchan")) {
17909 int sigchan, res;
17910 sigchan = atoi(v->value);
17911 res = linkset_addsigchan(sigchan);
17912 if (res < 0)
17913 return -1;
17914
17915 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17916 struct dahdi_ss7 *link;
17917 link = ss7_resolve_linkset(cur_linkset);
17918 if (!link) {
17919 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17920 return -1;
17921 }
17922 if (ast_true(v->value))
17923 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17924 #endif
17925 #ifdef HAVE_OPENR2
17926 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17927 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17928 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);
17929 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17930 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17931 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17932 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17933 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17934 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17935 confp->mfcr2.variant = OR2_VAR_ITU;
17936 }
17937 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17938 confp->mfcr2.mfback_timeout = atoi(v->value);
17939 if (!confp->mfcr2.mfback_timeout) {
17940 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17941 confp->mfcr2.mfback_timeout = -1;
17942 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17943 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17944 }
17945 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17946 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17947 if (confp->mfcr2.metering_pulse_timeout > 500) {
17948 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17949 }
17950 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17951 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17952 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17953 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17954 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17955 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17956 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17957 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17958 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17959 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17960 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17961 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17962 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17963 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17964 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17965 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17966 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17967 #endif
17968 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17969 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17970 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17971 confp->mfcr2.max_ani = atoi(v->value);
17972 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17973 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17974 }
17975 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17976 confp->mfcr2.max_dnis = atoi(v->value);
17977 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17978 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17979 }
17980 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17981 confp->mfcr2.category = openr2_proto_get_category(v->value);
17982 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17983 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17984 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17985 v->value, v->lineno);
17986 }
17987 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17988 openr2_log_level_t tmplevel;
17989 char *clevel;
17990 char *logval = ast_strdupa(v->value);
17991 while (logval) {
17992 clevel = strsep(&logval,",");
17993 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17994 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17995 continue;
17996 }
17997 confp->mfcr2.loglevel |= tmplevel;
17998 }
17999 #endif
18000 } else if (!strcasecmp(v->name, "cadence")) {
18001
18002 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18003 int i;
18004 struct dahdi_ring_cadence new_cadence;
18005 int cid_location = -1;
18006 int firstcadencepos = 0;
18007 char original_args[80];
18008 int cadence_is_ok = 1;
18009
18010 ast_copy_string(original_args, v->value, sizeof(original_args));
18011
18012 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]);
18013
18014
18015 if (element_count % 2 == 1) {
18016 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18017 cadence_is_ok = 0;
18018 }
18019
18020
18021 for (i = 0; i < element_count; i++) {
18022 if (c[i] == 0) {
18023 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18024 cadence_is_ok = 0;
18025 break;
18026 } else if (c[i] < 0) {
18027 if (i % 2 == 1) {
18028
18029 if (cid_location == -1) {
18030 cid_location = i;
18031 c[i] *= -1;
18032 } else {
18033 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18034 cadence_is_ok = 0;
18035 break;
18036 }
18037 } else {
18038 if (firstcadencepos == 0) {
18039 firstcadencepos = i;
18040
18041 } else {
18042 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18043 cadence_is_ok = 0;
18044 break;
18045 }
18046 }
18047 }
18048 }
18049
18050
18051 for (i = 0; i < 16; i++) {
18052 new_cadence.ringcadence[i] = c[i];
18053 }
18054
18055 if (cadence_is_ok) {
18056
18057 if (element_count < 2) {
18058 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18059 } else {
18060 if (cid_location == -1) {
18061
18062 cid_location = 1;
18063 } else {
18064
18065 cid_location = (cid_location + 1) / 2;
18066 }
18067
18068 if (!user_has_defined_cadences++)
18069
18070 num_cadence = 0;
18071 if ((num_cadence+1) >= NUM_CADENCE_MAX)
18072 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18073 else {
18074 cadences[num_cadence] = new_cadence;
18075 cidrings[num_cadence++] = cid_location;
18076 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18077 }
18078 }
18079 }
18080 } else if (!strcasecmp(v->name, "ringtimeout")) {
18081 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18082 } else if (!strcasecmp(v->name, "prewink")) {
18083 confp->timing.prewinktime = atoi(v->value);
18084 } else if (!strcasecmp(v->name, "preflash")) {
18085 confp->timing.preflashtime = atoi(v->value);
18086 } else if (!strcasecmp(v->name, "wink")) {
18087 confp->timing.winktime = atoi(v->value);
18088 } else if (!strcasecmp(v->name, "flash")) {
18089 confp->timing.flashtime = atoi(v->value);
18090 } else if (!strcasecmp(v->name, "start")) {
18091 confp->timing.starttime = atoi(v->value);
18092 } else if (!strcasecmp(v->name, "rxwink")) {
18093 confp->timing.rxwinktime = atoi(v->value);
18094 } else if (!strcasecmp(v->name, "rxflash")) {
18095 confp->timing.rxflashtime = atoi(v->value);
18096 } else if (!strcasecmp(v->name, "debounce")) {
18097 confp->timing.debouncetime = atoi(v->value);
18098 } else if (!strcasecmp(v->name, "toneduration")) {
18099 int toneduration;
18100 int ctlfd;
18101 int res;
18102 struct dahdi_dialparams dps;
18103
18104 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18105 if (ctlfd == -1) {
18106 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18107 return -1;
18108 }
18109
18110 toneduration = atoi(v->value);
18111 if (toneduration > -1) {
18112 memset(&dps, 0, sizeof(dps));
18113
18114 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18115 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18116 if (res < 0) {
18117 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18118 close(ctlfd);
18119 return -1;
18120 }
18121 }
18122 close(ctlfd);
18123 } else if (!strcasecmp(v->name, "defaultcic")) {
18124 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18125 } else if (!strcasecmp(v->name, "defaultozz")) {
18126 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18127 } else if (!strcasecmp(v->name, "mwilevel")) {
18128 mwilevel = atoi(v->value);
18129 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18130 dtmfcid_level = atoi(v->value);
18131 } else if (!strcasecmp(v->name, "reportalarms")) {
18132 if (!strcasecmp(v->value, "all"))
18133 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18134 if (!strcasecmp(v->value, "none"))
18135 report_alarms = 0;
18136 else if (!strcasecmp(v->value, "channels"))
18137 report_alarms = REPORT_CHANNEL_ALARMS;
18138 else if (!strcasecmp(v->value, "spans"))
18139 report_alarms = REPORT_SPAN_ALARMS;
18140 }
18141 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18142 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18143 }
18144
18145
18146 if (confp->chan.vars) {
18147 ast_variables_destroy(confp->chan.vars);
18148 confp->chan.vars = NULL;
18149 }
18150
18151 if (dahdichan) {
18152
18153 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18154 &found_pseudo)) {
18155 if (confp->ignore_failed_channels) {
18156 ast_log(LOG_WARNING,
18157 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18158 dahdichan->value);
18159 } else {
18160 return -1;
18161 }
18162 }
18163 }
18164
18165
18166 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18167 if (!tmp->destroy && tmp->span != y) {
18168 tmp->manages_span_alarms = 1;
18169 y = tmp->span;
18170 } else {
18171 tmp->manages_span_alarms = 0;
18172 }
18173 }
18174
18175
18176
18177 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18178
18179
18180
18181
18182 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18183
18184 if (conf.chan.cc_params) {
18185 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18186 } else {
18187 tmp = NULL;
18188 }
18189 if (tmp) {
18190 ast_verb(3, "Automatically generated pseudo channel\n");
18191 } else {
18192 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18193 }
18194 ast_cc_config_params_destroy(conf.chan.cc_params);
18195 }
18196 return 0;
18197 }
18198
18199
18200
18201
18202
18203
18204
18205
18206
18207
18208
18209 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18210 {
18211 struct ast_cc_config_params *cc_params;
18212
18213 cc_params = dest->chan.cc_params;
18214 *dest = *src;
18215 dest->chan.cc_params = cc_params;
18216 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18217 }
18218
18219
18220
18221
18222
18223
18224
18225
18226
18227
18228
18229
18230
18231 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18232 {
18233 struct ast_config *cfg;
18234 struct ast_config *ucfg;
18235 struct ast_variable *v;
18236 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18237 const char *chans;
18238 const char *cat;
18239 int res;
18240
18241 #ifdef HAVE_PRI
18242 char *c;
18243 int spanno;
18244 int i;
18245 int logicalspan;
18246 int trunkgroup;
18247 int dchannels[SIG_PRI_NUM_DCHANS];
18248 #endif
18249 int have_cfg_now;
18250 static int had_cfg_before = 1;
18251
18252 cfg = ast_config_load(config, config_flags);
18253 have_cfg_now = !!cfg;
18254 if (!cfg) {
18255
18256 if (had_cfg_before) {
18257 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18258 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18259 }
18260 cfg = ast_config_new();
18261 if (!cfg) {
18262 return 0;
18263 }
18264 ucfg = ast_config_load("users.conf", config_flags);
18265 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18266 ast_config_destroy(cfg);
18267 return 0;
18268 }
18269 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18270 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18271 ast_config_destroy(cfg);
18272 return 0;
18273 }
18274 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18275 ucfg = ast_config_load("users.conf", config_flags);
18276 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18277 return 0;
18278 }
18279 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18280 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18281 return 0;
18282 }
18283 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18284 cfg = ast_config_load(config, config_flags);
18285 have_cfg_now = !!cfg;
18286 if (!cfg) {
18287 if (had_cfg_before) {
18288
18289 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18290 ast_config_destroy(ucfg);
18291 return 0;
18292 }
18293 cfg = ast_config_new();
18294 if (!cfg) {
18295 ast_config_destroy(ucfg);
18296 return 0;
18297 }
18298 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18299 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18300 ast_config_destroy(ucfg);
18301 return 0;
18302 }
18303 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18304 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18305 return 0;
18306 } else {
18307 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18308 ucfg = ast_config_load("users.conf", config_flags);
18309 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18310 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18311 ast_config_destroy(cfg);
18312 return 0;
18313 }
18314 }
18315 had_cfg_before = have_cfg_now;
18316
18317
18318 ast_mutex_lock(&iflock);
18319 #ifdef HAVE_PRI
18320 if (reload != 1) {
18321
18322 v = ast_variable_browse(cfg, "trunkgroups");
18323 while (v) {
18324 if (!strcasecmp(v->name, "trunkgroup")) {
18325 trunkgroup = atoi(v->value);
18326 if (trunkgroup > 0) {
18327 if ((c = strchr(v->value, ','))) {
18328 i = 0;
18329 memset(dchannels, 0, sizeof(dchannels));
18330 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18331 dchannels[i] = atoi(c + 1);
18332 if (dchannels[i] < 0) {
18333 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);
18334 } else
18335 i++;
18336 c = strchr(c + 1, ',');
18337 }
18338 if (i) {
18339 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18340 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);
18341 } else
18342 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");
18343 } else
18344 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18345 } else
18346 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18347 } else
18348 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18349 } else if (!strcasecmp(v->name, "spanmap")) {
18350 spanno = atoi(v->value);
18351 if (spanno > 0) {
18352 if ((c = strchr(v->value, ','))) {
18353 trunkgroup = atoi(c + 1);
18354 if (trunkgroup > 0) {
18355 if ((c = strchr(c + 1, ',')))
18356 logicalspan = atoi(c + 1);
18357 else
18358 logicalspan = 0;
18359 if (logicalspan >= 0) {
18360 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18361 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18362 } else
18363 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18364 } else
18365 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);
18366 } else
18367 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18368 } else
18369 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18370 } else
18371 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18372 } else {
18373 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18374 }
18375 v = v->next;
18376 }
18377 }
18378 #endif
18379
18380
18381 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18382
18383 mwimonitornotify[0] = '\0';
18384
18385 v = ast_variable_browse(cfg, "channels");
18386 if ((res = process_dahdi(base_conf,
18387 "" ,
18388 v, reload, 0))) {
18389 ast_mutex_unlock(&iflock);
18390 ast_config_destroy(cfg);
18391 if (ucfg) {
18392 ast_config_destroy(ucfg);
18393 }
18394 return res;
18395 }
18396
18397
18398 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18399
18400
18401
18402 if (!strcasecmp(cat, "general") ||
18403 !strcasecmp(cat, "trunkgroups") ||
18404 !strcasecmp(cat, "globals") ||
18405 !strcasecmp(cat, "channels")) {
18406 continue;
18407 }
18408
18409 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18410 if (ast_strlen_zero(chans)) {
18411
18412 continue;
18413 }
18414
18415
18416 deep_copy_dahdi_chan_conf(conf, base_conf);
18417
18418 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18419 ast_mutex_unlock(&iflock);
18420 ast_config_destroy(cfg);
18421 if (ucfg) {
18422 ast_config_destroy(ucfg);
18423 }
18424 return res;
18425 }
18426 }
18427
18428 ast_config_destroy(cfg);
18429
18430 if (ucfg) {
18431
18432 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18433 process_dahdi(base_conf,
18434 "" ,
18435 ast_variable_browse(ucfg, "general"), 1, 0);
18436
18437 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18438 if (!strcasecmp(cat, "general")) {
18439 continue;
18440 }
18441
18442 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18443 if (ast_strlen_zero(chans)) {
18444
18445 continue;
18446 }
18447
18448
18449 deep_copy_dahdi_chan_conf(conf, base_conf);
18450
18451 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18452 ast_config_destroy(ucfg);
18453 ast_mutex_unlock(&iflock);
18454 return res;
18455 }
18456 }
18457 ast_config_destroy(ucfg);
18458 }
18459 ast_mutex_unlock(&iflock);
18460
18461 #ifdef HAVE_PRI
18462 if (reload != 1) {
18463 int x;
18464 for (x = 0; x < NUM_SPANS; x++) {
18465 if (pris[x].pri.pvts[0]) {
18466 prepare_pri(pris + x);
18467 if (sig_pri_start_pri(&pris[x].pri)) {
18468 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18469 return -1;
18470 } else
18471 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18472 }
18473 }
18474 }
18475 #endif
18476 #if defined(HAVE_SS7)
18477 if (reload != 1) {
18478 int x;
18479 for (x = 0; x < NUM_SPANS; x++) {
18480 if (linksets[x].ss7.ss7) {
18481 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18482 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18483 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18484 return -1;
18485 } else
18486 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18487 }
18488 }
18489 }
18490 #endif
18491 #ifdef HAVE_OPENR2
18492 if (reload != 1) {
18493 int x;
18494 for (x = 0; x < r2links_count; x++) {
18495 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18496 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18497 return -1;
18498 } else {
18499 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18500 }
18501 }
18502 }
18503 #endif
18504
18505 restart_monitor();
18506 return 0;
18507 }
18508
18509
18510
18511
18512
18513
18514
18515
18516
18517
18518 static int setup_dahdi(int reload)
18519 {
18520 int res;
18521 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18522 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18523 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18524
18525 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18526 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18527 } else {
18528 res = -1;
18529 }
18530 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18531 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18532 ast_cc_config_params_destroy(conf.chan.cc_params);
18533
18534 return res;
18535 }
18536
18537
18538
18539
18540
18541
18542
18543
18544 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18545 struct ast_data *data_root)
18546 {
18547 int ctl, res, span;
18548 struct ast_data *data_span, *data_alarms;
18549 struct dahdi_spaninfo s;
18550
18551 ctl = open("/dev/dahdi/ctl", O_RDWR);
18552 if (ctl < 0) {
18553 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18554 return -1;
18555 }
18556 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18557 s.spanno = span;
18558 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18559 if (res) {
18560 continue;
18561 }
18562
18563 data_span = ast_data_add_node(data_root, "span");
18564 if (!data_span) {
18565 continue;
18566 }
18567 ast_data_add_str(data_span, "description", s.desc);
18568
18569
18570 data_alarms = ast_data_add_node(data_span, "alarms");
18571 if (!data_alarms) {
18572 continue;
18573 }
18574
18575 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18576 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18577 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18578 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18579 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18580 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18581
18582 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18583 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18584 ast_data_add_int(data_span, "crc4", s.crc4count);
18585 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18586 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18587 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18588 "CAS");
18589 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18590 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18591 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18592 "Unknown");
18593 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18594 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18595 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18596 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18597
18598
18599 if (!ast_data_search_match(search, data_span)) {
18600 ast_data_remove_node(data_root, data_span);
18601 }
18602 }
18603 close(ctl);
18604
18605 return 0;
18606 }
18607
18608
18609
18610
18611
18612
18613
18614
18615 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18616 struct ast_data *data_root)
18617 {
18618 struct dahdi_pvt *tmp;
18619 struct ast_data *data_channel;
18620
18621 ast_mutex_lock(&iflock);
18622 for (tmp = iflist; tmp; tmp = tmp->next) {
18623 data_channel = ast_data_add_node(data_root, "channel");
18624 if (!data_channel) {
18625 continue;
18626 }
18627
18628 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18629
18630
18631 if (!ast_data_search_match(search, data_channel)) {
18632 ast_data_remove_node(data_root, data_channel);
18633 }
18634 }
18635 ast_mutex_unlock(&iflock);
18636
18637 return 0;
18638 }
18639
18640
18641
18642
18643
18644
18645
18646
18647 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18648 struct ast_data *data_root)
18649 {
18650 int pseudo_fd = -1;
18651 struct dahdi_versioninfo vi = {
18652 .version = "Unknown",
18653 .echo_canceller = "Unknown"
18654 };
18655
18656 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18657 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18658 return -1;
18659 }
18660
18661 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18662 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18663 }
18664
18665 close(pseudo_fd);
18666
18667 ast_data_add_str(data_root, "value", vi.version);
18668 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18669
18670 return 0;
18671 }
18672
18673 static const struct ast_data_handler dahdi_status_data_provider = {
18674 .version = AST_DATA_HANDLER_VERSION,
18675 .get = dahdi_status_data_provider_get
18676 };
18677
18678 static const struct ast_data_handler dahdi_channels_data_provider = {
18679 .version = AST_DATA_HANDLER_VERSION,
18680 .get = dahdi_channels_data_provider_get
18681 };
18682
18683 static const struct ast_data_handler dahdi_version_data_provider = {
18684 .version = AST_DATA_HANDLER_VERSION,
18685 .get = dahdi_version_data_provider_get
18686 };
18687
18688 static const struct ast_data_entry dahdi_data_providers[] = {
18689 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18690 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18691 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18692 };
18693
18694 static int load_module(void)
18695 {
18696 int res;
18697 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18698 int y;
18699 #endif
18700
18701 #ifdef HAVE_PRI
18702 memset(pris, 0, sizeof(pris));
18703 for (y = 0; y < NUM_SPANS; y++) {
18704 sig_pri_init_pri(&pris[y].pri);
18705 }
18706 pri_set_error(dahdi_pri_error);
18707 pri_set_message(dahdi_pri_message);
18708 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18709 #ifdef HAVE_PRI_PROG_W_CAUSE
18710 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18711 #endif
18712 #if defined(HAVE_PRI_CCSS)
18713 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18714 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18715 __unload_module();
18716 return AST_MODULE_LOAD_FAILURE;
18717 }
18718 #endif
18719 if (sig_pri_load(
18720 #if defined(HAVE_PRI_CCSS)
18721 dahdi_pri_cc_type
18722 #else
18723 NULL
18724 #endif
18725 )) {
18726 __unload_module();
18727 return AST_MODULE_LOAD_FAILURE;
18728 }
18729 #endif
18730 #if defined(HAVE_SS7)
18731 memset(linksets, 0, sizeof(linksets));
18732 for (y = 0; y < NUM_SPANS; y++) {
18733 sig_ss7_init_linkset(&linksets[y].ss7);
18734 }
18735 ss7_set_error(dahdi_ss7_error);
18736 ss7_set_message(dahdi_ss7_message);
18737 #endif
18738 res = setup_dahdi(0);
18739
18740 if (res)
18741 return AST_MODULE_LOAD_DECLINE;
18742 if (ast_channel_register(&dahdi_tech)) {
18743 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18744 __unload_module();
18745 return AST_MODULE_LOAD_FAILURE;
18746 }
18747 #ifdef HAVE_PRI
18748 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18749 #endif
18750 #if defined(HAVE_SS7)
18751 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18752 #endif
18753 #ifdef HAVE_OPENR2
18754 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18755 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18756 #endif
18757
18758 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18759
18760 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18761 memset(round_robin, 0, sizeof(round_robin));
18762 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18763 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18764 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18765 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18766 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18767 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18768 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18769
18770 ast_cond_init(&ss_thread_complete, NULL);
18771
18772 return res;
18773 }
18774
18775 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18776 {
18777 #define END_SILENCE_LEN 400
18778 #define HEADER_MS 50
18779 #define TRAILER_MS 5
18780 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18781 #define ASCII_BYTES_PER_CHAR 80
18782
18783 unsigned char *buf,*mybuf;
18784 struct dahdi_pvt *p = c->tech_pvt;
18785 struct pollfd fds[1];
18786 int size,res,fd,len,x;
18787 int bytes=0;
18788
18789 float cr = 1.0;
18790 float ci = 0.0;
18791 float scont = 0.0;
18792 int idx;
18793
18794 idx = dahdi_get_index(c, p, 0);
18795 if (idx < 0) {
18796 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18797 return -1;
18798 }
18799 if (!text[0]) return(0);
18800 if ((!p->tdd) && (!p->mate)) return(0);
18801 if (p->mate)
18802 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18803 else
18804 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18805 if (!buf)
18806 return -1;
18807 mybuf = buf;
18808 if (p->mate) {
18809 int codec = AST_LAW(p);
18810 for (x = 0; x < HEADER_MS; x++) {
18811 PUT_CLID_MARKMS;
18812 }
18813
18814 for (x = 0; text[x]; x++) {
18815 PUT_CLID(text[x]);
18816 }
18817 for (x = 0; x < TRAILER_MS; x++) {
18818 PUT_CLID_MARKMS;
18819 }
18820 len = bytes;
18821 buf = mybuf;
18822 } else {
18823 len = tdd_generate(p->tdd, buf, text);
18824 if (len < 1) {
18825 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18826 ast_free(mybuf);
18827 return -1;
18828 }
18829 }
18830 memset(buf + len, 0x7f, END_SILENCE_LEN);
18831 len += END_SILENCE_LEN;
18832 fd = p->subs[idx].dfd;
18833 while (len) {
18834 if (ast_check_hangup(c)) {
18835 ast_free(mybuf);
18836 return -1;
18837 }
18838 size = len;
18839 if (size > READ_SIZE)
18840 size = READ_SIZE;
18841 fds[0].fd = fd;
18842 fds[0].events = POLLOUT | POLLPRI;
18843 fds[0].revents = 0;
18844 res = poll(fds, 1, -1);
18845 if (!res) {
18846 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18847 continue;
18848 }
18849
18850 if (fds[0].revents & POLLPRI) {
18851 ast_free(mybuf);
18852 return -1;
18853 }
18854 if (!(fds[0].revents & POLLOUT)) {
18855 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18856 continue;
18857 }
18858 res = write(fd, buf, size);
18859 if (res != size) {
18860 if (res == -1) {
18861 ast_free(mybuf);
18862 return -1;
18863 }
18864 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18865 break;
18866 }
18867 len -= size;
18868 buf += size;
18869 }
18870 ast_free(mybuf);
18871 return(0);
18872 }
18873
18874
18875 static int reload(void)
18876 {
18877 int res = 0;
18878
18879 res = setup_dahdi(1);
18880 if (res) {
18881 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18882 return -1;
18883 }
18884 return 0;
18885 }
18886
18887
18888
18889
18890
18891 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18892 .load = load_module,
18893 .unload = unload_module,
18894 .reload = reload,
18895 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18896 .nonoptreq = "res_smdi",
18897 );