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: 404784 $")
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 void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03145 {
03146 int x;
03147
03148 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03149 switch (x) {
03150 case DAHDI_EVENT_NONE:
03151 break;
03152 case DAHDI_EVENT_ALARM:
03153 case DAHDI_EVENT_NOALARM:
03154 if (sig_pri_is_alarm_ignored(pri)) {
03155 break;
03156 }
03157
03158 default:
03159 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03160 event2str(x), x, pri->span);
03161 break;
03162 }
03163
03164 switch (x) {
03165 case DAHDI_EVENT_ALARM:
03166 pri_event_alarm(pri, index, 0);
03167 break;
03168 case DAHDI_EVENT_NOALARM:
03169 pri_event_noalarm(pri, index, 0);
03170 break;
03171 default:
03172 break;
03173 }
03174 }
03175 #endif
03176
03177 #if defined(HAVE_PRI)
03178 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03179 {
03180 struct dahdi_pvt *p = pvt;
03181
03182 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03183 }
03184 #endif
03185
03186 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03198 {
03199 struct dahdi_pvt *p = pvt;
03200
03201 ast_copy_string(p->cid_num,
03202 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03203 sizeof(p->cid_num));
03204 ast_copy_string(p->cid_name,
03205 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03206 sizeof(p->cid_name));
03207 ast_copy_string(p->cid_subaddr,
03208 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03209 sizeof(p->cid_subaddr));
03210 p->cid_ton = caller->id.number.plan;
03211 p->callingpres = ast_party_id_presentation(&caller->id);
03212 if (caller->id.tag) {
03213 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03214 }
03215 ast_copy_string(p->cid_ani,
03216 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03217 sizeof(p->cid_ani));
03218 p->cid_ani2 = caller->ani2;
03219 }
03220 #endif
03221
03222 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233 static void my_set_dnid(void *pvt, const char *dnid)
03234 {
03235 struct dahdi_pvt *p = pvt;
03236
03237 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03238 }
03239 #endif
03240
03241 #if defined(HAVE_PRI)
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252 static void my_set_rdnis(void *pvt, const char *rdnis)
03253 {
03254 struct dahdi_pvt *p = pvt;
03255
03256 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03257 }
03258 #endif
03259
03260 #if defined(HAVE_PRI)
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03286 {
03287 char *dial;
03288 struct dahdi_pvt *pvt;
03289 AST_DECLARE_APP_ARGS(args,
03290 AST_APP_ARG(tech);
03291 AST_APP_ARG(group);
03292
03293
03294
03295 );
03296
03297 pvt = priv;
03298 dial = ast_strdupa(pvt->dialstring);
03299 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03300 if (!args.tech) {
03301 ast_copy_string(buf, pvt->dialstring, buf_size);
03302 return;
03303 }
03304 if (!args.group) {
03305
03306 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03307 return;
03308 }
03309 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03310
03311
03312 ast_copy_string(buf, pvt->dialstring, buf_size);
03313 return;
03314 }
03315
03316 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03317 }
03318 #endif
03319
03320 #if defined(HAVE_PRI)
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03333 {
03334 unsigned idx;
03335 unsigned num_b_chans;
03336 unsigned in_use;
03337 unsigned in_alarm;
03338 enum ast_device_state new_state;
03339
03340
03341 num_b_chans = 0;
03342 in_use = 0;
03343 in_alarm = 1;
03344 for (idx = pri->numchans; idx--;) {
03345 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03346
03347 ++num_b_chans;
03348 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03349 ++in_use;
03350 }
03351 if (!pri->pvts[idx]->inalarm) {
03352
03353 in_alarm = 0;
03354 }
03355 }
03356 }
03357
03358
03359 if (in_alarm) {
03360 new_state = AST_DEVICE_UNAVAILABLE;
03361 } else {
03362 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03363 }
03364 if (pri->congestion_devstate != new_state) {
03365 pri->congestion_devstate = new_state;
03366 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03367 }
03368 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03369
03370 if (in_alarm) {
03371 new_state = AST_DEVICE_UNAVAILABLE;
03372 } else if (!in_use) {
03373 new_state = AST_DEVICE_NOT_INUSE;
03374 } else if (!pri->user_busy_threshold) {
03375 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03376 } else {
03377 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03378 : AST_DEVICE_BUSY;
03379 }
03380 if (pri->threshold_devstate != new_state) {
03381 pri->threshold_devstate = new_state;
03382 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03383 }
03384 #endif
03385 }
03386 #endif
03387
03388 #if defined(HAVE_PRI)
03389
03390
03391
03392
03393
03394
03395
03396 static void my_module_ref(void)
03397 {
03398 ast_module_ref(ast_module_info->self);
03399 }
03400 #endif
03401
03402 #if defined(HAVE_PRI)
03403
03404
03405
03406
03407
03408
03409
03410 static void my_module_unref(void)
03411 {
03412 ast_module_unref(ast_module_info->self);
03413 }
03414 #endif
03415
03416 #if defined(HAVE_PRI)
03417 #if defined(HAVE_PRI_CALL_WAITING)
03418 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03419 #endif
03420 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03421
03422 static struct sig_pri_callback dahdi_pri_callbacks =
03423 {
03424 .handle_dchan_exception = my_handle_dchan_exception,
03425 .play_tone = my_pri_play_tone,
03426 .set_echocanceller = my_set_echocanceller,
03427 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03428 .lock_private = my_lock_private,
03429 .unlock_private = my_unlock_private,
03430 .new_ast_channel = my_new_pri_ast_channel,
03431 .fixup_chans = my_pri_fixup_chans,
03432 .set_alarm = my_set_alarm,
03433 .set_dialing = my_set_dialing,
03434 .set_outgoing = my_set_outgoing,
03435 .set_digital = my_set_digital,
03436 .set_callerid = my_set_callerid,
03437 .set_dnid = my_set_dnid,
03438 .set_rdnis = my_set_rdnis,
03439 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03440 #if defined(HAVE_PRI_CALL_WAITING)
03441 .init_config = my_pri_init_config,
03442 #endif
03443 .get_orig_dialstring = my_get_orig_dialstring,
03444 .make_cc_dialstring = my_pri_make_cc_dialstring,
03445 .update_span_devstate = dahdi_pri_update_span_devstate,
03446 .module_ref = my_module_ref,
03447 .module_unref = my_module_unref,
03448 .dial_digits = my_pri_dial_digits,
03449 .open_media = my_pri_ss7_open_media,
03450 .ami_channel_event = my_ami_channel_event,
03451 };
03452 #endif
03453
03454 #if defined(HAVE_SS7)
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03466 {
03467 int event;
03468
03469 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03470 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03471 linkset->span, which);
03472 return;
03473 }
03474 switch (event) {
03475 case DAHDI_EVENT_NONE:
03476 break;
03477 case DAHDI_EVENT_ALARM:
03478 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03479 event2str(event), event, linkset->span, which);
03480 sig_ss7_link_alarm(linkset, which);
03481 break;
03482 case DAHDI_EVENT_NOALARM:
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_noalarm(linkset, which);
03486 break;
03487 default:
03488 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03489 event2str(event), event, linkset->span, which);
03490 break;
03491 }
03492 }
03493 #endif
03494
03495 #if defined(HAVE_SS7)
03496 static void my_ss7_set_loopback(void *pvt, int enable)
03497 {
03498 struct dahdi_pvt *p = pvt;
03499
03500 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03501 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03502 strerror(errno));
03503 }
03504 }
03505 #endif
03506
03507 #if defined(HAVE_SS7)
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522 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)
03523 {
03524 struct dahdi_pvt *p = pvt;
03525 int audio;
03526 int newlaw;
03527
03528
03529 audio = 1;
03530 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03531 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03532 p->channel, audio, strerror(errno));
03533
03534 if (law != SIG_SS7_DEFLAW) {
03535 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03536 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03537 }
03538
03539 ast_copy_string(p->exten, exten, sizeof(p->exten));
03540
03541 newlaw = -1;
03542 switch (law) {
03543 case SIG_SS7_DEFLAW:
03544 newlaw = 0;
03545 break;
03546 case SIG_SS7_ALAW:
03547 newlaw = DAHDI_LAW_ALAW;
03548 break;
03549 case SIG_SS7_ULAW:
03550 newlaw = DAHDI_LAW_MULAW;
03551 break;
03552 }
03553 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03554 }
03555 #endif
03556
03557 #if defined(HAVE_SS7)
03558 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03559 {
03560 switch (tone) {
03561 case SIG_SS7_TONE_RINGTONE:
03562 return DAHDI_TONE_RINGTONE;
03563 case SIG_SS7_TONE_STUTTER:
03564 return DAHDI_TONE_STUTTER;
03565 case SIG_SS7_TONE_CONGESTION:
03566 return DAHDI_TONE_CONGESTION;
03567 case SIG_SS7_TONE_DIALTONE:
03568 return DAHDI_TONE_DIALTONE;
03569 case SIG_SS7_TONE_DIALRECALL:
03570 return DAHDI_TONE_DIALRECALL;
03571 case SIG_SS7_TONE_INFO:
03572 return DAHDI_TONE_INFO;
03573 case SIG_SS7_TONE_BUSY:
03574 return DAHDI_TONE_BUSY;
03575 default:
03576 return -1;
03577 }
03578 }
03579 #endif
03580
03581 #if defined(HAVE_SS7)
03582 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03583 {
03584 struct dahdi_pvt *p = pvt;
03585
03586 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03587 }
03588 #endif
03589
03590 #if defined(HAVE_SS7)
03591 static struct sig_ss7_callback dahdi_ss7_callbacks =
03592 {
03593 .lock_private = my_lock_private,
03594 .unlock_private = my_unlock_private,
03595
03596 .set_echocanceller = my_set_echocanceller,
03597 .set_loopback = my_ss7_set_loopback,
03598
03599 .new_ast_channel = my_new_ss7_ast_channel,
03600 .play_tone = my_ss7_play_tone,
03601
03602 .handle_link_exception = my_handle_link_exception,
03603 .set_alarm = my_set_alarm,
03604 .set_dialing = my_set_dialing,
03605 .set_outgoing = my_set_outgoing,
03606 .set_digital = my_set_digital,
03607 .set_inservice = my_set_inservice,
03608 .set_locallyblocked = my_set_locallyblocked,
03609 .set_remotelyblocked = my_set_remotelyblocked,
03610 .set_callerid = my_set_callerid,
03611 .set_dnid = my_set_dnid,
03612 .open_media = my_pri_ss7_open_media,
03613 };
03614 #endif
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634 static void notify_message(char *mailbox_full, int thereornot)
03635 {
03636 char s[sizeof(mwimonitornotify) + 80];
03637 struct ast_event *event;
03638 char *mailbox, *context;
03639
03640
03641 context = mailbox = ast_strdupa(mailbox_full);
03642 strsep(&context, "@");
03643 if (ast_strlen_zero(context))
03644 context = "default";
03645
03646 if (!(event = ast_event_new(AST_EVENT_MWI,
03647 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03648 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03649 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03650 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03651 AST_EVENT_IE_END))) {
03652 return;
03653 }
03654
03655 ast_event_queue_and_cache(event);
03656
03657 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03658 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03659 ast_safe_system(s);
03660 }
03661 }
03662
03663 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03664 {
03665 struct dahdi_pvt *p = pvt;
03666
03667 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03668 return;
03669
03670 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03671 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03672 notify_message(p->mailbox, 1);
03673 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03674 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03675 notify_message(p->mailbox, 0);
03676 }
03677
03678
03679 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03680 ast_hangup(chan);
03681 return;
03682 }
03683 }
03684
03685 static int my_have_progressdetect(void *pvt)
03686 {
03687 struct dahdi_pvt *p = pvt;
03688
03689 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03690 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03691 return 1;
03692 } else {
03693
03694 return 0;
03695 }
03696 }
03697
03698 static struct analog_callback dahdi_analog_callbacks =
03699 {
03700 .play_tone = my_play_tone,
03701 .get_event = my_get_event,
03702 .wait_event = my_wait_event,
03703 .is_off_hook = my_is_off_hook,
03704 .set_echocanceller = my_set_echocanceller,
03705 .ring = my_ring,
03706 .flash = my_flash,
03707 .off_hook = my_off_hook,
03708 .dial_digits = my_dial_digits,
03709 .train_echocanceller = my_train_echocanceller,
03710 .on_hook = my_on_hook,
03711 .is_dialing = my_is_dialing,
03712 .allocate_sub = my_allocate_sub,
03713 .unallocate_sub = my_unallocate_sub,
03714 .swap_subs = my_swap_subchannels,
03715 .has_voicemail = my_has_voicemail,
03716 .check_for_conference = my_check_for_conference,
03717 .conf_add = my_conf_add,
03718 .conf_del = my_conf_del,
03719 .complete_conference_update = my_complete_conference_update,
03720 .start = my_start,
03721 .all_subchannels_hungup = my_all_subchannels_hungup,
03722 .lock_private = my_lock_private,
03723 .unlock_private = my_unlock_private,
03724 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03725 .handle_dtmf = my_handle_dtmf,
03726 .wink = my_wink,
03727 .new_ast_channel = my_new_analog_ast_channel,
03728 .dsp_set_digitmode = my_dsp_set_digitmode,
03729 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03730 .send_callerid = my_send_callerid,
03731 .callwait = my_callwait,
03732 .stop_callwait = my_stop_callwait,
03733 .get_callerid = my_get_callerid,
03734 .start_cid_detect = my_start_cid_detect,
03735 .stop_cid_detect = my_stop_cid_detect,
03736 .handle_notify_message = my_handle_notify_message,
03737 .increase_ss_count = my_increase_ss_count,
03738 .decrease_ss_count = my_decrease_ss_count,
03739 .distinctive_ring = my_distinctive_ring,
03740 .set_linear_mode = my_set_linear_mode,
03741 .set_inthreeway = my_set_inthreeway,
03742 .get_and_handle_alarms = my_get_and_handle_alarms,
03743 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03744 .get_sub_fd = my_get_sub_fd,
03745 .set_cadence = my_set_cadence,
03746 .set_alarm = my_set_alarm,
03747 .set_dialing = my_set_dialing,
03748 .set_outgoing = my_set_outgoing,
03749 .set_ringtimeout = my_set_ringtimeout,
03750 .set_waitingfordt = my_set_waitingfordt,
03751 .check_waitingfordt = my_check_waitingfordt,
03752 .set_confirmanswer = my_set_confirmanswer,
03753 .check_confirmanswer = my_check_confirmanswer,
03754 .set_callwaiting = my_set_callwaiting,
03755 .cancel_cidspill = my_cancel_cidspill,
03756 .confmute = my_confmute,
03757 .set_pulsedial = my_set_pulsedial,
03758 .set_new_owner = my_set_new_owner,
03759 .get_orig_dialstring = my_get_orig_dialstring,
03760 .set_needringing = my_set_needringing,
03761 .set_polarity = my_set_polarity,
03762 .start_polarityswitch = my_start_polarityswitch,
03763 .answer_polarityswitch = my_answer_polarityswitch,
03764 .hangup_polarityswitch = my_hangup_polarityswitch,
03765 .have_progressdetect = my_have_progressdetect,
03766 };
03767
03768
03769 static struct dahdi_pvt *round_robin[32];
03770
03771 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03772 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03773 {
03774 int res;
03775 if (p->subs[SUB_REAL].owner == ast)
03776 res = 0;
03777 else if (p->subs[SUB_CALLWAIT].owner == ast)
03778 res = 1;
03779 else if (p->subs[SUB_THREEWAY].owner == ast)
03780 res = 2;
03781 else {
03782 res = -1;
03783 if (!nullok)
03784 ast_log(LOG_WARNING,
03785 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03786 ast ? ast->name : "", p->channel, fname, line);
03787 }
03788 return res;
03789 }
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03807 {
03808 for (;;) {
03809 if (!pvt->subs[sub_idx].owner) {
03810
03811 break;
03812 }
03813 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03814
03815 break;
03816 }
03817
03818 DEADLOCK_AVOIDANCE(&pvt->lock);
03819 }
03820 }
03821
03822 static void wakeup_sub(struct dahdi_pvt *p, int a)
03823 {
03824 dahdi_lock_sub_owner(p, a);
03825 if (p->subs[a].owner) {
03826 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03827 ast_channel_unlock(p->subs[a].owner);
03828 }
03829 }
03830
03831 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03832 {
03833 for (;;) {
03834 if (p->owner) {
03835 if (ast_channel_trylock(p->owner)) {
03836 DEADLOCK_AVOIDANCE(&p->lock);
03837 } else {
03838 ast_queue_frame(p->owner, f);
03839 ast_channel_unlock(p->owner);
03840 break;
03841 }
03842 } else
03843 break;
03844 }
03845 }
03846
03847 static void handle_clear_alarms(struct dahdi_pvt *p)
03848 {
03849 #if defined(HAVE_PRI)
03850 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03851 return;
03852 }
03853 #endif
03854
03855 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03856 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03857 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03858 }
03859 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03860 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03861 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03862 }
03863 }
03864
03865 #ifdef HAVE_OPENR2
03866
03867 static int dahdi_r2_answer(struct dahdi_pvt *p)
03868 {
03869 int res = 0;
03870
03871
03872
03873 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03874 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03875 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03876 if (!double_answer) {
03877
03878
03879 res = openr2_chan_answer_call(p->r2chan);
03880 } else if (wants_double_answer) {
03881 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03882 } else {
03883 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03884 }
03885 #else
03886 res = openr2_chan_answer_call(p->r2chan);
03887 #endif
03888 return res;
03889 }
03890
03891
03892
03893
03894 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03895 {
03896 openr2_calling_party_category_t cat;
03897 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03898 struct dahdi_pvt *p = c->tech_pvt;
03899 if (ast_strlen_zero(catstr)) {
03900 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03901 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03902 return p->mfcr2_category;
03903 }
03904 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03905 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03906 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03907 return p->mfcr2_category;
03908 }
03909 ast_debug(1, "Using category %s\n", catstr);
03910 return cat;
03911 }
03912
03913 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03914 {
03915 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03916 ast_mutex_lock(&p->lock);
03917 if (p->mfcr2call) {
03918 ast_mutex_unlock(&p->lock);
03919
03920
03921
03922
03923
03924 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03925 return;
03926 }
03927 p->mfcr2call = 1;
03928
03929 p->cid_name[0] = '\0';
03930 p->cid_num[0] = '\0';
03931 p->cid_subaddr[0] = '\0';
03932 p->rdnis[0] = '\0';
03933 p->exten[0] = '\0';
03934 p->mfcr2_ani_index = '\0';
03935 p->mfcr2_dnis_index = '\0';
03936 p->mfcr2_dnis_matched = 0;
03937 p->mfcr2_answer_pending = 0;
03938 p->mfcr2_call_accepted = 0;
03939 ast_mutex_unlock(&p->lock);
03940 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03941 }
03942
03943 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03944 {
03945 int res;
03946 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03947 ast_mutex_lock(&p->lock);
03948 p->inalarm = alarm ? 1 : 0;
03949 if (p->inalarm) {
03950 res = get_alarms(p);
03951 handle_alarms(p, res);
03952 } else {
03953 handle_clear_alarms(p);
03954 }
03955 ast_mutex_unlock(&p->lock);
03956 }
03957
03958 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03959 {
03960 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03961 }
03962
03963 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03964 {
03965 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03966 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03967 if (p->owner) {
03968 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03969 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03970 }
03971 ast_mutex_lock(&p->lock);
03972 p->mfcr2call = 0;
03973 ast_mutex_unlock(&p->lock);
03974 }
03975
03976 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03977 {
03978 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03979 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03980 p->channel, openr2_proto_get_disconnect_string(cause));
03981
03982 openr2_chan_set_idle(p->r2chan);
03983 ast_mutex_lock(&p->lock);
03984 p->mfcr2call = 0;
03985 ast_mutex_unlock(&p->lock);
03986 }
03987 }
03988
03989 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03990 {
03991 struct dahdi_pvt *p;
03992 struct ast_channel *c;
03993 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03994 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03995 openr2_proto_get_category_string(category));
03996 p = openr2_chan_get_client_data(r2chan);
03997
03998 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03999 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04000 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04001 return;
04002 }
04003 ast_mutex_lock(&p->lock);
04004 p->mfcr2_recvd_category = category;
04005
04006 if (!p->use_callerid) {
04007 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04008 p->cid_num[0] = 0;
04009 p->cid_name[0] = 0;
04010 }
04011
04012 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04013 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04014 p->exten[0] = 's';
04015 p->exten[1] = 0;
04016 }
04017 ast_mutex_unlock(&p->lock);
04018 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04019 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04020 p->channel, p->exten, p->context);
04021 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04022 return;
04023 }
04024 if (!p->mfcr2_accept_on_offer) {
04025
04026 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04027 if (c) {
04028
04029
04030
04031 return;
04032 }
04033 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04034 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04035 } else if (p->mfcr2_charge_calls) {
04036 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04037 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04038 } else {
04039 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04040 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04041 }
04042 }
04043
04044 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04045 {
04046 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04047 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04048 ast_mutex_lock(&p->lock);
04049 p->mfcr2call = 0;
04050 ast_mutex_unlock(&p->lock);
04051 }
04052
04053 static void dahdi_enable_ec(struct dahdi_pvt *p);
04054 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04055 {
04056 struct dahdi_pvt *p = NULL;
04057 struct ast_channel *c = NULL;
04058 p = openr2_chan_get_client_data(r2chan);
04059 dahdi_enable_ec(p);
04060 p->mfcr2_call_accepted = 1;
04061
04062 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04063 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04064
04065
04066
04067
04068 if (!p->mfcr2_accept_on_offer) {
04069 openr2_chan_disable_read(r2chan);
04070 if (p->mfcr2_answer_pending) {
04071 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04072 dahdi_r2_answer(p);
04073 }
04074 return;
04075 }
04076 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04077 if (c) {
04078
04079
04080 openr2_chan_disable_read(r2chan);
04081 return;
04082 }
04083 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04084
04085 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04086 return;
04087 }
04088
04089 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04090 p->subs[SUB_REAL].needringing = 1;
04091 p->dialing = 0;
04092
04093 openr2_chan_disable_read(r2chan);
04094 }
04095
04096 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04097 {
04098 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04099 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04100 p->subs[SUB_REAL].needanswer = 1;
04101 }
04102
04103 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04104 {
04105
04106 }
04107
04108 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04109 {
04110 switch (cause) {
04111 case OR2_CAUSE_BUSY_NUMBER:
04112 return AST_CAUSE_BUSY;
04113 case OR2_CAUSE_NETWORK_CONGESTION:
04114 return AST_CAUSE_CONGESTION;
04115 case OR2_CAUSE_OUT_OF_ORDER:
04116 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04117 case OR2_CAUSE_UNALLOCATED_NUMBER:
04118 return AST_CAUSE_UNREGISTERED;
04119 case OR2_CAUSE_NO_ANSWER:
04120 return AST_CAUSE_NO_ANSWER;
04121 case OR2_CAUSE_NORMAL_CLEARING:
04122 return AST_CAUSE_NORMAL_CLEARING;
04123 case OR2_CAUSE_UNSPECIFIED:
04124 default:
04125 return AST_CAUSE_NOTDEFINED;
04126 }
04127 }
04128
04129 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04130 {
04131 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04132 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04133 ast_mutex_lock(&p->lock);
04134 if (!p->owner) {
04135 ast_mutex_unlock(&p->lock);
04136
04137 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04138 return;
04139 }
04140
04141
04142 if (p->owner->_state == AST_STATE_UP) {
04143 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04144 ast_mutex_unlock(&p->lock);
04145 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04146
04147 switch (cause) {
04148 case OR2_CAUSE_BUSY_NUMBER:
04149 p->subs[SUB_REAL].needbusy = 1;
04150 break;
04151 case OR2_CAUSE_NETWORK_CONGESTION:
04152 case OR2_CAUSE_OUT_OF_ORDER:
04153 case OR2_CAUSE_UNALLOCATED_NUMBER:
04154 case OR2_CAUSE_NO_ANSWER:
04155 case OR2_CAUSE_UNSPECIFIED:
04156 case OR2_CAUSE_NORMAL_CLEARING:
04157 p->subs[SUB_REAL].needcongestion = 1;
04158 break;
04159 default:
04160 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04161 }
04162 ast_mutex_unlock(&p->lock);
04163 } else {
04164 ast_mutex_unlock(&p->lock);
04165
04166
04167 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04168 }
04169 }
04170
04171 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04172 {
04173 switch (level) {
04174 case OR2_LOG_NOTICE:
04175 ast_verbose("%s", logmessage);
04176 break;
04177 case OR2_LOG_WARNING:
04178 ast_log(LOG_WARNING, "%s", logmessage);
04179 break;
04180 case OR2_LOG_ERROR:
04181 ast_log(LOG_ERROR, "%s", logmessage);
04182 break;
04183 case OR2_LOG_STACK_TRACE:
04184 case OR2_LOG_MF_TRACE:
04185 case OR2_LOG_CAS_TRACE:
04186 case OR2_LOG_DEBUG:
04187 case OR2_LOG_EX_DEBUG:
04188 ast_log(LOG_DEBUG, "%s", logmessage);
04189 break;
04190 default:
04191 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04192 ast_log(LOG_DEBUG, "%s", logmessage);
04193 break;
04194 }
04195 }
04196
04197 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04198 {
04199 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04200 ast_mutex_lock(&p->lock);
04201 p->remotelyblocked = 1;
04202 ast_mutex_unlock(&p->lock);
04203 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04204 }
04205
04206 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04207 {
04208 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04209 ast_mutex_lock(&p->lock);
04210 p->remotelyblocked = 0;
04211 ast_mutex_unlock(&p->lock);
04212 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04213 }
04214
04215 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04216 __attribute__((format (printf, 3, 0)));
04217 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04218 {
04219 #define CONTEXT_TAG "Context - "
04220 char logmsg[256];
04221 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04222 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04223 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04224 dahdi_r2_write_log(level, completemsg);
04225 #undef CONTEXT_TAG
04226 }
04227
04228 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04229 __attribute__((format (printf, 3, 0)));
04230 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04231 {
04232 #define CHAN_TAG "Chan "
04233 char logmsg[256];
04234 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04235 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04236 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04237 dahdi_r2_write_log(level, completemsg);
04238 }
04239
04240 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04241 {
04242 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04243
04244 if (p->immediate) {
04245 return 0;
04246 }
04247 p->exten[p->mfcr2_dnis_index] = digit;
04248 p->rdnis[p->mfcr2_dnis_index] = digit;
04249 p->mfcr2_dnis_index++;
04250 p->exten[p->mfcr2_dnis_index] = 0;
04251 p->rdnis[p->mfcr2_dnis_index] = 0;
04252
04253 if ((p->mfcr2_dnis_matched ||
04254 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04255 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04256 return 0;
04257 }
04258
04259 return 1;
04260 }
04261
04262 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04263 {
04264 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04265 p->cid_num[p->mfcr2_ani_index] = digit;
04266 p->cid_name[p->mfcr2_ani_index] = digit;
04267 p->mfcr2_ani_index++;
04268 p->cid_num[p->mfcr2_ani_index] = 0;
04269 p->cid_name[p->mfcr2_ani_index] = 0;
04270 }
04271
04272 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04273 {
04274 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04275 }
04276
04277 static openr2_event_interface_t dahdi_r2_event_iface = {
04278 .on_call_init = dahdi_r2_on_call_init,
04279 .on_call_offered = dahdi_r2_on_call_offered,
04280 .on_call_accepted = dahdi_r2_on_call_accepted,
04281 .on_call_answered = dahdi_r2_on_call_answered,
04282 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04283 .on_call_end = dahdi_r2_on_call_end,
04284 .on_call_read = dahdi_r2_on_call_read,
04285 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04286 .on_os_error = dahdi_r2_on_os_error,
04287 .on_protocol_error = dahdi_r2_on_protocol_error,
04288 .on_line_blocked = dahdi_r2_on_line_blocked,
04289 .on_line_idle = dahdi_r2_on_line_idle,
04290
04291 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04292 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04293 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04294
04295 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04296 };
04297
04298 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04299 {
04300 return AST_ALAW(sample);
04301 }
04302
04303 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04304 {
04305 return AST_LIN2A(sample);
04306 }
04307
04308 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04309 dahdi_r2_alaw_to_linear,
04310 dahdi_r2_linear_to_alaw
04311 };
04312
04313 #endif
04314
04315 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04316 {
04317 int tchan;
04318 int tinthreeway;
04319 struct ast_channel *towner;
04320
04321 ast_debug(1, "Swapping %d and %d\n", a, b);
04322
04323 tchan = p->subs[a].chan;
04324 towner = p->subs[a].owner;
04325 tinthreeway = p->subs[a].inthreeway;
04326
04327 p->subs[a].chan = p->subs[b].chan;
04328 p->subs[a].owner = p->subs[b].owner;
04329 p->subs[a].inthreeway = p->subs[b].inthreeway;
04330
04331 p->subs[b].chan = tchan;
04332 p->subs[b].owner = towner;
04333 p->subs[b].inthreeway = tinthreeway;
04334
04335 if (p->subs[a].owner)
04336 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04337 if (p->subs[b].owner)
04338 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04339 wakeup_sub(p, a);
04340 wakeup_sub(p, b);
04341 }
04342
04343 static int dahdi_open(char *fn)
04344 {
04345 int fd;
04346 int isnum;
04347 int chan = 0;
04348 int bs;
04349 int x;
04350 isnum = 1;
04351 for (x = 0; x < strlen(fn); x++) {
04352 if (!isdigit(fn[x])) {
04353 isnum = 0;
04354 break;
04355 }
04356 }
04357 if (isnum) {
04358 chan = atoi(fn);
04359 if (chan < 1) {
04360 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04361 return -1;
04362 }
04363 fn = "/dev/dahdi/channel";
04364 }
04365 fd = open(fn, O_RDWR | O_NONBLOCK);
04366 if (fd < 0) {
04367 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04368 return -1;
04369 }
04370 if (chan) {
04371 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04372 x = errno;
04373 close(fd);
04374 errno = x;
04375 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04376 return -1;
04377 }
04378 }
04379 bs = READ_SIZE;
04380 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04381 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04382 x = errno;
04383 close(fd);
04384 errno = x;
04385 return -1;
04386 }
04387 return fd;
04388 }
04389
04390 static void dahdi_close(int fd)
04391 {
04392 if (fd > 0)
04393 close(fd);
04394 }
04395
04396 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04397 {
04398 dahdi_close(chan_pvt->subs[sub_num].dfd);
04399 chan_pvt->subs[sub_num].dfd = -1;
04400 }
04401
04402 #if defined(HAVE_PRI)
04403 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04404 {
04405 dahdi_close(pri->pri.fds[fd_num]);
04406 pri->pri.fds[fd_num] = -1;
04407 }
04408 #endif
04409
04410 #if defined(HAVE_SS7)
04411 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04412 {
04413 dahdi_close(ss7->ss7.fds[fd_num]);
04414 ss7->ss7.fds[fd_num] = -1;
04415 }
04416 #endif
04417
04418 static int dahdi_setlinear(int dfd, int linear)
04419 {
04420 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04421 }
04422
04423
04424 static int alloc_sub(struct dahdi_pvt *p, int x)
04425 {
04426 struct dahdi_bufferinfo bi;
04427 int res;
04428 if (p->subs[x].dfd >= 0) {
04429 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04430 return -1;
04431 }
04432
04433 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04434 if (p->subs[x].dfd <= -1) {
04435 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04436 return -1;
04437 }
04438
04439 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04440 if (!res) {
04441 bi.txbufpolicy = p->buf_policy;
04442 bi.rxbufpolicy = p->buf_policy;
04443 bi.numbufs = p->buf_no;
04444 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04445 if (res < 0) {
04446 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04447 }
04448 } else
04449 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04450
04451 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04452 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04453 dahdi_close_sub(p, x);
04454 p->subs[x].dfd = -1;
04455 return -1;
04456 }
04457 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04458 return 0;
04459 }
04460
04461 static int unalloc_sub(struct dahdi_pvt *p, int x)
04462 {
04463 if (!x) {
04464 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04465 return -1;
04466 }
04467 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04468 dahdi_close_sub(p, x);
04469 p->subs[x].linear = 0;
04470 p->subs[x].chan = 0;
04471 p->subs[x].owner = NULL;
04472 p->subs[x].inthreeway = 0;
04473 p->polarity = POLARITY_IDLE;
04474 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04475 return 0;
04476 }
04477
04478 static int digit_to_dtmfindex(char digit)
04479 {
04480 if (isdigit(digit))
04481 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04482 else if (digit >= 'A' && digit <= 'D')
04483 return DAHDI_TONE_DTMF_A + (digit - 'A');
04484 else if (digit >= 'a' && digit <= 'd')
04485 return DAHDI_TONE_DTMF_A + (digit - 'a');
04486 else if (digit == '*')
04487 return DAHDI_TONE_DTMF_s;
04488 else if (digit == '#')
04489 return DAHDI_TONE_DTMF_p;
04490 else
04491 return -1;
04492 }
04493
04494 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04495 {
04496 struct dahdi_pvt *pvt;
04497 int idx;
04498 int dtmf = -1;
04499 int res;
04500
04501 pvt = chan->tech_pvt;
04502
04503 ast_mutex_lock(&pvt->lock);
04504
04505 idx = dahdi_get_index(chan, pvt, 0);
04506
04507 if ((idx != SUB_REAL) || !pvt->owner)
04508 goto out;
04509
04510 #ifdef HAVE_PRI
04511 switch (pvt->sig) {
04512 case SIG_PRI_LIB_HANDLE_CASES:
04513 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04514 if (!res)
04515 goto out;
04516 break;
04517 default:
04518 break;
04519 }
04520 #endif
04521 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04522 goto out;
04523
04524 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04525 struct dahdi_dialoperation zo = {
04526 .op = DAHDI_DIAL_OP_APPEND,
04527 };
04528
04529 zo.dialstr[0] = 'T';
04530 zo.dialstr[1] = digit;
04531 zo.dialstr[2] = '\0';
04532 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04533 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04534 chan->name, digit, strerror(errno));
04535 else
04536 pvt->dialing = 1;
04537 } else {
04538 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04539 chan->name, digit);
04540 pvt->dialing = 1;
04541 pvt->begindigit = digit;
04542 }
04543
04544 out:
04545 ast_mutex_unlock(&pvt->lock);
04546
04547 return 0;
04548 }
04549
04550 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04551 {
04552 struct dahdi_pvt *pvt;
04553 int res = 0;
04554 int idx;
04555 int x;
04556
04557 pvt = chan->tech_pvt;
04558
04559 ast_mutex_lock(&pvt->lock);
04560
04561 idx = dahdi_get_index(chan, pvt, 0);
04562
04563 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04564 goto out;
04565
04566 #ifdef HAVE_PRI
04567
04568 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04569 goto out;
04570 }
04571 #endif
04572
04573 if (pvt->begindigit) {
04574 x = -1;
04575 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04576 chan->name, digit);
04577 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04578 pvt->dialing = 0;
04579 pvt->begindigit = 0;
04580 }
04581
04582 out:
04583 ast_mutex_unlock(&pvt->lock);
04584
04585 return res;
04586 }
04587
04588 static const char * const events[] = {
04589 "No event",
04590 "On hook",
04591 "Ring/Answered",
04592 "Wink/Flash",
04593 "Alarm",
04594 "No more alarm",
04595 "HDLC Abort",
04596 "HDLC Overrun",
04597 "HDLC Bad FCS",
04598 "Dial Complete",
04599 "Ringer On",
04600 "Ringer Off",
04601 "Hook Transition Complete",
04602 "Bits Changed",
04603 "Pulse Start",
04604 "Timer Expired",
04605 "Timer Ping",
04606 "Polarity Reversal",
04607 "Ring Begin",
04608 };
04609
04610 static struct {
04611 int alarm;
04612 char *name;
04613 } alarms[] = {
04614 { DAHDI_ALARM_RED, "Red Alarm" },
04615 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04616 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04617 { DAHDI_ALARM_RECOVER, "Recovering" },
04618 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04619 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04620 { DAHDI_ALARM_NONE, "None" },
04621 };
04622
04623 static char *alarm2str(int alm)
04624 {
04625 int x;
04626 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04627 if (alarms[x].alarm & alm)
04628 return alarms[x].name;
04629 }
04630 return alm ? "Unknown Alarm" : "No Alarm";
04631 }
04632
04633 static const char *event2str(int event)
04634 {
04635 static char buf[256];
04636 if ((event < (ARRAY_LEN(events))) && (event > -1))
04637 return events[event];
04638 sprintf(buf, "Event %d", event);
04639 return buf;
04640 }
04641
04642 static char *dahdi_sig2str(int sig)
04643 {
04644 static char buf[256];
04645 switch (sig) {
04646 case SIG_EM:
04647 return "E & M Immediate";
04648 case SIG_EMWINK:
04649 return "E & M Wink";
04650 case SIG_EM_E1:
04651 return "E & M E1";
04652 case SIG_FEATD:
04653 return "Feature Group D (DTMF)";
04654 case SIG_FEATDMF:
04655 return "Feature Group D (MF)";
04656 case SIG_FEATDMF_TA:
04657 return "Feature Groud D (MF) Tandem Access";
04658 case SIG_FEATB:
04659 return "Feature Group B (MF)";
04660 case SIG_E911:
04661 return "E911 (MF)";
04662 case SIG_FGC_CAMA:
04663 return "FGC/CAMA (Dialpulse)";
04664 case SIG_FGC_CAMAMF:
04665 return "FGC/CAMA (MF)";
04666 case SIG_FXSLS:
04667 return "FXS Loopstart";
04668 case SIG_FXSGS:
04669 return "FXS Groundstart";
04670 case SIG_FXSKS:
04671 return "FXS Kewlstart";
04672 case SIG_FXOLS:
04673 return "FXO Loopstart";
04674 case SIG_FXOGS:
04675 return "FXO Groundstart";
04676 case SIG_FXOKS:
04677 return "FXO Kewlstart";
04678 case SIG_PRI:
04679 return "ISDN PRI";
04680 case SIG_BRI:
04681 return "ISDN BRI Point to Point";
04682 case SIG_BRI_PTMP:
04683 return "ISDN BRI Point to MultiPoint";
04684 case SIG_SS7:
04685 return "SS7";
04686 case SIG_MFCR2:
04687 return "MFC/R2";
04688 case SIG_SF:
04689 return "SF (Tone) Immediate";
04690 case SIG_SFWINK:
04691 return "SF (Tone) Wink";
04692 case SIG_SF_FEATD:
04693 return "SF (Tone) with Feature Group D (DTMF)";
04694 case SIG_SF_FEATDMF:
04695 return "SF (Tone) with Feature Group D (MF)";
04696 case SIG_SF_FEATB:
04697 return "SF (Tone) with Feature Group B (MF)";
04698 case 0:
04699 return "Pseudo";
04700 default:
04701 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04702 return buf;
04703 }
04704 }
04705
04706 #define sig2str dahdi_sig2str
04707
04708 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04709 {
04710
04711
04712 struct dahdi_confinfo zi;
04713
04714 memset(&zi, 0, sizeof(zi));
04715 zi.chan = 0;
04716
04717 if (slavechannel > 0) {
04718
04719 zi.confmode = DAHDI_CONF_DIGITALMON;
04720 zi.confno = slavechannel;
04721 } else {
04722 if (!idx) {
04723
04724 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04725 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04726 } else
04727 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04728 zi.confno = p->confno;
04729 }
04730 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04731 return 0;
04732 if (c->dfd < 0)
04733 return 0;
04734 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04735 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04736 return -1;
04737 }
04738 if (slavechannel < 1) {
04739 p->confno = zi.confno;
04740 }
04741 c->curconf = zi;
04742 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04743 return 0;
04744 }
04745
04746 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04747 {
04748
04749 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04750 return 1;
04751
04752 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04753 return 1;
04754 return 0;
04755 }
04756
04757 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04758 {
04759 struct dahdi_confinfo zi;
04760 if (
04761 (c->dfd < 0) ||
04762
04763 !isourconf(p, c)
04764
04765 ) return 0;
04766 memset(&zi, 0, sizeof(zi));
04767 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04768 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04769 return -1;
04770 }
04771 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04772 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04773 return 0;
04774 }
04775
04776 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04777 {
04778 int x;
04779 int useslavenative;
04780 struct dahdi_pvt *slave = NULL;
04781
04782 useslavenative = 1;
04783
04784 for (x = 0; x < 3; x++) {
04785
04786
04787 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04788 useslavenative = 0;
04789 }
04790
04791
04792 if (useslavenative) {
04793 for (x = 0; x < MAX_SLAVES; x++) {
04794 if (p->slaves[x]) {
04795 if (slave) {
04796
04797
04798 slave = NULL;
04799 useslavenative = 0;
04800 break;
04801 } else {
04802
04803 slave = p->slaves[x];
04804 }
04805 }
04806 }
04807 }
04808
04809 if (!slave)
04810 useslavenative = 0;
04811 else if (slave->law != p->law) {
04812 useslavenative = 0;
04813 slave = NULL;
04814 }
04815 if (out)
04816 *out = slave;
04817 return useslavenative;
04818 }
04819
04820 static int reset_conf(struct dahdi_pvt *p)
04821 {
04822 p->confno = -1;
04823 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04824 if (p->subs[SUB_REAL].dfd > -1) {
04825 struct dahdi_confinfo zi;
04826
04827 memset(&zi, 0, sizeof(zi));
04828 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04829 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04830 }
04831 return 0;
04832 }
04833
04834 static int update_conf(struct dahdi_pvt *p)
04835 {
04836 int needconf = 0;
04837 int x;
04838 int useslavenative;
04839 struct dahdi_pvt *slave = NULL;
04840
04841 useslavenative = isslavenative(p, &slave);
04842
04843 for (x = 0; x < 3; x++) {
04844
04845 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04846 conf_add(p, &p->subs[x], x, 0);
04847 needconf++;
04848 } else {
04849 conf_del(p, &p->subs[x], x);
04850 }
04851 }
04852
04853
04854 for (x = 0; x < MAX_SLAVES; x++) {
04855 if (p->slaves[x]) {
04856 if (useslavenative)
04857 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04858 else {
04859 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04860 needconf++;
04861 }
04862 }
04863 }
04864
04865 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04866 if (useslavenative)
04867 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04868 else {
04869 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04870 needconf++;
04871 }
04872 }
04873
04874 if (p->master) {
04875 if (isslavenative(p->master, NULL)) {
04876 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04877 } else {
04878 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04879 }
04880 }
04881 if (!needconf) {
04882
04883
04884 p->confno = -1;
04885 }
04886 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04887 return 0;
04888 }
04889
04890 static void dahdi_enable_ec(struct dahdi_pvt *p)
04891 {
04892 int res;
04893 if (!p)
04894 return;
04895 if (p->echocanon) {
04896 ast_debug(1, "Echo cancellation already on\n");
04897 return;
04898 }
04899 if (p->digital) {
04900 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04901 return;
04902 }
04903 if (p->echocancel.head.tap_length) {
04904 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04905 switch (p->sig) {
04906 #if defined(HAVE_PRI)
04907 case SIG_PRI_LIB_HANDLE_CASES:
04908 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04909
04910
04911
04912
04913 return;
04914 }
04915
04916 #endif
04917 #if defined(HAVE_SS7)
04918 case SIG_SS7:
04919 #endif
04920 {
04921 int x = 1;
04922
04923 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04924 if (res)
04925 ast_log(LOG_WARNING,
04926 "Unable to enable audio mode on channel %d (%s)\n",
04927 p->channel, strerror(errno));
04928 }
04929 break;
04930 default:
04931 break;
04932 }
04933 #endif
04934 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04935 if (res) {
04936 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04937 } else {
04938 p->echocanon = 1;
04939 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04940 }
04941 } else
04942 ast_debug(1, "No echo cancellation requested\n");
04943 }
04944
04945 static void dahdi_train_ec(struct dahdi_pvt *p)
04946 {
04947 int x;
04948 int res;
04949
04950 if (p && p->echocanon && p->echotraining) {
04951 x = p->echotraining;
04952 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04953 if (res)
04954 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04955 else
04956 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04957 } else {
04958 ast_debug(1, "No echo training requested\n");
04959 }
04960 }
04961
04962 static void dahdi_disable_ec(struct dahdi_pvt *p)
04963 {
04964 int res;
04965
04966 if (p->echocanon) {
04967 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04968
04969 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04970
04971 if (res)
04972 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04973 else
04974 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04975 }
04976
04977 p->echocanon = 0;
04978 }
04979
04980
04981 static int drc_sample(int sample, float drc)
04982 {
04983 float neg;
04984 float shallow, steep;
04985 float max = SHRT_MAX;
04986
04987 neg = (sample < 0 ? -1 : 1);
04988 steep = drc*sample;
04989 shallow = neg*(max-max/drc)+(float)sample/drc;
04990 if (abs(steep) < abs(shallow)) {
04991 sample = steep;
04992 }
04993 else {
04994 sample = shallow;
04995 }
04996
04997 return sample;
04998 }
04999
05000
05001 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05002 {
05003 int j;
05004 int k;
05005
05006 float linear_gain = pow(10.0, gain / 20.0);
05007
05008 switch (law) {
05009 case DAHDI_LAW_ALAW:
05010 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05011 if (gain || drc) {
05012 k = AST_ALAW(j);
05013 if (drc) {
05014 k = drc_sample(k, drc);
05015 }
05016 k = (float)k * linear_gain;
05017 if (k > 32767) {
05018 k = 32767;
05019 } else if (k < -32768) {
05020 k = -32768;
05021 }
05022 g->txgain[j] = AST_LIN2A(k);
05023 } else {
05024 g->txgain[j] = j;
05025 }
05026 }
05027 break;
05028 case DAHDI_LAW_MULAW:
05029 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05030 if (gain || drc) {
05031 k = AST_MULAW(j);
05032 if (drc) {
05033 k = drc_sample(k, drc);
05034 }
05035 k = (float)k * linear_gain;
05036 if (k > 32767) {
05037 k = 32767;
05038 } else if (k < -32768) {
05039 k = -32768;
05040 }
05041 g->txgain[j] = AST_LIN2MU(k);
05042
05043 } else {
05044 g->txgain[j] = j;
05045 }
05046 }
05047 break;
05048 }
05049 }
05050
05051 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05052 {
05053 int j;
05054 int k;
05055 float linear_gain = pow(10.0, gain / 20.0);
05056
05057 switch (law) {
05058 case DAHDI_LAW_ALAW:
05059 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05060 if (gain || drc) {
05061 k = AST_ALAW(j);
05062 if (drc) {
05063 k = drc_sample(k, drc);
05064 }
05065 k = (float)k * linear_gain;
05066 if (k > 32767) {
05067 k = 32767;
05068 } else if (k < -32768) {
05069 k = -32768;
05070 }
05071 g->rxgain[j] = AST_LIN2A(k);
05072 } else {
05073 g->rxgain[j] = j;
05074 }
05075 }
05076 break;
05077 case DAHDI_LAW_MULAW:
05078 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05079 if (gain || drc) {
05080 k = AST_MULAW(j);
05081 if (drc) {
05082 k = drc_sample(k, drc);
05083 }
05084 k = (float)k * linear_gain;
05085 if (k > 32767) {
05086 k = 32767;
05087 } else if (k < -32768) {
05088 k = -32768;
05089 }
05090 g->rxgain[j] = AST_LIN2MU(k);
05091 } else {
05092 g->rxgain[j] = j;
05093 }
05094 }
05095 break;
05096 }
05097 }
05098
05099 static int set_actual_txgain(int fd, float gain, float drc, int law)
05100 {
05101 struct dahdi_gains g;
05102 int res;
05103
05104 memset(&g, 0, sizeof(g));
05105 res = ioctl(fd, DAHDI_GETGAINS, &g);
05106 if (res) {
05107 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05108 return res;
05109 }
05110
05111 fill_txgain(&g, gain, drc, law);
05112
05113 return ioctl(fd, DAHDI_SETGAINS, &g);
05114 }
05115
05116 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05117 {
05118 struct dahdi_gains g;
05119 int res;
05120
05121 memset(&g, 0, sizeof(g));
05122 res = ioctl(fd, DAHDI_GETGAINS, &g);
05123 if (res) {
05124 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05125 return res;
05126 }
05127
05128 fill_rxgain(&g, gain, drc, law);
05129
05130 return ioctl(fd, DAHDI_SETGAINS, &g);
05131 }
05132
05133 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05134 {
05135 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05136 }
05137
05138 static int bump_gains(struct dahdi_pvt *p)
05139 {
05140 int res;
05141
05142
05143 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05144 if (res) {
05145 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05146 return -1;
05147 }
05148
05149 return 0;
05150 }
05151
05152 static int restore_gains(struct dahdi_pvt *p)
05153 {
05154 int res;
05155
05156 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05157 if (res) {
05158 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05159 return -1;
05160 }
05161
05162 return 0;
05163 }
05164
05165 static inline int dahdi_set_hook(int fd, int hs)
05166 {
05167 int x, res;
05168
05169 x = hs;
05170 res = ioctl(fd, DAHDI_HOOK, &x);
05171
05172 if (res < 0) {
05173 if (errno == EINPROGRESS)
05174 return 0;
05175 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05176
05177 }
05178
05179 return res;
05180 }
05181
05182 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05183 {
05184 int x, res;
05185
05186 x = muted;
05187 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05188 switch (p->sig) {
05189 #if defined(HAVE_PRI)
05190 case SIG_PRI_LIB_HANDLE_CASES:
05191 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05192
05193 break;
05194 }
05195
05196 #endif
05197 #if defined(HAVE_SS7)
05198 case SIG_SS7:
05199 #endif
05200 {
05201 int y = 1;
05202
05203 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05204 if (res)
05205 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05206 p->channel, strerror(errno));
05207 }
05208 break;
05209 default:
05210 break;
05211 }
05212 #endif
05213 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05214 if (res < 0)
05215 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05216 return res;
05217 }
05218
05219 static int save_conference(struct dahdi_pvt *p)
05220 {
05221 struct dahdi_confinfo c;
05222 int res;
05223 if (p->saveconf.confmode) {
05224 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05225 return -1;
05226 }
05227 p->saveconf.chan = 0;
05228 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05229 if (res) {
05230 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05231 p->saveconf.confmode = 0;
05232 return -1;
05233 }
05234 memset(&c, 0, sizeof(c));
05235 c.confmode = DAHDI_CONF_NORMAL;
05236 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05237 if (res) {
05238 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05239 return -1;
05240 }
05241 ast_debug(1, "Disabled conferencing\n");
05242 return 0;
05243 }
05244
05245 static int restore_conference(struct dahdi_pvt *p)
05246 {
05247 int res;
05248 if (p->saveconf.confmode) {
05249 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05250 p->saveconf.confmode = 0;
05251 if (res) {
05252 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05253 return -1;
05254 }
05255 ast_debug(1, "Restored conferencing\n");
05256 }
05257 return 0;
05258 }
05259
05260 static int send_cwcidspill(struct dahdi_pvt *p)
05261 {
05262 p->callwaitcas = 0;
05263 p->cidcwexpire = 0;
05264 p->cid_suppress_expire = 0;
05265 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05266 return -1;
05267 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05268
05269 p->cidlen += READ_SIZE * 4;
05270 p->cidpos = 0;
05271 send_callerid(p);
05272 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05273 return 0;
05274 }
05275
05276 static int has_voicemail(struct dahdi_pvt *p)
05277 {
05278 int new_msgs;
05279 struct ast_event *event;
05280 char *mailbox, *context;
05281
05282 mailbox = context = ast_strdupa(p->mailbox);
05283 strsep(&context, "@");
05284 if (ast_strlen_zero(context))
05285 context = "default";
05286
05287 event = ast_event_get_cached(AST_EVENT_MWI,
05288 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05289 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05290 AST_EVENT_IE_END);
05291
05292 if (event) {
05293 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05294 ast_event_destroy(event);
05295 } else
05296 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05297
05298 return new_msgs;
05299 }
05300
05301
05302
05303 static int send_callerid(struct dahdi_pvt *p)
05304 {
05305
05306 int res;
05307
05308 if (p->subs[SUB_REAL].linear) {
05309 p->subs[SUB_REAL].linear = 0;
05310 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05311 }
05312 while (p->cidpos < p->cidlen) {
05313 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05314 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05315 if (res < 0) {
05316 if (errno == EAGAIN)
05317 return 0;
05318 else {
05319 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05320 return -1;
05321 }
05322 }
05323 if (!res)
05324 return 0;
05325 p->cidpos += res;
05326 }
05327 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05328 ast_free(p->cidspill);
05329 p->cidspill = NULL;
05330 if (p->callwaitcas) {
05331
05332 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05333 p->cid_suppress_expire = p->cidcwexpire;
05334 } else
05335 restore_conference(p);
05336 return 0;
05337 }
05338
05339 static int dahdi_callwait(struct ast_channel *ast)
05340 {
05341 struct dahdi_pvt *p = ast->tech_pvt;
05342 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05343 if (p->cidspill) {
05344 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05345 ast_free(p->cidspill);
05346 }
05347
05348
05349
05350
05351
05352 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05353 return -1;
05354 save_conference(p);
05355
05356 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05357 if (!p->callwaitrings && p->callwaitingcallerid) {
05358 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05359 p->callwaitcas = 1;
05360 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05361 } else {
05362 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05363 p->callwaitcas = 0;
05364 p->cidlen = 2400 + READ_SIZE * 4;
05365 }
05366 p->cidpos = 0;
05367 send_callerid(p);
05368
05369 return 0;
05370 }
05371
05372 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05373 {
05374 struct dahdi_pvt *p = ast->tech_pvt;
05375 int x, res, mysig;
05376 char dest[256];
05377
05378 ast_mutex_lock(&p->lock);
05379 ast_copy_string(dest, rdest, sizeof(dest));
05380 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05381 if ((ast->_state == AST_STATE_BUSY)) {
05382 p->subs[SUB_REAL].needbusy = 1;
05383 ast_mutex_unlock(&p->lock);
05384 return 0;
05385 }
05386 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05387 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05388 ast_mutex_unlock(&p->lock);
05389 return -1;
05390 }
05391 p->waitingfordt.tv_sec = 0;
05392 p->dialednone = 0;
05393 if ((p->radio || (p->oprmode < 0)))
05394 {
05395
05396 ast_setstate(ast, AST_STATE_UP);
05397 ast_mutex_unlock(&p->lock);
05398 return 0;
05399 }
05400 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05401 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05402 if (res)
05403 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05404 p->outgoing = 1;
05405
05406 if (IS_DIGITAL(ast->transfercapability)){
05407 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05408 } else {
05409 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05410 }
05411
05412 #ifdef HAVE_PRI
05413 if (dahdi_sig_pri_lib_handles(p->sig)) {
05414 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05415 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05416 ast_mutex_unlock(&p->lock);
05417 return res;
05418 }
05419 #endif
05420
05421 #if defined(HAVE_SS7)
05422 if (p->sig == SIG_SS7) {
05423 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05424 ast_mutex_unlock(&p->lock);
05425 return res;
05426 }
05427 #endif
05428
05429
05430 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05431 p->callwaitrings = 0;
05432 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05433 ast_mutex_unlock(&p->lock);
05434 return res;
05435 }
05436
05437 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05438 switch (mysig) {
05439 case 0:
05440
05441 ast_setstate(ast, AST_STATE_UP);
05442 break;
05443 case SIG_MFCR2:
05444 break;
05445 default:
05446 ast_debug(1, "not yet implemented\n");
05447 ast_mutex_unlock(&p->lock);
05448 return -1;
05449 }
05450
05451 #ifdef HAVE_OPENR2
05452 if (p->mfcr2) {
05453 openr2_calling_party_category_t chancat;
05454 int callres = 0;
05455 char *c, *l;
05456
05457
05458 p->dialdest[0] = '\0';
05459
05460 c = strchr(dest, '/');
05461 if (c) {
05462 c++;
05463 } else {
05464 c = "";
05465 }
05466 if (!p->hidecallerid) {
05467 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05468 } else {
05469 l = NULL;
05470 }
05471 if (strlen(c) < p->stripmsd) {
05472 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05473 ast_mutex_unlock(&p->lock);
05474 return -1;
05475 }
05476 p->dialing = 1;
05477 chancat = dahdi_r2_get_channel_category(ast);
05478 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05479 if (-1 == callres) {
05480 ast_mutex_unlock(&p->lock);
05481 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05482 return -1;
05483 }
05484 p->mfcr2_call_accepted = 0;
05485 p->mfcr2_progress = 0;
05486 ast_setstate(ast, AST_STATE_DIALING);
05487 }
05488 #endif
05489 ast_mutex_unlock(&p->lock);
05490 return 0;
05491 }
05492
05493
05494
05495
05496
05497
05498
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05509 {
05510 struct dahdi_pvt *cur;
05511
05512 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05513
05514
05515 for (cur = iflist; cur; cur = cur->next) {
05516 if (pvt->channel < cur->channel) {
05517
05518 pvt->prev = cur->prev;
05519 pvt->next = cur;
05520 if (cur->prev) {
05521
05522 cur->prev->next = pvt;
05523 } else {
05524
05525 iflist = pvt;
05526 }
05527 cur->prev = pvt;
05528 return;
05529 }
05530 }
05531
05532
05533 pvt->prev = ifend;
05534 pvt->next = NULL;
05535 if (ifend) {
05536 ifend->next = pvt;
05537 }
05538 ifend = pvt;
05539 if (!iflist) {
05540
05541 iflist = pvt;
05542 }
05543 }
05544
05545
05546
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05559 {
05560
05561 if (pvt->prev) {
05562 pvt->prev->next = pvt->next;
05563 } else if (iflist == pvt) {
05564
05565 iflist = pvt->next;
05566 }
05567
05568
05569 if (pvt->next) {
05570 pvt->next->prev = pvt->prev;
05571 } else if (ifend == pvt) {
05572
05573 ifend = pvt->prev;
05574 }
05575
05576
05577 pvt->which_iflist = DAHDI_IFLIST_NONE;
05578 pvt->prev = NULL;
05579 pvt->next = NULL;
05580 }
05581
05582 #if defined(HAVE_PRI)
05583
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05600 {
05601 struct dahdi_pvt *cur;
05602
05603 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05604
05605
05606 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05607 if (pvt->channel < cur->channel) {
05608
05609 pvt->prev = cur->prev;
05610 pvt->next = cur;
05611 if (cur->prev) {
05612
05613 cur->prev->next = pvt;
05614 } else {
05615
05616 pri->no_b_chan_iflist = pvt;
05617 }
05618 cur->prev = pvt;
05619 return;
05620 }
05621 }
05622
05623
05624 pvt->prev = pri->no_b_chan_end;
05625 pvt->next = NULL;
05626 if (pri->no_b_chan_end) {
05627 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05628 }
05629 pri->no_b_chan_end = pvt;
05630 if (!pri->no_b_chan_iflist) {
05631
05632 pri->no_b_chan_iflist = pvt;
05633 }
05634 }
05635 #endif
05636
05637 #if defined(HAVE_PRI)
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05653 {
05654
05655 if (pvt->prev) {
05656 pvt->prev->next = pvt->next;
05657 } else if (pri->no_b_chan_iflist == pvt) {
05658
05659 pri->no_b_chan_iflist = pvt->next;
05660 }
05661
05662
05663 if (pvt->next) {
05664 pvt->next->prev = pvt->prev;
05665 } else if (pri->no_b_chan_end == pvt) {
05666
05667 pri->no_b_chan_end = pvt->prev;
05668 }
05669
05670
05671 pvt->which_iflist = DAHDI_IFLIST_NONE;
05672 pvt->prev = NULL;
05673 pvt->next = NULL;
05674 }
05675 #endif
05676
05677 #if defined(HAVE_PRI)
05678
05679
05680
05681
05682
05683
05684
05685
05686
05687 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05688 {
05689 unsigned idx;
05690 struct sig_pri_span *pri;
05691
05692 pri = pvt->pri;
05693 if (!pri) {
05694
05695 return;
05696 }
05697 ast_mutex_lock(&pri->lock);
05698 for (idx = 0; idx < pri->numchans; ++idx) {
05699 if (pri->pvts[idx] == pvt->sig_pvt) {
05700 pri->pvts[idx] = NULL;
05701 ast_mutex_unlock(&pri->lock);
05702 return;
05703 }
05704 }
05705 ast_mutex_unlock(&pri->lock);
05706 }
05707 #endif
05708
05709 #if defined(HAVE_SS7)
05710
05711
05712
05713
05714
05715
05716
05717
05718
05719 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05720 {
05721 unsigned idx;
05722 struct sig_ss7_linkset *ss7;
05723
05724 ss7 = pvt->ss7;
05725 if (!ss7) {
05726
05727 return;
05728 }
05729 ast_mutex_lock(&ss7->lock);
05730 for (idx = 0; idx < ss7->numchans; ++idx) {
05731 if (ss7->pvts[idx] == pvt->sig_pvt) {
05732 ss7->pvts[idx] = NULL;
05733 ast_mutex_unlock(&ss7->lock);
05734 return;
05735 }
05736 }
05737 ast_mutex_unlock(&ss7->lock);
05738 }
05739 #endif
05740
05741 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05742 {
05743 if (cur->next && cur->next->span == cur->span) {
05744 return cur->next;
05745 } else if (cur->prev && cur->prev->span == cur->span) {
05746 return cur->prev;
05747 }
05748
05749 return NULL;
05750 }
05751
05752 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05753 {
05754 struct dahdi_pvt *p = pvt;
05755
05756 if (p->manages_span_alarms) {
05757 struct dahdi_pvt *next = find_next_iface_in_span(p);
05758 if (next) {
05759 next->manages_span_alarms = 1;
05760 }
05761 }
05762
05763
05764 #if defined(HAVE_PRI)
05765 dahdi_unlink_pri_pvt(p);
05766 #endif
05767 #if defined(HAVE_SS7)
05768 dahdi_unlink_ss7_pvt(p);
05769 #endif
05770 switch (pvt->which_iflist) {
05771 case DAHDI_IFLIST_NONE:
05772 break;
05773 case DAHDI_IFLIST_MAIN:
05774 dahdi_iflist_extract(p);
05775 break;
05776 #if defined(HAVE_PRI)
05777 case DAHDI_IFLIST_NO_B_CHAN:
05778 if (p->pri) {
05779 dahdi_nobch_extract(p->pri, p);
05780 }
05781 break;
05782 #endif
05783 }
05784
05785 if (p->sig_pvt) {
05786 if (analog_lib_handles(p->sig, 0, 0)) {
05787 analog_delete(p->sig_pvt);
05788 }
05789 switch (p->sig) {
05790 #if defined(HAVE_PRI)
05791 case SIG_PRI_LIB_HANDLE_CASES:
05792 sig_pri_chan_delete(p->sig_pvt);
05793 break;
05794 #endif
05795 #if defined(HAVE_SS7)
05796 case SIG_SS7:
05797 sig_ss7_chan_delete(p->sig_pvt);
05798 break;
05799 #endif
05800 default:
05801 break;
05802 }
05803 }
05804 ast_free(p->cidspill);
05805 if (p->use_smdi)
05806 ast_smdi_interface_unref(p->smdi_iface);
05807 if (p->mwi_event_sub)
05808 ast_event_unsubscribe(p->mwi_event_sub);
05809 if (p->vars) {
05810 ast_variables_destroy(p->vars);
05811 }
05812 if (p->cc_params) {
05813 ast_cc_config_params_destroy(p->cc_params);
05814 }
05815 ast_mutex_destroy(&p->lock);
05816 dahdi_close_sub(p, SUB_REAL);
05817 if (p->owner)
05818 p->owner->tech_pvt = NULL;
05819 ast_free(p);
05820 }
05821
05822 static void destroy_channel(struct dahdi_pvt *cur, int now)
05823 {
05824 int i;
05825
05826 if (!now) {
05827
05828 if (cur->owner) {
05829 return;
05830 }
05831 for (i = 0; i < 3; i++) {
05832 if (cur->subs[i].owner) {
05833 return;
05834 }
05835 }
05836 }
05837 destroy_dahdi_pvt(cur);
05838 }
05839
05840 static void destroy_all_channels(void)
05841 {
05842 int chan;
05843 #if defined(HAVE_PRI)
05844 unsigned span;
05845 struct sig_pri_span *pri;
05846 #endif
05847 struct dahdi_pvt *p;
05848
05849 while (num_restart_pending) {
05850 usleep(1);
05851 }
05852
05853 ast_mutex_lock(&iflock);
05854
05855 while (iflist) {
05856 p = iflist;
05857
05858 chan = p->channel;
05859 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05860 {
05861 char db_chan_name[20];
05862 char db_answer[5];
05863 char state;
05864 int why = -1;
05865
05866 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05867 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05868 sscanf(db_answer, "%1c:%30d", &state, &why);
05869 }
05870 if (!why) {
05871
05872 ast_db_del(db_chan_name, SRVST_DBKEY);
05873 }
05874 }
05875 #endif
05876
05877 destroy_dahdi_pvt(p);
05878 ast_verb(3, "Unregistered channel %d\n", chan);
05879 }
05880 ifcount = 0;
05881 ast_mutex_unlock(&iflock);
05882
05883 #if defined(HAVE_PRI)
05884
05885 for (span = 0; span < NUM_SPANS; ++span) {
05886 if (!pris[span].dchannels[0]) {
05887 break;
05888 }
05889 pri = &pris[span].pri;
05890 ast_mutex_lock(&pri->lock);
05891 while (pri->no_b_chan_iflist) {
05892 p = pri->no_b_chan_iflist;
05893
05894
05895 destroy_dahdi_pvt(p);
05896 }
05897 ast_mutex_unlock(&pri->lock);
05898 }
05899 #endif
05900 }
05901
05902 #if defined(HAVE_PRI)
05903 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05904
05905 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05906 {
05907
05908 struct dahdi_pvt *p;
05909
05910 if (ast_strlen_zero(digits)) {
05911 ast_debug(1, "No digit string sent to application!\n");
05912 return -1;
05913 }
05914
05915 p = (struct dahdi_pvt *)chan->tech_pvt;
05916
05917 if (!p) {
05918 ast_debug(1, "Unable to find technology private\n");
05919 return -1;
05920 }
05921
05922 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05923
05924 return 0;
05925 }
05926 #endif
05927
05928 #if defined(HAVE_PRI)
05929 #if defined(HAVE_PRI_PROG_W_CAUSE)
05930 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05931
05932 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05933 {
05934
05935 struct dahdi_pvt *pvt;
05936 char *parse;
05937 int res;
05938 AST_DECLARE_APP_ARGS(args,
05939 AST_APP_ARG(destination);
05940 AST_APP_ARG(original);
05941 AST_APP_ARG(reason);
05942 );
05943
05944 if (ast_strlen_zero(data)) {
05945 ast_log(LOG_DEBUG, "No data sent to application!\n");
05946 return -1;
05947 }
05948 if (chan->tech != &dahdi_tech) {
05949 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05950 return -1;
05951 }
05952 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05953 if (!pvt) {
05954 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05955 return -1;
05956 }
05957 switch (pvt->sig) {
05958 case SIG_PRI_LIB_HANDLE_CASES:
05959 break;
05960 default:
05961 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05962 chan->name);
05963 return -1;
05964 }
05965
05966 parse = ast_strdupa(data);
05967 AST_STANDARD_APP_ARGS(args, parse);
05968
05969 if (ast_strlen_zero(args.destination)) {
05970 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05971 return -1;
05972 }
05973
05974 if (ast_strlen_zero(args.original)) {
05975 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05976 args.original = NULL;
05977 }
05978
05979 if (ast_strlen_zero(args.reason)) {
05980 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05981 args.reason = NULL;
05982 }
05983
05984 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05985 args.destination, args.original, args.reason);
05986 if (!res) {
05987
05988
05989
05990
05991 ast_safe_sleep(chan, 5000);
05992 }
05993
05994 return -1;
05995 }
05996 #endif
05997 #endif
05998
05999 #if defined(HAVE_OPENR2)
06000 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06001
06002 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06003 {
06004
06005 openr2_call_mode_t accept_mode;
06006 int res, timeout, maxloops;
06007 struct ast_frame *f;
06008 struct dahdi_pvt *p;
06009 char *parse;
06010 AST_DECLARE_APP_ARGS(args,
06011 AST_APP_ARG(charge);
06012 );
06013
06014 if (ast_strlen_zero(data)) {
06015 ast_log(LOG_DEBUG, "No data sent to application!\n");
06016 return -1;
06017 }
06018
06019 if (chan->tech != &dahdi_tech) {
06020 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06021 return -1;
06022 }
06023
06024 p = (struct dahdi_pvt *)chan->tech_pvt;
06025 if (!p) {
06026 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06027 return -1;
06028 }
06029
06030 parse = ast_strdupa(data);
06031 AST_STANDARD_APP_ARGS(args, parse);
06032
06033 if (ast_strlen_zero(args.charge)) {
06034 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06035 return -1;
06036 }
06037
06038 ast_mutex_lock(&p->lock);
06039 if (!p->mfcr2 || !p->mfcr2call) {
06040 ast_mutex_unlock(&p->lock);
06041 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06042 return -1;
06043 }
06044
06045 if (p->mfcr2_call_accepted) {
06046 ast_mutex_unlock(&p->lock);
06047 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06048 return 0;
06049 }
06050 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06051 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06052 ast_mutex_unlock(&p->lock);
06053 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06054 return -1;
06055 }
06056 ast_mutex_unlock(&p->lock);
06057
06058 res = 0;
06059 timeout = 100;
06060 maxloops = 50;
06061
06062 while (maxloops > 0) {
06063 maxloops--;
06064 if (ast_check_hangup(chan)) {
06065 break;
06066 }
06067 res = ast_waitfor(chan, timeout);
06068 if (res < 0) {
06069 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06070 res = -1;
06071 break;
06072 }
06073 if (res == 0) {
06074 continue;
06075 }
06076 res = 0;
06077 f = ast_read(chan);
06078 if (!f) {
06079 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06080 res = -1;
06081 break;
06082 }
06083 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06084 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06085 ast_frfree(f);
06086 res = -1;
06087 break;
06088 }
06089 ast_frfree(f);
06090 ast_mutex_lock(&p->lock);
06091 if (p->mfcr2_call_accepted) {
06092 ast_mutex_unlock(&p->lock);
06093 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06094 break;
06095 }
06096 ast_mutex_unlock(&p->lock);
06097 }
06098 if (res == -1) {
06099 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06100 }
06101 return res;
06102 }
06103
06104 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06105 {
06106 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06107 switch (cause) {
06108 case AST_CAUSE_USER_BUSY:
06109 case AST_CAUSE_CALL_REJECTED:
06110 case AST_CAUSE_INTERWORKING:
06111 r2cause = OR2_CAUSE_BUSY_NUMBER;
06112 break;
06113
06114 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06115 case AST_CAUSE_SWITCH_CONGESTION:
06116 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06117 break;
06118
06119 case AST_CAUSE_UNALLOCATED:
06120 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06121 break;
06122
06123 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06124 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06125 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06126 break;
06127
06128 case AST_CAUSE_NO_ANSWER:
06129 case AST_CAUSE_NO_USER_RESPONSE:
06130 r2cause = OR2_CAUSE_NO_ANSWER;
06131 break;
06132
06133 default:
06134 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06135 break;
06136 }
06137 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06138 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06139 return r2cause;
06140 }
06141 #endif
06142
06143 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06144 {
06145 if (p->bufferoverrideinuse) {
06146
06147 struct dahdi_bufferinfo bi = {
06148 .txbufpolicy = p->buf_policy,
06149 .rxbufpolicy = p->buf_policy,
06150 .bufsize = p->bufsize,
06151 .numbufs = p->buf_no
06152 };
06153 int bpres;
06154
06155 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06156 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06157 }
06158 p->bufferoverrideinuse = 0;
06159 return bpres;
06160 }
06161
06162 return -1;
06163 }
06164
06165 static int dahdi_hangup(struct ast_channel *ast)
06166 {
06167 int res = 0;
06168 int idx,x;
06169 int law;
06170
06171 struct dahdi_pvt *p = ast->tech_pvt;
06172 struct dahdi_params par;
06173
06174 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06175 if (!ast->tech_pvt) {
06176 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06177 return 0;
06178 }
06179
06180 ast_mutex_lock(&p->lock);
06181 p->exten[0] = '\0';
06182 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06183 dahdi_confmute(p, 0);
06184 restore_gains(p);
06185 p->ignoredtmf = 0;
06186 p->waitingfordt.tv_sec = 0;
06187
06188 res = analog_hangup(p->sig_pvt, ast);
06189 revert_fax_buffers(p, ast);
06190
06191 goto hangup_out;
06192 } else {
06193 p->cid_num[0] = '\0';
06194 p->cid_name[0] = '\0';
06195 p->cid_subaddr[0] = '\0';
06196 }
06197
06198 #if defined(HAVE_PRI)
06199 if (dahdi_sig_pri_lib_handles(p->sig)) {
06200 x = 1;
06201 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06202
06203 dahdi_confmute(p, 0);
06204 p->muting = 0;
06205 restore_gains(p);
06206 if (p->dsp) {
06207 ast_dsp_free(p->dsp);
06208 p->dsp = NULL;
06209 }
06210 p->ignoredtmf = 0;
06211
06212
06213 p->subs[SUB_REAL].owner = NULL;
06214 p->subs[SUB_REAL].needbusy = 0;
06215 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06216
06217 p->owner = NULL;
06218 p->cid_tag[0] = '\0';
06219 p->ringt = 0;
06220 p->distinctivering = 0;
06221 p->confirmanswer = 0;
06222 p->outgoing = 0;
06223 p->digital = 0;
06224 p->faxhandled = 0;
06225 p->pulsedial = 0;
06226
06227 revert_fax_buffers(p, ast);
06228
06229 p->law = p->law_default;
06230 law = p->law_default;
06231 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06232 if (res < 0) {
06233 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06234 p->channel, strerror(errno));
06235 }
06236
06237 sig_pri_hangup(p->sig_pvt, ast);
06238
06239 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06240 dahdi_disable_ec(p);
06241
06242 x = 0;
06243 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06244 p->didtdd = 0;
06245
06246 p->rdnis[0] = '\0';
06247 update_conf(p);
06248 reset_conf(p);
06249
06250
06251 x = 0;
06252 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06253
06254 if (num_restart_pending == 0) {
06255 restart_monitor();
06256 }
06257 goto hangup_out;
06258 }
06259 #endif
06260
06261 #if defined(HAVE_SS7)
06262 if (p->sig == SIG_SS7) {
06263 x = 1;
06264 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06265
06266 dahdi_confmute(p, 0);
06267 p->muting = 0;
06268 restore_gains(p);
06269 if (p->dsp) {
06270 ast_dsp_free(p->dsp);
06271 p->dsp = NULL;
06272 }
06273 p->ignoredtmf = 0;
06274
06275
06276 p->subs[SUB_REAL].owner = NULL;
06277 p->subs[SUB_REAL].needbusy = 0;
06278 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06279
06280 p->owner = NULL;
06281 p->ringt = 0;
06282 p->distinctivering = 0;
06283 p->confirmanswer = 0;
06284 p->outgoing = 0;
06285 p->digital = 0;
06286 p->faxhandled = 0;
06287 p->pulsedial = 0;
06288
06289 revert_fax_buffers(p, ast);
06290
06291 p->law = p->law_default;
06292 law = p->law_default;
06293 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06294 if (res < 0) {
06295 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06296 p->channel, strerror(errno));
06297 }
06298
06299 sig_ss7_hangup(p->sig_pvt, ast);
06300
06301 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06302 dahdi_disable_ec(p);
06303
06304 x = 0;
06305 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06306 p->didtdd = 0;
06307
06308 update_conf(p);
06309 reset_conf(p);
06310
06311
06312 x = 0;
06313 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06314
06315 if (num_restart_pending == 0) {
06316 restart_monitor();
06317 }
06318 goto hangup_out;
06319 }
06320 #endif
06321
06322 idx = dahdi_get_index(ast, p, 1);
06323
06324 dahdi_confmute(p, 0);
06325 p->muting = 0;
06326 restore_gains(p);
06327 if (p->origcid_num) {
06328 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06329 ast_free(p->origcid_num);
06330 p->origcid_num = NULL;
06331 }
06332 if (p->origcid_name) {
06333 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06334 ast_free(p->origcid_name);
06335 p->origcid_name = NULL;
06336 }
06337 if (p->dsp)
06338 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06339
06340 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06341 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06342 p->ignoredtmf = 0;
06343
06344 if (idx > -1) {
06345
06346 p->subs[idx].owner = NULL;
06347 p->subs[idx].needanswer = 0;
06348 p->subs[idx].needflash = 0;
06349 p->subs[idx].needringing = 0;
06350 p->subs[idx].needbusy = 0;
06351 p->subs[idx].needcongestion = 0;
06352 p->subs[idx].linear = 0;
06353 p->polarity = POLARITY_IDLE;
06354 dahdi_setlinear(p->subs[idx].dfd, 0);
06355 if (idx == SUB_REAL) {
06356 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06357 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06358 if (p->subs[SUB_CALLWAIT].inthreeway) {
06359
06360 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06361
06362 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06363 unalloc_sub(p, SUB_CALLWAIT);
06364 p->owner = NULL;
06365 } else {
06366
06367 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06368 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06369 unalloc_sub(p, SUB_THREEWAY);
06370 if (p->subs[SUB_REAL].inthreeway) {
06371
06372
06373 ast_debug(1, "Call was complete, setting owner to former third call\n");
06374 p->owner = p->subs[SUB_REAL].owner;
06375 } else {
06376
06377 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06378 p->owner = NULL;
06379 }
06380 p->subs[SUB_REAL].inthreeway = 0;
06381 }
06382 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06383
06384 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06385 unalloc_sub(p, SUB_CALLWAIT);
06386 p->owner = p->subs[SUB_REAL].owner;
06387 if (p->owner->_state != AST_STATE_UP)
06388 p->subs[SUB_REAL].needanswer = 1;
06389 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06390 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06391 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06392 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06393 unalloc_sub(p, SUB_THREEWAY);
06394 if (p->subs[SUB_REAL].inthreeway) {
06395
06396
06397 ast_debug(1, "Call was complete, setting owner to former third call\n");
06398 p->owner = p->subs[SUB_REAL].owner;
06399 } else {
06400
06401 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06402 p->owner = NULL;
06403 }
06404 p->subs[SUB_REAL].inthreeway = 0;
06405 }
06406 } else if (idx == SUB_CALLWAIT) {
06407
06408 if (p->subs[SUB_CALLWAIT].inthreeway) {
06409
06410
06411 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06412 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06413 S_OR(p->mohsuggest, NULL),
06414 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06415 }
06416 p->subs[SUB_THREEWAY].inthreeway = 0;
06417
06418 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06419 unalloc_sub(p, SUB_THREEWAY);
06420 } else
06421 unalloc_sub(p, SUB_CALLWAIT);
06422 } else if (idx == SUB_THREEWAY) {
06423 if (p->subs[SUB_CALLWAIT].inthreeway) {
06424
06425
06426 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06427 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06428 S_OR(p->mohsuggest, NULL),
06429 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06430 }
06431 p->subs[SUB_CALLWAIT].inthreeway = 0;
06432 }
06433 p->subs[SUB_REAL].inthreeway = 0;
06434
06435
06436 unalloc_sub(p, SUB_THREEWAY);
06437 } else {
06438
06439 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06440 }
06441 }
06442
06443 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06444 p->owner = NULL;
06445 p->ringt = 0;
06446 p->distinctivering = 0;
06447 p->confirmanswer = 0;
06448 p->outgoing = 0;
06449 p->digital = 0;
06450 p->faxhandled = 0;
06451 p->pulsedial = 0;
06452 if (p->dsp) {
06453 ast_dsp_free(p->dsp);
06454 p->dsp = NULL;
06455 }
06456
06457 revert_fax_buffers(p, ast);
06458
06459 p->law = p->law_default;
06460 law = p->law_default;
06461 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06462 if (res < 0)
06463 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06464
06465 #ifdef HAVE_OPENR2
06466 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06467 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06468
06469 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06470 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06471 } else {
06472 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06473 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06474 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06475 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06476 dahdi_r2_disconnect_call(p, r2cause);
06477 }
06478 } else if (p->mfcr2call) {
06479 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06480
06481
06482
06483
06484 p->mfcr2call = 0;
06485 }
06486 #endif
06487 switch (p->sig) {
06488 case SIG_SS7:
06489 case SIG_MFCR2:
06490 case SIG_PRI_LIB_HANDLE_CASES:
06491 case 0:
06492 break;
06493 default:
06494 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06495 break;
06496 }
06497 if (res < 0) {
06498 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06499 }
06500 switch (p->sig) {
06501 case SIG_FXOGS:
06502 case SIG_FXOLS:
06503 case SIG_FXOKS:
06504 memset(&par, 0, sizeof(par));
06505 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06506 if (!res) {
06507 struct analog_pvt *analog_p = p->sig_pvt;
06508 #if 0
06509 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06510 #endif
06511
06512 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06513 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06514 else
06515 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06516 analog_p->fxsoffhookstate = par.rxisoffhook;
06517 }
06518 break;
06519 case SIG_FXSGS:
06520 case SIG_FXSLS:
06521 case SIG_FXSKS:
06522
06523
06524 if (ast->_state != AST_STATE_RESERVED) {
06525 time(&p->guardtime);
06526 p->guardtime += 2;
06527 }
06528 break;
06529 default:
06530 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06531 break;
06532 }
06533 if (p->sig)
06534 dahdi_disable_ec(p);
06535 x = 0;
06536 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06537 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06538 p->didtdd = 0;
06539 p->callwaitcas = 0;
06540 p->callwaiting = p->permcallwaiting;
06541 p->hidecallerid = p->permhidecallerid;
06542 p->waitingfordt.tv_sec = 0;
06543 p->dialing = 0;
06544 p->rdnis[0] = '\0';
06545 update_conf(p);
06546 reset_conf(p);
06547
06548 switch (p->sig) {
06549 case SIG_PRI_LIB_HANDLE_CASES:
06550 case SIG_SS7:
06551 x = 0;
06552 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06553 break;
06554 default:
06555 break;
06556 }
06557 if (num_restart_pending == 0)
06558 restart_monitor();
06559 }
06560
06561 p->callwaitingrepeat = 0;
06562 p->cidcwexpire = 0;
06563 p->cid_suppress_expire = 0;
06564 p->oprmode = 0;
06565 hangup_out:
06566 ast->tech_pvt = NULL;
06567 ast_free(p->cidspill);
06568 p->cidspill = NULL;
06569
06570 ast_mutex_unlock(&p->lock);
06571 ast_verb(3, "Hungup '%s'\n", ast->name);
06572
06573 ast_mutex_lock(&iflock);
06574 if (p->restartpending) {
06575 num_restart_pending--;
06576 }
06577
06578 if (p->destroy) {
06579 destroy_channel(p, 0);
06580 }
06581 ast_mutex_unlock(&iflock);
06582
06583 ast_module_unref(ast_module_info->self);
06584 return 0;
06585 }
06586
06587 static int dahdi_answer(struct ast_channel *ast)
06588 {
06589 struct dahdi_pvt *p = ast->tech_pvt;
06590 int res = 0;
06591 int idx;
06592 ast_setstate(ast, AST_STATE_UP);
06593 ast_mutex_lock(&p->lock);
06594 idx = dahdi_get_index(ast, p, 0);
06595 if (idx < 0)
06596 idx = SUB_REAL;
06597
06598 if ((p->radio || (p->oprmode < 0))) {
06599 ast_mutex_unlock(&p->lock);
06600 return 0;
06601 }
06602
06603 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06604 res = analog_answer(p->sig_pvt, ast);
06605 ast_mutex_unlock(&p->lock);
06606 return res;
06607 }
06608
06609 switch (p->sig) {
06610 #if defined(HAVE_PRI)
06611 case SIG_PRI_LIB_HANDLE_CASES:
06612 res = sig_pri_answer(p->sig_pvt, ast);
06613 break;
06614 #endif
06615 #if defined(HAVE_SS7)
06616 case SIG_SS7:
06617 res = sig_ss7_answer(p->sig_pvt, ast);
06618 break;
06619 #endif
06620 #ifdef HAVE_OPENR2
06621 case SIG_MFCR2:
06622 if (!p->mfcr2_call_accepted) {
06623
06624
06625 p->mfcr2_answer_pending = 1;
06626 if (p->mfcr2_charge_calls) {
06627 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06628 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06629 } else {
06630 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06631 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06632 }
06633 } else {
06634 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06635 dahdi_r2_answer(p);
06636 }
06637 break;
06638 #endif
06639 case 0:
06640 ast_mutex_unlock(&p->lock);
06641 return 0;
06642 default:
06643 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06644 res = -1;
06645 break;
06646 }
06647 ast_mutex_unlock(&p->lock);
06648 return res;
06649 }
06650
06651 static void disable_dtmf_detect(struct dahdi_pvt *p)
06652 {
06653 int val = 0;
06654
06655 p->ignoredtmf = 1;
06656
06657 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06658
06659 if (!p->hardwaredtmf && p->dsp) {
06660 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06661 ast_dsp_set_features(p->dsp, p->dsp_features);
06662 }
06663 }
06664
06665 static void enable_dtmf_detect(struct dahdi_pvt *p)
06666 {
06667 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06668
06669 if (p->channel == CHAN_PSEUDO)
06670 return;
06671
06672 p->ignoredtmf = 0;
06673
06674 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06675
06676 if (!p->hardwaredtmf && p->dsp) {
06677 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06678 ast_dsp_set_features(p->dsp, p->dsp_features);
06679 }
06680 }
06681
06682 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06683 {
06684 char *cp;
06685 struct dahdi_pvt *p = chan->tech_pvt;
06686
06687
06688 if (!p || !data || (*datalen < 1)) {
06689 errno = EINVAL;
06690 return -1;
06691 }
06692
06693 switch (option) {
06694 case AST_OPTION_DIGIT_DETECT:
06695 cp = (char *) data;
06696 *cp = p->ignoredtmf ? 0 : 1;
06697 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06698 break;
06699 case AST_OPTION_FAX_DETECT:
06700 cp = (char *) data;
06701 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06702 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06703 break;
06704 case AST_OPTION_CC_AGENT_TYPE:
06705 #if defined(HAVE_PRI)
06706 #if defined(HAVE_PRI_CCSS)
06707 if (dahdi_sig_pri_lib_handles(p->sig)) {
06708 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06709 break;
06710 }
06711 #endif
06712 #endif
06713 return -1;
06714 default:
06715 return -1;
06716 }
06717
06718 errno = 0;
06719
06720 return 0;
06721 }
06722
06723 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06724 {
06725 char *cp;
06726 signed char *scp;
06727 int x;
06728 int idx;
06729 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06730 struct oprmode *oprmode;
06731
06732
06733
06734 if (!p || !data || (datalen < 1)) {
06735 errno = EINVAL;
06736 return -1;
06737 }
06738
06739 switch (option) {
06740 case AST_OPTION_TXGAIN:
06741 scp = (signed char *) data;
06742 idx = dahdi_get_index(chan, p, 0);
06743 if (idx < 0) {
06744 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06745 return -1;
06746 }
06747 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06748 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06749 case AST_OPTION_RXGAIN:
06750 scp = (signed char *) data;
06751 idx = dahdi_get_index(chan, p, 0);
06752 if (idx < 0) {
06753 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06754 return -1;
06755 }
06756 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06757 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06758 case AST_OPTION_TONE_VERIFY:
06759 if (!p->dsp)
06760 break;
06761 cp = (char *) data;
06762 switch (*cp) {
06763 case 1:
06764 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06765 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06766 break;
06767 case 2:
06768 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06769 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06770 break;
06771 default:
06772 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06773 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06774 break;
06775 }
06776 break;
06777 case AST_OPTION_TDD:
06778
06779 cp = (char *) data;
06780 p->mate = 0;
06781 if (!*cp) {
06782 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06783 if (p->tdd)
06784 tdd_free(p->tdd);
06785 p->tdd = 0;
06786 break;
06787 }
06788 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06789 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06790 dahdi_disable_ec(p);
06791
06792 if (!p->didtdd) {
06793 unsigned char mybuf[41000];
06794 unsigned char *buf;
06795 int size, res, fd, len;
06796 struct pollfd fds[1];
06797
06798 buf = mybuf;
06799 memset(buf, 0x7f, sizeof(mybuf));
06800 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06801 len = 40000;
06802 idx = dahdi_get_index(chan, p, 0);
06803 if (idx < 0) {
06804 ast_log(LOG_WARNING, "No index in TDD?\n");
06805 return -1;
06806 }
06807 fd = p->subs[idx].dfd;
06808 while (len) {
06809 if (ast_check_hangup(chan))
06810 return -1;
06811 size = len;
06812 if (size > READ_SIZE)
06813 size = READ_SIZE;
06814 fds[0].fd = fd;
06815 fds[0].events = POLLPRI | POLLOUT;
06816 fds[0].revents = 0;
06817 res = poll(fds, 1, -1);
06818 if (!res) {
06819 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06820 continue;
06821 }
06822
06823 if (fds[0].revents & POLLPRI)
06824 return -1;
06825 if (!(fds[0].revents & POLLOUT)) {
06826 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06827 continue;
06828 }
06829 res = write(fd, buf, size);
06830 if (res != size) {
06831 if (res == -1) return -1;
06832 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06833 break;
06834 }
06835 len -= size;
06836 buf += size;
06837 }
06838 p->didtdd = 1;
06839 }
06840 if (*cp == 2) {
06841 if (p->tdd)
06842 tdd_free(p->tdd);
06843 p->tdd = 0;
06844 p->mate = 1;
06845 break;
06846 }
06847 if (!p->tdd) {
06848 p->tdd = tdd_new();
06849 }
06850 break;
06851 case AST_OPTION_RELAXDTMF:
06852 if (!p->dsp)
06853 break;
06854 cp = (char *) data;
06855 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06856 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06857 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06858 break;
06859 case AST_OPTION_AUDIO_MODE:
06860 #if defined(HAVE_PRI)
06861 if (dahdi_sig_pri_lib_handles(p->sig)
06862 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06863
06864 break;
06865 }
06866 #endif
06867
06868 cp = (char *) data;
06869 if (!*cp) {
06870 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06871 x = 0;
06872 dahdi_disable_ec(p);
06873 } else {
06874 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06875 x = 1;
06876 }
06877 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06878 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06879 break;
06880 case AST_OPTION_OPRMODE:
06881 oprmode = (struct oprmode *) data;
06882
06883 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06884 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06885 chan->tech->type, oprmode->peer->tech->type);
06886 errno = EINVAL;
06887 return -1;
06888 }
06889 pp = oprmode->peer->tech_pvt;
06890 p->oprmode = pp->oprmode = 0;
06891
06892 p->oprpeer = pp;
06893 pp->oprpeer = p;
06894
06895 if (oprmode->mode)
06896 {
06897 pp->oprmode = oprmode->mode;
06898 p->oprmode = -oprmode->mode;
06899 }
06900 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06901 oprmode->mode, chan->name,oprmode->peer->name);
06902 break;
06903 case AST_OPTION_ECHOCAN:
06904 cp = (char *) data;
06905 if (*cp) {
06906 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06907 dahdi_enable_ec(p);
06908 } else {
06909 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06910 dahdi_disable_ec(p);
06911 }
06912 break;
06913 case AST_OPTION_DIGIT_DETECT:
06914 cp = (char *) data;
06915 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06916 if (*cp) {
06917 enable_dtmf_detect(p);
06918 } else {
06919 disable_dtmf_detect(p);
06920 }
06921 break;
06922 case AST_OPTION_FAX_DETECT:
06923 cp = (char *) data;
06924 if (p->dsp) {
06925 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06926 if (*cp) {
06927 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06928 } else {
06929 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06930 }
06931 ast_dsp_set_features(p->dsp, p->dsp_features);
06932 }
06933 break;
06934 default:
06935 return -1;
06936 }
06937 errno = 0;
06938
06939 return 0;
06940 }
06941
06942 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06943 {
06944 struct dahdi_pvt *p = chan->tech_pvt;
06945 int res = 0;
06946
06947 if (!p) {
06948
06949 *buf = '\0';
06950 return -1;
06951 }
06952
06953 if (!strcasecmp(data, "rxgain")) {
06954 ast_mutex_lock(&p->lock);
06955 snprintf(buf, len, "%f", p->rxgain);
06956 ast_mutex_unlock(&p->lock);
06957 } else if (!strcasecmp(data, "txgain")) {
06958 ast_mutex_lock(&p->lock);
06959 snprintf(buf, len, "%f", p->txgain);
06960 ast_mutex_unlock(&p->lock);
06961 } else if (!strcasecmp(data, "dahdi_channel")) {
06962 ast_mutex_lock(&p->lock);
06963 snprintf(buf, len, "%d", p->channel);
06964 ast_mutex_unlock(&p->lock);
06965 } else if (!strcasecmp(data, "dahdi_span")) {
06966 ast_mutex_lock(&p->lock);
06967 snprintf(buf, len, "%d", p->span);
06968 ast_mutex_unlock(&p->lock);
06969 } else if (!strcasecmp(data, "dahdi_type")) {
06970 ast_mutex_lock(&p->lock);
06971 switch (p->sig) {
06972 #if defined(HAVE_OPENR2)
06973 case SIG_MFCR2:
06974 ast_copy_string(buf, "mfc/r2", len);
06975 break;
06976 #endif
06977 #if defined(HAVE_PRI)
06978 case SIG_PRI_LIB_HANDLE_CASES:
06979 ast_copy_string(buf, "pri", len);
06980 break;
06981 #endif
06982 case 0:
06983 ast_copy_string(buf, "pseudo", len);
06984 break;
06985 #if defined(HAVE_SS7)
06986 case SIG_SS7:
06987 ast_copy_string(buf, "ss7", len);
06988 break;
06989 #endif
06990 default:
06991
06992 ast_copy_string(buf, "analog", len);
06993 break;
06994 }
06995 ast_mutex_unlock(&p->lock);
06996 #if defined(HAVE_PRI)
06997 #if defined(HAVE_PRI_REVERSE_CHARGE)
06998 } else if (!strcasecmp(data, "reversecharge")) {
06999 ast_mutex_lock(&p->lock);
07000 switch (p->sig) {
07001 case SIG_PRI_LIB_HANDLE_CASES:
07002 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07003 break;
07004 default:
07005 *buf = '\0';
07006 res = -1;
07007 break;
07008 }
07009 ast_mutex_unlock(&p->lock);
07010 #endif
07011 #if defined(HAVE_PRI_SETUP_KEYPAD)
07012 } else if (!strcasecmp(data, "keypad_digits")) {
07013 ast_mutex_lock(&p->lock);
07014 switch (p->sig) {
07015 case SIG_PRI_LIB_HANDLE_CASES:
07016 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07017 len);
07018 break;
07019 default:
07020 *buf = '\0';
07021 res = -1;
07022 break;
07023 }
07024 ast_mutex_unlock(&p->lock);
07025 #endif
07026 } else if (!strcasecmp(data, "no_media_path")) {
07027 ast_mutex_lock(&p->lock);
07028 switch (p->sig) {
07029 case SIG_PRI_LIB_HANDLE_CASES:
07030
07031
07032
07033
07034 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07035 break;
07036 default:
07037 *buf = '\0';
07038 res = -1;
07039 break;
07040 }
07041 ast_mutex_unlock(&p->lock);
07042 #endif
07043 } else {
07044 *buf = '\0';
07045 res = -1;
07046 }
07047
07048 return res;
07049 }
07050
07051
07052 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07053 {
07054 int res;
07055 char policy_str[21] = "";
07056
07057 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07058 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07059 return 1;
07060 }
07061 if (*num_buffers < 0) {
07062 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07063 return -1;
07064 }
07065 if (!strcasecmp(policy_str, "full")) {
07066 *policy = DAHDI_POLICY_WHEN_FULL;
07067 } else if (!strcasecmp(policy_str, "immediate")) {
07068 *policy = DAHDI_POLICY_IMMEDIATE;
07069 #if defined(HAVE_DAHDI_HALF_FULL)
07070 } else if (!strcasecmp(policy_str, "half")) {
07071 *policy = DAHDI_POLICY_HALF_FULL;
07072 #endif
07073 } else {
07074 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07075 return -1;
07076 }
07077
07078 return 0;
07079 }
07080
07081 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07082 {
07083 struct dahdi_pvt *p = chan->tech_pvt;
07084 int res = 0;
07085
07086 if (!p) {
07087
07088 return -1;
07089 }
07090
07091 if (!strcasecmp(data, "buffers")) {
07092 int num_bufs, policy;
07093
07094 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07095 struct dahdi_bufferinfo bi = {
07096 .txbufpolicy = policy,
07097 .rxbufpolicy = policy,
07098 .bufsize = p->bufsize,
07099 .numbufs = num_bufs,
07100 };
07101 int bpres;
07102
07103 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07104 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07105 } else {
07106 p->bufferoverrideinuse = 1;
07107 }
07108 } else {
07109 res = -1;
07110 }
07111 } else if (!strcasecmp(data, "echocan_mode")) {
07112 if (!strcasecmp(value, "on")) {
07113 ast_mutex_lock(&p->lock);
07114 dahdi_enable_ec(p);
07115 ast_mutex_unlock(&p->lock);
07116 } else if (!strcasecmp(value, "off")) {
07117 ast_mutex_lock(&p->lock);
07118 dahdi_disable_ec(p);
07119 ast_mutex_unlock(&p->lock);
07120 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07121 } else if (!strcasecmp(value, "fax")) {
07122 int blah = 1;
07123
07124 ast_mutex_lock(&p->lock);
07125 if (!p->echocanon) {
07126 dahdi_enable_ec(p);
07127 }
07128 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07129 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07130 }
07131 ast_mutex_unlock(&p->lock);
07132 } else if (!strcasecmp(value, "voice")) {
07133 int blah = 0;
07134
07135 ast_mutex_lock(&p->lock);
07136 if (!p->echocanon) {
07137 dahdi_enable_ec(p);
07138 }
07139 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07140 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07141 }
07142 ast_mutex_unlock(&p->lock);
07143 #endif
07144 } else {
07145 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07146 res = -1;
07147 }
07148 } else {
07149 res = -1;
07150 }
07151
07152 return res;
07153 }
07154
07155 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07156 {
07157
07158 int x;
07159 int hasslaves;
07160 if (!master)
07161 return;
07162 if (needlock) {
07163 ast_mutex_lock(&master->lock);
07164 if (slave) {
07165 while (ast_mutex_trylock(&slave->lock)) {
07166 DEADLOCK_AVOIDANCE(&master->lock);
07167 }
07168 }
07169 }
07170 hasslaves = 0;
07171 for (x = 0; x < MAX_SLAVES; x++) {
07172 if (master->slaves[x]) {
07173 if (!slave || (master->slaves[x] == slave)) {
07174
07175 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07176 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07177 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07178 master->slaves[x]->master = NULL;
07179 master->slaves[x] = NULL;
07180 } else
07181 hasslaves = 1;
07182 }
07183 if (!hasslaves)
07184 master->inconference = 0;
07185 }
07186 if (!slave) {
07187 if (master->master) {
07188
07189 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07190 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07191 hasslaves = 0;
07192 for (x = 0; x < MAX_SLAVES; x++) {
07193 if (master->master->slaves[x] == master)
07194 master->master->slaves[x] = NULL;
07195 else if (master->master->slaves[x])
07196 hasslaves = 1;
07197 }
07198 if (!hasslaves)
07199 master->master->inconference = 0;
07200 }
07201 master->master = NULL;
07202 }
07203 update_conf(master);
07204 if (needlock) {
07205 if (slave)
07206 ast_mutex_unlock(&slave->lock);
07207 ast_mutex_unlock(&master->lock);
07208 }
07209 }
07210
07211 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07212 int x;
07213 if (!slave || !master) {
07214 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07215 return;
07216 }
07217 for (x = 0; x < MAX_SLAVES; x++) {
07218 if (!master->slaves[x]) {
07219 master->slaves[x] = slave;
07220 break;
07221 }
07222 }
07223 if (x >= MAX_SLAVES) {
07224 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07225 master->slaves[MAX_SLAVES - 1] = slave;
07226 }
07227 if (slave->master)
07228 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07229 slave->master = master;
07230
07231 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07232 }
07233
07234 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)
07235 {
07236 struct ast_channel *who;
07237 struct dahdi_pvt *p0, *p1, *op0, *op1;
07238 struct dahdi_pvt *master = NULL, *slave = NULL;
07239 struct ast_frame *f;
07240 int inconf = 0;
07241 int nothingok = 1;
07242 int ofd0, ofd1;
07243 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07244 int os0 = -1, os1 = -1;
07245 int priority = 0;
07246 struct ast_channel *oc0, *oc1;
07247 enum ast_bridge_result res;
07248 struct timeval start = ast_tvnow();
07249 #ifdef PRI_2BCT
07250 int triedtopribridge = 0;
07251 q931_call *q931c0;
07252 q931_call *q931c1;
07253 #endif
07254
07255
07256
07257
07258
07259
07260 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07261 return AST_BRIDGE_FAILED_NOWARN;
07262
07263 ast_channel_lock(c0);
07264 while (ast_channel_trylock(c1)) {
07265 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07266 }
07267
07268 p0 = c0->tech_pvt;
07269 p1 = c1->tech_pvt;
07270
07271 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07272 ast_channel_unlock(c0);
07273 ast_channel_unlock(c1);
07274 return AST_BRIDGE_FAILED_NOWARN;
07275 }
07276
07277 oi0 = dahdi_get_index(c0, p0, 0);
07278 oi1 = dahdi_get_index(c1, p1, 0);
07279 if ((oi0 < 0) || (oi1 < 0)) {
07280 ast_channel_unlock(c0);
07281 ast_channel_unlock(c1);
07282 return AST_BRIDGE_FAILED;
07283 }
07284
07285 op0 = p0 = c0->tech_pvt;
07286 op1 = p1 = c1->tech_pvt;
07287 ofd0 = c0->fds[0];
07288 ofd1 = c1->fds[0];
07289 oc0 = p0->owner;
07290 oc1 = p1->owner;
07291
07292 if (ast_mutex_trylock(&p0->lock)) {
07293
07294 ast_channel_unlock(c0);
07295 ast_channel_unlock(c1);
07296 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07297 return AST_BRIDGE_RETRY;
07298 }
07299 if (ast_mutex_trylock(&p1->lock)) {
07300
07301 ast_mutex_unlock(&p0->lock);
07302 ast_channel_unlock(c0);
07303 ast_channel_unlock(c1);
07304 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07305 return AST_BRIDGE_RETRY;
07306 }
07307
07308 if ((p0->callwaiting && p0->callwaitingcallerid)
07309 || (p1->callwaiting && p1->callwaitingcallerid)) {
07310
07311
07312
07313
07314
07315
07316
07317
07318
07319 ast_mutex_unlock(&p0->lock);
07320 ast_mutex_unlock(&p1->lock);
07321 ast_channel_unlock(c0);
07322 ast_channel_unlock(c1);
07323 return AST_BRIDGE_FAILED_NOWARN;
07324 }
07325
07326 #if defined(HAVE_PRI)
07327 if ((dahdi_sig_pri_lib_handles(p0->sig)
07328 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07329 || (dahdi_sig_pri_lib_handles(p1->sig)
07330 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07331
07332
07333
07334
07335 ast_mutex_unlock(&p0->lock);
07336 ast_mutex_unlock(&p1->lock);
07337 ast_channel_unlock(c0);
07338 ast_channel_unlock(c1);
07339 return AST_BRIDGE_FAILED_NOWARN;
07340 }
07341 #endif
07342
07343 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07344 if (p0->owner && p1->owner) {
07345
07346 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07347 master = p0;
07348 slave = p1;
07349 inconf = 1;
07350 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07351 master = p1;
07352 slave = p0;
07353 inconf = 1;
07354 } else {
07355 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07356 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07357 p0->channel,
07358 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07359 p0->subs[SUB_REAL].inthreeway, p0->channel,
07360 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07361 p1->subs[SUB_REAL].inthreeway);
07362 }
07363 nothingok = 0;
07364 }
07365 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07366 if (p1->subs[SUB_THREEWAY].inthreeway) {
07367 master = p1;
07368 slave = p0;
07369 nothingok = 0;
07370 }
07371 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07372 if (p0->subs[SUB_THREEWAY].inthreeway) {
07373 master = p0;
07374 slave = p1;
07375 nothingok = 0;
07376 }
07377 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07378
07379
07380 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07381 master = p1;
07382 slave = p0;
07383 nothingok = 0;
07384 }
07385 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07386
07387 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07388 master = p0;
07389 slave = p1;
07390 nothingok = 0;
07391 }
07392 }
07393 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07394 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07395 if (master && slave) {
07396
07397
07398
07399 if ((oi1 == SUB_THREEWAY) &&
07400 p1->subs[SUB_THREEWAY].inthreeway &&
07401 p1->subs[SUB_REAL].owner &&
07402 p1->subs[SUB_REAL].inthreeway &&
07403 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07404 ast_debug(1,
07405 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07406 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07407 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07408 os1 = p1->subs[SUB_REAL].owner->_state;
07409 } else {
07410 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07411 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07412 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07413 }
07414 if ((oi0 == SUB_THREEWAY) &&
07415 p0->subs[SUB_THREEWAY].inthreeway &&
07416 p0->subs[SUB_REAL].owner &&
07417 p0->subs[SUB_REAL].inthreeway &&
07418 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07419 ast_debug(1,
07420 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07421 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07422 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07423 os0 = p0->subs[SUB_REAL].owner->_state;
07424 } else {
07425 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07426 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07427 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07428 }
07429 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07430 if (!p0->echocanbridged || !p1->echocanbridged) {
07431
07432 dahdi_disable_ec(p0);
07433 dahdi_disable_ec(p1);
07434 }
07435 }
07436 dahdi_link(slave, master);
07437 master->inconference = inconf;
07438 } else if (!nothingok)
07439 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07440
07441 update_conf(p0);
07442 update_conf(p1);
07443 t0 = p0->subs[SUB_REAL].inthreeway;
07444 t1 = p1->subs[SUB_REAL].inthreeway;
07445
07446 ast_mutex_unlock(&p0->lock);
07447 ast_mutex_unlock(&p1->lock);
07448
07449 ast_channel_unlock(c0);
07450 ast_channel_unlock(c1);
07451
07452
07453 if ((!master || !slave) && !nothingok) {
07454 dahdi_enable_ec(p0);
07455 dahdi_enable_ec(p1);
07456 return AST_BRIDGE_FAILED;
07457 }
07458
07459 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07460
07461 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07462 disable_dtmf_detect(op0);
07463
07464 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07465 disable_dtmf_detect(op1);
07466
07467 for (;;) {
07468 struct ast_channel *c0_priority[2] = {c0, c1};
07469 struct ast_channel *c1_priority[2] = {c1, c0};
07470 int ms;
07471
07472
07473
07474
07475 ast_channel_lock(c0);
07476 while (ast_channel_trylock(c1)) {
07477 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07478 }
07479
07480 p0 = c0->tech_pvt;
07481 p1 = c1->tech_pvt;
07482
07483 if (op0 == p0)
07484 i0 = dahdi_get_index(c0, p0, 1);
07485 if (op1 == p1)
07486 i1 = dahdi_get_index(c1, p1, 1);
07487
07488 ast_channel_unlock(c0);
07489 ast_channel_unlock(c1);
07490 ms = ast_remaining_ms(start, timeoutms);
07491 if (!ms ||
07492 (op0 != p0) ||
07493 (op1 != p1) ||
07494 (ofd0 != c0->fds[0]) ||
07495 (ofd1 != c1->fds[0]) ||
07496 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07497 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07498 (oc0 != p0->owner) ||
07499 (oc1 != p1->owner) ||
07500 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07501 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07502 (oi0 != i0) ||
07503 (oi1 != i1)) {
07504 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07505 op0->channel, oi0, op1->channel, oi1);
07506 res = AST_BRIDGE_RETRY;
07507 goto return_from_bridge;
07508 }
07509
07510 #ifdef PRI_2BCT
07511 if (!triedtopribridge) {
07512 triedtopribridge = 1;
07513 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07514 ast_mutex_lock(&p0->pri->lock);
07515 switch (p0->sig) {
07516 case SIG_PRI_LIB_HANDLE_CASES:
07517 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07518 break;
07519 default:
07520 q931c0 = NULL;
07521 break;
07522 }
07523 switch (p1->sig) {
07524 case SIG_PRI_LIB_HANDLE_CASES:
07525 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07526 break;
07527 default:
07528 q931c1 = NULL;
07529 break;
07530 }
07531 if (q931c0 && q931c1) {
07532 pri_channel_bridge(q931c0, q931c1);
07533 }
07534 ast_mutex_unlock(&p0->pri->lock);
07535 }
07536 }
07537 #endif
07538
07539 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07540 if (!who) {
07541 ast_debug(1, "Ooh, empty read...\n");
07542 continue;
07543 }
07544 f = ast_read(who);
07545 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07546 *fo = f;
07547 *rc = who;
07548 res = AST_BRIDGE_COMPLETE;
07549 goto return_from_bridge;
07550 }
07551 if (f->frametype == AST_FRAME_DTMF) {
07552 if ((who == c0) && p0->pulsedial) {
07553 ast_write(c1, f);
07554 } else if ((who == c1) && p1->pulsedial) {
07555 ast_write(c0, f);
07556 } else {
07557 *fo = f;
07558 *rc = who;
07559 res = AST_BRIDGE_COMPLETE;
07560 goto return_from_bridge;
07561 }
07562 }
07563 ast_frfree(f);
07564
07565
07566 priority = !priority;
07567 }
07568
07569 return_from_bridge:
07570 if (op0 == p0)
07571 dahdi_enable_ec(p0);
07572
07573 if (op1 == p1)
07574 dahdi_enable_ec(p1);
07575
07576 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07577 enable_dtmf_detect(op0);
07578
07579 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07580 enable_dtmf_detect(op1);
07581
07582 dahdi_unlink(slave, master, 1);
07583
07584 return res;
07585 }
07586
07587 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07588 {
07589 struct dahdi_pvt *p = newchan->tech_pvt;
07590 int x;
07591
07592 ast_mutex_lock(&p->lock);
07593
07594 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07595 if (p->owner == oldchan) {
07596 p->owner = newchan;
07597 }
07598 for (x = 0; x < 3; x++) {
07599 if (p->subs[x].owner == oldchan) {
07600 if (!x) {
07601 dahdi_unlink(NULL, p, 0);
07602 }
07603 p->subs[x].owner = newchan;
07604 }
07605 }
07606 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07607 analog_fixup(oldchan, newchan, p->sig_pvt);
07608 #if defined(HAVE_PRI)
07609 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07610 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07611 #endif
07612 #if defined(HAVE_SS7)
07613 } else if (p->sig == SIG_SS7) {
07614 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07615 #endif
07616 }
07617 update_conf(p);
07618
07619 ast_mutex_unlock(&p->lock);
07620
07621 if (newchan->_state == AST_STATE_RINGING) {
07622 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07623 }
07624 return 0;
07625 }
07626
07627 static int dahdi_ring_phone(struct dahdi_pvt *p)
07628 {
07629 int x;
07630 int res;
07631
07632 x = 0;
07633 x = DAHDI_ONHOOK;
07634 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07635 do {
07636 x = DAHDI_RING;
07637 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07638 if (res) {
07639 switch (errno) {
07640 case EBUSY:
07641 case EINTR:
07642
07643 usleep(10000);
07644 continue;
07645 case EINPROGRESS:
07646 res = 0;
07647 break;
07648 default:
07649 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07650 res = 0;
07651 }
07652 }
07653 } while (res);
07654 return res;
07655 }
07656
07657 static void *analog_ss_thread(void *data);
07658
07659 static int attempt_transfer(struct dahdi_pvt *p)
07660 {
07661
07662
07663
07664 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07665
07666
07667 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07668 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07669 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07670 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07671 }
07672 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07673 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07674 }
07675 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07676 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07677 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07678 return -1;
07679 }
07680
07681 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07682 unalloc_sub(p, SUB_THREEWAY);
07683 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07684 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07685 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07686 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07687 }
07688 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07689 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07690 }
07691 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07692 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07693 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07694 return -1;
07695 }
07696
07697 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07698 ast_channel_unlock(p->subs[SUB_REAL].owner);
07699 unalloc_sub(p, SUB_THREEWAY);
07700
07701 return 1;
07702 } else {
07703 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07704 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07705 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07706 return -1;
07707 }
07708 return 0;
07709 }
07710
07711 static int check_for_conference(struct dahdi_pvt *p)
07712 {
07713 struct dahdi_confinfo ci;
07714
07715 if (p->master || (p->confno > -1))
07716 return 0;
07717 memset(&ci, 0, sizeof(ci));
07718 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07719 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07720 return 0;
07721 }
07722
07723
07724
07725 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07726 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07727 return 1;
07728 }
07729 return 0;
07730 }
07731
07732
07733
07734
07735
07736
07737 static int get_alarms(struct dahdi_pvt *p)
07738 {
07739 int res;
07740 struct dahdi_spaninfo zi;
07741 struct dahdi_params params;
07742
07743 memset(&zi, 0, sizeof(zi));
07744 zi.spanno = p->span;
07745
07746 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07747 if (zi.alarms != DAHDI_ALARM_NONE)
07748 return zi.alarms;
07749 } else {
07750 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07751 return 0;
07752 }
07753
07754
07755 memset(¶ms, 0, sizeof(params));
07756 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07757 return params.chan_alarms;
07758
07759 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07760
07761 return DAHDI_ALARM_NONE;
07762 }
07763
07764 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07765 {
07766 struct dahdi_pvt *p = ast->tech_pvt;
07767 struct ast_frame *f = *dest;
07768
07769 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07770 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07771 f->subclass.integer, f->subclass.integer, ast->name);
07772
07773 if (p->confirmanswer) {
07774 if (f->frametype == AST_FRAME_DTMF_END) {
07775 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07776
07777
07778 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07779 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07780
07781 p->confirmanswer = 0;
07782 } else {
07783 p->subs[idx].f.frametype = AST_FRAME_NULL;
07784 p->subs[idx].f.subclass.integer = 0;
07785 }
07786 *dest = &p->subs[idx].f;
07787 } else if (p->callwaitcas) {
07788 if (f->frametype == AST_FRAME_DTMF_END) {
07789 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07790 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07791 ast_free(p->cidspill);
07792 p->cidspill = NULL;
07793 send_cwcidspill(p);
07794 }
07795 p->callwaitcas = 0;
07796 }
07797 p->subs[idx].f.frametype = AST_FRAME_NULL;
07798 p->subs[idx].f.subclass.integer = 0;
07799 *dest = &p->subs[idx].f;
07800 } else if (f->subclass.integer == 'f') {
07801 if (f->frametype == AST_FRAME_DTMF_END) {
07802
07803 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07804
07805 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07806 struct dahdi_bufferinfo bi = {
07807 .txbufpolicy = p->faxbuf_policy,
07808 .bufsize = p->bufsize,
07809 .numbufs = p->faxbuf_no
07810 };
07811 int res;
07812
07813 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07814 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07815 } else {
07816 p->bufferoverrideinuse = 1;
07817 }
07818 }
07819 p->faxhandled = 1;
07820 if (p->dsp) {
07821 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07822 ast_dsp_set_features(p->dsp, p->dsp_features);
07823 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07824 }
07825 if (strcmp(ast->exten, "fax")) {
07826 const char *target_context = S_OR(ast->macrocontext, ast->context);
07827
07828
07829
07830
07831
07832 ast_mutex_unlock(&p->lock);
07833 ast_channel_unlock(ast);
07834 if (ast_exists_extension(ast, target_context, "fax", 1,
07835 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07836 ast_channel_lock(ast);
07837 ast_mutex_lock(&p->lock);
07838 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07839
07840 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07841 if (ast_async_goto(ast, target_context, "fax", 1))
07842 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07843 } else {
07844 ast_channel_lock(ast);
07845 ast_mutex_lock(&p->lock);
07846 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07847 }
07848 } else {
07849 ast_debug(1, "Already in a fax extension, not redirecting\n");
07850 }
07851 } else {
07852 ast_debug(1, "Fax already handled\n");
07853 }
07854 dahdi_confmute(p, 0);
07855 }
07856 p->subs[idx].f.frametype = AST_FRAME_NULL;
07857 p->subs[idx].f.subclass.integer = 0;
07858 *dest = &p->subs[idx].f;
07859 }
07860 }
07861
07862 static void handle_alarms(struct dahdi_pvt *p, int alms)
07863 {
07864 const char *alarm_str;
07865
07866 #if defined(HAVE_PRI)
07867 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07868 return;
07869 }
07870 #endif
07871
07872 alarm_str = alarm2str(alms);
07873 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07874 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07875 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07876 "Alarm: %s\r\n"
07877 "Channel: %d\r\n",
07878 alarm_str, p->channel);
07879 }
07880
07881 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07882 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07883 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07884 "Alarm: %s\r\n"
07885 "Span: %d\r\n",
07886 alarm_str, p->span);
07887 }
07888 }
07889
07890 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07891 {
07892 int res, x;
07893 int idx, mysig;
07894 char *c;
07895 struct dahdi_pvt *p = ast->tech_pvt;
07896 pthread_t threadid;
07897 struct ast_channel *chan;
07898 struct ast_frame *f;
07899
07900 idx = dahdi_get_index(ast, p, 0);
07901 if (idx < 0) {
07902 return &ast_null_frame;
07903 }
07904 mysig = p->sig;
07905 if (p->outsigmod > -1)
07906 mysig = p->outsigmod;
07907 p->subs[idx].f.frametype = AST_FRAME_NULL;
07908 p->subs[idx].f.subclass.integer = 0;
07909 p->subs[idx].f.datalen = 0;
07910 p->subs[idx].f.samples = 0;
07911 p->subs[idx].f.mallocd = 0;
07912 p->subs[idx].f.offset = 0;
07913 p->subs[idx].f.src = "dahdi_handle_event";
07914 p->subs[idx].f.data.ptr = NULL;
07915 f = &p->subs[idx].f;
07916
07917 if (p->fake_event) {
07918 res = p->fake_event;
07919 p->fake_event = 0;
07920 } else
07921 res = dahdi_get_event(p->subs[idx].dfd);
07922
07923 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07924
07925 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07926 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07927 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07928 #if defined(HAVE_PRI)
07929 if (dahdi_sig_pri_lib_handles(p->sig)
07930 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07931 && p->pri
07932 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07933
07934 } else
07935 #endif
07936 {
07937
07938 dahdi_confmute(p, 0);
07939 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07940 p->subs[idx].f.subclass.integer = res & 0xff;
07941 dahdi_handle_dtmf(ast, idx, &f);
07942 }
07943 return f;
07944 }
07945
07946 if (res & DAHDI_EVENT_DTMFDOWN) {
07947 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07948 #if defined(HAVE_PRI)
07949 if (dahdi_sig_pri_lib_handles(p->sig)
07950 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07951 && p->pri
07952 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07953
07954 } else
07955 #endif
07956 {
07957
07958 dahdi_confmute(p, 1);
07959 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07960 p->subs[idx].f.subclass.integer = res & 0xff;
07961 dahdi_handle_dtmf(ast, idx, &f);
07962 }
07963 return &p->subs[idx].f;
07964 }
07965
07966 switch (res) {
07967 case DAHDI_EVENT_EC_DISABLED:
07968 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07969 p->echocanon = 0;
07970 break;
07971 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07972 case DAHDI_EVENT_TX_CED_DETECTED:
07973 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07974 break;
07975 case DAHDI_EVENT_RX_CED_DETECTED:
07976 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07977 break;
07978 case DAHDI_EVENT_EC_NLP_DISABLED:
07979 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07980 break;
07981 case DAHDI_EVENT_EC_NLP_ENABLED:
07982 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07983 break;
07984 #endif
07985 case DAHDI_EVENT_BITSCHANGED:
07986 #ifdef HAVE_OPENR2
07987 if (p->sig != SIG_MFCR2) {
07988 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07989 } else {
07990 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07991 openr2_chan_handle_cas(p->r2chan);
07992 }
07993 #else
07994 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07995 #endif
07996 break;
07997 case DAHDI_EVENT_PULSE_START:
07998
07999 if (!ast->pbx)
08000 tone_zone_play_tone(p->subs[idx].dfd, -1);
08001 break;
08002 case DAHDI_EVENT_DIALCOMPLETE:
08003
08004 #if defined(HAVE_PRI)
08005 if (dahdi_sig_pri_lib_handles(p->sig)) {
08006 if (p->inalarm) {
08007 break;
08008 }
08009 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08010 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08011 strerror(errno));
08012 return NULL;
08013 }
08014 if (x) {
08015
08016 break;
08017 }
08018
08019
08020
08021
08022 sig_pri_dial_complete(p->sig_pvt, ast);
08023 break;
08024 }
08025 #endif
08026 #ifdef HAVE_OPENR2
08027 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08028
08029
08030 break;
08031 }
08032 #endif
08033 if (p->inalarm) break;
08034 if ((p->radio || (p->oprmode < 0))) break;
08035 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08036 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08037 return NULL;
08038 }
08039 if (!x) {
08040 dahdi_enable_ec(p);
08041 if (p->echobreak) {
08042 dahdi_train_ec(p);
08043 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08044 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08045 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08046 p->echobreak = 0;
08047 } else {
08048 p->dialing = 0;
08049 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08050
08051 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08052 ast_setstate(ast, AST_STATE_UP);
08053 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08054 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08055 break;
08056 } else {
08057
08058 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08059 }
08060 }
08061 if (ast->_state == AST_STATE_DIALING) {
08062 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08063 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08064 } else if (p->confirmanswer || (!p->dialednone
08065 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08066 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08067 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08068 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08069 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08070 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08071 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08072 || (mysig == SIG_SF_FEATB)))) {
08073 ast_setstate(ast, AST_STATE_RINGING);
08074 } else if (!p->answeronpolarityswitch) {
08075 ast_setstate(ast, AST_STATE_UP);
08076 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08077 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08078
08079 p->polarity = POLARITY_REV;
08080 } else {
08081
08082 p->polarity = POLARITY_IDLE;
08083 }
08084 }
08085 }
08086 }
08087 break;
08088 case DAHDI_EVENT_ALARM:
08089 switch (p->sig) {
08090 #if defined(HAVE_PRI)
08091 case SIG_PRI_LIB_HANDLE_CASES:
08092 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08093 break;
08094 #endif
08095 #if defined(HAVE_SS7)
08096 case SIG_SS7:
08097 sig_ss7_set_alarm(p->sig_pvt, 1);
08098 break;
08099 #endif
08100 default:
08101 p->inalarm = 1;
08102 break;
08103 }
08104 res = get_alarms(p);
08105 handle_alarms(p, res);
08106 #ifdef HAVE_PRI
08107 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08108
08109 } else {
08110 break;
08111 }
08112 #endif
08113 #if defined(HAVE_SS7)
08114 if (p->sig == SIG_SS7)
08115 break;
08116 #endif
08117 #ifdef HAVE_OPENR2
08118 if (p->sig == SIG_MFCR2)
08119 break;
08120 #endif
08121 case DAHDI_EVENT_ONHOOK:
08122 if (p->radio) {
08123 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08124 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08125 break;
08126 }
08127 if (p->oprmode < 0)
08128 {
08129 if (p->oprmode != -1) break;
08130 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08131 {
08132
08133 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08134 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08135 save_conference(p->oprpeer);
08136 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08137 }
08138 break;
08139 }
08140 switch (p->sig) {
08141 case SIG_FXOLS:
08142 case SIG_FXOGS:
08143 case SIG_FXOKS:
08144
08145 if (idx == SUB_REAL) {
08146
08147 if (p->subs[SUB_CALLWAIT].owner) {
08148
08149 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08150 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08151 unalloc_sub(p, SUB_CALLWAIT);
08152 #if 0
08153 p->subs[idx].needanswer = 0;
08154 p->subs[idx].needringing = 0;
08155 #endif
08156 p->callwaitingrepeat = 0;
08157 p->cidcwexpire = 0;
08158 p->cid_suppress_expire = 0;
08159 p->owner = NULL;
08160
08161 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08162 p->dialing = 1;
08163 dahdi_ring_phone(p);
08164 } else if (p->subs[SUB_THREEWAY].owner) {
08165 unsigned int mssinceflash;
08166
08167
08168 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08169
08170 DLA_UNLOCK(&p->lock);
08171 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08172
08173
08174
08175 DLA_LOCK(&p->lock);
08176 if (p->owner != ast) {
08177 ast_log(LOG_WARNING, "This isn't good...\n");
08178 return NULL;
08179 }
08180 }
08181 if (!p->subs[SUB_THREEWAY].owner) {
08182 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08183 return NULL;
08184 }
08185 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08186 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08187 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08188
08189
08190 if (p->subs[SUB_THREEWAY].owner)
08191 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08192 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08193 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08194 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08195 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08196 if (p->transfer) {
08197
08198 p->subs[SUB_REAL].inthreeway = 0;
08199 p->subs[SUB_THREEWAY].inthreeway = 0;
08200
08201 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08202 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08203
08204 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08205 p->owner = NULL;
08206
08207 dahdi_ring_phone(p);
08208 } else {
08209 if ((res = attempt_transfer(p)) < 0) {
08210 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08211 if (p->subs[SUB_THREEWAY].owner)
08212 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08213 } else if (res) {
08214
08215 if (p->subs[SUB_THREEWAY].owner)
08216 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08217 break;
08218 }
08219 }
08220 } else {
08221 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08222 if (p->subs[SUB_THREEWAY].owner)
08223 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08224 }
08225 } else {
08226 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08227
08228 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08229 p->owner = NULL;
08230
08231 dahdi_ring_phone(p);
08232 }
08233 }
08234 } else {
08235 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08236 }
08237
08238 default:
08239 dahdi_disable_ec(p);
08240 return NULL;
08241 }
08242 break;
08243 case DAHDI_EVENT_RINGOFFHOOK:
08244 if (p->inalarm) break;
08245 if (p->oprmode < 0)
08246 {
08247 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08248 {
08249
08250 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08251 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08252 restore_conference(p->oprpeer);
08253 }
08254 break;
08255 }
08256 if (p->radio)
08257 {
08258 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08259 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08260 break;
08261 }
08262
08263
08264 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08265 c = strchr(p->dialdest, '/');
08266 if (c)
08267 c++;
08268 else
08269 c = p->dialdest;
08270 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08271 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08272 if (strlen(p->dop.dialstr) > 4) {
08273 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08274 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08275 p->echorest[sizeof(p->echorest) - 1] = '\0';
08276 p->echobreak = 1;
08277 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08278 } else
08279 p->echobreak = 0;
08280 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08281 int saveerr = errno;
08282
08283 x = DAHDI_ONHOOK;
08284 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08285 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08286 return NULL;
08287 }
08288 p->dialing = 1;
08289 return &p->subs[idx].f;
08290 }
08291 switch (p->sig) {
08292 case SIG_FXOLS:
08293 case SIG_FXOGS:
08294 case SIG_FXOKS:
08295 switch (ast->_state) {
08296 case AST_STATE_RINGING:
08297 dahdi_enable_ec(p);
08298 dahdi_train_ec(p);
08299 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08300 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08301
08302 p->subs[SUB_REAL].needringing = 0;
08303 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08304 ast_debug(1, "channel %d answered\n", p->channel);
08305
08306
08307 ast_free(p->cidspill);
08308 p->cidspill = NULL;
08309 restore_conference(p);
08310
08311 p->dialing = 0;
08312 p->callwaitcas = 0;
08313 if (p->confirmanswer) {
08314
08315 p->subs[idx].f.frametype = AST_FRAME_NULL;
08316 p->subs[idx].f.subclass.integer = 0;
08317 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08318
08319 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08320 if (res < 0) {
08321 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08322 p->dop.dialstr[0] = '\0';
08323 return NULL;
08324 } else {
08325 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08326 p->subs[idx].f.frametype = AST_FRAME_NULL;
08327 p->subs[idx].f.subclass.integer = 0;
08328 p->dialing = 1;
08329 }
08330 p->dop.dialstr[0] = '\0';
08331 ast_setstate(ast, AST_STATE_DIALING);
08332 } else
08333 ast_setstate(ast, AST_STATE_UP);
08334 return &p->subs[idx].f;
08335 case AST_STATE_DOWN:
08336 ast_setstate(ast, AST_STATE_RING);
08337 ast->rings = 1;
08338 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08339 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08340 ast_debug(1, "channel %d picked up\n", p->channel);
08341 return &p->subs[idx].f;
08342 case AST_STATE_UP:
08343
08344 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08345
08346 if (ast_bridged_channel(p->owner))
08347 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08348 p->subs[idx].needunhold = 1;
08349 break;
08350 case AST_STATE_RESERVED:
08351
08352 if (has_voicemail(p))
08353 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08354 else
08355 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08356 break;
08357 default:
08358 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08359 }
08360 break;
08361 case SIG_FXSLS:
08362 case SIG_FXSGS:
08363 case SIG_FXSKS:
08364 if (ast->_state == AST_STATE_RING) {
08365 p->ringt = p->ringt_base;
08366 }
08367
08368
08369
08370 ast_debug(1, "Setting IDLE polarity due "
08371 "to ring. Old polarity was %d\n",
08372 p->polarity);
08373 p->polarity = POLARITY_IDLE;
08374
08375
08376 case SIG_EM:
08377 case SIG_EM_E1:
08378 case SIG_EMWINK:
08379 case SIG_FEATD:
08380 case SIG_FEATDMF:
08381 case SIG_FEATDMF_TA:
08382 case SIG_E911:
08383 case SIG_FGC_CAMA:
08384 case SIG_FGC_CAMAMF:
08385 case SIG_FEATB:
08386 case SIG_SF:
08387 case SIG_SFWINK:
08388 case SIG_SF_FEATD:
08389 case SIG_SF_FEATDMF:
08390 case SIG_SF_FEATB:
08391 if (ast->_state == AST_STATE_PRERING)
08392 ast_setstate(ast, AST_STATE_RING);
08393 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08394 ast_debug(1, "Ring detected\n");
08395 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08396 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08397 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08398 ast_debug(1, "Line answered\n");
08399 if (p->confirmanswer) {
08400 p->subs[idx].f.frametype = AST_FRAME_NULL;
08401 p->subs[idx].f.subclass.integer = 0;
08402 } else {
08403 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08404 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08405 ast_setstate(ast, AST_STATE_UP);
08406 }
08407 } else if (ast->_state != AST_STATE_RING)
08408 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08409 break;
08410 default:
08411 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08412 }
08413 break;
08414 case DAHDI_EVENT_RINGBEGIN:
08415 switch (p->sig) {
08416 case SIG_FXSLS:
08417 case SIG_FXSGS:
08418 case SIG_FXSKS:
08419 if (ast->_state == AST_STATE_RING) {
08420 p->ringt = p->ringt_base;
08421 }
08422 break;
08423 }
08424 break;
08425 case DAHDI_EVENT_RINGERON:
08426 break;
08427 case DAHDI_EVENT_NOALARM:
08428 switch (p->sig) {
08429 #if defined(HAVE_PRI)
08430 case SIG_PRI_LIB_HANDLE_CASES:
08431 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08432 break;
08433 #endif
08434 #if defined(HAVE_SS7)
08435 case SIG_SS7:
08436 sig_ss7_set_alarm(p->sig_pvt, 0);
08437 break;
08438 #endif
08439 default:
08440 p->inalarm = 0;
08441 break;
08442 }
08443 handle_clear_alarms(p);
08444 break;
08445 case DAHDI_EVENT_WINKFLASH:
08446 if (p->inalarm) break;
08447 if (p->radio) break;
08448 if (p->oprmode < 0) break;
08449 if (p->oprmode > 1)
08450 {
08451 struct dahdi_params par;
08452
08453 memset(&par, 0, sizeof(par));
08454 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08455 {
08456 if (!par.rxisoffhook)
08457 {
08458
08459 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08460 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08461 save_conference(p);
08462 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08463 }
08464 }
08465 break;
08466 }
08467
08468 p->flashtime = ast_tvnow();
08469 switch (mysig) {
08470 case SIG_FXOLS:
08471 case SIG_FXOGS:
08472 case SIG_FXOKS:
08473 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08474 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08475
08476
08477 ast_free(p->cidspill);
08478 p->cidspill = NULL;
08479 restore_conference(p);
08480 p->callwaitcas = 0;
08481
08482 if (idx != SUB_REAL) {
08483 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08484 goto winkflashdone;
08485 }
08486
08487 if (p->subs[SUB_CALLWAIT].owner) {
08488
08489 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08490 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08491 p->owner = p->subs[SUB_REAL].owner;
08492 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08493 if (p->owner->_state == AST_STATE_RINGING) {
08494 ast_setstate(p->owner, AST_STATE_UP);
08495 p->subs[SUB_REAL].needanswer = 1;
08496 }
08497 p->callwaitingrepeat = 0;
08498 p->cidcwexpire = 0;
08499 p->cid_suppress_expire = 0;
08500
08501 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08502 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08503 S_OR(p->mohsuggest, NULL),
08504 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08505 }
08506 p->subs[SUB_CALLWAIT].needhold = 1;
08507 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08508 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08509 S_OR(p->mohsuggest, NULL),
08510 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08511 }
08512 p->subs[SUB_REAL].needunhold = 1;
08513 } else if (!p->subs[SUB_THREEWAY].owner) {
08514 if (!p->threewaycalling) {
08515
08516 p->subs[SUB_REAL].needflash = 1;
08517 goto winkflashdone;
08518 } else if (!check_for_conference(p)) {
08519 char cid_num[256];
08520 char cid_name[256];
08521
08522 cid_num[0] = 0;
08523 cid_name[0] = 0;
08524 if (p->dahditrcallerid && p->owner) {
08525 if (p->owner->caller.id.number.valid
08526 && p->owner->caller.id.number.str) {
08527 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08528 sizeof(cid_num));
08529 }
08530 if (p->owner->caller.id.name.valid
08531 && p->owner->caller.id.name.str) {
08532 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08533 sizeof(cid_name));
08534 }
08535 }
08536
08537
08538 if (!((ast->pbx) ||
08539 (ast->_state == AST_STATE_UP) ||
08540 (ast->_state == AST_STATE_RING))) {
08541 ast_debug(1, "Flash when call not up or ringing\n");
08542 goto winkflashdone;
08543 }
08544 if (alloc_sub(p, SUB_THREEWAY)) {
08545 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08546 goto winkflashdone;
08547 }
08548
08549
08550
08551
08552
08553
08554
08555 ast_mutex_unlock(&p->lock);
08556 ast_channel_unlock(ast);
08557 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08558 ast_channel_lock(ast);
08559 ast_mutex_lock(&p->lock);
08560 if (p->dahditrcallerid) {
08561 if (!p->origcid_num)
08562 p->origcid_num = ast_strdup(p->cid_num);
08563 if (!p->origcid_name)
08564 p->origcid_name = ast_strdup(p->cid_name);
08565 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08566 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08567 }
08568
08569 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08570
08571 dahdi_disable_ec(p);
08572 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08573 if (res)
08574 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08575 p->owner = chan;
08576 if (!chan) {
08577 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08578 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08579 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08580 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08581 dahdi_enable_ec(p);
08582 ast_hangup(chan);
08583 } else {
08584 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08585
08586
08587 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08588 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08589 S_OR(p->mohsuggest, NULL),
08590 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08591 }
08592 p->subs[SUB_THREEWAY].needhold = 1;
08593 }
08594 }
08595 } else {
08596
08597 if (p->subs[SUB_THREEWAY].inthreeway) {
08598
08599 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08600
08601 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08602
08603 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08604 p->owner = p->subs[SUB_REAL].owner;
08605 }
08606
08607 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08608 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08609 p->subs[SUB_REAL].inthreeway = 0;
08610 p->subs[SUB_THREEWAY].inthreeway = 0;
08611 } else {
08612
08613 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08614 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08615 int otherindex = SUB_THREEWAY;
08616
08617 ast_verb(3, "Building conference call with %s and %s\n",
08618 p->subs[SUB_THREEWAY].owner->name,
08619 p->subs[SUB_REAL].owner->name);
08620
08621 p->subs[SUB_THREEWAY].inthreeway = 1;
08622 p->subs[SUB_REAL].inthreeway = 1;
08623 if (ast->_state == AST_STATE_UP) {
08624 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08625 otherindex = SUB_REAL;
08626 }
08627 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08628 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08629 p->subs[otherindex].needunhold = 1;
08630 p->owner = p->subs[SUB_REAL].owner;
08631 } else {
08632 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08633 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08634 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08635 p->owner = p->subs[SUB_REAL].owner;
08636 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08637 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08638 p->subs[SUB_REAL].needunhold = 1;
08639 dahdi_enable_ec(p);
08640 }
08641 }
08642 }
08643 winkflashdone:
08644 update_conf(p);
08645 break;
08646 case SIG_EM:
08647 case SIG_EM_E1:
08648 case SIG_FEATD:
08649 case SIG_SF:
08650 case SIG_SFWINK:
08651 case SIG_SF_FEATD:
08652 case SIG_FXSLS:
08653 case SIG_FXSGS:
08654 if (p->dialing)
08655 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08656 else
08657 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08658 break;
08659 case SIG_FEATDMF_TA:
08660 switch (p->whichwink) {
08661 case 0:
08662 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08663 S_COR(p->owner->caller.ani.number.valid,
08664 p->owner->caller.ani.number.str, ""));
08665 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08666 p->owner->caller.ani2,
08667 S_COR(p->owner->caller.ani.number.valid,
08668 p->owner->caller.ani.number.str, ""));
08669 break;
08670 case 1:
08671 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08672 break;
08673 case 2:
08674 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08675 return NULL;
08676 }
08677 p->whichwink++;
08678
08679 case SIG_FEATDMF:
08680 case SIG_E911:
08681 case SIG_FGC_CAMAMF:
08682 case SIG_FGC_CAMA:
08683 case SIG_FEATB:
08684 case SIG_SF_FEATDMF:
08685 case SIG_SF_FEATB:
08686 case SIG_EMWINK:
08687
08688 if (!ast_strlen_zero(p->dop.dialstr)) {
08689 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08690 if (res < 0) {
08691 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08692 p->dop.dialstr[0] = '\0';
08693 return NULL;
08694 } else
08695 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08696 }
08697 p->dop.dialstr[0] = '\0';
08698 break;
08699 default:
08700 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08701 }
08702 break;
08703 case DAHDI_EVENT_HOOKCOMPLETE:
08704 if (p->inalarm) break;
08705 if ((p->radio || (p->oprmode < 0))) break;
08706 if (p->waitingfordt.tv_sec) break;
08707 switch (mysig) {
08708 case SIG_FXSLS:
08709 case SIG_FXSGS:
08710 case SIG_FXSKS:
08711 case SIG_EM:
08712 case SIG_EM_E1:
08713 case SIG_EMWINK:
08714 case SIG_FEATD:
08715 case SIG_SF:
08716 case SIG_SFWINK:
08717 case SIG_SF_FEATD:
08718 if (!ast_strlen_zero(p->dop.dialstr)) {
08719 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08720 if (res < 0) {
08721 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08722 p->dop.dialstr[0] = '\0';
08723 return NULL;
08724 } else
08725 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08726 }
08727 p->dop.dialstr[0] = '\0';
08728 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08729 break;
08730 case SIG_FEATDMF:
08731 case SIG_FEATDMF_TA:
08732 case SIG_E911:
08733 case SIG_FGC_CAMA:
08734 case SIG_FGC_CAMAMF:
08735 case SIG_FEATB:
08736 case SIG_SF_FEATDMF:
08737 case SIG_SF_FEATB:
08738 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08739 break;
08740 default:
08741 break;
08742 }
08743 break;
08744 case DAHDI_EVENT_POLARITY:
08745
08746
08747
08748
08749
08750
08751 if (p->polarity == POLARITY_IDLE) {
08752 p->polarity = POLARITY_REV;
08753 if (p->answeronpolarityswitch &&
08754 ((ast->_state == AST_STATE_DIALING) ||
08755 (ast->_state == AST_STATE_RINGING))) {
08756 ast_debug(1, "Answering on polarity switch!\n");
08757 ast_setstate(p->owner, AST_STATE_UP);
08758 if (p->hanguponpolarityswitch) {
08759 p->polaritydelaytv = ast_tvnow();
08760 }
08761 } else
08762 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08763 }
08764
08765
08766 if (p->hanguponpolarityswitch &&
08767 (p->polarityonanswerdelay > 0) &&
08768 (p->polarity == POLARITY_REV) &&
08769 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08770
08771 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) );
08772
08773 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08774 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08775 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08776 p->polarity = POLARITY_IDLE;
08777 } else
08778 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);
08779
08780 } else {
08781 p->polarity = POLARITY_IDLE;
08782 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08783 }
08784
08785 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) );
08786 break;
08787 default:
08788 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08789 }
08790 return &p->subs[idx].f;
08791 }
08792
08793 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08794 {
08795 int res;
08796 int idx;
08797 struct ast_frame *f;
08798 int usedindex = -1;
08799 struct dahdi_pvt *p = ast->tech_pvt;
08800
08801 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08802 idx = SUB_REAL;
08803 }
08804
08805 p->subs[idx].f.frametype = AST_FRAME_NULL;
08806 p->subs[idx].f.datalen = 0;
08807 p->subs[idx].f.samples = 0;
08808 p->subs[idx].f.mallocd = 0;
08809 p->subs[idx].f.offset = 0;
08810 p->subs[idx].f.subclass.integer = 0;
08811 p->subs[idx].f.delivery = ast_tv(0,0);
08812 p->subs[idx].f.src = "dahdi_exception";
08813 p->subs[idx].f.data.ptr = NULL;
08814
08815
08816 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08817
08818
08819
08820
08821
08822 if (p->fake_event) {
08823 res = p->fake_event;
08824 p->fake_event = 0;
08825 } else
08826 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08827
08828 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08829 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08830 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08831 p->owner = p->subs[SUB_REAL].owner;
08832 if (p->owner && ast_bridged_channel(p->owner))
08833 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08834 p->subs[SUB_REAL].needunhold = 1;
08835 }
08836 switch (res) {
08837 case DAHDI_EVENT_ONHOOK:
08838 dahdi_disable_ec(p);
08839 if (p->owner) {
08840 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08841 dahdi_ring_phone(p);
08842 p->callwaitingrepeat = 0;
08843 p->cidcwexpire = 0;
08844 p->cid_suppress_expire = 0;
08845 } else
08846 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08847 update_conf(p);
08848 break;
08849 case DAHDI_EVENT_RINGOFFHOOK:
08850 dahdi_enable_ec(p);
08851 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08852 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08853 p->subs[SUB_REAL].needanswer = 1;
08854 p->dialing = 0;
08855 }
08856 break;
08857 case DAHDI_EVENT_HOOKCOMPLETE:
08858 case DAHDI_EVENT_RINGERON:
08859 case DAHDI_EVENT_RINGEROFF:
08860
08861 break;
08862 case DAHDI_EVENT_WINKFLASH:
08863 p->flashtime = ast_tvnow();
08864 if (p->owner) {
08865 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08866 if (p->owner->_state != AST_STATE_UP) {
08867
08868 usedindex = dahdi_get_index(p->owner, p, 0);
08869 if (usedindex > -1) {
08870 p->subs[usedindex].needanswer = 1;
08871 }
08872 ast_setstate(p->owner, AST_STATE_UP);
08873 }
08874 p->callwaitingrepeat = 0;
08875 p->cidcwexpire = 0;
08876 p->cid_suppress_expire = 0;
08877 if (ast_bridged_channel(p->owner))
08878 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08879 p->subs[SUB_REAL].needunhold = 1;
08880 } else
08881 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08882 update_conf(p);
08883 break;
08884 default:
08885 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08886 }
08887 f = &p->subs[idx].f;
08888 return f;
08889 }
08890 if (!(p->radio || (p->oprmode < 0)))
08891 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08892
08893 if (ast != p->owner) {
08894 if (p->owner) {
08895 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08896 }
08897 f = &p->subs[idx].f;
08898 return f;
08899 }
08900
08901 f = dahdi_handle_event(ast);
08902 if (!f) {
08903 const char *name = ast_strdupa(ast->name);
08904
08905
08906 ast_mutex_unlock(&p->lock);
08907 ast_channel_unlock(ast);
08908 ast_set_hangupsource(ast, name, 0);
08909 ast_channel_lock(ast);
08910 ast_mutex_lock(&p->lock);
08911 }
08912 return f;
08913 }
08914
08915 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08916 {
08917 struct dahdi_pvt *p = ast->tech_pvt;
08918 struct ast_frame *f;
08919 ast_mutex_lock(&p->lock);
08920 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08921 struct analog_pvt *analog_p = p->sig_pvt;
08922 f = analog_exception(analog_p, ast);
08923 } else {
08924 f = __dahdi_exception(ast);
08925 }
08926 ast_mutex_unlock(&p->lock);
08927 return f;
08928 }
08929
08930 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08931 {
08932 struct dahdi_pvt *p;
08933 int res;
08934 int idx;
08935 void *readbuf;
08936 struct ast_frame *f;
08937
08938
08939
08940
08941
08942
08943 p = ast->tech_pvt;
08944 while (ast_mutex_trylock(&p->lock)) {
08945 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08946
08947
08948
08949
08950
08951
08952
08953
08954
08955
08956
08957
08958 if (ast->tech_pvt != p) {
08959
08960 return &ast_null_frame;
08961 }
08962 }
08963
08964 idx = dahdi_get_index(ast, p, 0);
08965
08966
08967 if (idx < 0) {
08968 ast_log(LOG_WARNING, "We don't exist?\n");
08969 ast_mutex_unlock(&p->lock);
08970 return NULL;
08971 }
08972
08973 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08974 ast_mutex_unlock(&p->lock);
08975 return NULL;
08976 }
08977
08978 p->subs[idx].f.frametype = AST_FRAME_NULL;
08979 p->subs[idx].f.datalen = 0;
08980 p->subs[idx].f.samples = 0;
08981 p->subs[idx].f.mallocd = 0;
08982 p->subs[idx].f.offset = 0;
08983 p->subs[idx].f.subclass.integer = 0;
08984 p->subs[idx].f.delivery = ast_tv(0,0);
08985 p->subs[idx].f.src = "dahdi_read";
08986 p->subs[idx].f.data.ptr = NULL;
08987
08988
08989 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08990 {
08991 struct dahdi_params ps;
08992
08993 memset(&ps, 0, sizeof(ps));
08994 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08995 ast_mutex_unlock(&p->lock);
08996 return NULL;
08997 }
08998 p->firstradio = 1;
08999 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09000 if (ps.rxisoffhook)
09001 {
09002 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09003 }
09004 else
09005 {
09006 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09007 }
09008 ast_mutex_unlock(&p->lock);
09009 return &p->subs[idx].f;
09010 }
09011 if (p->ringt > 0) {
09012 if (!(--p->ringt)) {
09013 ast_mutex_unlock(&p->lock);
09014 return NULL;
09015 }
09016 }
09017
09018 #ifdef HAVE_OPENR2
09019 if (p->mfcr2) {
09020 openr2_chan_process_event(p->r2chan);
09021 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09022 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09023
09024
09025 if (p->mfcr2_call_accepted &&
09026 !p->mfcr2_progress &&
09027 ast->_state == AST_STATE_RINGING) {
09028 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09029 ast_queue_frame(p->owner, &f);
09030 p->mfcr2_progress = 1;
09031 }
09032 }
09033 }
09034 #endif
09035
09036 if (p->subs[idx].needringing) {
09037
09038 p->subs[idx].needringing = 0;
09039 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09040 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09041 ast_setstate(ast, AST_STATE_RINGING);
09042 ast_mutex_unlock(&p->lock);
09043 return &p->subs[idx].f;
09044 }
09045
09046 if (p->subs[idx].needbusy) {
09047
09048 p->subs[idx].needbusy = 0;
09049 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09050 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09051 ast_mutex_unlock(&p->lock);
09052 return &p->subs[idx].f;
09053 }
09054
09055 if (p->subs[idx].needcongestion) {
09056
09057 p->subs[idx].needcongestion = 0;
09058 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09059 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09060 ast_mutex_unlock(&p->lock);
09061 return &p->subs[idx].f;
09062 }
09063
09064 if (p->subs[idx].needanswer) {
09065
09066 p->subs[idx].needanswer = 0;
09067 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09068 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09069 ast_mutex_unlock(&p->lock);
09070 return &p->subs[idx].f;
09071 }
09072 #ifdef HAVE_OPENR2
09073 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09074
09075
09076
09077
09078 ast_mutex_unlock(&p->lock);
09079 return &ast_null_frame;
09080 }
09081 #endif
09082
09083 if (p->subs[idx].needflash) {
09084
09085 p->subs[idx].needflash = 0;
09086 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09087 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09088 ast_mutex_unlock(&p->lock);
09089 return &p->subs[idx].f;
09090 }
09091
09092 if (p->subs[idx].needhold) {
09093
09094 p->subs[idx].needhold = 0;
09095 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09096 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09097 ast_mutex_unlock(&p->lock);
09098 ast_debug(1, "Sending hold on '%s'\n", ast->name);
09099 return &p->subs[idx].f;
09100 }
09101
09102 if (p->subs[idx].needunhold) {
09103
09104 p->subs[idx].needunhold = 0;
09105 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09106 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09107 ast_mutex_unlock(&p->lock);
09108 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09109 return &p->subs[idx].f;
09110 }
09111
09112
09113
09114
09115
09116 if (p->fake_event && p->owner == ast) {
09117 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09118 struct analog_pvt *analog_p = p->sig_pvt;
09119
09120 f = analog_exception(analog_p, ast);
09121 } else {
09122 f = __dahdi_exception(ast);
09123 }
09124 ast_mutex_unlock(&p->lock);
09125 return f;
09126 }
09127
09128 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09129 if (!p->subs[idx].linear) {
09130 p->subs[idx].linear = 1;
09131 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09132 if (res)
09133 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09134 }
09135 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09136 (ast->rawreadformat == AST_FORMAT_ALAW)) {
09137 if (p->subs[idx].linear) {
09138 p->subs[idx].linear = 0;
09139 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09140 if (res)
09141 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09142 }
09143 } else {
09144 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09145 ast_mutex_unlock(&p->lock);
09146 return NULL;
09147 }
09148 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09149 CHECK_BLOCKING(ast);
09150 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09151 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09152
09153 if (res < 0) {
09154 f = NULL;
09155 if (res == -1) {
09156 if (errno == EAGAIN) {
09157
09158 ast_mutex_unlock(&p->lock);
09159 return &p->subs[idx].f;
09160 } else if (errno == ELAST) {
09161 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09162 struct analog_pvt *analog_p = p->sig_pvt;
09163 f = analog_exception(analog_p, ast);
09164 } else {
09165 f = __dahdi_exception(ast);
09166 }
09167 } else
09168 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09169 }
09170 ast_mutex_unlock(&p->lock);
09171 return f;
09172 }
09173 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09174 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09175 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09176 struct analog_pvt *analog_p = p->sig_pvt;
09177 f = analog_exception(analog_p, ast);
09178 } else {
09179 f = __dahdi_exception(ast);
09180 }
09181 ast_mutex_unlock(&p->lock);
09182 return f;
09183 }
09184 if (p->tdd) {
09185 int c;
09186
09187 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09188 if (c < 0) {
09189 ast_debug(1,"tdd_feed failed\n");
09190 ast_mutex_unlock(&p->lock);
09191 return NULL;
09192 }
09193 if (c) {
09194 p->subs[idx].f.subclass.integer = 0;
09195 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09196 p->subs[idx].f.mallocd = 0;
09197 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09198 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09199 p->subs[idx].f.datalen = 1;
09200 *((char *) p->subs[idx].f.data.ptr) = c;
09201 ast_mutex_unlock(&p->lock);
09202 return &p->subs[idx].f;
09203 }
09204 }
09205 if (idx == SUB_REAL) {
09206
09207 if (p->cidcwexpire) {
09208 if (!--p->cidcwexpire) {
09209
09210 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09211 restore_conference(p);
09212 }
09213 }
09214 if (p->cid_suppress_expire) {
09215 --p->cid_suppress_expire;
09216 }
09217 if (p->callwaitingrepeat) {
09218 if (!--p->callwaitingrepeat) {
09219
09220 ++p->callwaitrings;
09221 dahdi_callwait(ast);
09222 }
09223 }
09224 }
09225 if (p->subs[idx].linear) {
09226 p->subs[idx].f.datalen = READ_SIZE * 2;
09227 } else
09228 p->subs[idx].f.datalen = READ_SIZE;
09229
09230
09231 if ((p->owner == ast) && p->cidspill) {
09232 send_callerid(p);
09233 }
09234
09235 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09236 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09237 p->subs[idx].f.samples = READ_SIZE;
09238 p->subs[idx].f.mallocd = 0;
09239 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09240 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09241 #if 0
09242 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09243 #endif
09244 if (p->dialing || p->radio ||
09245 (idx && (ast->_state != AST_STATE_UP)) ||
09246 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09247 ) {
09248
09249
09250 p->subs[idx].f.frametype = AST_FRAME_NULL;
09251 p->subs[idx].f.subclass.integer = 0;
09252 p->subs[idx].f.samples = 0;
09253 p->subs[idx].f.mallocd = 0;
09254 p->subs[idx].f.offset = 0;
09255 p->subs[idx].f.data.ptr = NULL;
09256 p->subs[idx].f.datalen= 0;
09257 }
09258 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09259
09260 int mute;
09261
09262 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09263
09264
09265 mute = ast_dsp_was_muted(p->dsp);
09266 if (p->muting != mute) {
09267 p->muting = mute;
09268 dahdi_confmute(p, mute);
09269 }
09270
09271 if (f) {
09272 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09273 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09274
09275
09276 ast_frfree(f);
09277 f = NULL;
09278 }
09279 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09280 || f->frametype == AST_FRAME_DTMF_END) {
09281 #ifdef HAVE_PRI
09282 if (dahdi_sig_pri_lib_handles(p->sig)
09283 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09284 && p->pri
09285 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09286 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09287
09288 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09289 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09290 f->subclass.integer, f->subclass.integer, ast->name);
09291
09292 f->frametype = AST_FRAME_NULL;
09293 f->subclass.integer = 0;
09294 }
09295 #endif
09296
09297 p->pulsedial = 0;
09298 } else if (p->waitingfordt.tv_sec) {
09299 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09300 p->waitingfordt.tv_sec = 0;
09301 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09302 ast_frfree(f);
09303 f = NULL;
09304 } else if (f->frametype == AST_FRAME_VOICE) {
09305 f->frametype = AST_FRAME_NULL;
09306 f->subclass.integer = 0;
09307 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) {
09308 p->waitingfordt.tv_sec = 0;
09309 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09310 ast_dsp_set_features(p->dsp, p->dsp_features);
09311 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09312 if (!ast_strlen_zero(p->dop.dialstr)) {
09313 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09314 if (res < 0) {
09315 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09316 p->dop.dialstr[0] = '\0';
09317 ast_mutex_unlock(&p->lock);
09318 ast_frfree(f);
09319 return NULL;
09320 } else {
09321 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09322 p->dialing = 1;
09323 p->dop.dialstr[0] = '\0';
09324 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09325 ast_setstate(ast, AST_STATE_DIALING);
09326 }
09327 }
09328 }
09329 }
09330 }
09331 }
09332 } else
09333 f = &p->subs[idx].f;
09334
09335 if (f) {
09336 switch (f->frametype) {
09337 case AST_FRAME_DTMF_BEGIN:
09338 case AST_FRAME_DTMF_END:
09339 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09340 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09341 } else {
09342 dahdi_handle_dtmf(ast, idx, &f);
09343 }
09344 break;
09345 case AST_FRAME_VOICE:
09346 if (p->cidspill || p->cid_suppress_expire) {
09347
09348 p->subs[idx].f.frametype = AST_FRAME_NULL;
09349 p->subs[idx].f.subclass.integer = 0;
09350 p->subs[idx].f.samples = 0;
09351 p->subs[idx].f.mallocd = 0;
09352 p->subs[idx].f.offset = 0;
09353 p->subs[idx].f.data.ptr = NULL;
09354 p->subs[idx].f.datalen= 0;
09355 }
09356 break;
09357 default:
09358 break;
09359 }
09360 }
09361
09362 ast_mutex_unlock(&p->lock);
09363 return f;
09364 }
09365
09366 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09367 {
09368 int sent=0;
09369 int size;
09370 int res;
09371 int fd;
09372 fd = p->subs[idx].dfd;
09373 while (len) {
09374 size = len;
09375 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09376 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09377 res = write(fd, buf, size);
09378 if (res != size) {
09379 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09380 return sent;
09381 }
09382 len -= size;
09383 buf += size;
09384 }
09385 return sent;
09386 }
09387
09388 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09389 {
09390 struct dahdi_pvt *p = ast->tech_pvt;
09391 int res;
09392 int idx;
09393 idx = dahdi_get_index(ast, p, 0);
09394 if (idx < 0) {
09395 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09396 return -1;
09397 }
09398
09399
09400 if (frame->frametype != AST_FRAME_VOICE) {
09401 if (frame->frametype != AST_FRAME_IMAGE)
09402 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09403 return 0;
09404 }
09405 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09406 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09407 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09408 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09409 return -1;
09410 }
09411 if (p->dialing) {
09412 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09413 return 0;
09414 }
09415 if (!p->owner) {
09416 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09417 return 0;
09418 }
09419 if (p->cidspill) {
09420 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09421 ast->name);
09422 return 0;
09423 }
09424
09425 if (!frame->data.ptr || !frame->datalen)
09426 return 0;
09427
09428 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09429 if (!p->subs[idx].linear) {
09430 p->subs[idx].linear = 1;
09431 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09432 if (res)
09433 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09434 }
09435 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09436 } else {
09437
09438 if (p->subs[idx].linear) {
09439 p->subs[idx].linear = 0;
09440 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09441 if (res)
09442 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09443 }
09444 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09445 }
09446 if (res < 0) {
09447 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09448 return -1;
09449 }
09450 return 0;
09451 }
09452
09453 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09454 {
09455 struct dahdi_pvt *p = chan->tech_pvt;
09456 int res=-1;
09457 int idx;
09458 int func = DAHDI_FLASH;
09459
09460 ast_mutex_lock(&p->lock);
09461 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09462 switch (p->sig) {
09463 #if defined(HAVE_PRI)
09464 case SIG_PRI_LIB_HANDLE_CASES:
09465 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09466 ast_mutex_unlock(&p->lock);
09467 return res;
09468 #endif
09469 #if defined(HAVE_SS7)
09470 case SIG_SS7:
09471 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09472 ast_mutex_unlock(&p->lock);
09473 return res;
09474 #endif
09475 default:
09476 break;
09477 }
09478 #ifdef HAVE_OPENR2
09479 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09480 ast_mutex_unlock(&p->lock);
09481
09482
09483 return 0;
09484 }
09485 #endif
09486 idx = dahdi_get_index(chan, p, 0);
09487 if (idx == SUB_REAL) {
09488 switch (condition) {
09489 case AST_CONTROL_BUSY:
09490 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09491 break;
09492 case AST_CONTROL_RINGING:
09493 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09494
09495 if (chan->_state != AST_STATE_UP) {
09496 if ((chan->_state != AST_STATE_RING) ||
09497 ((p->sig != SIG_FXSKS) &&
09498 (p->sig != SIG_FXSLS) &&
09499 (p->sig != SIG_FXSGS)))
09500 ast_setstate(chan, AST_STATE_RINGING);
09501 }
09502 break;
09503 case AST_CONTROL_INCOMPLETE:
09504 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09505
09506 res = 0;
09507 break;
09508 case AST_CONTROL_PROCEEDING:
09509 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09510
09511 res = 0;
09512 break;
09513 case AST_CONTROL_PROGRESS:
09514 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09515
09516 res = 0;
09517 break;
09518 case AST_CONTROL_CONGESTION:
09519
09520 switch (chan->hangupcause) {
09521 case AST_CAUSE_USER_BUSY:
09522 case AST_CAUSE_NORMAL_CLEARING:
09523 case 0:
09524
09525 chan->hangupcause = AST_CAUSE_CONGESTION;
09526 break;
09527 default:
09528 break;
09529 }
09530 break;
09531 case AST_CONTROL_HOLD:
09532 ast_moh_start(chan, data, p->mohinterpret);
09533 break;
09534 case AST_CONTROL_UNHOLD:
09535 ast_moh_stop(chan);
09536 break;
09537 case AST_CONTROL_RADIO_KEY:
09538 if (p->radio)
09539 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09540 res = 0;
09541 break;
09542 case AST_CONTROL_RADIO_UNKEY:
09543 if (p->radio)
09544 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09545 res = 0;
09546 break;
09547 case AST_CONTROL_FLASH:
09548
09549 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09550
09551 p->dop.dialstr[0] = '\0';
09552 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09553 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09554 chan->name, strerror(errno));
09555 } else
09556 res = 0;
09557 } else
09558 res = 0;
09559 break;
09560 case AST_CONTROL_SRCUPDATE:
09561 res = 0;
09562 break;
09563 case -1:
09564 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09565 break;
09566 }
09567 } else {
09568 res = 0;
09569 }
09570 ast_mutex_unlock(&p->lock);
09571 return res;
09572 }
09573
09574 #if defined(HAVE_PRI)
09575 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09576 #else
09577 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09578 #endif
09579 {
09580 struct ast_str *chan_name;
09581 int x, y;
09582
09583
09584 if (!(chan_name = ast_str_create(32))) {
09585 return NULL;
09586 }
09587 if (i->channel == CHAN_PSEUDO) {
09588 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09589 #if defined(HAVE_PRI)
09590 } else if (i->pri) {
09591 ast_mutex_lock(&i->pri->lock);
09592 y = ++i->pri->new_chan_seq;
09593 if (is_outgoing) {
09594 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09595 address[0] = '\0';
09596 } else if (ast_strlen_zero(i->cid_subaddr)) {
09597
09598 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09599 } else {
09600
09601 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09602 i->cid_subaddr, y);
09603 }
09604 ast_mutex_unlock(&i->pri->lock);
09605 #endif
09606 } else {
09607 y = 1;
09608 do {
09609 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09610 for (x = 0; x < 3; ++x) {
09611 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09612 i->subs[x].owner->name + 6)) {
09613 break;
09614 }
09615 }
09616 ++y;
09617 } while (x < 3);
09618 }
09619 return chan_name;
09620 }
09621
09622 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09623 {
09624 struct ast_channel *tmp;
09625 format_t deflaw;
09626 int x;
09627 int features;
09628 struct ast_str *chan_name;
09629 struct ast_variable *v;
09630 char *dashptr;
09631 char device_name[AST_CHANNEL_NAME];
09632
09633 if (i->subs[idx].owner) {
09634 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09635 return NULL;
09636 }
09637
09638 #if defined(HAVE_PRI)
09639
09640
09641
09642
09643 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09644 #else
09645 chan_name = create_channel_name(i);
09646 #endif
09647 if (!chan_name) {
09648 return NULL;
09649 }
09650
09651 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));
09652 ast_free(chan_name);
09653 if (!tmp)
09654 return NULL;
09655 tmp->tech = &dahdi_tech;
09656 #if defined(HAVE_PRI)
09657 if (i->pri) {
09658 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09659 }
09660 #endif
09661 ast_channel_cc_params_init(tmp, i->cc_params);
09662 if (law) {
09663 i->law = law;
09664 if (law == DAHDI_LAW_ALAW) {
09665 deflaw = AST_FORMAT_ALAW;
09666 } else {
09667 deflaw = AST_FORMAT_ULAW;
09668 }
09669 } else {
09670 switch (i->sig) {
09671 case SIG_PRI_LIB_HANDLE_CASES:
09672
09673 i->law = (i->law_default == DAHDI_LAW_ALAW)
09674 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09675 break;
09676 default:
09677 i->law = i->law_default;
09678 break;
09679 }
09680 if (i->law_default == DAHDI_LAW_ALAW) {
09681 deflaw = AST_FORMAT_ALAW;
09682 } else {
09683 deflaw = AST_FORMAT_ULAW;
09684 }
09685 }
09686 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09687 tmp->nativeformats = deflaw;
09688
09689 tmp->rawreadformat = deflaw;
09690 tmp->readformat = deflaw;
09691 tmp->rawwriteformat = deflaw;
09692 tmp->writeformat = deflaw;
09693 i->subs[idx].linear = 0;
09694 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09695 features = 0;
09696 if (idx == SUB_REAL) {
09697 if (i->busydetect && CANBUSYDETECT(i))
09698 features |= DSP_FEATURE_BUSY_DETECT;
09699 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09700 features |= DSP_FEATURE_CALL_PROGRESS;
09701 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09702 features |= DSP_FEATURE_WAITDIALTONE;
09703 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09704 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09705 features |= DSP_FEATURE_FAX_DETECT;
09706 }
09707 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09708 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09709 i->hardwaredtmf = 0;
09710 features |= DSP_FEATURE_DIGIT_DETECT;
09711 } else if (NEED_MFDETECT(i)) {
09712 i->hardwaredtmf = 1;
09713 features |= DSP_FEATURE_DIGIT_DETECT;
09714 }
09715 }
09716 if (features) {
09717 if (i->dsp) {
09718 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09719 } else {
09720 if (i->channel != CHAN_PSEUDO)
09721 i->dsp = ast_dsp_new();
09722 else
09723 i->dsp = NULL;
09724 if (i->dsp) {
09725 i->dsp_features = features;
09726 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09727
09728 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09729
09730
09731 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09732 features = 0;
09733 }
09734 #endif
09735 ast_dsp_set_features(i->dsp, features);
09736 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09737 if (!ast_strlen_zero(progzone))
09738 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09739 if (i->busydetect && CANBUSYDETECT(i)) {
09740 ast_dsp_set_busy_count(i->dsp, i->busycount);
09741 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09742 }
09743 }
09744 }
09745 }
09746
09747 if (state == AST_STATE_RING)
09748 tmp->rings = 1;
09749 tmp->tech_pvt = i;
09750 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09751
09752 tmp->callgroup = i->callgroup;
09753 tmp->pickupgroup = i->pickupgroup;
09754 }
09755 if (!ast_strlen_zero(i->parkinglot))
09756 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09757 if (!ast_strlen_zero(i->language))
09758 ast_string_field_set(tmp, language, i->language);
09759 if (!i->owner)
09760 i->owner = tmp;
09761 if (!ast_strlen_zero(i->accountcode))
09762 ast_string_field_set(tmp, accountcode, i->accountcode);
09763 if (i->amaflags)
09764 tmp->amaflags = i->amaflags;
09765 i->subs[idx].owner = tmp;
09766 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09767 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09768 ast_string_field_set(tmp, call_forward, i->call_forward);
09769 }
09770
09771 if (!i->adsi)
09772 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09773 if (!ast_strlen_zero(i->exten))
09774 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09775 if (!ast_strlen_zero(i->rdnis)) {
09776 tmp->redirecting.from.number.valid = 1;
09777 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09778 }
09779 if (!ast_strlen_zero(i->dnid)) {
09780 tmp->dialed.number.str = ast_strdup(i->dnid);
09781 }
09782
09783
09784
09785 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09786 if (!ast_strlen_zero(i->cid_ani)) {
09787 tmp->caller.ani.number.valid = 1;
09788 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09789 } else if (!ast_strlen_zero(i->cid_num)) {
09790 tmp->caller.ani.number.valid = 1;
09791 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09792 }
09793 #else
09794 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 #endif
09799 tmp->caller.id.name.presentation = i->callingpres;
09800 tmp->caller.id.number.presentation = i->callingpres;
09801 tmp->caller.id.number.plan = i->cid_ton;
09802 tmp->caller.ani2 = i->cid_ani2;
09803 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09804
09805 i->fake_event = 0;
09806
09807 dahdi_confmute(i, 0);
09808 i->muting = 0;
09809
09810 ast_jb_configure(tmp, &global_jbconf);
09811
09812
09813 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09814 dashptr = strrchr(device_name, '-');
09815 if (dashptr) {
09816 *dashptr = '\0';
09817 }
09818 tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09819 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09820
09821 for (v = i->vars ; v ; v = v->next)
09822 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09823
09824 ast_module_ref(ast_module_info->self);
09825
09826 dahdi_ami_channel_event(i, tmp);
09827 if (startpbx) {
09828 #ifdef HAVE_OPENR2
09829 if (i->mfcr2call) {
09830 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09831 }
09832 #endif
09833 if (ast_pbx_start(tmp)) {
09834 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09835 ast_hangup(tmp);
09836 return NULL;
09837 }
09838 }
09839 return tmp;
09840 }
09841
09842
09843 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09844 {
09845 char c;
09846
09847 *str = 0;
09848 for (;;)
09849 {
09850
09851 c = ast_waitfordigit(chan, ms);
09852
09853 if (c < 1)
09854 return c;
09855 *str++ = c;
09856 *str = 0;
09857 if (strchr(term, c))
09858 return 1;
09859 }
09860 }
09861
09862 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09863 {
09864 int j;
09865 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09866 for (;;)
09867 {
09868
09869 j = DAHDI_IOMUX_SIGEVENT;
09870
09871 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09872
09873 if (j & DAHDI_IOMUX_SIGEVENT) break;
09874 }
09875
09876 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09877 return 0;
09878 }
09879
09880
09881
09882
09883
09884
09885
09886
09887
09888
09889 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09890 {
09891 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09892 return analog_dnd(dahdichan->sig_pvt, flag);
09893 }
09894
09895 if (flag == -1) {
09896 return dahdichan->dnd;
09897 }
09898
09899
09900 dahdichan->dnd = flag;
09901 ast_verb(3, "%s DND on channel %d\n",
09902 flag? "Enabled" : "Disabled",
09903 dahdichan->channel);
09904 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09905 "Channel: DAHDI/%d\r\n"
09906 "Status: %s\r\n", dahdichan->channel,
09907 flag? "enabled" : "disabled");
09908
09909 return 0;
09910 }
09911
09912 static int canmatch_featurecode(const char *exten)
09913 {
09914 int extlen = strlen(exten);
09915 const char *pickup_ext;
09916 if (!extlen) {
09917 return 1;
09918 }
09919 pickup_ext = ast_pickup_ext();
09920 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09921 return 1;
09922 }
09923
09924 if (exten[0] == '*' && extlen < 3) {
09925 if (extlen == 1) {
09926 return 1;
09927 }
09928
09929 switch (exten[1]) {
09930 case '6':
09931 case '7':
09932 case '8':
09933 return 1;
09934 }
09935 }
09936 return 0;
09937 }
09938
09939 static void *analog_ss_thread(void *data)
09940 {
09941 struct ast_channel *chan = data;
09942 struct dahdi_pvt *p = chan->tech_pvt;
09943 char exten[AST_MAX_EXTENSION] = "";
09944 char exten2[AST_MAX_EXTENSION] = "";
09945 unsigned char buf[256];
09946 char dtmfcid[300];
09947 char dtmfbuf[300];
09948 struct callerid_state *cs = NULL;
09949 char *name = NULL, *number = NULL;
09950 int distMatches;
09951 int curRingData[3];
09952 int receivedRingT;
09953 int counter1;
09954 int counter;
09955 int samples = 0;
09956 struct ast_smdi_md_message *smdi_msg = NULL;
09957 int flags = 0;
09958 int i;
09959 int timeout;
09960 int getforward = 0;
09961 char *s1, *s2;
09962 int len = 0;
09963 int res;
09964 int idx;
09965
09966 ast_mutex_lock(&ss_thread_lock);
09967 ss_thread_count++;
09968 ast_mutex_unlock(&ss_thread_lock);
09969
09970
09971
09972 if (!p) {
09973 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09974 ast_hangup(chan);
09975 goto quit;
09976 }
09977 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09978 idx = dahdi_get_index(chan, p, 1);
09979 if (idx < 0) {
09980 ast_log(LOG_WARNING, "Huh?\n");
09981 ast_hangup(chan);
09982 goto quit;
09983 }
09984 if (p->dsp)
09985 ast_dsp_digitreset(p->dsp);
09986 switch (p->sig) {
09987 case SIG_FEATD:
09988 case SIG_FEATDMF:
09989 case SIG_FEATDMF_TA:
09990 case SIG_E911:
09991 case SIG_FGC_CAMAMF:
09992 case SIG_FEATB:
09993 case SIG_EMWINK:
09994 case SIG_SF_FEATD:
09995 case SIG_SF_FEATDMF:
09996 case SIG_SF_FEATB:
09997 case SIG_SFWINK:
09998 if (dahdi_wink(p, idx))
09999 goto quit;
10000
10001 case SIG_EM:
10002 case SIG_EM_E1:
10003 case SIG_SF:
10004 case SIG_FGC_CAMA:
10005 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10006 if (p->dsp)
10007 ast_dsp_digitreset(p->dsp);
10008
10009 if (p->dsp) {
10010 if (NEED_MFDETECT(p))
10011 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10012 else
10013 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10014 }
10015 memset(dtmfbuf, 0, sizeof(dtmfbuf));
10016
10017 if (!p->immediate)
10018
10019 res = ast_waitfordigit(chan, 5000);
10020 else
10021 res = 0;
10022 if (res > 0) {
10023
10024 dtmfbuf[0] = res;
10025 switch (p->sig) {
10026 case SIG_FEATD:
10027 case SIG_SF_FEATD:
10028 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10029 if (res > 0)
10030 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10031 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10032 break;
10033 case SIG_FEATDMF_TA:
10034 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10035 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10036 if (dahdi_wink(p, idx)) goto quit;
10037 dtmfbuf[0] = 0;
10038
10039 res = ast_waitfordigit(chan, 5000);
10040 if (res <= 0) break;
10041 dtmfbuf[0] = res;
10042
10043 case SIG_FEATDMF:
10044 case SIG_E911:
10045 case SIG_FGC_CAMAMF:
10046 case SIG_SF_FEATDMF:
10047 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10048
10049 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10050 {
10051 if (dahdi_wink(p, idx)) goto quit;
10052 dtmfbuf[0] = 0;
10053
10054 res = ast_waitfordigit(chan, 5000);
10055 if (res <= 0) break;
10056 dtmfbuf[0] = res;
10057 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10058 }
10059 if (res > 0) {
10060
10061 if (p->sig == SIG_E911)
10062 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10063 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10064 }
10065 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10066 break;
10067 case SIG_FEATB:
10068 case SIG_SF_FEATB:
10069 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10070 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10071 break;
10072 case SIG_EMWINK:
10073
10074
10075
10076
10077 if (res == '*') {
10078 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10079 if (res > 0)
10080 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10081 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10082 break;
10083 }
10084 default:
10085
10086 len = 1;
10087 dtmfbuf[len] = '\0';
10088 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10089 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10090 timeout = matchdigittimeout;
10091 } else {
10092 timeout = gendigittimeout;
10093 }
10094 res = ast_waitfordigit(chan, timeout);
10095 if (res < 0) {
10096 ast_debug(1, "waitfordigit returned < 0...\n");
10097 ast_hangup(chan);
10098 goto quit;
10099 } else if (res) {
10100 dtmfbuf[len++] = res;
10101 dtmfbuf[len] = '\0';
10102 } else {
10103 break;
10104 }
10105 }
10106 break;
10107 }
10108 }
10109 if (res == -1) {
10110 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10111 ast_hangup(chan);
10112 goto quit;
10113 } else if (res < 0) {
10114 ast_debug(1, "Got hung up before digits finished\n");
10115 ast_hangup(chan);
10116 goto quit;
10117 }
10118
10119 if (p->sig == SIG_FGC_CAMA) {
10120 char anibuf[100];
10121
10122 if (ast_safe_sleep(chan,1000) == -1) {
10123 ast_hangup(chan);
10124 goto quit;
10125 }
10126 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10127 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10128 res = my_getsigstr(chan, anibuf, "#", 10000);
10129 if ((res > 0) && (strlen(anibuf) > 2)) {
10130 if (anibuf[strlen(anibuf) - 1] == '#')
10131 anibuf[strlen(anibuf) - 1] = 0;
10132 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10133 }
10134 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10135 }
10136
10137 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10138 if (ast_strlen_zero(exten))
10139 ast_copy_string(exten, "s", sizeof(exten));
10140 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10141
10142 if (exten[0] == '*') {
10143 char *stringp=NULL;
10144 ast_copy_string(exten2, exten, sizeof(exten2));
10145
10146 stringp=exten2 +1;
10147 s1 = strsep(&stringp, "*");
10148 s2 = strsep(&stringp, "*");
10149 if (s2) {
10150 if (!ast_strlen_zero(p->cid_num))
10151 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10152 else
10153 ast_set_callerid(chan, s1, NULL, s1);
10154 ast_copy_string(exten, s2, sizeof(exten));
10155 } else
10156 ast_copy_string(exten, s1, sizeof(exten));
10157 } else if (p->sig == SIG_FEATD)
10158 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10159 }
10160 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10161 if (exten[0] == '*') {
10162 char *stringp=NULL;
10163 ast_copy_string(exten2, exten, sizeof(exten2));
10164
10165 stringp=exten2 +1;
10166 s1 = strsep(&stringp, "#");
10167 s2 = strsep(&stringp, "#");
10168 if (s2) {
10169 if (!ast_strlen_zero(p->cid_num))
10170 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10171 else
10172 if (*(s1 + 2))
10173 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10174 ast_copy_string(exten, s2 + 1, sizeof(exten));
10175 } else
10176 ast_copy_string(exten, s1 + 2, sizeof(exten));
10177 } else
10178 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10179 }
10180 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10181 if (exten[0] == '*') {
10182 char *stringp=NULL;
10183 ast_copy_string(exten2, exten, sizeof(exten2));
10184
10185 stringp=exten2 +1;
10186 s1 = strsep(&stringp, "#");
10187 s2 = strsep(&stringp, "#");
10188 if (s2 && (*(s2 + 1) == '0')) {
10189 if (*(s2 + 2))
10190 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10191 }
10192 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10193 else ast_copy_string(exten, "911", sizeof(exten));
10194 } else
10195 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10196 }
10197 if (p->sig == SIG_FEATB) {
10198 if (exten[0] == '*') {
10199 char *stringp=NULL;
10200 ast_copy_string(exten2, exten, sizeof(exten2));
10201
10202 stringp=exten2 +1;
10203 s1 = strsep(&stringp, "#");
10204 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10205 } else
10206 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10207 }
10208 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10209 dahdi_wink(p, idx);
10210
10211
10212
10213 if (ast_safe_sleep(chan, 100)) {
10214 ast_hangup(chan);
10215 goto quit;
10216 }
10217 }
10218 dahdi_enable_ec(p);
10219 if (NEED_MFDETECT(p)) {
10220 if (p->dsp) {
10221 if (!p->hardwaredtmf)
10222 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10223 else {
10224 ast_dsp_free(p->dsp);
10225 p->dsp = NULL;
10226 }
10227 }
10228 }
10229
10230 if (ast_exists_extension(chan, chan->context, exten, 1,
10231 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10232 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10233 if (p->dsp) ast_dsp_digitreset(p->dsp);
10234 res = ast_pbx_run(chan);
10235 if (res) {
10236 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10237 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10238 }
10239 goto quit;
10240 } else {
10241 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10242 sleep(2);
10243 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10244 if (res < 0)
10245 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10246 else
10247 sleep(1);
10248 res = ast_streamfile(chan, "ss-noservice", chan->language);
10249 if (res >= 0)
10250 ast_waitstream(chan, "");
10251 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10252 ast_hangup(chan);
10253 goto quit;
10254 }
10255 break;
10256 case SIG_FXOLS:
10257 case SIG_FXOGS:
10258 case SIG_FXOKS:
10259
10260 timeout = firstdigittimeout;
10261
10262
10263 if (p->subs[SUB_THREEWAY].owner)
10264 timeout = 999999;
10265 while (len < AST_MAX_EXTENSION-1) {
10266
10267
10268 if (p->immediate)
10269 res = 's';
10270 else
10271 res = ast_waitfordigit(chan, timeout);
10272 timeout = 0;
10273 if (res < 0) {
10274 ast_debug(1, "waitfordigit returned < 0...\n");
10275 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10276 ast_hangup(chan);
10277 goto quit;
10278 } else if (res) {
10279 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10280 exten[len++]=res;
10281 exten[len] = '\0';
10282 }
10283 if (!ast_ignore_pattern(chan->context, exten))
10284 tone_zone_play_tone(p->subs[idx].dfd, -1);
10285 else
10286 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10287 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10288 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10289 if (getforward) {
10290
10291 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10292 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10293 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10294 if (res)
10295 break;
10296 usleep(500000);
10297 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10298 sleep(1);
10299 memset(exten, 0, sizeof(exten));
10300 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10301 len = 0;
10302 getforward = 0;
10303 } else {
10304 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10305 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10306 if (!ast_strlen_zero(p->cid_num)) {
10307 if (!p->hidecallerid)
10308 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10309 else
10310 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10311 }
10312 if (!ast_strlen_zero(p->cid_name)) {
10313 if (!p->hidecallerid)
10314 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10315 }
10316 ast_setstate(chan, AST_STATE_RING);
10317 dahdi_enable_ec(p);
10318 res = ast_pbx_run(chan);
10319 if (res) {
10320 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10321 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10322 }
10323 goto quit;
10324 }
10325 } else {
10326
10327
10328 timeout = matchdigittimeout;
10329 }
10330 } else if (res == 0) {
10331 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10332 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10333 dahdi_wait_event(p->subs[idx].dfd);
10334 ast_hangup(chan);
10335 goto quit;
10336 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10337 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10338
10339 p->callwaiting = 0;
10340 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10341 if (res) {
10342 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10343 chan->name, strerror(errno));
10344 }
10345 len = 0;
10346 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10347 memset(exten, 0, sizeof(exten));
10348 timeout = firstdigittimeout;
10349
10350 } else if (!strcmp(exten,ast_pickup_ext())) {
10351
10352
10353
10354
10355 if (idx == SUB_REAL) {
10356
10357 if (p->subs[SUB_THREEWAY].owner) {
10358
10359
10360 alloc_sub(p, SUB_CALLWAIT);
10361 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10362 unalloc_sub(p, SUB_THREEWAY);
10363 }
10364 dahdi_enable_ec(p);
10365 if (ast_pickup_call(chan)) {
10366 ast_debug(1, "No call pickup possible...\n");
10367 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10368 dahdi_wait_event(p->subs[idx].dfd);
10369 }
10370 ast_hangup(chan);
10371 goto quit;
10372 } else {
10373 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10374 ast_hangup(chan);
10375 goto quit;
10376 }
10377
10378 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10379 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10380
10381 p->hidecallerid = 1;
10382 ast_party_number_free(&chan->caller.id.number);
10383 ast_party_number_init(&chan->caller.id.number);
10384 ast_party_name_free(&chan->caller.id.name);
10385 ast_party_name_init(&chan->caller.id.name);
10386 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10387 if (res) {
10388 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10389 chan->name, strerror(errno));
10390 }
10391 len = 0;
10392 memset(exten, 0, sizeof(exten));
10393 timeout = firstdigittimeout;
10394 } else if (p->callreturn && !strcmp(exten, "*69")) {
10395 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10396 break;
10397 } else if (!strcmp(exten, "*78")) {
10398 dahdi_dnd(p, 1);
10399
10400 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10401 getforward = 0;
10402 memset(exten, 0, sizeof(exten));
10403 len = 0;
10404 } else if (!strcmp(exten, "*79")) {
10405 dahdi_dnd(p, 0);
10406
10407 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10408 getforward = 0;
10409 memset(exten, 0, sizeof(exten));
10410 len = 0;
10411 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10412 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10413 getforward = 1;
10414 memset(exten, 0, sizeof(exten));
10415 len = 0;
10416 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10417 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10418 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10419 memset(p->call_forward, 0, sizeof(p->call_forward));
10420 getforward = 0;
10421 memset(exten, 0, sizeof(exten));
10422 len = 0;
10423 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10424 p->subs[SUB_THREEWAY].owner &&
10425 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10426
10427
10428 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10429 chan, exten, chan->context, 0, NULL);
10430 ast_verb(3, "Parking call to '%s'\n", chan->name);
10431 break;
10432 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10433 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10434
10435 p->hidecallerid = 0;
10436 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10437 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10438 if (res) {
10439 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10440 chan->name, strerror(errno));
10441 }
10442 len = 0;
10443 memset(exten, 0, sizeof(exten));
10444 timeout = firstdigittimeout;
10445 } else if (!strcmp(exten, "*0")) {
10446 struct ast_channel *nbridge =
10447 p->subs[SUB_THREEWAY].owner;
10448 struct dahdi_pvt *pbridge = NULL;
10449
10450 if (nbridge && ast_bridged_channel(nbridge))
10451 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10452 if (nbridge && pbridge &&
10453 (nbridge->tech == &dahdi_tech) &&
10454 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10455 ISTRUNK(pbridge)) {
10456 int func = DAHDI_FLASH;
10457
10458 p->dop.dialstr[0] = '\0';
10459
10460 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10461 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10462 nbridge->name, strerror(errno));
10463 }
10464 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10465 unalloc_sub(p, SUB_THREEWAY);
10466 p->owner = p->subs[SUB_REAL].owner;
10467 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10468 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10469 ast_hangup(chan);
10470 goto quit;
10471 } else {
10472 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10473 dahdi_wait_event(p->subs[idx].dfd);
10474 tone_zone_play_tone(p->subs[idx].dfd, -1);
10475 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10476 unalloc_sub(p, SUB_THREEWAY);
10477 p->owner = p->subs[SUB_REAL].owner;
10478 ast_hangup(chan);
10479 goto quit;
10480 }
10481 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10482 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10483 && !canmatch_featurecode(exten)) {
10484 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10485 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10486 chan->context);
10487 break;
10488 }
10489 if (!timeout)
10490 timeout = gendigittimeout;
10491 if (len && !ast_ignore_pattern(chan->context, exten))
10492 tone_zone_play_tone(p->subs[idx].dfd, -1);
10493 }
10494 break;
10495 case SIG_FXSLS:
10496 case SIG_FXSGS:
10497 case SIG_FXSKS:
10498
10499 if (p->use_smdi && p->smdi_iface) {
10500 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10501
10502 if (smdi_msg != NULL) {
10503 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10504
10505 if (smdi_msg->type == 'B')
10506 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10507 else if (smdi_msg->type == 'N')
10508 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10509
10510 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10511 } else {
10512 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10513 }
10514 }
10515
10516 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10517 number = smdi_msg->calling_st;
10518
10519
10520
10521
10522 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10523 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10524
10525 if (p->cid_signalling == CID_SIG_DTMF) {
10526 int k = 0;
10527 int off_ms;
10528 struct timeval start = ast_tvnow();
10529 int ms;
10530 cs = NULL;
10531 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10532 dahdi_setlinear(p->subs[idx].dfd, 0);
10533
10534
10535
10536
10537
10538
10539 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10540 off_ms = 4000;
10541 for (;;) {
10542 struct ast_frame *f;
10543
10544 ms = ast_remaining_ms(start, off_ms);
10545 res = ast_waitfor(chan, ms);
10546 if (res <= 0) {
10547
10548
10549
10550
10551
10552 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10553 "Exiting simple switch\n");
10554 ast_hangup(chan);
10555 goto quit;
10556 }
10557 f = ast_read(chan);
10558 if (!f)
10559 break;
10560 if (f->frametype == AST_FRAME_DTMF) {
10561 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10562 dtmfbuf[k++] = f->subclass.integer;
10563 }
10564 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10565 start = ast_tvnow();
10566 }
10567 ast_frfree(f);
10568 if (chan->_state == AST_STATE_RING ||
10569 chan->_state == AST_STATE_RINGING)
10570 break;
10571 }
10572 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10573 dtmfbuf[k] = '\0';
10574 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10575
10576 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10577 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10578 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10579
10580 if (!ast_strlen_zero(dtmfcid))
10581 number = dtmfcid;
10582 else
10583 number = NULL;
10584
10585 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10586 cs = callerid_new(p->cid_signalling);
10587 if (cs) {
10588 int off_ms;
10589 struct timeval start;
10590 int ms;
10591 samples = 0;
10592 #if 1
10593 bump_gains(p);
10594 #endif
10595
10596 dahdi_setlinear(p->subs[idx].dfd, 0);
10597
10598
10599 for (;;) {
10600 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10601 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10602 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10603 callerid_free(cs);
10604 ast_hangup(chan);
10605 goto quit;
10606 }
10607 if (i & DAHDI_IOMUX_SIGEVENT) {
10608 res = dahdi_get_event(p->subs[idx].dfd);
10609 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10610 if (res == DAHDI_EVENT_NOALARM) {
10611 p->inalarm = 0;
10612 }
10613
10614 if (p->cid_signalling == CID_SIG_V23_JP) {
10615 if (res == DAHDI_EVENT_RINGBEGIN) {
10616 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10617 usleep(1);
10618 }
10619 } else {
10620 res = 0;
10621 break;
10622 }
10623 } else if (i & DAHDI_IOMUX_READ) {
10624 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10625 if (res < 0) {
10626 if (errno != ELAST) {
10627 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10628 callerid_free(cs);
10629 ast_hangup(chan);
10630 goto quit;
10631 }
10632 break;
10633 }
10634 samples += res;
10635
10636 if (p->cid_signalling == CID_SIG_V23_JP) {
10637 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10638 } else {
10639 res = callerid_feed(cs, buf, res, AST_LAW(p));
10640 }
10641 if (res < 0) {
10642
10643
10644
10645
10646 ast_log(LOG_WARNING,
10647 "Failed to decode CallerID on channel '%s'\n",
10648 chan->name);
10649 break;
10650 } else if (res)
10651 break;
10652 else if (samples > (8000 * 10))
10653 break;
10654 }
10655 }
10656 if (res == 1) {
10657 callerid_get(cs, &name, &number, &flags);
10658 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10659 }
10660
10661 if (p->cid_signalling == CID_SIG_V23_JP) {
10662 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10663 usleep(1);
10664 }
10665
10666
10667 start = ast_tvnow();
10668 off_ms = 4000;
10669 for (;;) {
10670 struct ast_frame *f;
10671
10672 ms = ast_remaining_ms(start, off_ms);
10673 res = ast_waitfor(chan, ms);
10674 if (res <= 0) {
10675 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10676 "Exiting simple switch\n");
10677 ast_hangup(chan);
10678 goto quit;
10679 }
10680 if (!(f = ast_read(chan))) {
10681 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10682 ast_hangup(chan);
10683 goto quit;
10684 }
10685 ast_frfree(f);
10686 if (chan->_state == AST_STATE_RING ||
10687 chan->_state == AST_STATE_RINGING)
10688 break;
10689 }
10690
10691
10692
10693 if (p->usedistinctiveringdetection) {
10694 len = 0;
10695 distMatches = 0;
10696
10697 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10698 curRingData[receivedRingT] = 0;
10699 receivedRingT = 0;
10700 counter = 0;
10701 counter1 = 0;
10702
10703 if (strcmp(p->context,p->defcontext) != 0) {
10704 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10705 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10706 }
10707
10708 for (;;) {
10709 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10710 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10711 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10712 callerid_free(cs);
10713 ast_hangup(chan);
10714 goto quit;
10715 }
10716 if (i & DAHDI_IOMUX_SIGEVENT) {
10717 res = dahdi_get_event(p->subs[idx].dfd);
10718 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10719 if (res == DAHDI_EVENT_NOALARM) {
10720 p->inalarm = 0;
10721 }
10722 res = 0;
10723
10724
10725 curRingData[receivedRingT] = p->ringt;
10726
10727 if (p->ringt < p->ringt_base/2)
10728 break;
10729
10730
10731 if (++receivedRingT == ARRAY_LEN(curRingData))
10732 break;
10733 } else if (i & DAHDI_IOMUX_READ) {
10734 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10735 if (res < 0) {
10736 if (errno != ELAST) {
10737 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10738 callerid_free(cs);
10739 ast_hangup(chan);
10740 goto quit;
10741 }
10742 break;
10743 }
10744 if (p->ringt > 0) {
10745 if (!(--p->ringt)) {
10746 res = -1;
10747 break;
10748 }
10749 }
10750 }
10751 }
10752
10753 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10754 for (counter = 0; counter < 3; counter++) {
10755
10756
10757 distMatches = 0;
10758 for (counter1 = 0; counter1 < 3; counter1++) {
10759 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10760 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10761 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10762 curRingData[counter1]);
10763 distMatches++;
10764 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10765 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10766 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10767 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10768 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10769 distMatches++;
10770 }
10771 }
10772
10773 if (distMatches == 3) {
10774
10775 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10776 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10777 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10778 break;
10779 }
10780 }
10781 }
10782
10783 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10784 #if 1
10785 restore_gains(p);
10786 #endif
10787 } else
10788 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10789 } else {
10790 ast_log(LOG_WARNING, "Channel %s in prering "
10791 "state, but I have nothing to do. "
10792 "Terminating simple switch, should be "
10793 "restarted by the actual ring.\n",
10794 chan->name);
10795 ast_hangup(chan);
10796 goto quit;
10797 }
10798 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10799 if (p->cid_signalling == CID_SIG_DTMF) {
10800 int k = 0;
10801 int off_ms;
10802 struct timeval start;
10803 int ms;
10804 cs = NULL;
10805 dahdi_setlinear(p->subs[idx].dfd, 0);
10806 off_ms = 2000;
10807 start = ast_tvnow();
10808 for (;;) {
10809 struct ast_frame *f;
10810
10811 ms = ast_remaining_ms(start, off_ms);
10812 res = ast_waitfor(chan, ms);
10813 if (res <= 0) {
10814 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10815 "Exiting simple switch\n");
10816 ast_hangup(chan);
10817 goto quit;
10818 }
10819 f = ast_read(chan);
10820 if (!f) {
10821
10822 ast_hangup(chan);
10823 goto quit;
10824 }
10825 if (f->frametype == AST_FRAME_DTMF) {
10826 dtmfbuf[k++] = f->subclass.integer;
10827 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10828 start = ast_tvnow();
10829 }
10830 ast_frfree(f);
10831
10832 if (p->ringt_base == p->ringt)
10833 break;
10834 }
10835 dtmfbuf[k] = '\0';
10836 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10837
10838 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10839 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10840 dtmfcid, flags);
10841
10842 if (!ast_strlen_zero(dtmfcid))
10843 number = dtmfcid;
10844 else
10845 number = NULL;
10846
10847 } else {
10848
10849 cs = callerid_new(p->cid_signalling);
10850 if (cs) {
10851 #if 1
10852 bump_gains(p);
10853 #endif
10854 samples = 0;
10855 len = 0;
10856 distMatches = 0;
10857
10858 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10859 curRingData[receivedRingT] = 0;
10860 receivedRingT = 0;
10861 counter = 0;
10862 counter1 = 0;
10863
10864 if (strcmp(p->context,p->defcontext) != 0) {
10865 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10866 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10867 }
10868
10869
10870 dahdi_setlinear(p->subs[idx].dfd, 0);
10871 for (;;) {
10872 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10873 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10874 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10875 callerid_free(cs);
10876 ast_hangup(chan);
10877 goto quit;
10878 }
10879 if (i & DAHDI_IOMUX_SIGEVENT) {
10880 res = dahdi_get_event(p->subs[idx].dfd);
10881 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10882 if (res == DAHDI_EVENT_NOALARM) {
10883 p->inalarm = 0;
10884 }
10885
10886 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10887 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10888 p->polarity = POLARITY_IDLE;
10889 callerid_free(cs);
10890 ast_hangup(chan);
10891 goto quit;
10892 }
10893 res = 0;
10894
10895
10896 curRingData[receivedRingT] = p->ringt;
10897
10898 if (p->ringt < p->ringt_base/2)
10899 break;
10900
10901
10902 if (++receivedRingT == ARRAY_LEN(curRingData))
10903 break;
10904 } else if (i & DAHDI_IOMUX_READ) {
10905 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10906 if (res < 0) {
10907 if (errno != ELAST) {
10908 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10909 callerid_free(cs);
10910 ast_hangup(chan);
10911 goto quit;
10912 }
10913 break;
10914 }
10915 if (p->ringt > 0) {
10916 if (!(--p->ringt)) {
10917 res = -1;
10918 break;
10919 }
10920 }
10921 samples += res;
10922 res = callerid_feed(cs, buf, res, AST_LAW(p));
10923 if (res < 0) {
10924
10925
10926
10927
10928 ast_log(LOG_WARNING,
10929 "Failed to decode CallerID on channel '%s'\n",
10930 chan->name);
10931 break;
10932 } else if (res)
10933 break;
10934 else if (samples > (8000 * 10))
10935 break;
10936 }
10937 }
10938 if (res == 1) {
10939 callerid_get(cs, &name, &number, &flags);
10940 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10941 }
10942 if (distinctiveringaftercid == 1) {
10943
10944 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10945 curRingData[receivedRingT] = 0;
10946 }
10947 receivedRingT = 0;
10948 ast_verb(3, "Detecting post-CID distinctive ring\n");
10949 for (;;) {
10950 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10951 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10952 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10953 callerid_free(cs);
10954 ast_hangup(chan);
10955 goto quit;
10956 }
10957 if (i & DAHDI_IOMUX_SIGEVENT) {
10958 res = dahdi_get_event(p->subs[idx].dfd);
10959 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10960 if (res == DAHDI_EVENT_NOALARM) {
10961 p->inalarm = 0;
10962 }
10963 res = 0;
10964
10965
10966 curRingData[receivedRingT] = p->ringt;
10967
10968 if (p->ringt < p->ringt_base/2)
10969 break;
10970
10971
10972 if (++receivedRingT == ARRAY_LEN(curRingData))
10973 break;
10974 } else if (i & DAHDI_IOMUX_READ) {
10975 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10976 if (res < 0) {
10977 if (errno != ELAST) {
10978 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10979 callerid_free(cs);
10980 ast_hangup(chan);
10981 goto quit;
10982 }
10983 break;
10984 }
10985 if (p->ringt > 0) {
10986 if (!(--p->ringt)) {
10987 res = -1;
10988 break;
10989 }
10990 }
10991 }
10992 }
10993 }
10994 if (p->usedistinctiveringdetection) {
10995
10996 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10997
10998 for (counter = 0; counter < 3; counter++) {
10999
11000
11001
11002 ast_verb(3, "Checking %d,%d,%d\n",
11003 p->drings.ringnum[counter].ring[0],
11004 p->drings.ringnum[counter].ring[1],
11005 p->drings.ringnum[counter].ring[2]);
11006 distMatches = 0;
11007 for (counter1 = 0; counter1 < 3; counter1++) {
11008 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11009 if (p->drings.ringnum[counter].ring[counter1] == -1) {
11010 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11011 curRingData[counter1]);
11012 distMatches++;
11013 }
11014 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11015 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11016 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11017 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11018 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11019 distMatches++;
11020 }
11021 }
11022 if (distMatches == 3) {
11023
11024 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11025 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11026 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11027 break;
11028 }
11029 }
11030 }
11031
11032 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11033 #if 1
11034 restore_gains(p);
11035 #endif
11036 if (res < 0) {
11037 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11038 }
11039 } else
11040 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11041 }
11042 } else
11043 cs = NULL;
11044
11045 if (number)
11046 ast_shrink_phone_number(number);
11047 ast_set_callerid(chan, number, name, number);
11048
11049 if (smdi_msg)
11050 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11051
11052 if (cs)
11053 callerid_free(cs);
11054
11055 my_handle_notify_message(chan, p, flags, -1);
11056
11057 ast_setstate(chan, AST_STATE_RING);
11058 chan->rings = 1;
11059 p->ringt = p->ringt_base;
11060 res = ast_pbx_run(chan);
11061 if (res) {
11062 ast_hangup(chan);
11063 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11064 }
11065 goto quit;
11066 default:
11067 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11068 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11069 if (res < 0)
11070 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11071 }
11072 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11073 if (res < 0)
11074 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11075 ast_hangup(chan);
11076 quit:
11077 ast_mutex_lock(&ss_thread_lock);
11078 ss_thread_count--;
11079 ast_cond_signal(&ss_thread_complete);
11080 ast_mutex_unlock(&ss_thread_lock);
11081 return NULL;
11082 }
11083
11084 struct mwi_thread_data {
11085 struct dahdi_pvt *pvt;
11086 unsigned char buf[READ_SIZE];
11087 size_t len;
11088 };
11089
11090 static int calc_energy(const unsigned char *buf, int len, format_t law)
11091 {
11092 int x;
11093 int sum = 0;
11094
11095 if (!len)
11096 return 0;
11097
11098 for (x = 0; x < len; x++)
11099 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11100
11101 return sum / len;
11102 }
11103
11104 static void *mwi_thread(void *data)
11105 {
11106 struct mwi_thread_data *mtd = data;
11107 struct callerid_state *cs;
11108 pthread_t threadid;
11109 int samples = 0;
11110 char *name, *number;
11111 int flags;
11112 int i, res;
11113 unsigned int spill_done = 0;
11114 int spill_result = -1;
11115
11116 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11117 goto quit_no_clean;
11118 }
11119
11120 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11121
11122 bump_gains(mtd->pvt);
11123
11124 for (;;) {
11125 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11126 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11127 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11128 goto quit;
11129 }
11130
11131 if (i & DAHDI_IOMUX_SIGEVENT) {
11132 struct ast_channel *chan;
11133
11134
11135
11136
11137 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11138
11139 switch (res) {
11140 case DAHDI_EVENT_NEONMWI_ACTIVE:
11141 case DAHDI_EVENT_NEONMWI_INACTIVE:
11142 case DAHDI_EVENT_NONE:
11143 case DAHDI_EVENT_BITSCHANGED:
11144 break;
11145 case DAHDI_EVENT_NOALARM:
11146 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11147 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11148
11149 analog_p->inalarm = 0;
11150 }
11151 mtd->pvt->inalarm = 0;
11152 handle_clear_alarms(mtd->pvt);
11153 break;
11154 case DAHDI_EVENT_ALARM:
11155 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11156 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11157
11158 analog_p->inalarm = 1;
11159 }
11160 mtd->pvt->inalarm = 1;
11161 res = get_alarms(mtd->pvt);
11162 handle_alarms(mtd->pvt, res);
11163 break;
11164 default:
11165 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11166 callerid_free(cs);
11167
11168 restore_gains(mtd->pvt);
11169 mtd->pvt->ringt = mtd->pvt->ringt_base;
11170
11171 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11172 int result;
11173
11174 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11175 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11176 } else {
11177 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11178 }
11179 if (result) {
11180 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11181 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11182 if (res < 0)
11183 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11184 ast_hangup(chan);
11185 }
11186 } else {
11187 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11188 }
11189 goto quit_no_clean;
11190 }
11191 } else if (i & DAHDI_IOMUX_READ) {
11192 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11193 if (errno != ELAST) {
11194 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11195 goto quit;
11196 }
11197 break;
11198 }
11199 samples += res;
11200 if (!spill_done) {
11201 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11202
11203
11204
11205
11206 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11207 break;
11208 } else if (spill_result) {
11209 spill_done = 1;
11210 }
11211 } else {
11212
11213
11214
11215 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11216 break;
11217 }
11218 if (samples > (8000 * 4))
11219 break;
11220 }
11221 }
11222
11223 if (spill_result == 1) {
11224 callerid_get(cs, &name, &number, &flags);
11225 if (flags & CID_MSGWAITING) {
11226 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11227 notify_message(mtd->pvt->mailbox, 1);
11228 } else if (flags & CID_NOMSGWAITING) {
11229 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11230 notify_message(mtd->pvt->mailbox, 0);
11231 } else {
11232 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11233 }
11234 }
11235
11236
11237 quit:
11238 callerid_free(cs);
11239
11240 restore_gains(mtd->pvt);
11241
11242 quit_no_clean:
11243 mtd->pvt->mwimonitoractive = 0;
11244 ast_free(mtd);
11245
11246 return NULL;
11247 }
11248
11249
11250
11251
11252
11253
11254
11255
11256 static int mwi_send_init(struct dahdi_pvt * pvt)
11257 {
11258 int x;
11259
11260 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11261
11262 if (pvt->mwisend_rpas) {
11263 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11264 pvt->mwisendactive = 1;
11265 } else if (pvt->mwisend_fsk) {
11266 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11267 pvt->mwisendactive = 1;
11268 } else {
11269 pvt->mwisendactive = 0;
11270 return 0;
11271 }
11272 #else
11273 if (mwisend_rpas) {
11274 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11275 } else {
11276 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11277 }
11278 pvt->mwisendactive = 1;
11279 #endif
11280
11281 if (pvt->cidspill) {
11282 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11283 ast_free(pvt->cidspill);
11284 pvt->cidspill = NULL;
11285 pvt->cidpos = 0;
11286 pvt->cidlen = 0;
11287 }
11288 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11289 if (!pvt->cidspill) {
11290 pvt->mwisendactive = 0;
11291 return -1;
11292 }
11293 x = DAHDI_FLUSH_BOTH;
11294 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11295 x = 3000;
11296 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11297 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11298 if (pvt->mwisend_fsk) {
11299 #endif
11300 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11301 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11302 pvt->cidpos = 0;
11303 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11304 }
11305 #endif
11306 return 0;
11307 }
11308
11309 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11310 {
11311 struct timeval now;
11312 int res;
11313
11314
11315
11316
11317 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11318 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11319 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11320
11321 switch ( pvt->mwisend_data.mwisend_current) {
11322 case MWI_SEND_SA:
11323
11324 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11325 if (res) {
11326 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11327 goto quit;
11328 }
11329 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11330 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11331 break;
11332 case MWI_SEND_SA_WAIT:
11333 break;
11334 case MWI_SEND_PAUSE:
11335 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11336 if (pvt->mwisend_fsk) {
11337 #endif
11338 gettimeofday(&now, NULL);
11339 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11340 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11341 }
11342 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11343 } else {
11344 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11345 }
11346 #endif
11347 break;
11348 case MWI_SEND_SPILL:
11349
11350 if(0 < num_read) {
11351 if (num_read > pvt->cidlen - pvt->cidpos)
11352 num_read = pvt->cidlen - pvt->cidpos;
11353 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11354 if (res > 0) {
11355 pvt->cidpos += res;
11356 if (pvt->cidpos >= pvt->cidlen) {
11357 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11358 }
11359 } else {
11360 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11361 goto quit;
11362 }
11363 }
11364 break;
11365 case MWI_SEND_CLEANUP:
11366
11367 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11368 break;
11369 default:
11370
11371 goto quit;
11372 }
11373 }
11374
11375 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11376 if (pvt->cidspill) {
11377 ast_free(pvt->cidspill);
11378 pvt->cidspill = NULL;
11379 pvt->cidpos = 0;
11380 pvt->cidlen = 0;
11381 }
11382 pvt->mwisendactive = 0;
11383 }
11384 return 0;
11385 quit:
11386 if (pvt->cidspill) {
11387 ast_free(pvt->cidspill);
11388 pvt->cidspill = NULL;
11389 pvt->cidpos = 0;
11390 pvt->cidlen = 0;
11391 }
11392 pvt->mwisendactive = 0;
11393 return -1;
11394 }
11395
11396 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11397 {
11398 int handled = 0;
11399
11400 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11401 switch (event) {
11402 case DAHDI_EVENT_RINGEROFF:
11403 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11404 handled = 1;
11405
11406 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11407 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11408 ast_free(pvt->cidspill);
11409 pvt->cidspill = NULL;
11410 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11411 pvt->mwisendactive = 0;
11412 } else {
11413 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11414 gettimeofday(&pvt->mwisend_data.pause, NULL);
11415 }
11416 }
11417 break;
11418
11419 case DAHDI_EVENT_RINGOFFHOOK:
11420 if (pvt->cidspill) {
11421 ast_free(pvt->cidspill);
11422 pvt->cidspill = NULL;
11423 pvt->cidpos = 0;
11424 pvt->cidlen = 0;
11425 }
11426 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11427 pvt->mwisendactive = 0;
11428 break;
11429 case DAHDI_EVENT_RINGERON:
11430 case DAHDI_EVENT_HOOKCOMPLETE:
11431 break;
11432 default:
11433 break;
11434 }
11435 }
11436 return handled;
11437 }
11438
11439
11440 static int dahdi_destroy_channel_bynum(int channel)
11441 {
11442 struct dahdi_pvt *cur;
11443
11444 ast_mutex_lock(&iflock);
11445 for (cur = iflist; cur; cur = cur->next) {
11446 if (cur->channel == channel) {
11447 int x = DAHDI_FLASH;
11448
11449
11450 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11451
11452 destroy_channel(cur, 1);
11453 ast_mutex_unlock(&iflock);
11454 ast_module_unref(ast_module_info->self);
11455 return RESULT_SUCCESS;
11456 }
11457 }
11458 ast_mutex_unlock(&iflock);
11459 return RESULT_FAILURE;
11460 }
11461
11462 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11463 {
11464 int res;
11465 pthread_t threadid;
11466 struct ast_channel *chan;
11467
11468
11469
11470 switch (event) {
11471 case DAHDI_EVENT_NONE:
11472 case DAHDI_EVENT_BITSCHANGED:
11473 break;
11474 case DAHDI_EVENT_WINKFLASH:
11475 case DAHDI_EVENT_RINGOFFHOOK:
11476 if (i->inalarm) break;
11477 if (i->radio) break;
11478
11479 switch (i->sig) {
11480 case SIG_FXOLS:
11481 case SIG_FXOGS:
11482 case SIG_FXOKS:
11483 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11484 if (res && (errno == EBUSY))
11485 break;
11486
11487
11488 ast_free(i->cidspill);
11489 i->cidspill = NULL;
11490 restore_conference(i);
11491
11492 if (i->immediate) {
11493 dahdi_enable_ec(i);
11494
11495 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11496 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11497 if (!chan) {
11498 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11499 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11500 if (res < 0)
11501 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11502 }
11503 } else {
11504
11505 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11506 if (chan) {
11507 if (has_voicemail(i))
11508 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11509 else
11510 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11511 if (res < 0)
11512 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11513 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11514 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11515 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11516 if (res < 0)
11517 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11518 ast_hangup(chan);
11519 }
11520 } else
11521 ast_log(LOG_WARNING, "Unable to create channel\n");
11522 }
11523 break;
11524 case SIG_FXSLS:
11525 case SIG_FXSGS:
11526 case SIG_FXSKS:
11527 i->ringt = i->ringt_base;
11528
11529 case SIG_EMWINK:
11530 case SIG_FEATD:
11531 case SIG_FEATDMF:
11532 case SIG_FEATDMF_TA:
11533 case SIG_E911:
11534 case SIG_FGC_CAMA:
11535 case SIG_FGC_CAMAMF:
11536 case SIG_FEATB:
11537 case SIG_EM:
11538 case SIG_EM_E1:
11539 case SIG_SFWINK:
11540 case SIG_SF_FEATD:
11541 case SIG_SF_FEATDMF:
11542 case SIG_SF_FEATB:
11543 case SIG_SF:
11544
11545 if (i->cid_start == CID_START_POLARITY_IN) {
11546 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11547 } else {
11548 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11549 }
11550
11551 if (!chan) {
11552 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11553 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11554 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11555 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11556 if (res < 0) {
11557 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11558 }
11559 ast_hangup(chan);
11560 }
11561 break;
11562 default:
11563 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11564 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11565 if (res < 0)
11566 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11567 return NULL;
11568 }
11569 break;
11570 case DAHDI_EVENT_NOALARM:
11571 switch (i->sig) {
11572 #if defined(HAVE_PRI)
11573 case SIG_PRI_LIB_HANDLE_CASES:
11574 ast_mutex_lock(&i->lock);
11575 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11576 ast_mutex_unlock(&i->lock);
11577 break;
11578 #endif
11579 #if defined(HAVE_SS7)
11580 case SIG_SS7:
11581 sig_ss7_set_alarm(i->sig_pvt, 0);
11582 break;
11583 #endif
11584 default:
11585 i->inalarm = 0;
11586 break;
11587 }
11588 handle_clear_alarms(i);
11589 break;
11590 case DAHDI_EVENT_ALARM:
11591 switch (i->sig) {
11592 #if defined(HAVE_PRI)
11593 case SIG_PRI_LIB_HANDLE_CASES:
11594 ast_mutex_lock(&i->lock);
11595 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11596 ast_mutex_unlock(&i->lock);
11597 break;
11598 #endif
11599 #if defined(HAVE_SS7)
11600 case SIG_SS7:
11601 sig_ss7_set_alarm(i->sig_pvt, 1);
11602 break;
11603 #endif
11604 default:
11605 i->inalarm = 1;
11606 break;
11607 }
11608 res = get_alarms(i);
11609 handle_alarms(i, res);
11610
11611 case DAHDI_EVENT_ONHOOK:
11612 if (i->radio)
11613 break;
11614
11615 switch (i->sig) {
11616 case SIG_FXOLS:
11617 case SIG_FXOGS:
11618 case SIG_FEATD:
11619 case SIG_FEATDMF:
11620 case SIG_FEATDMF_TA:
11621 case SIG_E911:
11622 case SIG_FGC_CAMA:
11623 case SIG_FGC_CAMAMF:
11624 case SIG_FEATB:
11625 case SIG_EM:
11626 case SIG_EM_E1:
11627 case SIG_EMWINK:
11628 case SIG_SF_FEATD:
11629 case SIG_SF_FEATDMF:
11630 case SIG_SF_FEATB:
11631 case SIG_SF:
11632 case SIG_SFWINK:
11633 case SIG_FXSLS:
11634 case SIG_FXSGS:
11635 case SIG_FXSKS:
11636 case SIG_FXOKS:
11637 dahdi_disable_ec(i);
11638
11639 #ifdef ZHONE_HACK
11640 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11641 usleep(1);
11642 #endif
11643 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11644 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11645 break;
11646 case SIG_SS7:
11647 case SIG_PRI_LIB_HANDLE_CASES:
11648 dahdi_disable_ec(i);
11649 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11650 break;
11651 default:
11652 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11653 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11654 return NULL;
11655 }
11656 break;
11657 case DAHDI_EVENT_POLARITY:
11658 switch (i->sig) {
11659 case SIG_FXSLS:
11660 case SIG_FXSKS:
11661 case SIG_FXSGS:
11662
11663
11664
11665
11666 if (i->hanguponpolarityswitch)
11667 i->polarity = POLARITY_REV;
11668 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11669 i->polarity = POLARITY_REV;
11670 ast_verb(2, "Starting post polarity "
11671 "CID detection on channel %d\n",
11672 i->channel);
11673 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11674 if (!chan) {
11675 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11676 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11677 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11678 ast_hangup(chan);
11679 }
11680 }
11681 break;
11682 default:
11683 ast_log(LOG_WARNING, "handle_init_event detected "
11684 "polarity reversal on non-FXO (SIG_FXS) "
11685 "interface %d\n", i->channel);
11686 }
11687 break;
11688 case DAHDI_EVENT_REMOVED:
11689 ast_log(LOG_NOTICE,
11690 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11691 i->channel);
11692 return i;
11693 case DAHDI_EVENT_NEONMWI_ACTIVE:
11694 if (i->mwimonitor_neon) {
11695 notify_message(i->mailbox, 1);
11696 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11697 }
11698 break;
11699 case DAHDI_EVENT_NEONMWI_INACTIVE:
11700 if (i->mwimonitor_neon) {
11701 notify_message(i->mailbox, 0);
11702 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11703 }
11704 break;
11705 }
11706 return NULL;
11707 }
11708
11709 static void monitor_pfds_clean(void *arg) {
11710 struct pollfd **pfds = arg;
11711 ast_free(*pfds);
11712 }
11713
11714 static void *do_monitor(void *data)
11715 {
11716 int count, res, res2, spoint, pollres=0;
11717 struct dahdi_pvt *i;
11718 struct dahdi_pvt *last = NULL;
11719 struct dahdi_pvt *doomed;
11720 time_t thispass = 0, lastpass = 0;
11721 int found;
11722 char buf[1024];
11723 struct pollfd *pfds=NULL;
11724 int lastalloc = -1;
11725
11726
11727
11728 #if 0
11729 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11730 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11731 return NULL;
11732 }
11733 ast_debug(1, "Monitor starting...\n");
11734 #endif
11735 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11736
11737 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11738 for (;;) {
11739
11740 ast_mutex_lock(&iflock);
11741 if (!pfds || (lastalloc != ifcount)) {
11742 if (pfds) {
11743 ast_free(pfds);
11744 pfds = NULL;
11745 }
11746 if (ifcount) {
11747 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11748 ast_mutex_unlock(&iflock);
11749 return NULL;
11750 }
11751 }
11752 lastalloc = ifcount;
11753 }
11754
11755
11756 count = 0;
11757 for (i = iflist; i; i = i->next) {
11758 ast_mutex_lock(&i->lock);
11759 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11760 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11761 struct analog_pvt *p = i->sig_pvt;
11762
11763 if (!p) {
11764 ast_log(LOG_ERROR, "No sig_pvt?\n");
11765 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11766
11767 pfds[count].fd = i->subs[SUB_REAL].dfd;
11768 pfds[count].events = POLLPRI;
11769 pfds[count].revents = 0;
11770
11771 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11772 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11773 pfds[count].events |= POLLIN;
11774 }
11775 count++;
11776 }
11777 } else {
11778 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11779
11780 pfds[count].fd = i->subs[SUB_REAL].dfd;
11781 pfds[count].events = POLLPRI;
11782 pfds[count].revents = 0;
11783
11784
11785 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11786 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11787 pfds[count].events |= POLLIN;
11788 }
11789 count++;
11790 }
11791 }
11792 }
11793 ast_mutex_unlock(&i->lock);
11794 }
11795
11796 ast_mutex_unlock(&iflock);
11797
11798 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11799 pthread_testcancel();
11800
11801 res = poll(pfds, count, 1000);
11802 pthread_testcancel();
11803 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11804
11805
11806 if (res < 0) {
11807 if ((errno != EAGAIN) && (errno != EINTR))
11808 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11809 continue;
11810 }
11811
11812
11813 ast_mutex_lock(&iflock);
11814 found = 0;
11815 spoint = 0;
11816 lastpass = thispass;
11817 thispass = time(NULL);
11818 doomed = NULL;
11819 for (i = iflist;; i = i->next) {
11820 if (doomed) {
11821 int res;
11822 res = dahdi_destroy_channel_bynum(doomed->channel);
11823 if (res != RESULT_SUCCESS) {
11824 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11825 }
11826 doomed = NULL;
11827 }
11828 if (!i) {
11829 break;
11830 }
11831
11832 if (thispass != lastpass) {
11833 if (!found && ((i == last) || ((i == iflist) && !last))) {
11834 last = i;
11835 if (last) {
11836 struct analog_pvt *analog_p = last->sig_pvt;
11837
11838 if (analog_p
11839 && !last->mwisendactive
11840 && (last->sig & __DAHDI_SIG_FXO)
11841 && !analog_p->fxsoffhookstate
11842 && !last->owner
11843 && !ast_strlen_zero(last->mailbox)
11844 && (thispass - analog_p->onhooktime > 3)) {
11845 res = has_voicemail(last);
11846 if (analog_p->msgstate != res) {
11847
11848 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11849 if (res2) {
11850
11851 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11852 }
11853
11854 if (mwi_send_init(last)) {
11855 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11856 }
11857 analog_p->msgstate = res;
11858 found ++;
11859 }
11860 }
11861 last = last->next;
11862 }
11863 }
11864 }
11865 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11866 if (i->radio && !i->owner)
11867 {
11868 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11869 if (res)
11870 {
11871 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11872
11873 ast_mutex_unlock(&iflock);
11874 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11875 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11876 else
11877 doomed = handle_init_event(i, res);
11878 ast_mutex_lock(&iflock);
11879 }
11880 continue;
11881 }
11882 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11883 if (pollres & POLLIN) {
11884 if (i->owner || i->subs[SUB_REAL].owner) {
11885 #ifdef HAVE_PRI
11886 if (!i->pri)
11887 #endif
11888 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11889 continue;
11890 }
11891 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11892 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11893 continue;
11894 }
11895 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11896 if (res > 0) {
11897 if (i->mwimonitor_fsk) {
11898 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11899 pthread_attr_t attr;
11900 pthread_t threadid;
11901 struct mwi_thread_data *mtd;
11902
11903 pthread_attr_init(&attr);
11904 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11905
11906 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11907 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11908 mtd->pvt = i;
11909 memcpy(mtd->buf, buf, res);
11910 mtd->len = res;
11911 i->mwimonitoractive = 1;
11912 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11913 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11914 i->mwimonitoractive = 0;
11915 ast_free(mtd);
11916 }
11917 }
11918 }
11919
11920 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11921 int energy;
11922 struct timeval now;
11923
11924
11925
11926 if (1 == i->dtmfcid_holdoff_state) {
11927 gettimeofday(&i->dtmfcid_delay, NULL);
11928 i->dtmfcid_holdoff_state = 2;
11929 } else if (2 == i->dtmfcid_holdoff_state) {
11930 gettimeofday(&now, NULL);
11931 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11932 i->dtmfcid_holdoff_state = 0;
11933 }
11934 } else {
11935 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11936 if (!i->mwisendactive && energy > dtmfcid_level) {
11937 pthread_t threadid;
11938 struct ast_channel *chan;
11939 ast_mutex_unlock(&iflock);
11940 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11941
11942 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11943 i->dtmfcid_holdoff_state = 1;
11944 } else {
11945 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11946 if (!chan) {
11947 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11948 } else {
11949 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11950 if (res) {
11951 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11952 ast_hangup(chan);
11953 } else {
11954 i->dtmfcid_holdoff_state = 1;
11955 }
11956 }
11957 }
11958 ast_mutex_lock(&iflock);
11959 }
11960 }
11961 }
11962 if (i->mwisendactive) {
11963 mwi_send_process_buffer(i, res);
11964 }
11965 } else {
11966 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11967 }
11968 }
11969 if (pollres & POLLPRI) {
11970 if (i->owner || i->subs[SUB_REAL].owner) {
11971 #ifdef HAVE_PRI
11972 if (!i->pri)
11973 #endif
11974 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11975 continue;
11976 }
11977 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11978 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11979
11980 ast_mutex_unlock(&iflock);
11981 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11982 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11983 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11984 else
11985 doomed = handle_init_event(i, res);
11986 }
11987 ast_mutex_lock(&iflock);
11988 }
11989 }
11990 }
11991 ast_mutex_unlock(&iflock);
11992 }
11993
11994 pthread_cleanup_pop(1);
11995 return NULL;
11996
11997 }
11998
11999 static int restart_monitor(void)
12000 {
12001
12002 if (monitor_thread == AST_PTHREADT_STOP)
12003 return 0;
12004 ast_mutex_lock(&monlock);
12005 if (monitor_thread == pthread_self()) {
12006 ast_mutex_unlock(&monlock);
12007 ast_log(LOG_WARNING, "Cannot kill myself\n");
12008 return -1;
12009 }
12010 if (monitor_thread != AST_PTHREADT_NULL) {
12011
12012 pthread_kill(monitor_thread, SIGURG);
12013 } else {
12014
12015 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12016 ast_mutex_unlock(&monlock);
12017 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12018 return -1;
12019 }
12020 }
12021 ast_mutex_unlock(&monlock);
12022 return 0;
12023 }
12024
12025 #if defined(HAVE_PRI)
12026 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12027 {
12028 int x;
12029 int trunkgroup;
12030
12031 trunkgroup = pris[*span].mastertrunkgroup;
12032 if (trunkgroup) {
12033
12034 for (x = 0; x < NUM_SPANS; x++) {
12035 if (pris[x].pri.trunkgroup == trunkgroup) {
12036 *span = x;
12037 return 0;
12038 }
12039 }
12040 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12041 *span = -1;
12042 } else {
12043 if (pris[*span].pri.trunkgroup) {
12044 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);
12045 *span = -1;
12046 } else if (pris[*span].mastertrunkgroup) {
12047 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12048 *span = -1;
12049 } else {
12050 if (si->totalchans == 31) {
12051
12052 pris[*span].dchannels[0] = 16 + offset;
12053 } else if (si->totalchans == 24) {
12054
12055 pris[*span].dchannels[0] = 24 + offset;
12056 } else if (si->totalchans == 3) {
12057
12058 pris[*span].dchannels[0] = 3 + offset;
12059 } else {
12060 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);
12061 *span = -1;
12062 return 0;
12063 }
12064 pris[*span].pri.span = *span + 1;
12065 }
12066 }
12067 return 0;
12068 }
12069 #endif
12070
12071 #if defined(HAVE_PRI)
12072 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12073 {
12074 struct dahdi_spaninfo si;
12075 struct dahdi_params p;
12076 int fd;
12077 int span;
12078 int ospan=0;
12079 int x,y;
12080 for (x = 0; x < NUM_SPANS; x++) {
12081 if (pris[x].pri.trunkgroup == trunkgroup) {
12082 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12083 return -1;
12084 }
12085 }
12086 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12087 if (!channels[y])
12088 break;
12089 memset(&si, 0, sizeof(si));
12090 memset(&p, 0, sizeof(p));
12091 fd = open("/dev/dahdi/channel", O_RDWR);
12092 if (fd < 0) {
12093 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12094 return -1;
12095 }
12096 x = channels[y];
12097 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12098 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12099 close(fd);
12100 return -1;
12101 }
12102 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12103 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12104 return -1;
12105 }
12106 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12107 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12108 close(fd);
12109 return -1;
12110 }
12111 span = p.spanno - 1;
12112 if (pris[span].pri.trunkgroup) {
12113 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12114 close(fd);
12115 return -1;
12116 }
12117 if (pris[span].pri.pvts[0]) {
12118 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12119 close(fd);
12120 return -1;
12121 }
12122 if (!y) {
12123 pris[span].pri.trunkgroup = trunkgroup;
12124 ospan = span;
12125 }
12126 pris[ospan].dchannels[y] = channels[y];
12127 pris[span].pri.span = span + 1;
12128 close(fd);
12129 }
12130 return 0;
12131 }
12132 #endif
12133
12134 #if defined(HAVE_PRI)
12135 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12136 {
12137 if (pris[span].mastertrunkgroup) {
12138 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);
12139 return -1;
12140 }
12141 pris[span].mastertrunkgroup = trunkgroup;
12142 pris[span].prilogicalspan = logicalspan;
12143 return 0;
12144 }
12145 #endif
12146
12147 #if defined(HAVE_SS7)
12148 static unsigned int parse_pointcode(const char *pcstring)
12149 {
12150 unsigned int code1, code2, code3;
12151 int numvals;
12152
12153 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12154 if (numvals == 1)
12155 return code1;
12156 if (numvals == 3)
12157 return (code1 << 16) | (code2 << 8) | code3;
12158
12159 return 0;
12160 }
12161 #endif
12162
12163 #if defined(HAVE_SS7)
12164 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12165 {
12166 if ((linkset < 0) || (linkset >= NUM_SPANS))
12167 return NULL;
12168 else
12169 return &linksets[linkset - 1];
12170 }
12171 #endif
12172
12173 #ifdef HAVE_OPENR2
12174 static void dahdi_r2_destroy_links(void)
12175 {
12176 int i = 0;
12177 if (!r2links) {
12178 return;
12179 }
12180 for (; i < r2links_count; i++) {
12181 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12182 pthread_cancel(r2links[i]->r2master);
12183 pthread_join(r2links[i]->r2master, NULL);
12184 openr2_context_delete(r2links[i]->protocol_context);
12185 }
12186 ast_free(r2links[i]);
12187 }
12188 ast_free(r2links);
12189 r2links = NULL;
12190 r2links_count = 0;
12191 }
12192
12193
12194 #define R2_LINK_CAPACITY 30
12195 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12196 {
12197 struct dahdi_mfcr2 *new_r2link = NULL;
12198 struct dahdi_mfcr2 **new_r2links = NULL;
12199
12200
12201
12202
12203
12204 if (!r2links_count ||
12205 memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12206 (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12207 new_r2link = ast_calloc(1, sizeof(**r2links));
12208 if (!new_r2link) {
12209 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12210 return NULL;
12211 }
12212 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12213 if (!new_r2links) {
12214 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12215 ast_free(new_r2link);
12216 return NULL;
12217 }
12218 r2links = new_r2links;
12219 new_r2link->r2master = AST_PTHREADT_NULL;
12220 r2links[r2links_count] = new_r2link;
12221 r2links_count++;
12222 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12223 }
12224 return r2links[r2links_count - 1];
12225 }
12226
12227 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12228 {
12229 char tmplogdir[] = "/tmp";
12230 char logdir[OR2_MAX_PATH];
12231 int threshold = 0;
12232 int snres = 0;
12233 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12234 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12235 conf->mfcr2.max_dnis);
12236 if (!r2_link->protocol_context) {
12237 return -1;
12238 }
12239 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12240 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12241 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12242 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12243 #endif
12244 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12245 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12246 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12247 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12248 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12249 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12250 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12251 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12252 }
12253 } else {
12254 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12255 if (snres >= sizeof(logdir)) {
12256 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12257 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12258 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12259 }
12260 } else {
12261 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12262 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12263 }
12264 }
12265 }
12266 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12267 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12268 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12269 }
12270 }
12271
12272 memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12273 return 0;
12274 }
12275 #endif
12276
12277
12278
12279
12280
12281
12282 static int sigtype_to_signalling(int sigtype)
12283 {
12284 return sigtype;
12285 }
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12300 {
12301 struct stat stbuf;
12302 int num;
12303
12304 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12305 if (stat(path, &stbuf) < 0) {
12306 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12307 return -errno;
12308 }
12309 if (!S_ISCHR(stbuf.st_mode)) {
12310 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12311 return -EINVAL;
12312 }
12313 num = minor(stbuf.st_rdev);
12314 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12315 return num;
12316
12317 }
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12334 {
12335
12336 struct dahdi_pvt *tmp;
12337 char fn[80];
12338 struct dahdi_bufferinfo bi;
12339
12340 int res;
12341 #if defined(HAVE_PRI)
12342 int span = 0;
12343 #endif
12344 int here = 0;
12345 int x;
12346 struct analog_pvt *analog_p = NULL;
12347 struct dahdi_params p;
12348 #if defined(HAVE_PRI)
12349 struct dahdi_spaninfo si;
12350 struct sig_pri_chan *pri_chan = NULL;
12351 #endif
12352 #if defined(HAVE_SS7)
12353 struct sig_ss7_chan *ss7_chan = NULL;
12354 #endif
12355
12356
12357 for (tmp = iflist; tmp; tmp = tmp->next) {
12358 if (!tmp->destroy) {
12359 if (tmp->channel == channel) {
12360
12361 here = 1;
12362 break;
12363 }
12364 if (tmp->channel > channel) {
12365
12366 tmp = NULL;
12367 break;
12368 }
12369 }
12370 }
12371
12372 if (!here && reloading != 1) {
12373 tmp = ast_calloc(1, sizeof(*tmp));
12374 if (!tmp) {
12375 return NULL;
12376 }
12377 tmp->cc_params = ast_cc_config_params_init();
12378 if (!tmp->cc_params) {
12379 ast_free(tmp);
12380 return NULL;
12381 }
12382 ast_mutex_init(&tmp->lock);
12383 ifcount++;
12384 for (x = 0; x < 3; x++)
12385 tmp->subs[x].dfd = -1;
12386 tmp->channel = channel;
12387 tmp->priindication_oob = conf->chan.priindication_oob;
12388 }
12389
12390 if (tmp) {
12391 int chan_sig = conf->chan.sig;
12392
12393
12394 if (reloading && tmp->vars) {
12395 ast_variables_destroy(tmp->vars);
12396 tmp->vars = NULL;
12397 }
12398
12399
12400 if (!here) {
12401
12402 if ((channel != CHAN_PSEUDO)) {
12403 int count = 0;
12404
12405 snprintf(fn, sizeof(fn), "%d", channel);
12406
12407 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12408 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12409 usleep(1);
12410 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12411 count++;
12412 }
12413
12414 if (tmp->subs[SUB_REAL].dfd < 0) {
12415 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);
12416 destroy_dahdi_pvt(tmp);
12417 return NULL;
12418 }
12419 memset(&p, 0, sizeof(p));
12420 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12421 if (res < 0) {
12422 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12423 destroy_dahdi_pvt(tmp);
12424 return NULL;
12425 }
12426 if (conf->is_sig_auto)
12427 chan_sig = sigtype_to_signalling(p.sigtype);
12428 if (p.sigtype != (chan_sig & 0x3ffff)) {
12429 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));
12430 destroy_dahdi_pvt(tmp);
12431 return NULL;
12432 }
12433 tmp->law_default = p.curlaw;
12434 tmp->law = p.curlaw;
12435 tmp->span = p.spanno;
12436 #if defined(HAVE_PRI)
12437 span = p.spanno - 1;
12438 #endif
12439 } else {
12440 chan_sig = 0;
12441 }
12442 tmp->sig = chan_sig;
12443 tmp->outsigmod = conf->chan.outsigmod;
12444
12445 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12446 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12447 if (!analog_p) {
12448 destroy_dahdi_pvt(tmp);
12449 return NULL;
12450 }
12451 tmp->sig_pvt = analog_p;
12452 }
12453 #if defined(HAVE_SS7)
12454 if (chan_sig == SIG_SS7) {
12455 struct dahdi_ss7 *ss7;
12456 int clear = 0;
12457
12458 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12459 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12460 destroy_dahdi_pvt(tmp);
12461 return NULL;
12462 }
12463
12464 ss7 = ss7_resolve_linkset(cur_linkset);
12465 if (!ss7) {
12466 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12467 destroy_dahdi_pvt(tmp);
12468 return NULL;
12469 }
12470 ss7->ss7.span = cur_linkset;
12471 if (cur_cicbeginswith < 0) {
12472 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12473 destroy_dahdi_pvt(tmp);
12474 return NULL;
12475 }
12476 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12477 if (!ss7_chan) {
12478 destroy_dahdi_pvt(tmp);
12479 return NULL;
12480 }
12481 tmp->sig_pvt = ss7_chan;
12482 tmp->ss7 = &ss7->ss7;
12483
12484 ss7_chan->channel = tmp->channel;
12485 ss7_chan->cic = cur_cicbeginswith++;
12486
12487
12488 ss7_chan->dpc = cur_defaultdpc;
12489
12490 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12491
12492 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12493 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12494 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12495 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12496
12497 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12498 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12499 }
12500 #endif
12501 #ifdef HAVE_OPENR2
12502 if (chan_sig == SIG_MFCR2) {
12503 struct dahdi_mfcr2 *r2_link;
12504 r2_link = dahdi_r2_get_link(conf);
12505 if (!r2_link) {
12506 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12507 destroy_dahdi_pvt(tmp);
12508 return NULL;
12509 }
12510 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12511 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12512 destroy_dahdi_pvt(tmp);
12513 return NULL;
12514 }
12515 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12516 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12517 destroy_dahdi_pvt(tmp);
12518 return NULL;
12519 }
12520 r2_link->pvts[r2_link->numchans++] = tmp;
12521 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12522 tmp->subs[SUB_REAL].dfd,
12523 NULL, NULL);
12524 if (!tmp->r2chan) {
12525 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12526 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12527 destroy_dahdi_pvt(tmp);
12528 return NULL;
12529 }
12530 tmp->mfcr2 = r2_link;
12531 if (conf->mfcr2.call_files) {
12532 openr2_chan_enable_call_files(tmp->r2chan);
12533 }
12534 openr2_chan_set_client_data(tmp->r2chan, tmp);
12535
12536 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12537 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12538 tmp->mfcr2_category = conf->mfcr2.category;
12539 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12540 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12541 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12542 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12543 tmp->mfcr2call = 0;
12544 tmp->mfcr2_dnis_index = 0;
12545 tmp->mfcr2_ani_index = 0;
12546 }
12547 #endif
12548 #ifdef HAVE_PRI
12549 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12550 int offset;
12551 int matchesdchan;
12552 int x,y;
12553 int myswitchtype = 0;
12554
12555 offset = 0;
12556 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12557 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12558 destroy_dahdi_pvt(tmp);
12559 return NULL;
12560 }
12561 if (span >= NUM_SPANS) {
12562 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12563 destroy_dahdi_pvt(tmp);
12564 return NULL;
12565 } else {
12566 si.spanno = 0;
12567 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12568 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12569 destroy_dahdi_pvt(tmp);
12570 return NULL;
12571 }
12572
12573 tmp->logicalspan = pris[span].prilogicalspan;
12574 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12575 if (span < 0) {
12576 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12577 destroy_dahdi_pvt(tmp);
12578 return NULL;
12579 }
12580 myswitchtype = conf->pri.pri.switchtype;
12581
12582 matchesdchan=0;
12583 for (x = 0; x < NUM_SPANS; x++) {
12584 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12585 if (pris[x].dchannels[y] == tmp->channel) {
12586 matchesdchan = 1;
12587 break;
12588 }
12589 }
12590 }
12591 if (!matchesdchan) {
12592 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12593 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12594 destroy_dahdi_pvt(tmp);
12595 return NULL;
12596 }
12597 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12598 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12599 destroy_dahdi_pvt(tmp);
12600 return NULL;
12601 }
12602 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12603 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));
12604 destroy_dahdi_pvt(tmp);
12605 return NULL;
12606 }
12607 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12608 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12609 destroy_dahdi_pvt(tmp);
12610 return NULL;
12611 }
12612 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12613 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12614 destroy_dahdi_pvt(tmp);
12615 return NULL;
12616 }
12617 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12618 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12619 destroy_dahdi_pvt(tmp);
12620 return NULL;
12621 }
12622 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12623 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12624 destroy_dahdi_pvt(tmp);
12625 return NULL;
12626 }
12627 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12628 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12629 pris[span].pri.trunkgroup);
12630 destroy_dahdi_pvt(tmp);
12631 return NULL;
12632 }
12633
12634 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12635 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12636 if (!pri_chan) {
12637 destroy_dahdi_pvt(tmp);
12638 return NULL;
12639 }
12640 tmp->sig_pvt = pri_chan;
12641 tmp->pri = &pris[span].pri;
12642
12643 tmp->priexclusive = conf->chan.priexclusive;
12644
12645 if (!tmp->pri->cc_params) {
12646 tmp->pri->cc_params = ast_cc_config_params_init();
12647 if (!tmp->pri->cc_params) {
12648 destroy_dahdi_pvt(tmp);
12649 return NULL;
12650 }
12651 }
12652 ast_cc_copy_config_params(tmp->pri->cc_params,
12653 conf->chan.cc_params);
12654
12655 pris[span].pri.sig = chan_sig;
12656 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12657 pris[span].pri.switchtype = myswitchtype;
12658 pris[span].pri.nsf = conf->pri.pri.nsf;
12659 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12660 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12661 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12662 pris[span].pri.minunused = conf->pri.pri.minunused;
12663 pris[span].pri.minidle = conf->pri.pri.minidle;
12664 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12665 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12666 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12667 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12668 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12669 #endif
12670 #ifdef HAVE_PRI_INBANDDISCONNECT
12671 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12672 #endif
12673 #if defined(HAVE_PRI_CALL_HOLD)
12674 pris[span].pri.hold_disconnect_transfer =
12675 conf->pri.pri.hold_disconnect_transfer;
12676 #endif
12677 #if defined(HAVE_PRI_CCSS)
12678 pris[span].pri.cc_ptmp_recall_mode =
12679 conf->pri.pri.cc_ptmp_recall_mode;
12680 pris[span].pri.cc_qsig_signaling_link_req =
12681 conf->pri.pri.cc_qsig_signaling_link_req;
12682 pris[span].pri.cc_qsig_signaling_link_rsp =
12683 conf->pri.pri.cc_qsig_signaling_link_rsp;
12684 #endif
12685 #if defined(HAVE_PRI_CALL_WAITING)
12686 pris[span].pri.max_call_waiting_calls =
12687 conf->pri.pri.max_call_waiting_calls;
12688 pris[span].pri.allow_call_waiting_calls =
12689 conf->pri.pri.allow_call_waiting_calls;
12690 #endif
12691 pris[span].pri.transfer = conf->chan.transfer;
12692 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12693 #if defined(HAVE_PRI_L2_PERSISTENCE)
12694 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12695 #endif
12696 #if defined(HAVE_PRI_AOC_EVENTS)
12697 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12698 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12699 #endif
12700 if (chan_sig == SIG_BRI_PTMP) {
12701 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12702 } else {
12703
12704 pris[span].pri.layer1_ignored = 0;
12705 }
12706 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12707 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12708 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12709 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12710 #if defined(HAVE_PRI_MWI)
12711 ast_copy_string(pris[span].pri.mwi_mailboxes,
12712 conf->pri.pri.mwi_mailboxes,
12713 sizeof(pris[span].pri.mwi_mailboxes));
12714 #endif
12715 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12716 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12717 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12718 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12719 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12720 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12721 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12722 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12723
12724 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12725 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12726 }
12727
12728 #if defined(HAVE_PRI_CALL_WAITING)
12729
12730 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12731 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12732 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12733 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12734 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12735 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12736 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12737 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12738 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12739 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12740 #endif
12741 } else {
12742 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12743 destroy_dahdi_pvt(tmp);
12744 return NULL;
12745 }
12746 }
12747 }
12748 #endif
12749 } else {
12750
12751 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));
12752 chan_sig = tmp->sig;
12753 if (tmp->subs[SUB_REAL].dfd > -1) {
12754 memset(&p, 0, sizeof(p));
12755 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12756 }
12757 }
12758
12759 switch (chan_sig) {
12760 case SIG_FXSKS:
12761 case SIG_FXSLS:
12762 case SIG_EM:
12763 case SIG_EM_E1:
12764 case SIG_EMWINK:
12765 case SIG_FEATD:
12766 case SIG_FEATDMF:
12767 case SIG_FEATDMF_TA:
12768 case SIG_FEATB:
12769 case SIG_E911:
12770 case SIG_SF:
12771 case SIG_SFWINK:
12772 case SIG_FGC_CAMA:
12773 case SIG_FGC_CAMAMF:
12774 case SIG_SF_FEATD:
12775 case SIG_SF_FEATDMF:
12776 case SIG_SF_FEATB:
12777 p.starttime = 250;
12778 break;
12779 }
12780
12781 if (tmp->radio) {
12782
12783 p.channo = channel;
12784 p.rxwinktime = 1;
12785 p.rxflashtime = 1;
12786 p.starttime = 1;
12787 p.debouncetime = 5;
12788 } else {
12789 p.channo = channel;
12790
12791 if (conf->timing.prewinktime >= 0)
12792 p.prewinktime = conf->timing.prewinktime;
12793 if (conf->timing.preflashtime >= 0)
12794 p.preflashtime = conf->timing.preflashtime;
12795 if (conf->timing.winktime >= 0)
12796 p.winktime = conf->timing.winktime;
12797 if (conf->timing.flashtime >= 0)
12798 p.flashtime = conf->timing.flashtime;
12799 if (conf->timing.starttime >= 0)
12800 p.starttime = conf->timing.starttime;
12801 if (conf->timing.rxwinktime >= 0)
12802 p.rxwinktime = conf->timing.rxwinktime;
12803 if (conf->timing.rxflashtime >= 0)
12804 p.rxflashtime = conf->timing.rxflashtime;
12805 if (conf->timing.debouncetime >= 0)
12806 p.debouncetime = conf->timing.debouncetime;
12807 }
12808
12809
12810 if (tmp->subs[SUB_REAL].dfd >= 0)
12811 {
12812 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12813 if (res < 0) {
12814 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12815 destroy_dahdi_pvt(tmp);
12816 return NULL;
12817 }
12818 }
12819 #if 1
12820 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12821 memset(&bi, 0, sizeof(bi));
12822 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12823 if (!res) {
12824 bi.txbufpolicy = conf->chan.buf_policy;
12825 bi.rxbufpolicy = conf->chan.buf_policy;
12826 bi.numbufs = conf->chan.buf_no;
12827 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12828 if (res < 0) {
12829 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12830 }
12831 } else {
12832 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12833 }
12834 tmp->buf_policy = conf->chan.buf_policy;
12835 tmp->buf_no = conf->chan.buf_no;
12836 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12837 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12838 tmp->faxbuf_no = conf->chan.faxbuf_no;
12839
12840
12841
12842
12843 tmp->bufsize = bi.bufsize;
12844 }
12845 #endif
12846 tmp->immediate = conf->chan.immediate;
12847 tmp->transfertobusy = conf->chan.transfertobusy;
12848 if (chan_sig & __DAHDI_SIG_FXS) {
12849 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12850 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12851 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12852 }
12853 tmp->ringt_base = ringt_base;
12854 tmp->firstradio = 0;
12855 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12856 tmp->permcallwaiting = conf->chan.callwaiting;
12857 else
12858 tmp->permcallwaiting = 0;
12859
12860 tmp->destroy = 0;
12861 tmp->drings = conf->chan.drings;
12862
12863
12864 if (tmp->drings.ringnum[0].range == 0)
12865 tmp->drings.ringnum[0].range = 10;
12866 if (tmp->drings.ringnum[1].range == 0)
12867 tmp->drings.ringnum[1].range = 10;
12868 if (tmp->drings.ringnum[2].range == 0)
12869 tmp->drings.ringnum[2].range = 10;
12870
12871 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12872 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12873 tmp->threewaycalling = conf->chan.threewaycalling;
12874 tmp->adsi = conf->chan.adsi;
12875 tmp->use_smdi = conf->chan.use_smdi;
12876 tmp->permhidecallerid = conf->chan.hidecallerid;
12877 tmp->hidecalleridname = conf->chan.hidecalleridname;
12878 tmp->callreturn = conf->chan.callreturn;
12879 tmp->echocancel = conf->chan.echocancel;
12880 tmp->echotraining = conf->chan.echotraining;
12881 tmp->pulse = conf->chan.pulse;
12882 if (tmp->echocancel.head.tap_length) {
12883 tmp->echocanbridged = conf->chan.echocanbridged;
12884 } else {
12885 if (conf->chan.echocanbridged)
12886 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12887 tmp->echocanbridged = 0;
12888 }
12889 tmp->busydetect = conf->chan.busydetect;
12890 tmp->busycount = conf->chan.busycount;
12891 tmp->busy_tonelength = conf->chan.busy_tonelength;
12892 tmp->busy_quietlength = conf->chan.busy_quietlength;
12893 tmp->callprogress = conf->chan.callprogress;
12894 tmp->waitfordialtone = conf->chan.waitfordialtone;
12895 tmp->cancallforward = conf->chan.cancallforward;
12896 tmp->dtmfrelax = conf->chan.dtmfrelax;
12897 tmp->callwaiting = tmp->permcallwaiting;
12898 tmp->hidecallerid = tmp->permhidecallerid;
12899 tmp->channel = channel;
12900 tmp->stripmsd = conf->chan.stripmsd;
12901 tmp->use_callerid = conf->chan.use_callerid;
12902 tmp->cid_signalling = conf->chan.cid_signalling;
12903 tmp->cid_start = conf->chan.cid_start;
12904 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12905 tmp->restrictcid = conf->chan.restrictcid;
12906 tmp->use_callingpres = conf->chan.use_callingpres;
12907 if (tmp->usedistinctiveringdetection) {
12908 if (!tmp->use_callerid) {
12909 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12910 tmp->use_callerid = 1;
12911 }
12912 }
12913
12914 if (tmp->cid_signalling == CID_SIG_SMDI) {
12915 if (!tmp->use_smdi) {
12916 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12917 tmp->use_smdi = 1;
12918 }
12919 }
12920 if (tmp->use_smdi) {
12921 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12922 if (!(tmp->smdi_iface)) {
12923 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12924 tmp->use_smdi = 0;
12925 }
12926 }
12927
12928 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12929 tmp->amaflags = conf->chan.amaflags;
12930 if (!here) {
12931 tmp->confno = -1;
12932 tmp->propconfno = -1;
12933 }
12934 tmp->canpark = conf->chan.canpark;
12935 tmp->transfer = conf->chan.transfer;
12936 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12937 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12938 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12939 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12940 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12941 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12942 tmp->cid_ton = 0;
12943 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12944 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12945 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12946 } else {
12947 tmp->cid_num[0] = '\0';
12948 tmp->cid_name[0] = '\0';
12949 }
12950 #if defined(HAVE_PRI)
12951 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12952 tmp->cid_tag[0] = '\0';
12953 } else
12954 #endif
12955 {
12956 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12957 }
12958 tmp->cid_subaddr[0] = '\0';
12959 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12960 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12961 char *mailbox, *context;
12962 mailbox = context = ast_strdupa(tmp->mailbox);
12963 strsep(&context, "@");
12964 if (ast_strlen_zero(context))
12965 context = "default";
12966 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12967 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12968 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12969 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12970 AST_EVENT_IE_END);
12971 }
12972 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12973 tmp->mwisend_setting = conf->chan.mwisend_setting;
12974 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12975 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12976 #endif
12977
12978 tmp->group = conf->chan.group;
12979 tmp->callgroup = conf->chan.callgroup;
12980 tmp->pickupgroup= conf->chan.pickupgroup;
12981 if (conf->chan.vars) {
12982 struct ast_variable *v, *tmpvar;
12983 for (v = conf->chan.vars ; v ; v = v->next) {
12984 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12985 tmpvar->next = tmp->vars;
12986 tmp->vars = tmpvar;
12987 }
12988 }
12989 }
12990 tmp->cid_rxgain = conf->chan.cid_rxgain;
12991 tmp->rxgain = conf->chan.rxgain;
12992 tmp->txgain = conf->chan.txgain;
12993 tmp->txdrc = conf->chan.txdrc;
12994 tmp->rxdrc = conf->chan.rxdrc;
12995 tmp->tonezone = conf->chan.tonezone;
12996 if (tmp->subs[SUB_REAL].dfd > -1) {
12997 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12998 if (tmp->dsp)
12999 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13000 update_conf(tmp);
13001 if (!here) {
13002 switch (chan_sig) {
13003 case SIG_PRI_LIB_HANDLE_CASES:
13004 case SIG_SS7:
13005 case SIG_MFCR2:
13006 break;
13007 default:
13008
13009 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13010 break;
13011 }
13012 }
13013 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13014 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13015
13016 switch (tmp->sig) {
13017 #ifdef HAVE_PRI
13018 case SIG_PRI_LIB_HANDLE_CASES:
13019 sig_pri_set_alarm(tmp->sig_pvt, 1);
13020 break;
13021 #endif
13022 #if defined(HAVE_SS7)
13023 case SIG_SS7:
13024 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13025 break;
13026 #endif
13027 default:
13028
13029 analog_p = tmp->sig_pvt;
13030 if (analog_p) {
13031 analog_p->inalarm = 1;
13032 }
13033 tmp->inalarm = 1;
13034 break;
13035 }
13036 handle_alarms(tmp, res);
13037 }
13038 }
13039
13040 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13041 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13042 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13043 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13044 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13045
13046 if (!here) {
13047 tmp->locallyblocked = 0;
13048 tmp->remotelyblocked = 0;
13049 switch (tmp->sig) {
13050 #if defined(HAVE_PRI)
13051 case SIG_PRI_LIB_HANDLE_CASES:
13052 tmp->inservice = 1;
13053 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13054 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13055 if (chan_sig == SIG_PRI) {
13056 char db_chan_name[20];
13057 char db_answer[5];
13058
13059
13060
13061
13062
13063 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13064 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13065 unsigned *why;
13066
13067 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13068 if (tmp->pri->enable_service_message_support) {
13069 char state;
13070
13071 sscanf(db_answer, "%1c:%30u", &state, why);
13072
13073
13074 *why &= (SRVST_NEAREND | SRVST_FAREND);
13075 }
13076 if (!*why) {
13077 ast_db_del(db_chan_name, SRVST_DBKEY);
13078 }
13079 }
13080 }
13081 #endif
13082 break;
13083 #endif
13084 #if defined(HAVE_SS7)
13085 case SIG_SS7:
13086 tmp->inservice = 0;
13087 break;
13088 #endif
13089 default:
13090
13091 tmp->inservice = 1;
13092 break;
13093 }
13094 }
13095
13096 switch (tmp->sig) {
13097 #if defined(HAVE_PRI)
13098 case SIG_PRI_LIB_HANDLE_CASES:
13099 if (pri_chan) {
13100 pri_chan->channel = tmp->channel;
13101 pri_chan->hidecallerid = tmp->hidecallerid;
13102 pri_chan->hidecalleridname = tmp->hidecalleridname;
13103 pri_chan->immediate = tmp->immediate;
13104 pri_chan->inalarm = tmp->inalarm;
13105 pri_chan->priexclusive = tmp->priexclusive;
13106 pri_chan->priindication_oob = tmp->priindication_oob;
13107 pri_chan->use_callerid = tmp->use_callerid;
13108 pri_chan->use_callingpres = tmp->use_callingpres;
13109 ast_copy_string(pri_chan->context, tmp->context,
13110 sizeof(pri_chan->context));
13111 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13112 sizeof(pri_chan->mohinterpret));
13113 pri_chan->stripmsd = tmp->stripmsd;
13114 }
13115 break;
13116 #endif
13117 #if defined(HAVE_SS7)
13118 case SIG_SS7:
13119 if (ss7_chan) {
13120 ss7_chan->inalarm = tmp->inalarm;
13121
13122 ss7_chan->stripmsd = tmp->stripmsd;
13123 ss7_chan->hidecallerid = tmp->hidecallerid;
13124 ss7_chan->use_callerid = tmp->use_callerid;
13125 ss7_chan->use_callingpres = tmp->use_callingpres;
13126 ss7_chan->immediate = tmp->immediate;
13127 ss7_chan->locallyblocked = tmp->locallyblocked;
13128 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13129 ast_copy_string(ss7_chan->context, tmp->context,
13130 sizeof(ss7_chan->context));
13131 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13132 sizeof(ss7_chan->mohinterpret));
13133 }
13134 break;
13135 #endif
13136 default:
13137
13138 analog_p = tmp->sig_pvt;
13139 if (analog_p) {
13140 analog_p->channel = tmp->channel;
13141 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13142 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13143 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13144 analog_p->permcallwaiting = conf->chan.callwaiting;
13145 analog_p->callreturn = conf->chan.callreturn;
13146 analog_p->cancallforward = conf->chan.cancallforward;
13147 analog_p->canpark = conf->chan.canpark;
13148 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13149 analog_p->immediate = conf->chan.immediate;
13150 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13151 analog_p->pulse = conf->chan.pulse;
13152 analog_p->threewaycalling = conf->chan.threewaycalling;
13153 analog_p->transfer = conf->chan.transfer;
13154 analog_p->transfertobusy = conf->chan.transfertobusy;
13155 analog_p->use_callerid = tmp->use_callerid;
13156 analog_p->use_smdi = tmp->use_smdi;
13157 analog_p->smdi_iface = tmp->smdi_iface;
13158 analog_p->outsigmod = ANALOG_SIG_NONE;
13159 analog_p->echotraining = conf->chan.echotraining;
13160 analog_p->cid_signalling = conf->chan.cid_signalling;
13161 analog_p->stripmsd = conf->chan.stripmsd;
13162 switch (conf->chan.cid_start) {
13163 case CID_START_POLARITY:
13164 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13165 break;
13166 case CID_START_POLARITY_IN:
13167 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13168 break;
13169 case CID_START_DTMF_NOALERT:
13170 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13171 break;
13172 default:
13173 analog_p->cid_start = ANALOG_CID_START_RING;
13174 break;
13175 }
13176 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13177 analog_p->ringt = conf->chan.ringt;
13178 analog_p->ringt_base = ringt_base;
13179 analog_p->onhooktime = time(NULL);
13180 if (chan_sig & __DAHDI_SIG_FXO) {
13181 memset(&p, 0, sizeof(p));
13182 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13183 if (!res) {
13184 analog_p->fxsoffhookstate = p.rxisoffhook;
13185 }
13186 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13187 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13188 #endif
13189 }
13190 analog_p->msgstate = -1;
13191
13192 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13193 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13194 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13195
13196 analog_config_complete(analog_p);
13197 }
13198 break;
13199 }
13200 #if defined(HAVE_PRI)
13201 if (tmp->channel == CHAN_PSEUDO) {
13202
13203
13204
13205
13206 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13207 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13208 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13209 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13210 }
13211 #endif
13212 }
13213 if (tmp && !here) {
13214
13215 dahdi_iflist_insert(tmp);
13216 }
13217 return tmp;
13218 }
13219
13220 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13221 {
13222 #if defined(HAVE_PRI)
13223 if (0 < span) {
13224
13225 if (!p->pri || p->pri->span != span) {
13226 return 0;
13227 }
13228 if (!groupmatch && channelmatch == -1) {
13229
13230 *groupmatched = 1;
13231 return 1;
13232 }
13233 }
13234 #endif
13235
13236 if (groupmatch) {
13237 if ((p->group & groupmatch) != groupmatch)
13238
13239 return 0;
13240 *groupmatched = 1;
13241 }
13242
13243 if (channelmatch != -1) {
13244 if (p->channel != channelmatch)
13245
13246 return 0;
13247 *channelmatched = 1;
13248 }
13249
13250 return 1;
13251 }
13252
13253 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13254 {
13255 struct dahdi_pvt *p = *pvt;
13256
13257 if (p->inalarm)
13258 return 0;
13259
13260 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13261 return analog_available(p->sig_pvt);
13262
13263 switch (p->sig) {
13264 #if defined(HAVE_PRI)
13265 case SIG_PRI_LIB_HANDLE_CASES:
13266 {
13267 struct sig_pri_chan *pvt_chan;
13268 int res;
13269
13270 pvt_chan = p->sig_pvt;
13271 res = sig_pri_available(&pvt_chan, is_specific_channel);
13272 *pvt = pvt_chan->chan_pvt;
13273 return res;
13274 }
13275 #endif
13276 #if defined(HAVE_SS7)
13277 case SIG_SS7:
13278 return sig_ss7_available(p->sig_pvt);
13279 #endif
13280 default:
13281 break;
13282 }
13283
13284 if (p->locallyblocked || p->remotelyblocked) {
13285 return 0;
13286 }
13287
13288
13289 if (!p->owner) {
13290 #ifdef HAVE_OPENR2
13291
13292 if (p->mfcr2) {
13293 if (p->mfcr2call) {
13294 return 0;
13295 } else {
13296 return 1;
13297 }
13298 }
13299 #endif
13300 return 1;
13301 }
13302
13303 return 0;
13304 }
13305
13306 #if defined(HAVE_PRI)
13307 #if defined(HAVE_PRI_CALL_WAITING)
13308
13309
13310
13311
13312
13313
13314
13315
13316
13317
13318
13319
13320 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13321 {
13322 struct dahdi_pvt *pvt = priv;
13323
13324 pvt->stripmsd = pri->ch_cfg.stripmsd;
13325 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13326 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13327 pvt->immediate = pri->ch_cfg.immediate;
13328 pvt->priexclusive = pri->ch_cfg.priexclusive;
13329 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13330 pvt->use_callerid = pri->ch_cfg.use_callerid;
13331 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13332 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13333 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13334 }
13335 #endif
13336 #endif
13337
13338 #if defined(HAVE_PRI)
13339
13340
13341
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13352 {
13353 int pvt_idx;
13354 int res;
13355 unsigned idx;
13356 struct dahdi_pvt *pvt;
13357 struct sig_pri_chan *chan;
13358 struct dahdi_bufferinfo bi;
13359
13360 static int nobch_channel = CHAN_PSEUDO;
13361
13362
13363 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13364 if (!pri->pvts[pvt_idx]) {
13365 break;
13366 }
13367 }
13368 if (pri->numchans == pvt_idx) {
13369 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13370 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13371 return -1;
13372 }
13373
13374
13375 pri->pvts[pvt_idx] = NULL;
13376 ++pri->numchans;
13377 }
13378
13379 pvt = ast_calloc(1, sizeof(*pvt));
13380 if (!pvt) {
13381 return -1;
13382 }
13383 pvt->cc_params = ast_cc_config_params_init();
13384 if (!pvt->cc_params) {
13385 ast_free(pvt);
13386 return -1;
13387 }
13388 ast_mutex_init(&pvt->lock);
13389 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13390 pvt->subs[idx].dfd = -1;
13391 }
13392 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13393 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13394 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13395 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13396
13397 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13398 if (!chan) {
13399 destroy_dahdi_pvt(pvt);
13400 return -1;
13401 }
13402 chan->no_b_channel = 1;
13403
13404
13405
13406
13407
13408
13409 pvt->law_default = DAHDI_LAW_ALAW;
13410
13411 pvt->sig = pri->sig;
13412 pvt->outsigmod = -1;
13413 pvt->pri = pri;
13414 pvt->sig_pvt = chan;
13415 pri->pvts[pvt_idx] = chan;
13416
13417 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13418 if (pvt->subs[SUB_REAL].dfd < 0) {
13419 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13420 strerror(errno));
13421 destroy_dahdi_pvt(pvt);
13422 return -1;
13423 }
13424 memset(&bi, 0, sizeof(bi));
13425 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13426 if (!res) {
13427 pvt->bufsize = bi.bufsize;
13428 bi.txbufpolicy = pvt->buf_policy;
13429 bi.rxbufpolicy = pvt->buf_policy;
13430 bi.numbufs = pvt->buf_no;
13431 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13432 if (res < 0) {
13433 ast_log(LOG_WARNING,
13434 "Unable to set buffer policy on no B channel interface: %s\n",
13435 strerror(errno));
13436 }
13437 } else
13438 ast_log(LOG_WARNING,
13439 "Unable to check buffer policy on no B channel interface: %s\n",
13440 strerror(errno));
13441
13442 --nobch_channel;
13443 if (CHAN_PSEUDO < nobch_channel) {
13444 nobch_channel = CHAN_PSEUDO - 1;
13445 }
13446 pvt->channel = nobch_channel;
13447 pvt->span = pri->span;
13448 chan->channel = pvt->channel;
13449
13450 dahdi_nobch_insert(pri, pvt);
13451
13452 return pvt_idx;
13453 }
13454 #endif
13455
13456
13457
13458
13459
13460
13461 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13462 {
13463 struct dahdi_pvt *p;
13464 struct dahdi_bufferinfo bi;
13465 int res;
13466
13467 p = ast_malloc(sizeof(*p));
13468 if (!p) {
13469 return NULL;
13470 }
13471 *p = *src;
13472
13473
13474 p->cc_params = ast_cc_config_params_init();
13475 if (!p->cc_params) {
13476 ast_free(p);
13477 return NULL;
13478 }
13479 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13480
13481 p->which_iflist = DAHDI_IFLIST_NONE;
13482 p->next = NULL;
13483 p->prev = NULL;
13484 ast_mutex_init(&p->lock);
13485 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13486 if (p->subs[SUB_REAL].dfd < 0) {
13487 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13488 destroy_dahdi_pvt(p);
13489 return NULL;
13490 }
13491 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13492 if (!res) {
13493 bi.txbufpolicy = src->buf_policy;
13494 bi.rxbufpolicy = src->buf_policy;
13495 bi.numbufs = src->buf_no;
13496 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13497 if (res < 0) {
13498 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13499 }
13500 } else
13501 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13502 p->destroy = 1;
13503 dahdi_iflist_insert(p);
13504 return p;
13505 }
13506
13507 struct dahdi_starting_point {
13508
13509 ast_group_t groupmatch;
13510
13511 int channelmatch;
13512
13513 int rr_starting_point;
13514
13515 int span;
13516
13517 int cadance;
13518
13519 char opt;
13520
13521 char backwards;
13522
13523 char roundrobin;
13524 };
13525 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13526 {
13527 char *dest;
13528 char *s;
13529 int x;
13530 int res = 0;
13531 struct dahdi_pvt *p;
13532 char *subdir = NULL;
13533 AST_DECLARE_APP_ARGS(args,
13534 AST_APP_ARG(group);
13535
13536
13537 AST_APP_ARG(other);
13538 );
13539
13540
13541
13542
13543
13544
13545
13546
13547
13548
13549
13550
13551
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561
13562
13563 if (data) {
13564 dest = ast_strdupa(data);
13565 } else {
13566 ast_log(LOG_WARNING, "Channel requested with no data\n");
13567 return NULL;
13568 }
13569 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13570 if (!args.argc || ast_strlen_zero(args.group)) {
13571 ast_log(LOG_WARNING, "No channel/group specified\n");
13572 return NULL;
13573 }
13574
13575
13576 memset(param, 0, sizeof(*param));
13577 param->channelmatch = -1;
13578
13579 if (strchr(args.group, '!') != NULL) {
13580 char *prev = args.group;
13581 while ((s = strchr(prev, '!')) != NULL) {
13582 *s++ = '/';
13583 prev = s;
13584 }
13585 *(prev - 1) = '\0';
13586 subdir = args.group;
13587 args.group = prev;
13588 } else if (args.group[0] == 'i') {
13589
13590 res = sscanf(args.group + 1, "%30d", &x);
13591 if (res < 1) {
13592 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13593 return NULL;
13594 }
13595 param->span = x;
13596
13597
13598 s = strchr(args.group, '-');
13599 if (!s) {
13600
13601 return iflist;
13602 }
13603 args.group = s + 1;
13604 res = 0;
13605 }
13606 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13607
13608 s = args.group + 1;
13609 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13610 if (res < 1) {
13611 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13612 return NULL;
13613 }
13614 param->groupmatch = ((ast_group_t) 1 << x);
13615
13616 if (toupper(args.group[0]) == 'G') {
13617 if (args.group[0] == 'G') {
13618 param->backwards = 1;
13619 p = ifend;
13620 } else
13621 p = iflist;
13622 } else {
13623 if (ARRAY_LEN(round_robin) <= x) {
13624 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13625 x, data);
13626 return NULL;
13627 }
13628 if (args.group[0] == 'R') {
13629 param->backwards = 1;
13630 p = round_robin[x] ? round_robin[x]->prev : ifend;
13631 if (!p)
13632 p = ifend;
13633 } else {
13634 p = round_robin[x] ? round_robin[x]->next : iflist;
13635 if (!p)
13636 p = iflist;
13637 }
13638 param->roundrobin = 1;
13639 param->rr_starting_point = x;
13640 }
13641 } else {
13642 s = args.group;
13643 if (!strcasecmp(s, "pseudo")) {
13644
13645 x = CHAN_PSEUDO;
13646 param->channelmatch = x;
13647 } else {
13648 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13649 if (res < 1) {
13650 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13651 return NULL;
13652 } else {
13653 param->channelmatch = x;
13654 }
13655 }
13656 if (subdir) {
13657 char path[PATH_MAX];
13658 struct stat stbuf;
13659
13660 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13661 subdir, param->channelmatch);
13662 if (stat(path, &stbuf) < 0) {
13663 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13664 path, strerror(errno));
13665 return NULL;
13666 }
13667 if (!S_ISCHR(stbuf.st_mode)) {
13668 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13669 path);
13670 return NULL;
13671 }
13672 param->channelmatch = minor(stbuf.st_rdev);
13673 }
13674
13675 p = iflist;
13676 }
13677
13678 if (param->opt == 'r' && res < 3) {
13679 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13680 param->opt = '\0';
13681 }
13682
13683 return p;
13684 }
13685
13686 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13687 {
13688 int callwait = 0;
13689 struct dahdi_pvt *p;
13690 struct ast_channel *tmp = NULL;
13691 struct dahdi_pvt *exitpvt;
13692 int channelmatched = 0;
13693 int groupmatched = 0;
13694 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13695 int transcapdigital = 0;
13696 #endif
13697 struct dahdi_starting_point start;
13698
13699 ast_mutex_lock(&iflock);
13700 p = determine_starting_point(data, &start);
13701 if (!p) {
13702
13703 ast_mutex_unlock(&iflock);
13704 return NULL;
13705 }
13706
13707
13708 exitpvt = p;
13709 while (p && !tmp) {
13710 if (start.roundrobin)
13711 round_robin[start.rr_starting_point] = p;
13712
13713 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13714 && available(&p, channelmatched)) {
13715 ast_debug(1, "Using channel %d\n", p->channel);
13716
13717 callwait = (p->owner != NULL);
13718 #ifdef HAVE_OPENR2
13719 if (p->mfcr2) {
13720 ast_mutex_lock(&p->lock);
13721 if (p->mfcr2call) {
13722 ast_mutex_unlock(&p->lock);
13723 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13724 goto next;
13725 }
13726 p->mfcr2call = 1;
13727 ast_mutex_unlock(&p->lock);
13728 }
13729 #endif
13730 if (p->channel == CHAN_PSEUDO) {
13731 p = duplicate_pseudo(p);
13732 if (!p) {
13733 break;
13734 }
13735 }
13736
13737 p->distinctivering = 0;
13738
13739 switch (start.opt) {
13740 case '\0':
13741
13742 break;
13743 case 'c':
13744
13745 p->confirmanswer = 1;
13746 break;
13747 case 'r':
13748
13749 p->distinctivering = start.cadance;
13750 break;
13751 case 'd':
13752 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13753
13754 transcapdigital = AST_TRANS_CAP_DIGITAL;
13755 #endif
13756 break;
13757 default:
13758 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13759 break;
13760 }
13761
13762 p->outgoing = 1;
13763 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13764 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13765 #ifdef HAVE_PRI
13766 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13767
13768
13769
13770
13771
13772 ast_mutex_lock(&p->lock);
13773 ast_mutex_unlock(&p->lock);
13774
13775 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13776 sizeof(p->dnid));
13777 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13778 #endif
13779 #if defined(HAVE_SS7)
13780 } else if (p->sig == SIG_SS7) {
13781 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13782 #endif
13783 } else {
13784 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13785 }
13786 if (!tmp) {
13787 p->outgoing = 0;
13788 #if defined(HAVE_PRI)
13789 switch (p->sig) {
13790 case SIG_PRI_LIB_HANDLE_CASES:
13791 #if defined(HAVE_PRI_CALL_WAITING)
13792 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13793 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13794 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13795 }
13796 #endif
13797
13798
13799
13800
13801 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13802 break;
13803 default:
13804 break;
13805 }
13806 #endif
13807 } else {
13808 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13809 }
13810 break;
13811 }
13812 #ifdef HAVE_OPENR2
13813 next:
13814 #endif
13815 if (start.backwards) {
13816 p = p->prev;
13817 if (!p)
13818 p = ifend;
13819 } else {
13820 p = p->next;
13821 if (!p)
13822 p = iflist;
13823 }
13824
13825 if (p == exitpvt)
13826 break;
13827 }
13828 ast_mutex_unlock(&iflock);
13829 restart_monitor();
13830 if (cause && !tmp) {
13831 if (callwait || channelmatched) {
13832 *cause = AST_CAUSE_BUSY;
13833 } else if (groupmatched) {
13834 *cause = AST_CAUSE_CONGESTION;
13835 } else {
13836
13837
13838
13839
13840 }
13841 }
13842
13843 return tmp;
13844 }
13845
13846
13847
13848
13849
13850
13851
13852
13853
13854
13855
13856 static int dahdi_devicestate(void *data)
13857 {
13858 #if defined(HAVE_PRI)
13859 char *device;
13860 unsigned span;
13861 int res;
13862
13863 device = data;
13864
13865 if (*device != 'I') {
13866
13867 return AST_DEVICE_UNKNOWN;
13868 }
13869 res = sscanf(device, "I%30u", &span);
13870 if (res != 1 || !span || NUM_SPANS < span) {
13871
13872 return AST_DEVICE_UNKNOWN;
13873 }
13874 device = strchr(device, '/');
13875 if (!device) {
13876
13877 return AST_DEVICE_UNKNOWN;
13878 }
13879
13880
13881
13882
13883
13884 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13885 ++device;
13886 if (!strcmp(device, "congestion"))
13887 #endif
13888 {
13889 return pris[span - 1].pri.congestion_devstate;
13890 }
13891 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13892 else if (!strcmp(device, "threshold")) {
13893 return pris[span - 1].pri.threshold_devstate;
13894 }
13895 return AST_DEVICE_UNKNOWN;
13896 #endif
13897 #else
13898 return AST_DEVICE_UNKNOWN;
13899 #endif
13900 }
13901
13902
13903
13904
13905
13906
13907
13908
13909
13910
13911
13912
13913
13914
13915
13916
13917
13918 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13919 {
13920 struct dahdi_pvt *p;
13921 struct dahdi_pvt *exitpvt;
13922 struct dahdi_starting_point start;
13923 int groupmatched = 0;
13924 int channelmatched = 0;
13925
13926 ast_mutex_lock(&iflock);
13927 p = determine_starting_point(dest, &start);
13928 if (!p) {
13929 ast_mutex_unlock(&iflock);
13930 return -1;
13931 }
13932 exitpvt = p;
13933 for (;;) {
13934 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13935
13936 struct ast_str *device_name;
13937 char *dash;
13938 const char *monitor_type;
13939 char dialstring[AST_CHANNEL_NAME];
13940 char full_device_name[AST_CHANNEL_NAME];
13941
13942 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13943 case AST_CC_MONITOR_NEVER:
13944 break;
13945 case AST_CC_MONITOR_NATIVE:
13946 case AST_CC_MONITOR_ALWAYS:
13947 case AST_CC_MONITOR_GENERIC:
13948 #if defined(HAVE_PRI)
13949 if (dahdi_sig_pri_lib_handles(p->sig)) {
13950
13951
13952
13953
13954 snprintf(full_device_name, sizeof(full_device_name),
13955 "DAHDI/I%d/congestion", p->pri->span);
13956 } else
13957 #endif
13958 {
13959 #if defined(HAVE_PRI)
13960 device_name = create_channel_name(p, 1, "");
13961 #else
13962 device_name = create_channel_name(p);
13963 #endif
13964 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13965 device_name ? ast_str_buffer(device_name) : "");
13966 ast_free(device_name);
13967
13968
13969
13970
13971
13972 dash = strrchr(full_device_name, '-');
13973 if (dash) {
13974 *dash = '\0';
13975 }
13976 }
13977 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13978
13979
13980
13981
13982
13983
13984
13985 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13986 callback(inbound,
13987 #if defined(HAVE_PRI)
13988 p->pri ? p->pri->cc_params : p->cc_params,
13989 #else
13990 p->cc_params,
13991 #endif
13992 monitor_type, full_device_name, dialstring, NULL);
13993 break;
13994 }
13995 }
13996 p = start.backwards ? p->prev : p->next;
13997 if (!p) {
13998 p = start.backwards ? ifend : iflist;
13999 }
14000 if (p == exitpvt) {
14001 break;
14002 }
14003 }
14004 ast_mutex_unlock(&iflock);
14005 return 0;
14006 }
14007
14008 #if defined(HAVE_SS7)
14009 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14010 {
14011 int i;
14012
14013 if (ss7) {
14014 for (i = 0; i < NUM_SPANS; i++) {
14015 if (linksets[i].ss7.ss7 == ss7) {
14016 ast_verbose("[%d] %s", i + 1, s);
14017 return;
14018 }
14019 }
14020 }
14021 ast_verbose("%s", s);
14022 }
14023 #endif
14024
14025 #if defined(HAVE_SS7)
14026 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14027 {
14028 int i;
14029
14030 if (ss7) {
14031 for (i = 0; i < NUM_SPANS; i++) {
14032 if (linksets[i].ss7.ss7 == ss7) {
14033 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14034 return;
14035 }
14036 }
14037 }
14038 ast_log(LOG_ERROR, "%s", s);
14039 }
14040 #endif
14041
14042 #if defined(HAVE_OPENR2)
14043 static void *mfcr2_monitor(void *data)
14044 {
14045 struct dahdi_mfcr2 *mfcr2 = data;
14046
14047
14048
14049
14050
14051 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14052 int res = 0;
14053 int i = 0;
14054 int oldstate = 0;
14055 int quit_loop = 0;
14056 int maxsleep = 20;
14057 int was_idle = 0;
14058 int pollsize = 0;
14059
14060
14061 for (i = 0; i < mfcr2->numchans; i++) {
14062 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14063 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14064 }
14065 while (1) {
14066
14067
14068 pollsize = 0;
14069 for (i = 0; i < mfcr2->numchans; i++) {
14070 pollers[i].revents = 0;
14071 pollers[i].events = 0;
14072 if (mfcr2->pvts[i]->owner) {
14073 continue;
14074 }
14075 if (!mfcr2->pvts[i]->r2chan) {
14076 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14077 quit_loop = 1;
14078 break;
14079 }
14080 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14081 pollers[i].events = POLLIN | POLLPRI;
14082 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14083 pollsize++;
14084 }
14085 if (quit_loop) {
14086 break;
14087 }
14088 if (pollsize == 0) {
14089 if (!was_idle) {
14090 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14091 was_idle = 1;
14092 }
14093 poll(NULL, 0, maxsleep);
14094 continue;
14095 }
14096 was_idle = 0;
14097
14098
14099 pthread_testcancel();
14100 res = poll(pollers, mfcr2->numchans, maxsleep);
14101 pthread_testcancel();
14102 if ((res < 0) && (errno != EINTR)) {
14103 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14104 break;
14105 }
14106
14107 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14108 for (i = 0; i < mfcr2->numchans; i++) {
14109 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14110 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14111 }
14112 }
14113 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14114 }
14115 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14116 return 0;
14117 }
14118 #endif
14119
14120 #if defined(HAVE_PRI)
14121 static void dahdi_pri_message(struct pri *pri, char *s)
14122 {
14123 int x;
14124 int y;
14125 int dchan = -1;
14126 int span = -1;
14127 int dchancount = 0;
14128
14129 if (pri) {
14130 for (x = 0; x < NUM_SPANS; x++) {
14131 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14132 if (pris[x].pri.dchans[y]) {
14133 dchancount++;
14134 }
14135
14136 if (pris[x].pri.dchans[y] == pri) {
14137 dchan = y;
14138 }
14139 }
14140 if (dchan >= 0) {
14141 span = x;
14142 break;
14143 }
14144 dchancount = 0;
14145 }
14146 if (-1 < span) {
14147 if (1 < dchancount) {
14148 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14149 } else {
14150 ast_verbose("PRI Span: %d %s", span + 1, s);
14151 }
14152 } else {
14153 ast_verbose("PRI Span: ? %s", s);
14154 }
14155 } else {
14156 ast_verbose("PRI Span: ? %s", s);
14157 }
14158
14159 ast_mutex_lock(&pridebugfdlock);
14160
14161 if (pridebugfd >= 0) {
14162 if (write(pridebugfd, s, strlen(s)) < 0) {
14163 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14164 }
14165 }
14166
14167 ast_mutex_unlock(&pridebugfdlock);
14168 }
14169 #endif
14170
14171 #if defined(HAVE_PRI)
14172 static void dahdi_pri_error(struct pri *pri, char *s)
14173 {
14174 int x;
14175 int y;
14176 int dchan = -1;
14177 int span = -1;
14178 int dchancount = 0;
14179
14180 if (pri) {
14181 for (x = 0; x < NUM_SPANS; x++) {
14182 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14183 if (pris[x].pri.dchans[y]) {
14184 dchancount++;
14185 }
14186
14187 if (pris[x].pri.dchans[y] == pri) {
14188 dchan = y;
14189 }
14190 }
14191 if (dchan >= 0) {
14192 span = x;
14193 break;
14194 }
14195 dchancount = 0;
14196 }
14197 if (-1 < span) {
14198 if (1 < dchancount) {
14199 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14200 } else {
14201 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14202 }
14203 } else {
14204 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14205 }
14206 } else {
14207 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14208 }
14209
14210 ast_mutex_lock(&pridebugfdlock);
14211
14212 if (pridebugfd >= 0) {
14213 if (write(pridebugfd, s, strlen(s)) < 0) {
14214 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14215 }
14216 }
14217
14218 ast_mutex_unlock(&pridebugfdlock);
14219 }
14220 #endif
14221
14222 #if defined(HAVE_PRI)
14223 static int prepare_pri(struct dahdi_pri *pri)
14224 {
14225 int i, res, x;
14226 struct dahdi_params p;
14227 struct dahdi_bufferinfo bi;
14228 struct dahdi_spaninfo si;
14229
14230 pri->pri.calls = &dahdi_pri_callbacks;
14231
14232 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14233 if (!pri->dchannels[i])
14234 break;
14235 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14236 x = pri->dchannels[i];
14237 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14238 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14239 return -1;
14240 }
14241 memset(&p, 0, sizeof(p));
14242 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14243 if (res) {
14244 dahdi_close_pri_fd(pri, i);
14245 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14246 return -1;
14247 }
14248 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14249 dahdi_close_pri_fd(pri, i);
14250 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14251 return -1;
14252 }
14253 memset(&si, 0, sizeof(si));
14254 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14255 if (res) {
14256 dahdi_close_pri_fd(pri, i);
14257 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14258 }
14259 if (!si.alarms) {
14260 pri_event_noalarm(&pri->pri, i, 1);
14261 } else {
14262 pri_event_alarm(&pri->pri, i, 1);
14263 }
14264 memset(&bi, 0, sizeof(bi));
14265 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14266 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14267 bi.numbufs = 32;
14268 bi.bufsize = 1024;
14269 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14270 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14271 dahdi_close_pri_fd(pri, i);
14272 return -1;
14273 }
14274 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14275 }
14276 return 0;
14277 }
14278 #endif
14279
14280 #if defined(HAVE_PRI)
14281 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14282 {
14283 int which, span;
14284 char *ret = NULL;
14285
14286 if (pos != rpos)
14287 return ret;
14288
14289 for (which = span = 0; span < NUM_SPANS; span++) {
14290 if (pris[span].pri.pri && ++which > state) {
14291 if (ast_asprintf(&ret, "%d", span + 1) < 0) {
14292 ret = NULL;
14293 }
14294 break;
14295 }
14296 }
14297 return ret;
14298 }
14299 #endif
14300
14301 #if defined(HAVE_PRI)
14302 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14303 {
14304 return complete_span_helper(line,word,pos,state,3);
14305 }
14306 #endif
14307
14308 #if defined(HAVE_PRI)
14309 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14310 {
14311 int myfd;
14312 switch (cmd) {
14313 case CLI_INIT:
14314 e->command = "pri set debug file";
14315 e->usage = "Usage: pri set debug file [output-file]\n"
14316 " Sends PRI debug output to the specified output file\n";
14317 return NULL;
14318 case CLI_GENERATE:
14319 return NULL;
14320 }
14321 if (a->argc < 5)
14322 return CLI_SHOWUSAGE;
14323
14324 if (ast_strlen_zero(a->argv[4]))
14325 return CLI_SHOWUSAGE;
14326
14327 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14328 if (myfd < 0) {
14329 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14330 return CLI_SUCCESS;
14331 }
14332
14333 ast_mutex_lock(&pridebugfdlock);
14334
14335 if (pridebugfd >= 0)
14336 close(pridebugfd);
14337
14338 pridebugfd = myfd;
14339 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14340 ast_mutex_unlock(&pridebugfdlock);
14341 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14342 return CLI_SUCCESS;
14343 }
14344 #endif
14345
14346 #if defined(HAVE_PRI)
14347 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14348 {
14349 int span;
14350 int x;
14351 int level = 0;
14352 switch (cmd) {
14353 case CLI_INIT:
14354 e->command = "pri set debug {on|off|0|1|2} span";
14355 e->usage =
14356 "Usage: pri set debug {<level>|on|off} span <span>\n"
14357 " Enables debugging on a given PRI span\n";
14358 return NULL;
14359 case CLI_GENERATE:
14360 return complete_span_4(a->line, a->word, a->pos, a->n);
14361 }
14362 if (a->argc < 6) {
14363 return CLI_SHOWUSAGE;
14364 }
14365
14366 if (!strcasecmp(a->argv[3], "on")) {
14367 level = 1;
14368 } else if (!strcasecmp(a->argv[3], "off")) {
14369 level = 0;
14370 } else {
14371 level = atoi(a->argv[3]);
14372 }
14373 span = atoi(a->argv[5]);
14374 if ((span < 1) || (span > NUM_SPANS)) {
14375 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14376 return CLI_SUCCESS;
14377 }
14378 if (!pris[span-1].pri.pri) {
14379 ast_cli(a->fd, "No PRI running on span %d\n", span);
14380 return CLI_SUCCESS;
14381 }
14382
14383
14384 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14385 if (pris[span - 1].pri.dchans[x]) {
14386 switch (level) {
14387 case 0:
14388 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14389 break;
14390 case 1:
14391 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14392 break;
14393 default:
14394 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14395 break;
14396 }
14397 }
14398 }
14399 if (level == 0) {
14400
14401 ast_mutex_lock(&pridebugfdlock);
14402 if (0 <= pridebugfd) {
14403 close(pridebugfd);
14404 pridebugfd = -1;
14405 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14406 pridebugfilename);
14407 }
14408 ast_mutex_unlock(&pridebugfdlock);
14409 }
14410 pris[span - 1].pri.debug = (level) ? 1 : 0;
14411 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14412 return CLI_SUCCESS;
14413 }
14414 #endif
14415
14416 #if defined(HAVE_PRI)
14417 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14418 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14419 {
14420 unsigned *why;
14421 int channel;
14422 int trunkgroup;
14423 int x, y, fd = a->fd;
14424 int interfaceid = 0;
14425 char db_chan_name[20], db_answer[5];
14426 struct dahdi_pvt *tmp;
14427 struct dahdi_pri *pri;
14428
14429 if (a->argc < 5 || a->argc > 6)
14430 return CLI_SHOWUSAGE;
14431 if (strchr(a->argv[4], ':')) {
14432 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14433 return CLI_SHOWUSAGE;
14434 if ((trunkgroup < 1) || (channel < 1))
14435 return CLI_SHOWUSAGE;
14436 pri = NULL;
14437 for (x=0;x<NUM_SPANS;x++) {
14438 if (pris[x].pri.trunkgroup == trunkgroup) {
14439 pri = pris + x;
14440 break;
14441 }
14442 }
14443 if (!pri) {
14444 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14445 return CLI_FAILURE;
14446 }
14447 } else
14448 channel = atoi(a->argv[4]);
14449
14450 if (a->argc == 6)
14451 interfaceid = atoi(a->argv[5]);
14452
14453
14454 for (x = 0; x < NUM_SPANS; x++) {
14455 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14456 if (pris[x].dchannels[y] == channel) {
14457 pri = pris + x;
14458 if (pri->pri.enable_service_message_support) {
14459 ast_mutex_lock(&pri->pri.lock);
14460 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14461 ast_mutex_unlock(&pri->pri.lock);
14462 } else {
14463 ast_cli(fd,
14464 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14465 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14466 }
14467 return CLI_SUCCESS;
14468 }
14469 }
14470 }
14471
14472
14473 ast_mutex_lock(&iflock);
14474 for (tmp = iflist; tmp; tmp = tmp->next) {
14475 if (tmp->pri && tmp->channel == channel) {
14476 ast_mutex_unlock(&iflock);
14477 ast_mutex_lock(&tmp->pri->lock);
14478 if (!tmp->pri->enable_service_message_support) {
14479 ast_mutex_unlock(&tmp->pri->lock);
14480 ast_cli(fd,
14481 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14482 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14483 return CLI_SUCCESS;
14484 }
14485 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14486 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14487 switch(changestatus) {
14488 case 0:
14489
14490 ast_db_del(db_chan_name, SRVST_DBKEY);
14491 *why &= ~SRVST_NEAREND;
14492 if (*why) {
14493 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14494 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14495 } else {
14496 dahdi_pri_update_span_devstate(tmp->pri);
14497 }
14498 break;
14499
14500 case 2:
14501
14502 ast_db_del(db_chan_name, SRVST_DBKEY);
14503 *why |= SRVST_NEAREND;
14504 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14505 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14506 dahdi_pri_update_span_devstate(tmp->pri);
14507 break;
14508
14509
14510 default:
14511 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14512 break;
14513 }
14514 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14515 ast_mutex_unlock(&tmp->pri->lock);
14516 return CLI_SUCCESS;
14517 }
14518 }
14519 ast_mutex_unlock(&iflock);
14520
14521 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14522 return CLI_FAILURE;
14523 }
14524
14525 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14526 {
14527 switch (cmd) {
14528 case CLI_INIT:
14529 e->command = "pri service enable channel";
14530 e->usage =
14531 "Usage: pri service enable channel <channel> [<interface id>]\n"
14532 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14533 " to restore a channel to service, with optional interface id\n"
14534 " as agreed upon with remote switch operator\n";
14535 return NULL;
14536 case CLI_GENERATE:
14537 return NULL;
14538 }
14539 return handle_pri_service_generic(e, cmd, a, 0);
14540 }
14541
14542 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14543 {
14544 switch (cmd) {
14545 case CLI_INIT:
14546 e->command = "pri service disable channel";
14547 e->usage =
14548 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14549 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14550 " to remove a channel from service, with optional interface id\n"
14551 " as agreed upon with remote switch operator\n";
14552 return NULL;
14553 case CLI_GENERATE:
14554 return NULL;
14555 }
14556 return handle_pri_service_generic(e, cmd, a, 2);
14557 }
14558 #endif
14559 #endif
14560
14561 #if defined(HAVE_PRI)
14562 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14563 {
14564 int span;
14565
14566 switch (cmd) {
14567 case CLI_INIT:
14568 e->command = "pri show channels";
14569 e->usage =
14570 "Usage: pri show channels\n"
14571 " Displays PRI channel information such as the current mapping\n"
14572 " of DAHDI B channels to Asterisk channel names and which calls\n"
14573 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14574 " are not associated with any B channel.\n";
14575 return NULL;
14576 case CLI_GENERATE:
14577 return NULL;
14578 }
14579
14580 if (a->argc != 3)
14581 return CLI_SHOWUSAGE;
14582
14583 sig_pri_cli_show_channels_header(a->fd);
14584 for (span = 0; span < NUM_SPANS; ++span) {
14585 if (pris[span].pri.pri) {
14586 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14587 }
14588 }
14589 return CLI_SUCCESS;
14590 }
14591 #endif
14592
14593 #if defined(HAVE_PRI)
14594 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14595 {
14596 int span;
14597
14598 switch (cmd) {
14599 case CLI_INIT:
14600 e->command = "pri show spans";
14601 e->usage =
14602 "Usage: pri show spans\n"
14603 " Displays PRI span information\n";
14604 return NULL;
14605 case CLI_GENERATE:
14606 return NULL;
14607 }
14608
14609 if (a->argc != 3)
14610 return CLI_SHOWUSAGE;
14611
14612 for (span = 0; span < NUM_SPANS; span++) {
14613 if (pris[span].pri.pri) {
14614 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14615 }
14616 }
14617 return CLI_SUCCESS;
14618 }
14619 #endif
14620
14621 #if defined(HAVE_PRI)
14622 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14623 {
14624 int span;
14625
14626 switch (cmd) {
14627 case CLI_INIT:
14628 e->command = "pri show span";
14629 e->usage =
14630 "Usage: pri show span <span>\n"
14631 " Displays PRI Information on a given PRI span\n";
14632 return NULL;
14633 case CLI_GENERATE:
14634 return complete_span_4(a->line, a->word, a->pos, a->n);
14635 }
14636
14637 if (a->argc < 4)
14638 return CLI_SHOWUSAGE;
14639 span = atoi(a->argv[3]);
14640 if ((span < 1) || (span > NUM_SPANS)) {
14641 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14642 return CLI_SUCCESS;
14643 }
14644 if (!pris[span-1].pri.pri) {
14645 ast_cli(a->fd, "No PRI running on span %d\n", span);
14646 return CLI_SUCCESS;
14647 }
14648
14649 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14650
14651 return CLI_SUCCESS;
14652 }
14653 #endif
14654
14655 #if defined(HAVE_PRI)
14656 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14657 {
14658 int x;
14659 int span;
14660 int count=0;
14661 int debug;
14662
14663 switch (cmd) {
14664 case CLI_INIT:
14665 e->command = "pri show debug";
14666 e->usage =
14667 "Usage: pri show debug\n"
14668 " Show the debug state of pri spans\n";
14669 return NULL;
14670 case CLI_GENERATE:
14671 return NULL;
14672 }
14673
14674 for (span = 0; span < NUM_SPANS; span++) {
14675 if (pris[span].pri.pri) {
14676 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14677 if (pris[span].pri.dchans[x]) {
14678 debug = pri_get_debug(pris[span].pri.dchans[x]);
14679 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" );
14680 count++;
14681 }
14682 }
14683 }
14684
14685 }
14686 ast_mutex_lock(&pridebugfdlock);
14687 if (pridebugfd >= 0)
14688 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14689 ast_mutex_unlock(&pridebugfdlock);
14690
14691 if (!count)
14692 ast_cli(a->fd, "No PRI running\n");
14693 return CLI_SUCCESS;
14694 }
14695 #endif
14696
14697 #if defined(HAVE_PRI)
14698 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14699 {
14700 switch (cmd) {
14701 case CLI_INIT:
14702 e->command = "pri show version";
14703 e->usage =
14704 "Usage: pri show version\n"
14705 "Show libpri version information\n";
14706 return NULL;
14707 case CLI_GENERATE:
14708 return NULL;
14709 }
14710
14711 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14712
14713 return CLI_SUCCESS;
14714 }
14715 #endif
14716
14717 #if defined(HAVE_PRI)
14718 static struct ast_cli_entry dahdi_pri_cli[] = {
14719 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14720 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14721 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14722 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14723 #endif
14724 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14725 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14726 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14727 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14728 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14729 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14730 };
14731 #endif
14732
14733 #ifdef HAVE_OPENR2
14734
14735 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14736 {
14737 switch (cmd) {
14738 case CLI_INIT:
14739 e->command = "mfcr2 show version";
14740 e->usage =
14741 "Usage: mfcr2 show version\n"
14742 " Shows the version of the OpenR2 library being used.\n";
14743 return NULL;
14744 case CLI_GENERATE:
14745 return NULL;
14746 }
14747 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14748 return CLI_SUCCESS;
14749 }
14750
14751 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14752 {
14753 #define FORMAT "%4s %40s\n"
14754 int i = 0;
14755 int numvariants = 0;
14756 const openr2_variant_entry_t *variants;
14757 switch (cmd) {
14758 case CLI_INIT:
14759 e->command = "mfcr2 show variants";
14760 e->usage =
14761 "Usage: mfcr2 show variants\n"
14762 " Shows the list of MFC/R2 variants supported.\n";
14763 return NULL;
14764 case CLI_GENERATE:
14765 return NULL;
14766 }
14767 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14768 ast_cli(a->fd, "Failed to get list of variants.\n");
14769 return CLI_FAILURE;
14770 }
14771 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14772 for (i = 0; i < numvariants; i++) {
14773 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14774 }
14775 return CLI_SUCCESS;
14776 #undef FORMAT
14777 }
14778
14779 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14780 {
14781 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14782 int filtertype = 0;
14783 int targetnum = 0;
14784 char channo[5];
14785 char anino[5];
14786 char dnisno[5];
14787 struct dahdi_pvt *p;
14788 openr2_context_t *r2context;
14789 openr2_variant_t r2variant;
14790 switch (cmd) {
14791 case CLI_INIT:
14792 e->command = "mfcr2 show channels [group|context]";
14793 e->usage =
14794 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14795 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14796 return NULL;
14797 case CLI_GENERATE:
14798 return NULL;
14799 }
14800 if (!((a->argc == 3) || (a->argc == 5))) {
14801 return CLI_SHOWUSAGE;
14802 }
14803 if (a->argc == 5) {
14804 if (!strcasecmp(a->argv[3], "group")) {
14805 targetnum = atoi(a->argv[4]);
14806 if ((targetnum < 0) || (targetnum > 63))
14807 return CLI_SHOWUSAGE;
14808 targetnum = 1 << targetnum;
14809 filtertype = 1;
14810 } else if (!strcasecmp(a->argv[3], "context")) {
14811 filtertype = 2;
14812 } else {
14813 return CLI_SHOWUSAGE;
14814 }
14815 }
14816 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14817 ast_mutex_lock(&iflock);
14818 for (p = iflist; p; p = p->next) {
14819 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14820 continue;
14821 }
14822 if (filtertype) {
14823 switch(filtertype) {
14824 case 1:
14825 if (p->group != targetnum) {
14826 continue;
14827 }
14828 break;
14829 case 2:
14830 if (strcasecmp(p->context, a->argv[4])) {
14831 continue;
14832 }
14833 break;
14834 default:
14835 ;
14836 }
14837 }
14838 r2context = openr2_chan_get_context(p->r2chan);
14839 r2variant = openr2_context_get_variant(r2context);
14840 snprintf(channo, sizeof(channo), "%d", p->channel);
14841 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14842 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14843 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14844 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14845 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14846 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14847 }
14848 ast_mutex_unlock(&iflock);
14849 return CLI_SUCCESS;
14850 #undef FORMAT
14851 }
14852
14853 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14854 {
14855 struct dahdi_pvt *p = NULL;
14856 int channo = 0;
14857 char *toklevel = NULL;
14858 char *saveptr = NULL;
14859 char *logval = NULL;
14860 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14861 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14862 switch (cmd) {
14863 case CLI_INIT:
14864 e->command = "mfcr2 set debug";
14865 e->usage =
14866 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14867 " Set a new logging level for the specified channel.\n"
14868 " If no channel is specified the logging level will be applied to all channels.\n";
14869 return NULL;
14870 case CLI_GENERATE:
14871 return NULL;
14872 }
14873 if (a->argc < 4) {
14874 return CLI_SHOWUSAGE;
14875 }
14876 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14877 logval = ast_strdupa(a->argv[3]);
14878 toklevel = strtok_r(logval, ",", &saveptr);
14879 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14880 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14881 return CLI_FAILURE;
14882 } else if (OR2_LOG_NOTHING == tmplevel) {
14883 loglevel = tmplevel;
14884 } else {
14885 loglevel |= tmplevel;
14886 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14887 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14888 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14889 continue;
14890 }
14891 loglevel |= tmplevel;
14892 }
14893 }
14894 ast_mutex_lock(&iflock);
14895 for (p = iflist; p; p = p->next) {
14896 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14897 continue;
14898 }
14899 if ((channo != -1) && (p->channel != channo )) {
14900 continue;
14901 }
14902 openr2_chan_set_log_level(p->r2chan, loglevel);
14903 if (channo != -1) {
14904 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14905 break;
14906 }
14907 }
14908 if ((channo != -1) && !p) {
14909 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14910 }
14911 if (channo == -1) {
14912 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14913 }
14914 ast_mutex_unlock(&iflock);
14915 return CLI_SUCCESS;
14916 }
14917
14918 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14919 {
14920 struct dahdi_pvt *p = NULL;
14921 int channo = 0;
14922 switch (cmd) {
14923 case CLI_INIT:
14924 e->command = "mfcr2 call files [on|off]";
14925 e->usage =
14926 "Usage: mfcr2 call files [on|off] <channel>\n"
14927 " Enable call files creation on the specified channel.\n"
14928 " If no channel is specified call files creation policy will be applied to all channels.\n";
14929 return NULL;
14930 case CLI_GENERATE:
14931 return NULL;
14932 }
14933 if (a->argc < 4) {
14934 return CLI_SHOWUSAGE;
14935 }
14936 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14937 ast_mutex_lock(&iflock);
14938 for (p = iflist; p; p = p->next) {
14939 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14940 continue;
14941 }
14942 if ((channo != -1) && (p->channel != channo )) {
14943 continue;
14944 }
14945 if (ast_true(a->argv[3])) {
14946 openr2_chan_enable_call_files(p->r2chan);
14947 } else {
14948 openr2_chan_disable_call_files(p->r2chan);
14949 }
14950 if (channo != -1) {
14951 if (ast_true(a->argv[3])) {
14952 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14953 } else {
14954 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14955 }
14956 break;
14957 }
14958 }
14959 if ((channo != -1) && !p) {
14960 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14961 }
14962 if (channo == -1) {
14963 if (ast_true(a->argv[3])) {
14964 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14965 } else {
14966 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14967 }
14968 }
14969 ast_mutex_unlock(&iflock);
14970 return CLI_SUCCESS;
14971 }
14972
14973 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14974 {
14975 struct dahdi_pvt *p = NULL;
14976 int channo = 0;
14977 switch (cmd) {
14978 case CLI_INIT:
14979 e->command = "mfcr2 set idle";
14980 e->usage =
14981 "Usage: mfcr2 set idle <channel>\n"
14982 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14983 " Force the given channel into IDLE state.\n"
14984 " If no channel is specified, all channels will be set to IDLE.\n";
14985 return NULL;
14986 case CLI_GENERATE:
14987 return NULL;
14988 }
14989 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14990 ast_mutex_lock(&iflock);
14991 for (p = iflist; p; p = p->next) {
14992 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14993 continue;
14994 }
14995 if ((channo != -1) && (p->channel != channo )) {
14996 continue;
14997 }
14998 openr2_chan_set_idle(p->r2chan);
14999 ast_mutex_lock(&p->lock);
15000 p->locallyblocked = 0;
15001 p->mfcr2call = 0;
15002 ast_mutex_unlock(&p->lock);
15003 if (channo != -1) {
15004 break;
15005 }
15006 }
15007 if ((channo != -1) && !p) {
15008 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15009 }
15010 ast_mutex_unlock(&iflock);
15011 return CLI_SUCCESS;
15012 }
15013
15014 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15015 {
15016 struct dahdi_pvt *p = NULL;
15017 int channo = 0;
15018 switch (cmd) {
15019 case CLI_INIT:
15020 e->command = "mfcr2 set blocked";
15021 e->usage =
15022 "Usage: mfcr2 set blocked <channel>\n"
15023 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15024 " Force the given channel into BLOCKED state.\n"
15025 " If no channel is specified, all channels will be set to BLOCKED.\n";
15026 return NULL;
15027 case CLI_GENERATE:
15028 return NULL;
15029 }
15030 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15031 ast_mutex_lock(&iflock);
15032 for (p = iflist; p; p = p->next) {
15033 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15034 continue;
15035 }
15036 if ((channo != -1) && (p->channel != channo )) {
15037 continue;
15038 }
15039 openr2_chan_set_blocked(p->r2chan);
15040 ast_mutex_lock(&p->lock);
15041 p->locallyblocked = 1;
15042 ast_mutex_unlock(&p->lock);
15043 if (channo != -1) {
15044 break;
15045 }
15046 }
15047 if ((channo != -1) && !p) {
15048 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15049 }
15050 ast_mutex_unlock(&iflock);
15051 return CLI_SUCCESS;
15052 }
15053
15054 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15055 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15056 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15057 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15058 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15059 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15060 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15061 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15062 };
15063
15064 #endif
15065
15066 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15067 {
15068 int channel;
15069 int ret;
15070 switch (cmd) {
15071 case CLI_INIT:
15072 e->command = "dahdi destroy channel";
15073 e->usage =
15074 "Usage: dahdi destroy channel <chan num>\n"
15075 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15076 return NULL;
15077 case CLI_GENERATE:
15078 return NULL;
15079 }
15080 if (a->argc != 4)
15081 return CLI_SHOWUSAGE;
15082
15083 channel = atoi(a->argv[3]);
15084 ret = dahdi_destroy_channel_bynum(channel);
15085 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15086 }
15087
15088 static void dahdi_softhangup_all(void)
15089 {
15090 struct dahdi_pvt *p;
15091 retry:
15092 ast_mutex_lock(&iflock);
15093 for (p = iflist; p; p = p->next) {
15094 ast_mutex_lock(&p->lock);
15095 if (p->owner && !p->restartpending) {
15096 if (ast_channel_trylock(p->owner)) {
15097 if (option_debug > 2)
15098 ast_verbose("Avoiding deadlock\n");
15099
15100 ast_mutex_unlock(&p->lock);
15101 ast_mutex_unlock(&iflock);
15102 goto retry;
15103 }
15104 if (option_debug > 2)
15105 ast_verbose("Softhanging up on %s\n", p->owner->name);
15106 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15107 p->restartpending = 1;
15108 num_restart_pending++;
15109 ast_channel_unlock(p->owner);
15110 }
15111 ast_mutex_unlock(&p->lock);
15112 }
15113 ast_mutex_unlock(&iflock);
15114 }
15115
15116 static int setup_dahdi(int reload);
15117 static int dahdi_restart(void)
15118 {
15119 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15120 int i, j;
15121 #endif
15122 int cancel_code;
15123 struct dahdi_pvt *p;
15124
15125 ast_mutex_lock(&restart_lock);
15126 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15127 dahdi_softhangup_all();
15128 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15129 #ifdef HAVE_OPENR2
15130 dahdi_r2_destroy_links();
15131 #endif
15132
15133 #if defined(HAVE_PRI)
15134 for (i = 0; i < NUM_SPANS; i++) {
15135 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15136 cancel_code = pthread_cancel(pris[i].pri.master);
15137 pthread_kill(pris[i].pri.master, SIGURG);
15138 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);
15139 pthread_join(pris[i].pri.master, NULL);
15140 ast_debug(4, "Joined thread of span %d\n", i);
15141 }
15142 }
15143 #endif
15144
15145 #if defined(HAVE_SS7)
15146 for (i = 0; i < NUM_SPANS; i++) {
15147 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15148 cancel_code = pthread_cancel(linksets[i].ss7.master);
15149 pthread_kill(linksets[i].ss7.master, SIGURG);
15150 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);
15151 pthread_join(linksets[i].ss7.master, NULL);
15152 ast_debug(4, "Joined thread of span %d\n", i);
15153 }
15154 }
15155 #endif
15156
15157 ast_mutex_lock(&monlock);
15158 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15159 cancel_code = pthread_cancel(monitor_thread);
15160 pthread_kill(monitor_thread, SIGURG);
15161 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15162 pthread_join(monitor_thread, NULL);
15163 ast_debug(4, "Joined monitor thread\n");
15164 }
15165 monitor_thread = AST_PTHREADT_NULL;
15166
15167 ast_mutex_lock(&ss_thread_lock);
15168 while (ss_thread_count > 0) {
15169 int x = DAHDI_FLASH;
15170 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15171
15172 ast_mutex_lock(&iflock);
15173 for (p = iflist; p; p = p->next) {
15174 if (p->owner) {
15175
15176 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15177 }
15178 }
15179 ast_mutex_unlock(&iflock);
15180 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15181 }
15182
15183
15184 dahdi_softhangup_all();
15185 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15186 destroy_all_channels();
15187 memset(round_robin, 0, sizeof(round_robin));
15188 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15189
15190 ast_mutex_unlock(&monlock);
15191
15192 #ifdef HAVE_PRI
15193 for (i = 0; i < NUM_SPANS; i++) {
15194 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15195 dahdi_close_pri_fd(&(pris[i]), j);
15196 }
15197
15198 memset(pris, 0, sizeof(pris));
15199 for (i = 0; i < NUM_SPANS; i++) {
15200 sig_pri_init_pri(&pris[i].pri);
15201 }
15202 pri_set_error(dahdi_pri_error);
15203 pri_set_message(dahdi_pri_message);
15204 #endif
15205 #if defined(HAVE_SS7)
15206 for (i = 0; i < NUM_SPANS; i++) {
15207 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15208 dahdi_close_ss7_fd(&(linksets[i]), j);
15209 }
15210
15211 memset(linksets, 0, sizeof(linksets));
15212 for (i = 0; i < NUM_SPANS; i++) {
15213 sig_ss7_init_linkset(&linksets[i].ss7);
15214 }
15215 ss7_set_error(dahdi_ss7_error);
15216 ss7_set_message(dahdi_ss7_message);
15217 #endif
15218
15219 if (setup_dahdi(2) != 0) {
15220 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15221 ast_mutex_unlock(&ss_thread_lock);
15222 return 1;
15223 }
15224 ast_mutex_unlock(&ss_thread_lock);
15225 ast_mutex_unlock(&restart_lock);
15226 return 0;
15227 }
15228
15229 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15230 {
15231 switch (cmd) {
15232 case CLI_INIT:
15233 e->command = "dahdi restart";
15234 e->usage =
15235 "Usage: dahdi restart\n"
15236 " Restarts the DAHDI channels: destroys them all and then\n"
15237 " re-reads them from chan_dahdi.conf.\n"
15238 " Note that this will STOP any running CALL on DAHDI channels.\n"
15239 "";
15240 return NULL;
15241 case CLI_GENERATE:
15242 return NULL;
15243 }
15244 if (a->argc != 2)
15245 return CLI_SHOWUSAGE;
15246
15247 if (dahdi_restart() != 0)
15248 return CLI_FAILURE;
15249 return CLI_SUCCESS;
15250 }
15251
15252 static int action_dahdirestart(struct mansession *s, const struct message *m)
15253 {
15254 if (dahdi_restart() != 0) {
15255 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15256 return 1;
15257 }
15258 astman_send_ack(s, m, "DAHDIRestart: Success");
15259 return 0;
15260 }
15261
15262 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15263 {
15264 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15265 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15266 ast_group_t targetnum = 0;
15267 int filtertype = 0;
15268 struct dahdi_pvt *tmp = NULL;
15269 char tmps[20] = "";
15270 char statestr[20] = "";
15271 char blockstr[20] = "";
15272
15273 switch (cmd) {
15274 case CLI_INIT:
15275 e->command = "dahdi show channels [group|context]";
15276 e->usage =
15277 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15278 " Shows a list of available channels with optional filtering\n"
15279 " <group> must be a number between 0 and 63\n";
15280 return NULL;
15281 case CLI_GENERATE:
15282 return NULL;
15283 }
15284
15285
15286
15287 if (!((a->argc == 3) || (a->argc == 5)))
15288 return CLI_SHOWUSAGE;
15289
15290 if (a->argc == 5) {
15291 if (!strcasecmp(a->argv[3], "group")) {
15292 targetnum = atoi(a->argv[4]);
15293 if (63 < targetnum) {
15294 return CLI_SHOWUSAGE;
15295 }
15296 targetnum = ((ast_group_t) 1) << targetnum;
15297 filtertype = 1;
15298 } else if (!strcasecmp(a->argv[3], "context")) {
15299 filtertype = 2;
15300 }
15301 }
15302
15303 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15304 ast_mutex_lock(&iflock);
15305 for (tmp = iflist; tmp; tmp = tmp->next) {
15306 if (filtertype) {
15307 switch(filtertype) {
15308 case 1:
15309 if (!(tmp->group & targetnum)) {
15310 continue;
15311 }
15312 break;
15313 case 2:
15314 if (strcasecmp(tmp->context, a->argv[4])) {
15315 continue;
15316 }
15317 break;
15318 default:
15319 break;
15320 }
15321 }
15322 if (tmp->channel > 0) {
15323 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15324 } else
15325 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15326
15327 if (tmp->locallyblocked)
15328 blockstr[0] = 'L';
15329 else
15330 blockstr[0] = ' ';
15331
15332 if (tmp->remotelyblocked)
15333 blockstr[1] = 'R';
15334 else
15335 blockstr[1] = ' ';
15336
15337 blockstr[2] = '\0';
15338
15339 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15340
15341 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15342 }
15343 ast_mutex_unlock(&iflock);
15344 return CLI_SUCCESS;
15345 #undef FORMAT
15346 #undef FORMAT2
15347 }
15348
15349 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15350 {
15351 int channel;
15352 struct dahdi_pvt *tmp = NULL;
15353 struct dahdi_confinfo ci;
15354 struct dahdi_params ps;
15355 int x;
15356
15357 switch (cmd) {
15358 case CLI_INIT:
15359 e->command = "dahdi show channel";
15360 e->usage =
15361 "Usage: dahdi show channel <chan num>\n"
15362 " Detailed information about a given channel\n";
15363 return NULL;
15364 case CLI_GENERATE:
15365 return NULL;
15366 }
15367
15368 if (a->argc != 4)
15369 return CLI_SHOWUSAGE;
15370
15371 channel = atoi(a->argv[3]);
15372
15373 ast_mutex_lock(&iflock);
15374 for (tmp = iflist; tmp; tmp = tmp->next) {
15375 if (tmp->channel == channel) {
15376 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15377 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15378 ast_cli(a->fd, "Span: %d\n", tmp->span);
15379 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15380 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15381 ast_cli(a->fd, "Context: %s\n", tmp->context);
15382 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15383 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15384 #if defined(HAVE_PRI)
15385 #if defined(HAVE_PRI_SUBADDR)
15386 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15387 #endif
15388 #endif
15389 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15390 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15391 if (tmp->vars) {
15392 struct ast_variable *v;
15393 ast_cli(a->fd, "Variables:\n");
15394 for (v = tmp->vars ; v ; v = v->next)
15395 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15396 }
15397 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15398 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15399 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15400 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15401 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15402 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)" : "");
15403 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)" : "");
15404 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)" : "");
15405 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15406 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15407 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15408 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15409 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15410 if (tmp->busydetect) {
15411 #if defined(BUSYDETECT_TONEONLY)
15412 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15413 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15414 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15415 #endif
15416 #ifdef BUSYDETECT_DEBUG
15417 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15418 #endif
15419 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15420 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15421 }
15422 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15423 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15424 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15425 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15426 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15427 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15428 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15429 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15430 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15431 ast_cli(a->fd, "Echo Cancellation:\n");
15432
15433 if (tmp->echocancel.head.tap_length) {
15434 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15435 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15436 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15437 }
15438 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15439 } else {
15440 ast_cli(a->fd, "\tnone\n");
15441 }
15442 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15443 if (tmp->master)
15444 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15445 for (x = 0; x < MAX_SLAVES; x++) {
15446 if (tmp->slaves[x])
15447 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15448 }
15449 #ifdef HAVE_OPENR2
15450 if (tmp->mfcr2) {
15451 char calldir[OR2_MAX_PATH];
15452 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15453 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15454 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15455 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15456 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15457 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15458 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15459 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15460 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15461 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15462 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15463 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15464 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15465 #endif
15466 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15467 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15468 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15469 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15470 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15471 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15472 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15473 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15474 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15475 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15476 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15477 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15478 }
15479 #endif
15480 #if defined(HAVE_SS7)
15481 if (tmp->ss7) {
15482 struct sig_ss7_chan *chan = tmp->sig_pvt;
15483
15484 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15485 }
15486 #endif
15487 #ifdef HAVE_PRI
15488 if (tmp->pri) {
15489 struct sig_pri_chan *chan = tmp->sig_pvt;
15490
15491 ast_cli(a->fd, "PRI Flags: ");
15492 if (chan->resetting != SIG_PRI_RESET_IDLE) {
15493 ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15494 }
15495 if (chan->call)
15496 ast_cli(a->fd, "Call ");
15497 if (chan->allocated) {
15498 ast_cli(a->fd, "Allocated ");
15499 }
15500 ast_cli(a->fd, "\n");
15501 if (tmp->logicalspan)
15502 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15503 else
15504 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15505 }
15506 #endif
15507 memset(&ci, 0, sizeof(ci));
15508 ps.channo = tmp->channel;
15509 if (tmp->subs[SUB_REAL].dfd > -1) {
15510 memset(&ci, 0, sizeof(ci));
15511 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15512 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15513 }
15514 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15515 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15516 }
15517 memset(&ps, 0, sizeof(ps));
15518 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15519 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15520 } else {
15521 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15522 }
15523 }
15524 ast_mutex_unlock(&iflock);
15525 return CLI_SUCCESS;
15526 }
15527 }
15528 ast_mutex_unlock(&iflock);
15529
15530 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15531 return CLI_FAILURE;
15532 }
15533
15534 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15535 {
15536 int i, j;
15537 switch (cmd) {
15538 case CLI_INIT:
15539 e->command = "dahdi show cadences";
15540 e->usage =
15541 "Usage: dahdi show cadences\n"
15542 " Shows all cadences currently defined\n";
15543 return NULL;
15544 case CLI_GENERATE:
15545 return NULL;
15546 }
15547 for (i = 0; i < num_cadence; i++) {
15548 char output[1024];
15549 char tmp[16], tmp2[64];
15550 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15551 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15552
15553 for (j = 0; j < 16; j++) {
15554 if (cadences[i].ringcadence[j] == 0)
15555 break;
15556 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15557 if (cidrings[i] * 2 - 1 == j)
15558 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15559 else
15560 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15561 if (j != 0)
15562 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15563 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15564 }
15565 ast_cli(a->fd,"%s\n",output);
15566 }
15567 return CLI_SUCCESS;
15568 }
15569
15570
15571 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15572 {
15573 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15574 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15575 int span;
15576 int res;
15577 char alarmstr[50];
15578
15579 int ctl;
15580 struct dahdi_spaninfo s;
15581
15582 switch (cmd) {
15583 case CLI_INIT:
15584 e->command = "dahdi show status";
15585 e->usage =
15586 "Usage: dahdi show status\n"
15587 " Shows a list of DAHDI cards with status\n";
15588 return NULL;
15589 case CLI_GENERATE:
15590 return NULL;
15591 }
15592 ctl = open("/dev/dahdi/ctl", O_RDWR);
15593 if (ctl < 0) {
15594 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15595 return CLI_FAILURE;
15596 }
15597 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15598
15599 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15600 s.spanno = span;
15601 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15602 if (res) {
15603 continue;
15604 }
15605 alarmstr[0] = '\0';
15606 if (s.alarms > 0) {
15607 if (s.alarms & DAHDI_ALARM_BLUE)
15608 strcat(alarmstr, "BLU/");
15609 if (s.alarms & DAHDI_ALARM_YELLOW)
15610 strcat(alarmstr, "YEL/");
15611 if (s.alarms & DAHDI_ALARM_RED)
15612 strcat(alarmstr, "RED/");
15613 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15614 strcat(alarmstr, "LB/");
15615 if (s.alarms & DAHDI_ALARM_RECOVER)
15616 strcat(alarmstr, "REC/");
15617 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15618 strcat(alarmstr, "NOP/");
15619 if (!strlen(alarmstr))
15620 strcat(alarmstr, "UUU/");
15621 if (strlen(alarmstr)) {
15622
15623 alarmstr[strlen(alarmstr) - 1] = '\0';
15624 }
15625 } else {
15626 if (s.numchans)
15627 strcpy(alarmstr, "OK");
15628 else
15629 strcpy(alarmstr, "UNCONFIGURED");
15630 }
15631
15632 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15633 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15634 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15635 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15636 "CAS",
15637 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15638 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15639 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15640 "Unk",
15641 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15642 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15643 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15644 lbostr[s.lbo]
15645 );
15646 }
15647 close(ctl);
15648
15649 return CLI_SUCCESS;
15650 #undef FORMAT
15651 #undef FORMAT2
15652 }
15653
15654 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15655 {
15656 int pseudo_fd = -1;
15657 struct dahdi_versioninfo vi;
15658
15659 switch (cmd) {
15660 case CLI_INIT:
15661 e->command = "dahdi show version";
15662 e->usage =
15663 "Usage: dahdi show version\n"
15664 " Shows the DAHDI version in use\n";
15665 return NULL;
15666 case CLI_GENERATE:
15667 return NULL;
15668 }
15669 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15670 ast_cli(a->fd, "Failed to open control file to get version.\n");
15671 return CLI_SUCCESS;
15672 }
15673
15674 strcpy(vi.version, "Unknown");
15675 strcpy(vi.echo_canceller, "Unknown");
15676
15677 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15678 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15679 else
15680 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15681
15682 close(pseudo_fd);
15683
15684 return CLI_SUCCESS;
15685 }
15686
15687 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15688 {
15689 int channel;
15690 int gain;
15691 int tx;
15692 struct dahdi_hwgain hwgain;
15693 struct dahdi_pvt *tmp = NULL;
15694
15695 switch (cmd) {
15696 case CLI_INIT:
15697 e->command = "dahdi set hwgain {rx|tx}";
15698 e->usage =
15699 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15700 " Sets the hardware gain on a given channel. Changes take effect\n"
15701 " immediately whether the channel is in use or not.\n"
15702 "\n"
15703 " <rx|tx> which direction do you want to change (relative to our module)\n"
15704 " <chan num> is the channel number relative to the device\n"
15705 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15706 "\n"
15707 " Please note:\n"
15708 " * This is currently the only way to set hwgain by the channel driver.\n"
15709 " * hwgain is only supportable by hardware with analog ports because\n"
15710 " hwgain works on the analog side of an analog-digital conversion.\n";
15711 return NULL;
15712 case CLI_GENERATE:
15713 return NULL;
15714 }
15715
15716 if (a->argc != 6)
15717 return CLI_SHOWUSAGE;
15718
15719 if (!strcasecmp("rx", a->argv[3]))
15720 tx = 0;
15721 else if (!strcasecmp("tx", a->argv[3]))
15722 tx = 1;
15723 else
15724 return CLI_SHOWUSAGE;
15725
15726 channel = atoi(a->argv[4]);
15727 gain = atof(a->argv[5])*10.0;
15728
15729 ast_mutex_lock(&iflock);
15730
15731 for (tmp = iflist; tmp; tmp = tmp->next) {
15732
15733 if (tmp->channel != channel)
15734 continue;
15735
15736 if (tmp->subs[SUB_REAL].dfd == -1)
15737 break;
15738
15739 hwgain.newgain = gain;
15740 hwgain.tx = tx;
15741 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15742 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15743 ast_mutex_unlock(&iflock);
15744 return CLI_FAILURE;
15745 }
15746 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15747 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15748 break;
15749 }
15750
15751 ast_mutex_unlock(&iflock);
15752
15753 if (tmp)
15754 return CLI_SUCCESS;
15755
15756 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15757 return CLI_FAILURE;
15758
15759 }
15760
15761 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15762 {
15763 int channel;
15764 float gain;
15765 int tx;
15766 int res;
15767 struct dahdi_pvt *tmp = NULL;
15768
15769 switch (cmd) {
15770 case CLI_INIT:
15771 e->command = "dahdi set swgain {rx|tx}";
15772 e->usage =
15773 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15774 " Sets the software gain on a given channel and overrides the\n"
15775 " value provided at module loadtime. Changes take effect\n"
15776 " immediately whether the channel is in use or not.\n"
15777 "\n"
15778 " <rx|tx> which direction do you want to change (relative to our module)\n"
15779 " <chan num> is the channel number relative to the device\n"
15780 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15781 return NULL;
15782 case CLI_GENERATE:
15783 return NULL;
15784 }
15785
15786 if (a->argc != 6)
15787 return CLI_SHOWUSAGE;
15788
15789 if (!strcasecmp("rx", a->argv[3]))
15790 tx = 0;
15791 else if (!strcasecmp("tx", a->argv[3]))
15792 tx = 1;
15793 else
15794 return CLI_SHOWUSAGE;
15795
15796 channel = atoi(a->argv[4]);
15797 gain = atof(a->argv[5]);
15798
15799 ast_mutex_lock(&iflock);
15800 for (tmp = iflist; tmp; tmp = tmp->next) {
15801
15802 if (tmp->channel != channel)
15803 continue;
15804
15805 if (tmp->subs[SUB_REAL].dfd == -1)
15806 break;
15807
15808 if (tx)
15809 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15810 else
15811 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15812
15813 if (res) {
15814 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15815 ast_mutex_unlock(&iflock);
15816 return CLI_FAILURE;
15817 }
15818
15819 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15820 tx ? "tx" : "rx", gain, channel);
15821
15822 if (tx) {
15823 tmp->txgain = gain;
15824 } else {
15825 tmp->rxgain = gain;
15826 }
15827 break;
15828 }
15829 ast_mutex_unlock(&iflock);
15830
15831 if (tmp)
15832 return CLI_SUCCESS;
15833
15834 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15835 return CLI_FAILURE;
15836
15837 }
15838
15839 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15840 {
15841 int channel;
15842 int on;
15843 struct dahdi_pvt *dahdi_chan = NULL;
15844
15845 switch (cmd) {
15846 case CLI_INIT:
15847 e->command = "dahdi set dnd";
15848 e->usage =
15849 "Usage: dahdi set dnd <chan#> <on|off>\n"
15850 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15851 " Changes take effect immediately.\n"
15852 " <chan num> is the channel number\n"
15853 " <on|off> Enable or disable DND mode?\n"
15854 ;
15855 return NULL;
15856 case CLI_GENERATE:
15857 return NULL;
15858 }
15859
15860 if (a->argc != 5)
15861 return CLI_SHOWUSAGE;
15862
15863 if ((channel = atoi(a->argv[3])) <= 0) {
15864 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15865 return CLI_SHOWUSAGE;
15866 }
15867
15868 if (ast_true(a->argv[4]))
15869 on = 1;
15870 else if (ast_false(a->argv[4]))
15871 on = 0;
15872 else {
15873 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15874 return CLI_SHOWUSAGE;
15875 }
15876
15877 ast_mutex_lock(&iflock);
15878 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15879 if (dahdi_chan->channel != channel)
15880 continue;
15881
15882
15883 dahdi_dnd(dahdi_chan, on);
15884 break;
15885 }
15886 ast_mutex_unlock(&iflock);
15887
15888 if (!dahdi_chan) {
15889 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15890 return CLI_FAILURE;
15891 }
15892
15893 return CLI_SUCCESS;
15894 }
15895
15896 static struct ast_cli_entry dahdi_cli[] = {
15897 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15898 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15899 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15900 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15901 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15902 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15903 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15904 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15905 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15906 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15907 };
15908
15909 #define TRANSFER 0
15910 #define HANGUP 1
15911
15912 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15913 {
15914 if (p) {
15915 switch (mode) {
15916 case TRANSFER:
15917 p->fake_event = DAHDI_EVENT_WINKFLASH;
15918 break;
15919 case HANGUP:
15920 p->fake_event = DAHDI_EVENT_ONHOOK;
15921 break;
15922 default:
15923 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15924 }
15925 }
15926 return 0;
15927 }
15928 static struct dahdi_pvt *find_channel(int channel)
15929 {
15930 struct dahdi_pvt *p;
15931
15932 ast_mutex_lock(&iflock);
15933 for (p = iflist; p; p = p->next) {
15934 if (p->channel == channel) {
15935 break;
15936 }
15937 }
15938 ast_mutex_unlock(&iflock);
15939 return p;
15940 }
15941
15942
15943
15944
15945
15946
15947
15948
15949
15950
15951 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15952 {
15953 int chan_num;
15954
15955 if (sscanf(channel, "%30d", &chan_num) != 1) {
15956
15957 return NULL;
15958 }
15959
15960 return find_channel(chan_num);
15961 }
15962
15963 static int action_dahdidndon(struct mansession *s, const struct message *m)
15964 {
15965 struct dahdi_pvt *p;
15966 const char *channel = astman_get_header(m, "DAHDIChannel");
15967
15968 if (ast_strlen_zero(channel)) {
15969 astman_send_error(s, m, "No channel specified");
15970 return 0;
15971 }
15972 p = find_channel_from_str(channel);
15973 if (!p) {
15974 astman_send_error(s, m, "No such channel");
15975 return 0;
15976 }
15977 dahdi_dnd(p, 1);
15978 astman_send_ack(s, m, "DND Enabled");
15979 return 0;
15980 }
15981
15982 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15983 {
15984 struct dahdi_pvt *p;
15985 const char *channel = astman_get_header(m, "DAHDIChannel");
15986
15987 if (ast_strlen_zero(channel)) {
15988 astman_send_error(s, m, "No channel specified");
15989 return 0;
15990 }
15991 p = find_channel_from_str(channel);
15992 if (!p) {
15993 astman_send_error(s, m, "No such channel");
15994 return 0;
15995 }
15996 dahdi_dnd(p, 0);
15997 astman_send_ack(s, m, "DND Disabled");
15998 return 0;
15999 }
16000
16001 static int action_transfer(struct mansession *s, const struct message *m)
16002 {
16003 struct dahdi_pvt *p;
16004 const char *channel = astman_get_header(m, "DAHDIChannel");
16005
16006 if (ast_strlen_zero(channel)) {
16007 astman_send_error(s, m, "No channel specified");
16008 return 0;
16009 }
16010 p = find_channel_from_str(channel);
16011 if (!p) {
16012 astman_send_error(s, m, "No such channel");
16013 return 0;
16014 }
16015 if (!analog_lib_handles(p->sig, 0, 0)) {
16016 astman_send_error(s, m, "Channel signaling is not analog");
16017 return 0;
16018 }
16019 dahdi_fake_event(p,TRANSFER);
16020 astman_send_ack(s, m, "DAHDITransfer");
16021 return 0;
16022 }
16023
16024 static int action_transferhangup(struct mansession *s, const struct message *m)
16025 {
16026 struct dahdi_pvt *p;
16027 const char *channel = astman_get_header(m, "DAHDIChannel");
16028
16029 if (ast_strlen_zero(channel)) {
16030 astman_send_error(s, m, "No channel specified");
16031 return 0;
16032 }
16033 p = find_channel_from_str(channel);
16034 if (!p) {
16035 astman_send_error(s, m, "No such channel");
16036 return 0;
16037 }
16038 if (!analog_lib_handles(p->sig, 0, 0)) {
16039 astman_send_error(s, m, "Channel signaling is not analog");
16040 return 0;
16041 }
16042 dahdi_fake_event(p,HANGUP);
16043 astman_send_ack(s, m, "DAHDIHangup");
16044 return 0;
16045 }
16046
16047 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16048 {
16049 struct dahdi_pvt *p;
16050 const char *channel = astman_get_header(m, "DAHDIChannel");
16051 const char *number = astman_get_header(m, "Number");
16052 int i;
16053
16054 if (ast_strlen_zero(channel)) {
16055 astman_send_error(s, m, "No channel specified");
16056 return 0;
16057 }
16058 if (ast_strlen_zero(number)) {
16059 astman_send_error(s, m, "No number specified");
16060 return 0;
16061 }
16062 p = find_channel_from_str(channel);
16063 if (!p) {
16064 astman_send_error(s, m, "No such channel");
16065 return 0;
16066 }
16067 if (!p->owner) {
16068 astman_send_error(s, m, "Channel does not have it's owner");
16069 return 0;
16070 }
16071 for (i = 0; i < strlen(number); i++) {
16072 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16073 dahdi_queue_frame(p, &f);
16074 }
16075 astman_send_ack(s, m, "DAHDIDialOffhook");
16076 return 0;
16077 }
16078
16079 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16080 {
16081 struct dahdi_pvt *tmp = NULL;
16082 const char *id = astman_get_header(m, "ActionID");
16083 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16084 char idText[256] = "";
16085 int channels = 0;
16086 int dahdichanquery;
16087
16088 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16089
16090 dahdichanquery = -1;
16091 }
16092
16093 astman_send_ack(s, m, "DAHDI channel status will follow");
16094 if (!ast_strlen_zero(id))
16095 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16096
16097 ast_mutex_lock(&iflock);
16098
16099 for (tmp = iflist; tmp; tmp = tmp->next) {
16100 if (tmp->channel > 0) {
16101 int alm;
16102
16103
16104 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16105 continue;
16106
16107 alm = get_alarms(tmp);
16108 channels++;
16109 if (tmp->owner) {
16110
16111 astman_append(s,
16112 "Event: DAHDIShowChannels\r\n"
16113 "DAHDIChannel: %d\r\n"
16114 "Channel: %s\r\n"
16115 "Uniqueid: %s\r\n"
16116 "AccountCode: %s\r\n"
16117 "Signalling: %s\r\n"
16118 "SignallingCode: %d\r\n"
16119 "Context: %s\r\n"
16120 "DND: %s\r\n"
16121 "Alarm: %s\r\n"
16122 "%s"
16123 "\r\n",
16124 tmp->channel,
16125 tmp->owner->name,
16126 tmp->owner->uniqueid,
16127 tmp->owner->accountcode,
16128 sig2str(tmp->sig),
16129 tmp->sig,
16130 tmp->context,
16131 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16132 alarm2str(alm), idText);
16133 } else {
16134 astman_append(s,
16135 "Event: DAHDIShowChannels\r\n"
16136 "DAHDIChannel: %d\r\n"
16137 "Signalling: %s\r\n"
16138 "SignallingCode: %d\r\n"
16139 "Context: %s\r\n"
16140 "DND: %s\r\n"
16141 "Alarm: %s\r\n"
16142 "%s"
16143 "\r\n",
16144 tmp->channel, sig2str(tmp->sig), tmp->sig,
16145 tmp->context,
16146 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16147 alarm2str(alm), idText);
16148 }
16149 }
16150 }
16151
16152 ast_mutex_unlock(&iflock);
16153
16154 astman_append(s,
16155 "Event: DAHDIShowChannelsComplete\r\n"
16156 "%s"
16157 "Items: %d\r\n"
16158 "\r\n",
16159 idText,
16160 channels);
16161 return 0;
16162 }
16163
16164 #if defined(HAVE_SS7)
16165 static int linkset_addsigchan(int sigchan)
16166 {
16167 struct dahdi_ss7 *link;
16168 int res;
16169 int curfd;
16170 struct dahdi_params params;
16171 struct dahdi_bufferinfo bi;
16172 struct dahdi_spaninfo si;
16173
16174 if (sigchan < 0) {
16175 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16176 return -1;
16177 }
16178 if (cur_ss7type < 0) {
16179 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16180 return -1;
16181 }
16182 if (cur_pointcode < 0) {
16183 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16184 return -1;
16185 }
16186 if (cur_adjpointcode < 0) {
16187 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16188 return -1;
16189 }
16190 if (cur_defaultdpc < 0) {
16191 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16192 return -1;
16193 }
16194 if (cur_networkindicator < 0) {
16195 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16196 return -1;
16197 }
16198 link = ss7_resolve_linkset(cur_linkset);
16199 if (!link) {
16200 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16201 return -1;
16202 }
16203 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16204 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16205 return -1;
16206 }
16207
16208 curfd = link->ss7.numsigchans;
16209
16210
16211 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16212 if (link->ss7.fds[curfd] < 0) {
16213 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16214 strerror(errno));
16215 return -1;
16216 }
16217 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16218 dahdi_close_ss7_fd(link, curfd);
16219 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16220 strerror(errno));
16221 return -1;
16222 }
16223
16224
16225 memset(¶ms, 0, sizeof(params));
16226 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16227 if (res) {
16228 dahdi_close_ss7_fd(link, curfd);
16229 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16230 strerror(errno));
16231 return -1;
16232 }
16233 if (params.sigtype != DAHDI_SIG_HDLCFCS
16234 && params.sigtype != DAHDI_SIG_HARDHDLC
16235 && params.sigtype != DAHDI_SIG_MTP2) {
16236 dahdi_close_ss7_fd(link, curfd);
16237 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16238 return -1;
16239 }
16240
16241
16242 memset(&bi, 0, sizeof(bi));
16243 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16244 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16245 bi.numbufs = 32;
16246 bi.bufsize = 512;
16247 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16248 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16249 sigchan, strerror(errno));
16250 dahdi_close_ss7_fd(link, curfd);
16251 return -1;
16252 }
16253
16254
16255 memset(&si, 0, sizeof(si));
16256 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16257 if (res) {
16258 dahdi_close_ss7_fd(link, curfd);
16259 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16260 strerror(errno));
16261 }
16262
16263 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16264 (params.sigtype == DAHDI_SIG_MTP2)
16265 ? SS7_TRANSPORT_DAHDIMTP2
16266 : SS7_TRANSPORT_DAHDIDCHAN,
16267 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16268 if (res) {
16269 dahdi_close_ss7_fd(link, curfd);
16270 return -1;
16271 }
16272
16273 ++link->ss7.numsigchans;
16274
16275 return 0;
16276 }
16277 #endif
16278
16279 #if defined(HAVE_SS7)
16280 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16281 {
16282 int span;
16283 switch (cmd) {
16284 case CLI_INIT:
16285 e->command = "ss7 set debug {on|off} linkset";
16286 e->usage =
16287 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16288 " Enables debugging on a given SS7 linkset\n";
16289 return NULL;
16290 case CLI_GENERATE:
16291 return NULL;
16292 }
16293 if (a->argc < 6)
16294 return CLI_SHOWUSAGE;
16295 span = atoi(a->argv[5]);
16296 if ((span < 1) || (span > NUM_SPANS)) {
16297 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16298 return CLI_SUCCESS;
16299 }
16300 if (!linksets[span-1].ss7.ss7) {
16301 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16302 } else {
16303 if (!strcasecmp(a->argv[3], "on")) {
16304 linksets[span - 1].ss7.debug = 1;
16305 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16306 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16307 } else {
16308 linksets[span - 1].ss7.debug = 0;
16309 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16310 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16311 }
16312 }
16313
16314 return CLI_SUCCESS;
16315 }
16316 #endif
16317
16318 #if defined(HAVE_SS7)
16319 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16320 {
16321 int linkset, cic;
16322 int blocked = -1, i;
16323 switch (cmd) {
16324 case CLI_INIT:
16325 e->command = "ss7 block cic";
16326 e->usage =
16327 "Usage: ss7 block cic <linkset> <CIC>\n"
16328 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16329 return NULL;
16330 case CLI_GENERATE:
16331 return NULL;
16332 }
16333 if (a->argc == 5)
16334 linkset = atoi(a->argv[3]);
16335 else
16336 return CLI_SHOWUSAGE;
16337
16338 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16339 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16340 return CLI_SUCCESS;
16341 }
16342
16343 if (!linksets[linkset-1].ss7.ss7) {
16344 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16345 return CLI_SUCCESS;
16346 }
16347
16348 cic = atoi(a->argv[4]);
16349
16350 if (cic < 1) {
16351 ast_cli(a->fd, "Invalid CIC specified!\n");
16352 return CLI_SUCCESS;
16353 }
16354
16355 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16356 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16357 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16358 if (!blocked) {
16359 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16360 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16361 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16362 }
16363 }
16364 }
16365
16366 if (blocked < 0) {
16367 ast_cli(a->fd, "Invalid CIC specified!\n");
16368 return CLI_SUCCESS;
16369 }
16370
16371 if (!blocked)
16372 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16373 else
16374 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16375
16376
16377 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16378
16379 return CLI_SUCCESS;
16380 }
16381 #endif
16382
16383 #if defined(HAVE_SS7)
16384 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16385 {
16386 int linkset;
16387 int i;
16388 switch (cmd) {
16389 case CLI_INIT:
16390 e->command = "ss7 block linkset";
16391 e->usage =
16392 "Usage: ss7 block linkset <linkset number>\n"
16393 " Sends a remote blocking request for all CICs on the given linkset\n";
16394 return NULL;
16395 case CLI_GENERATE:
16396 return NULL;
16397 }
16398 if (a->argc == 4)
16399 linkset = atoi(a->argv[3]);
16400 else
16401 return CLI_SHOWUSAGE;
16402
16403 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16404 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16405 return CLI_SUCCESS;
16406 }
16407
16408 if (!linksets[linkset-1].ss7.ss7) {
16409 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16410 return CLI_SUCCESS;
16411 }
16412
16413 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16414 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16415 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16416 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16417 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16418 }
16419
16420
16421 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16422
16423 return CLI_SUCCESS;
16424 }
16425 #endif
16426
16427 #if defined(HAVE_SS7)
16428 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16429 {
16430 int linkset, cic;
16431 int i, blocked = -1;
16432 switch (cmd) {
16433 case CLI_INIT:
16434 e->command = "ss7 unblock cic";
16435 e->usage =
16436 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16437 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16438 return NULL;
16439 case CLI_GENERATE:
16440 return NULL;
16441 }
16442
16443 if (a->argc == 5)
16444 linkset = atoi(a->argv[3]);
16445 else
16446 return CLI_SHOWUSAGE;
16447
16448 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16449 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16450 return CLI_SUCCESS;
16451 }
16452
16453 if (!linksets[linkset-1].ss7.ss7) {
16454 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16455 return CLI_SUCCESS;
16456 }
16457
16458 cic = atoi(a->argv[4]);
16459
16460 if (cic < 1) {
16461 ast_cli(a->fd, "Invalid CIC specified!\n");
16462 return CLI_SUCCESS;
16463 }
16464
16465 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16466 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16467 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16468 if (blocked) {
16469 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16470 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16471 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16472 }
16473 }
16474 }
16475
16476 if (blocked > 0)
16477 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16478
16479
16480 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16481
16482 return CLI_SUCCESS;
16483 }
16484 #endif
16485
16486 #if defined(HAVE_SS7)
16487 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16488 {
16489 int linkset;
16490 int i;
16491 switch (cmd) {
16492 case CLI_INIT:
16493 e->command = "ss7 unblock linkset";
16494 e->usage =
16495 "Usage: ss7 unblock linkset <linkset number>\n"
16496 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16497 return NULL;
16498 case CLI_GENERATE:
16499 return NULL;
16500 }
16501
16502 if (a->argc == 4)
16503 linkset = atoi(a->argv[3]);
16504 else
16505 return CLI_SHOWUSAGE;
16506
16507 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16508 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16509 return CLI_SUCCESS;
16510 }
16511
16512 if (!linksets[linkset-1].ss7.ss7) {
16513 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16514 return CLI_SUCCESS;
16515 }
16516
16517 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16518 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16519 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16520 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16521 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16522 }
16523
16524
16525 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16526
16527 return CLI_SUCCESS;
16528 }
16529 #endif
16530
16531 #if defined(HAVE_SS7)
16532 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16533 {
16534 int linkset;
16535 struct sig_ss7_linkset *ss7;
16536 switch (cmd) {
16537 case CLI_INIT:
16538 e->command = "ss7 show linkset";
16539 e->usage =
16540 "Usage: ss7 show linkset <span>\n"
16541 " Shows the status of an SS7 linkset.\n";
16542 return NULL;
16543 case CLI_GENERATE:
16544 return NULL;
16545 }
16546
16547 if (a->argc < 4)
16548 return CLI_SHOWUSAGE;
16549 linkset = atoi(a->argv[3]);
16550 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16551 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16552 return CLI_SUCCESS;
16553 }
16554 ss7 = &linksets[linkset - 1].ss7;
16555 if (!ss7->ss7) {
16556 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16557 return CLI_SUCCESS;
16558 }
16559
16560 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16561
16562 return CLI_SUCCESS;
16563 }
16564 #endif
16565
16566 #if defined(HAVE_SS7)
16567 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16568 {
16569 int linkset;
16570
16571 switch (cmd) {
16572 case CLI_INIT:
16573 e->command = "ss7 show channels";
16574 e->usage =
16575 "Usage: ss7 show channels\n"
16576 " Displays SS7 channel information at a glance.\n";
16577 return NULL;
16578 case CLI_GENERATE:
16579 return NULL;
16580 }
16581
16582 if (a->argc != 3)
16583 return CLI_SHOWUSAGE;
16584
16585 sig_ss7_cli_show_channels_header(a->fd);
16586 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16587 if (linksets[linkset].ss7.ss7) {
16588 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16589 }
16590 }
16591 return CLI_SUCCESS;
16592 }
16593 #endif
16594
16595 #if defined(HAVE_SS7)
16596 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16597 {
16598 switch (cmd) {
16599 case CLI_INIT:
16600 e->command = "ss7 show version";
16601 e->usage =
16602 "Usage: ss7 show version\n"
16603 " Show the libss7 version\n";
16604 return NULL;
16605 case CLI_GENERATE:
16606 return NULL;
16607 }
16608
16609 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16610
16611 return CLI_SUCCESS;
16612 }
16613 #endif
16614
16615 #if defined(HAVE_SS7)
16616 static struct ast_cli_entry dahdi_ss7_cli[] = {
16617 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16618 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16619 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16620 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16621 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16622 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16623 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16624 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16625 };
16626 #endif
16627
16628 #if defined(HAVE_PRI)
16629 #if defined(HAVE_PRI_CCSS)
16630
16631
16632
16633
16634
16635
16636
16637
16638
16639
16640
16641
16642
16643
16644
16645
16646
16647 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16648 {
16649 struct dahdi_pvt *pvt;
16650 struct sig_pri_chan *pvt_chan;
16651 int res;
16652
16653 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16654
16655 pvt = chan->tech_pvt;
16656 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16657 pvt_chan = pvt->sig_pvt;
16658 } else {
16659 pvt_chan = NULL;
16660 }
16661 if (!pvt_chan) {
16662 return -1;
16663 }
16664
16665 ast_module_ref(ast_module_info->self);
16666
16667 res = sig_pri_cc_agent_init(agent, pvt_chan);
16668 if (res) {
16669 ast_module_unref(ast_module_info->self);
16670 }
16671 return res;
16672 }
16673 #endif
16674 #endif
16675
16676 #if defined(HAVE_PRI)
16677 #if defined(HAVE_PRI_CCSS)
16678
16679
16680
16681
16682
16683
16684
16685
16686
16687
16688
16689
16690
16691 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16692 {
16693 sig_pri_cc_agent_destructor(agent);
16694
16695 ast_module_unref(ast_module_info->self);
16696 }
16697 #endif
16698 #endif
16699
16700 #if defined(HAVE_PRI)
16701 #if defined(HAVE_PRI_CCSS)
16702 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16703 .type = dahdi_pri_cc_type,
16704 .init = dahdi_pri_cc_agent_init,
16705 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16706 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16707 .respond = sig_pri_cc_agent_req_rsp,
16708 .status_request = sig_pri_cc_agent_status_req,
16709 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16710 .party_b_free = sig_pri_cc_agent_party_b_free,
16711 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16712 .callee_available = sig_pri_cc_agent_callee_available,
16713 .destructor = dahdi_pri_cc_agent_destructor,
16714 };
16715 #endif
16716 #endif
16717
16718 #if defined(HAVE_PRI)
16719 #if defined(HAVE_PRI_CCSS)
16720 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16721 .type = dahdi_pri_cc_type,
16722 .request_cc = sig_pri_cc_monitor_req_cc,
16723 .suspend = sig_pri_cc_monitor_suspend,
16724 .unsuspend = sig_pri_cc_monitor_unsuspend,
16725 .status_response = sig_pri_cc_monitor_status_rsp,
16726 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16727 .destructor = sig_pri_cc_monitor_destructor,
16728 };
16729 #endif
16730 #endif
16731
16732 static int __unload_module(void)
16733 {
16734 struct dahdi_pvt *p;
16735 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16736 int i, j;
16737 #endif
16738
16739 #ifdef HAVE_PRI
16740 for (i = 0; i < NUM_SPANS; i++) {
16741 if (pris[i].pri.master != AST_PTHREADT_NULL) {
16742 pthread_cancel(pris[i].pri.master);
16743 pthread_kill(pris[i].pri.master, SIGURG);
16744 }
16745 }
16746 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16747 ast_unregister_application(dahdi_send_keypad_facility_app);
16748 #ifdef HAVE_PRI_PROG_W_CAUSE
16749 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16750 #endif
16751 #endif
16752 #if defined(HAVE_SS7)
16753 for (i = 0; i < NUM_SPANS; i++) {
16754 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16755 pthread_cancel(linksets[i].ss7.master);
16756 pthread_kill(linksets[i].ss7.master, SIGURG);
16757 }
16758 }
16759 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16760 #endif
16761 #if defined(HAVE_OPENR2)
16762 dahdi_r2_destroy_links();
16763 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16764 ast_unregister_application(dahdi_accept_r2_call_app);
16765 #endif
16766
16767 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16768 ast_manager_unregister("DAHDIDialOffhook");
16769 ast_manager_unregister("DAHDIHangup");
16770 ast_manager_unregister("DAHDITransfer");
16771 ast_manager_unregister("DAHDIDNDoff");
16772 ast_manager_unregister("DAHDIDNDon");
16773 ast_manager_unregister("DAHDIShowChannels");
16774 ast_manager_unregister("DAHDIRestart");
16775 ast_data_unregister(NULL);
16776 ast_channel_unregister(&dahdi_tech);
16777
16778
16779 ast_mutex_lock(&iflock);
16780 for (p = iflist; p; p = p->next) {
16781 if (p->owner)
16782 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16783 }
16784 ast_mutex_unlock(&iflock);
16785
16786 ast_mutex_lock(&monlock);
16787 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16788 pthread_cancel(monitor_thread);
16789 pthread_kill(monitor_thread, SIGURG);
16790 pthread_join(monitor_thread, NULL);
16791 }
16792 monitor_thread = AST_PTHREADT_STOP;
16793 ast_mutex_unlock(&monlock);
16794
16795 destroy_all_channels();
16796
16797 #if defined(HAVE_PRI)
16798 for (i = 0; i < NUM_SPANS; i++) {
16799 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16800 pthread_join(pris[i].pri.master, NULL);
16801 }
16802 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16803 dahdi_close_pri_fd(&(pris[i]), j);
16804 }
16805 sig_pri_stop_pri(&pris[i].pri);
16806 }
16807 #if defined(HAVE_PRI_CCSS)
16808 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16809 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16810 #endif
16811 sig_pri_unload();
16812 #endif
16813
16814 #if defined(HAVE_SS7)
16815 for (i = 0; i < NUM_SPANS; i++) {
16816 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16817 pthread_join(linksets[i].ss7.master, NULL);
16818 }
16819 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16820 dahdi_close_ss7_fd(&(linksets[i]), j);
16821 }
16822 }
16823 #endif
16824 ast_cond_destroy(&ss_thread_complete);
16825 return 0;
16826 }
16827
16828 static int unload_module(void)
16829 {
16830 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16831 int y;
16832 #endif
16833 #ifdef HAVE_PRI
16834 for (y = 0; y < NUM_SPANS; y++)
16835 ast_mutex_destroy(&pris[y].pri.lock);
16836 #endif
16837 #if defined(HAVE_SS7)
16838 for (y = 0; y < NUM_SPANS; y++)
16839 ast_mutex_destroy(&linksets[y].ss7.lock);
16840 #endif
16841 return __unload_module();
16842 }
16843
16844 static void string_replace(char *str, int char1, int char2)
16845 {
16846 for (; *str; str++) {
16847 if (*str == char1) {
16848 *str = char2;
16849 }
16850 }
16851 }
16852
16853 static char *parse_spanchan(char *chanstr, char **subdir)
16854 {
16855 char *p;
16856
16857 if ((p = strrchr(chanstr, '!')) == NULL) {
16858 *subdir = NULL;
16859 return chanstr;
16860 }
16861 *p++ = '\0';
16862 string_replace(chanstr, '!', '/');
16863 *subdir = chanstr;
16864 return p;
16865 }
16866
16867 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16868 {
16869 char *c, *chan;
16870 char *subdir;
16871 int x, start, finish;
16872 struct dahdi_pvt *tmp;
16873
16874 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16875 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16876 return -1;
16877 }
16878
16879 c = ast_strdupa(value);
16880 c = parse_spanchan(c, &subdir);
16881
16882 while ((chan = strsep(&c, ","))) {
16883 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16884
16885 } else if (sscanf(chan, "%30d", &start)) {
16886
16887 finish = start;
16888 } else if (!strcasecmp(chan, "pseudo")) {
16889 finish = start = CHAN_PSEUDO;
16890 if (found_pseudo)
16891 *found_pseudo = 1;
16892 } else {
16893 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16894 return -1;
16895 }
16896 if (finish < start) {
16897 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16898 x = finish;
16899 finish = start;
16900 start = x;
16901 }
16902
16903 for (x = start; x <= finish; x++) {
16904 char fn[PATH_MAX];
16905 int real_channel = x;
16906
16907 if (!ast_strlen_zero(subdir)) {
16908 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16909 if (real_channel < 0) {
16910 if (conf->ignore_failed_channels) {
16911 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16912 subdir, x, real_channel);
16913 continue;
16914 } else {
16915 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16916 subdir, x, real_channel);
16917 return -1;
16918 }
16919 }
16920 }
16921 tmp = mkintf(real_channel, conf, reload);
16922
16923 if (tmp) {
16924 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16925 } else {
16926 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16927 (reload == 1) ? "reconfigure" : "register", value);
16928 return -1;
16929 }
16930 }
16931 }
16932
16933 return 0;
16934 }
16935
16936
16937
16938 #define MAX_CHANLIST_LEN 80
16939
16940 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16941 {
16942 char *parse = ast_strdupa(data);
16943 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16944 unsigned int param_count;
16945 unsigned int x;
16946
16947 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16948 return;
16949
16950 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16951
16952
16953
16954 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16955
16956 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16957 confp->chan.echocancel.head.tap_length = x;
16958 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16959 confp->chan.echocancel.head.tap_length = 128;
16960
16961
16962
16963 for (x = 1; x < param_count; x++) {
16964 struct {
16965 char *name;
16966 char *value;
16967 } param;
16968
16969 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16970 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16971 continue;
16972 }
16973
16974 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16975 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16976 continue;
16977 }
16978
16979 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16980
16981 if (param.value) {
16982 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16983 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16984 continue;
16985 }
16986 }
16987 confp->chan.echocancel.head.param_count++;
16988 }
16989 }
16990
16991
16992 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16993
16994 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16995
16996 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16997 {
16998 struct dahdi_pvt *tmp;
16999 int y;
17000 int found_pseudo = 0;
17001 struct ast_variable *dahdichan = NULL;
17002
17003 for (; v; v = v->next) {
17004 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17005 continue;
17006
17007
17008 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17009 if (options & PROC_DAHDI_OPT_NOCHAN) {
17010 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17011 continue;
17012 }
17013 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17014 if (confp->ignore_failed_channels) {
17015 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17016 continue;
17017 } else {
17018 return -1;
17019 }
17020 }
17021 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17022 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17023 confp->ignore_failed_channels = ast_true(v->value);
17024 } else if (!strcasecmp(v->name, "buffers")) {
17025 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17026 ast_log(LOG_WARNING, "Using default buffer policy.\n");
17027 confp->chan.buf_no = numbufs;
17028 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17029 }
17030 } else if (!strcasecmp(v->name, "faxbuffers")) {
17031 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17032 confp->chan.usefaxbuffers = 1;
17033 }
17034 } else if (!strcasecmp(v->name, "dahdichan")) {
17035
17036 dahdichan = v;
17037 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17038 usedistinctiveringdetection = ast_true(v->value);
17039 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17040 distinctiveringaftercid = ast_true(v->value);
17041 } else if (!strcasecmp(v->name, "dring1context")) {
17042 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17043 } else if (!strcasecmp(v->name, "dring2context")) {
17044 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17045 } else if (!strcasecmp(v->name, "dring3context")) {
17046 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17047 } else if (!strcasecmp(v->name, "dring1range")) {
17048 confp->chan.drings.ringnum[0].range = atoi(v->value);
17049 } else if (!strcasecmp(v->name, "dring2range")) {
17050 confp->chan.drings.ringnum[1].range = atoi(v->value);
17051 } else if (!strcasecmp(v->name, "dring3range")) {
17052 confp->chan.drings.ringnum[2].range = atoi(v->value);
17053 } else if (!strcasecmp(v->name, "dring1")) {
17054 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]);
17055 } else if (!strcasecmp(v->name, "dring2")) {
17056 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]);
17057 } else if (!strcasecmp(v->name, "dring3")) {
17058 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]);
17059 } else if (!strcasecmp(v->name, "usecallerid")) {
17060 confp->chan.use_callerid = ast_true(v->value);
17061 } else if (!strcasecmp(v->name, "cidsignalling")) {
17062 if (!strcasecmp(v->value, "bell"))
17063 confp->chan.cid_signalling = CID_SIG_BELL;
17064 else if (!strcasecmp(v->value, "v23"))
17065 confp->chan.cid_signalling = CID_SIG_V23;
17066 else if (!strcasecmp(v->value, "dtmf"))
17067 confp->chan.cid_signalling = CID_SIG_DTMF;
17068 else if (!strcasecmp(v->value, "smdi"))
17069 confp->chan.cid_signalling = CID_SIG_SMDI;
17070 else if (!strcasecmp(v->value, "v23_jp"))
17071 confp->chan.cid_signalling = CID_SIG_V23_JP;
17072 else if (ast_true(v->value))
17073 confp->chan.cid_signalling = CID_SIG_BELL;
17074 } else if (!strcasecmp(v->name, "cidstart")) {
17075 if (!strcasecmp(v->value, "ring"))
17076 confp->chan.cid_start = CID_START_RING;
17077 else if (!strcasecmp(v->value, "polarity_in"))
17078 confp->chan.cid_start = CID_START_POLARITY_IN;
17079 else if (!strcasecmp(v->value, "polarity"))
17080 confp->chan.cid_start = CID_START_POLARITY;
17081 else if (!strcasecmp(v->value, "dtmf"))
17082 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17083 else if (ast_true(v->value))
17084 confp->chan.cid_start = CID_START_RING;
17085 } else if (!strcasecmp(v->name, "threewaycalling")) {
17086 confp->chan.threewaycalling = ast_true(v->value);
17087 } else if (!strcasecmp(v->name, "cancallforward")) {
17088 confp->chan.cancallforward = ast_true(v->value);
17089 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17090 if (ast_true(v->value))
17091 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17092 else
17093 confp->chan.dtmfrelax = 0;
17094 } else if (!strcasecmp(v->name, "mailbox")) {
17095 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17096 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17097 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17098 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17099 }
17100 } else if (!strcasecmp(v->name, "adsi")) {
17101 confp->chan.adsi = ast_true(v->value);
17102 } else if (!strcasecmp(v->name, "usesmdi")) {
17103 confp->chan.use_smdi = ast_true(v->value);
17104 } else if (!strcasecmp(v->name, "smdiport")) {
17105 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17106 } else if (!strcasecmp(v->name, "transfer")) {
17107 confp->chan.transfer = ast_true(v->value);
17108 } else if (!strcasecmp(v->name, "canpark")) {
17109 confp->chan.canpark = ast_true(v->value);
17110 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17111 confp->chan.echocanbridged = ast_true(v->value);
17112 } else if (!strcasecmp(v->name, "busydetect")) {
17113 confp->chan.busydetect = ast_true(v->value);
17114 } else if (!strcasecmp(v->name, "busycount")) {
17115 confp->chan.busycount = atoi(v->value);
17116 } else if (!strcasecmp(v->name, "busypattern")) {
17117 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17118 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17119 }
17120 } else if (!strcasecmp(v->name, "callprogress")) {
17121 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17122 if (ast_true(v->value))
17123 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17124 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17125 confp->chan.waitfordialtone = atoi(v->value);
17126 } else if (!strcasecmp(v->name, "faxdetect")) {
17127 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17128 if (!strcasecmp(v->value, "incoming")) {
17129 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17130 } else if (!strcasecmp(v->value, "outgoing")) {
17131 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17132 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17133 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17134 } else if (!strcasecmp(v->name, "echocancel")) {
17135 process_echocancel(confp, v->value, v->lineno);
17136 } else if (!strcasecmp(v->name, "echotraining")) {
17137 if (sscanf(v->value, "%30d", &y) == 1) {
17138 if ((y < 10) || (y > 4000)) {
17139 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17140 } else {
17141 confp->chan.echotraining = y;
17142 }
17143 } else if (ast_true(v->value)) {
17144 confp->chan.echotraining = 400;
17145 } else
17146 confp->chan.echotraining = 0;
17147 } else if (!strcasecmp(v->name, "hidecallerid")) {
17148 confp->chan.hidecallerid = ast_true(v->value);
17149 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17150 confp->chan.hidecalleridname = ast_true(v->value);
17151 } else if (!strcasecmp(v->name, "pulsedial")) {
17152 confp->chan.pulse = ast_true(v->value);
17153 } else if (!strcasecmp(v->name, "callreturn")) {
17154 confp->chan.callreturn = ast_true(v->value);
17155 } else if (!strcasecmp(v->name, "callwaiting")) {
17156 confp->chan.callwaiting = ast_true(v->value);
17157 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17158 confp->chan.callwaitingcallerid = ast_true(v->value);
17159 } else if (!strcasecmp(v->name, "context")) {
17160 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17161 } else if (!strcasecmp(v->name, "language")) {
17162 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17163 } else if (!strcasecmp(v->name, "progzone")) {
17164 ast_copy_string(progzone, v->value, sizeof(progzone));
17165 } else if (!strcasecmp(v->name, "mohinterpret")
17166 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17167 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17168 } else if (!strcasecmp(v->name, "mohsuggest")) {
17169 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17170 } else if (!strcasecmp(v->name, "parkinglot")) {
17171 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17172 } else if (!strcasecmp(v->name, "stripmsd")) {
17173 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17174 confp->chan.stripmsd = atoi(v->value);
17175 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17176 numbufs = atoi(v->value);
17177 } else if (!strcasecmp(v->name, "group")) {
17178 confp->chan.group = ast_get_group(v->value);
17179 } else if (!strcasecmp(v->name, "callgroup")) {
17180 if (!strcasecmp(v->value, "none"))
17181 confp->chan.callgroup = 0;
17182 else
17183 confp->chan.callgroup = ast_get_group(v->value);
17184 } else if (!strcasecmp(v->name, "pickupgroup")) {
17185 if (!strcasecmp(v->value, "none"))
17186 confp->chan.pickupgroup = 0;
17187 else
17188 confp->chan.pickupgroup = ast_get_group(v->value);
17189 } else if (!strcasecmp(v->name, "setvar")) {
17190 char *varname = ast_strdupa(v->value), *varval = NULL;
17191 struct ast_variable *tmpvar;
17192 if (varname && (varval = strchr(varname, '='))) {
17193 *varval++ = '\0';
17194 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17195 tmpvar->next = confp->chan.vars;
17196 confp->chan.vars = tmpvar;
17197 }
17198 }
17199 } else if (!strcasecmp(v->name, "immediate")) {
17200 confp->chan.immediate = ast_true(v->value);
17201 } else if (!strcasecmp(v->name, "transfertobusy")) {
17202 confp->chan.transfertobusy = ast_true(v->value);
17203 } else if (!strcasecmp(v->name, "mwimonitor")) {
17204 confp->chan.mwimonitor_neon = 0;
17205 confp->chan.mwimonitor_fsk = 0;
17206 confp->chan.mwimonitor_rpas = 0;
17207 if (strcasestr(v->value, "fsk")) {
17208 confp->chan.mwimonitor_fsk = 1;
17209 }
17210 if (strcasestr(v->value, "rpas")) {
17211 confp->chan.mwimonitor_rpas = 1;
17212 }
17213 if (strcasestr(v->value, "neon")) {
17214 confp->chan.mwimonitor_neon = 1;
17215 }
17216
17217 if (ast_true(v->value)) {
17218 confp->chan.mwimonitor_fsk = 1;
17219 }
17220 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17221 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17222 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17223 }
17224 } else if (!strcasecmp(v->name, "rxgain")) {
17225 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17226 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17227 }
17228 } else if (!strcasecmp(v->name, "txgain")) {
17229 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17230 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17231 }
17232 } else if (!strcasecmp(v->name, "txdrc")) {
17233 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17234 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17235 }
17236 } else if (!strcasecmp(v->name, "rxdrc")) {
17237 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17238 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17239 }
17240 } else if (!strcasecmp(v->name, "tonezone")) {
17241 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17242 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17243 }
17244 } else if (!strcasecmp(v->name, "callerid")) {
17245 if (!strcasecmp(v->value, "asreceived")) {
17246 confp->chan.cid_num[0] = '\0';
17247 confp->chan.cid_name[0] = '\0';
17248 } else {
17249 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17250 }
17251 } else if (!strcasecmp(v->name, "fullname")) {
17252 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17253 } else if (!strcasecmp(v->name, "cid_number")) {
17254 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17255 } else if (!strcasecmp(v->name, "cid_tag")) {
17256 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17257 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17258 confp->chan.dahditrcallerid = ast_true(v->value);
17259 } else if (!strcasecmp(v->name, "restrictcid")) {
17260 confp->chan.restrictcid = ast_true(v->value);
17261 } else if (!strcasecmp(v->name, "usecallingpres")) {
17262 confp->chan.use_callingpres = ast_true(v->value);
17263 } else if (!strcasecmp(v->name, "accountcode")) {
17264 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17265 } else if (!strcasecmp(v->name, "amaflags")) {
17266 y = ast_cdr_amaflags2int(v->value);
17267 if (y < 0)
17268 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17269 else
17270 confp->chan.amaflags = y;
17271 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17272 confp->chan.polarityonanswerdelay = atoi(v->value);
17273 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17274 confp->chan.answeronpolarityswitch = ast_true(v->value);
17275 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17276 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17277 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17278 confp->chan.sendcalleridafter = atoi(v->value);
17279 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17280 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17281 } else if (ast_cc_is_config_param(v->name)) {
17282 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17283 } else if (!strcasecmp(v->name, "mwisendtype")) {
17284 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17285 if (!strcasecmp(v->value, "rpas")) {
17286 mwisend_rpas = 1;
17287 } else {
17288 mwisend_rpas = 0;
17289 }
17290 #else
17291
17292 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17293 if (strcasestr(v->value, "nofsk")) {
17294 confp->chan.mwisend_fsk = 0;
17295 } else {
17296 confp->chan.mwisend_fsk = 1;
17297 }
17298 if (strcasestr(v->value, "rpas")) {
17299 confp->chan.mwisend_rpas = 1;
17300 } else {
17301 confp->chan.mwisend_rpas = 0;
17302 }
17303 if (strcasestr(v->value, "lrev")) {
17304 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17305 }
17306 if (strcasestr(v->value, "hvdc")) {
17307 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17308 }
17309 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17310 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17311 }
17312 #endif
17313 } else if (reload != 1) {
17314 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17315 int orig_radio = confp->chan.radio;
17316 int orig_outsigmod = confp->chan.outsigmod;
17317 int orig_auto = confp->is_sig_auto;
17318
17319 confp->chan.radio = 0;
17320 confp->chan.outsigmod = -1;
17321 confp->is_sig_auto = 0;
17322 if (!strcasecmp(v->value, "em")) {
17323 confp->chan.sig = SIG_EM;
17324 } else if (!strcasecmp(v->value, "em_e1")) {
17325 confp->chan.sig = SIG_EM_E1;
17326 } else if (!strcasecmp(v->value, "em_w")) {
17327 confp->chan.sig = SIG_EMWINK;
17328 } else if (!strcasecmp(v->value, "fxs_ls")) {
17329 confp->chan.sig = SIG_FXSLS;
17330 } else if (!strcasecmp(v->value, "fxs_gs")) {
17331 confp->chan.sig = SIG_FXSGS;
17332 } else if (!strcasecmp(v->value, "fxs_ks")) {
17333 confp->chan.sig = SIG_FXSKS;
17334 } else if (!strcasecmp(v->value, "fxo_ls")) {
17335 confp->chan.sig = SIG_FXOLS;
17336 } else if (!strcasecmp(v->value, "fxo_gs")) {
17337 confp->chan.sig = SIG_FXOGS;
17338 } else if (!strcasecmp(v->value, "fxo_ks")) {
17339 confp->chan.sig = SIG_FXOKS;
17340 } else if (!strcasecmp(v->value, "fxs_rx")) {
17341 confp->chan.sig = SIG_FXSKS;
17342 confp->chan.radio = 1;
17343 } else if (!strcasecmp(v->value, "fxo_rx")) {
17344 confp->chan.sig = SIG_FXOLS;
17345 confp->chan.radio = 1;
17346 } else if (!strcasecmp(v->value, "fxs_tx")) {
17347 confp->chan.sig = SIG_FXSLS;
17348 confp->chan.radio = 1;
17349 } else if (!strcasecmp(v->value, "fxo_tx")) {
17350 confp->chan.sig = SIG_FXOGS;
17351 confp->chan.radio = 1;
17352 } else if (!strcasecmp(v->value, "em_rx")) {
17353 confp->chan.sig = SIG_EM;
17354 confp->chan.radio = 1;
17355 } else if (!strcasecmp(v->value, "em_tx")) {
17356 confp->chan.sig = SIG_EM;
17357 confp->chan.radio = 1;
17358 } else if (!strcasecmp(v->value, "em_rxtx")) {
17359 confp->chan.sig = SIG_EM;
17360 confp->chan.radio = 2;
17361 } else if (!strcasecmp(v->value, "em_txrx")) {
17362 confp->chan.sig = SIG_EM;
17363 confp->chan.radio = 2;
17364 } else if (!strcasecmp(v->value, "sf")) {
17365 confp->chan.sig = SIG_SF;
17366 } else if (!strcasecmp(v->value, "sf_w")) {
17367 confp->chan.sig = SIG_SFWINK;
17368 } else if (!strcasecmp(v->value, "sf_featd")) {
17369 confp->chan.sig = SIG_FEATD;
17370 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17371 confp->chan.sig = SIG_FEATDMF;
17372 } else if (!strcasecmp(v->value, "sf_featb")) {
17373 confp->chan.sig = SIG_SF_FEATB;
17374 } else if (!strcasecmp(v->value, "sf")) {
17375 confp->chan.sig = SIG_SF;
17376 } else if (!strcasecmp(v->value, "sf_rx")) {
17377 confp->chan.sig = SIG_SF;
17378 confp->chan.radio = 1;
17379 } else if (!strcasecmp(v->value, "sf_tx")) {
17380 confp->chan.sig = SIG_SF;
17381 confp->chan.radio = 1;
17382 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17383 confp->chan.sig = SIG_SF;
17384 confp->chan.radio = 2;
17385 } else if (!strcasecmp(v->value, "sf_txrx")) {
17386 confp->chan.sig = SIG_SF;
17387 confp->chan.radio = 2;
17388 } else if (!strcasecmp(v->value, "featd")) {
17389 confp->chan.sig = SIG_FEATD;
17390 } else if (!strcasecmp(v->value, "featdmf")) {
17391 confp->chan.sig = SIG_FEATDMF;
17392 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17393 confp->chan.sig = SIG_FEATDMF_TA;
17394 } else if (!strcasecmp(v->value, "e911")) {
17395 confp->chan.sig = SIG_E911;
17396 } else if (!strcasecmp(v->value, "fgccama")) {
17397 confp->chan.sig = SIG_FGC_CAMA;
17398 } else if (!strcasecmp(v->value, "fgccamamf")) {
17399 confp->chan.sig = SIG_FGC_CAMAMF;
17400 } else if (!strcasecmp(v->value, "featb")) {
17401 confp->chan.sig = SIG_FEATB;
17402 #ifdef HAVE_PRI
17403 } else if (!strcasecmp(v->value, "pri_net")) {
17404 confp->chan.sig = SIG_PRI;
17405 confp->pri.pri.nodetype = PRI_NETWORK;
17406 } else if (!strcasecmp(v->value, "pri_cpe")) {
17407 confp->chan.sig = SIG_PRI;
17408 confp->pri.pri.nodetype = PRI_CPE;
17409 } else if (!strcasecmp(v->value, "bri_cpe")) {
17410 confp->chan.sig = SIG_BRI;
17411 confp->pri.pri.nodetype = PRI_CPE;
17412 } else if (!strcasecmp(v->value, "bri_net")) {
17413 confp->chan.sig = SIG_BRI;
17414 confp->pri.pri.nodetype = PRI_NETWORK;
17415 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17416 confp->chan.sig = SIG_BRI_PTMP;
17417 confp->pri.pri.nodetype = PRI_CPE;
17418 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17419 #if defined(HAVE_PRI_CALL_HOLD)
17420 confp->chan.sig = SIG_BRI_PTMP;
17421 confp->pri.pri.nodetype = PRI_NETWORK;
17422 #else
17423 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17424 #endif
17425 #endif
17426 #if defined(HAVE_SS7)
17427 } else if (!strcasecmp(v->value, "ss7")) {
17428 confp->chan.sig = SIG_SS7;
17429 #endif
17430 #ifdef HAVE_OPENR2
17431 } else if (!strcasecmp(v->value, "mfcr2")) {
17432 confp->chan.sig = SIG_MFCR2;
17433 #endif
17434 } else if (!strcasecmp(v->value, "auto")) {
17435 confp->is_sig_auto = 1;
17436 } else {
17437 confp->chan.outsigmod = orig_outsigmod;
17438 confp->chan.radio = orig_radio;
17439 confp->is_sig_auto = orig_auto;
17440 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17441 }
17442 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17443 if (!strcasecmp(v->value, "em")) {
17444 confp->chan.outsigmod = SIG_EM;
17445 } else if (!strcasecmp(v->value, "em_e1")) {
17446 confp->chan.outsigmod = SIG_EM_E1;
17447 } else if (!strcasecmp(v->value, "em_w")) {
17448 confp->chan.outsigmod = SIG_EMWINK;
17449 } else if (!strcasecmp(v->value, "sf")) {
17450 confp->chan.outsigmod = SIG_SF;
17451 } else if (!strcasecmp(v->value, "sf_w")) {
17452 confp->chan.outsigmod = SIG_SFWINK;
17453 } else if (!strcasecmp(v->value, "sf_featd")) {
17454 confp->chan.outsigmod = SIG_FEATD;
17455 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17456 confp->chan.outsigmod = SIG_FEATDMF;
17457 } else if (!strcasecmp(v->value, "sf_featb")) {
17458 confp->chan.outsigmod = SIG_SF_FEATB;
17459 } else if (!strcasecmp(v->value, "sf")) {
17460 confp->chan.outsigmod = SIG_SF;
17461 } else if (!strcasecmp(v->value, "featd")) {
17462 confp->chan.outsigmod = SIG_FEATD;
17463 } else if (!strcasecmp(v->value, "featdmf")) {
17464 confp->chan.outsigmod = SIG_FEATDMF;
17465 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17466 confp->chan.outsigmod = SIG_FEATDMF_TA;
17467 } else if (!strcasecmp(v->value, "e911")) {
17468 confp->chan.outsigmod = SIG_E911;
17469 } else if (!strcasecmp(v->value, "fgccama")) {
17470 confp->chan.outsigmod = SIG_FGC_CAMA;
17471 } else if (!strcasecmp(v->value, "fgccamamf")) {
17472 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17473 } else if (!strcasecmp(v->value, "featb")) {
17474 confp->chan.outsigmod = SIG_FEATB;
17475 } else {
17476 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17477 }
17478 #ifdef HAVE_PRI
17479 } else if (!strcasecmp(v->name, "pridialplan")) {
17480 if (!strcasecmp(v->value, "national")) {
17481 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17482 } else if (!strcasecmp(v->value, "unknown")) {
17483 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17484 } else if (!strcasecmp(v->value, "private")) {
17485 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17486 } else if (!strcasecmp(v->value, "international")) {
17487 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17488 } else if (!strcasecmp(v->value, "local")) {
17489 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17490 } else if (!strcasecmp(v->value, "dynamic")) {
17491 confp->pri.pri.dialplan = -1;
17492 } else if (!strcasecmp(v->value, "redundant")) {
17493 confp->pri.pri.dialplan = -2;
17494 } else {
17495 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17496 }
17497 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17498 if (!strcasecmp(v->value, "national")) {
17499 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17500 } else if (!strcasecmp(v->value, "unknown")) {
17501 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17502 } else if (!strcasecmp(v->value, "private")) {
17503 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17504 } else if (!strcasecmp(v->value, "international")) {
17505 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17506 } else if (!strcasecmp(v->value, "local")) {
17507 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17508 } else if (!strcasecmp(v->value, "dynamic")) {
17509 confp->pri.pri.localdialplan = -1;
17510 } else if (!strcasecmp(v->value, "redundant")) {
17511 confp->pri.pri.localdialplan = -2;
17512 } else {
17513 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17514 }
17515 } else if (!strcasecmp(v->name, "switchtype")) {
17516 if (!strcasecmp(v->value, "national"))
17517 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17518 else if (!strcasecmp(v->value, "ni1"))
17519 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17520 else if (!strcasecmp(v->value, "dms100"))
17521 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17522 else if (!strcasecmp(v->value, "4ess"))
17523 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17524 else if (!strcasecmp(v->value, "5ess"))
17525 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17526 else if (!strcasecmp(v->value, "euroisdn"))
17527 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17528 else if (!strcasecmp(v->value, "qsig"))
17529 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17530 else {
17531 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17532 return -1;
17533 }
17534 } else if (!strcasecmp(v->name, "msn")) {
17535 ast_copy_string(confp->pri.pri.msn_list, v->value,
17536 sizeof(confp->pri.pri.msn_list));
17537 } else if (!strcasecmp(v->name, "nsf")) {
17538 if (!strcasecmp(v->value, "sdn"))
17539 confp->pri.pri.nsf = PRI_NSF_SDN;
17540 else if (!strcasecmp(v->value, "megacom"))
17541 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17542 else if (!strcasecmp(v->value, "tollfreemegacom"))
17543 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17544 else if (!strcasecmp(v->value, "accunet"))
17545 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17546 else if (!strcasecmp(v->value, "none"))
17547 confp->pri.pri.nsf = PRI_NSF_NONE;
17548 else {
17549 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17550 confp->pri.pri.nsf = PRI_NSF_NONE;
17551 }
17552 } else if (!strcasecmp(v->name, "priindication")) {
17553 if (!strcasecmp(v->value, "outofband"))
17554 confp->chan.priindication_oob = 1;
17555 else if (!strcasecmp(v->value, "inband"))
17556 confp->chan.priindication_oob = 0;
17557 else
17558 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17559 v->value, v->lineno);
17560 } else if (!strcasecmp(v->name, "priexclusive")) {
17561 confp->chan.priexclusive = ast_true(v->value);
17562 } else if (!strcasecmp(v->name, "internationalprefix")) {
17563 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17564 } else if (!strcasecmp(v->name, "nationalprefix")) {
17565 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17566 } else if (!strcasecmp(v->name, "localprefix")) {
17567 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17568 } else if (!strcasecmp(v->name, "privateprefix")) {
17569 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17570 } else if (!strcasecmp(v->name, "unknownprefix")) {
17571 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17572 } else if (!strcasecmp(v->name, "resetinterval")) {
17573 if (!strcasecmp(v->value, "never"))
17574 confp->pri.pri.resetinterval = -1;
17575 else if (atoi(v->value) >= 60)
17576 confp->pri.pri.resetinterval = atoi(v->value);
17577 else
17578 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17579 v->value, v->lineno);
17580 } else if (!strcasecmp(v->name, "minunused")) {
17581 confp->pri.pri.minunused = atoi(v->value);
17582 } else if (!strcasecmp(v->name, "minidle")) {
17583 confp->pri.pri.minidle = atoi(v->value);
17584 } else if (!strcasecmp(v->name, "idleext")) {
17585 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17586 } else if (!strcasecmp(v->name, "idledial")) {
17587 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17588 } else if (!strcasecmp(v->name, "overlapdial")) {
17589 if (ast_true(v->value)) {
17590 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17591 } else if (!strcasecmp(v->value, "incoming")) {
17592 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17593 } else if (!strcasecmp(v->value, "outgoing")) {
17594 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17595 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17596 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17597 } else {
17598 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17599 }
17600 #ifdef HAVE_PRI_PROG_W_CAUSE
17601 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17602 if (!strcasecmp(v->value, "logical")) {
17603 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17604 } else if (!strcasecmp(v->value, "physical")) {
17605 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17606 } else {
17607 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17608 }
17609 #endif
17610 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17611 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17612 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17613 } else if (!strcasecmp(v->name, "service_message_support")) {
17614
17615 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17616 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17617 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17618 confp->pri.pri.enable_service_message_support = 1;
17619 } else {
17620 confp->pri.pri.enable_service_message_support = 0;
17621 }
17622 #endif
17623 #ifdef HAVE_PRI_INBANDDISCONNECT
17624 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17625 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17626 #endif
17627 } else if (!strcasecmp(v->name, "pritimer")) {
17628 #ifdef PRI_GETSET_TIMERS
17629 char tmp[20];
17630 char *timerc;
17631 char *c;
17632 int timer;
17633 int timeridx;
17634
17635 ast_copy_string(tmp, v->value, sizeof(tmp));
17636 c = tmp;
17637 timerc = strsep(&c, ",");
17638 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17639 timeridx = pri_timer2idx(timerc);
17640 timer = atoi(c);
17641 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17642 ast_log(LOG_WARNING,
17643 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17644 v->lineno);
17645 } else if (!timer) {
17646 ast_log(LOG_WARNING,
17647 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17648 c, timerc, v->lineno);
17649 } else {
17650 confp->pri.pri.pritimers[timeridx] = timer;
17651 }
17652 } else {
17653 ast_log(LOG_WARNING,
17654 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17655 v->value, v->lineno);
17656 }
17657 #endif
17658 } else if (!strcasecmp(v->name, "facilityenable")) {
17659 confp->pri.pri.facilityenable = ast_true(v->value);
17660 #if defined(HAVE_PRI_AOC_EVENTS)
17661 } else if (!strcasecmp(v->name, "aoc_enable")) {
17662 confp->pri.pri.aoc_passthrough_flag = 0;
17663 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17664 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17665 }
17666 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17667 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17668 }
17669 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17670 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17671 }
17672 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17673 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17674 #endif
17675 #if defined(HAVE_PRI_CALL_HOLD)
17676 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17677 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17678 #endif
17679 #if defined(HAVE_PRI_CCSS)
17680 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17681 if (!strcasecmp(v->value, "global")) {
17682 confp->pri.pri.cc_ptmp_recall_mode = 0;
17683 } else if (!strcasecmp(v->value, "specific")) {
17684 confp->pri.pri.cc_ptmp_recall_mode = 1;
17685 } else {
17686 confp->pri.pri.cc_ptmp_recall_mode = 1;
17687 }
17688 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17689 if (!strcasecmp(v->value, "release")) {
17690 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17691 } else if (!strcasecmp(v->value, "retain")) {
17692 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17693 } else if (!strcasecmp(v->value, "do_not_care")) {
17694 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17695 } else {
17696 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17697 }
17698 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17699 if (!strcasecmp(v->value, "release")) {
17700 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17701 } else if (!strcasecmp(v->value, "retain")) {
17702 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17703 } else {
17704 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17705 }
17706 #endif
17707 #if defined(HAVE_PRI_CALL_WAITING)
17708 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17709 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17710 if (confp->pri.pri.max_call_waiting_calls < 0) {
17711
17712 confp->pri.pri.max_call_waiting_calls = 0;
17713 }
17714 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17715 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17716 #endif
17717 #if defined(HAVE_PRI_MWI)
17718 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17719 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17720 sizeof(confp->pri.pri.mwi_mailboxes));
17721 #endif
17722 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17723 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17724 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
17725 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
17726 } else if (!strcasecmp(v->name, "layer1_presence")) {
17727 if (!strcasecmp(v->value, "required")) {
17728 confp->pri.pri.layer1_ignored = 0;
17729 } else if (!strcasecmp(v->value, "ignore")) {
17730 confp->pri.pri.layer1_ignored = 1;
17731 } else {
17732
17733 confp->pri.pri.layer1_ignored = 0;
17734 }
17735 #if defined(HAVE_PRI_L2_PERSISTENCE)
17736 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17737 if (!strcasecmp(v->value, "keep_up")) {
17738 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17739 } else if (!strcasecmp(v->value, "leave_down")) {
17740 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17741 } else {
17742 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17743 }
17744 #endif
17745 #endif
17746 #if defined(HAVE_SS7)
17747 } else if (!strcasecmp(v->name, "ss7type")) {
17748 if (!strcasecmp(v->value, "itu")) {
17749 cur_ss7type = SS7_ITU;
17750 } else if (!strcasecmp(v->value, "ansi")) {
17751 cur_ss7type = SS7_ANSI;
17752 } else
17753 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17754 } else if (!strcasecmp(v->name, "linkset")) {
17755 cur_linkset = atoi(v->value);
17756 } else if (!strcasecmp(v->name, "pointcode")) {
17757 cur_pointcode = parse_pointcode(v->value);
17758 } else if (!strcasecmp(v->name, "adjpointcode")) {
17759 cur_adjpointcode = parse_pointcode(v->value);
17760 } else if (!strcasecmp(v->name, "defaultdpc")) {
17761 cur_defaultdpc = parse_pointcode(v->value);
17762 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17763 cur_cicbeginswith = atoi(v->value);
17764 } else if (!strcasecmp(v->name, "networkindicator")) {
17765 if (!strcasecmp(v->value, "national"))
17766 cur_networkindicator = SS7_NI_NAT;
17767 else if (!strcasecmp(v->value, "national_spare"))
17768 cur_networkindicator = SS7_NI_NAT_SPARE;
17769 else if (!strcasecmp(v->value, "international"))
17770 cur_networkindicator = SS7_NI_INT;
17771 else if (!strcasecmp(v->value, "international_spare"))
17772 cur_networkindicator = SS7_NI_INT_SPARE;
17773 else
17774 cur_networkindicator = -1;
17775 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17776 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17777 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17778 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17779 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17780 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17781 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17782 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17783 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17784 if (!strcasecmp(v->value, "national")) {
17785 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17786 } else if (!strcasecmp(v->value, "international")) {
17787 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17788 } else if (!strcasecmp(v->value, "subscriber")) {
17789 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17790 } else if (!strcasecmp(v->value, "unknown")) {
17791 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17792 } else if (!strcasecmp(v->value, "dynamic")) {
17793 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17794 } else {
17795 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17796 }
17797 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17798 if (!strcasecmp(v->value, "national")) {
17799 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17800 } else if (!strcasecmp(v->value, "international")) {
17801 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17802 } else if (!strcasecmp(v->value, "subscriber")) {
17803 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17804 } else if (!strcasecmp(v->value, "unknown")) {
17805 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17806 } else if (!strcasecmp(v->value, "dynamic")) {
17807 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17808 } else {
17809 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17810 }
17811 } else if (!strcasecmp(v->name, "sigchan")) {
17812 int sigchan, res;
17813 sigchan = atoi(v->value);
17814 res = linkset_addsigchan(sigchan);
17815 if (res < 0)
17816 return -1;
17817
17818 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17819 struct dahdi_ss7 *link;
17820 link = ss7_resolve_linkset(cur_linkset);
17821 if (!link) {
17822 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17823 return -1;
17824 }
17825 if (ast_true(v->value))
17826 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17827 #endif
17828 #ifdef HAVE_OPENR2
17829 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17830 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17831 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);
17832 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17833 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17834 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17835 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17836 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17837 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17838 confp->mfcr2.variant = OR2_VAR_ITU;
17839 }
17840 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17841 confp->mfcr2.mfback_timeout = atoi(v->value);
17842 if (!confp->mfcr2.mfback_timeout) {
17843 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17844 confp->mfcr2.mfback_timeout = -1;
17845 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17846 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17847 }
17848 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17849 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17850 if (confp->mfcr2.metering_pulse_timeout > 500) {
17851 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17852 }
17853 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17854 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17855 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17856 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17857 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17858 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17859 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17860 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17861 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17862 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17863 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17864 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17865 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17866 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17867 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17868 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17869 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17870 #endif
17871 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17872 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17873 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17874 confp->mfcr2.max_ani = atoi(v->value);
17875 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17876 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17877 }
17878 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17879 confp->mfcr2.max_dnis = atoi(v->value);
17880 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17881 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17882 }
17883 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17884 confp->mfcr2.category = openr2_proto_get_category(v->value);
17885 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17886 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17887 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17888 v->value, v->lineno);
17889 }
17890 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17891 openr2_log_level_t tmplevel;
17892 char *clevel;
17893 char *logval = ast_strdupa(v->value);
17894 while (logval) {
17895 clevel = strsep(&logval,",");
17896 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17897 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17898 continue;
17899 }
17900 confp->mfcr2.loglevel |= tmplevel;
17901 }
17902 #endif
17903 } else if (!strcasecmp(v->name, "cadence")) {
17904
17905 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17906 int i;
17907 struct dahdi_ring_cadence new_cadence;
17908 int cid_location = -1;
17909 int firstcadencepos = 0;
17910 char original_args[80];
17911 int cadence_is_ok = 1;
17912
17913 ast_copy_string(original_args, v->value, sizeof(original_args));
17914
17915 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]);
17916
17917
17918 if (element_count % 2 == 1) {
17919 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17920 cadence_is_ok = 0;
17921 }
17922
17923
17924 for (i = 0; i < element_count; i++) {
17925 if (c[i] == 0) {
17926 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17927 cadence_is_ok = 0;
17928 break;
17929 } else if (c[i] < 0) {
17930 if (i % 2 == 1) {
17931
17932 if (cid_location == -1) {
17933 cid_location = i;
17934 c[i] *= -1;
17935 } else {
17936 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17937 cadence_is_ok = 0;
17938 break;
17939 }
17940 } else {
17941 if (firstcadencepos == 0) {
17942 firstcadencepos = i;
17943
17944 } else {
17945 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17946 cadence_is_ok = 0;
17947 break;
17948 }
17949 }
17950 }
17951 }
17952
17953
17954 for (i = 0; i < 16; i++) {
17955 new_cadence.ringcadence[i] = c[i];
17956 }
17957
17958 if (cadence_is_ok) {
17959
17960 if (element_count < 2) {
17961 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17962 } else {
17963 if (cid_location == -1) {
17964
17965 cid_location = 1;
17966 } else {
17967
17968 cid_location = (cid_location + 1) / 2;
17969 }
17970
17971 if (!user_has_defined_cadences++)
17972
17973 num_cadence = 0;
17974 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17975 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17976 else {
17977 cadences[num_cadence] = new_cadence;
17978 cidrings[num_cadence++] = cid_location;
17979 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17980 }
17981 }
17982 }
17983 } else if (!strcasecmp(v->name, "ringtimeout")) {
17984 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17985 } else if (!strcasecmp(v->name, "prewink")) {
17986 confp->timing.prewinktime = atoi(v->value);
17987 } else if (!strcasecmp(v->name, "preflash")) {
17988 confp->timing.preflashtime = atoi(v->value);
17989 } else if (!strcasecmp(v->name, "wink")) {
17990 confp->timing.winktime = atoi(v->value);
17991 } else if (!strcasecmp(v->name, "flash")) {
17992 confp->timing.flashtime = atoi(v->value);
17993 } else if (!strcasecmp(v->name, "start")) {
17994 confp->timing.starttime = atoi(v->value);
17995 } else if (!strcasecmp(v->name, "rxwink")) {
17996 confp->timing.rxwinktime = atoi(v->value);
17997 } else if (!strcasecmp(v->name, "rxflash")) {
17998 confp->timing.rxflashtime = atoi(v->value);
17999 } else if (!strcasecmp(v->name, "debounce")) {
18000 confp->timing.debouncetime = atoi(v->value);
18001 } else if (!strcasecmp(v->name, "toneduration")) {
18002 int toneduration;
18003 int ctlfd;
18004 int res;
18005 struct dahdi_dialparams dps;
18006
18007 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18008 if (ctlfd == -1) {
18009 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18010 return -1;
18011 }
18012
18013 toneduration = atoi(v->value);
18014 if (toneduration > -1) {
18015 memset(&dps, 0, sizeof(dps));
18016
18017 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18018 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18019 if (res < 0) {
18020 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18021 close(ctlfd);
18022 return -1;
18023 }
18024 }
18025 close(ctlfd);
18026 } else if (!strcasecmp(v->name, "defaultcic")) {
18027 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18028 } else if (!strcasecmp(v->name, "defaultozz")) {
18029 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18030 } else if (!strcasecmp(v->name, "mwilevel")) {
18031 mwilevel = atoi(v->value);
18032 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18033 dtmfcid_level = atoi(v->value);
18034 } else if (!strcasecmp(v->name, "reportalarms")) {
18035 if (!strcasecmp(v->value, "all"))
18036 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18037 if (!strcasecmp(v->value, "none"))
18038 report_alarms = 0;
18039 else if (!strcasecmp(v->value, "channels"))
18040 report_alarms = REPORT_CHANNEL_ALARMS;
18041 else if (!strcasecmp(v->value, "spans"))
18042 report_alarms = REPORT_SPAN_ALARMS;
18043 }
18044 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18045 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18046 }
18047
18048
18049 if (confp->chan.vars) {
18050 ast_variables_destroy(confp->chan.vars);
18051 confp->chan.vars = NULL;
18052 }
18053
18054 if (dahdichan) {
18055
18056 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18057 &found_pseudo)) {
18058 if (confp->ignore_failed_channels) {
18059 ast_log(LOG_WARNING,
18060 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18061 dahdichan->value);
18062 } else {
18063 return -1;
18064 }
18065 }
18066 }
18067
18068
18069 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18070 if (!tmp->destroy && tmp->span != y) {
18071 tmp->manages_span_alarms = 1;
18072 y = tmp->span;
18073 } else {
18074 tmp->manages_span_alarms = 0;
18075 }
18076 }
18077
18078
18079
18080 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18081
18082
18083
18084
18085 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18086
18087 if (conf.chan.cc_params) {
18088 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18089 } else {
18090 tmp = NULL;
18091 }
18092 if (tmp) {
18093 ast_verb(3, "Automatically generated pseudo channel\n");
18094 } else {
18095 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18096 }
18097 ast_cc_config_params_destroy(conf.chan.cc_params);
18098 }
18099 return 0;
18100 }
18101
18102
18103
18104
18105
18106
18107
18108
18109
18110
18111
18112 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18113 {
18114 struct ast_cc_config_params *cc_params;
18115
18116 cc_params = dest->chan.cc_params;
18117 *dest = *src;
18118 dest->chan.cc_params = cc_params;
18119 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18120 }
18121
18122
18123
18124
18125
18126
18127
18128
18129
18130
18131
18132
18133
18134 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18135 {
18136 struct ast_config *cfg;
18137 struct ast_config *ucfg;
18138 struct ast_variable *v;
18139 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18140 const char *chans;
18141 const char *cat;
18142 int res;
18143
18144 #ifdef HAVE_PRI
18145 char *c;
18146 int spanno;
18147 int i;
18148 int logicalspan;
18149 int trunkgroup;
18150 int dchannels[SIG_PRI_NUM_DCHANS];
18151 #endif
18152 int have_cfg_now;
18153 static int had_cfg_before = 1;
18154
18155 cfg = ast_config_load(config, config_flags);
18156 have_cfg_now = !!cfg;
18157 if (!cfg) {
18158
18159 if (had_cfg_before) {
18160 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18161 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18162 }
18163 cfg = ast_config_new();
18164 if (!cfg) {
18165 return 0;
18166 }
18167 ucfg = ast_config_load("users.conf", config_flags);
18168 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18169 ast_config_destroy(cfg);
18170 return 0;
18171 }
18172 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18173 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18174 ast_config_destroy(cfg);
18175 return 0;
18176 }
18177 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18178 ucfg = ast_config_load("users.conf", config_flags);
18179 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18180 return 0;
18181 }
18182 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18183 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18184 return 0;
18185 }
18186 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18187 cfg = ast_config_load(config, config_flags);
18188 have_cfg_now = !!cfg;
18189 if (!cfg) {
18190 if (had_cfg_before) {
18191
18192 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18193 ast_config_destroy(ucfg);
18194 return 0;
18195 }
18196 cfg = ast_config_new();
18197 if (!cfg) {
18198 ast_config_destroy(ucfg);
18199 return 0;
18200 }
18201 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18202 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18203 ast_config_destroy(ucfg);
18204 return 0;
18205 }
18206 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18207 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18208 return 0;
18209 } else {
18210 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18211 ucfg = ast_config_load("users.conf", config_flags);
18212 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18213 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18214 ast_config_destroy(cfg);
18215 return 0;
18216 }
18217 }
18218 had_cfg_before = have_cfg_now;
18219
18220
18221 ast_mutex_lock(&iflock);
18222 #ifdef HAVE_PRI
18223 if (reload != 1) {
18224
18225 v = ast_variable_browse(cfg, "trunkgroups");
18226 while (v) {
18227 if (!strcasecmp(v->name, "trunkgroup")) {
18228 trunkgroup = atoi(v->value);
18229 if (trunkgroup > 0) {
18230 if ((c = strchr(v->value, ','))) {
18231 i = 0;
18232 memset(dchannels, 0, sizeof(dchannels));
18233 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18234 dchannels[i] = atoi(c + 1);
18235 if (dchannels[i] < 0) {
18236 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);
18237 } else
18238 i++;
18239 c = strchr(c + 1, ',');
18240 }
18241 if (i) {
18242 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18243 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);
18244 } else
18245 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");
18246 } else
18247 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18248 } else
18249 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18250 } else
18251 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18252 } else if (!strcasecmp(v->name, "spanmap")) {
18253 spanno = atoi(v->value);
18254 if (spanno > 0) {
18255 if ((c = strchr(v->value, ','))) {
18256 trunkgroup = atoi(c + 1);
18257 if (trunkgroup > 0) {
18258 if ((c = strchr(c + 1, ',')))
18259 logicalspan = atoi(c + 1);
18260 else
18261 logicalspan = 0;
18262 if (logicalspan >= 0) {
18263 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18264 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18265 } else
18266 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18267 } else
18268 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);
18269 } else
18270 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18271 } else
18272 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18273 } else
18274 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18275 } else {
18276 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18277 }
18278 v = v->next;
18279 }
18280 }
18281 #endif
18282
18283
18284 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18285
18286 mwimonitornotify[0] = '\0';
18287
18288 v = ast_variable_browse(cfg, "channels");
18289 if ((res = process_dahdi(base_conf,
18290 "" ,
18291 v, reload, 0))) {
18292 ast_mutex_unlock(&iflock);
18293 ast_config_destroy(cfg);
18294 if (ucfg) {
18295 ast_config_destroy(ucfg);
18296 }
18297 return res;
18298 }
18299
18300
18301 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18302
18303
18304
18305 if (!strcasecmp(cat, "general") ||
18306 !strcasecmp(cat, "trunkgroups") ||
18307 !strcasecmp(cat, "globals") ||
18308 !strcasecmp(cat, "channels")) {
18309 continue;
18310 }
18311
18312 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18313 if (ast_strlen_zero(chans)) {
18314
18315 continue;
18316 }
18317
18318
18319 deep_copy_dahdi_chan_conf(conf, base_conf);
18320
18321 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18322 ast_mutex_unlock(&iflock);
18323 ast_config_destroy(cfg);
18324 if (ucfg) {
18325 ast_config_destroy(ucfg);
18326 }
18327 return res;
18328 }
18329 }
18330
18331 ast_config_destroy(cfg);
18332
18333 if (ucfg) {
18334
18335 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18336 process_dahdi(base_conf,
18337 "" ,
18338 ast_variable_browse(ucfg, "general"), 1, 0);
18339
18340 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18341 if (!strcasecmp(cat, "general")) {
18342 continue;
18343 }
18344
18345 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18346 if (ast_strlen_zero(chans)) {
18347
18348 continue;
18349 }
18350
18351
18352 deep_copy_dahdi_chan_conf(conf, base_conf);
18353
18354 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18355 ast_config_destroy(ucfg);
18356 ast_mutex_unlock(&iflock);
18357 return res;
18358 }
18359 }
18360 ast_config_destroy(ucfg);
18361 }
18362 ast_mutex_unlock(&iflock);
18363
18364 #ifdef HAVE_PRI
18365 if (reload != 1) {
18366 int x;
18367 for (x = 0; x < NUM_SPANS; x++) {
18368 if (pris[x].pri.pvts[0]) {
18369 prepare_pri(pris + x);
18370 if (sig_pri_start_pri(&pris[x].pri)) {
18371 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18372 return -1;
18373 } else
18374 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18375 }
18376 }
18377 }
18378 #endif
18379 #if defined(HAVE_SS7)
18380 if (reload != 1) {
18381 int x;
18382 for (x = 0; x < NUM_SPANS; x++) {
18383 if (linksets[x].ss7.ss7) {
18384 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18385 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18386 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18387 return -1;
18388 } else
18389 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18390 }
18391 }
18392 }
18393 #endif
18394 #ifdef HAVE_OPENR2
18395 if (reload != 1) {
18396 int x;
18397 for (x = 0; x < r2links_count; x++) {
18398 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18399 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18400 return -1;
18401 } else {
18402 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18403 }
18404 }
18405 }
18406 #endif
18407
18408 restart_monitor();
18409 return 0;
18410 }
18411
18412
18413
18414
18415
18416
18417
18418
18419
18420
18421 static int setup_dahdi(int reload)
18422 {
18423 int res;
18424 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18425 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18426 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18427
18428 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18429 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18430 } else {
18431 res = -1;
18432 }
18433 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18434 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18435 ast_cc_config_params_destroy(conf.chan.cc_params);
18436
18437 return res;
18438 }
18439
18440
18441
18442
18443
18444
18445
18446
18447 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18448 struct ast_data *data_root)
18449 {
18450 int ctl, res, span;
18451 struct ast_data *data_span, *data_alarms;
18452 struct dahdi_spaninfo s;
18453
18454 ctl = open("/dev/dahdi/ctl", O_RDWR);
18455 if (ctl < 0) {
18456 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18457 return -1;
18458 }
18459 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18460 s.spanno = span;
18461 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18462 if (res) {
18463 continue;
18464 }
18465
18466 data_span = ast_data_add_node(data_root, "span");
18467 if (!data_span) {
18468 continue;
18469 }
18470 ast_data_add_str(data_span, "description", s.desc);
18471
18472
18473 data_alarms = ast_data_add_node(data_span, "alarms");
18474 if (!data_alarms) {
18475 continue;
18476 }
18477
18478 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18479 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18480 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18481 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18482 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18483 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18484
18485 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18486 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18487 ast_data_add_int(data_span, "crc4", s.crc4count);
18488 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18489 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18490 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18491 "CAS");
18492 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18493 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18494 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18495 "Unknown");
18496 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18497 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18498 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18499 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18500
18501
18502 if (!ast_data_search_match(search, data_span)) {
18503 ast_data_remove_node(data_root, data_span);
18504 }
18505 }
18506 close(ctl);
18507
18508 return 0;
18509 }
18510
18511
18512
18513
18514
18515
18516
18517
18518 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18519 struct ast_data *data_root)
18520 {
18521 struct dahdi_pvt *tmp;
18522 struct ast_data *data_channel;
18523
18524 ast_mutex_lock(&iflock);
18525 for (tmp = iflist; tmp; tmp = tmp->next) {
18526 data_channel = ast_data_add_node(data_root, "channel");
18527 if (!data_channel) {
18528 continue;
18529 }
18530
18531 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18532
18533
18534 if (!ast_data_search_match(search, data_channel)) {
18535 ast_data_remove_node(data_root, data_channel);
18536 }
18537 }
18538 ast_mutex_unlock(&iflock);
18539
18540 return 0;
18541 }
18542
18543
18544
18545
18546
18547
18548
18549
18550 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18551 struct ast_data *data_root)
18552 {
18553 int pseudo_fd = -1;
18554 struct dahdi_versioninfo vi = {
18555 .version = "Unknown",
18556 .echo_canceller = "Unknown"
18557 };
18558
18559 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18560 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18561 return -1;
18562 }
18563
18564 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18565 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18566 }
18567
18568 close(pseudo_fd);
18569
18570 ast_data_add_str(data_root, "value", vi.version);
18571 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18572
18573 return 0;
18574 }
18575
18576 static const struct ast_data_handler dahdi_status_data_provider = {
18577 .version = AST_DATA_HANDLER_VERSION,
18578 .get = dahdi_status_data_provider_get
18579 };
18580
18581 static const struct ast_data_handler dahdi_channels_data_provider = {
18582 .version = AST_DATA_HANDLER_VERSION,
18583 .get = dahdi_channels_data_provider_get
18584 };
18585
18586 static const struct ast_data_handler dahdi_version_data_provider = {
18587 .version = AST_DATA_HANDLER_VERSION,
18588 .get = dahdi_version_data_provider_get
18589 };
18590
18591 static const struct ast_data_entry dahdi_data_providers[] = {
18592 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18593 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18594 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18595 };
18596
18597 static int load_module(void)
18598 {
18599 int res;
18600 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18601 int y;
18602 #endif
18603
18604 #ifdef HAVE_PRI
18605 memset(pris, 0, sizeof(pris));
18606 for (y = 0; y < NUM_SPANS; y++) {
18607 sig_pri_init_pri(&pris[y].pri);
18608 }
18609 pri_set_error(dahdi_pri_error);
18610 pri_set_message(dahdi_pri_message);
18611 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18612 #ifdef HAVE_PRI_PROG_W_CAUSE
18613 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18614 #endif
18615 #if defined(HAVE_PRI_CCSS)
18616 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18617 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18618 __unload_module();
18619 return AST_MODULE_LOAD_FAILURE;
18620 }
18621 #endif
18622 if (sig_pri_load(
18623 #if defined(HAVE_PRI_CCSS)
18624 dahdi_pri_cc_type
18625 #else
18626 NULL
18627 #endif
18628 )) {
18629 __unload_module();
18630 return AST_MODULE_LOAD_FAILURE;
18631 }
18632 #endif
18633 #if defined(HAVE_SS7)
18634 memset(linksets, 0, sizeof(linksets));
18635 for (y = 0; y < NUM_SPANS; y++) {
18636 sig_ss7_init_linkset(&linksets[y].ss7);
18637 }
18638 ss7_set_error(dahdi_ss7_error);
18639 ss7_set_message(dahdi_ss7_message);
18640 #endif
18641 res = setup_dahdi(0);
18642
18643 if (res)
18644 return AST_MODULE_LOAD_DECLINE;
18645 if (ast_channel_register(&dahdi_tech)) {
18646 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18647 __unload_module();
18648 return AST_MODULE_LOAD_FAILURE;
18649 }
18650 #ifdef HAVE_PRI
18651 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18652 #endif
18653 #if defined(HAVE_SS7)
18654 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18655 #endif
18656 #ifdef HAVE_OPENR2
18657 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18658 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18659 #endif
18660
18661 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18662
18663 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18664 memset(round_robin, 0, sizeof(round_robin));
18665 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18666 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18667 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18668 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18669 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18670 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18671 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18672
18673 ast_cond_init(&ss_thread_complete, NULL);
18674
18675 return res;
18676 }
18677
18678 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18679 {
18680 #define END_SILENCE_LEN 400
18681 #define HEADER_MS 50
18682 #define TRAILER_MS 5
18683 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18684 #define ASCII_BYTES_PER_CHAR 80
18685
18686 unsigned char *buf,*mybuf;
18687 struct dahdi_pvt *p = c->tech_pvt;
18688 struct pollfd fds[1];
18689 int size,res,fd,len,x;
18690 int bytes=0;
18691
18692 float cr = 1.0;
18693 float ci = 0.0;
18694 float scont = 0.0;
18695 int idx;
18696
18697 idx = dahdi_get_index(c, p, 0);
18698 if (idx < 0) {
18699 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18700 return -1;
18701 }
18702 if (!text[0]) return(0);
18703 if ((!p->tdd) && (!p->mate)) return(0);
18704 if (p->mate)
18705 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18706 else
18707 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18708 if (!buf)
18709 return -1;
18710 mybuf = buf;
18711 if (p->mate) {
18712 int codec = AST_LAW(p);
18713 for (x = 0; x < HEADER_MS; x++) {
18714 PUT_CLID_MARKMS;
18715 }
18716
18717 for (x = 0; text[x]; x++) {
18718 PUT_CLID(text[x]);
18719 }
18720 for (x = 0; x < TRAILER_MS; x++) {
18721 PUT_CLID_MARKMS;
18722 }
18723 len = bytes;
18724 buf = mybuf;
18725 } else {
18726 len = tdd_generate(p->tdd, buf, text);
18727 if (len < 1) {
18728 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18729 ast_free(mybuf);
18730 return -1;
18731 }
18732 }
18733 memset(buf + len, 0x7f, END_SILENCE_LEN);
18734 len += END_SILENCE_LEN;
18735 fd = p->subs[idx].dfd;
18736 while (len) {
18737 if (ast_check_hangup(c)) {
18738 ast_free(mybuf);
18739 return -1;
18740 }
18741 size = len;
18742 if (size > READ_SIZE)
18743 size = READ_SIZE;
18744 fds[0].fd = fd;
18745 fds[0].events = POLLOUT | POLLPRI;
18746 fds[0].revents = 0;
18747 res = poll(fds, 1, -1);
18748 if (!res) {
18749 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18750 continue;
18751 }
18752
18753 if (fds[0].revents & POLLPRI) {
18754 ast_free(mybuf);
18755 return -1;
18756 }
18757 if (!(fds[0].revents & POLLOUT)) {
18758 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18759 continue;
18760 }
18761 res = write(fd, buf, size);
18762 if (res != size) {
18763 if (res == -1) {
18764 ast_free(mybuf);
18765 return -1;
18766 }
18767 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18768 break;
18769 }
18770 len -= size;
18771 buf += size;
18772 }
18773 ast_free(mybuf);
18774 return(0);
18775 }
18776
18777
18778 static int reload(void)
18779 {
18780 int res = 0;
18781
18782 res = setup_dahdi(1);
18783 if (res) {
18784 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18785 return -1;
18786 }
18787 return 0;
18788 }
18789
18790
18791
18792
18793
18794 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18795 .load = load_module,
18796 .unload = unload_module,
18797 .reload = reload,
18798 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18799 .nonoptreq = "res_smdi",
18800 );